diff --git a/Applet/AndroidSEProviderLib/src/com/android/javacard/seprovider/KMAndroidSEProvider.java b/Applet/AndroidSEProviderLib/src/com/android/javacard/seprovider/KMAndroidSEProvider.java index d21e25ab..5365dcaa 100644 --- a/Applet/AndroidSEProviderLib/src/com/android/javacard/seprovider/KMAndroidSEProvider.java +++ b/Applet/AndroidSEProviderLib/src/com/android/javacard/seprovider/KMAndroidSEProvider.java @@ -583,11 +583,16 @@ private byte mapCipherAlg(byte alg, byte padding, byte blockmode, byte digest) { public KMOperation createSymmetricCipher(short alg, short purpose, short macLength, short blockMode, short padding, byte[] secret, short secretStart, - short secretLength, byte[] ivBuffer, short ivStart, short ivLength) { - - short cipherAlg = mapCipherAlg((byte) alg, (byte) padding, (byte) blockMode, (byte) 0); - KMOperation operation = - poolMgr.getOperationImpl(purpose, cipherAlg, alg, padding, blockMode, macLength, secretLength, false); + short secretLength, byte[] ivBuffer, short ivStart, short ivLength, + boolean isRkp) { + + short cipherAlg = mapCipherAlg((byte) alg, (byte) padding, (byte) blockMode, (byte) 0); + KMOperation operation = null; + if (isRkp) { + operation = poolMgr.getRKpOperation(purpose, cipherAlg, alg, padding, blockMode, macLength); + } else { + operation = poolMgr.getOperationImpl(purpose, cipherAlg, alg, padding, blockMode, macLength, secretLength, false); + } // Get the KeyObject from the operation and update the key with the secret key material. KMKeyObject keyObj = operation.getKeyObject(); Key key = (Key)keyObj.getKeyObjectInstance(); @@ -608,13 +613,18 @@ public KMOperation createSymmetricCipher(short alg, short purpose, short macLeng } public KMOperation createHmacSignerVerifier(short purpose, short digest, - byte[] secret, short secretStart, short secretLength) { + byte[] secret, short secretStart, short secretLength, boolean isRkp) { + KMOperation operation = null; if (digest != KMType.SHA2_256) { CryptoException.throwIt(CryptoException.ILLEGAL_VALUE); } - KMOperation operation = - poolMgr.getOperationImpl(purpose, Signature.ALG_HMAC_SHA_256, + if (isRkp) { + operation = poolMgr.getRKpOperation(purpose, Signature.ALG_HMAC_SHA_256, KMType.HMAC, + KMType.INVALID_VALUE, KMType.INVALID_VALUE, KMType.INVALID_VALUE); + } else { + operation = poolMgr.getOperationImpl(purpose, Signature.ALG_HMAC_SHA_256, KMType.HMAC, KMType.INVALID_VALUE, KMType.INVALID_VALUE, KMType.INVALID_VALUE, (short)0, false); + } // Get the KeyObject from the operation and update the key with the secret key material. KMKeyObject keyObj = operation.getKeyObject(); HMACKey key = (HMACKey)keyObj.getKeyObjectInstance(); @@ -632,13 +642,36 @@ private KMOperation createHmacSignerVerifier(short purpose, short digest, HMACKe KMType.HMAC, KMType.INVALID_VALUE, KMType.INVALID_VALUE, KMType.INVALID_VALUE, (short)0, isTrustedConf); // Get the KeyObject from the operation and update the key with the secret key material. KMKeyObject keyObj = operation.getKeyObject(); - HMACKey key = (HMACKey)keyObj.getKeyObject(); + HMACKey key = (HMACKey)keyObj.getKeyObjectInstance(); short len = hmacKey.getKey(tmpArray, (short) 0); key.setKey(tmpArray, (short) 0, len); ((KMOperationImpl) operation).init(key, digest, null, (short) 0, (short) 0); return operation; } + @Override + public KMOperation getRkpOperation(byte purpose, byte alg, + byte digest, byte padding, byte blockMode, byte[] keyBuf, short keyStart, + short keyLength, byte[] ivBuf, short ivStart, short ivLength, + short macLength) { + KMOperation opr = null; + switch (alg) { + case KMType.AES: + // Convert macLength to bytes + macLength = (short) (macLength / 8); + opr = createSymmetricCipher(alg, purpose, macLength, blockMode, padding, keyBuf, keyStart, keyLength, ivBuf, + ivStart, ivLength, true/* isRKP */); + break; + case KMType.HMAC: + opr = createHmacSignerVerifier(purpose, digest, keyBuf, keyStart, keyLength, true/* isRKP */); + break; + default: + CryptoException.throwIt(CryptoException.NO_SUCH_ALGORITHM); + break; + } + return opr; + } + @Override public KMOperation initSymmetricOperation(byte purpose, byte alg, byte digest, byte padding, byte blockMode, byte[] keyBuf, short keyStart, @@ -651,10 +684,10 @@ public KMOperation initSymmetricOperation(byte purpose, byte alg, // Convert macLength to bytes macLength = (short) (macLength / 8); opr = createSymmetricCipher(alg, purpose, macLength, blockMode, padding, keyBuf, keyStart, - keyLength, ivBuf, ivStart, ivLength); + keyLength, ivBuf, ivStart, ivLength, false/* isRKP */); break; case KMType.HMAC: - opr = createHmacSignerVerifier(purpose, digest, keyBuf, keyStart, keyLength); + opr = createHmacSignerVerifier(purpose, digest, keyBuf, keyStart, keyLength, false/* isRKP */); break; default: CryptoException.throwIt(CryptoException.NO_SUCH_ALGORITHM); diff --git a/Applet/AndroidSEProviderLib/src/com/android/javacard/seprovider/KMPoolManager.java b/Applet/AndroidSEProviderLib/src/com/android/javacard/seprovider/KMPoolManager.java index 9db4d0fb..7b65303a 100644 --- a/Applet/AndroidSEProviderLib/src/com/android/javacard/seprovider/KMPoolManager.java +++ b/Applet/AndroidSEProviderLib/src/com/android/javacard/seprovider/KMPoolManager.java @@ -24,7 +24,6 @@ import javacard.security.KeyAgreement; import javacard.security.KeyBuilder; import javacard.security.KeyPair; -import javacard.security.SecretKey; import javacard.security.Signature; import javacardx.crypto.AEADCipher; import javacardx.crypto.Cipher; @@ -68,15 +67,21 @@ public class KMPoolManager { private Object[] hmacSignOperationPool; private Object[] keysPool; + // RKP uses AESGCM and HMAC in generateCSR flow. + KMOperation rkpOPeration; + Cipher rkpAesGcm; + Signature rkpHmac; + KMKeyObject rkpHmacKey; + KMKeyObject rkpAesKey; final byte[] KEY_ALGS = { AES_128, AES_256, - KMType.DES, - KMType.RSA, - KMType.EC, - KMType.HMAC, - }; + KMType.DES, + KMType.RSA, + KMType.EC, + KMType.HMAC, + }; final byte[] CIPHER_ALGS = { Cipher.ALG_AES_BLOCK_128_CBC_NOPAD, @@ -186,8 +191,8 @@ private KMPoolManager() { keyAgreementPool = new Object[(short) (KEY_AGREE_ALGS.length * 4)]; keysPool = new Object[(short) ((KEY_ALGS.length * 4) + 4)]; - operationPool = new Object[4]; - hmacSignOperationPool = new Object[4]; + operationPool = new Object[MAX_OPERATION_INSTANCES]; + hmacSignOperationPool = new Object[MAX_OPERATION_INSTANCES]; /* Initialize pools */ initializeOperationPool(); initializeHmacSignOperationPool(); @@ -195,8 +200,18 @@ private KMPoolManager() { initializeCipherPool(); initializeKeyAgreementPool(); initializeKeysPool(); + // Initialize the Crypto and Key objects required for RKP flow. + initializeRKpObjects(); } + + private void initializeRKpObjects() { + rkpOPeration = new KMOperationImpl(); + rkpAesGcm = Cipher.getInstance(AEADCipher.ALG_AES_GCM, false); + rkpHmac = Signature.getInstance(Signature.ALG_HMAC_SHA_256, false); + rkpAesKey = createKeyObjectInstance(AES_256); + rkpHmacKey = createKeyObjectInstance(KMType.HMAC); + } private void initializeKeysPool() { short index = 0; @@ -229,6 +244,12 @@ private void initializeSignerPool() { signerPool[index] = getSignatureInstance(SIG_ALGS[index]); index++; } + // Allocate extra 4 HMAC signer instances required for trusted confirmation + short len = (short) (index + 4); + while (index < len) { + signerPool[index] = getSignatureInstance(Signature.ALG_HMAC_SHA_256); + index++; + } } //Create a cipher instance of each algorithm once. @@ -428,6 +449,34 @@ private void reserveOperation(KMOperation operation, short purpose, short strong ((KMOperationImpl) operation).setKeyObject(keyObject); setObject(purpose, operation, obj); } + + public KMOperation getRKpOperation(short purpose, short alg, short strongboxAlgType, + short padding, short blockMode, short macLength) { + if (((KMOperationImpl) rkpOPeration).getPurpose() != KMType.INVALID_VALUE) { + // Should not come here. + KMException.throwIt(KMError.UNKNOWN_ERROR); + } + Object cryptoObj = null; + KMKeyObject keyObject = null; + + switch (alg) { + case AEADCipher.ALG_AES_GCM: + cryptoObj = rkpAesGcm; + keyObject = rkpAesKey; + break; + case Signature.ALG_HMAC_SHA_256: + cryptoObj = rkpHmac; + keyObject = rkpHmacKey; + break; + default: + // Should not come here. + KMException.throwIt(KMError.UNSUPPORTED_ALGORITHM); + break; + } + reserveOperation(rkpOPeration, purpose, strongboxAlgType, padding, blockMode, macLength, + cryptoObj, keyObject); + return rkpOPeration; + } public KMOperation getOperationImpl(short purpose, short alg, short strongboxAlgType, @@ -573,6 +622,8 @@ public void powerReset() { ((KMOperationImpl) hmacSignOperationPool[index]).abort(); index++; } + // release rkp operation + rkpOPeration.abort(); } } diff --git a/Applet/AndroidSEProviderLib/src/com/android/javacard/seprovider/KMSEProvider.java b/Applet/AndroidSEProviderLib/src/com/android/javacard/seprovider/KMSEProvider.java index 515fe4b4..9177109c 100644 --- a/Applet/AndroidSEProviderLib/src/com/android/javacard/seprovider/KMSEProvider.java +++ b/Applet/AndroidSEProviderLib/src/com/android/javacard/seprovider/KMSEProvider.java @@ -540,6 +540,39 @@ KMOperation initSymmetricOperation( short ivLength, short macLength); + /** + * This function creates an Operation instance only for RKP module. + * + * @param purpose is KMType.ENCRYPT or KMType.DECRYPT for AES and DES algorithm. It will be + * KMType.SIGN and KMType.VERIFY for HMAC algorithm + * @param alg is KMType.HMAC, KMType.AES or KMType.DES. + * @param digest is KMType.SHA2_256 in case of HMAC else it will be KMType.DIGEST_NONE. + * @param padding is KMType.PADDING_NONE or KMType.PKCS7 (in case of AES and DES). + * @param blockMode is KMType.CTR, KMType.GCM. KMType.CBC or KMType.ECB for AES or DES else it is + * 0. + * @param keyBuf is aes, des or hmac key buffer. + * @param keyStart is the start of the key buffer. + * @param keyLength is the length of the key buffer. + * @param ivBuf is the iv buffer (in case on AES and DES algorithm without ECB mode) + * @param ivStart is the start of the iv buffer. + * @param ivLength is the length of the iv buffer. It will be zero in case of HMAC and AES/DES + * with ECB mode. + * @param macLength is the mac length in case of signing operation for hmac algorithm. + * @return KMOperation instance. + */ + KMOperation getRkpOperation(byte purpose, + byte alg, + byte digest, + byte padding, + byte blockMode, + byte[] keyBuf, + short keyStart, + short keyLength, + byte[] ivBuf, + short ivStart, + short ivLength, + short macLength); + /** * This creates a persistent operation for signing, verify, encryption and decryption using RSA * and EC algorithms when keymaster hal's beginOperation function is executed. For RSA the public diff --git a/Applet/src/com/android/javacard/keymaster/KMKeymintDataStore.java b/Applet/src/com/android/javacard/keymaster/KMKeymintDataStore.java index 2a1f24e8..581a18e2 100644 --- a/Applet/src/com/android/javacard/keymaster/KMKeymintDataStore.java +++ b/Applet/src/com/android/javacard/keymaster/KMKeymintDataStore.java @@ -570,7 +570,7 @@ public void createRkpMacKey(byte[] keydata, short offset, short length) { } } - public KMRkpMacKey getRkpMacacKey() { + public KMRkpMacKey getRkpMacKey() { return rkpMacKey; } diff --git a/Applet/src/com/android/javacard/keymaster/RemotelyProvisionedComponentDevice.java b/Applet/src/com/android/javacard/keymaster/RemotelyProvisionedComponentDevice.java index 87ad8541..578cbcdb 100644 --- a/Applet/src/com/android/javacard/keymaster/RemotelyProvisionedComponentDevice.java +++ b/Applet/src/com/android/javacard/keymaster/RemotelyProvisionedComponentDevice.java @@ -1093,7 +1093,7 @@ private short generateEphemeralEcKey(byte[] scratchPad) { private void initHmacOperation() { short dataEntryIndex = getEntry(EPHEMERAL_MAC_KEY); operation[0] = - seProvider.initSymmetricOperation( + seProvider.getRkpOperation( KMType.SIGN, KMType.HMAC, KMType.SHA2_256, @@ -1134,7 +1134,7 @@ private void initAesGcmOperation(byte[] scratchPad, short nonce) { ); // Initialize the Cipher object. operation[0] = - seProvider.initSymmetricOperation( + seProvider.getRkpOperation( KMType.ENCRYPT, KMType.AES, (byte) 0, @@ -1470,7 +1470,7 @@ private short rkpHmacSign(boolean testMode, byte[] data, short dataStart, short KMByteBlob.cast(macKey).getStartOff(), MAC_KEY_SIZE, (byte) 0); result = seProvider.hmacSign(KMByteBlob.cast(macKey).getBuffer(), KMByteBlob.cast(macKey).getStartOff(), MAC_KEY_SIZE, data, dataStart, dataLength, signature, signatureStart); } else { - result = seProvider.hmacSign(storeDataInst.getRkpMacacKey(), data, dataStart, dataLength, signature, signatureStart); + result = seProvider.hmacSign(storeDataInst.getRkpMacKey(), data, dataStart, dataLength, signature, signatureStart); } return result; }