From 154c9493b6824afa24c4ea6706fb9351e1e7ee2c Mon Sep 17 00:00:00 2001 From: Subrahmanyaman Date: Thu, 21 Apr 2022 16:04:59 +0000 Subject: [PATCH 1/8] customtags change --- .../javacard/keymaster/KMAndroidSEApplet.java | 1 + .../javacard/seprovider/KMJCardSimulator.java | 6 +- .../javacard/keymaster/KMKeyParameters.java | 70 ++++++----- .../javacard/keymaster/KMKeymasterApplet.java | 119 ++++++++---------- .../android/javacard/keymaster/KMType.java | 8 ++ 5 files changed, 105 insertions(+), 99 deletions(-) diff --git a/Applet/AndroidSEProvider/src/com/android/javacard/keymaster/KMAndroidSEApplet.java b/Applet/AndroidSEProvider/src/com/android/javacard/keymaster/KMAndroidSEApplet.java index 1987d576..45822390 100644 --- a/Applet/AndroidSEProvider/src/com/android/javacard/keymaster/KMAndroidSEApplet.java +++ b/Applet/AndroidSEProvider/src/com/android/javacard/keymaster/KMAndroidSEApplet.java @@ -97,6 +97,7 @@ public static void install(byte[] bArray, short bOffset, byte bLength) { @Override public void process(APDU apdu) { try { + resetData(); // If this is select applet apdu which is selecting this applet then return if (apdu.isISOInterindustryCLA()) { if (selectingApplet()) { diff --git a/Applet/JCardSimProviderLib/src/com/android/javacard/seprovider/KMJCardSimulator.java b/Applet/JCardSimProviderLib/src/com/android/javacard/seprovider/KMJCardSimulator.java index 31ca6519..ee5a8d4d 100644 --- a/Applet/JCardSimProviderLib/src/com/android/javacard/seprovider/KMJCardSimulator.java +++ b/Applet/JCardSimProviderLib/src/com/android/javacard/seprovider/KMJCardSimulator.java @@ -621,8 +621,10 @@ public short hmacSign(Object key, byte[] data, short dataStart, short dataLength @Override public boolean hmacVerify(KMComputedHmacKey key, byte[] data, short dataStart, short dataLength, byte[] mac, short macStart, short macLength) { - KMHmacKey hmacKey = (KMHmacKey) key; - hmacSignature.init(hmacKey.getKey(), Signature.MODE_VERIFY); + //KMHmacKey hmacKey = (KMHmacKey) key; + byte[] keyBuf = new byte[32]; + HMACKey hmacKey = createHMACKey(keyBuf, (short) 0, (short) keyBuf.length); + hmacSignature.init(hmacKey, Signature.MODE_VERIFY); return hmacSignature.verify(data, dataStart, dataLength, mac, macStart, macLength); } diff --git a/Applet/src/com/android/javacard/keymaster/KMKeyParameters.java b/Applet/src/com/android/javacard/keymaster/KMKeyParameters.java index 9b2e4dad..d1ea64ba 100644 --- a/Applet/src/com/android/javacard/keymaster/KMKeyParameters.java +++ b/Applet/src/com/android/javacard/keymaster/KMKeyParameters.java @@ -46,37 +46,43 @@ private static KMKeyParameters proto(short ptr) { } public static short exp() { - short arrPtr = KMArray.instance((short) 11); - KMArray arr = KMArray.cast(arrPtr); - arr.add((short) 0, KMEnum.instance(KMType.RULE, KMType.FAIL_ON_INVALID_TAGS)); - arr.add((short) 1, KMIntegerTag.exp(UINT_TAG)); - arr.add((short) 2, KMIntegerArrayTag.exp(UINT_ARRAY_TAG)); - arr.add((short) 3, KMIntegerTag.exp(ULONG_TAG)); - arr.add((short) 4, KMIntegerTag.exp(DATE_TAG)); - arr.add((short) 5, KMIntegerArrayTag.exp(ULONG_ARRAY_TAG)); - arr.add((short) 6, KMEnumTag.exp()); - arr.add((short) 7, KMEnumArrayTag.exp()); - arr.add((short) 8, KMByteTag.exp()); - arr.add((short) 9, KMBoolTag.exp()); - arr.add((short) 10, KMBignumTag.exp()); - return instance(arrPtr); + if (KMType.keyParamExp[0] == KMType.INVALID_VALUE) { + short arrPtr = KMArray.instance((short) 11); + KMArray arr = KMArray.cast(arrPtr); + arr.add((short) 0, KMEnum.instance(KMType.RULE, KMType.FAIL_ON_INVALID_TAGS)); + arr.add((short) 1, KMIntegerTag.exp(UINT_TAG)); + arr.add((short) 2, KMIntegerArrayTag.exp(UINT_ARRAY_TAG)); + arr.add((short) 3, KMIntegerTag.exp(ULONG_TAG)); + arr.add((short) 4, KMIntegerTag.exp(DATE_TAG)); + arr.add((short) 5, KMIntegerArrayTag.exp(ULONG_ARRAY_TAG)); + arr.add((short) 6, KMEnumTag.exp()); + arr.add((short) 7, KMEnumArrayTag.exp()); + arr.add((short) 8, KMByteTag.exp()); + arr.add((short) 9, KMBoolTag.exp()); + arr.add((short) 10, KMBignumTag.exp()); + KMType.keyParamExp[0] = instance(arrPtr); + } + return KMType.keyParamExp[0]; } public static short expAny() { - short arrPtr = KMArray.instance((short) 11); - KMArray arr = KMArray.cast(arrPtr); - arr.add((short) 0, KMEnum.instance(KMType.RULE, KMType.IGNORE_INVALID_TAGS)); - arr.add((short) 1, KMIntegerTag.exp(UINT_TAG)); - arr.add((short) 2, KMIntegerArrayTag.exp(UINT_ARRAY_TAG)); - arr.add((short) 3, KMIntegerTag.exp(ULONG_TAG)); - arr.add((short) 4, KMIntegerTag.exp(DATE_TAG)); - arr.add((short) 5, KMIntegerArrayTag.exp(ULONG_ARRAY_TAG)); - arr.add((short) 6, KMEnumTag.exp()); - arr.add((short) 7, KMEnumArrayTag.exp()); - arr.add((short) 8, KMByteTag.exp()); - arr.add((short) 9, KMBoolTag.exp()); - arr.add((short) 10, KMBignumTag.exp()); - return instance(arrPtr); + if (KMType.keyParamExp[1] == KMType.INVALID_VALUE) { + short arrPtr = KMArray.instance((short) 11); + KMArray arr = KMArray.cast(arrPtr); + arr.add((short) 0, KMEnum.instance(KMType.RULE, KMType.IGNORE_INVALID_TAGS)); + arr.add((short) 1, KMIntegerTag.exp(UINT_TAG)); + arr.add((short) 2, KMIntegerArrayTag.exp(UINT_ARRAY_TAG)); + arr.add((short) 3, KMIntegerTag.exp(ULONG_TAG)); + arr.add((short) 4, KMIntegerTag.exp(DATE_TAG)); + arr.add((short) 5, KMIntegerArrayTag.exp(ULONG_ARRAY_TAG)); + arr.add((short) 6, KMEnumTag.exp()); + arr.add((short) 7, KMEnumArrayTag.exp()); + arr.add((short) 8, KMByteTag.exp()); + arr.add((short) 9, KMBoolTag.exp()); + arr.add((short) 10, KMBignumTag.exp()); + KMType.keyParamExp[1] = instance(arrPtr); + } + return KMType.keyParamExp[1]; } public static short instance(short vals) { @@ -393,9 +399,6 @@ public static short makeTeeEnforced(short keyParamsPtr, byte[] scratchPad) { } index++; } - // Add custom tags at the end of the array. So it becomes easy to - // delete them when sending key characteristics back to HAL. - arrInd = addCustomTags(keyParamsPtr, scratchPad, arrInd); return createKeyParameters(scratchPad, (short) (arrInd / 2)); } @@ -471,9 +474,10 @@ public static short createKeyParameters(byte[] ptrArr, short len) { return KMKeyParameters.instance(arrPtr); } - public static short addCustomTags(short keyParams, byte[] scratchPad, short offset) { + public static short makeCustomTags(short keyParams, byte[] scratchPad) { short index = 0; short tagPtr; + short offset = 0; short len = (short) customTags.length; short tagType; while (index < len) { @@ -493,7 +497,7 @@ public static short addCustomTags(short keyParams, byte[] scratchPad, short offs } index += 2; } - return offset; + return createKeyParameters(scratchPad, (short) (offset / 2)); } public void deleteCustomTags() { diff --git a/Applet/src/com/android/javacard/keymaster/KMKeymasterApplet.java b/Applet/src/com/android/javacard/keymaster/KMKeymasterApplet.java index 64b81ea6..fcb6d2ae 100644 --- a/Applet/src/com/android/javacard/keymaster/KMKeymasterApplet.java +++ b/Applet/src/com/android/javacard/keymaster/KMKeymasterApplet.java @@ -191,6 +191,7 @@ public class KMKeymasterApplet extends Applet implements AppletEvent, ExtendedLe public static final byte SB_PARAMETERS = 35; public static final byte CONFIRMATION_TOKEN = 36; public static final byte KEY_BLOB_VERSION_DATA_OFFSET = 37; + public static final byte CUSTOM_TAGS = 38; // Constant // AddRngEntropy @@ -202,7 +203,8 @@ public class KMKeymasterApplet extends Applet implements AppletEvent, ExtendedLe public static final byte KEY_BLOB_NONCE = 2; public static final byte KEY_BLOB_AUTH_TAG = 3; public static final byte KEY_BLOB_PARAMS = 4; - public static final byte KEY_BLOB_PUB_KEY = 5; + public static final byte KEY_BLOB_CUSTOM_TAGS = 5; + public static final byte KEY_BLOB_PUB_KEY = 6; // AES GCM constants public static final byte AES_GCM_AUTH_TAG_LENGTH = 16; public static final byte AES_GCM_NONCE_LENGTH = 12; @@ -217,8 +219,8 @@ public class KMKeymasterApplet extends Applet implements AppletEvent, ExtendedLe // KeyBlob (structure, encryption algorithm etc). public static final short KEYBLOB_CURRENT_VERSION = 1; // KeyBlob array size constants. - public static final byte SYM_KEY_BLOB_SIZE_V1 = 5; - public static final byte ASYM_KEY_BLOB_SIZE_V1 = 6; + public static final byte SYM_KEY_BLOB_SIZE_V1 = 6; + public static final byte ASYM_KEY_BLOB_SIZE_V1 = 7; public static final byte SYM_KEY_BLOB_SIZE_V0 = 4; public static final byte ASYM_KEY_BLOB_SIZE_V0 = 5; // Key type constants @@ -397,7 +399,6 @@ protected short mapCryptoErrorToKMError(short reason) { @Override public void process(APDU apdu) { try { - resetData(); repository.onProcess(); // If this is select applet apdu which is selecting this applet then return if (apdu.isISOInterindustryCLA()) { @@ -594,6 +595,7 @@ protected void resetData() { tmpVariables[index] = KMType.INVALID_VALUE; index++; } + KMType.resetData(); } /** @@ -652,23 +654,11 @@ public void sendOutgoing(APDU apdu, KMAttestationCert cert, short certStart, sho // reclaim the unused memory in the certificate. repository.reclaimMemory((short) (bufferStart - certStart)); } - // Reserve space of MAX_KEY_CHARS_SIZE to encode KeyCharacteristics - short prevReclaimIndex = repository.getHeapReclaimIndex(); - short keyCharsIndex = repository.allocReclaimableMemory(MAX_KEY_CHARS_SIZE); - - // Encode keyblob at the end of the buffer before KEY_CHARACTERISTICS - short keyBlobLen = encodeKeyBlob(keyblob); - short keyBlobStart = repository.getHeapReclaimIndex(); // Encode KeyCharacteristics at the end of heap just before data[CERTIFICATE] - // in the reserved space of MAX_KEY_CHARS_SIZE - short keyCharsLen = encodeKeyCharacteristics(keyCharsIndex, prevReclaimIndex, keyChars); - - // Adjust the keyblob buffer before KeyChars and reclaim the memory - short newKeyBlobStart = (short) (keyBlobStart + (MAX_KEY_CHARS_SIZE - keyCharsLen)); - Util.arrayCopyNonAtomic(buffer, keyBlobStart, buffer, newKeyBlobStart, keyBlobLen); - repository.reclaimMemory((short) (newKeyBlobStart - keyBlobStart)); - + encodeKeyCharacteristics(keyChars); + // and encode it to the end of the buffer before KEY_CHARACTERISTICS + encodeKeyBlob(keyblob); // Write Array header and ErrorCode before data[KEY_BLOB] short bufferStartOffset = repository.allocReclaimableMemory((short) 2); Util.setShort(buffer, bufferStartOffset, (short) 0x8400); @@ -779,11 +769,6 @@ private void processGetKeyCharacteristicsCmd(APDU apdu) { if (isKeyUpgradeRequired(data[KEY_BLOB], data[APP_ID], data[APP_DATA], scratchPad)) { KMException.throwIt(KMError.KEY_REQUIRES_UPGRADE); } - // Remove custom tags from key characteristics - short teeParams = KMKeyCharacteristics.cast(data[KEY_CHARACTERISTICS]).getTeeEnforced(); - if(teeParams != KMType.INVALID_VALUE) { - KMKeyParameters.cast(teeParams).deleteCustomTags(); - } // make response. short resp = KMArray.instance((short) 2); KMArray.cast(resp).add((short) 0, KMInteger.uint_16(KMError.OK)); @@ -816,6 +801,7 @@ private short createKeyBlobExp(short version) { short keyBlob = KMType.INVALID_VALUE; short byteBlobExp = KMByteBlob.exp(); short keyChar = KMKeyCharacteristics.exp(); + short keyParam = KMKeyParameters.exp(); switch(version) { case (short) 0: // Old KeyBlob has a maximum of 5 elements. @@ -833,6 +819,7 @@ private short createKeyBlobExp(short version) { KMArray.cast(keyBlob).add(KMKeymasterApplet.KEY_BLOB_AUTH_TAG, byteBlobExp); KMArray.cast(keyBlob).add(KMKeymasterApplet.KEY_BLOB_NONCE, byteBlobExp); KMArray.cast(keyBlob).add(KMKeymasterApplet.KEY_BLOB_PARAMS, keyChar); + KMArray.cast(keyBlob).add(KMKeymasterApplet.KEY_BLOB_CUSTOM_TAGS, keyParam); KMArray.cast(keyBlob).add(KMKeymasterApplet.KEY_BLOB_PUB_KEY, byteBlobExp); break; default: @@ -1365,6 +1352,7 @@ private KMAttestationCert makeAttestationCert(short attKeyBlob, short attKeyPara short privKey = data[SECRET]; short hwParams = data[HW_PARAMETERS]; short keyChars = data[KEY_CHARACTERISTICS]; + short customTags = data[CUSTOM_TAGS]; // Check if key requires upgrade for attestKeyBlob. The KeyBlob is parsed inside // isKeyUpgradeRequired function itself. if (isKeyUpgradeRequired(attKeyBlob, appId, appData, scratchPad)) { @@ -1412,6 +1400,7 @@ private KMAttestationCert makeAttestationCert(short attKeyBlob, short attKeyPara data[KEY_BLOB] = origBlob; data[HW_PARAMETERS] = hwParams; data[KEY_CHARACTERISTICS] = keyChars; + data[CUSTOM_TAGS] = customTags; data[SW_PARAMETERS] = KMKeyCharacteristics.cast(data[KEY_CHARACTERISTICS]).getKeystoreEnforced(); data[TEE_PARAMETERS] = KMKeyCharacteristics.cast(data[KEY_CHARACTERISTICS]).getTeeEnforced(); data[SB_PARAMETERS] = KMKeyCharacteristics.cast(data[KEY_CHARACTERISTICS]).getStrongboxEnforced(); @@ -3506,20 +3495,6 @@ private void processGenerateKey(APDU apdu) { sendOutgoing(apdu, cert, data[CERTIFICATE], data[KEY_BLOB], data[KEY_CHARACTERISTICS]); } - private short generateAttestKeyCmd(APDU apdu) { - short params = KMKeyParameters.expAny(); - short blob = KMByteBlob.exp(); - // Array of expected arguments - short cmd = KMArray.instance((short) 6); - KMArray.cast(cmd).add((short) 0, blob); // key blob - KMArray.cast(cmd).add((short) 1, params); // keyparamters to be attested. - KMArray.cast(cmd).add((short) 2, blob); // attest key blob - KMArray.cast(cmd).add((short) 3, params); // attest key params - KMArray.cast(cmd).add((short) 4, blob); // attest issuer - KMArray.cast(cmd).add((short) 5, blob); // keyparams mac. - - return receiveIncoming(apdu, cmd); - } private short getApplicationId(short params) { short appId = KMKeyParameters.findTag(KMType.BYTES_TAG, KMType.APPLICATION_ID, params); @@ -3781,7 +3756,7 @@ protected static short getBootPatchLevel(byte[] scratchPad){ // KeyBlob's KeyCharacteristics. // 2. Re-create KeyBlob's KeyCharacteristics from HW_PARAMS to make sure we don't miss // anything which happens in these functions makeSbEnforced and makeTeeEnforced in - // the future. Like validations, addition of custom tags e.t.c. + // the future. Like validations. // 3. No need to create Keystore Enforced list here as it is not required to be included in // the KeyBlob's KeyCharacteristics. // 4. No need to create KeyCharacteristics as upgradeKey does not require to return any @@ -3795,6 +3770,20 @@ private static void upgradeKeyBlobKeyCharacteristics(short hwParams, byte[] scra hwParams, (byte) data[ORIGIN], osVersion, osPatch, vendorPatch, bootPatch, scratchPad); data[TEE_PARAMETERS] = KMKeyParameters.makeTeeEnforced(hwParams, scratchPad); data[HW_PARAMETERS] = KMKeyParameters.makeHwEnforced(data[SB_PARAMETERS], data[TEE_PARAMETERS]); + + // Create custom tags from tee params and remove the custom tags from old Keyblob keychars. + short version = KMInteger.cast(data[KEY_BLOB_VERSION_DATA_OFFSET]).getShort(); + switch (version) { + case 0: + if (data[TEE_PARAMETERS] != KMType.INVALID_VALUE) { + data[CUSTOM_TAGS] = KMKeyParameters.makeCustomTags(data[TEE_PARAMETERS], scratchPad); + KMKeyParameters.cast(data[TEE_PARAMETERS]).deleteCustomTags(); + } + break; + + default: + break; + } } private static void makeKeyCharacteristics(byte[] scratchPad) { @@ -3811,6 +3800,8 @@ private static void makeKeyCharacteristics(byte[] scratchPad) { KMKeyCharacteristics.cast(data[KEY_CHARACTERISTICS]).setStrongboxEnforced(data[SB_PARAMETERS]); KMKeyCharacteristics.cast(data[KEY_CHARACTERISTICS]).setKeystoreEnforced(data[SW_PARAMETERS]); KMKeyCharacteristics.cast(data[KEY_CHARACTERISTICS]).setTeeEnforced(data[TEE_PARAMETERS]); + // Add custom tags + data[CUSTOM_TAGS] = KMKeyParameters.makeCustomTags(data[KEY_PARAMETERS], scratchPad); } private static void createEncryptedKeyBlob(byte[] scratchPad) { @@ -3832,6 +3823,7 @@ private static void createEncryptedKeyBlob(byte[] scratchPad) { KMArray.cast(data[KEY_BLOB]).add(KEY_BLOB_AUTH_TAG, data[AUTH_TAG]); KMArray.cast(data[KEY_BLOB]).add(KEY_BLOB_NONCE, data[NONCE]); KMArray.cast(data[KEY_BLOB]).add(KEY_BLOB_VERSION_OFFSET, data[KEY_BLOB_VERSION_DATA_OFFSET]); + KMArray.cast(data[KEY_BLOB]).add(KEY_BLOB_CUSTOM_TAGS, data[CUSTOM_TAGS]); short tempChar = KMKeyCharacteristics.instance(); short emptyParam = KMArray.instance((short) 0); @@ -3843,39 +3835,34 @@ private static void createEncryptedKeyBlob(byte[] scratchPad) { } // Encodes KeyCharacteristics at the end of the heap - // and return the length of encoded KeyChars. - private short encodeKeyCharacteristics(short startOffset, short prevReclaimIndex, short keyChars) { - // Remove custom tags from key characteristics - short teeParams = KMKeyCharacteristics.cast(data[KEY_CHARACTERISTICS]).getTeeEnforced(); - if(teeParams != KMType.INVALID_VALUE) { - KMKeyParameters.cast(teeParams).deleteCustomTags(); - } + private void encodeKeyCharacteristics(short keyChars) { byte[] buffer = repository.getHeap(); - short len = encoder.encode(keyChars, buffer, startOffset, prevReclaimIndex, MAX_KEY_CHARS_SIZE); + short prevReclaimIndex = repository.getHeapReclaimIndex(); + short ptr = repository.allocReclaimableMemory(MAX_KEY_CHARS_SIZE); + short len = encoder.encode(keyChars, buffer, ptr, prevReclaimIndex, MAX_KEY_CHARS_SIZE); // shift the encoded KeyCharacteristics data towards the right till the data[CERTIFICATE] offset. - Util.arrayCopyNonAtomic(buffer, startOffset, buffer, (short) (startOffset + (MAX_KEY_CHARS_SIZE - len)), len); - return len; + Util.arrayCopyNonAtomic(buffer, ptr, buffer, (short) (ptr + (MAX_KEY_CHARS_SIZE - len)), len); + // Reclaim the unused memory. + repository.reclaimMemory((short) (MAX_KEY_CHARS_SIZE - len)); } // Encodes KeyBlob at the end of the heap - // and returns the length of the encoded keyblob - private short encodeKeyBlob(short keyBlobPtr) { + private void encodeKeyBlob(short keyBlobPtr) { // allocate reclaimable memory. byte[] buffer = repository.getHeap(); short prevReclaimIndex = repository.getHeapReclaimIndex(); short top = repository.allocReclaimableMemory(MAX_KEYBLOB_SIZE); - short keyBlobLen = encoder.encode(keyBlobPtr, buffer, top, prevReclaimIndex, MAX_KEYBLOB_SIZE); + short keyBlob = encoder.encode(keyBlobPtr, buffer, top, prevReclaimIndex, MAX_KEYBLOB_SIZE); Util.arrayCopyNonAtomic(repository.getHeap(), top, repository.getHeap(), - (short) (top + MAX_KEYBLOB_SIZE - keyBlobLen), keyBlobLen); - short newTop = (short) (top + MAX_KEYBLOB_SIZE - keyBlobLen); - // Encode the KeyBlob array inside a ByteBlob. Get the length of - // the ByteBlob header. - short encodedBytesLength = encoder.getEncodedBytesLength(keyBlobLen); + (short) (top + MAX_KEYBLOB_SIZE - keyBlob), keyBlob); + short newTop = (short) (top + MAX_KEYBLOB_SIZE - keyBlob); + // Encode the KeyBlob array inside a ByteString. Get the length of + // the ByteString header. + short encodedBytesLength = encoder.getEncodedBytesLength(keyBlob); newTop -= encodedBytesLength; - encoder.encodeByteBlobHeader(keyBlobLen, buffer, newTop, encodedBytesLength); + encoder.encodeByteBlobHeader(keyBlob, buffer, newTop, encodedBytesLength); // Reclaim unused memory. repository.reclaimMemory((short) (newTop - top)); - return (short) (keyBlobLen + encodedBytesLength); } private short readKeyBlobVersion(short keyBlob) { @@ -3914,6 +3901,7 @@ private void readKeyBlobParams(short version, short parsedKeyBlob) { if (KMArray.cast(parsedKeyBlob).length() == ASYM_KEY_BLOB_SIZE_V0) { data[PUB_KEY] = KMArray.cast(parsedKeyBlob).get((short) 4); } + data[KEY_BLOB_VERSION_DATA_OFFSET] = KMInteger.uint_8((byte) 0); break; case (short) 1: data[SECRET] = KMArray.cast(parsedKeyBlob).get(KEY_BLOB_SECRET); @@ -3922,6 +3910,8 @@ private void readKeyBlobParams(short version, short parsedKeyBlob) { data[KEY_CHARACTERISTICS] = KMArray.cast(parsedKeyBlob).get(KEY_BLOB_PARAMS); data[KEY_BLOB_VERSION_DATA_OFFSET] = KMArray.cast(parsedKeyBlob).get( KEY_BLOB_VERSION_OFFSET); + data[CUSTOM_TAGS] = KMArray.cast(parsedKeyBlob).get( + KEY_BLOB_CUSTOM_TAGS); data[PUB_KEY] = KMType.INVALID_VALUE; if (KMArray.cast(parsedKeyBlob).length() == ASYM_KEY_BLOB_SIZE_V1) { data[PUB_KEY] = KMArray.cast(parsedKeyBlob).get(KEY_BLOB_PUB_KEY); @@ -4062,7 +4052,7 @@ private static byte getKeyType(short hardwareParams) { } private static void makeAuthData(short version, byte[] scratchPad) { - // For KeyBlob V1: Auth Data includes HW_PARAMETERS, HIDDEN_PARAMETERS, VERSION and PUB_KEY. + // For KeyBlob V1: Auth Data includes HW_PARAMETERS, HIDDEN_PARAMETERS, CUSTOM_TAGS, VERSION and PUB_KEY. // For KeyBlob V0: Auth Data includes HW_PARAMETERS, HIDDEN_PARAMETERS and PUB_KEY. // VERSION is included only for KeyBlobs having version >= 1. // PUB_KEY is included for only ASYMMETRIC KeyBlobs. @@ -4087,14 +4077,15 @@ private static void makeAuthData(short version, byte[] scratchPad) { } break; case (short) 1: - numParams = 3; + numParams = 4; Util.setShort(scratchPad, (short) 0, KMKeyParameters.cast(data[HW_PARAMETERS]).getVals()); Util.setShort(scratchPad, (short) 2, KMKeyParameters.cast(data[HIDDEN_PARAMETERS]).getVals()); - Util.setShort(scratchPad, (short) 4, data[KEY_BLOB_VERSION_DATA_OFFSET]); + Util.setShort(scratchPad, (short) 4, KMKeyParameters.cast(data[CUSTOM_TAGS]).getVals()); + Util.setShort(scratchPad, (short) 6, data[KEY_BLOB_VERSION_DATA_OFFSET]); // For Asymmetric Keys include the PUB_KEY. if (keyType == ASYM_KEY_TYPE) { - numParams = 4; - Util.setShort(scratchPad, (short) 6, data[PUB_KEY]); + numParams = 5; + Util.setShort(scratchPad, (short) 8, data[PUB_KEY]); } break; default: diff --git a/Applet/src/com/android/javacard/keymaster/KMType.java b/Applet/src/com/android/javacard/keymaster/KMType.java index 95806ad3..891de5b6 100644 --- a/Applet/src/com/android/javacard/keymaster/KMType.java +++ b/Applet/src/com/android/javacard/keymaster/KMType.java @@ -364,6 +364,8 @@ public abstract class KMType { public static final short MAX_SUBJECT_DER_LEN = 1095; + protected static short[] keyParamExp; + protected static KMRepository repository; protected static byte[] heap; // Instance table @@ -372,6 +374,7 @@ public abstract class KMType { public static void initialize() { instanceTable = JCSystem.makeTransientShortArray(INSTANCE_TABLE_SIZE, JCSystem.CLEAR_ON_RESET); + keyParamExp = JCSystem.makeTransientShortArray((short) 2, JCSystem.CLEAR_ON_RESET); KMType.repository = KMRepository.instance(); KMType.heap = repository.getHeap(); } @@ -404,5 +407,10 @@ protected static short exp(byte type) { Util.setShort(heap, (short) (ptr + 1), INVALID_VALUE); return ptr; } + + protected static void resetData() { + keyParamExp[0] = KMType.INVALID_VALUE; + keyParamExp[1] = KMType.INVALID_VALUE; + } } From 971e5926fe607857c18a7978ac925a8f4e6589fd Mon Sep 17 00:00:00 2001 From: Subrahmanyaman Date: Fri, 22 Apr 2022 01:22:01 +0000 Subject: [PATCH 2/8] Custom tags moved to KeyBlob from KeyChars --- .../javacard/keymaster/KMAndroidSEApplet.java | 1 - .../javacard/keymaster/KMKeyParameters.java | 123 +++++------------- .../javacard/keymaster/KMKeymasterApplet.java | 98 +++++++++++--- .../android/javacard/keymaster/KMType.java | 11 +- 4 files changed, 113 insertions(+), 120 deletions(-) diff --git a/Applet/AndroidSEProvider/src/com/android/javacard/keymaster/KMAndroidSEApplet.java b/Applet/AndroidSEProvider/src/com/android/javacard/keymaster/KMAndroidSEApplet.java index 45822390..1987d576 100644 --- a/Applet/AndroidSEProvider/src/com/android/javacard/keymaster/KMAndroidSEApplet.java +++ b/Applet/AndroidSEProvider/src/com/android/javacard/keymaster/KMAndroidSEApplet.java @@ -97,7 +97,6 @@ public static void install(byte[] bArray, short bOffset, byte bLength) { @Override public void process(APDU apdu) { try { - resetData(); // If this is select applet apdu which is selecting this applet then return if (apdu.isISOInterindustryCLA()) { if (selectingApplet()) { diff --git a/Applet/src/com/android/javacard/keymaster/KMKeyParameters.java b/Applet/src/com/android/javacard/keymaster/KMKeyParameters.java index d1ea64ba..89805dc7 100644 --- a/Applet/src/com/android/javacard/keymaster/KMKeyParameters.java +++ b/Applet/src/com/android/javacard/keymaster/KMKeyParameters.java @@ -46,43 +46,37 @@ private static KMKeyParameters proto(short ptr) { } public static short exp() { - if (KMType.keyParamExp[0] == KMType.INVALID_VALUE) { - short arrPtr = KMArray.instance((short) 11); - KMArray arr = KMArray.cast(arrPtr); - arr.add((short) 0, KMEnum.instance(KMType.RULE, KMType.FAIL_ON_INVALID_TAGS)); - arr.add((short) 1, KMIntegerTag.exp(UINT_TAG)); - arr.add((short) 2, KMIntegerArrayTag.exp(UINT_ARRAY_TAG)); - arr.add((short) 3, KMIntegerTag.exp(ULONG_TAG)); - arr.add((short) 4, KMIntegerTag.exp(DATE_TAG)); - arr.add((short) 5, KMIntegerArrayTag.exp(ULONG_ARRAY_TAG)); - arr.add((short) 6, KMEnumTag.exp()); - arr.add((short) 7, KMEnumArrayTag.exp()); - arr.add((short) 8, KMByteTag.exp()); - arr.add((short) 9, KMBoolTag.exp()); - arr.add((short) 10, KMBignumTag.exp()); - KMType.keyParamExp[0] = instance(arrPtr); - } - return KMType.keyParamExp[0]; + short arrPtr = KMArray.instance((short) 11); + KMArray arr = KMArray.cast(arrPtr); + arr.add((short) 0, KMEnum.instance(KMType.RULE, KMType.FAIL_ON_INVALID_TAGS)); + arr.add((short) 1, KMIntegerTag.exp(UINT_TAG)); + arr.add((short) 2, KMIntegerArrayTag.exp(UINT_ARRAY_TAG)); + arr.add((short) 3, KMIntegerTag.exp(ULONG_TAG)); + arr.add((short) 4, KMIntegerTag.exp(DATE_TAG)); + arr.add((short) 5, KMIntegerArrayTag.exp(ULONG_ARRAY_TAG)); + arr.add((short) 6, KMEnumTag.exp()); + arr.add((short) 7, KMEnumArrayTag.exp()); + arr.add((short) 8, KMByteTag.exp()); + arr.add((short) 9, KMBoolTag.exp()); + arr.add((short) 10, KMBignumTag.exp()); + return instance(arrPtr); } public static short expAny() { - if (KMType.keyParamExp[1] == KMType.INVALID_VALUE) { - short arrPtr = KMArray.instance((short) 11); - KMArray arr = KMArray.cast(arrPtr); - arr.add((short) 0, KMEnum.instance(KMType.RULE, KMType.IGNORE_INVALID_TAGS)); - arr.add((short) 1, KMIntegerTag.exp(UINT_TAG)); - arr.add((short) 2, KMIntegerArrayTag.exp(UINT_ARRAY_TAG)); - arr.add((short) 3, KMIntegerTag.exp(ULONG_TAG)); - arr.add((short) 4, KMIntegerTag.exp(DATE_TAG)); - arr.add((short) 5, KMIntegerArrayTag.exp(ULONG_ARRAY_TAG)); - arr.add((short) 6, KMEnumTag.exp()); - arr.add((short) 7, KMEnumArrayTag.exp()); - arr.add((short) 8, KMByteTag.exp()); - arr.add((short) 9, KMBoolTag.exp()); - arr.add((short) 10, KMBignumTag.exp()); - KMType.keyParamExp[1] = instance(arrPtr); - } - return KMType.keyParamExp[1]; + short arrPtr = KMArray.instance((short) 11); + KMArray arr = KMArray.cast(arrPtr); + arr.add((short) 0, KMEnum.instance(KMType.RULE, KMType.IGNORE_INVALID_TAGS)); + arr.add((short) 1, KMIntegerTag.exp(UINT_TAG)); + arr.add((short) 2, KMIntegerArrayTag.exp(UINT_ARRAY_TAG)); + arr.add((short) 3, KMIntegerTag.exp(ULONG_TAG)); + arr.add((short) 4, KMIntegerTag.exp(DATE_TAG)); + arr.add((short) 5, KMIntegerArrayTag.exp(ULONG_ARRAY_TAG)); + arr.add((short) 6, KMEnumTag.exp()); + arr.add((short) 7, KMEnumArrayTag.exp()); + arr.add((short) 8, KMByteTag.exp()); + arr.add((short) 9, KMBoolTag.exp()); + arr.add((short) 10, KMBignumTag.exp()); + return instance(arrPtr); } public static short instance(short vals) { @@ -241,64 +235,6 @@ public static short makeSbEnforced(short keyParamsPtr, byte origin, return createKeyParameters(scratchPad, (short) (arrInd / 2)); } - public static short makeSbEnforced(short keyParamsPtr, byte[] scratchPad) { - final short[] hwEnforcedTagArr = { - // HW Enforced - KMType.ENUM_TAG, KMType.ORIGIN, - KMType.UINT_TAG, KMType.OS_VERSION, - KMType.UINT_TAG, KMType.OS_PATCH_LEVEL, - KMType.UINT_TAG, KMType.VENDOR_PATCH_LEVEL, - KMType.UINT_TAG, KMType.BOOT_PATCH_LEVEL, - KMType.ENUM_ARRAY_TAG, KMType.PURPOSE, - KMType.ENUM_TAG, KMType.ALGORITHM, - KMType.UINT_TAG, KMType.KEYSIZE, - KMType.ULONG_TAG, KMType.RSA_PUBLIC_EXPONENT, - KMType.ENUM_TAG, KMType.BLOB_USAGE_REQ, - KMType.ENUM_ARRAY_TAG, KMType.DIGEST, - KMType.ENUM_ARRAY_TAG, KMType.PADDING, - KMType.ENUM_ARRAY_TAG, KMType.BLOCK_MODE, - KMType.ENUM_ARRAY_TAG, KMType.RSA_OAEP_MGF_DIGEST, - KMType.BOOL_TAG, KMType.NO_AUTH_REQUIRED, - KMType.BOOL_TAG, KMType.CALLER_NONCE, - KMType.UINT_TAG, KMType.MIN_MAC_LENGTH, - KMType.ENUM_TAG, KMType.ECCURVE, - KMType.BOOL_TAG, KMType.INCLUDE_UNIQUE_ID, - KMType.BOOL_TAG, KMType.ROLLBACK_RESISTANCE, - KMType.BOOL_TAG, KMType.UNLOCKED_DEVICE_REQUIRED, - KMType.BOOL_TAG, KMType.EARLY_BOOT_ONLY, - KMType.BOOL_TAG, KMType.BOOTLOADER_ONLY, - KMType.BOOL_TAG, KMType.TRUSTED_CONFIRMATION_REQUIRED, - }; - byte index = 0; - short tagInd; - short arrInd = 0; - short tagPtr; - short tagKey; - short tagType; - short arrPtr = KMKeyParameters.cast(keyParamsPtr).getVals(); - short len = KMArray.cast(arrPtr).length(); - while (index < len) { - tagInd = 0; - tagPtr = KMArray.cast(arrPtr).get(index); - tagKey = KMTag.getKey(tagPtr); - tagType = KMTag.getTagType(tagPtr); - if (!isValidTag(tagType, tagKey)) { - KMException.throwIt(KMError.INVALID_KEY_BLOB); - } - while (tagInd < (short) hwEnforcedTagArr.length) { - if ((hwEnforcedTagArr[tagInd] == tagType) - && (hwEnforcedTagArr[(short) (tagInd + 1)] == tagKey)) { - Util.setShort(scratchPad, arrInd, tagPtr); - arrInd += 2; - break; - } - tagInd += 2; - } - index++; - } - return createKeyParameters(scratchPad, (short) (arrInd / 2)); - } - public static short makeHwEnforced(short sb, short tee){ short len = KMKeyParameters.cast(sb).length(); len += KMKeyParameters.cast(tee).length(); @@ -334,7 +270,8 @@ public static short makeKeystoreEnforced(short keyParamsPtr, byte[] scratchPad) KMType.UINT_TAG, KMType.USERID, KMType.DATE_TAG, KMType.CREATION_DATETIME, KMType.UINT_TAG, KMType.USAGE_COUNT_LIMIT, - KMType.BOOL_TAG, KMType.ALLOW_WHILE_ON_BODY + KMType.BOOL_TAG, KMType.ALLOW_WHILE_ON_BODY, + KMType.UINT_TAG, KMType.MAX_BOOT_LEVEL, }; byte index = 0; short tagInd; diff --git a/Applet/src/com/android/javacard/keymaster/KMKeymasterApplet.java b/Applet/src/com/android/javacard/keymaster/KMKeymasterApplet.java index fcb6d2ae..62436edf 100644 --- a/Applet/src/com/android/javacard/keymaster/KMKeymasterApplet.java +++ b/Applet/src/com/android/javacard/keymaster/KMKeymasterApplet.java @@ -217,10 +217,12 @@ public class KMKeymasterApplet extends Applet implements AppletEvent, ExtendedLe // the KeyBlobs if it is changed. please increment this // version number whenever you change anything related to // KeyBlob (structure, encryption algorithm etc). - public static final short KEYBLOB_CURRENT_VERSION = 1; + public static final short KEYBLOB_CURRENT_VERSION = 2; // KeyBlob array size constants. - public static final byte SYM_KEY_BLOB_SIZE_V1 = 6; - public static final byte ASYM_KEY_BLOB_SIZE_V1 = 7; + public static final byte SYM_KEY_BLOB_SIZE_V2 = 6; + public static final byte ASYM_KEY_BLOB_SIZE_V2 = 7; + public static final byte SYM_KEY_BLOB_SIZE_V1 = 5; + public static final byte ASYM_KEY_BLOB_SIZE_V1 = 6; public static final byte SYM_KEY_BLOB_SIZE_V0 = 4; public static final byte ASYM_KEY_BLOB_SIZE_V0 = 5; // Key type constants @@ -399,6 +401,7 @@ protected short mapCryptoErrorToKMError(short reason) { @Override public void process(APDU apdu) { try { + resetData(); repository.onProcess(); // If this is select applet apdu which is selecting this applet then return if (apdu.isISOInterindustryCLA()) { @@ -595,7 +598,6 @@ protected void resetData() { tmpVariables[index] = KMType.INVALID_VALUE; index++; } - KMType.resetData(); } /** @@ -814,6 +816,15 @@ private short createKeyBlobExp(short version) { break; case (short) 1: keyBlob = KMArray.instance(ASYM_KEY_BLOB_SIZE_V1); + KMArray.cast(keyBlob).add((short) 0, KMInteger.exp()); + KMArray.cast(keyBlob).add((short) 1, byteBlobExp); + KMArray.cast(keyBlob).add((short) 2, byteBlobExp); + KMArray.cast(keyBlob).add((short) 3, byteBlobExp); + KMArray.cast(keyBlob).add((short) 4, keyChar); + KMArray.cast(keyBlob).add((short) 5, byteBlobExp); + break; + case (short) 2: + keyBlob = KMArray.instance(ASYM_KEY_BLOB_SIZE_V2); KMArray.cast(keyBlob).add(KMKeymasterApplet.KEY_BLOB_VERSION_OFFSET, KMInteger.exp()); KMArray.cast(keyBlob).add(KMKeymasterApplet.KEY_BLOB_SECRET, byteBlobExp); KMArray.cast(keyBlob).add(KMKeymasterApplet.KEY_BLOB_AUTH_TAG, byteBlobExp); @@ -832,10 +843,10 @@ private static short createKeyBlobInstance(byte keyType) { short arrayLen = 0; switch (keyType) { case ASYM_KEY_TYPE: - arrayLen = ASYM_KEY_BLOB_SIZE_V1; + arrayLen = ASYM_KEY_BLOB_SIZE_V2; break; case SYM_KEY_TYPE: - arrayLen = SYM_KEY_BLOB_SIZE_V1; + arrayLen = SYM_KEY_BLOB_SIZE_V2; break; default: KMException.throwIt(KMError.UNSUPPORTED_ALGORITHM); @@ -1056,11 +1067,11 @@ private void processUpgradeKeyCmd(APDU apdu) { byte keyType = getKeyType(data[HW_PARAMETERS]); switch (keyType) { case ASYM_KEY_TYPE: - data[KEY_BLOB] = KMArray.instance(ASYM_KEY_BLOB_SIZE_V1); + data[KEY_BLOB] = KMArray.instance(ASYM_KEY_BLOB_SIZE_V2); KMArray.cast(data[KEY_BLOB]).add(KEY_BLOB_PUB_KEY, data[PUB_KEY]); break; case SYM_KEY_TYPE: - data[KEY_BLOB] = KMArray.instance(SYM_KEY_BLOB_SIZE_V1); + data[KEY_BLOB] = KMArray.instance(SYM_KEY_BLOB_SIZE_V2); break; default: KMException.throwIt(KMError.UNSUPPORTED_ALGORITHM); @@ -2833,7 +2844,7 @@ private void authorizeUserSecureIdAuthTimeout(KMOperationState op, byte[] scratc } authTimeoutTagPtr = - KMKeyParameters.findTag(KMType.ULONG_TAG, KMType.AUTH_TIMEOUT_MILLIS, data[HW_PARAMETERS]); + KMKeyParameters.findTag(KMType.ULONG_TAG, KMType.AUTH_TIMEOUT_MILLIS, data[CUSTOM_TAGS]); if (authTimeoutTagPtr == KMType.INVALID_VALUE) { KMException.throwIt(KMError.INVALID_KEY_BLOB); } @@ -3775,8 +3786,8 @@ private static void upgradeKeyBlobKeyCharacteristics(short hwParams, byte[] scra short version = KMInteger.cast(data[KEY_BLOB_VERSION_DATA_OFFSET]).getShort(); switch (version) { case 0: + case 1: if (data[TEE_PARAMETERS] != KMType.INVALID_VALUE) { - data[CUSTOM_TAGS] = KMKeyParameters.makeCustomTags(data[TEE_PARAMETERS], scratchPad); KMKeyParameters.cast(data[TEE_PARAMETERS]).deleteCustomTags(); } break; @@ -3800,8 +3811,6 @@ private static void makeKeyCharacteristics(byte[] scratchPad) { KMKeyCharacteristics.cast(data[KEY_CHARACTERISTICS]).setStrongboxEnforced(data[SB_PARAMETERS]); KMKeyCharacteristics.cast(data[KEY_CHARACTERISTICS]).setKeystoreEnforced(data[SW_PARAMETERS]); KMKeyCharacteristics.cast(data[KEY_CHARACTERISTICS]).setTeeEnforced(data[TEE_PARAMETERS]); - // Add custom tags - data[CUSTOM_TAGS] = KMKeyParameters.makeCustomTags(data[KEY_PARAMETERS], scratchPad); } private static void createEncryptedKeyBlob(byte[] scratchPad) { @@ -3814,6 +3823,8 @@ private static void createEncryptedKeyBlob(byte[] scratchPad) { data[HIDDEN_PARAMETERS] = KMKeyParameters.makeHidden(data[KEY_PARAMETERS], data[ROT], scratchPad); data[KEY_BLOB_VERSION_DATA_OFFSET] = KMInteger.uint_16(KEYBLOB_CURRENT_VERSION); + // create custom tags + data[CUSTOM_TAGS] = KMKeyParameters.makeCustomTags(data[HW_PARAMETERS], scratchPad); // make authorization data makeAuthData(KEYBLOB_CURRENT_VERSION, scratchPad); // encrypt the secret and cryptographically attach that to authorization data @@ -3901,9 +3912,24 @@ private void readKeyBlobParams(short version, short parsedKeyBlob) { if (KMArray.cast(parsedKeyBlob).length() == ASYM_KEY_BLOB_SIZE_V0) { data[PUB_KEY] = KMArray.cast(parsedKeyBlob).get((short) 4); } + // Set the data[KEY_BLOB_VERSION_DATA_OFFSET] with integer value of 0 so + // that it will used at later point of time. data[KEY_BLOB_VERSION_DATA_OFFSET] = KMInteger.uint_8((byte) 0); break; case (short) 1: + data[SECRET] = KMArray.cast(parsedKeyBlob).get((short) 0); + data[NONCE]= KMArray.cast(parsedKeyBlob).get((short) 1); + data[AUTH_TAG] = KMArray.cast(parsedKeyBlob).get((short) 2); + data[KEY_CHARACTERISTICS] = KMArray.cast(parsedKeyBlob).get((short) 3); + data[KEY_BLOB_VERSION_DATA_OFFSET] = KMArray.cast(parsedKeyBlob).get( + (short) 4); + data[CUSTOM_TAGS] = KMType.INVALID_VALUE; + data[PUB_KEY] = KMType.INVALID_VALUE; + if (KMArray.cast(parsedKeyBlob).length() == ASYM_KEY_BLOB_SIZE_V1) { + data[PUB_KEY] = KMArray.cast(parsedKeyBlob).get((short) 5); + } + break; + case (short) 2: data[SECRET] = KMArray.cast(parsedKeyBlob).get(KEY_BLOB_SECRET); data[NONCE]= KMArray.cast(parsedKeyBlob).get(KEY_BLOB_NONCE); data[AUTH_TAG] = KMArray.cast(parsedKeyBlob).get(KEY_BLOB_AUTH_TAG); @@ -3913,7 +3939,7 @@ private void readKeyBlobParams(short version, short parsedKeyBlob) { data[CUSTOM_TAGS] = KMArray.cast(parsedKeyBlob).get( KEY_BLOB_CUSTOM_TAGS); data[PUB_KEY] = KMType.INVALID_VALUE; - if (KMArray.cast(parsedKeyBlob).length() == ASYM_KEY_BLOB_SIZE_V1) { + if (KMArray.cast(parsedKeyBlob).length() == ASYM_KEY_BLOB_SIZE_V2) { data[PUB_KEY] = KMArray.cast(parsedKeyBlob).get(KEY_BLOB_PUB_KEY); } break; @@ -3928,7 +3954,20 @@ private void decodeKeyBlob(short version, short keyBlob) { KMByteBlob.cast(keyBlob).getBuffer(), KMByteBlob.cast(keyBlob).getStartOff(), KMByteBlob.cast(keyBlob).length()); - short minArraySize = (version > 0) ? SYM_KEY_BLOB_SIZE_V1 : (short) 4; + short minArraySize = 0; + switch(version) { + case 0: + minArraySize = (short) 4; + break; + case 1: + minArraySize = (short) 5; + break; + case 2: + minArraySize = SYM_KEY_BLOB_SIZE_V2; + break; + default: + KMException.throwIt(KMError.INVALID_KEY_BLOB); + }; // KeyBlob size should not be less than the minimum KeyBlob size. if (KMArray.cast(parsedBlob).length() < minArraySize) { KMException.throwIt(KMError.INVALID_KEY_BLOB); @@ -3947,7 +3986,20 @@ private void processDecryptSecret(short version, short appId, short appData, byt makeAuthData(version, scratchPad); // Decrypt Secret and verify auth tag decryptSecret(scratchPad); - short keyBlobSecretOff = (version > 0) ? KEY_BLOB_SECRET : (short) 0; + short keyBlobSecretOff = 0; + switch(version) { + case 0: + keyBlobSecretOff = (short) 0; + break; + case 1: + keyBlobSecretOff = (short) 1; + break; + case 2: + keyBlobSecretOff = KEY_BLOB_SECRET; + break; + default: + KMException.throwIt(KMError.INVALID_KEY_BLOB); + }; KMArray.cast(data[KEY_BLOB]).add(keyBlobSecretOff, data[SECRET]); } @@ -4052,13 +4104,14 @@ private static byte getKeyType(short hardwareParams) { } private static void makeAuthData(short version, byte[] scratchPad) { - // For KeyBlob V1: Auth Data includes HW_PARAMETERS, HIDDEN_PARAMETERS, CUSTOM_TAGS, VERSION and PUB_KEY. + // For KeyBlob V2: Auth Data includes HW_PARAMETERS, HIDDEN_PARAMETERS, CUSTOM_TAGS, VERSION and PUB_KEY. + // For KeyBlob V1: Auth Data includes HW_PARAMETERS, HIDDEN_PARAMETERS, VERSION and PUB_KEY. // For KeyBlob V0: Auth Data includes HW_PARAMETERS, HIDDEN_PARAMETERS and PUB_KEY. // VERSION is included only for KeyBlobs having version >= 1. // PUB_KEY is included for only ASYMMETRIC KeyBlobs. short index = 0; short numParams = 0; - Util.arrayFillNonAtomic(scratchPad, (short) 0, (short) 8, (byte) 0); + Util.arrayFillNonAtomic(scratchPad, (short) 0, (short) 10, (byte) 0); byte keyType = getKeyType(data[HW_PARAMETERS]); // Copy the relevant parameters in the scratchPad in the order // 1. HW_PARAMETERS @@ -4077,6 +4130,17 @@ private static void makeAuthData(short version, byte[] scratchPad) { } break; case (short) 1: + numParams = 3; + Util.setShort(scratchPad, (short) 0, KMKeyParameters.cast(data[HW_PARAMETERS]).getVals()); + Util.setShort(scratchPad, (short) 2, KMKeyParameters.cast(data[HIDDEN_PARAMETERS]).getVals()); + Util.setShort(scratchPad, (short) 4, data[KEY_BLOB_VERSION_DATA_OFFSET]); + // For Asymmetric Keys include the PUB_KEY. + if (keyType == ASYM_KEY_TYPE) { + numParams = 4; + Util.setShort(scratchPad, (short) 6, data[PUB_KEY]); + } + break; + case (short) 2: numParams = 4; Util.setShort(scratchPad, (short) 0, KMKeyParameters.cast(data[HW_PARAMETERS]).getVals()); Util.setShort(scratchPad, (short) 2, KMKeyParameters.cast(data[HIDDEN_PARAMETERS]).getVals()); diff --git a/Applet/src/com/android/javacard/keymaster/KMType.java b/Applet/src/com/android/javacard/keymaster/KMType.java index 891de5b6..26eda3d3 100644 --- a/Applet/src/com/android/javacard/keymaster/KMType.java +++ b/Applet/src/com/android/javacard/keymaster/KMType.java @@ -247,6 +247,8 @@ public abstract class KMType { public static final short NO_AUTH_REQUIRED = (short) 0x01F7; // Allow While On Body public static final short ALLOW_WHILE_ON_BODY = (short) 0x01FA; + // Max Boot Level + public static final short MAX_BOOT_LEVEL = (short) 0x03F2; // Trusted User Presence Required public static final short TRUSTED_USER_PRESENCE_REQUIRED = (short) 0x01FB; // Trusted Confirmation Required @@ -364,8 +366,6 @@ public abstract class KMType { public static final short MAX_SUBJECT_DER_LEN = 1095; - protected static short[] keyParamExp; - protected static KMRepository repository; protected static byte[] heap; // Instance table @@ -374,7 +374,6 @@ public abstract class KMType { public static void initialize() { instanceTable = JCSystem.makeTransientShortArray(INSTANCE_TABLE_SIZE, JCSystem.CLEAR_ON_RESET); - keyParamExp = JCSystem.makeTransientShortArray((short) 2, JCSystem.CLEAR_ON_RESET); KMType.repository = KMRepository.instance(); KMType.heap = repository.getHeap(); } @@ -407,10 +406,4 @@ protected static short exp(byte type) { Util.setShort(heap, (short) (ptr + 1), INVALID_VALUE); return ptr; } - - protected static void resetData() { - keyParamExp[0] = KMType.INVALID_VALUE; - keyParamExp[1] = KMType.INVALID_VALUE; - } - } From 19281fba12b10fb68556d3bc693821ecfbc93b80 Mon Sep 17 00:00:00 2001 From: Subrahmanyaman Date: Fri, 22 Apr 2022 01:26:29 +0000 Subject: [PATCH 3/8] Updated KMJCardSimulator hmacVerify --- .../com/android/javacard/seprovider/KMJCardSimulator.java | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) diff --git a/Applet/JCardSimProviderLib/src/com/android/javacard/seprovider/KMJCardSimulator.java b/Applet/JCardSimProviderLib/src/com/android/javacard/seprovider/KMJCardSimulator.java index ee5a8d4d..937fb349 100644 --- a/Applet/JCardSimProviderLib/src/com/android/javacard/seprovider/KMJCardSimulator.java +++ b/Applet/JCardSimProviderLib/src/com/android/javacard/seprovider/KMJCardSimulator.java @@ -621,11 +621,9 @@ public short hmacSign(Object key, byte[] data, short dataStart, short dataLength @Override public boolean hmacVerify(KMComputedHmacKey key, byte[] data, short dataStart, short dataLength, byte[] mac, short macStart, short macLength) { - //KMHmacKey hmacKey = (KMHmacKey) key; - byte[] keyBuf = new byte[32]; - HMACKey hmacKey = createHMACKey(keyBuf, (short) 0, (short) keyBuf.length); - hmacSignature.init(hmacKey, Signature.MODE_VERIFY); - return hmacSignature.verify(data, dataStart, dataLength, mac, macStart, macLength); + KMHmacKey hmacKey = (KMHmacKey) key; + hmacSignature.init(hmacKey.getKey(), Signature.MODE_VERIFY); + return hmacSignature.verify(data, dataStart, dataLength, mac, macStart, macLength); } @Override From d0aab6af351849c4d121fe3bf39d1520a67fd9f2 Mon Sep 17 00:00:00 2001 From: Subrahmanyaman Date: Fri, 22 Apr 2022 01:34:05 +0000 Subject: [PATCH 4/8] Updated upgradeKeyChars function --- .../javacard/keymaster/KMKeymasterApplet.java | 14 -------------- 1 file changed, 14 deletions(-) diff --git a/Applet/src/com/android/javacard/keymaster/KMKeymasterApplet.java b/Applet/src/com/android/javacard/keymaster/KMKeymasterApplet.java index 62436edf..bd269dc1 100644 --- a/Applet/src/com/android/javacard/keymaster/KMKeymasterApplet.java +++ b/Applet/src/com/android/javacard/keymaster/KMKeymasterApplet.java @@ -3781,20 +3781,6 @@ private static void upgradeKeyBlobKeyCharacteristics(short hwParams, byte[] scra hwParams, (byte) data[ORIGIN], osVersion, osPatch, vendorPatch, bootPatch, scratchPad); data[TEE_PARAMETERS] = KMKeyParameters.makeTeeEnforced(hwParams, scratchPad); data[HW_PARAMETERS] = KMKeyParameters.makeHwEnforced(data[SB_PARAMETERS], data[TEE_PARAMETERS]); - - // Create custom tags from tee params and remove the custom tags from old Keyblob keychars. - short version = KMInteger.cast(data[KEY_BLOB_VERSION_DATA_OFFSET]).getShort(); - switch (version) { - case 0: - case 1: - if (data[TEE_PARAMETERS] != KMType.INVALID_VALUE) { - KMKeyParameters.cast(data[TEE_PARAMETERS]).deleteCustomTags(); - } - break; - - default: - break; - } } private static void makeKeyCharacteristics(byte[] scratchPad) { From a94b62628d259ec0a9cbf5b25880715bf2e78eb9 Mon Sep 17 00:00:00 2001 From: Subrahmanyaman Date: Fri, 22 Apr 2022 06:24:02 +0000 Subject: [PATCH 5/8] key pool implementation --- .../seprovider/KMAndroidSEProvider.java | 171 ++---------- .../javacard/seprovider/KMKeyObject.java | 19 ++ .../javacard/seprovider/KMOperation.java | 2 + .../javacard/seprovider/KMOperationImpl.java | 67 +++-- .../javacard/seprovider/KMPoolManager.java | 264 +++++++++++++++++- .../javacard/seprovider/KMSEProvider.java | 15 +- 6 files changed, 349 insertions(+), 189 deletions(-) create mode 100644 Applet/AndroidSEProviderLib/src/com/android/javacard/seprovider/KMKeyObject.java diff --git a/Applet/AndroidSEProviderLib/src/com/android/javacard/seprovider/KMAndroidSEProvider.java b/Applet/AndroidSEProviderLib/src/com/android/javacard/seprovider/KMAndroidSEProvider.java index ddaece5c..23e80b29 100644 --- a/Applet/AndroidSEProviderLib/src/com/android/javacard/seprovider/KMAndroidSEProvider.java +++ b/Applet/AndroidSEProviderLib/src/com/android/javacard/seprovider/KMAndroidSEProvider.java @@ -41,20 +41,6 @@ public class KMAndroidSEProvider implements KMSEProvider { - // static final variables - // -------------------------------------------------------------- - // P-256 Curve Parameters - static byte[] secp256r1_P; - static byte[] secp256r1_A; - - static byte[] secp256r1_B; - static byte[] secp256r1_S; - - // Uncompressed form - static byte[] secp256r1_UCG; - static byte[] secp256r1_N; - static final short secp256r1_H = 1; - // -------------------------------------------------------------- public static final short AES_GCM_TAG_LENGTH = 16; public static final short AES_GCM_NONCE_LENGTH = 12; public static final byte KEYSIZE_128_OFFSET = 0x00; @@ -102,7 +88,6 @@ public static KMAndroidSEProvider getInstance() { } public KMAndroidSEProvider() { - initStatics(); // Re-usable AES,DES and HMAC keys in persisted memory. aesKeys = new AESKey[2]; aesKeys[KEYSIZE_128_OFFSET] = (AESKey) KeyBuilder.buildKey( @@ -116,8 +101,8 @@ public KMAndroidSEProvider() { rsaKeyPair = new KeyPair(KeyPair.ALG_RSA, KeyBuilder.LENGTH_RSA_2048); ecKeyPair = new KeyPair(KeyPair.ALG_EC_FP, KeyBuilder.LENGTH_EC_FP_256); keyAgreement = KeyAgreement.getInstance(KeyAgreement.ALG_EC_SVDP_DH_PLAIN, false); - initECKey(ecKeyPair); poolMgr = KMPoolManager.getInstance(); + poolMgr.initECKey(ecKeyPair); //RsaOAEP Decipher rsaOaepDecipher = new KMRsaOAEPEncoding(KMRsaOAEPEncoding.ALG_RSA_PKCS1_OAEP_SHA256_MGF1_SHA1); @@ -136,95 +121,10 @@ public KMAndroidSEProvider() { resetFlag[0] = (byte) POWER_RESET_FALSE; } - public static void initStatics() { - secp256r1_P = new byte[]{(byte) 0xFF, (byte) 0xFF, (byte) 0xFF, (byte) 0xFF, (byte) 0x00, - (byte) 0x00, - (byte) 0x00, (byte) 0x01, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, - (byte) 0x00, - (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0xFF, - (byte) 0xFF, - (byte) 0xFF, (byte) 0xFF, (byte) 0xFF, (byte) 0xFF, (byte) 0xFF, (byte) 0xFF, (byte) 0xFF, - (byte) 0xFF, - (byte) 0xFF, (byte) 0xFF}; - - secp256r1_A = new byte[]{(byte) 0xFF, (byte) 0xFF, (byte) 0xFF, (byte) 0xFF, (byte) 0x00, - (byte) 0x00, - (byte) 0x00, (byte) 0x01, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, - (byte) 0x00, - (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0xFF, - (byte) 0xFF, - (byte) 0xFF, (byte) 0xFF, (byte) 0xFF, (byte) 0xFF, (byte) 0xFF, (byte) 0xFF, (byte) 0xFF, - (byte) 0xFF, - (byte) 0xFF, (byte) 0xFC}; - - secp256r1_B = new byte[]{(byte) 0x5A, (byte) 0xC6, (byte) 0x35, (byte) 0xD8, (byte) 0xAA, - (byte) 0x3A, - (byte) 0x93, (byte) 0xE7, (byte) 0xB3, (byte) 0xEB, (byte) 0xBD, (byte) 0x55, (byte) 0x76, - (byte) 0x98, - (byte) 0x86, (byte) 0xBC, (byte) 0x65, (byte) 0x1D, (byte) 0x06, (byte) 0xB0, (byte) 0xCC, - (byte) 0x53, - (byte) 0xB0, (byte) 0xF6, (byte) 0x3B, (byte) 0xCE, (byte) 0x3C, (byte) 0x3E, (byte) 0x27, - (byte) 0xD2, - (byte) 0x60, (byte) 0x4B}; - - secp256r1_S = new byte[]{(byte) 0xC4, (byte) 0x9D, (byte) 0x36, (byte) 0x08, (byte) 0x86, - (byte) 0xE7, - (byte) 0x04, (byte) 0x93, (byte) 0x6A, (byte) 0x66, (byte) 0x78, (byte) 0xE1, (byte) 0x13, - (byte) 0x9D, - (byte) 0x26, (byte) 0xB7, (byte) 0x81, (byte) 0x9F, (byte) 0x7E, (byte) 0x90}; - - // Uncompressed form - secp256r1_UCG = new byte[]{(byte) 0x04, (byte) 0x6B, (byte) 0x17, (byte) 0xD1, (byte) 0xF2, - (byte) 0xE1, - (byte) 0x2C, (byte) 0x42, (byte) 0x47, (byte) 0xF8, (byte) 0xBC, (byte) 0xE6, (byte) 0xE5, - (byte) 0x63, - (byte) 0xA4, (byte) 0x40, (byte) 0xF2, (byte) 0x77, (byte) 0x03, (byte) 0x7D, (byte) 0x81, - (byte) 0x2D, - (byte) 0xEB, (byte) 0x33, (byte) 0xA0, (byte) 0xF4, (byte) 0xA1, (byte) 0x39, (byte) 0x45, - (byte) 0xD8, - (byte) 0x98, (byte) 0xC2, (byte) 0x96, (byte) 0x4F, (byte) 0xE3, (byte) 0x42, (byte) 0xE2, - (byte) 0xFE, - (byte) 0x1A, (byte) 0x7F, (byte) 0x9B, (byte) 0x8E, (byte) 0xE7, (byte) 0xEB, (byte) 0x4A, - (byte) 0x7C, - (byte) 0x0F, (byte) 0x9E, (byte) 0x16, (byte) 0x2B, (byte) 0xCE, (byte) 0x33, (byte) 0x57, - (byte) 0x6B, - (byte) 0x31, (byte) 0x5E, (byte) 0xCE, (byte) 0xCB, (byte) 0xB6, (byte) 0x40, (byte) 0x68, - (byte) 0x37, - (byte) 0xBF, (byte) 0x51, (byte) 0xF5}; - - secp256r1_N = new byte[]{(byte) 0xFF, (byte) 0xFF, (byte) 0xFF, (byte) 0xFF, (byte) 0x00, - (byte) 0x00, - (byte) 0x00, (byte) 0x00, (byte) 0xFF, (byte) 0xFF, (byte) 0xFF, (byte) 0xFF, (byte) 0xFF, - (byte) 0xFF, - (byte) 0xFF, (byte) 0xFF, (byte) 0xBC, (byte) 0xE6, (byte) 0xFA, (byte) 0xAD, (byte) 0xA7, - (byte) 0x17, - (byte) 0x9E, (byte) 0x84, (byte) 0xF3, (byte) 0xB9, (byte) 0xCA, (byte) 0xC2, (byte) 0xFC, - (byte) 0x63, - (byte) 0x25, (byte) 0x51}; - } - public void clean() { Util.arrayFillNonAtomic(tmpArray, (short) 0, (short) 256, (byte) 0); } - private void initECKey(KeyPair ecKeyPair) { - ECPrivateKey privKey = (ECPrivateKey) ecKeyPair.getPrivate(); - ECPublicKey pubkey = (ECPublicKey) ecKeyPair.getPublic(); - pubkey.setFieldFP(secp256r1_P, (short) 0, (short) secp256r1_P.length); - pubkey.setA(secp256r1_A, (short) 0, (short) secp256r1_A.length); - pubkey.setB(secp256r1_B, (short) 0, (short) secp256r1_B.length); - pubkey.setG(secp256r1_UCG, (short) 0, (short) secp256r1_UCG.length); - pubkey.setK(secp256r1_H); - pubkey.setR(secp256r1_N, (short) 0, (short) secp256r1_N.length); - - privKey.setFieldFP(secp256r1_P, (short) 0, (short) secp256r1_P.length); - privKey.setA(secp256r1_A, (short) 0, (short) secp256r1_A.length); - privKey.setB(secp256r1_B, (short) 0, (short) secp256r1_B.length); - privKey.setG(secp256r1_UCG, (short) 0, (short) secp256r1_UCG.length); - privKey.setK(secp256r1_H); - privKey.setR(secp256r1_N, (short) 0, (short) secp256r1_N.length); - } - public AESKey createAESKey(short keysize) { try { newRandomNumber(tmpArray, (short) 0, (short) (keysize / 8)); @@ -684,27 +584,25 @@ 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) { - Key key = null; + + short cipherAlg = mapCipherAlg((byte) alg, (byte) padding, (byte) blockMode, (byte) 0); + KMOperation operation = + poolMgr.getOperationImpl(purpose, cipherAlg, alg, padding, blockMode, macLength, secretLength, false); + + KMKeyObject keyObj = operation.getKeyObject(); + Key key = (Key)keyObj.getKeyObject(); switch (secretLength) { case 32: - key = aesKeys[KEYSIZE_256_OFFSET]; - ((AESKey) key).setKey(secret, secretStart); - break; - case 16: - key = aesKeys[KEYSIZE_128_OFFSET]; + case 16: ((AESKey) key).setKey(secret, secretStart); break; case 24: - key = triDesKey; ((DESKey) key).setKey(secret, secretStart); break; default: CryptoException.throwIt(CryptoException.ILLEGAL_VALUE); break; - } - short cipherAlg = mapCipherAlg((byte) alg, (byte) padding, (byte) blockMode, (byte) 0); - KMOperation operation = - poolMgr.getOperationImpl(purpose, cipherAlg, alg, padding, blockMode, macLength, false); + } ((KMOperationImpl) operation).init(key, KMType.INVALID_VALUE, ivBuffer, ivStart, ivLength); return operation; } @@ -716,8 +614,10 @@ public KMOperation createHmacSignerVerifier(short purpose, short digest, } KMOperation operation = poolMgr.getOperationImpl(purpose, Signature.ALG_HMAC_SHA_256, - KMType.HMAC, KMType.INVALID_VALUE, KMType.INVALID_VALUE, KMType.INVALID_VALUE, false); - HMACKey key = createHMACKey(secret, secretStart, secretLength); + KMType.HMAC, KMType.INVALID_VALUE, KMType.INVALID_VALUE, KMType.INVALID_VALUE, (short)0, false); + KMKeyObject keyObj = operation.getKeyObject(); + HMACKey key = (HMACKey)keyObj.getKeyObject(); + key.setKey(secret, secretStart, secretLength); ((KMOperationImpl) operation).init(key, digest, null, (short) 0, (short) 0); return operation; } @@ -728,7 +628,7 @@ private KMOperation createHmacSignerVerifier(short purpose, short digest, HMACKe } KMOperation operation = poolMgr.getOperationImpl(purpose, Signature.ALG_HMAC_SHA_256, - KMType.HMAC, KMType.INVALID_VALUE, KMType.INVALID_VALUE, KMType.INVALID_VALUE, isTrustedConf); + KMType.HMAC, KMType.INVALID_VALUE, KMType.INVALID_VALUE, KMType.INVALID_VALUE, (short)0, isTrustedConf); ((KMOperationImpl) operation).init(key, digest, null, (short) 0, (short) 0); return operation; @@ -769,8 +669,9 @@ public KMOperation createRsaSigner(short digest, short padding, byte[] secret, short modLength) { byte alg = mapSignature256Alg(KMType.RSA, (byte) padding, (byte) digest); KMOperation operation = poolMgr.getOperationImpl(KMType.SIGN, alg, KMType.RSA, padding, - KMType.INVALID_VALUE, KMType.INVALID_VALUE, false); - RSAPrivateKey key = (RSAPrivateKey) rsaKeyPair.getPrivate(); + KMType.INVALID_VALUE, KMType.INVALID_VALUE, secretLength, false); + KMKeyObject keyObj = operation.getKeyObject(); + RSAPrivateKey key = (RSAPrivateKey)((KeyPair)(keyObj.getKeyObject())).getPrivate(); key.setExponent(secret, secretStart, secretLength); key.setModulus(modBuffer, modOff, modLength); ((KMOperationImpl) operation).init(key, digest, null, (short) 0, (short) 0); @@ -782,8 +683,9 @@ public KMOperation createRsaDecipher(short padding, short mgfDigest, byte[] secr short modLength) { byte cipherAlg = mapCipherAlg(KMType.RSA, (byte) padding, (byte) 0, (byte) mgfDigest); KMOperation operation = poolMgr.getOperationImpl(KMType.DECRYPT, cipherAlg, KMType.RSA, padding, - KMType.INVALID_VALUE, KMType.INVALID_VALUE, false); - RSAPrivateKey key = (RSAPrivateKey) rsaKeyPair.getPrivate(); + KMType.INVALID_VALUE, KMType.INVALID_VALUE, secretLength, false); + KMKeyObject keyObj = operation.getKeyObject(); + RSAPrivateKey key = (RSAPrivateKey) ((KeyPair)(keyObj.getKeyObject())).getPrivate(); key.setExponent(secret, secretStart, secretLength); key.setModulus(modBuffer, modOff, modLength); ((KMOperationImpl) operation).init(key, KMType.INVALID_VALUE, null, (short) 0, (short) 0); @@ -793,22 +695,24 @@ public KMOperation createRsaDecipher(short padding, short mgfDigest, byte[] secr public KMOperation createEcSigner(short digest, byte[] secret, short secretStart, short secretLength) { byte alg = mapSignature256Alg(KMType.EC, (byte) 0, (byte) digest); - ECPrivateKey key = (ECPrivateKey) ecKeyPair.getPrivate(); - key.setS(secret, secretStart, secretLength); KMOperation operation = poolMgr - .getOperationImpl(KMType.SIGN, alg, KMType.EC, KMType.INVALID_VALUE, - KMType.INVALID_VALUE, KMType.INVALID_VALUE, false); + .getOperationImpl(KMType.SIGN, alg, KMType.EC, KMType.INVALID_VALUE, + KMType.INVALID_VALUE, KMType.INVALID_VALUE, secretLength, false); + KMKeyObject keyObj = operation.getKeyObject(); + ECPrivateKey key = (ECPrivateKey) ((KeyPair)(keyObj.getKeyObject())).getPrivate(); + key.setS(secret, secretStart, secretLength); ((KMOperationImpl) operation).init(key, digest, null, (short) 0, (short) 0); return operation; } public KMOperation createKeyAgreement(byte[] secret, short secretStart, short secretLength) { - ECPrivateKey key = (ECPrivateKey) ecKeyPair.getPrivate(); - key.setS(secret, secretStart, secretLength); KMOperation operation = poolMgr .getOperationImpl(KMType.AGREE_KEY, KeyAgreement.ALG_EC_SVDP_DH_PLAIN, - KMType.EC, KMType.INVALID_VALUE, KMType.INVALID_VALUE, KMType.INVALID_VALUE, false); + KMType.EC, KMType.INVALID_VALUE, KMType.INVALID_VALUE, KMType.INVALID_VALUE, (short)0, false); + KMKeyObject keyObj = operation.getKeyObject(); + ECPrivateKey key = (ECPrivateKey) ((KeyPair)(keyObj.getKeyObject())).getPrivate(); + key.setS(secret, secretStart, secretLength); ((KMOperationImpl) operation).init(key, KMType.INVALID_VALUE, null, (short) 0, (short) 0); return operation; } @@ -884,19 +788,6 @@ public KMMasterKey createMasterKey(KMMasterKey masterKey, short keySizeBits) { } } - @Override - public KMAttestationKey createAttestationKey(KMAttestationKey attestationKey, byte[] keyData, short offset, - short length) { - if (attestationKey == null) { - // Strongbox supports only P-256 curve for EC key. - KeyPair ecKeyPair = new KeyPair(KeyPair.ALG_EC_FP, KeyBuilder.LENGTH_EC_FP_256); - initECKey(ecKeyPair); - attestationKey = new KMECPrivateKey(ecKeyPair); - } - ((KMECPrivateKey) attestationKey).setS(keyData, offset, length); - return (KMAttestationKey) attestationKey; - } - @Override public KMPreSharedKey createPreSharedKey(KMPreSharedKey preSharedKey, byte[] keyData, short offset, short length) { short lengthInBits = (short) (length * 8); @@ -1113,7 +1004,7 @@ public KMDeviceUniqueKeyPair createRkpDeviceUniqueKeyPair(KMDeviceUniqueKeyPair short privKeyOff, short privKeyLen) { if (key == null) { KeyPair ecKeyPair = new KeyPair(KeyPair.ALG_EC_FP, KeyBuilder.LENGTH_EC_FP_256); - initECKey(ecKeyPair); + poolMgr.initECKey(ecKeyPair); key = new KMECDeviceUniqueKey(ecKeyPair); } ((KMECDeviceUniqueKey) key).setS(privKey, privKeyOff, privKeyLen); diff --git a/Applet/AndroidSEProviderLib/src/com/android/javacard/seprovider/KMKeyObject.java b/Applet/AndroidSEProviderLib/src/com/android/javacard/seprovider/KMKeyObject.java new file mode 100644 index 00000000..ad5d1e5f --- /dev/null +++ b/Applet/AndroidSEProviderLib/src/com/android/javacard/seprovider/KMKeyObject.java @@ -0,0 +1,19 @@ +package com.android.javacard.seprovider; + +public class KMKeyObject { + private byte algorithm; + private Object keyObjectInst; + + public void setKeyObjectData(byte alg, Object keyObject) { + algorithm = alg; + keyObjectInst = keyObject; + } + + public byte getAlgorithm() { + return this.algorithm; + } + + public Object getKeyObject() { + return keyObjectInst; + } +} diff --git a/Applet/AndroidSEProviderLib/src/com/android/javacard/seprovider/KMOperation.java b/Applet/AndroidSEProviderLib/src/com/android/javacard/seprovider/KMOperation.java index b73d58d1..d824db2a 100644 --- a/Applet/AndroidSEProviderLib/src/com/android/javacard/seprovider/KMOperation.java +++ b/Applet/AndroidSEProviderLib/src/com/android/javacard/seprovider/KMOperation.java @@ -51,4 +51,6 @@ boolean verify(byte[] inputDataBuf, short inputDataStart, short inputDataLength, // include the auth tag which is appended at the end of the encrypted data. For decryption this will be // size of the decrypted data only. short getAESGCMOutputSize(short dataSize, short macLength); + + KMKeyObject getKeyObject(); } diff --git a/Applet/AndroidSEProviderLib/src/com/android/javacard/seprovider/KMOperationImpl.java b/Applet/AndroidSEProviderLib/src/com/android/javacard/seprovider/KMOperationImpl.java index baa8a0f9..bbb8c675 100644 --- a/Applet/AndroidSEProviderLib/src/com/android/javacard/seprovider/KMOperationImpl.java +++ b/Applet/AndroidSEProviderLib/src/com/android/javacard/seprovider/KMOperationImpl.java @@ -15,9 +15,6 @@ */ package com.android.javacard.seprovider; -import com.android.javacard.seprovider.KMError; -import com.android.javacard.seprovider.KMException; -import com.android.javacard.seprovider.KMType; import javacard.framework.JCSystem; import javacard.framework.Util; import javacard.security.KeyAgreement; @@ -46,7 +43,7 @@ public class KMOperationImpl implements KMOperation { public KMOperationImpl() { parameters = JCSystem.makeTransientShortArray(PARAMETERS_LENGTH, JCSystem.CLEAR_ON_RESET); - operationInst = JCSystem.makeTransientObjectArray((short) 1, JCSystem.CLEAR_ON_RESET); + operationInst = JCSystem.makeTransientObjectArray((short) 2, JCSystem.CLEAR_ON_RESET); reset(); } @@ -91,23 +88,32 @@ public void setAlgorithmType(short cipherAlg) { } public void setCipher(Cipher cipher) { - operationInst[0] = cipher; + operationInst[KMPoolManager.RESOURCE_TYPE_CRYPTO] = cipher; } public void setSignature(Signature signer) { - operationInst[0] = signer; + operationInst[KMPoolManager.RESOURCE_TYPE_CRYPTO] = signer; } public void setKeyAgreement(KeyAgreement keyAgreement) { - operationInst[0] = keyAgreement; + operationInst[KMPoolManager.RESOURCE_TYPE_CRYPTO] = keyAgreement; } - public boolean isResourceMatches(Object object) { - return operationInst[0] == object; + public boolean isResourceMatches(Object object, byte resourceType) { + return operationInst[resourceType] == object; } + public void setKeyObject(KMKeyObject keyObject) { + operationInst[KMPoolManager.RESOURCE_TYPE_KEY] = keyObject; + } + + public KMKeyObject getKeyObject() { + return (KMKeyObject) operationInst[KMPoolManager.RESOURCE_TYPE_KEY]; + } + private void reset() { - operationInst[0] = null; + operationInst[KMPoolManager.RESOURCE_TYPE_CRYPTO] = null; + operationInst[KMPoolManager.RESOURCE_TYPE_KEY] = null; parameters[MAC_LENGTH_OFFSET] = KMType.INVALID_VALUE; parameters[AES_GCM_UPDATE_LEN_OFFSET] = 0; parameters[BLOCK_MODE_OFFSET] = KMType.INVALID_VALUE; @@ -131,7 +137,7 @@ private byte mapPurpose(short purpose) { } private void initSymmetricCipher(Key key, byte[] ivBuffer, short ivStart, short ivLength) { - Cipher symmCipher = (Cipher) operationInst[0]; + Cipher symmCipher = (Cipher) operationInst[KMPoolManager.RESOURCE_TYPE_CRYPTO]; byte cipherAlg = symmCipher.getAlgorithm(); switch (cipherAlg) { case Cipher.ALG_AES_BLOCK_128_CBC_NOPAD: @@ -167,17 +173,19 @@ private void initRsa(Key key, short digest) { } else { mode = Signature.MODE_SIGN; } - ((Signature) operationInst[0]).init((PrivateKey) key, mode); + ((Signature) operationInst[KMPoolManager.RESOURCE_TYPE_CRYPTO]).init((PrivateKey) key, mode); } else { // RSA Cipher - ((Cipher) operationInst[0]).init((PrivateKey) key, mapPurpose(getPurpose())); + ((Cipher) operationInst[KMPoolManager.RESOURCE_TYPE_CRYPTO]). + init((PrivateKey) key, mapPurpose(getPurpose())); } } private void initEc(Key key) { if (KMType.AGREE_KEY == getPurpose()) { - ((KeyAgreement) operationInst[0]).init((PrivateKey) key); + ((KeyAgreement) operationInst[KMPoolManager.RESOURCE_TYPE_CRYPTO]).init((PrivateKey) key); } else { - ((Signature) operationInst[0]).init((PrivateKey) key, mapPurpose(getPurpose())); + ((Signature) operationInst[KMPoolManager.RESOURCE_TYPE_CRYPTO]) + .init((PrivateKey) key, mapPurpose(getPurpose())); } } @@ -188,7 +196,8 @@ public void init(Key key, short digest, byte[] buf, short start, short length) { initSymmetricCipher(key, buf, start, length); break; case KMType.HMAC: - ((Signature) operationInst[0]).init(key, mapPurpose(getPurpose())); + ((Signature) operationInst[KMPoolManager.RESOURCE_TYPE_CRYPTO]) + .init(key, mapPurpose(getPurpose())); break; case KMType.RSA: initRsa(key, digest); @@ -205,7 +214,8 @@ public void init(Key key, short digest, byte[] buf, short start, short length) { @Override public short update(byte[] inputDataBuf, short inputDataStart, short inputDataLength, byte[] outputDataBuf, short outputDataStart) { - short len = ((Cipher) operationInst[0]).update(inputDataBuf, inputDataStart, inputDataLength, + short len = ((Cipher) operationInst[KMPoolManager.RESOURCE_TYPE_CRYPTO]) + .update(inputDataBuf, inputDataStart, inputDataLength, outputDataBuf, outputDataStart); if (parameters[ALG_TYPE_OFFSET] == KMType.AES && parameters[BLOCK_MODE_OFFSET] == KMType.GCM) { @@ -218,13 +228,15 @@ public short update(byte[] inputDataBuf, short inputDataStart, @Override public short update(byte[] inputDataBuf, short inputDataStart, short inputDataLength) { - ((Signature) operationInst[0]).update(inputDataBuf, inputDataStart, inputDataLength); + ((Signature) operationInst[KMPoolManager.RESOURCE_TYPE_CRYPTO]) + .update(inputDataBuf, inputDataStart, inputDataLength); return 0; } private short finishKeyAgreement(byte[] publicKey, short start, short len, byte[] output, short outputStart) { - return ((KeyAgreement) operationInst[0]).generateSecret(publicKey, start, len, + return ((KeyAgreement) operationInst[KMPoolManager.RESOURCE_TYPE_CRYPTO]) + .generateSecret(publicKey, start, len, output, outputStart); } @@ -234,7 +246,7 @@ private short finishCipher(byte[] inputDataBuf, short inputDataStart, short inpu short len = 0; try { byte[] tmpArray = KMAndroidSEProvider.getInstance().tmpArray; - Cipher cipher = (Cipher) operationInst[0]; + Cipher cipher = (Cipher) operationInst[KMPoolManager.RESOURCE_TYPE_CRYPTO]; short cipherAlg = parameters[ALG_TYPE_OFFSET]; short blockMode = parameters[BLOCK_MODE_OFFSET]; short mode = parameters[PURPOSE_OFFSET]; @@ -328,14 +340,16 @@ public short finish(byte[] inputDataBuf, short inputDataStart, short inputDataLe @Override public short sign(byte[] inputDataBuf, short inputDataStart, short inputDataLength, byte[] signBuf, short signStart) { - return ((Signature) operationInst[0]).sign(inputDataBuf, inputDataStart, inputDataLength, + return ((Signature) operationInst[KMPoolManager.RESOURCE_TYPE_CRYPTO]) + .sign(inputDataBuf, inputDataStart, inputDataLength, signBuf, signStart); } @Override public boolean verify(byte[] inputDataBuf, short inputDataStart, short inputDataLength, byte[] signBuf, short signStart, short signLength) { - return ((Signature) operationInst[0]).verify(inputDataBuf, inputDataStart, inputDataLength, + return ((Signature) operationInst[KMPoolManager.RESOURCE_TYPE_CRYPTO]) + .verify(inputDataBuf, inputDataStart, inputDataLength, signBuf, signStart, signLength); } @@ -344,10 +358,10 @@ public void abort() { // Few simulators does not reset the Hmac signer instance on init so as // a workaround to reset the hmac signer instance in case of abort/failure of the operation // the corresponding sign / verify function is called. - if (operationInst[0] != null) { + if (operationInst[KMPoolManager.RESOURCE_TYPE_CRYPTO] != null) { if ((parameters[PURPOSE_OFFSET] == KMType.SIGN || parameters[PURPOSE_OFFSET] == KMType.VERIFY) && - (((Signature) operationInst[0]).getAlgorithm() == Signature.ALG_HMAC_SHA_256)) { - Signature signer = (Signature) operationInst[0]; + (((Signature) operationInst[KMPoolManager.RESOURCE_TYPE_CRYPTO]).getAlgorithm() == Signature.ALG_HMAC_SHA_256)) { + Signature signer = (Signature) operationInst[KMPoolManager.RESOURCE_TYPE_CRYPTO]; try { if (parameters[PURPOSE_OFFSET] == KMType.SIGN) { signer.sign(EMPTY, (short) 0, (short) 0, EMPTY, (short) 0); @@ -364,7 +378,8 @@ public void abort() { @Override public void updateAAD(byte[] dataBuf, short dataStart, short dataLength) { - ((AEADCipher) operationInst[0]).updateAAD(dataBuf, dataStart, dataLength); + ((AEADCipher) operationInst[KMPoolManager.RESOURCE_TYPE_CRYPTO]) + .updateAAD(dataBuf, dataStart, dataLength); } @Override diff --git a/Applet/AndroidSEProviderLib/src/com/android/javacard/seprovider/KMPoolManager.java b/Applet/AndroidSEProviderLib/src/com/android/javacard/seprovider/KMPoolManager.java index e3baf610..57d164cb 100644 --- a/Applet/AndroidSEProviderLib/src/com/android/javacard/seprovider/KMPoolManager.java +++ b/Applet/AndroidSEProviderLib/src/com/android/javacard/seprovider/KMPoolManager.java @@ -15,7 +15,16 @@ */ package com.android.javacard.seprovider; import javacard.framework.JCSystem; +import javacard.security.AESKey; +import javacard.security.CryptoException; +import javacard.security.DESKey; +import javacard.security.ECPrivateKey; +import javacard.security.ECPublicKey; +import javacard.security.HMACKey; 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; @@ -27,6 +36,26 @@ public class KMPoolManager { public static final short MAX_OPERATION_INSTANCES = 4; private static final short HMAC_MAX_OPERATION_INSTANCES = 8; + public static final byte AES_128 = 0x04; + public static final byte AES_256 = 0x05; + //Resource type constants + public static final byte RESOURCE_TYPE_CRYPTO = 0x00; + public static final byte RESOURCE_TYPE_KEY = 0x01; + // static final variables + // -------------------------------------------------------------- + // P-256 Curve Parameters + static byte[] secp256r1_P; + static byte[] secp256r1_A; + + static byte[] secp256r1_B; + static byte[] secp256r1_S; + + // Uncompressed form + static byte[] secp256r1_UCG; + static byte[] secp256r1_N; + static final short secp256r1_H = 1; + // -------------------------------------------------------------- + // Cipher pool private Object[] cipherPool; // Signature pool @@ -37,7 +66,18 @@ public class KMPoolManager { private Object[] operationPool; // Hmac signer pool which is used to support TRUSTED_CONFIRMATION_REQUIRED tag. private Object[] hmacSignOperationPool; - + + private Object[] keysPool; + + final byte[] KEY_ALGS = { + AES_128, + AES_256, + KMType.DES, + KMType.RSA, + KMType.EC, + KMType.HMAC, + }; + final byte[] CIPHER_ALGS = { Cipher.ALG_AES_BLOCK_128_CBC_NOPAD, Cipher.ALG_AES_BLOCK_128_ECB_NOPAD, @@ -71,11 +111,81 @@ public static KMPoolManager getInstance() { return poolManager; } + public static void initStatics() { + secp256r1_P = new byte[]{(byte) 0xFF, (byte) 0xFF, (byte) 0xFF, (byte) 0xFF, (byte) 0x00, + (byte) 0x00, + (byte) 0x00, (byte) 0x01, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, + (byte) 0x00, + (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0xFF, + (byte) 0xFF, + (byte) 0xFF, (byte) 0xFF, (byte) 0xFF, (byte) 0xFF, (byte) 0xFF, (byte) 0xFF, (byte) 0xFF, + (byte) 0xFF, + (byte) 0xFF, (byte) 0xFF}; + + secp256r1_A = new byte[]{(byte) 0xFF, (byte) 0xFF, (byte) 0xFF, (byte) 0xFF, (byte) 0x00, + (byte) 0x00, + (byte) 0x00, (byte) 0x01, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, + (byte) 0x00, + (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0xFF, + (byte) 0xFF, + (byte) 0xFF, (byte) 0xFF, (byte) 0xFF, (byte) 0xFF, (byte) 0xFF, (byte) 0xFF, (byte) 0xFF, + (byte) 0xFF, + (byte) 0xFF, (byte) 0xFC}; + + secp256r1_B = new byte[]{(byte) 0x5A, (byte) 0xC6, (byte) 0x35, (byte) 0xD8, (byte) 0xAA, + (byte) 0x3A, + (byte) 0x93, (byte) 0xE7, (byte) 0xB3, (byte) 0xEB, (byte) 0xBD, (byte) 0x55, (byte) 0x76, + (byte) 0x98, + (byte) 0x86, (byte) 0xBC, (byte) 0x65, (byte) 0x1D, (byte) 0x06, (byte) 0xB0, (byte) 0xCC, + (byte) 0x53, + (byte) 0xB0, (byte) 0xF6, (byte) 0x3B, (byte) 0xCE, (byte) 0x3C, (byte) 0x3E, (byte) 0x27, + (byte) 0xD2, + (byte) 0x60, (byte) 0x4B}; + + secp256r1_S = new byte[]{(byte) 0xC4, (byte) 0x9D, (byte) 0x36, (byte) 0x08, (byte) 0x86, + (byte) 0xE7, + (byte) 0x04, (byte) 0x93, (byte) 0x6A, (byte) 0x66, (byte) 0x78, (byte) 0xE1, (byte) 0x13, + (byte) 0x9D, + (byte) 0x26, (byte) 0xB7, (byte) 0x81, (byte) 0x9F, (byte) 0x7E, (byte) 0x90}; + + // Uncompressed form + secp256r1_UCG = new byte[]{(byte) 0x04, (byte) 0x6B, (byte) 0x17, (byte) 0xD1, (byte) 0xF2, + (byte) 0xE1, + (byte) 0x2C, (byte) 0x42, (byte) 0x47, (byte) 0xF8, (byte) 0xBC, (byte) 0xE6, (byte) 0xE5, + (byte) 0x63, + (byte) 0xA4, (byte) 0x40, (byte) 0xF2, (byte) 0x77, (byte) 0x03, (byte) 0x7D, (byte) 0x81, + (byte) 0x2D, + (byte) 0xEB, (byte) 0x33, (byte) 0xA0, (byte) 0xF4, (byte) 0xA1, (byte) 0x39, (byte) 0x45, + (byte) 0xD8, + (byte) 0x98, (byte) 0xC2, (byte) 0x96, (byte) 0x4F, (byte) 0xE3, (byte) 0x42, (byte) 0xE2, + (byte) 0xFE, + (byte) 0x1A, (byte) 0x7F, (byte) 0x9B, (byte) 0x8E, (byte) 0xE7, (byte) 0xEB, (byte) 0x4A, + (byte) 0x7C, + (byte) 0x0F, (byte) 0x9E, (byte) 0x16, (byte) 0x2B, (byte) 0xCE, (byte) 0x33, (byte) 0x57, + (byte) 0x6B, + (byte) 0x31, (byte) 0x5E, (byte) 0xCE, (byte) 0xCB, (byte) 0xB6, (byte) 0x40, (byte) 0x68, + (byte) 0x37, + (byte) 0xBF, (byte) 0x51, (byte) 0xF5}; + + secp256r1_N = new byte[]{(byte) 0xFF, (byte) 0xFF, (byte) 0xFF, (byte) 0xFF, (byte) 0x00, + (byte) 0x00, + (byte) 0x00, (byte) 0x00, (byte) 0xFF, (byte) 0xFF, (byte) 0xFF, (byte) 0xFF, (byte) 0xFF, + (byte) 0xFF, + (byte) 0xFF, (byte) 0xFF, (byte) 0xBC, (byte) 0xE6, (byte) 0xFA, (byte) 0xAD, (byte) 0xA7, + (byte) 0x17, + (byte) 0x9E, (byte) 0x84, (byte) 0xF3, (byte) 0xB9, (byte) 0xCA, (byte) 0xC2, (byte) 0xFC, + (byte) 0x63, + (byte) 0x25, (byte) 0x51}; + } + private KMPoolManager() { + initStatics(); cipherPool = new Object[(short) (CIPHER_ALGS.length * 4)]; // Extra 4 algorithms are used to support TRUSTED_CONFIRMATION_REQUIRED feature. signerPool = new Object[(short) ((SIG_ALGS.length * 4) + 4)]; 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]; /* Initialize pools */ @@ -84,8 +194,18 @@ private KMPoolManager() { initializeSignerPool(); initializeCipherPool(); initializeKeyAgreementPool(); + initializeKeysPool(); + } + private void initializeKeysPool() { + short index = 0; + while (index < KEY_ALGS.length) { + keysPool[index] = createKeyObjectInstance(KEY_ALGS[index]); + index++; + } + } + private void initializeOperationPool() { short index = 0; while (index < MAX_OPERATION_INSTANCES) { @@ -180,6 +300,40 @@ private Signature getSignatureInstance(byte alg) { return Signature.getInstance(alg, false); } } + + private KMKeyObject createKeyObjectInstance(byte alg) { + Object keyObject = null; + switch (alg) { + case AES_128: + keyObject = (AESKey) KeyBuilder.buildKey(KeyBuilder.TYPE_AES_TRANSIENT_RESET, + KeyBuilder.LENGTH_AES_128, false); + break; + case AES_256: + keyObject = (AESKey) KeyBuilder.buildKey(KeyBuilder.TYPE_AES_TRANSIENT_RESET, + KeyBuilder.LENGTH_AES_256, false); + break; + case KMType.DES: + keyObject = (DESKey) KeyBuilder.buildKey(KeyBuilder.TYPE_DES_TRANSIENT_RESET, + KeyBuilder.LENGTH_DES3_3KEY, false); + break; + case KMType.RSA: + keyObject = new KeyPair(KeyPair.ALG_RSA, KeyBuilder.LENGTH_RSA_2048); + break; + case KMType.EC: + keyObject = new KeyPair(KeyPair.ALG_EC_FP, KeyBuilder.LENGTH_EC_FP_256); + initECKey((KeyPair) keyObject); + break; + case KMType.HMAC: + keyObject = (HMACKey) KeyBuilder.buildKey(KeyBuilder.TYPE_HMAC_TRANSIENT_RESET, + (short) 512, false); + break; + default: + KMException.throwIt(KMError.UNSUPPORTED_ALGORITHM); + } + KMKeyObject ptr = new KMKeyObject(); + ptr.setKeyObjectData(alg, keyObject); + return ptr; + } private Cipher getCipherInstance(byte alg) { if ((KMRsaOAEPEncoding.ALG_RSA_PKCS1_OAEP_SHA256_MGF1_SHA1 == alg) || @@ -234,11 +388,11 @@ private byte getAlgorithm(short purpose, Object object) { return 0; } - private boolean isResourceBusy(Object obj) { + private boolean isResourceBusy(Object obj, byte resourceType) { short index = 0; while (index < MAX_OPERATION_INSTANCES) { - if (((KMOperationImpl) operationPool[index]).isResourceMatches(obj) - || ((KMOperationImpl) hmacSignOperationPool[index]).isResourceMatches(obj)) { + if (((KMOperationImpl) operationPool[index]).isResourceMatches(obj, resourceType) + || ((KMOperationImpl) hmacSignOperationPool[index]).isResourceMatches(obj, resourceType)) { return true; } index++; @@ -265,19 +419,20 @@ private void setObject(short purpose, KMOperation operation, Object obj) { } private void reserveOperation(KMOperation operation, short purpose, short strongboxAlgType, - short padding, short blockMode, short macLength, Object obj) { + short padding, short blockMode, short macLength, Object obj, KMKeyObject keyObject) { ((KMOperationImpl) operation).setPurpose(purpose); ((KMOperationImpl) operation).setAlgorithmType(strongboxAlgType); ((KMOperationImpl) operation).setPaddingAlgorithm(padding); ((KMOperationImpl) operation).setBlockMode(blockMode); ((KMOperationImpl) operation).setMacLength(macLength); + ((KMOperationImpl) operation).setKeyObject(keyObject); setObject(purpose, operation, obj); } public KMOperation getOperationImpl(short purpose, short alg, short strongboxAlgType, short padding, - short blockMode, short macLength, boolean isTrustedConfOpr) { + short blockMode, short macLength, short secretLength, boolean isTrustedConfOpr) { KMOperation operation; // Throw exception if no resource from operation pool is available. if (null == (operation = getResourceFromOperationPool(isTrustedConfOpr))) { @@ -292,6 +447,7 @@ public KMOperation getOperationImpl(short purpose, short alg, short strongboxAlg maxOperations = HMAC_MAX_OPERATION_INSTANCES; } + KMKeyObject keyObject = reserveKeyObject(alg, secretLength, maxOperations); while (index < pool.length) { if (usageCount >= maxOperations) { KMException.throwIt(KMError.TOO_MANY_OPERATIONS); @@ -302,14 +458,14 @@ public KMOperation getOperationImpl(short purpose, short alg, short strongboxAlg pool[index] = createInstance(purpose, alg); JCSystem.commitTransaction(); reserveOperation(operation, purpose, strongboxAlgType, padding, blockMode, macLength, - pool[index]); + pool[index], keyObject); break; } if (alg == getAlgorithm(purpose, pool[index])) { // Check if the crypto instance is not busy and free to use. - if (!isResourceBusy(pool[index])) { + if (!isResourceBusy(pool[index], RESOURCE_TYPE_CRYPTO)) { reserveOperation(operation, purpose, strongboxAlgType, padding, blockMode, macLength, - pool[index]); + pool[index], keyObject); break; } usageCount++; @@ -319,6 +475,96 @@ public KMOperation getOperationImpl(short purpose, short alg, short strongboxAlg return operation; } + public KMKeyObject reserveKeyObject(short alg, short secretLength, short maxOperations) { + KMKeyObject keyObject = null; + byte algo = mapAlgorithm(alg, secretLength); + short index = 0; + short usageCount = 0; + while (index < keysPool.length) { + if (usageCount >= maxOperations) { + KMException.throwIt(KMError.TOO_MANY_OPERATIONS); + } + if (keysPool[index] == null) { + JCSystem.beginTransaction(); + keysPool[index] = createKeyObjectInstance(algo); + keyObject = (KMKeyObject) keysPool[index]; + JCSystem.commitTransaction(); + break; + } + keyObject = (KMKeyObject) keysPool[index]; + if (algo == keyObject.getAlgorithm()) { + // Check if the Object instance is not busy and free to use. + if (!isResourceBusy(keyObject, RESOURCE_TYPE_KEY)) { + break; + } + usageCount++; + } + index++; + } + return keyObject; + } + + private byte mapAlgorithm(short alg, short secretLength) { + byte algo = 0; + switch (alg) { + case Cipher.ALG_AES_BLOCK_128_CBC_NOPAD: + case Cipher.ALG_AES_BLOCK_128_ECB_NOPAD: + case Cipher.ALG_AES_CTR: + case AEADCipher.ALG_AES_GCM: + if (secretLength == 16) { + algo = AES_128; + } else if (secretLength == 32) { + algo = AES_256; + } else { + CryptoException.throwIt(CryptoException.ILLEGAL_VALUE); + } + break; + case Cipher.ALG_DES_CBC_NOPAD: + case Cipher.ALG_DES_ECB_NOPAD: + algo = KMType.DES; + break; + case Cipher.ALG_RSA_PKCS1: + case KMRsaOAEPEncoding.ALG_RSA_PKCS1_OAEP_SHA256_MGF1_SHA1: + case KMRsaOAEPEncoding.ALG_RSA_PKCS1_OAEP_SHA256_MGF1_SHA256: + case Cipher.ALG_RSA_NOPAD: + case Signature.ALG_RSA_SHA_256_PKCS1: + case Signature.ALG_RSA_SHA_256_PKCS1_PSS: + case KMRsa2048NoDigestSignature.ALG_RSA_SIGN_NOPAD: + case KMRsa2048NoDigestSignature.ALG_RSA_PKCS1_NODIGEST: + algo = KMType.RSA; + break; + case Signature.ALG_ECDSA_SHA_256: + case KMEcdsa256NoDigestSignature.ALG_ECDSA_NODIGEST: + case KeyAgreement.ALG_EC_SVDP_DH_PLAIN: + algo = KMType.EC; + break; + case Signature.ALG_HMAC_SHA_256: + algo = KMType.HMAC; + break; + default: + KMException.throwIt(KMError.UNSUPPORTED_ALGORITHM); + } + return algo; + } + + public void initECKey(KeyPair ecKeyPair) { + ECPrivateKey privKey = (ECPrivateKey) ecKeyPair.getPrivate(); + ECPublicKey pubkey = (ECPublicKey) ecKeyPair.getPublic(); + pubkey.setFieldFP(secp256r1_P, (short) 0, (short) secp256r1_P.length); + pubkey.setA(secp256r1_A, (short) 0, (short) secp256r1_A.length); + pubkey.setB(secp256r1_B, (short) 0, (short) secp256r1_B.length); + pubkey.setG(secp256r1_UCG, (short) 0, (short) secp256r1_UCG.length); + pubkey.setK(secp256r1_H); + pubkey.setR(secp256r1_N, (short) 0, (short) secp256r1_N.length); + + privKey.setFieldFP(secp256r1_P, (short) 0, (short) secp256r1_P.length); + privKey.setA(secp256r1_A, (short) 0, (short) secp256r1_A.length); + privKey.setB(secp256r1_B, (short) 0, (short) secp256r1_B.length); + privKey.setG(secp256r1_UCG, (short) 0, (short) secp256r1_UCG.length); + privKey.setK(secp256r1_H); + privKey.setR(secp256r1_N, (short) 0, (short) secp256r1_N.length); + } + public void powerReset() { short index = 0; while (index < operationPool.length) { diff --git a/Applet/AndroidSEProviderLib/src/com/android/javacard/seprovider/KMSEProvider.java b/Applet/AndroidSEProviderLib/src/com/android/javacard/seprovider/KMSEProvider.java index c4445114..515fe4b4 100644 --- a/Applet/AndroidSEProviderLib/src/com/android/javacard/seprovider/KMSEProvider.java +++ b/Applet/AndroidSEProviderLib/src/com/android/javacard/seprovider/KMSEProvider.java @@ -643,20 +643,7 @@ KMDeviceUniqueKeyPair createRkpDeviceUniqueKeyPair(KMDeviceUniqueKeyPair key, short messageDigest256(byte[] inBuff, short inOffset, short inLength, byte[] outBuff, short outOffset); - /** - * This function creates an ECKey and initializes the ECPrivateKey with the provided input key - * data. The initialized Key is maintained by the SEProvider. This function should be called only - * while provisioning the attestation key. - * - * @param keyData buffer containing the ec private key. - * @param offset start of the buffer. - * @param length length of the buffer. - * @return An instance of KMAttestationKey. - */ - KMAttestationKey createAttestationKey(KMAttestationKey attestationKey, byte[] keyData, - short offset, - short length); - + /** * This function generates a HMAC key from the provided key buffers. * From 24d9d551e1984a67563a64a4083acbed1c587df3 Mon Sep 17 00:00:00 2001 From: "avinash.hedage" Date: Fri, 22 Apr 2022 14:50:37 +0000 Subject: [PATCH 6/8] key object pool changes --- .../javacard/seprovider/KMAndroidSEProvider.java | 12 ++++++------ .../com/android/javacard/seprovider/KMKeyObject.java | 2 +- .../android/javacard/seprovider/KMPoolManager.java | 4 ++-- 3 files changed, 9 insertions(+), 9 deletions(-) diff --git a/Applet/AndroidSEProviderLib/src/com/android/javacard/seprovider/KMAndroidSEProvider.java b/Applet/AndroidSEProviderLib/src/com/android/javacard/seprovider/KMAndroidSEProvider.java index 23e80b29..d2fc4f48 100644 --- a/Applet/AndroidSEProviderLib/src/com/android/javacard/seprovider/KMAndroidSEProvider.java +++ b/Applet/AndroidSEProviderLib/src/com/android/javacard/seprovider/KMAndroidSEProvider.java @@ -590,7 +590,7 @@ public KMOperation createSymmetricCipher(short alg, short purpose, short macLeng poolMgr.getOperationImpl(purpose, cipherAlg, alg, padding, blockMode, macLength, secretLength, false); KMKeyObject keyObj = operation.getKeyObject(); - Key key = (Key)keyObj.getKeyObject(); + Key key = (Key)keyObj.getKeyObjectInstance(); switch (secretLength) { case 32: case 16: @@ -616,7 +616,7 @@ public KMOperation createHmacSignerVerifier(short purpose, short digest, poolMgr.getOperationImpl(purpose, Signature.ALG_HMAC_SHA_256, KMType.HMAC, KMType.INVALID_VALUE, KMType.INVALID_VALUE, KMType.INVALID_VALUE, (short)0, false); KMKeyObject keyObj = operation.getKeyObject(); - HMACKey key = (HMACKey)keyObj.getKeyObject(); + HMACKey key = (HMACKey)keyObj.getKeyObjectInstance(); key.setKey(secret, secretStart, secretLength); ((KMOperationImpl) operation).init(key, digest, null, (short) 0, (short) 0); return operation; @@ -671,7 +671,7 @@ public KMOperation createRsaSigner(short digest, short padding, byte[] secret, KMOperation operation = poolMgr.getOperationImpl(KMType.SIGN, alg, KMType.RSA, padding, KMType.INVALID_VALUE, KMType.INVALID_VALUE, secretLength, false); KMKeyObject keyObj = operation.getKeyObject(); - RSAPrivateKey key = (RSAPrivateKey)((KeyPair)(keyObj.getKeyObject())).getPrivate(); + RSAPrivateKey key = (RSAPrivateKey)((KeyPair)(keyObj.getKeyObjectInstance())).getPrivate(); key.setExponent(secret, secretStart, secretLength); key.setModulus(modBuffer, modOff, modLength); ((KMOperationImpl) operation).init(key, digest, null, (short) 0, (short) 0); @@ -685,7 +685,7 @@ public KMOperation createRsaDecipher(short padding, short mgfDigest, byte[] secr KMOperation operation = poolMgr.getOperationImpl(KMType.DECRYPT, cipherAlg, KMType.RSA, padding, KMType.INVALID_VALUE, KMType.INVALID_VALUE, secretLength, false); KMKeyObject keyObj = operation.getKeyObject(); - RSAPrivateKey key = (RSAPrivateKey) ((KeyPair)(keyObj.getKeyObject())).getPrivate(); + RSAPrivateKey key = (RSAPrivateKey) ((KeyPair)(keyObj.getKeyObjectInstance())).getPrivate(); key.setExponent(secret, secretStart, secretLength); key.setModulus(modBuffer, modOff, modLength); ((KMOperationImpl) operation).init(key, KMType.INVALID_VALUE, null, (short) 0, (short) 0); @@ -699,7 +699,7 @@ public KMOperation createEcSigner(short digest, byte[] secret, .getOperationImpl(KMType.SIGN, alg, KMType.EC, KMType.INVALID_VALUE, KMType.INVALID_VALUE, KMType.INVALID_VALUE, secretLength, false); KMKeyObject keyObj = operation.getKeyObject(); - ECPrivateKey key = (ECPrivateKey) ((KeyPair)(keyObj.getKeyObject())).getPrivate(); + ECPrivateKey key = (ECPrivateKey) ((KeyPair)(keyObj.getKeyObjectInstance())).getPrivate(); key.setS(secret, secretStart, secretLength); ((KMOperationImpl) operation).init(key, digest, null, (short) 0, (short) 0); return operation; @@ -711,7 +711,7 @@ public KMOperation createKeyAgreement(byte[] secret, short secretStart, .getOperationImpl(KMType.AGREE_KEY, KeyAgreement.ALG_EC_SVDP_DH_PLAIN, KMType.EC, KMType.INVALID_VALUE, KMType.INVALID_VALUE, KMType.INVALID_VALUE, (short)0, false); KMKeyObject keyObj = operation.getKeyObject(); - ECPrivateKey key = (ECPrivateKey) ((KeyPair)(keyObj.getKeyObject())).getPrivate(); + ECPrivateKey key = (ECPrivateKey) ((KeyPair)(keyObj.getKeyObjectInstance())).getPrivate(); key.setS(secret, secretStart, secretLength); ((KMOperationImpl) operation).init(key, KMType.INVALID_VALUE, null, (short) 0, (short) 0); return operation; diff --git a/Applet/AndroidSEProviderLib/src/com/android/javacard/seprovider/KMKeyObject.java b/Applet/AndroidSEProviderLib/src/com/android/javacard/seprovider/KMKeyObject.java index ad5d1e5f..03f54ecc 100644 --- a/Applet/AndroidSEProviderLib/src/com/android/javacard/seprovider/KMKeyObject.java +++ b/Applet/AndroidSEProviderLib/src/com/android/javacard/seprovider/KMKeyObject.java @@ -13,7 +13,7 @@ public byte getAlgorithm() { return this.algorithm; } - public Object getKeyObject() { + public Object getKeyObjectInstance() { return keyObjectInst; } } diff --git a/Applet/AndroidSEProviderLib/src/com/android/javacard/seprovider/KMPoolManager.java b/Applet/AndroidSEProviderLib/src/com/android/javacard/seprovider/KMPoolManager.java index 57d164cb..6e9ca210 100644 --- a/Applet/AndroidSEProviderLib/src/com/android/javacard/seprovider/KMPoolManager.java +++ b/Applet/AndroidSEProviderLib/src/com/android/javacard/seprovider/KMPoolManager.java @@ -447,7 +447,7 @@ public KMOperation getOperationImpl(short purpose, short alg, short strongboxAlg maxOperations = HMAC_MAX_OPERATION_INSTANCES; } - KMKeyObject keyObject = reserveKeyObject(alg, secretLength, maxOperations); + KMKeyObject keyObject = getKeyObjectFromPool(alg, secretLength, maxOperations); while (index < pool.length) { if (usageCount >= maxOperations) { KMException.throwIt(KMError.TOO_MANY_OPERATIONS); @@ -475,7 +475,7 @@ public KMOperation getOperationImpl(short purpose, short alg, short strongboxAlg return operation; } - public KMKeyObject reserveKeyObject(short alg, short secretLength, short maxOperations) { + public KMKeyObject getKeyObjectFromPool(short alg, short secretLength, short maxOperations) { KMKeyObject keyObject = null; byte algo = mapAlgorithm(alg, secretLength); short index = 0; From 100ea995c74e6ddedfbd8d3dd7d157578af52105 Mon Sep 17 00:00:00 2001 From: Subrahmanyaman Date: Tue, 26 Apr 2022 05:55:18 +0000 Subject: [PATCH 7/8] Addressed review comments --- .../seprovider/KMAndroidSEProvider.java | 15 ++-- .../javacard/seprovider/KMPoolManager.java | 7 +- .../javacard/keymaster/KMKeymasterApplet.java | 71 +++++++++++-------- 3 files changed, 55 insertions(+), 38 deletions(-) diff --git a/Applet/AndroidSEProviderLib/src/com/android/javacard/seprovider/KMAndroidSEProvider.java b/Applet/AndroidSEProviderLib/src/com/android/javacard/seprovider/KMAndroidSEProvider.java index d2fc4f48..d21e25ab 100644 --- a/Applet/AndroidSEProviderLib/src/com/android/javacard/seprovider/KMAndroidSEProvider.java +++ b/Applet/AndroidSEProviderLib/src/com/android/javacard/seprovider/KMAndroidSEProvider.java @@ -588,7 +588,7 @@ public KMOperation createSymmetricCipher(short alg, short purpose, short macLeng short cipherAlg = mapCipherAlg((byte) alg, (byte) padding, (byte) blockMode, (byte) 0); KMOperation 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(); switch (secretLength) { @@ -615,6 +615,7 @@ public KMOperation createHmacSignerVerifier(short purpose, short digest, KMOperation 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(); key.setKey(secret, secretStart, secretLength); @@ -622,14 +623,18 @@ public KMOperation createHmacSignerVerifier(short purpose, short digest, return operation; } - private KMOperation createHmacSignerVerifier(short purpose, short digest, HMACKey key, boolean isTrustedConf) { + private KMOperation createHmacSignerVerifier(short purpose, short digest, HMACKey hmacKey, boolean isTrustedConf) { if (digest != KMType.SHA2_256) { CryptoException.throwIt(CryptoException.ILLEGAL_VALUE); } KMOperation operation = poolMgr.getOperationImpl(purpose, Signature.ALG_HMAC_SHA_256, 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(); + 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; } @@ -670,6 +675,7 @@ public KMOperation createRsaSigner(short digest, short padding, byte[] secret, byte alg = mapSignature256Alg(KMType.RSA, (byte) padding, (byte) digest); KMOperation operation = poolMgr.getOperationImpl(KMType.SIGN, alg, KMType.RSA, padding, KMType.INVALID_VALUE, KMType.INVALID_VALUE, secretLength, false); + // Get the KeyObject from the operation and update the key with the secret key material. KMKeyObject keyObj = operation.getKeyObject(); RSAPrivateKey key = (RSAPrivateKey)((KeyPair)(keyObj.getKeyObjectInstance())).getPrivate(); key.setExponent(secret, secretStart, secretLength); @@ -683,7 +689,8 @@ public KMOperation createRsaDecipher(short padding, short mgfDigest, byte[] secr short modLength) { byte cipherAlg = mapCipherAlg(KMType.RSA, (byte) padding, (byte) 0, (byte) mgfDigest); KMOperation operation = poolMgr.getOperationImpl(KMType.DECRYPT, cipherAlg, KMType.RSA, padding, - KMType.INVALID_VALUE, KMType.INVALID_VALUE, secretLength, false); + KMType.INVALID_VALUE, KMType.INVALID_VALUE, secretLength, false); + // Get the KeyObject from the operation and update the key with the secret key material. KMKeyObject keyObj = operation.getKeyObject(); RSAPrivateKey key = (RSAPrivateKey) ((KeyPair)(keyObj.getKeyObjectInstance())).getPrivate(); key.setExponent(secret, secretStart, secretLength); diff --git a/Applet/AndroidSEProviderLib/src/com/android/javacard/seprovider/KMPoolManager.java b/Applet/AndroidSEProviderLib/src/com/android/javacard/seprovider/KMPoolManager.java index 6e9ca210..9db4d0fb 100644 --- a/Applet/AndroidSEProviderLib/src/com/android/javacard/seprovider/KMPoolManager.java +++ b/Applet/AndroidSEProviderLib/src/com/android/javacard/seprovider/KMPoolManager.java @@ -454,8 +454,9 @@ public KMOperation getOperationImpl(short purpose, short alg, short strongboxAlg } if (pool[index] == null) { // Create one of the instance (Cipher / Signer / KeyAgreement] based on purpose. + Object cipherObject = createInstance(purpose, alg); JCSystem.beginTransaction(); - pool[index] = createInstance(purpose, alg); + pool[index] = cipherObject; JCSystem.commitTransaction(); reserveOperation(operation, purpose, strongboxAlgType, padding, blockMode, macLength, pool[index], keyObject); @@ -485,9 +486,9 @@ public KMKeyObject getKeyObjectFromPool(short alg, short secretLength, short max KMException.throwIt(KMError.TOO_MANY_OPERATIONS); } if (keysPool[index] == null) { + keyObject = createKeyObjectInstance(algo); JCSystem.beginTransaction(); - keysPool[index] = createKeyObjectInstance(algo); - keyObject = (KMKeyObject) keysPool[index]; + keysPool[index] = keyObject; JCSystem.commitTransaction(); break; } diff --git a/Applet/src/com/android/javacard/keymaster/KMKeymasterApplet.java b/Applet/src/com/android/javacard/keymaster/KMKeymasterApplet.java index bd269dc1..a14933e3 100644 --- a/Applet/src/com/android/javacard/keymaster/KMKeymasterApplet.java +++ b/Applet/src/com/android/javacard/keymaster/KMKeymasterApplet.java @@ -808,20 +808,20 @@ private short createKeyBlobExp(short version) { case (short) 0: // Old KeyBlob has a maximum of 5 elements. keyBlob = KMArray.instance(ASYM_KEY_BLOB_SIZE_V0); - KMArray.cast(keyBlob).add((short) 0, byteBlobExp); - KMArray.cast(keyBlob).add((short) 1, byteBlobExp); - KMArray.cast(keyBlob).add((short) 2, byteBlobExp); - KMArray.cast(keyBlob).add((short) 3, keyChar); - KMArray.cast(keyBlob).add((short) 4, byteBlobExp); + KMArray.cast(keyBlob).add((short) 0, byteBlobExp);// Secret + KMArray.cast(keyBlob).add((short) 1, byteBlobExp);// Nonce + KMArray.cast(keyBlob).add((short) 2, byteBlobExp);// AuthTag + KMArray.cast(keyBlob).add((short) 3, keyChar);// KeyChars + KMArray.cast(keyBlob).add((short) 4, byteBlobExp);// PubKey break; case (short) 1: keyBlob = KMArray.instance(ASYM_KEY_BLOB_SIZE_V1); - KMArray.cast(keyBlob).add((short) 0, KMInteger.exp()); - KMArray.cast(keyBlob).add((short) 1, byteBlobExp); - KMArray.cast(keyBlob).add((short) 2, byteBlobExp); - KMArray.cast(keyBlob).add((short) 3, byteBlobExp); - KMArray.cast(keyBlob).add((short) 4, keyChar); - KMArray.cast(keyBlob).add((short) 5, byteBlobExp); + KMArray.cast(keyBlob).add((short) 0, KMInteger.exp());// Version + KMArray.cast(keyBlob).add((short) 1, byteBlobExp);// Secret + KMArray.cast(keyBlob).add((short) 2, byteBlobExp);// Nonce + KMArray.cast(keyBlob).add((short) 3, byteBlobExp);// AuthTag + KMArray.cast(keyBlob).add((short) 4, keyChar);// KeyChars + KMArray.cast(keyBlob).add((short) 5, byteBlobExp);// PubKey break; case (short) 2: keyBlob = KMArray.instance(ASYM_KEY_BLOB_SIZE_V2); @@ -3031,9 +3031,6 @@ private void validateImportKey(short params, short keyFmt){ } private void importKey(APDU apdu, short keyFmt, byte[] scratchPad) { - // Take backup of the KeyParams before they get updated. The original - // key params are required to generate MAC in macKeyParams() function. - short keyParams = data[KEY_PARAMETERS]; validateImportKey(data[KEY_PARAMETERS], keyFmt); // Check algorithm and dispatch to appropriate handler. short alg = KMEnumTag.getValue(KMType.ALGORITHM, data[KEY_PARAMETERS]); @@ -3943,10 +3940,10 @@ private void decodeKeyBlob(short version, short keyBlob) { short minArraySize = 0; switch(version) { case 0: - minArraySize = (short) 4; + minArraySize = SYM_KEY_BLOB_SIZE_V0; break; case 1: - minArraySize = (short) 5; + minArraySize = SYM_KEY_BLOB_SIZE_V1; break; case 2: minArraySize = SYM_KEY_BLOB_SIZE_V2; @@ -3975,12 +3972,39 @@ private void processDecryptSecret(short version, short appId, short appData, byt short keyBlobSecretOff = 0; switch(version) { case 0: + // V0 KeyBlob + // KEY_BLOB = [ + // SECRET, + // NONCE, + // AUTH_TAG, + // KEY_CHARACTERISTICS, + // PUBKEY + // ] keyBlobSecretOff = (short) 0; break; case 1: + // V1 KeyBlob + // KEY_BLOB = [ + // VERSION, + // SECRET, + // NONCE, + // AUTH_TAG, + // KEY_CHARACTERISTICS, + // PUBKEY + // ] keyBlobSecretOff = (short) 1; break; case 2: + // V2 KeyBlob + // KEY_BLOB = [ + // VERSION, + // SECRET, + // NONCE, + // AUTH_TAG, + // KEY_CHARACTERISTICS, + // CUSTOM_TAGS, + // PUBKEY + // ] keyBlobSecretOff = KEY_BLOB_SECRET; break; default: @@ -4216,21 +4240,6 @@ private short addIntegers(short authTime, short timeStamp, byte[] scratchPad) { return KMInteger.uint_64(scratchPad, (short) 16); } - private void add(byte[] buf, short op1, short op2, short result) { - byte index = 7; - byte carry = 0; - short tmp; - while (index >= 0) { - tmp = (short) (buf[(short) (op1 + index)] + buf[(short) (op2 + index)] + carry); - carry = 0; - if (tmp > 255) { - carry = 1; // max unsigned byte value is 255 - } - buf[(short) (result + index)] = (byte) (tmp & (byte) 0xFF); - index--; - } - } - public void powerReset() { //TODO handle power reset signal. releaseAllOperations(); From 1fff08ae92c997c0a335c58477a339c488878cb0 Mon Sep 17 00:00:00 2001 From: Subrahmanyaman Date: Tue, 26 Apr 2022 17:30:54 +0000 Subject: [PATCH 8/8] Added Comments --- .../javacard/keymaster/KMKeymasterApplet.java | 71 +++++++++++-------- 1 file changed, 40 insertions(+), 31 deletions(-) diff --git a/Applet/src/com/android/javacard/keymaster/KMKeymasterApplet.java b/Applet/src/com/android/javacard/keymaster/KMKeymasterApplet.java index bd269dc1..a14933e3 100644 --- a/Applet/src/com/android/javacard/keymaster/KMKeymasterApplet.java +++ b/Applet/src/com/android/javacard/keymaster/KMKeymasterApplet.java @@ -808,20 +808,20 @@ private short createKeyBlobExp(short version) { case (short) 0: // Old KeyBlob has a maximum of 5 elements. keyBlob = KMArray.instance(ASYM_KEY_BLOB_SIZE_V0); - KMArray.cast(keyBlob).add((short) 0, byteBlobExp); - KMArray.cast(keyBlob).add((short) 1, byteBlobExp); - KMArray.cast(keyBlob).add((short) 2, byteBlobExp); - KMArray.cast(keyBlob).add((short) 3, keyChar); - KMArray.cast(keyBlob).add((short) 4, byteBlobExp); + KMArray.cast(keyBlob).add((short) 0, byteBlobExp);// Secret + KMArray.cast(keyBlob).add((short) 1, byteBlobExp);// Nonce + KMArray.cast(keyBlob).add((short) 2, byteBlobExp);// AuthTag + KMArray.cast(keyBlob).add((short) 3, keyChar);// KeyChars + KMArray.cast(keyBlob).add((short) 4, byteBlobExp);// PubKey break; case (short) 1: keyBlob = KMArray.instance(ASYM_KEY_BLOB_SIZE_V1); - KMArray.cast(keyBlob).add((short) 0, KMInteger.exp()); - KMArray.cast(keyBlob).add((short) 1, byteBlobExp); - KMArray.cast(keyBlob).add((short) 2, byteBlobExp); - KMArray.cast(keyBlob).add((short) 3, byteBlobExp); - KMArray.cast(keyBlob).add((short) 4, keyChar); - KMArray.cast(keyBlob).add((short) 5, byteBlobExp); + KMArray.cast(keyBlob).add((short) 0, KMInteger.exp());// Version + KMArray.cast(keyBlob).add((short) 1, byteBlobExp);// Secret + KMArray.cast(keyBlob).add((short) 2, byteBlobExp);// Nonce + KMArray.cast(keyBlob).add((short) 3, byteBlobExp);// AuthTag + KMArray.cast(keyBlob).add((short) 4, keyChar);// KeyChars + KMArray.cast(keyBlob).add((short) 5, byteBlobExp);// PubKey break; case (short) 2: keyBlob = KMArray.instance(ASYM_KEY_BLOB_SIZE_V2); @@ -3031,9 +3031,6 @@ private void validateImportKey(short params, short keyFmt){ } private void importKey(APDU apdu, short keyFmt, byte[] scratchPad) { - // Take backup of the KeyParams before they get updated. The original - // key params are required to generate MAC in macKeyParams() function. - short keyParams = data[KEY_PARAMETERS]; validateImportKey(data[KEY_PARAMETERS], keyFmt); // Check algorithm and dispatch to appropriate handler. short alg = KMEnumTag.getValue(KMType.ALGORITHM, data[KEY_PARAMETERS]); @@ -3943,10 +3940,10 @@ private void decodeKeyBlob(short version, short keyBlob) { short minArraySize = 0; switch(version) { case 0: - minArraySize = (short) 4; + minArraySize = SYM_KEY_BLOB_SIZE_V0; break; case 1: - minArraySize = (short) 5; + minArraySize = SYM_KEY_BLOB_SIZE_V1; break; case 2: minArraySize = SYM_KEY_BLOB_SIZE_V2; @@ -3975,12 +3972,39 @@ private void processDecryptSecret(short version, short appId, short appData, byt short keyBlobSecretOff = 0; switch(version) { case 0: + // V0 KeyBlob + // KEY_BLOB = [ + // SECRET, + // NONCE, + // AUTH_TAG, + // KEY_CHARACTERISTICS, + // PUBKEY + // ] keyBlobSecretOff = (short) 0; break; case 1: + // V1 KeyBlob + // KEY_BLOB = [ + // VERSION, + // SECRET, + // NONCE, + // AUTH_TAG, + // KEY_CHARACTERISTICS, + // PUBKEY + // ] keyBlobSecretOff = (short) 1; break; case 2: + // V2 KeyBlob + // KEY_BLOB = [ + // VERSION, + // SECRET, + // NONCE, + // AUTH_TAG, + // KEY_CHARACTERISTICS, + // CUSTOM_TAGS, + // PUBKEY + // ] keyBlobSecretOff = KEY_BLOB_SECRET; break; default: @@ -4216,21 +4240,6 @@ private short addIntegers(short authTime, short timeStamp, byte[] scratchPad) { return KMInteger.uint_64(scratchPad, (short) 16); } - private void add(byte[] buf, short op1, short op2, short result) { - byte index = 7; - byte carry = 0; - short tmp; - while (index >= 0) { - tmp = (short) (buf[(short) (op1 + index)] + buf[(short) (op2 + index)] + carry); - carry = 0; - if (tmp > 255) { - carry = 1; // max unsigned byte value is 255 - } - buf[(short) (result + index)] = (byte) (tmp & (byte) 0xFF); - index--; - } - } - public void powerReset() { //TODO handle power reset signal. releaseAllOperations();