private void ensureKeystoreOperationInitialized() throws InvalidKeyException { if (mChunkedStreamer != null) { return; } if (mKey == null) { throw new IllegalStateException("Not initialized"); } KeymasterArguments keymasterArgs = new KeymasterArguments(); keymasterArgs.addEnum(KeymasterDefs.KM_TAG_ALGORITHM, KeymasterDefs.KM_ALGORITHM_HMAC); keymasterArgs.addEnum(KeymasterDefs.KM_TAG_DIGEST, mKeymasterDigest); keymasterArgs.addUnsignedInt(KeymasterDefs.KM_TAG_MAC_LENGTH, mMacSizeBits); OperationResult opResult = mKeyStore.begin( mKey.getAlias(), KeymasterDefs.KM_PURPOSE_SIGN, true, keymasterArgs, null, // no additional entropy needed for HMAC because it's deterministic mKey.getUid()); if (opResult == null) { throw new KeyStoreConnectException(); } // Store operation token and handle regardless of the error code returned by KeyStore to // ensure that the operation gets aborted immediately if the code below throws an exception. mOperationToken = opResult.token; mOperationHandle = opResult.operationHandle; // If necessary, throw an exception due to KeyStore operation having failed. InvalidKeyException e = KeyStoreCryptoOperationUtils.getInvalidKeyExceptionForInit( mKeyStore, mKey, opResult.resultCode); if (e != null) { throw e; } if (mOperationToken == null) { throw new ProviderException("Keystore returned null operation token"); } if (mOperationHandle == 0) { throw new ProviderException("Keystore returned invalid operation handle"); } mChunkedStreamer = new KeyStoreCryptoOperationChunkedStreamer( new KeyStoreCryptoOperationChunkedStreamer.MainDataStream(mKeyStore, mOperationToken)); }
@Override protected SecretKey engineGenerateKey() { KeyGenParameterSpec spec = mSpec; if (spec == null) { throw new IllegalStateException("Not initialized"); } if ((spec.isEncryptionAtRestRequired()) && (mKeyStore.state() != KeyStore.State.UNLOCKED)) { throw new IllegalStateException( "Requested to import a key which must be encrypted at rest using secure lock" + " screen credential, but the credential hasn't yet been entered by the user"); } KeymasterArguments args = new KeymasterArguments(); args.addInt(KeymasterDefs.KM_TAG_KEY_SIZE, mKeySizeBits); args.addInt(KeymasterDefs.KM_TAG_ALGORITHM, mKeymasterAlgorithm); args.addInts(KeymasterDefs.KM_TAG_PURPOSE, mKeymasterPurposes); args.addInts(KeymasterDefs.KM_TAG_BLOCK_MODE, mKeymasterBlockModes); args.addInts(KeymasterDefs.KM_TAG_PADDING, mKeymasterPaddings); args.addInts(KeymasterDefs.KM_TAG_DIGEST, mKeymasterDigests); KeymasterUtils.addUserAuthArgs( args, spec.isUserAuthenticationRequired(), spec.getUserAuthenticationValidityDurationSeconds()); args.addDate( KeymasterDefs.KM_TAG_ACTIVE_DATETIME, (spec.getKeyValidityStart() != null) ? spec.getKeyValidityStart() : new Date(0)); args.addDate( KeymasterDefs.KM_TAG_ORIGINATION_EXPIRE_DATETIME, (spec.getKeyValidityForOriginationEnd() != null) ? spec.getKeyValidityForOriginationEnd() : new Date(Long.MAX_VALUE)); args.addDate( KeymasterDefs.KM_TAG_USAGE_EXPIRE_DATETIME, (spec.getKeyValidityForConsumptionEnd() != null) ? spec.getKeyValidityForConsumptionEnd() : new Date(Long.MAX_VALUE)); if (((spec.getPurposes() & KeyProperties.PURPOSE_ENCRYPT) != 0) && (!spec.isRandomizedEncryptionRequired())) { // Permit caller-provided IV when encrypting with this key args.addBoolean(KeymasterDefs.KM_TAG_CALLER_NONCE); } byte[] additionalEntropy = KeyStoreCryptoOperationUtils.getRandomBytesToMixIntoKeystoreRng( mRng, (mKeySizeBits + 7) / 8); int flags = spec.getFlags(); String keyAliasInKeystore = Credentials.USER_SECRET_KEY + spec.getKeystoreAlias(); KeyCharacteristics resultingKeyCharacteristics = new KeyCharacteristics(); int errorCode = mKeyStore.generateKey( keyAliasInKeystore, args, additionalEntropy, flags, resultingKeyCharacteristics); if (errorCode != KeyStore.NO_ERROR) { throw new ProviderException( "Keystore operation failed", KeyStore.getKeyStoreException(errorCode)); } @KeyProperties.KeyAlgorithmEnum String keyAlgorithmJCA; try { keyAlgorithmJCA = KeyProperties.KeyAlgorithm.fromKeymasterSecretKeyAlgorithm( mKeymasterAlgorithm, mKeymasterDigest); } catch (IllegalArgumentException e) { throw new ProviderException("Failed to obtain JCA secret key algorithm name", e); } return new KeyStoreSecretKey(keyAliasInKeystore, keyAlgorithmJCA); }