Search in sources :

Example 21 with KeyCharacteristics

use of android.security.keymaster.KeyCharacteristics in project android_frameworks_base by AOSPA.

the class AndroidKeyStoreSpi method setSecretKeyEntry.

private void setSecretKeyEntry(String entryAlias, SecretKey key, java.security.KeyStore.ProtectionParameter param) throws KeyStoreException {
    if ((param != null) && (!(param instanceof KeyProtection))) {
        throw new KeyStoreException("Unsupported protection parameter class: " + param.getClass().getName() + ". Supported: " + KeyProtection.class.getName());
    }
    KeyProtection params = (KeyProtection) param;
    if (key instanceof AndroidKeyStoreSecretKey) {
        // KeyStore-backed secret key. It cannot be duplicated into another entry and cannot
        // overwrite its own entry.
        String keyAliasInKeystore = ((AndroidKeyStoreSecretKey) key).getAlias();
        if (keyAliasInKeystore == null) {
            throw new KeyStoreException("KeyStore-backed secret key does not have an alias");
        }
        if (!keyAliasInKeystore.startsWith(Credentials.USER_SECRET_KEY)) {
            throw new KeyStoreException("KeyStore-backed secret key has invalid alias: " + keyAliasInKeystore);
        }
        String keyEntryAlias = keyAliasInKeystore.substring(Credentials.USER_SECRET_KEY.length());
        if (!entryAlias.equals(keyEntryAlias)) {
            throw new KeyStoreException("Can only replace KeyStore-backed keys with same" + " alias: " + entryAlias + " != " + keyEntryAlias);
        }
        // This is the entry where this key is already stored. No need to do anything.
        if (params != null) {
            throw new KeyStoreException("Modifying KeyStore-backed key using protection" + " parameters not supported");
        }
        return;
    }
    if (params == null) {
        throw new KeyStoreException("Protection parameters must be specified when importing a symmetric key");
    }
    // Not a KeyStore-backed secret key -- import its key material into keystore.
    String keyExportFormat = key.getFormat();
    if (keyExportFormat == null) {
        throw new KeyStoreException("Only secret keys that export their key material are supported");
    } else if (!"RAW".equals(keyExportFormat)) {
        throw new KeyStoreException("Unsupported secret key material export format: " + keyExportFormat);
    }
    byte[] keyMaterial = key.getEncoded();
    if (keyMaterial == null) {
        throw new KeyStoreException("Key did not export its key material despite supporting" + " RAW format export");
    }
    KeymasterArguments args = new KeymasterArguments();
    try {
        int keymasterAlgorithm = KeyProperties.KeyAlgorithm.toKeymasterSecretKeyAlgorithm(key.getAlgorithm());
        args.addEnum(KeymasterDefs.KM_TAG_ALGORITHM, keymasterAlgorithm);
        int[] keymasterDigests;
        if (keymasterAlgorithm == KeymasterDefs.KM_ALGORITHM_HMAC) {
            // JCA HMAC key algorithm implies a digest (e.g., HmacSHA256 key algorithm
            // implies SHA-256 digest). Because keymaster HMAC key is authorized only for one
            // digest, we don't let import parameters override the digest implied by the key.
            // If the parameters specify digests at all, they must specify only one digest, the
            // only implied by key algorithm.
            int keymasterImpliedDigest = KeyProperties.KeyAlgorithm.toKeymasterDigest(key.getAlgorithm());
            if (keymasterImpliedDigest == -1) {
                throw new ProviderException("HMAC key algorithm digest unknown for key algorithm " + key.getAlgorithm());
            }
            keymasterDigests = new int[] { keymasterImpliedDigest };
            if (params.isDigestsSpecified()) {
                // Digest(s) explicitly specified in params -- check that the list consists of
                // exactly one digest, the one implied by key algorithm.
                int[] keymasterDigestsFromParams = KeyProperties.Digest.allToKeymaster(params.getDigests());
                if ((keymasterDigestsFromParams.length != 1) || (keymasterDigestsFromParams[0] != keymasterImpliedDigest)) {
                    throw new KeyStoreException("Unsupported digests specification: " + Arrays.asList(params.getDigests()) + ". Only " + KeyProperties.Digest.fromKeymaster(keymasterImpliedDigest) + " supported for HMAC key algorithm " + key.getAlgorithm());
                }
            }
        } else {
            // Key algorithm does not imply a digest.
            if (params.isDigestsSpecified()) {
                keymasterDigests = KeyProperties.Digest.allToKeymaster(params.getDigests());
            } else {
                keymasterDigests = EmptyArray.INT;
            }
        }
        args.addEnums(KeymasterDefs.KM_TAG_DIGEST, keymasterDigests);
        @KeyProperties.PurposeEnum int purposes = params.getPurposes();
        int[] keymasterBlockModes = KeyProperties.BlockMode.allToKeymaster(params.getBlockModes());
        if (((purposes & KeyProperties.PURPOSE_ENCRYPT) != 0) && (params.isRandomizedEncryptionRequired())) {
            for (int keymasterBlockMode : keymasterBlockModes) {
                if (!KeymasterUtils.isKeymasterBlockModeIndCpaCompatibleWithSymmetricCrypto(keymasterBlockMode)) {
                    throw new KeyStoreException("Randomized encryption (IND-CPA) required but may be violated by" + " block mode: " + KeyProperties.BlockMode.fromKeymaster(keymasterBlockMode) + ". See KeyProtection documentation.");
                }
            }
        }
        args.addEnums(KeymasterDefs.KM_TAG_PURPOSE, KeyProperties.Purpose.allToKeymaster(purposes));
        args.addEnums(KeymasterDefs.KM_TAG_BLOCK_MODE, keymasterBlockModes);
        if (params.getSignaturePaddings().length > 0) {
            throw new KeyStoreException("Signature paddings not supported for symmetric keys");
        }
        int[] keymasterPaddings = KeyProperties.EncryptionPadding.allToKeymaster(params.getEncryptionPaddings());
        args.addEnums(KeymasterDefs.KM_TAG_PADDING, keymasterPaddings);
        KeymasterUtils.addUserAuthArgs(args, params.isUserAuthenticationRequired(), params.getUserAuthenticationValidityDurationSeconds(), params.isUserAuthenticationValidWhileOnBody(), params.isInvalidatedByBiometricEnrollment());
        KeymasterUtils.addMinMacLengthAuthorizationIfNecessary(args, keymasterAlgorithm, keymasterBlockModes, keymasterDigests);
        args.addDateIfNotNull(KeymasterDefs.KM_TAG_ACTIVE_DATETIME, params.getKeyValidityStart());
        args.addDateIfNotNull(KeymasterDefs.KM_TAG_ORIGINATION_EXPIRE_DATETIME, params.getKeyValidityForOriginationEnd());
        args.addDateIfNotNull(KeymasterDefs.KM_TAG_USAGE_EXPIRE_DATETIME, params.getKeyValidityForConsumptionEnd());
        if (((purposes & KeyProperties.PURPOSE_ENCRYPT) != 0) && (!params.isRandomizedEncryptionRequired())) {
            // Permit caller-provided IV when encrypting with this key
            args.addBoolean(KeymasterDefs.KM_TAG_CALLER_NONCE);
        }
    } catch (IllegalArgumentException | IllegalStateException e) {
        throw new KeyStoreException(e);
    }
    Credentials.deleteAllTypesForAlias(mKeyStore, entryAlias, mUid);
    String keyAliasInKeystore = Credentials.USER_SECRET_KEY + entryAlias;
    int errorCode = mKeyStore.importKey(keyAliasInKeystore, args, KeymasterDefs.KM_KEY_FORMAT_RAW, keyMaterial, mUid, // flags
    0, new KeyCharacteristics());
    if (errorCode != KeyStore.NO_ERROR) {
        throw new KeyStoreException("Failed to import secret key. Keystore error code: " + errorCode);
    }
}
Also used : KeymasterArguments(android.security.keymaster.KeymasterArguments) ProviderException(java.security.ProviderException) KeyStoreException(java.security.KeyStoreException) KeyProtection(android.security.keystore.KeyProtection) KeyCharacteristics(android.security.keymaster.KeyCharacteristics)

