diff --git a/Applet/JCardSimProvider/test/com/android/javacard/test/KMFunctionalTest.java b/Applet/JCardSimProvider/test/com/android/javacard/test/KMFunctionalTest.java index 9e9c2c6c..517afb7f 100644 --- a/Applet/JCardSimProvider/test/com/android/javacard/test/KMFunctionalTest.java +++ b/Applet/JCardSimProvider/test/com/android/javacard/test/KMFunctionalTest.java @@ -92,6 +92,7 @@ public class KMFunctionalTest { private static final byte INS_SET_BOOT_PARAMS_CMD = INS_BEGIN_KM_CMD + 6; //0x06 private static final byte INS_LOCK_PROVISIONING_CMD = INS_BEGIN_KM_CMD + 7; //0x07 private static final byte INS_GET_PROVISION_STATUS_CMD = INS_BEGIN_KM_CMD + 8; //0x08 + private static final byte INS_SET_VERSION_PATCHLEVEL_CMD = INS_BEGIN_KM_CMD + 9; //0x09 // Top 32 commands are reserved for provisioning. private static final byte INS_END_KM_PROVISION_CMD = 0x20; @@ -473,8 +474,8 @@ private void init() { provisionCmd(simulator); } - private void setBootParams(CardSimulator simulator, short osVersion, - short osPatchLevel, short vendorPatchLevel, short bootPatchLevel) { + private void setAndroidOSSystemProperties(CardSimulator simulator, short osVersion, + short osPatchLevel, short vendorPatchLevel) { // Argument 1 OS Version short versionPtr = KMInteger.uint_16(osVersion); // short versionTagPtr = KMIntegerTag.instance(KMType.UINT_TAG, @@ -482,31 +483,43 @@ private void setBootParams(CardSimulator simulator, short osVersion, // Argument 2 OS Patch level short patchPtr = KMInteger.uint_16(osPatchLevel); short vendorpatchPtr = KMInteger.uint_16((short) vendorPatchLevel); + // Arguments + short arrPtr = KMArray.instance((short) 3); + KMArray vals = KMArray.cast(arrPtr); + vals.add((short) 0, versionPtr); + vals.add((short) 1, patchPtr); + vals.add((short) 2, vendorpatchPtr); + CommandAPDU apdu = encodeApdu((byte) INS_SET_VERSION_PATCHLEVEL_CMD, arrPtr); + // print(commandAPDU.getBytes()); + ResponseAPDU response = simulator.transmitCommand(apdu); + Assert.assertEquals(0x9000, response.getSW()); + + } + + private void setBootParams(CardSimulator simulator, short bootPatchLevel) { + // Argument 0 boot patch level short bootpatchPtr = KMInteger.uint_16((short) bootPatchLevel); - // Argument 3 Verified Boot Key + // Argument 1 Verified Boot Key byte[] bootKeyHash = "00011122233344455566677788899900".getBytes(); short bootKeyPtr = KMByteBlob.instance(bootKeyHash, (short) 0, (short) bootKeyHash.length); - // Argument 4 Verified Boot Hash + // Argument 2 Verified Boot Hash short bootHashPtr = KMByteBlob.instance(bootKeyHash, (short) 0, (short) bootKeyHash.length); - // Argument 5 Verified Boot State + // Argument 3 Verified Boot State short bootStatePtr = KMEnum.instance(KMType.VERIFIED_BOOT_STATE, KMType.VERIFIED_BOOT); - // Argument 6 Device Locked + // Argument 4 Device Locked short deviceLockedPtr = KMEnum.instance(KMType.DEVICE_LOCKED, KMType.DEVICE_LOCKED_FALSE); // Arguments - short arrPtr = KMArray.instance((short) 8); + short arrPtr = KMArray.instance((short) 5); KMArray vals = KMArray.cast(arrPtr); - vals.add((short) 0, versionPtr); - vals.add((short) 1, patchPtr); - vals.add((short) 2, vendorpatchPtr); - vals.add((short) 3, bootpatchPtr); - vals.add((short) 4, bootKeyPtr); - vals.add((short) 5, bootHashPtr); - vals.add((short) 6, bootStatePtr); - vals.add((short) 7, deviceLockedPtr); + vals.add((short) 0, bootpatchPtr); + vals.add((short) 1, bootKeyPtr); + vals.add((short) 2, bootHashPtr); + vals.add((short) 3, bootStatePtr); + vals.add((short) 4, deviceLockedPtr); CommandAPDU apdu = encodeApdu((byte) INS_SET_BOOT_PARAMS_CMD, arrPtr); // print(commandAPDU.getBytes()); ResponseAPDU response = simulator.transmitCommand(apdu); @@ -661,8 +674,10 @@ private void provisionCmd(CardSimulator simulator) { provisionSharedSecret(simulator); provisionAttestIds(simulator); // set bootup parameters - setBootParams(simulator, (short) OS_VERSION, (short) OS_PATCH_LEVEL, - (short) VENDOR_PATCH_LEVEL, (short) BOOT_PATCH_LEVEL); + setBootParams(simulator, (short) BOOT_PATCH_LEVEL); + // set android system properties + setAndroidOSSystemProperties(simulator, (short) OS_VERSION, (short) OS_PATCH_LEVEL, + (short) VENDOR_PATCH_LEVEL); provisionLocked(simulator); } @@ -2722,11 +2737,12 @@ public void testUpgradeKey() { {0, OS_PATCH_LEVEL+1, VENDOR_PATCH_LEVEL-1, BOOT_PATCH_LEVEL+1, NO_UPGRADE, KMError.INVALID_ARGUMENT }, }; for (int i = 0; i < test_data.length; i++) { - setBootParams(simulator, (short) test_data[i][0], (short) test_data[i][1], - (short) test_data[i][2], (short) test_data[i][3]); + setAndroidOSSystemProperties(simulator, (short) test_data[i][0], (short) test_data[i][1], + (short) test_data[i][2]); + setBootParams(simulator, (short) test_data[i][3]); ret = upgradeKey( - KMByteBlob.instance(keyBlob, (short) 0, (short) keyBlob.length), - null, null, test_data[i][5]); + KMByteBlob.instance(keyBlob, (short) 0, (short) keyBlob.length), + null, null, test_data[i][5]); if (test_data[i][5] != KMError.OK) continue; keyBlobPtr = KMArray.cast(ret).get((short) 1); @@ -2738,27 +2754,27 @@ public void testUpgradeKey() { ret = getKeyCharacteristics(keyBlobPtr); keyCharacteristics = KMArray.cast(ret).get((short) 1); hwParams = KMKeyCharacteristics.cast(keyCharacteristics) - .getHardwareEnforced(); + .getHardwareEnforced(); osVersion = KMKeyParameters.findTag(KMType.UINT_TAG, KMType.OS_VERSION, - hwParams); + hwParams); osVersion = KMIntegerTag.cast(osVersion).getValue(); osPatch = KMKeyParameters.findTag(KMType.UINT_TAG, - KMType.OS_PATCH_LEVEL, hwParams); + KMType.OS_PATCH_LEVEL, hwParams); osPatch = KMIntegerTag.cast(osPatch).getValue(); short ptr = KMKeyParameters.findTag(KMType.UINT_TAG, - KMType.VENDOR_PATCH_LEVEL, hwParams); + KMType.VENDOR_PATCH_LEVEL, hwParams); short vendorPatchLevel = KMIntegerTag.cast(ptr).getValue(); ptr = KMKeyParameters.findTag(KMType.UINT_TAG, KMType.BOOT_PATCH_LEVEL, - hwParams); + hwParams); short bootPatchLevel = KMIntegerTag.cast(ptr).getValue(); Assert.assertEquals(KMInteger.cast(osVersion).getShort(), - test_data[i][0]); + test_data[i][0]); Assert.assertEquals(KMInteger.cast(osPatch).getShort(), - test_data[i][1]); + test_data[i][1]); Assert.assertEquals(KMInteger.cast(vendorPatchLevel).getShort(), - test_data[i][2]); + test_data[i][2]); Assert.assertEquals(KMInteger.cast(bootPatchLevel).getShort(), - test_data[i][3]); + test_data[i][3]); } } cleanUp(); diff --git a/Applet/src/com/android/javacard/keymaster/KMKeymasterApplet.java b/Applet/src/com/android/javacard/keymaster/KMKeymasterApplet.java index b1a78178..2f3e187f 100644 --- a/Applet/src/com/android/javacard/keymaster/KMKeymasterApplet.java +++ b/Applet/src/com/android/javacard/keymaster/KMKeymasterApplet.java @@ -85,6 +85,7 @@ public class KMKeymasterApplet extends Applet implements AppletEvent, ExtendedLe private static final byte INS_SET_BOOT_PARAMS_CMD = INS_BEGIN_KM_CMD + 6; //0x06 private static final byte INS_LOCK_PROVISIONING_CMD = INS_BEGIN_KM_CMD + 7; //0x07 private static final byte INS_GET_PROVISION_STATUS_CMD = INS_BEGIN_KM_CMD + 8; //0x08 + private static final byte INS_SET_VERSION_PATCHLEVEL_CMD = INS_BEGIN_KM_CMD + 9; //0x09 // Top 32 commands are reserved for provisioning. private static final byte INS_END_KM_PROVISION_CMD = 0x20; @@ -467,6 +468,9 @@ && isProvisioningComplete())) { case INS_GET_CERT_CHAIN_CMD: processGetCertChainCmd(apdu); break; + case INS_SET_VERSION_PATCHLEVEL_CMD: + processSetVersionAndPatchLevels(apdu); + break; default: ISOException.throwIt(ISO7816.SW_INS_NOT_SUPPORTED); } @@ -641,6 +645,47 @@ private void processAddRngEntropyCmd(APDU apdu) { sendError(apdu, KMError.OK); } + private void processSetVersionAndPatchLevels(APDU apdu) { + receiveIncoming(apdu); + byte[] scratchPad = apdu.getBuffer(); + // Argument 1 OS Version + tmpVariables[0] = KMInteger.exp(); + // Argument 2 OS Patch level + tmpVariables[1] = KMInteger.exp(); + // Argument 3 Vendor Patch level + tmpVariables[2] = KMInteger.exp(); + // Array of expected arguments + short argsProto = KMArray.instance((short) 3); + KMArray.cast(argsProto).add((short) 0, tmpVariables[0]); + KMArray.cast(argsProto).add((short) 1, tmpVariables[1]); + KMArray.cast(argsProto).add((short) 2, tmpVariables[2]); + // Decode the arguments + short args = decoder.decode(argsProto, (byte[]) bufferRef[0], bufferProp[BUF_START_OFFSET], bufferProp[BUF_LEN_OFFSET]); + //reclaim memory + repository.reclaimMemory(bufferProp[BUF_LEN_OFFSET]); + + tmpVariables[0] = KMArray.cast(args).get((short) 0); + tmpVariables[1] = KMArray.cast(args).get((short) 1); + tmpVariables[2] = KMArray.cast(args).get((short) 2); + + repository.setOsVersion( + KMInteger.cast(tmpVariables[0]).getBuffer(), + KMInteger.cast(tmpVariables[0]).getStartOff(), + KMInteger.cast(tmpVariables[0]).length()); + + repository.setOsPatch( + KMInteger.cast(tmpVariables[1]).getBuffer(), + KMInteger.cast(tmpVariables[1]).getStartOff(), + KMInteger.cast(tmpVariables[1]).length()); + + repository.setVendorPatchLevel( + KMInteger.cast(tmpVariables[2]).getBuffer(), + KMInteger.cast(tmpVariables[2]).getStartOff(), + KMInteger.cast(tmpVariables[2]).length()); + + sendError(apdu, KMError.OK); + } + private void processGetCertChainCmd(APDU apdu) { // Make the response tmpVariables[0] = seProvider.getCertificateChainLength(); @@ -3135,32 +3180,23 @@ private void updateKeyParameters(byte[] ptrArr, short len) { private void processSetBootParamsCmd(APDU apdu) { receiveIncoming(apdu); byte[] scratchPad = apdu.getBuffer(); - // Argument 1 OS Version + // Argument 0 Boot Patch level tmpVariables[0] = KMInteger.exp(); - // Argument 2 OS Patch level - tmpVariables[1] = KMInteger.exp(); - // Argument 3 Vendor Patch level - tmpVariables[2] = KMInteger.exp(); - // Argument 4 Boot Patch level - tmpVariables[3] = KMInteger.exp(); - // Argument 5 Verified Boot Key - tmpVariables[4] = KMByteBlob.exp(); - // Argument 6 Verified Boot Hash - tmpVariables[5] = KMByteBlob.exp(); - // Argument 7 Verified Boot State - tmpVariables[6] = KMEnum.instance(KMType.VERIFIED_BOOT_STATE); - // Argument 8 Device Locked - tmpVariables[7] = KMEnum.instance(KMType.DEVICE_LOCKED); - // Array of expected arguments - short argsProto = KMArray.instance((short) 8); + // Argument 1 Verified Boot Key + tmpVariables[1] = KMByteBlob.exp(); + // Argument 2 Verified Boot Hash + tmpVariables[2] = KMByteBlob.exp(); + // Argument 3 Verified Boot State + tmpVariables[3] = KMEnum.instance(KMType.VERIFIED_BOOT_STATE); + // Argument 4 Device Locked + tmpVariables[4] = KMEnum.instance(KMType.DEVICE_LOCKED); + // Array of e4pected arguments + short argsProto = KMArray.instance((short) 5); KMArray.cast(argsProto).add((short) 0, tmpVariables[0]); KMArray.cast(argsProto).add((short) 1, tmpVariables[1]); KMArray.cast(argsProto).add((short) 2, tmpVariables[2]); KMArray.cast(argsProto).add((short) 3, tmpVariables[3]); KMArray.cast(argsProto).add((short) 4, tmpVariables[4]); - KMArray.cast(argsProto).add((short) 5, tmpVariables[5]); - KMArray.cast(argsProto).add((short) 6, tmpVariables[6]); - KMArray.cast(argsProto).add((short) 7, tmpVariables[7]); // Decode the arguments short args = decoder.decode(argsProto, (byte[]) bufferRef[0], bufferProp[BUF_START_OFFSET], bufferProp[BUF_LEN_OFFSET]); //reclaim memory @@ -3171,51 +3207,38 @@ private void processSetBootParamsCmd(APDU apdu) { tmpVariables[2] = KMArray.cast(args).get((short) 2); tmpVariables[3] = KMArray.cast(args).get((short) 3); tmpVariables[4] = KMArray.cast(args).get((short) 4); - tmpVariables[5] = KMArray.cast(args).get((short) 5); - tmpVariables[6] = KMArray.cast(args).get((short) 6); - tmpVariables[7] = KMArray.cast(args).get((short) 7); - if (KMByteBlob.cast(tmpVariables[4]).length() > KMRepository.BOOT_KEY_MAX_SIZE) { + if (KMByteBlob.cast(tmpVariables[1]).length() > KMRepository.BOOT_KEY_MAX_SIZE) { KMException.throwIt(KMError.INVALID_ARGUMENT); } - if (KMByteBlob.cast(tmpVariables[5]).length() > KMRepository.BOOT_HASH_MAX_SIZE) { + if (KMByteBlob.cast(tmpVariables[2]).length() > KMRepository.BOOT_HASH_MAX_SIZE) { KMException.throwIt(KMError.INVALID_ARGUMENT); } - repository.setOsVersion( + repository.setBootPatchLevel( KMInteger.cast(tmpVariables[0]).getBuffer(), KMInteger.cast(tmpVariables[0]).getStartOff(), KMInteger.cast(tmpVariables[0]).length()); - repository.setOsPatch( - KMInteger.cast(tmpVariables[1]).getBuffer(), - KMInteger.cast(tmpVariables[1]).getStartOff(), - KMInteger.cast(tmpVariables[1]).length()); - - repository.setVendorPatchLevel( - KMInteger.cast(tmpVariables[2]).getBuffer(), - KMInteger.cast(tmpVariables[2]).getStartOff(), - KMInteger.cast(tmpVariables[2]).length()); - - repository.setBootPatchLevel( - KMInteger.cast(tmpVariables[3]).getBuffer(), - KMInteger.cast(tmpVariables[3]).getStartOff(), - KMInteger.cast(tmpVariables[3]).length()); repository.setVerifiedBootKey( - KMByteBlob.cast(tmpVariables[4]).getBuffer(), - KMByteBlob.cast(tmpVariables[4]).getStartOff(), - KMByteBlob.cast(tmpVariables[4]).length()); + KMByteBlob.cast(tmpVariables[1]).getBuffer(), + KMByteBlob.cast(tmpVariables[1]).getStartOff(), + KMByteBlob.cast(tmpVariables[1]).length()); repository.setVerifiedBootHash( - KMByteBlob.cast(tmpVariables[5]).getBuffer(), - KMByteBlob.cast(tmpVariables[5]).getStartOff(), - KMByteBlob.cast(tmpVariables[5]).length()); + KMByteBlob.cast(tmpVariables[2]).getBuffer(), + KMByteBlob.cast(tmpVariables[2]).getStartOff(), + KMByteBlob.cast(tmpVariables[2]).length()); - byte enumVal = KMEnum.cast(tmpVariables[6]).getVal(); + byte enumVal = KMEnum.cast(tmpVariables[3]).getVal(); repository.setBootState(enumVal); - enumVal = KMEnum.cast(tmpVariables[7]).getVal(); + enumVal = KMEnum.cast(tmpVariables[4]).getVal(); repository.setBootloaderLocked(enumVal == KMType.DEVICE_LOCKED_TRUE); + // Clear Android system properties expect boot patch level as it is + // already set. + repository.clearAndroidSystemProperties(); + // Clear the Computed SharedHmac and Hmac nonce from persistent memory. repository.clearComputedHmac(); repository.clearHmacNonce(); diff --git a/Applet/src/com/android/javacard/keymaster/KMRepository.java b/Applet/src/com/android/javacard/keymaster/KMRepository.java index 07caec72..c9fe8398 100644 --- a/Applet/src/com/android/javacard/keymaster/KMRepository.java +++ b/Applet/src/com/android/javacard/keymaster/KMRepository.java @@ -57,7 +57,7 @@ public class KMRepository implements KMUpgradable { public static final byte CERT_ISSUER = 10; public static final byte CERT_EXPIRY_TIME = 11; public static final byte BOOT_OS_VERSION = 12; - public static final byte BOOT_OS_PATCH = 13; + public static final byte BOOT_OS_PATCH_LEVEL = 13; public static final byte VENDOR_PATCH_LEVEL = 14; public static final byte BOOT_PATCH_LEVEL = 15; public static final byte BOOT_VERIFIED_BOOT_KEY = 16; @@ -532,7 +532,7 @@ public short getBootPatchLevel() { } public short getOsPatch() { - short blob = readData(BOOT_OS_PATCH); + short blob = readData(BOOT_OS_PATCH_LEVEL); if (blob != 0) { return KMInteger.uint_32( KMByteBlob.cast(blob).getBuffer(), KMByteBlob.cast(blob).getStartOff()); @@ -638,6 +638,14 @@ public void setBootPatchLevel(byte[] buf, short start, short len) { writeDataEntry(BOOT_PATCH_LEVEL, buf, start, len); } + public void clearAndroidSystemProperties() { + clearDataEntry(BOOT_OS_VERSION); + clearDataEntry(BOOT_OS_PATCH_LEVEL); + clearDataEntry(VENDOR_PATCH_LEVEL); + // Don't clear BOOT_PATCH_LEVEL as it is part of + // boot parameters. + } + public void setBootloaderLocked(boolean flag) { short start = alloc(DEVICE_LOCK_FLAG_SIZE); if (flag) { @@ -683,7 +691,7 @@ public void setOsPatch(byte[] buf, short start, short len) { if (len != OS_PATCH_SIZE) { KMException.throwIt(KMError.INVALID_INPUT_LENGTH); } - writeDataEntry(BOOT_OS_PATCH, buf, start, len); + writeDataEntry(BOOT_OS_PATCH_LEVEL, buf, start, len); } public void setVerifiedBootKey(byte[] buf, short start, short len) { diff --git a/HAL/keymaster/4.1/CommonUtils.cpp b/HAL/keymaster/4.1/CommonUtils.cpp index a6d2b7ab..090c8d0d 100644 --- a/HAL/keymaster/4.1/CommonUtils.cpp +++ b/HAL/keymaster/4.1/CommonUtils.cpp @@ -16,11 +16,15 @@ */ #include +#include +#include +#include #include #include #include #include #include +#include #include #include #include @@ -35,6 +39,13 @@ namespace keymaster { namespace V4_1 { namespace javacard { +constexpr char kVendorPatchlevelProp[] = "ro.vendor.build.security_patch"; +constexpr char kVendorPatchlevelRegex[] = "^([0-9]{4})-([0-9]{2})-([0-9]{2})$"; +constexpr size_t kYearMatch = 1; +constexpr size_t kMonthMatch = 2; +constexpr size_t kDayMatch = 3; +constexpr size_t kVendorPatchlevelMatchCount = kDayMatch + 1; + hidl_vec kmParamSet2Hidl(const keymaster_key_param_set_t& set) { hidl_vec result; if (set.length == 0 || set.params == nullptr) @@ -272,6 +283,70 @@ ErrorCode getCertificateChain(std::vector& chainBuffer, std::vector 12) { + LOG(ERROR) << "Invalid patch month " << month; + return 0; + } + bool isLeapYear = (0 == year % 4) ? true : false; + int maxDaysForMonth = 31; + switch(month) { + case 4: case 6: case 9: case 11: + maxDaysForMonth = 30; + break; + case 2: + maxDaysForMonth = isLeapYear ? 29 : 28; + break; + } + if (day < 1 || day > maxDaysForMonth) { + LOG(ERROR) << "Invalid patch day " << day; + return 0; + } + return year * 10000 + month * 100 + day; +} + +uint32_t GetVendorPatchlevel() { + std::string patchlevel = wait_and_get_property(kVendorPatchlevelProp); + return GetVendorPatchlevel(patchlevel.c_str()); +} + } // namespace javacard } // namespace V4_1 diff --git a/HAL/keymaster/4.1/JavacardKeymaster4Device.cpp b/HAL/keymaster/4.1/JavacardKeymaster4Device.cpp index eb8ccdd8..845071eb 100644 --- a/HAL/keymaster/4.1/JavacardKeymaster4Device.cpp +++ b/HAL/keymaster/4.1/JavacardKeymaster4Device.cpp @@ -92,6 +92,7 @@ enum class Instruction { INS_EARLY_BOOT_ENDED_CMD = INS_END_KM_PROVISION_CMD+21, INS_GET_CERT_CHAIN_CMD = INS_END_KM_PROVISION_CMD+22, INS_GET_PROVISION_STATUS_CMD = INS_BEGIN_KM_CMD+8, + INS_SET_VERSION_PATCHLEVEL_CMD = INS_BEGIN_KM_CMD+9, }; enum ProvisionStatus { @@ -438,13 +439,42 @@ ErrorCode sendData(Instruction ins, std::vector& inData, std::vector item; + std::vector cborOutData; + + array.add(GetOsVersion()). + add(GetOsPatchlevel()). + add(GetVendorPatchlevel()); + + std::vector cborData = array.encode(); + errorCode = sendData(Instruction::INS_SET_VERSION_PATCHLEVEL_CMD, cborData, cborOutData); + if (ErrorCode::OK == errorCode) { + //Skip last 2 bytes in cborData, it contains status. + std::tie(item, errorCode) = decodeData(cborConverter_, std::vector(cborOutData.begin(), cborOutData.end()-2), + true); + } + if (ErrorCode::OK != errorCode) + LOG(ERROR) << "Failed to set os_version, os_patchlevel and vendor_patchlevel err: " << (int32_t) errorCode; + + return errorCode; +} + JavacardKeymaster4Device::JavacardKeymaster4Device(): softKm_(new ::keymaster::AndroidKeymaster( []() -> auto { auto context = new JavaCardSoftKeymasterContext(); context->SetSystemVersion(GetOsVersion(), GetOsPatchlevel()); return context; }(), - kOperationTableSize)), oprCtx_(new OperationContext()) { + kOperationTableSize)), oprCtx_(new OperationContext()), isEachSystemPropertySet(false) { + // Send Android system properties like os_version, os_patchlevel and vendor_patchlevel + // to the Applet. Incase if setting system properties fails here, again try setting + // it from computeSharedHmac. + if (ErrorCode::OK == setAndroidSystemProperties(cborConverter_)) { + isEachSystemPropertySet = true; + } } @@ -524,10 +554,25 @@ Return JavacardKeymaster4Device::computeSharedHmac(const hidl_vec item; std::vector cborOutData; hidl_vec sharingCheck; - ErrorCode errorCode = ErrorCode::UNKNOWN_ERROR; std::vector tempVec; cppbor::Array outerArray; +#ifndef VTS_EMULATOR + // The Android system properties like OS_VERSION, OS_PATCHLEVEL and VENDOR_PATCHLEVEL are to + // be delivered to the Applet when the HAL is first loaded. Incase if settting system properties + // failed at construction time then this is one of the ideal places to send this information + // to the Applet as computeSharedHmac is called everytime when Android device boots. + if (!isEachSystemPropertySet) { + errorCode = setAndroidSystemProperties(cborConverter_); + if (ErrorCode::OK != errorCode) { + LOG(ERROR) << " Failed to set os_version, os_patchlevel and vendor_patchlevel err: " << (int32_t)errorCode; + _hidl_cb(errorCode, sharingCheck); + return Void(); + } + isEachSystemPropertySet = true; + } +#endif + for(size_t i = 0; i < params.size(); ++i) { cppbor::Array innerArray; innerArray.add(static_cast>(params[i].seed)); diff --git a/HAL/keymaster/Android.bp b/HAL/keymaster/Android.bp index 1bcc6e2c..92e3be8f 100644 --- a/HAL/keymaster/Android.bp +++ b/HAL/keymaster/Android.bp @@ -47,13 +47,14 @@ cc_binary { "libjc_common", "libcrypto", ], - product_variables: { - debuggable: { - cflags: [ - "-DVTS_EMULATOR", - ] - } - } + arch: { + x86_64: { + cflags: ["-DVTS_EMULATOR"], + }, + x86: { + cflags: ["-DVTS_EMULATOR"], + }, + }, } cc_library { diff --git a/HAL/keymaster/include/CommonUtils.h b/HAL/keymaster/include/CommonUtils.h index f08a60c3..b6612741 100644 --- a/HAL/keymaster/include/CommonUtils.h +++ b/HAL/keymaster/include/CommonUtils.h @@ -88,6 +88,8 @@ publicKey, EcCurve& eccurve); ErrorCode getCertificateChain(std::vector& chainBuffer, std::vector>& certChain); +uint32_t GetVendorPatchlevel(); + class KmParamSet : public keymaster_key_param_set_t { public: explicit KmParamSet(const hidl_vec& keyParams) diff --git a/HAL/keymaster/include/JavacardKeymaster4Device.h b/HAL/keymaster/include/JavacardKeymaster4Device.h index fcfdef0f..c8ada383 100644 --- a/HAL/keymaster/include/JavacardKeymaster4Device.h +++ b/HAL/keymaster/include/JavacardKeymaster4Device.h @@ -91,6 +91,7 @@ class JavacardKeymaster4Device : public IKeymasterDevice { private: std::unique_ptr<::keymaster::AndroidKeymaster> softKm_; std::unique_ptr oprCtx_; + bool isEachSystemPropertySet; }; } // namespace javacard diff --git a/ProvisioningTool/Provision.cpp b/ProvisioningTool/Provision.cpp index 45425975..92d76dbc 100644 --- a/ProvisioningTool/Provision.cpp +++ b/ProvisioningTool/Provision.cpp @@ -50,6 +50,7 @@ enum class Instruction { INS_SET_BOOT_PARAMS_CMD = INS_BEGIN_KM_CMD+6, INS_LOCK_PROVISIONING_CMD = INS_BEGIN_KM_CMD+7, INS_GET_PROVISION_STATUS_CMD = INS_BEGIN_KM_CMD+8, + INS_SET_VERSION_PATCHLEVEL_CMD = INS_BEGIN_KM_CMD+9, }; enum ProvisionStatus { @@ -325,17 +326,32 @@ ErrorCode Provision::provisionPreSharedSecret(std::vector& preSharedSec return errorCode; } -ErrorCode Provision::provisionBootParameters(BootParams& bootParams) { +ErrorCode Provision::setAndroidSystemProperties() { ErrorCode errorCode = ErrorCode::OK; cppbor::Array array; std::vector apdu; std::vector response; - Instruction ins = Instruction::INS_SET_BOOT_PARAMS_CMD; + Instruction ins = Instruction::INS_SET_VERSION_PATCHLEVEL_CMD; array.add(GetOsVersion()). add(GetOsPatchlevel()). - add(bootParams.vendorPatchLevel). - add(bootParams.bootPatchLevel). + add(GetVendorPatchlevel()); + std::vector cborData = array.encode(); + + if(ErrorCode::OK != (errorCode = sendProvisionData(pTransportFactory, ins, cborData, response))) { + return errorCode; + } + return errorCode; +} + +ErrorCode Provision::provisionBootParameters(BootParams& bootParams) { + ErrorCode errorCode = ErrorCode::OK; + cppbor::Array array; + std::vector apdu; + std::vector response; + Instruction ins = Instruction::INS_SET_BOOT_PARAMS_CMD; + + array.add(bootParams.bootPatchLevel). /* Verified Boot Key */ add(bootParams.verifiedBootKey). /* Verified Boot Hash */ diff --git a/ProvisioningTool/Provision.h b/ProvisioningTool/Provision.h index e541c496..68a7f1d1 100644 --- a/ProvisioningTool/Provision.h +++ b/ProvisioningTool/Provision.h @@ -25,10 +25,13 @@ namespace keymaster { namespace V4_1 { namespace javacard { -typedef struct BootParams_ { +typedef struct SystemProperties__ { uint32_t osVersion; uint32_t osPatchLevel; uint32_t vendorPatchLevel; +} SystemProperties; + +typedef struct BootParams_ { uint32_t bootPatchLevel; std::vector verifiedBootKey; std::vector verifiedBootKeyHash; @@ -77,6 +80,11 @@ class Provision { * Provision the boot parameters. */ ErrorCode provisionBootParameters(BootParams& bootParams ); + /** + * Set system properties. + */ + ErrorCode setAndroidSystemProperties(); + /** * Locks the provision. After this no more provision commanands are allowed. */ diff --git a/ProvisioningTool/ProvisionTool.cpp b/ProvisioningTool/ProvisionTool.cpp index 0f240b3c..3ff242f5 100644 --- a/ProvisioningTool/ProvisionTool.cpp +++ b/ProvisioningTool/ProvisionTool.cpp @@ -136,8 +136,9 @@ void usage() { printf("-c, --cert_chain jsonFile \t Provision attestation certificate chain \n"); printf("-p, --cert_params jsonFile \t Provision attestation certificate parameters \n"); printf("-i, --attest_ids jsonFile \t Provision attestation IDs \n"); - printf("-r, --shared_secret jsonFile \t Provion shared secret \n"); - printf("-b, --set_boot_params jsonFile \t Provion boot parameters \n"); + printf("-r, --shared_secret jsonFile \t Provision shared secret \n"); + printf("-b, --set_boot_params jsonFile \t Set boot parameters \n"); + printf("-e, --set_system_properties \t Set system properties \n"); printf("-s, --provision_status \t Prints the provision status.\n"); printf("-l, --lock_provision \t Locks the provision commands.\n"); } @@ -174,6 +175,18 @@ bool getBootParameterBlobValue(Json::Value& bootParamsObj, const char* key, std: return true; } +bool setAndroidSystemProperties() { + ErrorCode err = ErrorCode::OK; + bool ret = false; + if (ErrorCode::OK != (err = mProvision.setAndroidSystemProperties())) { + printf("\n set boot parameters failed with err:%d \n", (int32_t)err); + return ret; + } + printf("\n SE successfully accepted system properties.\n"); + return true; + +} + bool setBootParameters(const char* filename) { Json::Value bootParamsObj; bool ret = false; @@ -186,18 +199,6 @@ bool setBootParameters(const char* filename) { bootParamsObj = root.get("set_boot_params", bootParamsObj); if (!bootParamsObj.isNull()) { - if(!getBootParameterIntValue(bootParamsObj, "os_version", &bootParams.osVersion)) { - printf("\n Invalid value for os_version or os_version tag missing\n"); - return ret; - } - if(!getBootParameterIntValue(bootParamsObj, "os_patch_level", &bootParams.osPatchLevel)) { - printf("\n Invalid value for os_patch_level or os_patch_level tag missing\n"); - return ret; - } - if(!getBootParameterIntValue(bootParamsObj, "vendor_patch_level", &bootParams.vendorPatchLevel)) { - printf("\n Invalid value for vendor_patch_level or vendor_patch_level tag missing\n"); - return ret; - } if(!getBootParameterIntValue(bootParamsObj, "boot_patch_level", &bootParams.bootPatchLevel)) { printf("\n Invalid value for boot_patch_level or boot_patch_level tag missing\n"); return ret; @@ -492,6 +493,9 @@ bool provision(const char* filename) { if(!setBootParameters(filename)) { return false; } + if(!setAndroidSystemProperties()) { + return false; + } return true; } @@ -525,6 +529,7 @@ int main(int argc, char* argv[]) {"attest_ids", required_argument, NULL, 'i'}, {"shared_secret", required_argument, NULL, 'r'}, {"set_boot_params", required_argument, NULL, 'b'}, + {"set_system_properties", no_argument, NULL, 'e'}, {"provision_status", no_argument, NULL, 's'}, {"lock_provision", no_argument, NULL, 'l'}, {"help", no_argument, NULL, 'h'}, @@ -539,7 +544,7 @@ int main(int argc, char* argv[]) mProvision.init(); /* getopt_long stores the option index here. */ - while ((c = getopt_long(argc, argv, ":slha:k:c:p:i:r:b:", longOpts, NULL)) != -1) { + while ((c = getopt_long(argc, argv, ":slhea:k:c:p:i:r:b:", longOpts, NULL)) != -1) { switch(c) { case 'a': //all @@ -576,6 +581,11 @@ int main(int argc, char* argv[]) if(!setBootParameters(optarg)) printf("\n Failed to set boot parameters.\n"); break; + case 'e': + //set Android system properties + if(!setAndroidSystemProperties()) + printf("\n Failed to set android system properties.\n"); + break; case 's': if(!getProvisionStatus()) printf("\n Failed to get provision status \n"); diff --git a/ProvisioningTool/sample_json.txt b/ProvisioningTool/sample_json.txt index fbfd71de..7885b2aa 100644 --- a/ProvisioningTool/sample_json.txt +++ b/ProvisioningTool/sample_json.txt @@ -11,9 +11,6 @@ }, "shared_secret": "0000000000000000000000000000000000000000000000000000000000000000", "set_boot_params": { - "os_version": 100, - "os_patch_level": 100, - "vendor_patch_level": 0, "boot_patch_level": 0, "verified_boot_key": "0000000000000000000000000000000000000000000000000000000000000000", "verified_boot_key_hash": "0000000000000000000000000000000000000000000000000000000000000000",