Merge "Generating StrongBox backed keys"
diff --git a/api/current.txt b/api/current.txt
index 7192056..bbd9e18 100644
--- a/api/current.txt
+++ b/api/current.txt
@@ -11206,6 +11206,7 @@
field public static final java.lang.String FEATURE_SENSOR_STEP_DETECTOR = "android.hardware.sensor.stepdetector";
field public static final java.lang.String FEATURE_SIP = "android.software.sip";
field public static final java.lang.String FEATURE_SIP_VOIP = "android.software.sip.voip";
+ field public static final java.lang.String FEATURE_STRONGBOX_KEYSTORE = "android.hardware.strongbox_keystore";
field public static final java.lang.String FEATURE_TELEPHONY = "android.hardware.telephony";
field public static final java.lang.String FEATURE_TELEPHONY_CDMA = "android.hardware.telephony.cdma";
field public static final java.lang.String FEATURE_TELEPHONY_GSM = "android.hardware.telephony.gsm";
@@ -38248,7 +38249,6 @@
}
public class StrongBoxUnavailableException extends java.security.ProviderException {
- ctor public StrongBoxUnavailableException();
}
public class UserNotAuthenticatedException extends java.security.InvalidKeyException {
diff --git a/core/java/android/content/pm/PackageManager.java b/core/java/android/content/pm/PackageManager.java
index df69d80..3709a90 100644
--- a/core/java/android/content/pm/PackageManager.java
+++ b/core/java/android/content/pm/PackageManager.java
@@ -2604,6 +2604,14 @@
public static final String FEATURE_VR_HEADTRACKING = "android.hardware.vr.headtracking";
/**
+ * Feature for {@link #getSystemAvailableFeatures} and {@link #hasSystemFeature}:
+ * The device has a StrongBox hardware-backed Keystore.
+ */
+ @SdkConstant(SdkConstantType.FEATURE)
+ public static final String FEATURE_STRONGBOX_KEYSTORE =
+ "android.hardware.strongbox_keystore";
+
+ /**
* Action to external storage service to clean out removed apps.
* @hide
*/
diff --git a/keystore/java/android/security/KeyStore.java b/keystore/java/android/security/KeyStore.java
index e25386b..8547f48 100644
--- a/keystore/java/android/security/KeyStore.java
+++ b/keystore/java/android/security/KeyStore.java
@@ -38,6 +38,7 @@
import android.security.keystore.KeyExpiredException;
import android.security.keystore.KeyNotYetValidException;
import android.security.keystore.KeyPermanentlyInvalidatedException;
+import android.security.keystore.StrongBoxUnavailableException;
import android.security.keystore.UserNotAuthenticatedException;
import android.util.Log;
@@ -65,6 +66,7 @@
public static final int VALUE_CORRUPTED = 8;
public static final int UNDEFINED_ACTION = 9;
public static final int WRONG_PASSWORD = 10;
+ public static final int HARDWARE_TYPE_UNAVAILABLE = -68;
/**
* Per operation authentication is needed before this operation is valid.
@@ -123,7 +125,6 @@
*/
public static final int FLAG_STRONGBOX = 1 << 4;
-
// States
public enum State { UNLOCKED, LOCKED, UNINITIALIZED };
diff --git a/keystore/java/android/security/keystore/AndroidKeyStoreKeyPairGeneratorSpi.java b/keystore/java/android/security/keystore/AndroidKeyStoreKeyPairGeneratorSpi.java
index dba3949..d1eb688 100644
--- a/keystore/java/android/security/keystore/AndroidKeyStoreKeyPairGeneratorSpi.java
+++ b/keystore/java/android/security/keystore/AndroidKeyStoreKeyPairGeneratorSpi.java
@@ -21,6 +21,7 @@
import android.security.GateKeeper;
import android.security.KeyPairGeneratorSpec;
import android.security.KeyStore;
+import android.security.KeyStoreException;
import android.security.keymaster.KeyCharacteristics;
import android.security.keymaster.KeymasterArguments;
import android.security.keymaster.KeymasterCertificateChain;
@@ -451,7 +452,7 @@
throw new IllegalStateException("Not initialized");
}
- final int flags = (mEncryptionAtRestRequired) ? KeyStore.FLAG_ENCRYPTED : 0;
+ int flags = (mEncryptionAtRestRequired) ? KeyStore.FLAG_ENCRYPTED : 0;
if (((flags & KeyStore.FLAG_ENCRYPTED) != 0)
&& (mKeyStore.state() != KeyStore.State.UNLOCKED)) {
throw new IllegalStateException(
@@ -459,6 +460,10 @@
+ ", but the user has not yet entered the credential");
}
+ if (mSpec.isStrongBoxBacked()) {
+ flags |= KeyStore.FLAG_STRONGBOX;
+ }
+
byte[] additionalEntropy =
KeyStoreCryptoOperationUtils.getRandomBytesToMixIntoKeystoreRng(
mRng, (mKeySizeBits + 7) / 8);
@@ -501,8 +506,12 @@
int errorCode = mKeyStore.generateKey(privateKeyAlias, args, additionalEntropy,
mEntryUid, flags, resultingKeyCharacteristics);
if (errorCode != KeyStore.NO_ERROR) {
- throw new ProviderException(
- "Failed to generate key pair", KeyStore.getKeyStoreException(errorCode));
+ if (errorCode == KeyStore.HARDWARE_TYPE_UNAVAILABLE) {
+ throw new StrongBoxUnavailableException("Failed to generate key pair");
+ } else {
+ throw new ProviderException(
+ "Failed to generate key pair", KeyStore.getKeyStoreException(errorCode));
+ }
}
}
diff --git a/keystore/java/android/security/keystore/StrongBoxUnavailableException.java b/keystore/java/android/security/keystore/StrongBoxUnavailableException.java
index ad41a58..66a77ed 100644
--- a/keystore/java/android/security/keystore/StrongBoxUnavailableException.java
+++ b/keystore/java/android/security/keystore/StrongBoxUnavailableException.java
@@ -16,6 +16,9 @@
package android.security.keystore;
+import android.security.KeyStore;
+import android.security.KeyStoreException;
+
import java.security.ProviderException;
/**
@@ -24,5 +27,13 @@
*/
public class StrongBoxUnavailableException extends ProviderException {
+ /**
+ * @hide
+ */
+ public StrongBoxUnavailableException(String message) {
+ super(message,
+ new KeyStoreException(KeyStore.HARDWARE_TYPE_UNAVAILABLE, "No StrongBox available")
+ );
+ }
}