Example 22 with KeyCharacteristics

use of android.security.keymaster.KeyCharacteristics in project android_frameworks_base by AOSPA.

the class AndroidKeyStoreProvider method loadAndroidKeyStoreSecretKeyFromKeystore.

@NonNull
public static AndroidKeyStoreSecretKey loadAndroidKeyStoreSecretKeyFromKeystore(@NonNull KeyStore keyStore, @NonNull String secretKeyAlias, 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));
    }
    Integer keymasterAlgorithm = keyCharacteristics.getEnum(KeymasterDefs.KM_TAG_ALGORITHM);
    if (keymasterAlgorithm == null) {
        throw new UnrecoverableKeyException("Key algorithm unknown");
    }
    List<Integer> keymasterDigests = keyCharacteristics.getEnums(KeymasterDefs.KM_TAG_DIGEST);
    int keymasterDigest;
    if (keymasterDigests.isEmpty()) {
        keymasterDigest = -1;
    } else {
        // More than one digest can be permitted for this key. Use the first one to form the
        // JCA key algorithm name.
        keymasterDigest = keymasterDigests.get(0);
    }
    @KeyProperties.KeyAlgorithmEnum String keyAlgorithmString;
    try {
        keyAlgorithmString = KeyProperties.KeyAlgorithm.fromKeymasterSecretKeyAlgorithm(keymasterAlgorithm, keymasterDigest);
    } catch (IllegalArgumentException e) {
        throw (UnrecoverableKeyException) new UnrecoverableKeyException("Unsupported secret key type").initCause(e);
    }
    return new AndroidKeyStoreSecretKey(secretKeyAlias, uid, keyAlgorithmString);
}
Also used : UnrecoverableKeyException(java.security.UnrecoverableKeyException) KeyCharacteristics(android.security.keymaster.KeyCharacteristics) NonNull(android.annotation.NonNull)

