diff --git a/Applet/JCardSimProvider/test/com/android/javacard/test/KMFunctionalTest.java b/Applet/JCardSimProvider/test/com/android/javacard/test/KMFunctionalTest.java index 670039c8..a5b17a65 100644 --- a/Applet/JCardSimProvider/test/com/android/javacard/test/KMFunctionalTest.java +++ b/Applet/JCardSimProvider/test/com/android/javacard/test/KMFunctionalTest.java @@ -991,6 +991,43 @@ private ResponseAPDU provisionSeLocked(CardSimulator simulator) { return response; } + private ResponseAPDU computeSharedSecret(CardSimulator simulator) { + short ret = getHmacSharingParams(); + short error = KMInteger.cast(KMArray.cast(ret).get((short) 0)).getShort(); + KMHmacSharingParameters params = KMHmacSharingParameters.cast(KMArray.cast(ret).get((short) 1)); + short seed = params.getSeed(); + short nonce = params.getNonce(); + + short params1 = KMHmacSharingParameters.instance(); + KMHmacSharingParameters.cast(params1).setSeed(KMByteBlob.instance((short) 0)); + short num = KMByteBlob.instance((short) 32); + Util.arrayCopyNonAtomic( + KMByteBlob.cast(nonce).getBuffer(), + KMByteBlob.cast(nonce).getStartOff(), + KMByteBlob.cast(num).getBuffer(), + KMByteBlob.cast(num).getStartOff(), + KMByteBlob.cast(num).length()); + + KMHmacSharingParameters.cast(params1).setNonce(num); + short params2 = KMHmacSharingParameters.instance(); + KMHmacSharingParameters.cast(params2).setSeed(KMByteBlob.instance((short) 0)); + num = KMByteBlob.instance((short) 32); + cryptoProvider.newRandomNumber( + KMByteBlob.cast(num).getBuffer(), + KMByteBlob.cast(num).getStartOff(), + KMByteBlob.cast(num).length()); + KMHmacSharingParameters.cast(params2).setNonce(num); + short arr = KMArray.instance((short) 2); + KMArray.cast(arr).add((short) 0, params1); + KMArray.cast(arr).add((short) 1, params2); + short arrPtr = KMArray.instance((short) 1); + KMArray.cast(arrPtr).add((short) 0, arr); + CommandAPDU apdu = encodeApdu((byte) INS_COMPUTE_SHARED_HMAC_CMD, arrPtr); + // print(commandAPDU.getBytes()); + ResponseAPDU response = simulator.transmitCommand(apdu); + return response; + } + private void provisionCmd(CardSimulator simulator) { Assert.assertEquals(0x9000, provisionSigningKey(simulator).getSW()); Assert.assertEquals(0x9000, provisionSigningCertificate(simulator).getSW()); @@ -1004,6 +1041,8 @@ private void provisionCmd(CardSimulator simulator) { setAndroidOSSystemProperties(simulator, (short) OS_VERSION, (short) OS_PATCH_LEVEL, (short) VENDOR_PATCH_LEVEL); Assert.assertEquals(0x9000, provisionLocked(simulator).getSW()); + // negotiate shared secret. + Assert.assertEquals(0x9000, computeSharedSecret(simulator).getSW()); } private void cleanUp() { @@ -1575,6 +1614,7 @@ public void testRateLimitClearBufferAfterReboot() { setBootParams(simulator, (short) BOOT_PATCH_LEVEL); setAndroidOSSystemProperties(simulator, (short) OS_VERSION, (short) OS_PATCH_LEVEL, (short) VENDOR_PATCH_LEVEL); + computeSharedSecret(simulator); } short rsaKeyArr = generateRsaKey(null, null, KMInteger.uint_8((byte) 1)); Assert.assertEquals(KMInteger.cast(KMArray.cast(rsaKeyArr).get((short) 0)).getShort(), @@ -3230,6 +3270,7 @@ public void testVerifyOemUnLockAfterOemLockSuccess() { // set android system properties setAndroidOSSystemProperties(simulator, (short) OS_VERSION, (short) OS_PATCH_LEVEL, (short) VENDOR_PATCH_LEVEL); + computeSharedSecret(simulator); Assert.assertEquals(0x9000, provisionOemUnLock(simulator).getSW()); Assert.assertEquals(0x9000, provisionSharedSecret(simulator).getSW()); Assert.assertEquals(0x9000, provisionAttestIds(simulator).getSW()); @@ -3339,6 +3380,8 @@ public void testVerifyOemProvisionAfterOemLockFailure() { Assert.assertEquals(0x9000, provisionAttestIds(simulator).getSW()); Assert.assertEquals(0x9000, provisionOEMRootPublicKey(simulator).getSW()); Assert.assertEquals(0x9000, provisionLocked(simulator).getSW()); + // set bootup parameters + setBootParams(simulator, (short) BOOT_PATCH_LEVEL); ResponseAPDU response = provisionSharedSecret(simulator); Assert.assertEquals(0x9000, response.getSW()); byte[] respBuf = response.getBytes(); @@ -3465,6 +3508,7 @@ public void testUpgradeKey() { setBootParams(simulator, (short) test_data[i][3]); setAndroidOSSystemProperties(simulator, (short) test_data[i][0], (short) test_data[i][1], (short) test_data[i][2]); + computeSharedSecret(simulator); ret = upgradeKey( KMByteBlob.instance(keyBlob, (short) 0, (short) keyBlob.length), null, null, test_data[i][5]); diff --git a/Applet/src/com/android/javacard/keymaster/KMKeymasterApplet.java b/Applet/src/com/android/javacard/keymaster/KMKeymasterApplet.java index 1c55d5b1..cda3a989 100644 --- a/Applet/src/com/android/javacard/keymaster/KMKeymasterApplet.java +++ b/Applet/src/com/android/javacard/keymaster/KMKeymasterApplet.java @@ -237,6 +237,7 @@ public class KMKeymasterApplet extends Applet implements AppletEvent, ExtendedLe // INS_ADD_RNG_ENTROPY_CMD // INS_COMPUTE_SHARED_HMAC_CMD // INS_GET_HMAC_SHARING_PARAM_CMD + // INS_EARLY_BOOT_ENDED public static final byte SET_BOOT_PARAMS_SUCCESS = 0x01; public static final byte SET_SYSTEM_PROPERTIES_SUCCESS = 0x02; public static final byte NEGOTIATED_SHARED_SECRET_SUCCESS = 0x04; @@ -596,16 +597,6 @@ && isProvisioningComplete())) { case INS_OEM_UNLOCK_PROVISIONING_CMD: processOEMUnlockProvisionCmd(apdu); break; - case INS_PROVISION_ATTEST_IDS_CMD: - case INS_PROVISION_ATTESTATION_KEY_CMD: - case INS_PROVISION_ATTESTATION_CERT_DATA_CMD: - case INS_PROVISION_OEM_ROOT_PUBLIC_KEY_CMD: - case INS_PROVISION_PRESHARED_SECRET_CMD: - case INS_SE_FACTORY_LOCK_PROVISIONING_CMD: - case INS_OEM_LOCK_PROVISIONING_CMD: - // Provision commands are not allowed in ACTIVE_STATE - ISOException.throwIt(ISO7816.SW_COMMAND_NOT_ALLOWED); - break; default: ISOException.throwIt(ISO7816.SW_INS_NOT_SUPPORTED); } @@ -642,10 +633,21 @@ private boolean isKeymasterReady(byte apduIns) { // Keymaster is ready to execute all the commands. return true; } - // Below commands are allowed even if the Keymaster is not ready. switch (apduIns) { + case INS_PROVISION_ATTEST_IDS_CMD: + case INS_PROVISION_ATTESTATION_KEY_CMD: + case INS_PROVISION_ATTESTATION_CERT_DATA_CMD: + case INS_PROVISION_OEM_ROOT_PUBLIC_KEY_CMD: + case INS_PROVISION_PRESHARED_SECRET_CMD: + case INS_SE_FACTORY_LOCK_PROVISIONING_CMD: + case INS_OEM_LOCK_PROVISIONING_CMD: + // Provision commands are not allowed in ACTIVE_STATE + ISOException.throwIt(ISO7816.SW_COMMAND_NOT_ALLOWED); + break; + // Below commands are allowed even if the Keymaster is not ready. case INS_GET_HW_INFO_CMD: case INS_ADD_RNG_ENTROPY_CMD: + case INS_EARLY_BOOT_ENDED_CMD: case INS_GET_HMAC_SHARING_PARAM_CMD: case INS_COMPUTE_SHARED_HMAC_CMD: case INS_SET_VERSION_PATCHLEVEL_CMD: @@ -765,7 +767,12 @@ private void processDeviceLockedCmd(APDU apdu) { data[VERIFICATION_TOKEN] = KMArray.cast(tmpVariables[0]).get((short) 1); validateVerificationToken(data[VERIFICATION_TOKEN], scratchPad); short verTime = KMVerificationToken.cast(data[VERIFICATION_TOKEN]).getTimestamp(); - short lastDeviceLockedTime = repository.getDeviceTimeStamp(); + short lastDeviceLockedTime; + try { + lastDeviceLockedTime = repository.getDeviceTimeStamp(); + } catch (KMException e) { + lastDeviceLockedTime = KMInteger.uint_8((byte) 0); + } if (KMInteger.compare(verTime, lastDeviceLockedTime) > 0) { Util.arrayFillNonAtomic(scratchPad, (short) 0, KMInteger.UINT_64, (byte) 0); KMInteger.cast(verTime).getValue(scratchPad, (short) 0, KMInteger.UINT_64);