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;
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.
* For use with {@link #installKeyPair(ComponentName, PrivateKey, Certificate[], String, int)}
* {@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,
} 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;
}
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}
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