Example 23 with KeyCharacteristics

use of android.security.keymaster.KeyCharacteristics in project android_frameworks_base by AOSPA.

the class AndroidKeyStoreKeyPairGeneratorSpi method generateKeystoreKeyPair.

private void generateKeystoreKeyPair(final String privateKeyAlias, KeymasterArguments args, byte[] additionalEntropy, final int flags) throws ProviderException {
    KeyCharacteristics resultingKeyCharacteristics = new KeyCharacteristics();
    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));
    }
}
Also used : ProviderException(java.security.ProviderException) KeyCharacteristics(android.security.keymaster.KeyCharacteristics)

Example 24 with KeyCharacteristics

use of android.security.keymaster.KeyCharacteristics in project android_frameworks_base by AOSPA.

the class KeyStoreTest method testGetKeyCharacteristicsSuccess.

public void testGetKeyCharacteristicsSuccess() throws Exception {
    mKeyStore.onUserPasswordChanged(TEST_PASSWD);
    String name = "test";
    KeyCharacteristics gen = generateRsaKey(name);
    KeyCharacteristics call = new KeyCharacteristics();
    int result = mKeyStore.getKeyCharacteristics(name, null, null, call);
    assertEquals("getKeyCharacteristics should succeed", KeyStore.NO_ERROR, result);
    mKeyStore.delete("test");
}
Also used : KeyCharacteristics(android.security.keymaster.KeyCharacteristics)

Example 25 with KeyCharacteristics

use of android.security.keymaster.KeyCharacteristics in project android_frameworks_base by AOSPA.

the class KeyStoreTest method testAesGcmEncryptSuccess.

