Search in sources :

Example 36 with KeyCharacteristics

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

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 37 with KeyCharacteristics

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

the class KeyStoreTest method testAppId.

public void testAppId() throws Exception {
    String name = "test";
    byte[] id = new byte[] { 0x01, 0x02, 0x03 };
    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_RSA);
    args.addEnum(KeymasterDefs.KM_TAG_PADDING, KeymasterDefs.KM_PAD_NONE);
    args.addUnsignedInt(KeymasterDefs.KM_TAG_KEY_SIZE, 2048);
    args.addEnum(KeymasterDefs.KM_TAG_BLOCK_MODE, KeymasterDefs.KM_MODE_ECB);
    args.addBoolean(KeymasterDefs.KM_TAG_NO_AUTH_REQUIRED);
    args.addBytes(KeymasterDefs.KM_TAG_APPLICATION_ID, id);
    args.addUnsignedLong(KeymasterDefs.KM_TAG_RSA_PUBLIC_EXPONENT, RSAKeyGenParameterSpec.F4);
    KeyCharacteristics outCharacteristics = new KeyCharacteristics();
    int result = mKeyStore.generateKey(name, args, null, 0, outCharacteristics);
    assertEquals("generateRsaKey should succeed", KeyStore.NO_ERROR, result);
    assertEquals("getKeyCharacteristics should fail without application ID", KeymasterDefs.KM_ERROR_INVALID_KEY_BLOB, mKeyStore.getKeyCharacteristics(name, null, null, outCharacteristics));
    assertEquals("getKeyCharacteristics should succeed with application ID", KeyStore.NO_ERROR, mKeyStore.getKeyCharacteristics(name, new KeymasterBlob(id), null, outCharacteristics));
}
Also used : KeymasterBlob(android.security.keymaster.KeymasterBlob) KeymasterArguments(android.security.keymaster.KeymasterArguments) KeyCharacteristics(android.security.keymaster.KeyCharacteristics)

Example 38 with KeyCharacteristics

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

the class KeyStoreTest method testOperationPruning.

// This is a very implementation specific test and should be thrown out eventually, however it
// is nice for now to test that keystore is properly pruning operations.
public void testOperationPruning() 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_CTR);
    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_CTR);
    args.addEnum(KeymasterDefs.KM_TAG_PADDING, KeymasterDefs.KM_PAD_NONE);
    OperationResult result = mKeyStore.begin(name, KeymasterDefs.KM_PURPOSE_ENCRYPT, true, args, null);
    assertEquals("Begin should succeed", KeyStore.NO_ERROR, result.resultCode);
    IBinder first = result.token;
    // Implementation detail: softkeymaster supports 16 concurrent operations
    for (int i = 0; i < 16; i++) {
        result = mKeyStore.begin(name, KeymasterDefs.KM_PURPOSE_ENCRYPT, true, args, null);
        assertEquals("Begin should succeed", KeyStore.NO_ERROR, result.resultCode);
    }
    // At this point the first operation should be pruned.
    assertEquals("Operation should be pruned", KeymasterDefs.KM_ERROR_INVALID_OPERATION_HANDLE, mKeyStore.update(first, null, new byte[] { 0x01 }).resultCode);
}
Also used : IBinder(android.os.IBinder) KeymasterArguments(android.security.keymaster.KeymasterArguments) KeyCharacteristics(android.security.keymaster.KeyCharacteristics) OperationResult(android.security.keymaster.OperationResult)

Example 39 with KeyCharacteristics

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

the class KeyStoreTest method testAuthNeeded.

public void testAuthNeeded() 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_PKCS7);
    args.addUnsignedInt(KeymasterDefs.KM_TAG_KEY_SIZE, 256);
    args.addEnum(KeymasterDefs.KM_TAG_BLOCK_MODE, KeymasterDefs.KM_MODE_ECB);
    args.addEnum(KeymasterDefs.KM_TAG_USER_AUTH_TYPE, 1);
    KeyCharacteristics outCharacteristics = new KeyCharacteristics();
    int rc = mKeyStore.generateKey(name, args, null, 0, outCharacteristics);
    assertEquals("Generate should succeed", KeyStore.NO_ERROR, rc);
    OperationResult result = mKeyStore.begin(name, KeymasterDefs.KM_PURPOSE_ENCRYPT, true, args, null);
    assertEquals("Begin should expect authorization", KeyStore.OP_AUTH_NEEDED, result.resultCode);
    IBinder token = result.token;
    result = mKeyStore.update(token, null, new byte[] { 0x01, 0x02, 0x03, 0x04 });
    assertEquals("Update should require authorization", KeymasterDefs.KM_ERROR_KEY_USER_NOT_AUTHENTICATED, result.resultCode);
}
Also used : IBinder(android.os.IBinder) KeymasterArguments(android.security.keymaster.KeymasterArguments) KeyCharacteristics(android.security.keymaster.KeyCharacteristics) OperationResult(android.security.keymaster.OperationResult)

Example 40 with KeyCharacteristics

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

the class KeyStoreTest method importAesKey.

private int importAesKey(String name, byte[] key, int size, int mode) {
    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.addEnum(KeymasterDefs.KM_TAG_BLOCK_MODE, mode);
    args.addUnsignedInt(KeymasterDefs.KM_TAG_KEY_SIZE, size);
    args.addBoolean(KeymasterDefs.KM_TAG_NO_AUTH_REQUIRED);
    return mKeyStore.importKey(name, args, KeymasterDefs.KM_KEY_FORMAT_RAW, key, 0, new KeyCharacteristics());
}
Also used : KeymasterArguments(android.security.keymaster.KeymasterArguments) KeyCharacteristics(android.security.keymaster.KeyCharacteristics)

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