Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit ea5e038b authored by Frank Salim's avatar Frank Salim
Browse files

Generating StrongBox backed keys

•Add FLAG_STRONGBOX when the generator spec requires it.
•Throw StrongBoxUnavailableException when the request
fails due to HARDWARE_UNAVAILABLE.
•Add PackageManager.FEATURE_STRONGBOX_KEYSTORE

Test: KeyStore CTS tests under development on an emulator
Bug: 63931634
Change-Id: I42d32b22981e43e504d30e5657d21ac555c71ebe
parent f88fdc99
Loading
Loading
Loading
Loading
+1 −1
Original line number Diff line number Diff line
@@ -11197,6 +11197,7 @@ package android.content.pm {
    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";
@@ -38233,7 +38234,6 @@ package android.security.keystore {
  }
  public class StrongBoxUnavailableException extends java.security.ProviderException {
    ctor public StrongBoxUnavailableException();
  }
  public class UserNotAuthenticatedException extends java.security.InvalidKeyException {
+8 −0
Original line number Diff line number Diff line
@@ -2593,6 +2593,14 @@ public abstract class PackageManager {
    @SdkConstant(SdkConstantType.FEATURE)
    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
+2 −1
Original line number Diff line number Diff line
@@ -38,6 +38,7 @@ import android.security.keymaster.OperationResult;
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 class KeyStore {
    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 class KeyStore {
     */
    public static final int FLAG_STRONGBOX = 1 << 4;


    // States
    public enum State { UNLOCKED, LOCKED, UNINITIALIZED };

+12 −3
Original line number Diff line number Diff line
@@ -21,6 +21,7 @@ import android.security.Credentials;
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 @@ public abstract class AndroidKeyStoreKeyPairGeneratorSpi extends KeyPairGenerato
            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 @@ public abstract class AndroidKeyStoreKeyPairGeneratorSpi extends KeyPairGenerato
                    + ", 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,10 +506,14 @@ public abstract class AndroidKeyStoreKeyPairGeneratorSpi extends KeyPairGenerato
        int errorCode = mKeyStore.generateKey(privateKeyAlias, args, additionalEntropy,
                mEntryUid, flags, resultingKeyCharacteristics);
        if (errorCode != KeyStore.NO_ERROR) {
            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));
            }
        }
    }

    private KeyPair loadKeystoreKeyPair(final String privateKeyAlias) throws ProviderException {
        try {
+11 −0
Original line number Diff line number Diff line
@@ -16,6 +16,9 @@

package android.security.keystore;

import android.security.KeyStore;
import android.security.KeyStoreException;

import java.security.ProviderException;

/**
@@ -24,5 +27,13 @@ import java.security.ProviderException;
 */
public class StrongBoxUnavailableException extends ProviderException {

    /**
     * @hide
     */
    public StrongBoxUnavailableException(String message) {
        super(message,
                new KeyStoreException(KeyStore.HARDWARE_TYPE_UNAVAILABLE, "No StrongBox available")
        );
    }
}