public void testAesGcmEncryptSuccess() throws Exception {
    String name = "test";
    KeymasterArguments args = new KeymasterArguments();
    args.addEnum(KeymasterDefs.KM_TAG_PURPOSE, KeymasterDefs.KM_PURPOSE_ENCRYPT);
    args.addEnum(KeymasterDefs.KM_TAG_PURPOSE, KeymasterDefs.KM_PURPOSE_DECRYPT);
    args.addEnum(KeymasterDefs.KM_TAG_ALGORITHM, KeymasterDefs.KM_ALGORITHM_AES);
    args.addEnum(KeymasterDefs.KM_TAG_PADDING, KeymasterDefs.KM_PAD_NONE);
    args.addUnsignedInt(KeymasterDefs.KM_TAG_KEY_SIZE, 256);
    args.addEnum(KeymasterDefs.KM_TAG_BLOCK_MODE, KeymasterDefs.KM_MODE_GCM);
    args.addBoolean(KeymasterDefs.KM_TAG_NO_AUTH_REQUIRED);
    KeyCharacteristics outCharacteristics = new KeyCharacteristics();
    int rc = mKeyStore.generateKey(name, args, null, 0, outCharacteristics);
    assertEquals("Generate should succeed", KeyStore.NO_ERROR, rc);
    args = new KeymasterArguments();
    args.addEnum(KeymasterDefs.KM_TAG_ALGORITHM, KeymasterDefs.KM_ALGORITHM_AES);
    args.addEnum(KeymasterDefs.KM_TAG_BLOCK_MODE, KeymasterDefs.KM_MODE_GCM);
    args.addEnum(KeymasterDefs.KM_TAG_PADDING, KeymasterDefs.KM_PAD_NONE);
    args.addUnsignedInt(KeymasterDefs.KM_TAG_MAC_LENGTH, 128);
    OperationResult result = mKeyStore.begin(name, KeymasterDefs.KM_PURPOSE_ENCRYPT, true, args, null);
    IBinder token = result.token;
    assertEquals("Begin should succeed", KeyStore.NO_ERROR, result.resultCode);
    result = mKeyStore.update(token, null, new byte[] { 0x01, 0x02, 0x03, 0x04 });
    assertEquals("Update should succeed", KeyStore.NO_ERROR, result.resultCode);
    assertEquals("Finish should succeed", KeyStore.NO_ERROR, mKeyStore.finish(token, null, null).resultCode);
// TODO: Assert that an AEAD tag was returned by finish
}
Also used : IBinder(android.os.IBinder) KeymasterArguments(android.security.keymaster.KeymasterArguments) KeyCharacteristics(android.security.keymaster.KeyCharacteristics) OperationResult(android.security.keymaster.OperationResult)

Aggregations

KeyCharacteristics (android.security.keymaster.KeyCharacteristics)85 KeymasterArguments (android.security.keymaster.KeymasterArguments)50 ProviderException (java.security.ProviderException)20 IBinder (android.os.IBinder)15 OperationResult (android.security.keymaster.OperationResult)15 NonNull (android.annotation.NonNull)10 KeyProtection (android.security.keystore.KeyProtection)10 InvalidKeyException (java.security.InvalidKeyException)10 KeyStoreException (java.security.KeyStoreException)10 UnrecoverableKeyException (java.security.UnrecoverableKeyException)10 KeyStoreParameter (android.security.KeyStoreParameter)5 ExportResult (android.security.keymaster.ExportResult)5 KeymasterBlob (android.security.keymaster.KeymasterBlob)5 KeyGenParameterSpec (android.security.keystore.KeyGenParameterSpec)5 BigInteger (java.math.BigInteger)5 PrivateKey (java.security.PrivateKey)5 CertificateEncodingException (java.security.cert.CertificateEncodingException)5 X509Certificate (java.security.cert.X509Certificate)5 ArrayList (java.util.ArrayList)5 Date (java.util.Date)5