From cab9346907952615415a676cdc7750e517f88e8e Mon Sep 17 00:00:00 2001 From: subrahmanyaman Date: Mon, 28 Mar 2022 06:20:11 +0000 Subject: [PATCH 1/4] Renamed deviceuniqpair for JCardSim --- .../javacard/keymaster/KMJCardSimApplet.java | 29 +++++++++---------- .../seprovider/KMDataStoreConstants.java | 2 +- ...queKey.java => KMDeviceUniqueKeyPair.java} | 2 +- .../seprovider/KMECDeviceUniqueKey.java | 2 +- .../javacard/seprovider/KMJCardSimulator.java | 8 ++--- .../javacard/seprovider/KMSEProvider.java | 4 +-- 6 files changed, 23 insertions(+), 24 deletions(-) rename Applet/JCardSimProviderLib/src/com/android/javacard/seprovider/{KMDeviceUniqueKey.java => KMDeviceUniqueKeyPair.java} (94%) diff --git a/Applet/JCardSimProvider/src/com/android/javacard/keymaster/KMJCardSimApplet.java b/Applet/JCardSimProvider/src/com/android/javacard/keymaster/KMJCardSimApplet.java index f38f7d31..2271d0a5 100644 --- a/Applet/JCardSimProvider/src/com/android/javacard/keymaster/KMJCardSimApplet.java +++ b/Applet/JCardSimProvider/src/com/android/javacard/keymaster/KMJCardSimApplet.java @@ -15,10 +15,9 @@ */ package com.android.javacard.keymaster; -import com.android.javacard.seprovider.KMDeviceUniqueKey; +import com.android.javacard.seprovider.KMDeviceUniqueKeyPair; import com.android.javacard.seprovider.KMException; import com.android.javacard.seprovider.KMJCardSimulator; -import com.licel.jcardsim.smartcardio.JCardSimProvider; import javacard.framework.APDU; import javacard.framework.ISO7816; import javacard.framework.ISOException; @@ -36,9 +35,9 @@ public class KMJCardSimApplet extends KMKeymasterApplet { private static final byte INS_LOCK_PROVISIONING_CMD = INS_KEYMINT_PROVIDER_APDU_START + 3; private static final byte INS_GET_PROVISION_STATUS_CMD = INS_KEYMINT_PROVIDER_APDU_START + 4; private static final byte INS_SET_BOOT_PARAMS_CMD = INS_KEYMINT_PROVIDER_APDU_START + 5; - private static final byte INS_PROVISION_DEVICE_UNIQUE_KEY_CMD = + private static final byte INS_PROVISION_RKP_DEVICE_UNIQUE_KEYPAIR_CMD = INS_KEYMINT_PROVIDER_APDU_START + 6; - private static final byte INS_PROVISION_ADDITIONAL_CERT_CHAIN_CMD = + private static final byte INS_PROVISION_RKP_ADDITIONAL_CERT_CHAIN_CMD = INS_KEYMINT_PROVIDER_APDU_START + 7; private static final byte INS_SET_BOOT_ENDED_CMD = INS_KEYMINT_PROVIDER_APDU_START + 8; @@ -55,7 +54,7 @@ public class KMJCardSimApplet extends KMKeymasterApplet { private static final byte PROVISION_STATUS_ATTEST_IDS = 0x08; private static final byte PROVISION_STATUS_PRESHARED_SECRET = 0x10; private static final byte PROVISION_STATUS_PROVISIONING_LOCKED = 0x20; - private static final byte PROVISION_STATUS_DEVICE_UNIQUE_KEY = 0x40; + private static final byte PROVISION_STATUS_DEVICE_UNIQUE_KEYPAIR = 0x40; private static final byte PROVISION_STATUS_ADDITIONAL_CERT_CHAIN = (byte) 0x80; public static final short SHARED_SECRET_KEY_SIZE = 32; @@ -144,12 +143,12 @@ public void process(APDU apdu) { processSetBootParamsCmd(apdu); break; - case INS_PROVISION_DEVICE_UNIQUE_KEY_CMD: - processProvisionDeviceUniqueKey(apdu); + case INS_PROVISION_RKP_DEVICE_UNIQUE_KEYPAIR_CMD: + processProvisionRkpDeviceUniqueKeyPair(apdu); break; - case INS_PROVISION_ADDITIONAL_CERT_CHAIN_CMD: - processProvisionAdditionalCertChain(apdu); + case INS_PROVISION_RKP_ADDITIONAL_CERT_CHAIN_CMD: + processProvisionRkpAdditionalCertChain(apdu); break; default: @@ -180,7 +179,7 @@ private boolean isProvisioningComplete() { byte data[] = repository.getHeap(); kmDataStore.getProvisionStatus(data, dInex); boolean result = false; - if ((0 != (data[dInex] & PROVISION_STATUS_DEVICE_UNIQUE_KEY)) + if ((0 != (data[dInex] & PROVISION_STATUS_DEVICE_UNIQUE_KEYPAIR)) && (0 != (data[dInex] & PROVISION_STATUS_ADDITIONAL_CERT_CHAIN)) && (0 != (data[dInex] & PROVISION_STATUS_PRESHARED_SECRET))) { result = true; @@ -338,7 +337,7 @@ private short validateApdu(APDU apdu) { return apduBuffer[ISO7816.OFFSET_INS]; } - private static void processProvisionDeviceUniqueKey(APDU apdu) { + private static void processProvisionRkpDeviceUniqueKeyPair(APDU apdu) { // Re-purpose the apdu buffer as scratch pad. byte[] scratchPad = apdu.getBuffer(); short arr = KMArray.instance((short) 1); @@ -350,17 +349,17 @@ private static void processProvisionDeviceUniqueKey(APDU apdu) { short pubKeyLen = KMCoseKey.cast(coseKey).getEcdsa256PublicKey(scratchPad, (short) 0); short privKeyLen = KMCoseKey.cast(coseKey).getPrivateKey(scratchPad, pubKeyLen); //Store the Device unique Key. - kmDataStore.createDeviceUniqueKey(scratchPad, (short) 0, pubKeyLen, scratchPad, + kmDataStore.createRkpDeviceUniqueKeyPair(scratchPad, (short) 0, pubKeyLen, scratchPad, pubKeyLen, privKeyLen); short bcc = generateBcc(false, scratchPad); short len = KMKeymasterApplet.encodeToApduBuffer(bcc, scratchPad, (short) 0, MAX_COSE_BUF_SIZE); kmDataStore.persistBootCertificateChain(scratchPad, (short) 0, len); - kmDataStore.setProvisionStatus(PROVISION_STATUS_DEVICE_UNIQUE_KEY); + kmDataStore.setProvisionStatus(PROVISION_STATUS_DEVICE_UNIQUE_KEYPAIR); sendError(apdu, KMError.OK); } - private static void processProvisionAdditionalCertChain(APDU apdu) { + private static void processProvisionRkpAdditionalCertChain(APDU apdu) { // Prepare the expression to decode short headers = KMCoseHeaders.exp(); short arrInst = KMArray.instance((short) 4); @@ -393,7 +392,7 @@ private static void processProvisionAdditionalCertChain(APDU apdu) { srcBuffer, null); // Compare the DK_Pub. short pubKeyLen = KMCoseKey.cast(leafCoseKey).getEcdsa256PublicKey(srcBuffer, (short) 0); - KMDeviceUniqueKey uniqueKey = kmDataStore.getDeviceUniqueKey(false); + KMDeviceUniqueKeyPair uniqueKey = kmDataStore.getRkpDeviceUniqueKeyPair(false); if (uniqueKey == null) { KMException.throwIt(KMError.STATUS_FAILED); } diff --git a/Applet/JCardSimProviderLib/src/com/android/javacard/seprovider/KMDataStoreConstants.java b/Applet/JCardSimProviderLib/src/com/android/javacard/seprovider/KMDataStoreConstants.java index 31917a75..feb7d170 100644 --- a/Applet/JCardSimProviderLib/src/com/android/javacard/seprovider/KMDataStoreConstants.java +++ b/Applet/JCardSimProviderLib/src/com/android/javacard/seprovider/KMDataStoreConstants.java @@ -4,7 +4,7 @@ public class KMDataStoreConstants { // INTERFACE Types public static final byte INTERFACE_TYPE_COMPUTED_HMAC_KEY = 0x01; public static final byte INTERFACE_TYPE_ATTESTATION_KEY = 0x02; - public static final byte INTERFACE_TYPE_DEVICE_UNIQUE_KEY = 0x03; + public static final byte INTERFACE_TYPE_DEVICE_UNIQUE_KEY_PAIR = 0x03; public static final byte INTERFACE_TYPE_MASTER_KEY = 0x04; public static final byte INTERFACE_TYPE_PRE_SHARED_KEY = 0x05; public static final byte INTERFACE_TYPE_RKP_MAC_KEY = 0x06; diff --git a/Applet/JCardSimProviderLib/src/com/android/javacard/seprovider/KMDeviceUniqueKey.java b/Applet/JCardSimProviderLib/src/com/android/javacard/seprovider/KMDeviceUniqueKeyPair.java similarity index 94% rename from Applet/JCardSimProviderLib/src/com/android/javacard/seprovider/KMDeviceUniqueKey.java rename to Applet/JCardSimProviderLib/src/com/android/javacard/seprovider/KMDeviceUniqueKeyPair.java index 08e60a3f..9bbccd8f 100644 --- a/Applet/JCardSimProviderLib/src/com/android/javacard/seprovider/KMDeviceUniqueKey.java +++ b/Applet/JCardSimProviderLib/src/com/android/javacard/seprovider/KMDeviceUniqueKeyPair.java @@ -15,7 +15,7 @@ */ package com.android.javacard.seprovider; -public interface KMDeviceUniqueKey { +public interface KMDeviceUniqueKeyPair { short getPublicKey(byte[] buf, short offset); } diff --git a/Applet/JCardSimProviderLib/src/com/android/javacard/seprovider/KMECDeviceUniqueKey.java b/Applet/JCardSimProviderLib/src/com/android/javacard/seprovider/KMECDeviceUniqueKey.java index 0f68de61..2fc04c7e 100644 --- a/Applet/JCardSimProviderLib/src/com/android/javacard/seprovider/KMECDeviceUniqueKey.java +++ b/Applet/JCardSimProviderLib/src/com/android/javacard/seprovider/KMECDeviceUniqueKey.java @@ -18,7 +18,7 @@ import javacard.security.ECPublicKey; import javacard.security.KeyPair; -public class KMECDeviceUniqueKey implements KMDeviceUniqueKey { +public class KMECDeviceUniqueKey implements KMDeviceUniqueKeyPair { private KeyPair ecKeyPair; diff --git a/Applet/JCardSimProviderLib/src/com/android/javacard/seprovider/KMJCardSimulator.java b/Applet/JCardSimProviderLib/src/com/android/javacard/seprovider/KMJCardSimulator.java index 0a9e57e2..f4ee2cac 100644 --- a/Applet/JCardSimProviderLib/src/com/android/javacard/seprovider/KMJCardSimulator.java +++ b/Applet/JCardSimProviderLib/src/com/android/javacard/seprovider/KMJCardSimulator.java @@ -1253,8 +1253,8 @@ public short getAttestationKeyAlgorithm(){ } @Override - public com.android.javacard.seprovider.KMDeviceUniqueKey createDeviceUniqueKey( - com.android.javacard.seprovider.KMDeviceUniqueKey key, byte[] pubKey, short pubKeyOff, + public KMDeviceUniqueKeyPair createRkpDeviceUniqueKeyPair( + KMDeviceUniqueKeyPair key, byte[] pubKey, short pubKeyOff, short pubKeyLen, byte[] privKey, short privKeyOff, short privKeyLen) { if (key == null) { KeyPair ecKeyPair = new KeyPair(KeyPair.ALG_EC_FP, KeyBuilder.LENGTH_EC_FP_256); @@ -1262,7 +1262,7 @@ public com.android.javacard.seprovider.KMDeviceUniqueKey createDeviceUniqueKey( } ((KMECDeviceUniqueKey) key).setS(privKey, privKeyOff, privKeyLen); ((KMECDeviceUniqueKey) key).setW(pubKey, pubKeyOff, pubKeyLen); - return (KMDeviceUniqueKey) key; + return (KMDeviceUniqueKeyPair) key; } @Override @@ -1307,7 +1307,7 @@ public short ecSign256(KMAttestationKey attestationKey, @Override - public short ecSign256(KMDeviceUniqueKey deviceUniqueKey, byte[] inputDataBuf, short inputDataStart, + public short ecSign256(KMDeviceUniqueKeyPair deviceUniqueKey, byte[] inputDataBuf, short inputDataStart, short inputDataLength, byte[] outputDataBuf, short outputDataStart) { ECPrivateKey key = ((KMECDeviceUniqueKey) deviceUniqueKey).getPrivateKey(); Signature signer = Signature diff --git a/Applet/JCardSimProviderLib/src/com/android/javacard/seprovider/KMSEProvider.java b/Applet/JCardSimProviderLib/src/com/android/javacard/seprovider/KMSEProvider.java index 4d4570b6..c4445114 100644 --- a/Applet/JCardSimProviderLib/src/com/android/javacard/seprovider/KMSEProvider.java +++ b/Applet/JCardSimProviderLib/src/com/android/javacard/seprovider/KMSEProvider.java @@ -479,7 +479,7 @@ boolean ecVerify256( * @return length of the decrypted data. */ short ecSign256( - KMDeviceUniqueKey ecPrivKey, + KMDeviceUniqueKeyPair ecPrivKey, byte[] inputDataBuf, short inputDataStart, short inputDataLength, @@ -626,7 +626,7 @@ KMOperation initAsymmetricOperation( * @param privKeyLen private key buffer length. * @return instance of KMDeviceUniqueKey. */ - KMDeviceUniqueKey createDeviceUniqueKey(KMDeviceUniqueKey key, + KMDeviceUniqueKeyPair createRkpDeviceUniqueKeyPair(KMDeviceUniqueKeyPair key, byte[] pubKey, short pubKeyOff, short pubKeyLen, byte[] privKey, short privKeyOff, short privKeyLen); From 52a0cfa31600c6a7b87307d632621075efecf5c6 Mon Sep 17 00:00:00 2001 From: Subrahmanyaman Date: Wed, 30 Mar 2022 01:07:09 +0000 Subject: [PATCH 2/4] Fixed the issue with reclaim memory --- Applet/src/com/android/javacard/keymaster/KMRepository.java | 1 + 1 file changed, 1 insertion(+) diff --git a/Applet/src/com/android/javacard/keymaster/KMRepository.java b/Applet/src/com/android/javacard/keymaster/KMRepository.java index 1e6c8371..8d868be3 100644 --- a/Applet/src/com/android/javacard/keymaster/KMRepository.java +++ b/Applet/src/com/android/javacard/keymaster/KMRepository.java @@ -90,6 +90,7 @@ public void reclaimMemory(short length) { if (reclaimIndex < heapIndex[0]) { ISOException.throwIt(ISO7816.SW_CONDITIONS_NOT_SATISFIED); } + Util.arrayFillNonAtomic(heap, reclaimIndex, length, (byte) 0); reclaimIndex += length; } From 0edd6a04dc6189702998a14060dad61c7fa70b17 Mon Sep 17 00:00:00 2001 From: Subrahmanyaman Date: Wed, 30 Mar 2022 04:40:27 +0000 Subject: [PATCH 3/4] Updated aosp12 patches --- .../JavacardKeymaster_remove_omapi.patch | 39 +- .../hardware_interfaces.patch | 455 ++++++++++++++---- .../system_keymaster.patch | 231 ++++++--- .../system_security.patch | 2 +- 4 files changed, 546 insertions(+), 181 deletions(-) diff --git a/aosp_integration_patches_aosp_12_r15/JavacardKeymaster_remove_omapi.patch b/aosp_integration_patches_aosp_12_r15/JavacardKeymaster_remove_omapi.patch index c27763ef..2e2d3ca3 100644 --- a/aosp_integration_patches_aosp_12_r15/JavacardKeymaster_remove_omapi.patch +++ b/aosp_integration_patches_aosp_12_r15/JavacardKeymaster_remove_omapi.patch @@ -1,7 +1,20 @@ diff --git a/HAL/Android.bp b/HAL/Android.bp -index 557f204..69fead7 100644 +index 557f204..25f0e22 100644 --- a/HAL/Android.bp +++ b/HAL/Android.bp +@@ -30,9 +30,9 @@ cc_library { + ], + cflags:["-O0",], + shared_libs: [ +- "android.hardware.security.keymint-V1-ndk", +- "android.hardware.security.secureclock-V1-ndk", +- "android.hardware.security.sharedsecret-V1-ndk", ++ "android.hardware.security.keymint-V1-ndk_platform", ++ "android.hardware.security.secureclock-V1-ndk_platform", ++ "android.hardware.security.sharedsecret-V1-ndk_platform", + "libbase", + "libcppbor_external", + "libkeymaster_portable", @@ -55,17 +55,13 @@ cc_library { vendor_available: true, srcs: [ @@ -20,6 +33,17 @@ index 557f204..69fead7 100644 ], } +@@ -83,8 +79,8 @@ cc_binary { + "-Wextra", + ], + shared_libs: [ +- "android.hardware.security.keymint-V1-ndk", +- "android.hardware.security.sharedsecret-V1-ndk", ++ "android.hardware.security.keymint-V1-ndk_platform", ++ "android.hardware.security.sharedsecret-V1-ndk_platform", + "libbase", + "libbinder_ndk", + "libcppbor_external", @@ -94,7 +90,6 @@ cc_binary { "libjc_keymint_transport", "liblog", @@ -30,7 +54,7 @@ index 557f204..69fead7 100644 "service.cpp", diff --git a/HAL/OmapiTransport.cpp b/HAL/OmapiTransport.cpp deleted file mode 100644 -index b7e1dc0..0000000 +index 7c353d8..0000000 --- a/HAL/OmapiTransport.cpp +++ /dev/null @@ -1,221 +0,0 @@ @@ -74,7 +98,7 @@ index b7e1dc0..0000000 - LOG(DEBUG) << "Initialize the secure element connection"; - - // Get OMAPI vendor stable service handler -- ::ndk::SpAIBinder ks2Binder(AServiceManager_getService(omapiServiceName)); +- ::ndk::SpAIBinder ks2Binder(AServiceManager_checkService(omapiServiceName)); - omapiSeService = aidl::android::se::omapi::ISecureElementService::fromBinder(ks2Binder); - - if (omapiSeService == nullptr) { @@ -322,6 +346,15 @@ index 2a53787..0000000 -}; - -} +diff --git a/HAL/android.hardware.security.keymint-service.strongbox.rc b/HAL/android.hardware.security.keymint-service.strongbox.rc +index 7bb96f0..e81bc25 100644 +--- a/HAL/android.hardware.security.keymint-service.strongbox.rc ++++ b/HAL/android.hardware.security.keymint-service.strongbox.rc +@@ -1,3 +1,3 @@ + service vendor.keymint-strongbox /vendor/bin/hw/android.hardware.security.keymint-service.strongbox + class early_hal +- user jc_strongbox ++ user system diff --git a/HAL/service.cpp b/HAL/service.cpp index 14580f8..3d51877 100644 --- a/HAL/service.cpp diff --git a/aosp_integration_patches_aosp_12_r15/hardware_interfaces.patch b/aosp_integration_patches_aosp_12_r15/hardware_interfaces.patch index bf456260..875bcf8d 100644 --- a/aosp_integration_patches_aosp_12_r15/hardware_interfaces.patch +++ b/aosp_integration_patches_aosp_12_r15/hardware_interfaces.patch @@ -779,45 +779,82 @@ index 38f358686..74e44c7b4 100644 false /* testMode */, keysToSign_, testEekChain_.chain, challenge_, &deviceInfo, &protectedData, &keysToSignMac); diff --git a/security/keymint/support/Android.bp b/security/keymint/support/Android.bp -index 9e218b6a3..73fb8c277 100644 +index 9e218b6a3..71faee2a9 100644 --- a/security/keymint/support/Android.bp +++ b/security/keymint/support/Android.bp -@@ -62,6 +62,7 @@ cc_library { +@@ -44,6 +44,7 @@ cc_library { + "libbase", + "libcrypto", + "libutils", ++ "libhardware", + ], + } + +@@ -61,7 +62,9 @@ cc_library { + "libcppbor_external", "libcppcose_rkp", "libcrypto", ++ "libkeymaster_portable", "libjsoncpp", + "android.hardware.security.keymint-V1-ndk_platform", ], } +@@ -79,6 +82,7 @@ cc_test { + "libcrypto", + "libjsoncpp", + "libkeymaster_portable", ++ "android.hardware.security.keymint-V1-ndk_platform", + "libkeymint_remote_prov_support", + ], + } diff --git a/security/keymint/support/include/remote_prov/remote_prov_utils.h b/security/keymint/support/include/remote_prov/remote_prov_utils.h -index 406b7a9b7..4d9ed2b0c 100644 +index 406b7a9b7..1d3abe512 100644 --- a/security/keymint/support/include/remote_prov/remote_prov_utils.h +++ b/security/keymint/support/include/remote_prov/remote_prov_utils.h -@@ -52,6 +52,20 @@ inline constexpr uint8_t kCoseEncodedGeekCert[] = { +@@ -52,6 +52,34 @@ inline constexpr uint8_t kCoseEncodedGeekCert[] = { 0x31, 0xbf, 0x6b, 0xe8, 0x1e, 0x35, 0xe2, 0xf0, 0x2d, 0xce, 0x6c, 0x2f, 0x4f, 0xf2, 0xf5, 0x4f, 0xa5, 0xd4, 0x83, 0xad, 0x96, 0xa2, 0xf1, 0x87, 0x58, 0x04}; -+// The Google ECDSA root key for the Endpoint Encryption Key chain, encoded as COSE_Sign1 -+inline constexpr uint8_t kCoseEncodedEcdsaRootCert[] = { -+ 0x84, 0x43, 0xa1, 0x01, 0x26, 0xa0, 0x58, 0x4d, 0xa5, 0x01, 0x02, 0x03, 0x26, 0x20, 0x01, -+ 0x21, 0x58, 0x20, 0xf7, 0x14, 0x8a, 0xdb, 0x97, 0xf4, 0xcc, 0x53, 0xef, 0xd2, 0x64, 0x11, -+ 0xc4, 0xe3, 0x75, 0x1f, 0x66, 0x1f, 0xa4, 0x71, 0x0c, 0x6c, 0xcf, 0xfa, 0x09, 0x46, 0x80, -+ 0x74, 0x87, 0x54, 0xf2, 0xad, 0x22, 0x58, 0x20, 0x5e, 0x7f, 0x5b, 0xf6, 0xec, 0xe4, 0xf6, -+ 0x19, 0xcc, 0xff, 0x13, 0x37, 0xfd, 0x0f, 0xa1, 0xc8, 0x93, 0xdb, 0x18, 0x06, 0x76, 0xc4, -+ 0x5d, 0xe6, 0xd7, 0x6a, 0x77, 0x86, 0xc3, 0x2d, 0xaf, 0x8f, 0x58, 0x47, 0x30, 0x45, 0x02, -+ 0x20, 0x2f, 0x97, 0x8e, 0x42, 0xfb, 0xbe, 0x07, 0x2d, 0x95, 0x47, 0x85, 0x47, 0x93, 0x40, -+ 0xb0, 0x1f, 0xd4, 0x9b, 0x47, 0xa4, 0xc4, 0x44, 0xa9, 0xf2, 0xa1, 0x07, 0x87, 0x10, 0xc7, -+ 0x9f, 0xcb, 0x11, 0x02, 0x21, 0x00, 0xf4, 0xbf, 0x9f, 0xe8, 0x3b, 0xe0, 0xe7, 0x34, 0x4c, -+ 0x15, 0xfc, 0x7b, 0xc3, 0x7e, 0x33, 0x05, 0xf4, 0xd1, 0x34, 0x3c, 0xed, 0x02, 0x04, 0x60, -+ 0x7a, 0x15, 0xe0, 0x79, 0xd3, 0x8a, 0xff, 0x24}; ++// The Google ECDSA P256 root key for the Endpoint Encryption Key chain, encoded as COSE_Sign1 ++inline constexpr uint8_t kCoseEncodedEcdsa256RootCert[] = { ++ 0x84, 0x43, 0xa1, 0x01, 0x26, 0xa0, 0x58, 0x4d, 0xa5, 0x01, 0x02, 0x03, 0x26, 0x20, 0x01, 0x21, ++ 0x58, 0x20, 0xf7, 0x14, 0x8a, 0xdb, 0x97, 0xf4, 0xcc, 0x53, 0xef, 0xd2, 0x64, 0x11, 0xc4, 0xe3, ++ 0x75, 0x1f, 0x66, 0x1f, 0xa4, 0x71, 0x0c, 0x6c, 0xcf, 0xfa, 0x09, 0x46, 0x80, 0x74, 0x87, 0x54, ++ 0xf2, 0xad, 0x22, 0x58, 0x20, 0x5e, 0x7f, 0x5b, 0xf6, 0xec, 0xe4, 0xf6, 0x19, 0xcc, 0xff, 0x13, ++ 0x37, 0xfd, 0x0f, 0xa1, 0xc8, 0x93, 0xdb, 0x18, 0x06, 0x76, 0xc4, 0x5d, 0xe6, 0xd7, 0x6a, 0x77, ++ 0x86, 0xc3, 0x2d, 0xaf, 0x8f, 0x58, 0x40, 0x2f, 0x97, 0x8e, 0x42, 0xfb, 0xbe, 0x07, 0x2d, 0x95, ++ 0x47, 0x85, 0x47, 0x93, 0x40, 0xb0, 0x1f, 0xd4, 0x9b, 0x47, 0xa4, 0xc4, 0x44, 0xa9, 0xf2, 0xa1, ++ 0x07, 0x87, 0x10, 0xc7, 0x9f, 0xcb, 0x11, 0xf4, 0xbf, 0x9f, 0xe8, 0x3b, 0xe0, 0xe7, 0x34, 0x4c, ++ 0x15, 0xfc, 0x7b, 0xc3, 0x7e, 0x33, 0x05, 0xf4, 0xd1, 0x34, 0x3c, 0xed, 0x02, 0x04, 0x60, 0x7a, ++ 0x15, 0xe0, 0x79, 0xd3, 0x8a, 0xff, 0x24}; ++ ++// The Google ECDSA P256 Endpoint Encryption Key certificate, encoded as COSE_Sign1 ++inline constexpr uint8_t kCoseEncodedEcdsa256GeekCert[] = { ++ 0x84, 0x43, 0xa1, 0x01, 0x26, 0xa0, 0x58, 0x71, 0xa6, 0x01, 0x02, 0x02, 0x58, 0x20, 0x35, 0x73, ++ 0xb7, 0x3f, 0xa0, 0x8a, 0x80, 0x89, 0xb1, 0x26, 0x67, 0xe9, 0xcb, 0x7c, 0x75, 0xa1, 0xaf, 0x02, ++ 0x61, 0xfc, 0x6e, 0x65, 0x03, 0x91, 0x3b, 0xd3, 0x4b, 0x7d, 0x14, 0x94, 0x3e, 0x46, 0x03, 0x38, ++ 0x18, 0x20, 0x01, 0x21, 0x58, 0x20, 0xe0, 0x41, 0xcf, 0x2f, 0x0f, 0x34, 0x0f, 0x1c, 0x33, 0x2c, ++ 0x41, 0xb0, 0xcf, 0xd7, 0x0c, 0x30, 0x55, 0x35, 0xd2, 0x1e, 0x6a, 0x47, 0x13, 0x4b, 0x2e, 0xd1, ++ 0x48, 0x96, 0x7e, 0x24, 0x9c, 0x68, 0x22, 0x58, 0x20, 0x1f, 0xce, 0x45, 0xc5, 0xfb, 0x61, 0xba, ++ 0x81, 0x21, 0xf9, 0xe5, 0x05, 0x9b, 0x9b, 0x39, 0x0e, 0x76, 0x86, 0x86, 0x47, 0xb8, 0x1e, 0x2f, ++ 0x45, 0xf1, 0xce, 0xaf, 0xda, 0x3f, 0x80, 0x68, 0xdb, 0x58, 0x40, 0x8c, 0xb3, 0xba, 0x7e, 0x20, ++ 0x3e, 0x32, 0xb0, 0x68, 0xdf, 0x60, 0xd1, 0x1d, 0x7d, 0xf0, 0xac, 0x38, 0x8e, 0x51, 0xbc, 0xff, ++ 0x6c, 0xe1, 0x67, 0x3b, 0x4a, 0x79, 0xbc, 0x56, 0x78, 0xb3, 0x99, 0xd8, 0x7c, 0x8a, 0x07, 0xd8, ++ 0xda, 0xb5, 0xb5, 0x7f, 0x71, 0xf4, 0xd8, 0x6b, 0xdf, 0x33, 0x27, 0x34, 0x7b, 0x65, 0xd1, 0x2a, ++ 0xeb, 0x86, 0x99, 0x98, 0xab, 0x3a, 0xb4, 0x80, 0xaa, 0xbd, 0x50}; + /** * Generates random bytes. */ -@@ -67,12 +81,12 @@ struct EekChain { - * Generates an X25518 EEK with the specified eekId and an Ed25519 chain of the - * specified length. All keys are generated randomly. +@@ -64,15 +92,15 @@ struct EekChain { + }; + + /** +- * Generates an X25518 EEK with the specified eekId and an Ed25519 chain of the +- * specified length. All keys are generated randomly. ++ * Based on the supportedEekCurve, Generates an X25519/ECDH with the specified eekId ++ * and an Ed25519/ECDSA chain of the specified length. All keys are generated randomly. */ -ErrMsgOr generateEekChain(size_t length, const bytevec& eekId); +ErrMsgOr generateEekChain(int32_t supportedEekCurve, size_t length, const bytevec& eekId); @@ -831,10 +868,10 @@ index 406b7a9b7..4d9ed2b0c 100644 struct BccEntryData { bytevec pubKey; diff --git a/security/keymint/support/remote_prov_utils.cpp b/security/keymint/support/remote_prov_utils.cpp -index 0cbee5104..ae5120f8b 100644 +index 0cbee5104..485f871b9 100644 --- a/security/keymint/support/remote_prov_utils.cpp +++ b/security/keymint/support/remote_prov_utils.cpp -@@ -17,15 +17,195 @@ +@@ -17,15 +17,186 @@ #include #include @@ -853,6 +890,10 @@ index 0cbee5104..ae5120f8b 100644 namespace aidl::android::hardware::security::keymint::remote_prov { ++constexpr uint32_t kBccPayloadIssuer = 1; ++constexpr uint32_t kBccPayloadSubject = 2; ++constexpr int32_t kBccPayloadSubjPubKey = -4670552; ++constexpr int32_t kBccPayloadKeyUsage = -4670553; +constexpr int kP256AffinePointSize = 32; + +using EC_KEY_Ptr = bssl::UniquePtr; @@ -865,10 +906,9 @@ index 0cbee5104..ae5120f8b 100644 + if (bignum == nullptr) { + return "Error getting bignum from private key"; + } -+ int size = BN_num_bytes(bignum); -+ // Pad with zeros incase the length is lesser than 32. ++ // Pad with zeros in case the length is lesser than 32. + bytevec privKey(32, 0); -+ BN_bn2bin(bignum, privKey.data() + 32 - size); ++ BN_bn2binpad(bignum, privKey.data(), privKey.size()); + return privKey; +} + @@ -881,31 +921,26 @@ index 0cbee5104..ae5120f8b 100644 + const EC_POINT* point = EC_KEY_get0_public_key(ecKey); + if (point == nullptr) return "Error getting ecpoint from public key"; + -+ int size = EC_POINT_point2oct(group.get(), point, -+ POINT_CONVERSION_UNCOMPRESSED, nullptr, 0, -+ nullptr); ++ int size = ++ EC_POINT_point2oct(group.get(), point, POINT_CONVERSION_UNCOMPRESSED, nullptr, 0, nullptr); + if (size == 0) { + return "Error generating public key encoding"; + } + + bytevec publicKey; + publicKey.resize(size); -+ EC_POINT_point2oct(group.get(), point, -+ POINT_CONVERSION_UNCOMPRESSED, publicKey.data(), ++ EC_POINT_point2oct(group.get(), point, POINT_CONVERSION_UNCOMPRESSED, publicKey.data(), + publicKey.size(), nullptr); + return publicKey; +} + -+ErrMsgOr> getAffineCoordinates( -+ const bytevec& pubKey) { -+ auto group = EC_GROUP_Ptr( -+ EC_GROUP_new_by_curve_name(NID_X9_62_prime256v1)); ++ErrMsgOr> getAffineCoordinates(const bytevec& pubKey) { ++ auto group = EC_GROUP_Ptr(EC_GROUP_new_by_curve_name(NID_X9_62_prime256v1)); + if (group.get() == nullptr) { + return "Error creating EC group by curve name"; + } + auto point = EC_POINT_Ptr(EC_POINT_new(group.get())); -+ if (EC_POINT_oct2point(group.get(), point.get(), pubKey.data(), -+ pubKey.size(), nullptr) != 1) { ++ if (EC_POINT_oct2point(group.get(), point.get(), pubKey.data(), pubKey.size(), nullptr) != 1) { + return "Error decoding publicKey"; + } + BIGNUM_Ptr x(BN_new()); @@ -913,20 +948,17 @@ index 0cbee5104..ae5120f8b 100644 + BN_CTX_Ptr ctx(BN_CTX_new()); + if (!ctx.get()) return "Failed to create BN_CTX instance"; + -+ if (!EC_POINT_get_affine_coordinates_GFp(group.get(), point.get(), -+ x.get(), y.get(), ++ if (!EC_POINT_get_affine_coordinates_GFp(group.get(), point.get(), x.get(), y.get(), + ctx.get())) { + return "Failed to get affine coordinates from ECPoint"; + } + bytevec pubX(kP256AffinePointSize); + bytevec pubY(kP256AffinePointSize); -+ if (BN_bn2binpad(x.get(), pubX.data(), kP256AffinePointSize) != -+ kP256AffinePointSize) { -+ return "Error in converting absolute value of x cordinate to big-endian"; ++ if (BN_bn2binpad(x.get(), pubX.data(), kP256AffinePointSize) != kP256AffinePointSize) { ++ return "Error in converting absolute value of x coordinate to big-endian"; + } -+ if (BN_bn2binpad(y.get(), pubY.data(), kP256AffinePointSize) != -+ kP256AffinePointSize) { -+ return "Error in converting absolute value of y cordinate to big-endian"; ++ if (BN_bn2binpad(y.get(), pubY.data(), kP256AffinePointSize) != kP256AffinePointSize) { ++ return "Error in converting absolute value of y coordinate to big-endian"; + } + return std::make_tuple(std::move(pubX), std::move(pubY)); +} @@ -972,20 +1004,17 @@ index 0cbee5104..ae5120f8b 100644 + return std::make_tuple(std::move(pubKey), std::move(privKey)); +} + -+ErrMsgOr> generateKeyPair( -+ int32_t supportedEekCurve, bool isEek) { -+ ++ErrMsgOr> generateKeyPair(int32_t supportedEekCurve, bool isEek) { + switch (supportedEekCurve) { -+ case RpcHardwareInfo::CURVE_NONE: -+ case RpcHardwareInfo::CURVE_25519: -+ if (isEek) { -+ return generateX25519KeyPair(); -+ } -+ return generateED25519KeyPair(); -+ case RpcHardwareInfo::CURVE_P256: -+ return generateEc256KeyPair(); -+ default: -+ return "Unknown EEK Curve."; ++ case RpcHardwareInfo::CURVE_25519: ++ if (isEek) { ++ return generateX25519KeyPair(); ++ } ++ return generateED25519KeyPair(); ++ case RpcHardwareInfo::CURVE_P256: ++ return generateEc256KeyPair(); ++ default: ++ return "Unknown EEK Curve."; + } +} + @@ -997,7 +1026,6 @@ index 0cbee5104..ae5120f8b 100644 + bytevec pubX; + bytevec pubY; + switch (supportedEekCurve) { -+ case RpcHardwareInfo::CURVE_NONE: + case RpcHardwareInfo::CURVE_25519: + keyType = OCTET_KEY_PAIR; + algorithm = (eekId.empty()) ? EDDSA : ECDH_ES_HKDF_256; @@ -1030,7 +1058,7 @@ index 0cbee5104..ae5120f8b 100644 bytevec kTestMacKey(32 /* count */, 0 /* byte value */); bytevec randomBytes(size_t numBytes) { -@@ -34,7 +214,17 @@ bytevec randomBytes(size_t numBytes) { +@@ -34,7 +205,17 @@ bytevec randomBytes(size_t numBytes) { return retval; } @@ -1049,7 +1077,7 @@ index 0cbee5104..ae5120f8b 100644 if (length < 2) { return "EEK chain must contain at least 2 certs."; } -@@ -43,42 +233,31 @@ ErrMsgOr generateEekChain(size_t length, const bytevec& eekId) { +@@ -43,59 +224,74 @@ ErrMsgOr generateEekChain(size_t length, const bytevec& eekId) { bytevec prev_priv_key; for (size_t i = 0; i < length - 1; ++i) { @@ -1058,7 +1086,7 @@ index 0cbee5104..ae5120f8b 100644 - - ED25519_keypair(pub_key.data(), priv_key.data()); + auto keyPair = generateKeyPair(supportedEekCurve, false); -+ if (!keyPair) keyPair.moveMessage(); ++ if (!keyPair) return keyPair.moveMessage(); + auto [pub_key, priv_key] = keyPair.moveValue(); // The first signing key is self-signed. @@ -1072,26 +1100,28 @@ index 0cbee5104..ae5120f8b 100644 - .add(CoseKey::PUBKEY_X, pub_key) - .canonicalize() - .encode(), +- {} /* AAD */); + auto coseKey = constructCoseKey(supportedEekCurve, {}, pub_key); + if (!coseKey) return coseKey.moveMessage(); + -+ auto coseSign1 = constructCoseSign1(supportedEekCurve, prev_priv_key, coseKey.moveValue(), - {} /* AAD */); ++ auto coseSign1 = ++ constructCoseSign1(supportedEekCurve, prev_priv_key, coseKey.moveValue(), {} /* AAD */); if (!coseSign1) return coseSign1.moveMessage(); eekChain.add(coseSign1.moveValue()); prev_priv_key = priv_key; } + auto keyPair = generateKeyPair(supportedEekCurve, true); -+ if (!keyPair) keyPair.moveMessage(); ++ if (!keyPair) return keyPair.moveMessage(); + auto [pub_key, priv_key] = keyPair.moveValue(); ++ ++ auto coseKey = constructCoseKey(supportedEekCurve, eekId, pub_key); ++ if (!coseKey) return coseKey.moveMessage(); - bytevec pub_key(X25519_PUBLIC_VALUE_LEN); - bytevec priv_key(X25519_PRIVATE_KEY_LEN); - X25519_keypair(pub_key.data(), priv_key.data()); -+ auto coseKey = constructCoseKey(supportedEekCurve, eekId, pub_key); -+ if (!coseKey) return coseKey.moveMessage(); - +- - auto coseSign1 = constructCoseSign1(prev_priv_key, - cppbor::Map() /* payload CoseKey */ - .add(CoseKey::KEY_TYPE, OCTET_KEY_PAIR) @@ -1101,11 +1131,22 @@ index 0cbee5104..ae5120f8b 100644 - .add(CoseKey::PUBKEY_X, pub_key) - .canonicalize() - .encode(), -+ auto coseSign1 = constructCoseSign1(supportedEekCurve, prev_priv_key, coseKey.moveValue(), - {} /* AAD */); +- {} /* AAD */); ++ auto coseSign1 = ++ constructCoseSign1(supportedEekCurve, prev_priv_key, coseKey.moveValue(), {} /* AAD */); if (!coseSign1) return coseSign1.moveMessage(); eekChain.add(coseSign1.moveValue()); -@@ -86,16 +265,15 @@ ErrMsgOr generateEekChain(size_t length, const bytevec& eekId) { + ++ if (supportedEekCurve == RpcHardwareInfo::CURVE_P256) { ++ // convert ec public key to x and y co-ordinates. ++ auto affineCoordinates = getAffineCoordinates(pub_key); ++ if (!affineCoordinates) return affineCoordinates.moveMessage(); ++ auto [pubX, pubY] = affineCoordinates.moveValue(); ++ pub_key.clear(); ++ pub_key.insert(pub_key.begin(), pubX.begin(), pubX.end()); ++ pub_key.insert(pub_key.end(), pubY.begin(), pubY.end()); ++ } ++ return EekChain{eekChain.encode(), pub_key, priv_key}; } @@ -1117,46 +1158,71 @@ index 0cbee5104..ae5120f8b 100644 - prodEek.push_back(0x82); - prodEek.insert(prodEek.end(), std::begin(kCoseEncodedRootCert), std::end(kCoseEncodedRootCert)); - prodEek.insert(prodEek.end(), std::begin(kCoseEncodedGeekCert), std::end(kCoseEncodedGeekCert)); -- -- return prodEek; +bytevec getProdEekChain(int32_t supportedEekCurve) { + cppbor::Array chain; + if (supportedEekCurve == RpcHardwareInfo::CURVE_P256) { -+ chain.add(cppbor::EncodedItem(bytevec(std::begin(kCoseEncodedEcdsaRootCert), std::end(kCoseEncodedEcdsaRootCert)))); ++ chain.add(cppbor::EncodedItem(bytevec(std::begin(kCoseEncodedEcdsa256RootCert), ++ std::end(kCoseEncodedEcdsa256RootCert)))); ++ chain.add(cppbor::EncodedItem(bytevec(std::begin(kCoseEncodedEcdsa256GeekCert), ++ std::end(kCoseEncodedEcdsa256GeekCert)))); + } else { -+ chain.add(cppbor::EncodedItem(bytevec(std::begin(kCoseEncodedRootCert), std::end(kCoseEncodedRootCert)))); -+ chain.add(cppbor::EncodedItem(bytevec(std::begin(kCoseEncodedGeekCert), std::end(kCoseEncodedGeekCert)))); ++ chain.add(cppbor::EncodedItem( ++ bytevec(std::begin(kCoseEncodedRootCert), std::end(kCoseEncodedRootCert)))); ++ chain.add(cppbor::EncodedItem( ++ bytevec(std::begin(kCoseEncodedGeekCert), std::end(kCoseEncodedGeekCert)))); + } + return chain.encode(); ++} + +- return prodEek; ++ErrMsgOr validatePayloadAndFetchPubKey(const cppbor::Map* payload) { ++ const auto& issuer = payload->get(kBccPayloadIssuer); ++ if (!issuer || !issuer->asTstr()) return "Issuer is not present or not a tstr."; ++ const auto& subject = payload->get(kBccPayloadSubject); ++ if (!subject || !subject->asTstr()) return "Subject is not present or not a tstr."; ++ const auto& keyUsage = payload->get(kBccPayloadKeyUsage); ++ if (!keyUsage || !keyUsage->asBstr()) return "Key usage is not present or not a bstr."; ++ const auto& serializedKey = payload->get(kBccPayloadSubjPubKey); ++ if (!serializedKey || !serializedKey->asBstr()) return "Key is not present or not a bstr."; ++ return serializedKey->asBstr()->value(); } ErrMsgOr verifyAndParseCoseSign1Cwt(const cppbor::Array* coseSign1, -@@ -122,7 +300,8 @@ ErrMsgOr verifyAndParseCoseSign1Cwt(const cppbor::Array* coseSign1, +@@ -122,7 +318,8 @@ ErrMsgOr verifyAndParseCoseSign1Cwt(const cppbor::Array* coseSign1, } auto& algorithm = parsedProtParams->asMap()->get(ALGORITHM); - if (!algorithm || !algorithm->asInt() || algorithm->asInt()->value() != EDDSA) { -+ if (!algorithm || !algorithm->asInt() || (algorithm->asInt()->value() != EDDSA && -+ algorithm->asInt()->value() != ES256)) { ++ if (!algorithm || !algorithm->asInt() || ++ (algorithm->asInt()->value() != EDDSA && algorithm->asInt()->value() != ES256)) { return "Unsupported signature algorithm"; } -@@ -136,16 +315,35 @@ ErrMsgOr verifyAndParseCoseSign1Cwt(const cppbor::Array* coseSign1, - if (!serializedKey || !serializedKey->asBstr()) return "Could not find key entry"; +@@ -132,23 +329,45 @@ ErrMsgOr verifyAndParseCoseSign1Cwt(const cppbor::Array* coseSign1, + auto [parsedPayload, __, payloadErrMsg] = cppbor::parse(payload); + if (!parsedPayload) return payloadErrMsg + " when parsing key"; + if (!parsedPayload->asMap()) return "CWT must be a map"; +- auto serializedKey = parsedPayload->asMap()->get(-4670552)->clone(); +- if (!serializedKey || !serializedKey->asBstr()) return "Could not find key entry"; ++ auto serializedKey = validatePayloadAndFetchPubKey(parsedPayload->asMap()); ++ if (!serializedKey) { ++ return "CWT validation failed: " + serializedKey.moveMessage(); ++ } bool selfSigned = signingCoseKey.empty(); - auto key = -+ bytevec key; -+ if (algorithm->asInt()->value() == EDDSA) { -+ auto key = - CoseKey::parseEd25519(selfSigned ? serializedKey->asBstr()->value() : signingCoseKey); +- CoseKey::parseEd25519(selfSigned ? serializedKey->asBstr()->value() : signingCoseKey); - if (!key) return "Bad signing key: " + key.moveMessage(); +- + bytevec signatureInput = +- cppbor::Array().add("Signature1").add(*protectedParams).add(aad).add(*payload).encode(); ++ cppbor::Array().add("Signature1").add(*protectedParams).add(aad).add(*payload).encode(); ++ ++ if (algorithm->asInt()->value() == EDDSA) { ++ auto key = CoseKey::parseEd25519(selfSigned ? *serializedKey : signingCoseKey); ++ + if (!key) return "Bad signing key: " + key.moveMessage(); -- bytevec signatureInput = -+ bytevec signatureInput = - cppbor::Array().add("Signature1").add(*protectedParams).add(aad).add(*payload).encode(); - - if (!ED25519_verify(signatureInput.data(), signatureInput.size(), signature->value().data(), - key->getBstrValue(CoseKey::PUBKEY_X)->data())) { - return "Signature verification failed"; @@ -1164,9 +1230,8 @@ index 0cbee5104..ae5120f8b 100644 + key->getBstrValue(CoseKey::PUBKEY_X)->data())) { + return "Signature verification failed"; + } -+ } else { // P256 -+ auto key = -+ CoseKey::parseP256(selfSigned ? serializedKey->asBstr()->value() : signingCoseKey); ++ } else { // P256 ++ auto key = CoseKey::parseP256(selfSigned ? *serializedKey : signingCoseKey); + if (!key || key->getBstrValue(CoseKey::PUBKEY_X)->empty() || + key->getBstrValue(CoseKey::PUBKEY_Y)->empty()) { + return "Bad signing key: " + key.moveMessage(); @@ -1174,40 +1239,230 @@ index 0cbee5104..ae5120f8b 100644 + auto publicKey = key->getEcPublicKey(); + if (!publicKey) return publicKey.moveMessage(); + -+ bytevec signatureInput = -+ cppbor::Array().add("Signature1").add(*protectedParams).add(aad).add(*payload).encode(); ++ auto ecdsaDerSignature = ecdsaCoseSignatureToDer(signature->value()); ++ if (!ecdsaDerSignature) return ecdsaDerSignature.moveMessage(); ++ ++ // convert public key to uncompressed form. ++ publicKey->insert(publicKey->begin(), 0x04); + -+ if (!verifyEcdsaDigest(publicKey.moveValue(), sha256(signatureInput), signature->value())) { ++ if (!verifyEcdsaDigest(publicKey.moveValue(), sha256(signatureInput), *ecdsaDerSignature)) { + return "Signature verification failed"; + } } - return serializedKey->asBstr()->value(); +- return serializedKey->asBstr()->value(); ++ return serializedKey.moveValue(); + } + + ErrMsgOr> validateBcc(const cppbor::Array* bcc) { diff --git a/security/keymint/support/remote_prov_utils_test.cpp b/security/keymint/support/remote_prov_utils_test.cpp -index 8697c5190..0009bf713 100644 +index 8697c5190..e1c4467a6 100644 --- a/security/keymint/support/remote_prov_utils_test.cpp +++ b/security/keymint/support/remote_prov_utils_test.cpp -@@ -14,6 +14,7 @@ +@@ -14,8 +14,12 @@ * limitations under the License. */ ++#include "cppbor.h" ++#include "keymaster/cppcose/cppcose.h" +#include #include #include ++#include #include -@@ -35,13 +36,13 @@ using ::keymaster::validateAndExtractEekPubAndId; + #include + #include +@@ -23,25 +27,120 @@ + #include + #include + #include +-#include +-#include "cppbor.h" +-#include "keymaster/cppcose/cppcose.h" + + namespace aidl::android::hardware::security::keymint::remote_prov { + namespace { + + using ::keymaster::KeymasterBlob; +-using ::keymaster::validateAndExtractEekPubAndId; ++using ::keymaster::kStatusFailed; ++using ::keymaster::kStatusInvalidEek; ++using ::keymaster::StatusOr; using ::testing::ElementsAreArray; ++using byte_view = std::basic_string_view; ++ ++struct KeyInfoEcdsa { ++ CoseKeyCurve curve; ++ byte_view pubKeyX; ++ byte_view pubKeyY; ++ ++ bool operator==(const KeyInfoEcdsa& other) const { ++ return curve == other.curve && pubKeyX == other.pubKeyX && pubKeyY == other.pubKeyY; ++ } ++}; ++ ++// The production root signing key for Google ECDSA P256 Endpoint Encryption Key cert chains. ++inline constexpr uint8_t kEcdsa256GeekRootX[] = { ++ 0xf7, 0x14, 0x8a, 0xdb, 0x97, 0xf4, 0xcc, 0x53, 0xef, 0xd2, 0x64, 0x11, 0xc4, 0xe3, 0x75, 0x1f, ++ 0x66, 0x1f, 0xa4, 0x71, 0x0c, 0x6c, 0xcf, 0xfa, 0x09, 0x46, 0x80, 0x74, 0x87, 0x54, 0xf2, 0xad}; ++ ++inline constexpr uint8_t kEcdsa256GeekRootY[] = { ++ 0x5e, 0x7f, 0x5b, 0xf6, 0xec, 0xe4, 0xf6, 0x19, 0xcc, 0xff, 0x13, 0x37, 0xfd, 0x0f, 0xa1, 0xc8, ++ 0x93, 0xdb, 0x18, 0x06, 0x76, 0xc4, 0x5d, 0xe6, 0xd7, 0x6a, 0x77, 0x86, 0xc3, 0x2d, 0xaf, 0x8f}; ++ ++// Hard-coded set of acceptable public COSE_Keys that can act as roots of EEK chains. ++inline constexpr KeyInfoEcdsa kAuthorizedEcdsa256EekRoots[] = { ++ {CoseKeyCurve::P256, byte_view(kEcdsa256GeekRootX, sizeof(kEcdsa256GeekRootX)), ++ byte_view(kEcdsa256GeekRootY, sizeof(kEcdsa256GeekRootY))}, ++}; ++ ++static ErrMsgOr parseEcdh256(const bytevec& coseKey) { ++ auto key = CoseKey::parse(coseKey, EC2, ECDH_ES_HKDF_256, P256); ++ if (!key) return key; ++ ++ auto& pubkey_x = key->getMap().get(cppcose::CoseKey::PUBKEY_X); ++ auto& pubkey_y = key->getMap().get(cppcose::CoseKey::PUBKEY_Y); ++ if (!pubkey_x || !pubkey_y || !pubkey_x->asBstr() || !pubkey_y->asBstr() || ++ pubkey_x->asBstr()->value().size() != 32 || pubkey_y->asBstr()->value().size() != 32) { ++ return "Invalid P256 public key"; ++ } ++ ++ return key; ++} ++ ++StatusOr /* EEK pubX */, std::vector /* EEK pubY */, ++ std::vector /* EEK ID */>> ++validateAndExtractEcdsa256EekPubAndId(bool testMode, ++ const KeymasterBlob& endpointEncryptionCertChain) { ++ auto [item, newPos, errMsg] = ++ cppbor::parse(endpointEncryptionCertChain.begin(), endpointEncryptionCertChain.end()); ++ if (!item || !item->asArray()) { ++ return kStatusFailed; ++ } ++ const cppbor::Array* certArr = item->asArray(); ++ std::vector lastPubKey; ++ for (size_t i = 0; i < certArr->size(); ++i) { ++ auto cosePubKey = ++ verifyAndParseCoseSign1(certArr->get(i)->asArray(), lastPubKey, {} /* AAD */); ++ if (!cosePubKey) { ++ return kStatusInvalidEek; ++ } ++ lastPubKey = *std::move(cosePubKey); ++ ++ // In prod mode the first pubkey should match a well-known Google public key. ++ if (!testMode && i == 0) { ++ auto parsedPubKey = CoseKey::parse(lastPubKey); ++ if (!parsedPubKey) { ++ return kStatusFailed; ++ } ++ auto curve = parsedPubKey->getIntValue(CoseKey::CURVE); ++ if (!curve) { ++ return kStatusInvalidEek; ++ } ++ auto rawPubX = parsedPubKey->getBstrValue(CoseKey::PUBKEY_X); ++ if (!rawPubX) { ++ return kStatusInvalidEek; ++ } ++ auto rawPubY = parsedPubKey->getBstrValue(CoseKey::PUBKEY_Y); ++ if (!rawPubY) { ++ return kStatusInvalidEek; ++ } ++ KeyInfoEcdsa matcher = {static_cast(*curve), ++ byte_view(rawPubX->data(), rawPubX->size()), ++ byte_view(rawPubY->data(), rawPubY->size())}; ++ if (std::find(std::begin(kAuthorizedEcdsa256EekRoots), ++ std::end(kAuthorizedEcdsa256EekRoots), ++ matcher) == std::end(kAuthorizedEcdsa256EekRoots)) { ++ return kStatusInvalidEek; ++ } ++ } ++ } ++ auto eek = parseEcdh256(lastPubKey); ++ if (!eek) { ++ return kStatusInvalidEek; ++ } ++ return std::make_tuple(eek->getBstrValue(CoseKey::PUBKEY_X).value(), ++ eek->getBstrValue(CoseKey::PUBKEY_Y).value(), ++ eek->getBstrValue(CoseKey::KEY_ID).value()); ++} TEST(RemoteProvUtilsTest, GenerateEekChainInvalidLength) { - ASSERT_FALSE(generateEekChain(1, /*eekId=*/{})); -+ ASSERT_FALSE(generateEekChain(CURVE_25519, 1, /*eekId=*/{})); ++ ASSERT_FALSE(generateEekChain(RpcHardwareInfo::CURVE_25519, 1, /*eekId=*/{})); } TEST(RemoteProvUtilsTest, GenerateEekChain) { bytevec kTestEekId = {'t', 'e', 's', 't', 'I', 'd', 0}; for (size_t length : {2, 3, 31}) { - auto get_eek_result = generateEekChain(length, kTestEekId); -+ auto get_eek_result = generateEekChain(CURVE_25519, length, kTestEekId); ++ auto get_eek_result = generateEekChain(RpcHardwareInfo::CURVE_25519, length, kTestEekId); ASSERT_TRUE(get_eek_result) << get_eek_result.message(); auto& [chain, pubkey, privkey] = *get_eek_result; +@@ -57,7 +156,7 @@ TEST(RemoteProvUtilsTest, GenerateEekChain) { + } + + TEST(RemoteProvUtilsTest, GetProdEekChain) { +- auto chain = getProdEekChain(); ++ auto chain = getProdEekChain(RpcHardwareInfo::CURVE_25519); + + auto validation_result = validateAndExtractEekPubAndId( + /*testMode=*/false, KeymasterBlob(chain.data(), chain.size())); +@@ -97,5 +196,57 @@ TEST(RemoteProvUtilsTest, JsonEncodeCsr) { + ASSERT_EQ(json, expected); + } + ++TEST(RemoteProvUtilsTest, GenerateEcdsaEekChainInvalidLength) { ++ ASSERT_FALSE(generateEekChain(RpcHardwareInfo::CURVE_P256, 1, /*eekId=*/{})); ++} ++ ++TEST(RemoteProvUtilsTest, GenerateEcdsaEekChain) { ++ bytevec kTestEekId = {'t', 'e', 's', 't', 'I', 'd', 0}; ++ for (size_t length : {2, 3, 31}) { ++ auto get_eek_result = generateEekChain(RpcHardwareInfo::CURVE_P256, length, kTestEekId); ++ ASSERT_TRUE(get_eek_result) << get_eek_result.message(); ++ ++ auto& [chain, pubkey, privkey] = *get_eek_result; ++ ++ auto validation_result = validateAndExtractEcdsa256EekPubAndId( ++ /*testMode=*/true, KeymasterBlob(chain.data(), chain.size())); ++ ASSERT_TRUE(validation_result.isOk()); ++ ++ auto& [eekPubX, eekPubY, eekId] = *validation_result; ++ bytevec eekPub; ++ eekPub.insert(eekPub.begin(), eekPubX.begin(), eekPubX.end()); ++ eekPub.insert(eekPub.end(), eekPubY.begin(), eekPubY.end()); ++ EXPECT_THAT(eekId, ElementsAreArray(kTestEekId)); ++ EXPECT_THAT(eekPub, ElementsAreArray(pubkey)); ++ } ++} ++ ++TEST(RemoteProvUtilsTest, GetProdEcdsaEekChain) { ++ auto chain = getProdEekChain(RpcHardwareInfo::CURVE_P256); ++ ++ auto validation_result = validateAndExtractEcdsa256EekPubAndId( ++ /*testMode=*/false, KeymasterBlob(chain.data(), chain.size())); ++ ASSERT_TRUE(validation_result.isOk()) << "Error: " << validation_result.moveError(); ++ ++ auto& [eekPubX, eekPubY, eekId] = *validation_result; ++ ++ auto [geekCert, ignoredNewPos, error] = ++ cppbor::parse(kCoseEncodedEcdsa256GeekCert, sizeof(kCoseEncodedEcdsa256GeekCert)); ++ ASSERT_NE(geekCert, nullptr) << "Error: " << error; ++ ASSERT_NE(geekCert->asArray(), nullptr); ++ ++ auto& encodedGeekCoseKey = geekCert->asArray()->get(kCoseSign1Payload); ++ ASSERT_NE(encodedGeekCoseKey, nullptr); ++ ASSERT_NE(encodedGeekCoseKey->asBstr(), nullptr); ++ ++ auto geek = CoseKey::parse(encodedGeekCoseKey->asBstr()->value()); ++ ASSERT_TRUE(geek) << "Error: " << geek.message(); ++ ++ const std::vector empty; ++ EXPECT_THAT(eekId, ElementsAreArray(geek->getBstrValue(CoseKey::KEY_ID).value_or(empty))); ++ EXPECT_THAT(eekPubX, ElementsAreArray(geek->getBstrValue(CoseKey::PUBKEY_X).value_or(empty))); ++ EXPECT_THAT(eekPubY, ElementsAreArray(geek->getBstrValue(CoseKey::PUBKEY_Y).value_or(empty))); ++} ++ + } // namespace + } // namespace aidl::android::hardware::security::keymint::remote_prov diff --git a/aosp_integration_patches_aosp_12_r15/system_keymaster.patch b/aosp_integration_patches_aosp_12_r15/system_keymaster.patch index b994b768..d631bc0e 100644 --- a/aosp_integration_patches_aosp_12_r15/system_keymaster.patch +++ b/aosp_integration_patches_aosp_12_r15/system_keymaster.patch @@ -1,5 +1,5 @@ diff --git a/cppcose/cppcose.cpp b/cppcose/cppcose.cpp -index bfe9928..5009bfe 100644 +index bfe9928..411dc01 100644 --- a/cppcose/cppcose.cpp +++ b/cppcose/cppcose.cpp @@ -21,10 +21,17 @@ @@ -20,11 +20,10 @@ index bfe9928..5009bfe 100644 namespace { -@@ -51,6 +58,92 @@ ErrMsgOr> aesGcmInitAndProcessAad(const bytevec& +@@ -51,8 +58,134 @@ ErrMsgOr> aesGcmInitAndProcessAad(const bytevec& return std::move(ctx); } -+ +ErrMsgOr signEcdsaDigest(const bytevec& key, const bytevec& data) { + auto bn = BIGNUM_Ptr(BN_bin2bn(key.data(), key.size(), nullptr)); + if (bn.get() == nullptr) { @@ -36,15 +35,14 @@ index bfe9928..5009bfe 100644 + return "Error setting private key from BIGNUM"; + } + -+ ECDSA_SIG* sig = ECDSA_do_sign(data.data(), data.size(), ec_key.get()); ++ auto sig = ECDSA_SIG_Ptr(ECDSA_do_sign(data.data(), data.size(), ec_key.get())); + if (sig == nullptr) { + return "Error signing digest"; + } -+ size_t len = i2d_ECDSA_SIG(sig, nullptr); ++ size_t len = i2d_ECDSA_SIG(sig.get(), nullptr); + bytevec signature(len); + unsigned char* p = (unsigned char*)signature.data(); -+ i2d_ECDSA_SIG(sig, &p); -+ ECDSA_SIG_free(sig); ++ i2d_ECDSA_SIG(sig.get(), &p); + return signature; +} + @@ -101,8 +99,7 @@ index bfe9928..5009bfe 100644 + if (EVP_PKEY_derive(ctx.get(), NULL, &secretLen) != 1) { + return "Error determing length of shared secret"; + } -+ bytevec sharedSecret; -+ sharedSecret.resize(secretLen); ++ bytevec sharedSecret(secretLen); + + if (EVP_PKEY_derive(ctx.get(), sharedSecret.data(), &secretLen) != 1) { + return "Error deriving shared secret"; @@ -112,8 +109,53 @@ index bfe9928..5009bfe 100644 + } // namespace ++ErrMsgOr ecdsaCoseSignatureToDer(const bytevec& ecdsaCoseSignature) { ++ if (ecdsaCoseSignature.size() != 64) { ++ return "COSE signature wrong length"; ++ } ++ ++ auto rBn = BIGNUM_Ptr(BN_bin2bn(ecdsaCoseSignature.data(), 32, nullptr)); ++ if (rBn.get() == nullptr) { ++ return "Error creating BIGNUM for r"; ++ } ++ ++ auto sBn = BIGNUM_Ptr(BN_bin2bn(ecdsaCoseSignature.data() + 32, 32, nullptr)); ++ if (sBn.get() == nullptr) { ++ return "Error creating BIGNUM for s"; ++ } ++ ++ ECDSA_SIG sig; ++ sig.r = rBn.get(); ++ sig.s = sBn.get(); ++ ++ size_t len = i2d_ECDSA_SIG(&sig, nullptr); ++ bytevec derSignature(len); ++ unsigned char* p = (unsigned char*)derSignature.data(); ++ i2d_ECDSA_SIG(&sig, &p); ++ return derSignature; ++} ++ ++ErrMsgOr ecdsaDerSignatureToCose(const bytevec& ecdsaSignature) { ++ const unsigned char* p = ecdsaSignature.data(); ++ auto sig = ECDSA_SIG_Ptr(d2i_ECDSA_SIG(nullptr, &p, ecdsaSignature.size())); ++ if (sig == nullptr) { ++ return "Error decoding DER signature"; ++ } ++ ++ bytevec ecdsaCoseSignature(64, 0); ++ if (BN_bn2binpad(ECDSA_SIG_get0_r(sig.get()), ecdsaCoseSignature.data(), 32) != 32) { ++ return "Error encoding r"; ++ } ++ if (BN_bn2binpad(ECDSA_SIG_get0_s(sig.get()), ecdsaCoseSignature.data() + 32, 32) != 32) { ++ return "Error encoding s"; ++ } ++ return ecdsaCoseSignature; ++} ++ ErrMsgOr generateHmacSha256(const bytevec& key, const bytevec& data) { -@@ -134,6 +227,17 @@ ErrMsgOr verifyAndParseCoseMac0(const cppbor::Item* macIt + HmacSha256 digest; + unsigned int outLen; +@@ -134,6 +267,20 @@ ErrMsgOr verifyAndParseCoseMac0(const cppbor::Item* macIt return payload->value(); } @@ -125,13 +167,16 @@ index bfe9928..5009bfe 100644 + .add(aad) + .add(payload) + .encode(); -+ return signEcdsaDigest(key, sha256(signatureInput)); ++ auto ecdsaSignature = signEcdsaDigest(key, sha256(signatureInput)); ++ if (!ecdsaSignature) return ecdsaSignature.moveMessage(); ++ ++ return ecdsaDerSignatureToCose(*ecdsaSignature); +} + ErrMsgOr createCoseSign1Signature(const bytevec& key, const bytevec& protectedParams, const bytevec& payload, const bytevec& aad) { bytevec signatureInput = cppbor::Array() -@@ -152,6 +256,19 @@ ErrMsgOr createCoseSign1Signature(const bytevec& key, const bytevec& pr +@@ -152,6 +299,19 @@ ErrMsgOr createCoseSign1Signature(const bytevec& key, const bytevec& pr return signature; } @@ -151,7 +196,7 @@ index bfe9928..5009bfe 100644 ErrMsgOr constructCoseSign1(const bytevec& key, cppbor::Map protectedParams, const bytevec& payload, const bytevec& aad) { bytevec protParms = protectedParams.add(ALGORITHM, EDDSA).canonicalize().encode(); -@@ -193,7 +310,8 @@ ErrMsgOr verifyAndParseCoseSign1(const cppbor::Array* coseSign1, +@@ -193,7 +353,8 @@ ErrMsgOr verifyAndParseCoseSign1(const cppbor::Array* coseSign1, } auto& algorithm = parsedProtParams->asMap()->get(ALGORITHM); @@ -161,7 +206,7 @@ index bfe9928..5009bfe 100644 return "Unsupported signature algorithm"; } -@@ -203,17 +321,30 @@ ErrMsgOr verifyAndParseCoseSign1(const cppbor::Array* coseSign1, +@@ -203,17 +364,36 @@ ErrMsgOr verifyAndParseCoseSign1(const cppbor::Array* coseSign1, } bool selfSigned = signingCoseKey.empty(); @@ -195,19 +240,25 @@ index bfe9928..5009bfe 100644 + auto publicKey = key->getEcPublicKey(); + if (!publicKey) return publicKey.moveMessage(); + -+ if (!verifyEcdsaDigest(publicKey.moveValue(), sha256(signatureInput), signature->value())) { ++ auto ecdsaDerSignature = ecdsaCoseSignatureToDer(signature->value()); ++ if (!ecdsaDerSignature) return ecdsaDerSignature.moveMessage(); ++ ++ // convert public key to uncompressed form by prepending 0x04 at begin. ++ publicKey->insert(publicKey->begin(), 0x04); ++ ++ if (!verifyEcdsaDigest(publicKey.moveValue(), sha256(signatureInput), *ecdsaDerSignature)) { + return "Signature verification failed"; + } } return payload->value(); -@@ -294,28 +425,47 @@ getSenderPubKeyFromCoseEncrypt(const cppbor::Item* coseEncrypt) { +@@ -294,28 +474,47 @@ getSenderPubKeyFromCoseEncrypt(const cppbor::Item* coseEncrypt) { if (!senderCoseKey || !senderCoseKey->asMap()) return "Invalid sender COSE_Key"; auto& keyType = senderCoseKey->asMap()->get(CoseKey::KEY_TYPE); - if (!keyType || !keyType->asInt() || keyType->asInt()->value() != OCTET_KEY_PAIR) { -+ if (!keyType || !keyType->asInt() || (keyType->asInt()->value() != OCTET_KEY_PAIR && -+ keyType->asInt()->value() != EC2)) { ++ if (!keyType || !keyType->asInt() || ++ (keyType->asInt()->value() != OCTET_KEY_PAIR && keyType->asInt()->value() != EC2)) { return "Invalid key type"; } @@ -257,33 +308,48 @@ index bfe9928..5009bfe 100644 } ErrMsgOr decryptCoseEncrypt(const bytevec& key, const cppbor::Item* coseEncrypt, -@@ -367,6 +517,43 @@ ErrMsgOr decryptCoseEncrypt(const bytevec& key, const cppbor::Item* cos +@@ -367,17 +566,12 @@ ErrMsgOr decryptCoseEncrypt(const bytevec& key, const cppbor::Item* cos return aesGcmDecrypt(key, nonce->asBstr()->value(), aad, ciphertext->asBstr()->value()); } +-ErrMsgOr x25519_HKDF_DeriveKey(const bytevec& pubKeyA, const bytevec& privKeyA, +- const bytevec& pubKeyB, bool senderIsA) { ++ErrMsgOr consructKdfContext(const bytevec& pubKeyA, const bytevec& privKeyA, ++ const bytevec& pubKeyB, bool senderIsA) { + if (privKeyA.empty() || pubKeyA.empty() || pubKeyB.empty()) { + return "Missing input key parameters"; + } + +- bytevec rawSharedKey(X25519_SHARED_KEY_LEN); +- if (!::X25519(rawSharedKey.data(), privKeyA.data(), pubKeyB.data())) { +- return "ECDH operation failed"; +- } +- + bytevec kdfContext = cppbor::Array() + .add(AES_GCM_256) + .add(cppbor::Array() // Sender Info +@@ -392,6 +586,51 @@ ErrMsgOr x25519_HKDF_DeriveKey(const bytevec& pubKeyA, const bytevec& p + .add(kAesGcmKeySizeBits) // output key length + .add(bytevec{})) // protected + .encode(); ++ return kdfContext; ++} ++ +ErrMsgOr ECDH_HKDF_DeriveKey(const bytevec& pubKeyA, const bytevec& privKeyA, + const bytevec& pubKeyB, bool senderIsA) { + if (privKeyA.empty() || pubKeyA.empty() || pubKeyB.empty()) { + return "Missing input key parameters"; + } + -+ auto rawSharedKey = ecdh(pubKeyB, privKeyA); ++ // convert public key to uncompressed form by prepending 0x04 at begin ++ bytevec publicKey; ++ publicKey.insert(publicKey.begin(), 0x04); ++ publicKey.insert(publicKey.end(), pubKeyB.begin(), pubKeyB.end()); ++ auto rawSharedKey = ecdh(publicKey, privKeyA); + if (!rawSharedKey) return rawSharedKey.moveMessage(); + -+ bytevec kdfContext = cppbor::Array() -+ .add(AES_GCM_256) -+ .add(cppbor::Array() // Sender Info -+ .add(cppbor::Bstr("client")) -+ .add(bytevec{} /* nonce */) -+ .add(senderIsA ? pubKeyA : pubKeyB)) -+ .add(cppbor::Array() // Recipient Info -+ .add(cppbor::Bstr("server")) -+ .add(bytevec{} /* nonce */) -+ .add(senderIsA ? pubKeyB : pubKeyA)) -+ .add(cppbor::Array() // SuppPubInfo -+ .add(kAesGcmKeySizeBits) // output key length -+ .add(bytevec{})) // protected -+ .encode(); ++ auto kdfContext = consructKdfContext(pubKeyA, privKeyA, pubKeyB, senderIsA); ++ if (!kdfContext) return kdfContext.moveMessage(); + + bytevec retval(SHA256_DIGEST_LENGTH); + bytevec salt{}; @@ -291,17 +357,39 @@ index bfe9928..5009bfe 100644 + EVP_sha256(), // + rawSharedKey->data(), rawSharedKey->size(), // + salt.data(), salt.size(), // -+ kdfContext.data(), kdfContext.size())) { ++ kdfContext->data(), kdfContext->size())) { + return "ECDH HKDF failed"; + } + + return retval; +} + - ErrMsgOr x25519_HKDF_DeriveKey(const bytevec& pubKeyA, const bytevec& privKeyA, - const bytevec& pubKeyB, bool senderIsA) { - if (privKeyA.empty() || pubKeyA.empty() || pubKeyB.empty()) { -@@ -460,4 +647,43 @@ ErrMsgOr aesGcmDecrypt(const bytevec& key, const bytevec& nonce, const ++ErrMsgOr x25519_HKDF_DeriveKey(const bytevec& pubKeyA, const bytevec& privKeyA, ++ const bytevec& pubKeyB, bool senderIsA) { ++ if (privKeyA.empty() || pubKeyA.empty() || pubKeyB.empty()) { ++ return "Missing input key parameters"; ++ } ++ ++ bytevec rawSharedKey(X25519_SHARED_KEY_LEN); ++ if (!::X25519(rawSharedKey.data(), privKeyA.data(), pubKeyB.data())) { ++ return "ECDH operation failed"; ++ } ++ ++ auto kdfContext = consructKdfContext(pubKeyA, privKeyA, pubKeyB, senderIsA); ++ if (!kdfContext) return kdfContext.moveMessage(); + + bytevec retval(SHA256_DIGEST_LENGTH); + bytevec salt{}; +@@ -399,7 +638,7 @@ ErrMsgOr x25519_HKDF_DeriveKey(const bytevec& pubKeyA, const bytevec& p + EVP_sha256(), // + rawSharedKey.data(), rawSharedKey.size(), // + salt.data(), salt.size(), // +- kdfContext.data(), kdfContext.size())) { ++ kdfContext->data(), kdfContext->size())) { + return "ECDH HKDF failed"; + } + +@@ -460,4 +699,43 @@ ErrMsgOr aesGcmDecrypt(const bytevec& key, const bytevec& nonce, const return plaintext; } @@ -346,7 +434,7 @@ index bfe9928..5009bfe 100644 + } // namespace cppcose diff --git a/include/keymaster/cppcose/cppcose.h b/include/keymaster/cppcose/cppcose.h -index 0f97388..03251f1 100644 +index 0f97388..5803d2d 100644 --- a/include/keymaster/cppcose/cppcose.h +++ b/include/keymaster/cppcose/cppcose.h @@ -24,17 +24,25 @@ @@ -355,15 +443,15 @@ index 0f97388..03251f1 100644 #include - +#include -+#include -+#include #include #include #include - #include ++#include +#include + #include #include #include ++#include #include namespace cppcose { @@ -376,64 +464,53 @@ index 0f97388..03251f1 100644 template class ErrMsgOr; using bytevec = std::vector; using HmacSha256 = std::array; -@@ -203,6 +211,41 @@ class CoseKey { +@@ -203,6 +211,25 @@ class CoseKey { return key; } + static ErrMsgOr getEcPublicKey(const bytevec& pubX, const bytevec& pubY) { -+ auto bnX = BIGNUM_Ptr(BN_bin2bn(pubX.data(), pubX.size(), nullptr)); -+ if (bnX.get() == nullptr) { -+ return "Error creating BIGNUM X Coordinate"; ++ if (pubX.empty() || pubY.empty()) { ++ return "Missing input parameters"; + } -+ auto bnY = BIGNUM_Ptr(BN_bin2bn(pubY.data(), pubY.size(), nullptr)); -+ if (bnY.get() == nullptr) { -+ return "Error creating BIGNUM Y Coordinate"; -+ } -+ auto group = EC_GROUP_Ptr(EC_GROUP_new_by_curve_name(NID_X9_62_prime256v1)); -+ auto point = EC_POINT_Ptr(EC_POINT_new(group.get())); -+ if (!point) return "Failed to create EC_POINT instance"; -+ BN_CTX_Ptr ctx(BN_CTX_new()); -+ if (!ctx.get()) return "Failed to create BN_CTX instance"; -+ if (!EC_POINT_set_affine_coordinates_GFp(group.get(), point.get(), bnX.get(), bnY.get(), -+ ctx.get())) { -+ return "Failed to set affine coordinates."; -+ } -+ int size = EC_POINT_point2oct(group.get(), point.get(), POINT_CONVERSION_UNCOMPRESSED, -+ nullptr, 0, nullptr); -+ if (size == 0) { -+ return "Error generating public key encoding"; -+ } -+ bytevec publicKey(size); -+ EC_POINT_point2oct(group.get(), point.get(), POINT_CONVERSION_UNCOMPRESSED, -+ publicKey.data(), publicKey.size(), nullptr); -+ return publicKey; ++ bytevec pubKey; ++ pubKey.insert(pubKey.begin(), pubX.begin(), pubX.end()); ++ pubKey.insert(pubKey.end(), pubY.begin(), pubY.end()); ++ return pubKey; + } + + ErrMsgOr getEcPublicKey() { -+ auto pubX = getBstrValue(PUBKEY_X).value(); -+ auto pubY = getBstrValue(PUBKEY_Y).value(); -+ return getEcPublicKey(pubX, pubY); ++ auto pubX = getBstrValue(PUBKEY_X); ++ auto pubY = getBstrValue(PUBKEY_Y); ++ if (!pubX.has_value() || !pubY.has_value()) { ++ return "Error while getting EC public key from CoseKey."; ++ } ++ return getEcPublicKey(pubX.value(), pubY.value()); + } + std::optional getIntValue(Label label) { const auto& value = key_->get(label); if (!value || !value->asInt()) return {}; -@@ -252,6 +295,8 @@ ErrMsgOr constructCoseSign1(const bytevec& key, const bytevec& pa +@@ -252,6 +279,13 @@ ErrMsgOr constructCoseSign1(const bytevec& key, const bytevec& pa const bytevec& aad); ErrMsgOr constructCoseSign1(const bytevec& key, cppbor::Map extraProtectedFields, const bytevec& payload, const bytevec& aad); -+ErrMsgOr constructECDSACoseSign1(const bytevec& key, cppbor::Map extraProtectedFields, -+ const bytevec& payload, const bytevec& aad); ++ErrMsgOr constructECDSACoseSign1(const bytevec& key, ++ cppbor::Map extraProtectedFields, ++ const bytevec& payload, const bytevec& aad); ++ ++ErrMsgOr ecdsaCoseSignatureToDer(const bytevec& ecdsaCoseSignature); ++ ++ErrMsgOr ecdsaDerSignatureToCose(const bytevec& ecdsaSignature); /** * Verify and parse a COSE_Sign1 message, returning the payload. * -@@ -282,7 +327,10 @@ decryptCoseEncrypt(const bytevec& key, const cppbor::Item* encryptItem, const by +@@ -282,7 +316,10 @@ decryptCoseEncrypt(const bytevec& key, const cppbor::Item* encryptItem, const by ErrMsgOr x25519_HKDF_DeriveKey(const bytevec& senderPubKey, const bytevec& senderPrivKey, const bytevec& recipientPubKey, bool senderIsA); - +ErrMsgOr ECDH_HKDF_DeriveKey(const bytevec& pubKeyA, const bytevec& privKeyA, -+ const bytevec& pubKeyB, bool senderIsA); ++ const bytevec& pubKeyB, bool senderIsA); +bool verifyEcdsaDigest(const bytevec& key, const bytevec& digest, const bytevec& signature); +bytevec sha256(const bytevec& data); ErrMsgOr aesGcmEncrypt(const bytevec& key, const bytevec& nonce, diff --git a/aosp_integration_patches_aosp_12_r15/system_security.patch b/aosp_integration_patches_aosp_12_r15/system_security.patch index 22956d5e..3974e0b1 100644 --- a/aosp_integration_patches_aosp_12_r15/system_security.patch +++ b/aosp_integration_patches_aosp_12_r15/system_security.patch @@ -1,5 +1,5 @@ diff --git a/keystore2/src/km_compat/km_compat.cpp b/keystore2/src/km_compat/km_compat.cpp -index 64849c1..40ca554 100644 +index 64849c16..40ca5547 100644 --- a/keystore2/src/km_compat/km_compat.cpp +++ b/keystore2/src/km_compat/km_compat.cpp @@ -1314,7 +1314,7 @@ KeymasterDevices initializeKeymasters() { From f0fb1cebba41d1aaf15014e09acf9c6eee5bf3cc Mon Sep 17 00:00:00 2001 From: Subrahmanyaman Date: Fri, 1 Apr 2022 04:34:49 +0000 Subject: [PATCH 4/4] Updated goldfish patches --- .../device_generic_goldfish.patch | 15 ++++++++ .../system_sepolicy.patch | 36 ++++++++++--------- 2 files changed, 34 insertions(+), 17 deletions(-) diff --git a/aosp_integration_patches/goldfish_target_only/device_generic_goldfish.patch b/aosp_integration_patches/goldfish_target_only/device_generic_goldfish.patch index d1033185..e565b2d3 100644 --- a/aosp_integration_patches/goldfish_target_only/device_generic_goldfish.patch +++ b/aosp_integration_patches/goldfish_target_only/device_generic_goldfish.patch @@ -13,3 +13,18 @@ index 8b27fd14..09b8588e 100644 PRODUCT_COPY_FILES += \ frameworks/native/data/etc/android.hardware.keystore.app_attest_key.xml:$(TARGET_COPY_OUT_VENDOR)/etc/permissions/android.hardware.keystore.app_attest_key.xml +diff --git a/vendor.mk b/vendor.mk +index bc29713e..b9f23962 100644 +--- a/vendor.mk ++++ b/vendor.mk +@@ -101,7 +101,9 @@ PRODUCT_PACKAGES += \ + android.hardware.neuralnetworks@1.3-service-sample-limited + + PRODUCT_PACKAGES += \ +- android.hardware.security.keymint-service ++ android.hardware.security.keymint-service \ ++ android.hardware.security.keymint-service.strongbox ++ + PRODUCT_COPY_FILES += \ + frameworks/native/data/etc/android.hardware.keystore.app_attest_key.xml:$(TARGET_COPY_OUT_VENDOR)/etc/permissions/android.hardware.keystore.app_attest_key.xml + diff --git a/aosp_integration_patches/goldfish_target_only/system_sepolicy.patch b/aosp_integration_patches/goldfish_target_only/system_sepolicy.patch index d5a78454..6e755295 100644 --- a/aosp_integration_patches/goldfish_target_only/system_sepolicy.patch +++ b/aosp_integration_patches/goldfish_target_only/system_sepolicy.patch @@ -1,8 +1,8 @@ diff --git a/private/service_contexts b/private/service_contexts -index c7f881136..6c3bfc06c 100644 +index cac6ea822..1d076d07a 100644 --- a/private/service_contexts +++ b/private/service_contexts -@@ -53,6 +53,9 @@ android.hardware.security.keymint.IKeyMintDevice/default u:object_r: +@@ -55,6 +55,9 @@ android.hardware.security.keymint.IKeyMintDevice/default u:object_r: android.hardware.security.keymint.IRemotelyProvisionedComponent/default u:object_r:hal_remotelyprovisionedcomponent_service:s0 android.hardware.security.secureclock.ISecureClock/default u:object_r:hal_secureclock_service:s0 android.hardware.security.sharedsecret.ISharedSecret/default u:object_r:hal_sharedsecret_service:s0 @@ -13,34 +13,36 @@ index c7f881136..6c3bfc06c 100644 android.hardware.soundtrigger3.ISoundTriggerHw/default u:object_r:hal_audio_service:s0 android.hardware.tv.tuner.ITuner/default u:object_r:hal_tv_tuner_service:s0 diff --git a/vendor/file_contexts b/vendor/file_contexts -index 0cfb7cf39..65b8a8205 100644 +index 5a8d0aaed..9336123dc 100644 --- a/vendor/file_contexts +++ b/vendor/file_contexts -@@ -84,6 +84,7 @@ +@@ -85,6 +85,7 @@ /(vendor|system/vendor)/bin/hw/android\.hardware\.secure_element@1\.0-service u:object_r:hal_secure_element_default_exec:s0 /(vendor|system/vendor)/bin/hw/android\.hardware\.security\.dice-service\.non-secure-software u:object_r:hal_dice_default_exec:s0 /(vendor|system/vendor)/bin/hw/android\.hardware\.security\.keymint-service u:object_r:hal_keymint_default_exec:s0 -+/vendor/bin/hw/android\.hardware\.security\.keymint-service\.strongbox u:object_r:hal_keymint_strongbox_exec:s0 ++/(vendor|system/vendor)/bin/hw/android\.hardware\.security\.keymint-service\.strongbox u:object_r:hal_keymint_strongbox_exec:s0 /(vendor|system/vendor)/bin/hw/rild u:object_r:rild_exec:s0 /(vendor|system/vendor)/bin/hw/android\.hardware\.thermal@1\.[01]-service u:object_r:hal_thermal_default_exec:s0 /(vendor|system/vendor)/bin/hw/android\.hardware\.tv\.cec@1\.[01]-service u:object_r:hal_tv_cec_default_exec:s0 diff --git a/vendor/hal_keymint_strongbox.te b/vendor/hal_keymint_strongbox.te new file mode 100644 -index 000000000..40cb82c3f +index 000000000..4073d0790 --- /dev/null +++ b/vendor/hal_keymint_strongbox.te -@@ -0,0 +1,14 @@ -+type hal_keymaster_strongbox, domain; -+hal_server_domain(hal_keymaster_strongbox, hal_keymaster) +@@ -0,0 +1,16 @@ ++type hal_keymint_strongbox, domain; ++hal_server_domain(hal_keymint_strongbox, hal_keymint) + -+type hal_keymaster_strongbox_exec, exec_type, vendor_file_type, file_type; -+init_daemon_domain(hal_keymaster_strongbox) ++type hal_keymint_strongbox_exec, exec_type, vendor_file_type, file_type; ++init_daemon_domain(hal_keymint_strongbox) + -+vndbinder_use(hal_keymaster_strongbox) -+get_prop(hal_keymaster_strongbox, vendor_security_patch_level_prop); ++vndbinder_use(hal_keymint_strongbox) ++get_prop(hal_keymint_strongbox, vendor_security_patch_level_prop); ++ ++allow hal_keymint_strongbox secure_element_service:service_manager find; + +# Allow access to sockets -+allow hal_keymaster_strongbox self:tcp_socket { connect create write read getattr getopt setopt }; -+allow hal_keymaster_strongbox port_type:tcp_socket name_connect; -+allow hal_keymaster_strongbox port:tcp_socket { name_connect }; -+allow hal_keymaster_strongbox vendor_data_file:file { open read getattr }; ++allow hal_keymint_strongbox self:tcp_socket { connect create write read getattr getopt setopt }; ++allow hal_keymint_strongbox port_type:tcp_socket name_connect; ++allow hal_keymint_strongbox port:tcp_socket { name_connect }; ++allow hal_keymint_strongbox vendor_data_file:file { open read getattr };