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

Commit 39b4499d authored by Janis Danisevskis's avatar Janis Danisevskis Committed by Android (Google) Code Review
Browse files

Merge "Consolidate Keystore alias prefixes."

parents cc1b3e0e 64338c0e
Loading
Loading
Loading
Loading
+14 −20
Original line number Diff line number Diff line
@@ -60,10 +60,12 @@ public class Credentials {
    /** Key prefix for user certificates. */
    public static final String USER_CERTIFICATE = "USRCERT_";

    /** Key prefix for user private keys. */
    /** Key prefix for user private and secret keys. */
    public static final String USER_PRIVATE_KEY = "USRPKEY_";

    /** Key prefix for user secret keys. */
    /** Key prefix for user secret keys.
     *  @deprecated use {@code USER_PRIVATE_KEY} for this category instead.
     */
    public static final String USER_SECRET_KEY = "USRSKEY_";

    /** Key prefix for VPN. */
@@ -235,8 +237,7 @@ public class Credentials {
         * Make sure every type is deleted. There can be all three types, so
         * don't use a conditional here.
         */
        return deletePrivateKeyTypeForAlias(keystore, alias, uid)
                & deleteSecretKeyTypeForAlias(keystore, alias, uid)
        return deleteUserKeyTypeForAlias(keystore, alias, uid)
                & deleteCertificateTypesForAlias(keystore, alias, uid);
    }

@@ -264,34 +265,27 @@ public class Credentials {
    }

    /**
     * Delete private key for a particular {@code alias}.
     * Returns {@code true} if the entry no longer exists.
     */
    static boolean deletePrivateKeyTypeForAlias(KeyStore keystore, String alias) {
        return deletePrivateKeyTypeForAlias(keystore, alias, KeyStore.UID_SELF);
    }

    /**
     * Delete private key for a particular {@code alias}.
     * Delete user key for a particular {@code alias}.
     * Returns {@code true} if the entry no longer exists.
     */
    static boolean deletePrivateKeyTypeForAlias(KeyStore keystore, String alias, int uid) {
        return keystore.delete(Credentials.USER_PRIVATE_KEY + alias, uid);
    public static boolean deleteUserKeyTypeForAlias(KeyStore keystore, String alias) {
        return deleteUserKeyTypeForAlias(keystore, alias, KeyStore.UID_SELF);
    }

    /**
     * Delete secret key for a particular {@code alias}.
     * Delete user key for a particular {@code alias}.
     * Returns {@code true} if the entry no longer exists.
     */
    public static boolean deleteSecretKeyTypeForAlias(KeyStore keystore, String alias) {
        return deleteSecretKeyTypeForAlias(keystore, alias, KeyStore.UID_SELF);
    public static boolean deleteUserKeyTypeForAlias(KeyStore keystore, String alias, int uid) {
        return keystore.delete(Credentials.USER_PRIVATE_KEY + alias, uid) ||
                keystore.delete(Credentials.USER_SECRET_KEY + alias, uid);
    }

    /**
     * Delete secret key for a particular {@code alias}.
     * Delete legacy prefixed entry for a particular {@code alias}
     * Returns {@code true} if the entry no longer exists.
     */
    public static boolean deleteSecretKeyTypeForAlias(KeyStore keystore, String alias, int uid) {
    public static boolean deleteLegacyKeyForAlias(KeyStore keystore, String alias, int uid) {
        return keystore.delete(Credentials.USER_SECRET_KEY + alias, uid);
    }
}
+1 −1
Original line number Diff line number Diff line
@@ -305,7 +305,7 @@ public abstract class AndroidKeyStoreKeyGeneratorSpi extends KeyGeneratorSpi {
                KeyStoreCryptoOperationUtils.getRandomBytesToMixIntoKeystoreRng(
                        mRng, (mKeySizeBits + 7) / 8);
        int flags = 0;
        String keyAliasInKeystore = Credentials.USER_SECRET_KEY + spec.getKeystoreAlias();
        String keyAliasInKeystore = Credentials.USER_PRIVATE_KEY + spec.getKeystoreAlias();
        KeyCharacteristics resultingKeyCharacteristics = new KeyCharacteristics();
        boolean success = false;
        try {
+70 −20
Original line number Diff line number Diff line
@@ -196,7 +196,7 @@ public class AndroidKeyStoreProvider extends Provider {
    }

    @NonNull
    public static AndroidKeyStorePrivateKey getAndroidKeyStorePrivateKey(
    private static AndroidKeyStorePrivateKey getAndroidKeyStorePrivateKey(
            @NonNull AndroidKeyStorePublicKey publicKey) {
        String keyAlgorithm = publicKey.getAlgorithm();
        if (KeyProperties.KEY_ALGORITHM_EC.equalsIgnoreCase(keyAlgorithm)) {
@@ -212,17 +212,25 @@ public class AndroidKeyStoreProvider extends Provider {
    }

    @NonNull
    public static AndroidKeyStorePublicKey loadAndroidKeyStorePublicKeyFromKeystore(
            @NonNull KeyStore keyStore, @NonNull String privateKeyAlias, int uid)
    private static KeyCharacteristics getKeyCharacteristics(@NonNull KeyStore keyStore,
            @NonNull String alias, int uid)
            throws UnrecoverableKeyException {
        KeyCharacteristics keyCharacteristics = new KeyCharacteristics();
        int errorCode = keyStore.getKeyCharacteristics(
                privateKeyAlias, null, null, uid, keyCharacteristics);
                alias, null, null, uid, keyCharacteristics);
        if (errorCode != KeyStore.NO_ERROR) {
            throw (UnrecoverableKeyException)
                    new UnrecoverableKeyException("Failed to obtain information about private key")
                    new UnrecoverableKeyException("Failed to obtain information about key")
                            .initCause(KeyStore.getKeyStoreException(errorCode));
        }
        return keyCharacteristics;
    }

    @NonNull
    private static AndroidKeyStorePublicKey loadAndroidKeyStorePublicKeyFromKeystore(
            @NonNull KeyStore keyStore, @NonNull String privateKeyAlias, int uid,
            KeyCharacteristics keyCharacteristics)
            throws UnrecoverableKeyException {
        ExportResult exportResult = keyStore.exportKey(
                privateKeyAlias, KeymasterDefs.KM_KEY_FORMAT_X509, null, null, uid);
        if (exportResult.resultCode != KeyStore.NO_ERROR) {
@@ -252,37 +260,56 @@ public class AndroidKeyStoreProvider extends Provider {
    }

    @NonNull
    public static KeyPair loadAndroidKeyStoreKeyPairFromKeystore(
    public static AndroidKeyStorePublicKey loadAndroidKeyStorePublicKeyFromKeystore(
            @NonNull KeyStore keyStore, @NonNull String privateKeyAlias, int uid)
            throws UnrecoverableKeyException {
        return loadAndroidKeyStorePublicKeyFromKeystore(keyStore, privateKeyAlias, uid,
                getKeyCharacteristics(keyStore, privateKeyAlias, uid));
    }

    @NonNull
    private static KeyPair loadAndroidKeyStoreKeyPairFromKeystore(
            @NonNull KeyStore keyStore, @NonNull String privateKeyAlias, int uid,
            @NonNull KeyCharacteristics keyCharacteristics)
            throws UnrecoverableKeyException {
        AndroidKeyStorePublicKey publicKey =
                loadAndroidKeyStorePublicKeyFromKeystore(keyStore, privateKeyAlias, uid);
                loadAndroidKeyStorePublicKeyFromKeystore(keyStore, privateKeyAlias, uid,
                        keyCharacteristics);
        AndroidKeyStorePrivateKey privateKey =
                AndroidKeyStoreProvider.getAndroidKeyStorePrivateKey(publicKey);
        return new KeyPair(publicKey, privateKey);
    }

    @NonNull
    public static AndroidKeyStorePrivateKey loadAndroidKeyStorePrivateKeyFromKeystore(
    public static KeyPair loadAndroidKeyStoreKeyPairFromKeystore(
            @NonNull KeyStore keyStore, @NonNull String privateKeyAlias, int uid)
            throws UnrecoverableKeyException {
        KeyPair keyPair = loadAndroidKeyStoreKeyPairFromKeystore(keyStore, privateKeyAlias, uid);
        return loadAndroidKeyStoreKeyPairFromKeystore(keyStore, privateKeyAlias, uid,
                getKeyCharacteristics(keyStore, privateKeyAlias, uid));
    }

    @NonNull
    private static AndroidKeyStorePrivateKey loadAndroidKeyStorePrivateKeyFromKeystore(
            @NonNull KeyStore keyStore, @NonNull String privateKeyAlias, int uid,
            @NonNull KeyCharacteristics keyCharacteristics)
            throws UnrecoverableKeyException {
        KeyPair keyPair = loadAndroidKeyStoreKeyPairFromKeystore(keyStore, privateKeyAlias, uid,
                keyCharacteristics);
        return (AndroidKeyStorePrivateKey) keyPair.getPrivate();
    }

    @NonNull
    public static AndroidKeyStoreSecretKey loadAndroidKeyStoreSecretKeyFromKeystore(
            @NonNull KeyStore keyStore, @NonNull String secretKeyAlias, int uid)
    public static AndroidKeyStorePrivateKey loadAndroidKeyStorePrivateKeyFromKeystore(
            @NonNull KeyStore keyStore, @NonNull String privateKeyAlias, int uid)
            throws UnrecoverableKeyException {
        KeyCharacteristics keyCharacteristics = new KeyCharacteristics();
        int errorCode = keyStore.getKeyCharacteristics(
                secretKeyAlias, null, null, uid, keyCharacteristics);
        if (errorCode != KeyStore.NO_ERROR) {
            throw (UnrecoverableKeyException)
                    new UnrecoverableKeyException("Failed to obtain information about key")
                            .initCause(KeyStore.getKeyStoreException(errorCode));
        return loadAndroidKeyStorePrivateKeyFromKeystore(keyStore, privateKeyAlias, uid,
                getKeyCharacteristics(keyStore, privateKeyAlias, uid));
    }

    @NonNull
    private static AndroidKeyStoreSecretKey loadAndroidKeyStoreSecretKeyFromKeystore(
            @NonNull String secretKeyAlias, int uid, @NonNull KeyCharacteristics keyCharacteristics)
            throws UnrecoverableKeyException {
        Integer keymasterAlgorithm = keyCharacteristics.getEnum(KeymasterDefs.KM_TAG_ALGORITHM);
        if (keymasterAlgorithm == null) {
            throw new UnrecoverableKeyException("Key algorithm unknown");
@@ -310,6 +337,29 @@ public class AndroidKeyStoreProvider extends Provider {
        return new AndroidKeyStoreSecretKey(secretKeyAlias, uid, keyAlgorithmString);
    }

    public static AndroidKeyStoreKey loadAndroidKeyStoreKeyFromKeystore(
            @NonNull KeyStore keyStore, @NonNull String userKeyAlias, int uid)
            throws UnrecoverableKeyException  {
        KeyCharacteristics keyCharacteristics = getKeyCharacteristics(keyStore, userKeyAlias, uid);

        Integer keymasterAlgorithm = keyCharacteristics.getEnum(KeymasterDefs.KM_TAG_ALGORITHM);
        if (keymasterAlgorithm == null) {
            throw new UnrecoverableKeyException("Key algorithm unknown");
        }

        if (keymasterAlgorithm == KeymasterDefs.KM_ALGORITHM_HMAC ||
                keymasterAlgorithm == KeymasterDefs.KM_ALGORITHM_AES) {
            return loadAndroidKeyStoreSecretKeyFromKeystore(userKeyAlias, uid,
                    keyCharacteristics);
        } else if (keymasterAlgorithm == KeymasterDefs.KM_ALGORITHM_RSA ||
                keymasterAlgorithm == KeymasterDefs.KM_ALGORITHM_EC) {
            return loadAndroidKeyStorePrivateKeyFromKeystore(keyStore, userKeyAlias, uid,
                    keyCharacteristics);
        } else {
            throw new UnrecoverableKeyException("Key algorithm unknown");
        }
    }

    /**
     * Returns an {@code AndroidKeyStore} {@link java.security.KeyStore}} of the specified UID.
     * The {@code KeyStore} contains keys and certificates owned by that UID. Such cross-UID
+4 −1
Original line number Diff line number Diff line
@@ -64,7 +64,10 @@ public class AndroidKeyStoreSecretKeyFactorySpi extends SecretKeyFactorySpi {
        AndroidKeyStoreKey keystoreKey = (AndroidKeyStoreKey) key;
        String keyAliasInKeystore = keystoreKey.getAlias();
        String entryAlias;
        if (keyAliasInKeystore.startsWith(Credentials.USER_SECRET_KEY)) {
        if (keyAliasInKeystore.startsWith(Credentials.USER_PRIVATE_KEY)) {
            entryAlias = keyAliasInKeystore.substring(Credentials.USER_PRIVATE_KEY.length());
        } else if (keyAliasInKeystore.startsWith(Credentials.USER_SECRET_KEY)){
            // key has legacy prefix
            entryAlias = keyAliasInKeystore.substring(Credentials.USER_SECRET_KEY.length());
        } else {
            throw new InvalidKeySpecException("Invalid key alias: " + keyAliasInKeystore);
+21 −34
Original line number Diff line number Diff line
@@ -89,18 +89,14 @@ public class AndroidKeyStoreSpi extends KeyStoreSpi {
    @Override
    public Key engineGetKey(String alias, char[] password) throws NoSuchAlgorithmException,
            UnrecoverableKeyException {
        if (isPrivateKeyEntry(alias)) {
            String privateKeyAlias = Credentials.USER_PRIVATE_KEY + alias;
            return AndroidKeyStoreProvider.loadAndroidKeyStorePrivateKeyFromKeystore(
                    mKeyStore, privateKeyAlias, mUid);
        } else if (isSecretKeyEntry(alias)) {
            String secretKeyAlias = Credentials.USER_SECRET_KEY + alias;
            return AndroidKeyStoreProvider.loadAndroidKeyStoreSecretKeyFromKeystore(
                    mKeyStore, secretKeyAlias, mUid);
        } else {
            // Key not found
            return null;
        String userKeyAlias = Credentials.USER_PRIVATE_KEY + alias;
        if (!mKeyStore.contains(userKeyAlias, mUid)) {
            // try legacy prefix for backward compatibility
            userKeyAlias = Credentials.USER_SECRET_KEY + alias;
            if (!mKeyStore.contains(userKeyAlias, mUid)) return null;
        }
        return AndroidKeyStoreProvider.loadAndroidKeyStoreKeyFromKeystore(mKeyStore, userKeyAlias,
                mUid);
    }

    @Override
@@ -540,7 +536,7 @@ public class AndroidKeyStoreSpi extends KeyStoreSpi {
            } else {
                // Keep the stored private key around -- delete all other entry types
                Credentials.deleteCertificateTypesForAlias(mKeyStore, alias, mUid);
                Credentials.deleteSecretKeyTypeForAlias(mKeyStore, alias, mUid);
                Credentials.deleteLegacyKeyForAlias(mKeyStore, alias, mUid);
            }

            // Store the leaf certificate
@@ -565,7 +561,7 @@ public class AndroidKeyStoreSpi extends KeyStoreSpi {
                    Credentials.deleteAllTypesForAlias(mKeyStore, alias, mUid);
                } else {
                    Credentials.deleteCertificateTypesForAlias(mKeyStore, alias, mUid);
                    Credentials.deleteSecretKeyTypeForAlias(mKeyStore, alias, mUid);
                    Credentials.deleteLegacyKeyForAlias(mKeyStore, alias, mUid);
                }
            }
        }
@@ -588,12 +584,17 @@ public class AndroidKeyStoreSpi extends KeyStoreSpi {
            if (keyAliasInKeystore == null) {
                throw new KeyStoreException("KeyStore-backed secret key does not have an alias");
            }
            if (!keyAliasInKeystore.startsWith(Credentials.USER_SECRET_KEY)) {
            String keyAliasPrefix = Credentials.USER_PRIVATE_KEY;
            if (!keyAliasInKeystore.startsWith(keyAliasPrefix)) {
                // try legacy prefix
                keyAliasPrefix = Credentials.USER_SECRET_KEY;
                if (!keyAliasInKeystore.startsWith(keyAliasPrefix)) {
                    throw new KeyStoreException("KeyStore-backed secret key has invalid alias: "
                            + keyAliasInKeystore);
                }
            }
            String keyEntryAlias =
                    keyAliasInKeystore.substring(Credentials.USER_SECRET_KEY.length());
                    keyAliasInKeystore.substring(keyAliasPrefix.length());
            if (!entryAlias.equals(keyEntryAlias)) {
                throw new KeyStoreException("Can only replace KeyStore-backed keys with same"
                        + " alias: " + entryAlias + " != " + keyEntryAlias);
@@ -728,7 +729,7 @@ public class AndroidKeyStoreSpi extends KeyStoreSpi {
        }

        Credentials.deleteAllTypesForAlias(mKeyStore, entryAlias, mUid);
        String keyAliasInKeystore = Credentials.USER_SECRET_KEY + entryAlias;
        String keyAliasInKeystore = Credentials.USER_PRIVATE_KEY + entryAlias;
        int errorCode = mKeyStore.importKey(
                keyAliasInKeystore,
                args,
@@ -827,24 +828,10 @@ public class AndroidKeyStoreSpi extends KeyStoreSpi {
    }

    private boolean isKeyEntry(String alias) {
        return isPrivateKeyEntry(alias) || isSecretKeyEntry(alias);
    }

    private boolean isPrivateKeyEntry(String alias) {
        if (alias == null) {
            throw new NullPointerException("alias == null");
        return mKeyStore.contains(Credentials.USER_PRIVATE_KEY + alias, mUid) ||
                mKeyStore.contains(Credentials.USER_SECRET_KEY + alias, mUid);
    }

        return mKeyStore.contains(Credentials.USER_PRIVATE_KEY + alias, mUid);
    }

    private boolean isSecretKeyEntry(String alias) {
        if (alias == null) {
            throw new NullPointerException("alias == null");
        }

        return mKeyStore.contains(Credentials.USER_SECRET_KEY + alias, mUid);
    }

    private boolean isCertificateEntry(String alias) {
        if (alias == null) {