diff --git a/core/java/android/app/admin/DevicePolicyManager.java b/core/java/android/app/admin/DevicePolicyManager.java index bbdc5323648d0..cbd874176586c 100644 --- a/core/java/android/app/admin/DevicePolicyManager.java +++ b/core/java/android/app/admin/DevicePolicyManager.java @@ -72,6 +72,7 @@ import android.security.keystore.AttestationUtils; import android.security.keystore.KeyAttestationException; import android.security.keystore.KeyGenParameterSpec; import android.security.keystore.ParcelableKeyGenParameterSpec; +import android.security.keystore.StrongBoxUnavailableException; import android.service.restrictions.RestrictionsReceiver; import android.telephony.TelephonyManager; import android.telephony.data.ApnSetting; @@ -1773,6 +1774,13 @@ public class DevicePolicyManager { */ public static final int ID_TYPE_MEID = 8; + /** + * Service-specific error code for {@link #generateKeyPair}: + * Indicates the call has failed due to StrongBox unavailability. + * @hide + */ + public static final int KEY_GEN_STRONGBOX_UNAVAILABLE = 1; + /** * Specifies that the calling app should be granted access to the installed credentials * immediately. Otherwise, access to the credentials will be gated by user approval. @@ -4190,6 +4198,8 @@ public class DevicePolicyManager { * {@code keySpec} does not contain an attestation challenge. * @throws UnsupportedOperationException if Device ID attestation was requested but the * underlying hardware does not support it. + * @throws StrongBoxUnavailableException if the use of StrongBox for key generation was + * specified in {@code keySpec} but the device does not have one. * @see KeyGenParameterSpec.Builder#setAttestationChallenge(byte[]) */ public AttestedKeyPair generateKeyPair(@Nullable ComponentName admin, @@ -4230,6 +4240,15 @@ public class DevicePolicyManager { } catch (InterruptedException e) { Log.w(TAG, "Interrupted while generating key", e); Thread.currentThread().interrupt(); + } catch (ServiceSpecificException e) { + Log.w(TAG, String.format("Key Generation failure: %d", e.errorCode)); + switch (e.errorCode) { + case KEY_GEN_STRONGBOX_UNAVAILABLE: + throw new StrongBoxUnavailableException("No StrongBox for key generation."); + default: + throw new RuntimeException( + String.format("Unknown error while generating key: %d", e.errorCode)); + } } return null; } diff --git a/keystore/java/android/security/KeyChain.java b/keystore/java/android/security/KeyChain.java index 030fa60abfd3f..78dbb6ae0df3a 100644 --- a/keystore/java/android/security/KeyChain.java +++ b/keystore/java/android/security/KeyChain.java @@ -282,11 +282,17 @@ public final class KeyChain { */ public static final int KEY_GEN_NO_KEYSTORE_PROVIDER = 5; + /** + * StrongBox unavailable when calling {@link #generateKeyPair} + * @hide + */ + public static final int KEY_GEN_STRONGBOX_UNAVAILABLE = 6; + /** * General failure while calling {@link #generateKeyPair} * @hide */ - public static final int KEY_GEN_FAILURE = 6; + public static final int KEY_GEN_FAILURE = 7; /** * Successful call to {@link #attestKey} diff --git a/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java b/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java index 9ef806e807331..ed4d4db39db37 100644 --- a/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java +++ b/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java @@ -5465,7 +5465,14 @@ public class DevicePolicyManagerService extends BaseIDevicePolicyManager { if (generationResult != KeyChain.KEY_GEN_SUCCESS) { Log.e(LOG_TAG, String.format( "KeyChain failed to generate a keypair, error %d.", generationResult)); - return false; + switch (generationResult) { + case KeyChain.KEY_GEN_STRONGBOX_UNAVAILABLE: + throw new ServiceSpecificException( + DevicePolicyManager.KEY_GEN_STRONGBOX_UNAVAILABLE, + String.format("KeyChain error: %d", generationResult)); + default: + return false; + } } // Set a grant for the caller here so that when the client calls