diff --git a/aosp_integration_patches/device_google_cuttlefish.patch b/aosp_integration_patches/device_google_cuttlefish.patch index 1f5e0765..7d8461a6 100644 --- a/aosp_integration_patches/device_google_cuttlefish.patch +++ b/aosp_integration_patches/device_google_cuttlefish.patch @@ -1,8 +1,8 @@ diff --git a/shared/device.mk b/shared/device.mk -index 54042c107..622c6a549 100644 +index 36c66ce18..2f6505d4f 100644 --- a/shared/device.mk +++ b/shared/device.mk -@@ -607,6 +607,9 @@ endif +@@ -622,6 +622,9 @@ endif PRODUCT_PACKAGES += \ $(LOCAL_KEYMINT_PRODUCT_PACKAGE) @@ -13,18 +13,32 @@ index 54042c107..622c6a549 100644 ifneq ($(LOCAL_PREFER_VENDOR_APEX),true) PRODUCT_COPY_FILES += \ diff --git a/shared/sepolicy/vendor/file_contexts b/shared/sepolicy/vendor/file_contexts -index 55b8d964e..a0e88fb2e 100644 +index 6c471b8b8..cc223bdc4 100644 --- a/shared/sepolicy/vendor/file_contexts +++ b/shared/sepolicy/vendor/file_contexts -@@ -85,6 +85,7 @@ - /vendor/bin/hw/android\.hardware\.input\.classifier@1\.0-service.default u:object_r:hal_input_classifier_default_exec:s0 +@@ -93,6 +93,7 @@ /vendor/bin/hw/android\.hardware\.thermal@2\.0-service\.mock u:object_r:hal_thermal_default_exec:s0 + /vendor/bin/hw/android\.hardware\.identity-service\.remote u:object_r:hal_identity_remote_exec:s0 /vendor/bin/hw/android\.hardware\.security\.keymint-service\.remote u:object_r:hal_keymint_remote_exec:s0 +/vendor/bin/hw/android\.hardware\.security\.keymint-service\.strongbox u:object_r:hal_keymint_strongbox_exec:s0 /vendor/bin/hw/android\.hardware\.keymaster@4\.1-service.remote u:object_r:hal_keymaster_remote_exec:s0 /vendor/bin/hw/android\.hardware\.gatekeeper@1\.0-service.remote u:object_r:hal_gatekeeper_remote_exec:s0 /vendor/bin/hw/android\.hardware\.confirmationui@1\.0-service.cuttlefish u:object_r:hal_confirmationui_cuttlefish_exec:s0 -diff --git a/shared/sepolicy/vendor/hal_keymint_strongbox.te b/shared/sepolicy/vendor/hal_keymint_strongbox.te +diff --git a/shared/sepolicy/vendor/service_contexts b/shared/sepolicy/vendor/service_contexts +index c41503e3b..acd78e1ce 100644 +--- a/shared/sepolicy/vendor/service_contexts ++++ b/shared/sepolicy/vendor/service_contexts +@@ -5,6 +5,9 @@ android.hardware.neuralnetworks.IDevice/nnapi-sample_float_slow u:object_r:hal_n + android.hardware.neuralnetworks.IDevice/nnapi-sample_minimal u:object_r:hal_neuralnetworks_service:s0 + android.hardware.neuralnetworks.IDevice/nnapi-sample_quant u:object_r:hal_neuralnetworks_service:s0 + android.hardware.neuralnetworks.IDevice/nnapi-sample_sl_shim u:object_r:hal_neuralnetworks_service:s0 ++android.hardware.security.keymint.IKeyMintDevice/strongbox u:object_r:hal_keymint_service:s0 ++android.hardware.security.sharedsecret.ISharedSecret/strongbox u:object_r:hal_sharedsecret_service:s0 ++android.hardware.security.keymint.IRemotelyProvisionedComponent/strongbox u:object_r:hal_keymint_service:s0 + + # Binder service mappings + gce u:object_r:gce_service:s0 + diff --git a/shared/sepolicy/vendor/hal_keymint_strongbox.te b/shared/sepolicy/vendor/hal_keymint_strongbox.te new file mode 100644 index 000000000..839fd1a6b --- /dev/null @@ -44,17 +58,3 @@ index 000000000..839fd1a6b +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 }; -diff --git a/shared/sepolicy/vendor/service_contexts b/shared/sepolicy/vendor/service_contexts -index d20d026cf..b8f0155ab 100644 ---- a/shared/sepolicy/vendor/service_contexts -+++ b/shared/sepolicy/vendor/service_contexts -@@ -4,6 +4,9 @@ android.hardware.neuralnetworks.IDevice/nnapi-sample_float_slow u:object_r:hal_n - android.hardware.neuralnetworks.IDevice/nnapi-sample_minimal u:object_r:hal_neuralnetworks_service:s0 - android.hardware.neuralnetworks.IDevice/nnapi-sample_quant u:object_r:hal_neuralnetworks_service:s0 - android.hardware.neuralnetworks.IDevice/nnapi-sample_sl_shim u:object_r:hal_neuralnetworks_service:s0 -+android.hardware.security.keymint.IKeyMintDevice/strongbox u:object_r:hal_keymint_service:s0 -+android.hardware.security.sharedsecret.ISharedSecret/strongbox u:object_r:hal_sharedsecret_service:s0 -+android.hardware.security.keymint.IRemotelyProvisionedComponent/strongbox u:object_r:hal_keymint_service:s0 - - # Binder service mappings - gce u:object_r:gce_service:s0 diff --git a/aosp_integration_patches/hardware_interfaces.patch b/aosp_integration_patches/hardware_interfaces.patch index bd06e4cb..9b7797a1 100644 --- a/aosp_integration_patches/hardware_interfaces.patch +++ b/aosp_integration_patches/hardware_interfaces.patch @@ -1,1127 +1,12 @@ diff --git a/compatibility_matrices/compatibility_matrix.current.xml b/compatibility_matrices/compatibility_matrix.current.xml -index c39db36ae..39cce859b 100644 +index 8c5a812b0..8bb513be6 100644 --- a/compatibility_matrices/compatibility_matrix.current.xml +++ b/compatibility_matrices/compatibility_matrix.current.xml -@@ -355,6 +355,7 @@ +@@ -353,6 +353,7 @@ + 1-2 IRemotelyProvisionedComponent - default + strongbox + default - -diff --git a/security/keymint/aidl/vts/functional/AttestKeyTest.cpp b/security/keymint/aidl/vts/functional/AttestKeyTest.cpp -index 64550eff2..49283e8e3 100644 ---- a/security/keymint/aidl/vts/functional/AttestKeyTest.cpp -+++ b/security/keymint/aidl/vts/functional/AttestKeyTest.cpp -@@ -198,7 +198,7 @@ TEST_P(AttestKeyTest, RsaAttestedAttestKeys) { - AttestationKey attest_key; - vector attest_key_characteristics; - vector attest_key_cert_chain; -- ASSERT_EQ(ErrorCode::OK, -+ auto result = - GenerateKey(AuthorizationSetBuilder() - .RsaKey(2048, 65537) - .AttestKey() -@@ -209,7 +209,14 @@ TEST_P(AttestKeyTest, RsaAttestedAttestKeys) { - .Authorization(TAG_NO_AUTH_REQUIRED) - .SetDefaultValidity(), - {} /* attestation signing key */, &attest_key.keyBlob, -- &attest_key_characteristics, &attest_key_cert_chain)); -+ &attest_key_characteristics, &attest_key_cert_chain); -+ //Strongbox does not support Factory provisioned attestation key. -+ if (SecLevel() == SecurityLevel::STRONGBOX) { -+ ASSERT_EQ(ErrorCode::ATTESTATION_KEYS_NOT_PROVISIONED, result); -+ return; -+ } -+ ASSERT_EQ(ErrorCode::OK, result); -+ - - EXPECT_GT(attest_key_cert_chain.size(), 1); - verify_subject_and_serial(attest_key_cert_chain[0], serial_int, subject, false); -@@ -297,7 +304,7 @@ TEST_P(AttestKeyTest, RsaAttestKeyChaining) { - attest_key_opt = attest_key; - } - -- EXPECT_EQ(ErrorCode::OK, -+ auto result = - GenerateKey(AuthorizationSetBuilder() - .RsaKey(2048, 65537) - .AttestKey() -@@ -308,7 +315,14 @@ TEST_P(AttestKeyTest, RsaAttestKeyChaining) { - .Authorization(TAG_CERTIFICATE_SUBJECT, subject_der) - .SetDefaultValidity(), - attest_key_opt, &key_blob_list[i], &attested_key_characteristics, -- &cert_chain_list[i])); -+ &cert_chain_list[i]); -+ // Strongbox does not support Factory provisioned attestation key. -+ if (SecLevel() == SecurityLevel::STRONGBOX) { -+ ASSERT_EQ(ErrorCode::ATTESTATION_KEYS_NOT_PROVISIONED, result); -+ return; -+ } -+ ASSERT_EQ(ErrorCode::OK, result); -+ - - AuthorizationSet hw_enforced = HwEnforcedAuthorizations(attested_key_characteristics); - AuthorizationSet sw_enforced = SwEnforcedAuthorizations(attested_key_characteristics); -@@ -369,7 +383,7 @@ TEST_P(AttestKeyTest, EcAttestKeyChaining) { - attest_key_opt = attest_key; - } - -- EXPECT_EQ(ErrorCode::OK, -+ auto result = - GenerateKey(AuthorizationSetBuilder() - .EcdsaKey(EcCurve::P_256) - .AttestKey() -@@ -380,7 +394,13 @@ TEST_P(AttestKeyTest, EcAttestKeyChaining) { - .Authorization(TAG_NO_AUTH_REQUIRED) - .SetDefaultValidity(), - attest_key_opt, &key_blob_list[i], &attested_key_characteristics, -- &cert_chain_list[i])); -+ &cert_chain_list[i]); -+ // Strongbox does not support Factory provisioned attestation key. -+ if (SecLevel() == SecurityLevel::STRONGBOX) { -+ ASSERT_EQ(ErrorCode::ATTESTATION_KEYS_NOT_PROVISIONED, result); -+ return; -+ } -+ ASSERT_EQ(ErrorCode::OK, result); - - AuthorizationSet hw_enforced = HwEnforcedAuthorizations(attested_key_characteristics); - AuthorizationSet sw_enforced = SwEnforcedAuthorizations(attested_key_characteristics); -@@ -443,8 +463,9 @@ TEST_P(AttestKeyTest, AlternateAttestKeyChaining) { - attest_key_opt = attest_key; - } - -+ ErrorCode result; - if ((i & 0x1) == 1) { -- EXPECT_EQ(ErrorCode::OK, -+ result = - GenerateKey(AuthorizationSetBuilder() - .EcdsaKey(EcCurve::P_256) - .AttestKey() -@@ -455,9 +476,9 @@ TEST_P(AttestKeyTest, AlternateAttestKeyChaining) { - .Authorization(TAG_NO_AUTH_REQUIRED) - .SetDefaultValidity(), - attest_key_opt, &key_blob_list[i], &attested_key_characteristics, -- &cert_chain_list[i])); -+ &cert_chain_list[i]); - } else { -- EXPECT_EQ(ErrorCode::OK, -+ result = - GenerateKey(AuthorizationSetBuilder() - .RsaKey(2048, 65537) - .AttestKey() -@@ -468,8 +489,14 @@ TEST_P(AttestKeyTest, AlternateAttestKeyChaining) { - .Authorization(TAG_NO_AUTH_REQUIRED) - .SetDefaultValidity(), - attest_key_opt, &key_blob_list[i], &attested_key_characteristics, -- &cert_chain_list[i])); -+ &cert_chain_list[i]); -+ } -+ // Strongbox does not support Factory provisioned attestation key. -+ if (SecLevel() == SecurityLevel::STRONGBOX) { -+ ASSERT_EQ(ErrorCode::ATTESTATION_KEYS_NOT_PROVISIONED, result); -+ return; - } -+ ASSERT_EQ(ErrorCode::OK, result); - - AuthorizationSet hw_enforced = HwEnforcedAuthorizations(attested_key_characteristics); - AuthorizationSet sw_enforced = SwEnforcedAuthorizations(attested_key_characteristics); -diff --git a/security/keymint/aidl/vts/functional/KeyMintAidlTestBase.cpp b/security/keymint/aidl/vts/functional/KeyMintAidlTestBase.cpp -index 6140df135..b73d325c6 100644 ---- a/security/keymint/aidl/vts/functional/KeyMintAidlTestBase.cpp -+++ b/security/keymint/aidl/vts/functional/KeyMintAidlTestBase.cpp -@@ -1156,6 +1156,15 @@ vector KeyMintAidlTestBase::InvalidCurves() { - } - } - -+vector KeyMintAidlTestBase::ValidExponents() { -+ if (SecLevel() == SecurityLevel::STRONGBOX) { -+ return {65537}; -+ } else { -+ return {3, 65537}; -+ } -+} -+ -+ - vector KeyMintAidlTestBase::ValidDigests(bool withNone, bool withMD5) { - switch (SecLevel()) { - case SecurityLevel::SOFTWARE: -diff --git a/security/keymint/aidl/vts/functional/KeyMintAidlTestBase.h b/security/keymint/aidl/vts/functional/KeyMintAidlTestBase.h -index 7b3b9d4b4..c564d509a 100644 ---- a/security/keymint/aidl/vts/functional/KeyMintAidlTestBase.h -+++ b/security/keymint/aidl/vts/functional/KeyMintAidlTestBase.h -@@ -250,7 +250,9 @@ class KeyMintAidlTestBase : public ::testing::TestWithParam { - .SetDefaultValidity(); - tagModifier(&rsaBuilder); - errorCode = GenerateKey(rsaBuilder, &rsaKeyData.blob, &rsaKeyData.characteristics); -- EXPECT_EQ(expectedReturn, errorCode); -+ if (!(SecLevel() == SecurityLevel::STRONGBOX && ErrorCode::ATTESTATION_KEYS_NOT_PROVISIONED == errorCode)) { -+ EXPECT_EQ(expectedReturn, errorCode); -+ } - - /* ECDSA */ - KeyData ecdsaKeyData; -@@ -262,7 +264,10 @@ class KeyMintAidlTestBase : public ::testing::TestWithParam { - .SetDefaultValidity(); - tagModifier(&ecdsaBuilder); - errorCode = GenerateKey(ecdsaBuilder, &ecdsaKeyData.blob, &ecdsaKeyData.characteristics); -- EXPECT_EQ(expectedReturn, errorCode); -+ if (!(SecLevel() == SecurityLevel::STRONGBOX && ErrorCode::ATTESTATION_KEYS_NOT_PROVISIONED == errorCode)) { -+ EXPECT_EQ(expectedReturn, errorCode); -+ } -+ - return {aesKeyData, hmacKeyData, rsaKeyData, ecdsaKeyData}; - } - bool IsSecure() const { return securityLevel_ != SecurityLevel::SOFTWARE; } -@@ -279,6 +284,7 @@ class KeyMintAidlTestBase : public ::testing::TestWithParam { - vector InvalidCurves(); - - vector ValidDigests(bool withNone, bool withMD5); -+ vector ValidExponents(); - - static vector build_params() { - auto params = ::android::getAidlHalInstanceNames(IKeyMintDevice::descriptor); -diff --git a/security/keymint/aidl/vts/functional/KeyMintTest.cpp b/security/keymint/aidl/vts/functional/KeyMintTest.cpp -index 2a7911cc3..639b2a5dc 100644 ---- a/security/keymint/aidl/vts/functional/KeyMintTest.cpp -+++ b/security/keymint/aidl/vts/functional/KeyMintTest.cpp -@@ -912,8 +912,8 @@ TEST_P(NewKeyGenerationTest, RsaWithAttestation) { - for (auto key_size : ValidKeySizes(Algorithm::RSA)) { - vector key_blob; - vector key_characteristics; -- ASSERT_EQ(ErrorCode::OK, -- GenerateKey(AuthorizationSetBuilder() -+ -+ auto result = GenerateKey(AuthorizationSetBuilder() - .RsaSigningKey(key_size, 65537) - .Digest(Digest::NONE) - .Padding(PaddingMode::NONE) -@@ -923,8 +923,14 @@ TEST_P(NewKeyGenerationTest, RsaWithAttestation) { - .Authorization(TAG_CERTIFICATE_SERIAL, serial_blob) - .Authorization(TAG_CERTIFICATE_SUBJECT, subject_der) - .SetDefaultValidity(), -- &key_blob, &key_characteristics)); -+ &key_blob, &key_characteristics); - -+ // Strongbox does not support Factory provisioned attestation key -+ if (SecLevel() == SecurityLevel::STRONGBOX) { -+ ASSERT_EQ(ErrorCode::ATTESTATION_KEYS_NOT_PROVISIONED, result); -+ return; -+ } -+ ASSERT_EQ(ErrorCode::OK, result); - ASSERT_GT(key_blob.size(), 0U); - CheckBaseParams(key_characteristics); - CheckCharacteristics(key_blob, key_characteristics); -@@ -1045,8 +1051,7 @@ TEST_P(NewKeyGenerationTest, RsaEncryptionWithAttestation) { - - vector key_blob; - vector key_characteristics; -- ASSERT_EQ(ErrorCode::OK, -- GenerateKey(AuthorizationSetBuilder() -+ auto result = GenerateKey(AuthorizationSetBuilder() - .RsaEncryptionKey(key_size, 65537) - .Padding(PaddingMode::NONE) - .AttestationChallenge(challenge) -@@ -1055,8 +1060,14 @@ TEST_P(NewKeyGenerationTest, RsaEncryptionWithAttestation) { - .Authorization(TAG_CERTIFICATE_SERIAL, serial_blob) - .Authorization(TAG_CERTIFICATE_SUBJECT, subject_der) - .SetDefaultValidity(), -- &key_blob, &key_characteristics)); -+ &key_blob, &key_characteristics); - -+ // Strongbox does not support Factory provisioned attestation key -+ if (SecLevel() == SecurityLevel::STRONGBOX) { -+ ASSERT_EQ(ErrorCode::ATTESTATION_KEYS_NOT_PROVISIONED, result); -+ return; -+ } -+ ASSERT_EQ(ErrorCode::OK, result); - ASSERT_GT(key_blob.size(), 0U); - AuthorizationSet auths; - for (auto& entry : key_characteristics) { -@@ -1157,15 +1168,21 @@ TEST_P(NewKeyGenerationTest, RsaWithAttestationMissAppId) { - vector key_blob; - vector key_characteristics; - -- ASSERT_EQ(ErrorCode::ATTESTATION_APPLICATION_ID_MISSING, -- GenerateKey(AuthorizationSetBuilder() -+ auto result = GenerateKey(AuthorizationSetBuilder() - .RsaSigningKey(2048, 65537) - .Digest(Digest::NONE) - .Padding(PaddingMode::NONE) - .AttestationChallenge(challenge) - .Authorization(TAG_NO_AUTH_REQUIRED) - .SetDefaultValidity(), -- &key_blob, &key_characteristics)); -+ &key_blob, &key_characteristics); -+ -+ // Strongbox does not support Factory provisioned attestation key -+ if (SecLevel() == SecurityLevel::STRONGBOX) { -+ ASSERT_EQ(ErrorCode::ATTESTATION_KEYS_NOT_PROVISIONED, result); -+ return; -+ } -+ ASSERT_EQ(ErrorCode::ATTESTATION_APPLICATION_ID_MISSING, result); - } - - /* -@@ -1275,8 +1292,8 @@ TEST_P(NewKeyGenerationTest, LimitedUsageRsaWithAttestation) { - for (auto key_size : ValidKeySizes(Algorithm::RSA)) { - vector key_blob; - vector key_characteristics; -- ASSERT_EQ(ErrorCode::OK, -- GenerateKey(AuthorizationSetBuilder() -+ -+ auto result = GenerateKey(AuthorizationSetBuilder() - .RsaSigningKey(key_size, 65537) - .Digest(Digest::NONE) - .Padding(PaddingMode::NONE) -@@ -1287,7 +1304,14 @@ TEST_P(NewKeyGenerationTest, LimitedUsageRsaWithAttestation) { - .Authorization(TAG_CERTIFICATE_SERIAL, serial_blob) - .Authorization(TAG_CERTIFICATE_SUBJECT, subject_der) - .SetDefaultValidity(), -- &key_blob, &key_characteristics)); -+ &key_blob, &key_characteristics); -+ -+ //Strongbox does not support Factory provisioned attestation key -+ if (SecLevel() == SecurityLevel::STRONGBOX) { -+ ASSERT_EQ(ErrorCode::ATTESTATION_KEYS_NOT_PROVISIONED, result); -+ return; -+ } -+ ASSERT_EQ(ErrorCode::OK, result); - - ASSERT_GT(key_blob.size(), 0U); - CheckBaseParams(key_characteristics); -@@ -1418,8 +1442,8 @@ TEST_P(NewKeyGenerationTest, EcdsaAttestation) { - for (auto curve : ValidCurves()) { - vector key_blob; - vector key_characteristics; -- ASSERT_EQ(ErrorCode::OK, -- GenerateKey(AuthorizationSetBuilder() -+ -+ auto result = GenerateKey(AuthorizationSetBuilder() - .Authorization(TAG_NO_AUTH_REQUIRED) - .EcdsaSigningKey(curve) - .Digest(Digest::NONE) -@@ -1428,7 +1452,15 @@ TEST_P(NewKeyGenerationTest, EcdsaAttestation) { - .Authorization(TAG_CERTIFICATE_SERIAL, serial_blob) - .Authorization(TAG_CERTIFICATE_SUBJECT, subject_der) - .SetDefaultValidity(), -- &key_blob, &key_characteristics)); -+ &key_blob, &key_characteristics); -+ -+ //Strongbox does not support Factory provisioned attestation key -+ if (SecLevel() == SecurityLevel::STRONGBOX) { -+ ASSERT_EQ(ErrorCode::ATTESTATION_KEYS_NOT_PROVISIONED, result); -+ return; -+ } -+ ASSERT_EQ(ErrorCode::OK, result); -+ - ASSERT_GT(key_blob.size(), 0U); - CheckBaseParams(key_characteristics); - CheckCharacteristics(key_blob, key_characteristics); -@@ -1506,6 +1538,12 @@ TEST_P(NewKeyGenerationTest, EcdsaAttestationTags) { - // Tag not required to be supported by all KeyMint implementations. - continue; - } -+ -+ //Strongbox does not support Factory provisioned attestation key -+ if (SecLevel() == SecurityLevel::STRONGBOX) { -+ ASSERT_EQ(ErrorCode::ATTESTATION_KEYS_NOT_PROVISIONED, result); -+ continue; -+ } - ASSERT_EQ(result, ErrorCode::OK); - ASSERT_GT(key_blob.size(), 0U); - -@@ -1555,8 +1593,14 @@ TEST_P(NewKeyGenerationTest, EcdsaAttestationTags) { - .Authorization(TAG_CERTIFICATE_SUBJECT, subject_der) - .SetDefaultValidity(); - builder.push_back(tag); -- ASSERT_EQ(ErrorCode::CANNOT_ATTEST_IDS, -- GenerateKey(builder, &key_blob, &key_characteristics)); -+ -+ auto result = GenerateKey(builder, &key_blob, &key_characteristics); -+ //Strongbox does not support Factory provisioned attestation key -+ if (SecLevel() == SecurityLevel::STRONGBOX) { -+ ASSERT_EQ(ErrorCode::ATTESTATION_KEYS_NOT_PROVISIONED, result); -+ continue; -+ } -+ ASSERT_EQ(ErrorCode::CANNOT_ATTEST_IDS, result); - } - } - -@@ -1756,6 +1800,13 @@ TEST_P(NewKeyGenerationTest, EcdsaAttestationTagNoApplicationId) { - .Authorization(TAG_CERTIFICATE_SUBJECT, subject_der) - .SetDefaultValidity(), - &key_blob, &key_characteristics); -+ -+ // Strongbox does not support Factory provisioned attestation key -+ if (SecLevel() == SecurityLevel::STRONGBOX) { -+ ASSERT_EQ(ErrorCode::ATTESTATION_KEYS_NOT_PROVISIONED, result); -+ return; -+ } -+ - ASSERT_EQ(result, ErrorCode::OK); - ASSERT_GT(key_blob.size(), 0U); - -@@ -1834,13 +1885,19 @@ TEST_P(NewKeyGenerationTest, EcdsaAttestationRequireAppId) { - vector key_blob; - vector key_characteristics; - -- ASSERT_EQ(ErrorCode::ATTESTATION_APPLICATION_ID_MISSING, -- GenerateKey(AuthorizationSetBuilder() -+ auto result = GenerateKey(AuthorizationSetBuilder() - .EcdsaSigningKey(EcCurve::P_256) - .Digest(Digest::NONE) - .AttestationChallenge(challenge) - .SetDefaultValidity(), -- &key_blob, &key_characteristics)); -+ &key_blob, &key_characteristics); -+ -+ // Strongbox does not support Factory provisioned attestation key -+ if (SecLevel() == SecurityLevel::STRONGBOX) { -+ ASSERT_EQ(ErrorCode::ATTESTATION_KEYS_NOT_PROVISIONED, result); -+ return; -+ } -+ ASSERT_EQ(ErrorCode::ATTESTATION_APPLICATION_ID_MISSING, result); - } - - /* -@@ -1897,14 +1954,21 @@ TEST_P(NewKeyGenerationTest, AttestationApplicationIDLengthProperlyEncoded) { - const string app_id(length, 'a'); - vector key_blob; - vector key_characteristics; -- ASSERT_EQ(ErrorCode::OK, GenerateKey(AuthorizationSetBuilder() -+ auto result = GenerateKey(AuthorizationSetBuilder() - .Authorization(TAG_NO_AUTH_REQUIRED) - .EcdsaSigningKey(EcCurve::P_256) - .Digest(Digest::NONE) - .AttestationChallenge(challenge) - .AttestationApplicationId(app_id) - .SetDefaultValidity(), -- &key_blob, &key_characteristics)); -+ &key_blob, &key_characteristics); -+ //Strongbox does not support Factory provisioned attestation key -+ if (SecLevel() == SecurityLevel::STRONGBOX) { -+ ASSERT_EQ(ErrorCode::ATTESTATION_KEYS_NOT_PROVISIONED, result); -+ return; -+ } -+ ASSERT_EQ(ErrorCode::OK, result); -+ - ASSERT_GT(key_blob.size(), 0U); - CheckBaseParams(key_characteristics); - CheckCharacteristics(key_blob, key_characteristics); -@@ -3945,25 +4009,27 @@ typedef KeyMintAidlTestBase EncryptionOperationsTest; - * Verifies that raw RSA decryption works. - */ - TEST_P(EncryptionOperationsTest, RsaNoPaddingSuccess) { -- for (uint64_t exponent : {3, 65537}) { -- ASSERT_EQ(ErrorCode::OK, GenerateKey(AuthorizationSetBuilder() -- .Authorization(TAG_NO_AUTH_REQUIRED) -- .RsaEncryptionKey(2048, exponent) -- .Padding(PaddingMode::NONE) -- .SetDefaultValidity())); - -- string message = string(2048 / 8, 'a'); -- auto params = AuthorizationSetBuilder().Padding(PaddingMode::NONE); -- string ciphertext1 = LocalRsaEncryptMessage(message, params); -- EXPECT_EQ(2048U / 8, ciphertext1.size()); -+ for (uint64_t exponent : ValidExponents()) -+ { -+ ASSERT_EQ(ErrorCode::OK, GenerateKey(AuthorizationSetBuilder() -+ .Authorization(TAG_NO_AUTH_REQUIRED) -+ .RsaEncryptionKey(2048, exponent) -+ .Padding(PaddingMode::NONE) -+ .SetDefaultValidity())); - -- string ciphertext2 = LocalRsaEncryptMessage(message, params); -- EXPECT_EQ(2048U / 8, ciphertext2.size()); -+ string message = string(2048 / 8, 'a'); -+ auto params = AuthorizationSetBuilder().Padding(PaddingMode::NONE); -+ string ciphertext1 = LocalRsaEncryptMessage(message, params); -+ EXPECT_EQ(2048U / 8, ciphertext1.size()); - -- // Unpadded RSA is deterministic -- EXPECT_EQ(ciphertext1, ciphertext2); -+ string ciphertext2 = LocalRsaEncryptMessage(message, params); -+ EXPECT_EQ(2048U / 8, ciphertext2.size()); - -- CheckedDeleteKey(); -+ // Unpadded RSA is deterministic -+ EXPECT_EQ(ciphertext1, ciphertext2); -+ -+ CheckedDeleteKey(); - } - } - -@@ -6503,7 +6569,7 @@ TEST_P(ClearOperationsTest, TooManyOperations) { - size_t i; - - for (i = 0; i < max_operations; i++) { -- result = Begin(KeyPurpose::ENCRYPT, key_blob_, params, &out_params, op_handles[i]); -+ result = Begin(KeyPurpose::DECRYPT, key_blob_, params, &out_params, op_handles[i]); - if (ErrorCode::OK != result) { - break; - } -@@ -6511,12 +6577,12 @@ TEST_P(ClearOperationsTest, TooManyOperations) { - EXPECT_EQ(ErrorCode::TOO_MANY_OPERATIONS, result); - // Try again just in case there's a weird overflow bug - EXPECT_EQ(ErrorCode::TOO_MANY_OPERATIONS, -- Begin(KeyPurpose::ENCRYPT, key_blob_, params, &out_params)); -+ Begin(KeyPurpose::DECRYPT, key_blob_, params, &out_params)); - for (size_t j = 0; j < i; j++) { - EXPECT_EQ(ErrorCode::OK, Abort(op_handles[j])) - << "Aboort failed for i = " << j << std::endl; - } -- EXPECT_EQ(ErrorCode::OK, Begin(KeyPurpose::ENCRYPT, key_blob_, params, &out_params)); -+ EXPECT_EQ(ErrorCode::OK, Begin(KeyPurpose::DECRYPT, key_blob_, params, &out_params)); - AbortIfNeeded(); - } - -@@ -6615,7 +6681,6 @@ TEST_P(KeyAgreementTest, Ecdh) { - OPENSSL_free(p); - - // Generate EC key in KeyMint (only access to public key material) -- vector challenge = {0x41, 0x42}; - EXPECT_EQ( - ErrorCode::OK, - GenerateKey(AuthorizationSetBuilder() -@@ -6624,7 +6689,6 @@ TEST_P(KeyAgreementTest, Ecdh) { - .Authorization(TAG_PURPOSE, KeyPurpose::AGREE_KEY) - .Authorization(TAG_ALGORITHM, Algorithm::EC) - .Authorization(TAG_ATTESTATION_APPLICATION_ID, {0x61, 0x62}) -- .Authorization(TAG_ATTESTATION_CHALLENGE, challenge) - .SetDefaultValidity())) - << "Failed to generate key"; - ASSERT_GT(cert_chain_.size(), 0); -@@ -6704,14 +6768,24 @@ TEST_P(EarlyBootKeyTest, CreateEarlyBootKeys) { - CreateTestKeys(TAG_EARLY_BOOT_ONLY, ErrorCode::OK); - - for (const auto& keyData : {aesKeyData, hmacKeyData, rsaKeyData, ecdsaKeyData}) { -+ -+ if (SecLevel() == SecurityLevel::STRONGBOX && keyData.blob.size() == 0U) { -+ continue; -+ } - ASSERT_GT(keyData.blob.size(), 0U); - AuthorizationSet crypto_params = SecLevelAuthorizations(keyData.characteristics); - EXPECT_TRUE(crypto_params.Contains(TAG_EARLY_BOOT_ONLY)) << crypto_params; - } - CheckedDeleteKey(&aesKeyData.blob); - CheckedDeleteKey(&hmacKeyData.blob); -- CheckedDeleteKey(&rsaKeyData.blob); -- CheckedDeleteKey(&ecdsaKeyData.blob); -+ -+ if (rsaKeyData.blob.size() != 0U) { -+ CheckedDeleteKey(&rsaKeyData.blob); -+ } -+ if (ecdsaKeyData.blob.size() != 0U) { -+ CheckedDeleteKey(&ecdsaKeyData.blob); -+ } -+ - } - - /* -@@ -6727,14 +6801,21 @@ TEST_P(EarlyBootKeyTest, CreateAttestedEarlyBootKey) { - }); - - for (const auto& keyData : {aesKeyData, hmacKeyData, rsaKeyData, ecdsaKeyData}) { -+ if (SecLevel() == SecurityLevel::STRONGBOX && keyData.blob.size() == 0U) { -+ continue; -+ } - ASSERT_GT(keyData.blob.size(), 0U); - AuthorizationSet crypto_params = SecLevelAuthorizations(keyData.characteristics); - EXPECT_TRUE(crypto_params.Contains(TAG_EARLY_BOOT_ONLY)) << crypto_params; - } - CheckedDeleteKey(&aesKeyData.blob); - CheckedDeleteKey(&hmacKeyData.blob); -- CheckedDeleteKey(&rsaKeyData.blob); -- CheckedDeleteKey(&ecdsaKeyData.blob); -+ if (rsaKeyData.blob.size() != 0U) { -+ CheckedDeleteKey(&rsaKeyData.blob); -+ } -+ if (ecdsaKeyData.blob.size() != 0U) { -+ CheckedDeleteKey(&ecdsaKeyData.blob); -+ } - } - - /* -diff --git a/security/keymint/aidl/vts/functional/VtsRemotelyProvisionedComponentTests.cpp b/security/keymint/aidl/vts/functional/VtsRemotelyProvisionedComponentTests.cpp -index 76fb79b61..6e57d913b 100644 ---- a/security/keymint/aidl/vts/functional/VtsRemotelyProvisionedComponentTests.cpp -+++ b/security/keymint/aidl/vts/functional/VtsRemotelyProvisionedComponentTests.cpp -@@ -164,6 +164,7 @@ class VtsRemotelyProvisionedComponentTests : public testing::TestWithParamgetHardwareInfo(&rpcHardwareInfo).isOk()); - } - - static vector build_params() { -@@ -173,6 +174,7 @@ class VtsRemotelyProvisionedComponentTests : public testing::TestWithParam provisionable_; -+ RpcHardwareInfo rpcHardwareInfo; - }; - - using GenerateKeyTests = VtsRemotelyProvisionedComponentTests; -@@ -273,11 +275,10 @@ TEST_P(GenerateKeyTests, generateEcdsaP256Key_testMode) { - class CertificateRequestTest : public VtsRemotelyProvisionedComponentTests { - protected: - CertificateRequestTest() : eekId_(string_to_bytevec("eekid")), challenge_(randomBytes(32)) { -- generateTestEekChain(3); - } - - void generateTestEekChain(size_t eekLength) { -- auto chain = generateEekChain(eekLength, eekId_); -+ auto chain = generateEekChain(rpcHardwareInfo.supportedEekCurve, eekLength, eekId_); - EXPECT_TRUE(chain) << chain.message(); - if (chain) testEekChain_ = chain.moveValue(); - testEekLength_ = eekLength; -@@ -298,6 +299,17 @@ class CertificateRequestTest : public VtsRemotelyProvisionedComponentTests { - } - } - -+ ErrMsgOr getSessionKey(ErrMsgOr>& senderPubkey) { -+ if (rpcHardwareInfo.supportedEekCurve == RpcHardwareInfo::CURVE_25519 || -+ rpcHardwareInfo.supportedEekCurve == RpcHardwareInfo::CURVE_NONE) { -+ return x25519_HKDF_DeriveKey(testEekChain_.last_pubkey, testEekChain_.last_privkey, -+ senderPubkey->first, false /* senderIsA */); -+ } else { -+ return ECDH_HKDF_DeriveKey(testEekChain_.last_pubkey, testEekChain_.last_privkey, -+ senderPubkey->first, false /* senderIsA */); -+ } -+ } -+ - void checkProtectedData(const DeviceInfo& deviceInfo, const cppbor::Array& keysToSign, - const bytevec& keysToSignMac, const ProtectedData& protectedData, - std::vector* bccOutput = nullptr) { -@@ -310,9 +322,7 @@ class CertificateRequestTest : public VtsRemotelyProvisionedComponentTests { - ASSERT_TRUE(senderPubkey) << senderPubkey.message(); - EXPECT_EQ(senderPubkey->second, eekId_); - -- auto sessionKey = -- x25519_HKDF_DeriveKey(testEekChain_.last_pubkey, testEekChain_.last_privkey, -- senderPubkey->first, false /* senderIsA */); -+ auto sessionKey = getSessionKey(senderPubkey); - ASSERT_TRUE(sessionKey) << sessionKey.message(); - - auto protectedDataPayload = -@@ -322,7 +332,7 @@ class CertificateRequestTest : public VtsRemotelyProvisionedComponentTests { - auto [parsedPayload, __, payloadErrMsg] = cppbor::parse(*protectedDataPayload); - ASSERT_TRUE(parsedPayload) << "Failed to parse payload: " << payloadErrMsg; - ASSERT_TRUE(parsedPayload->asArray()); -- EXPECT_EQ(parsedPayload->asArray()->size(), 2U); -+ EXPECT_LE(parsedPayload->asArray()->size(), 3U); - - auto& signedMac = parsedPayload->asArray()->get(0); - auto& bcc = parsedPayload->asArray()->get(1); -@@ -406,6 +416,7 @@ TEST_P(CertificateRequestTest, NewKeyPerCallInTestMode) { - bytevec keysToSignMac; - DeviceInfo deviceInfo; - ProtectedData protectedData; -+ generateTestEekChain(3); - auto status = provisionable_->generateCertificateRequest( - testMode, {} /* keysToSign */, testEekChain_.chain, challenge_, &deviceInfo, - &protectedData, &keysToSignMac); -@@ -445,7 +456,7 @@ TEST_P(CertificateRequestTest, DISABLED_EmptyRequest_prodMode) { - DeviceInfo deviceInfo; - ProtectedData protectedData; - auto status = provisionable_->generateCertificateRequest( -- testMode, {} /* keysToSign */, getProdEekChain(), challenge_, &deviceInfo, -+ testMode, {} /* keysToSign */, getProdEekChain(rpcHardwareInfo.supportedEekCurve), challenge_, &deviceInfo, - &protectedData, &keysToSignMac); - EXPECT_TRUE(status.isOk()); - } -@@ -486,7 +497,7 @@ TEST_P(CertificateRequestTest, DISABLED_NonEmptyRequest_prodMode) { - DeviceInfo deviceInfo; - ProtectedData protectedData; - auto status = provisionable_->generateCertificateRequest( -- testMode, keysToSign_, getProdEekChain(), challenge_, &deviceInfo, &protectedData, -+ testMode, keysToSign_, getProdEekChain(rpcHardwareInfo.supportedEekCurve), challenge_, &deviceInfo, &protectedData, - &keysToSignMac); - EXPECT_TRUE(status.isOk()); - } -@@ -502,6 +513,7 @@ TEST_P(CertificateRequestTest, NonEmptyRequestCorruptMac_testMode) { - bytevec keysToSignMac; - DeviceInfo deviceInfo; - ProtectedData protectedData; -+ generateTestEekChain(3); - auto status = provisionable_->generateCertificateRequest( - testMode, {keyWithCorruptMac}, testEekChain_.chain, challenge_, &deviceInfo, - &protectedData, &keysToSignMac); -@@ -521,7 +533,7 @@ TEST_P(CertificateRequestTest, NonEmptyRequestCorruptMac_prodMode) { - DeviceInfo deviceInfo; - ProtectedData protectedData; - auto status = provisionable_->generateCertificateRequest( -- testMode, {keyWithCorruptMac}, getProdEekChain(), challenge_, &deviceInfo, -+ testMode, {keyWithCorruptMac}, getProdEekChain(rpcHardwareInfo.supportedEekCurve), challenge_, &deviceInfo, - &protectedData, &keysToSignMac); - ASSERT_FALSE(status.isOk()) << status.getMessage(); - EXPECT_EQ(status.getServiceSpecificError(), BnRemotelyProvisionedComponent::STATUS_INVALID_MAC); -@@ -535,7 +547,7 @@ TEST_P(CertificateRequestTest, NonEmptyCorruptEekRequest_prodMode) { - bool testMode = false; - generateKeys(testMode, 4 /* numKeys */); - -- auto prodEekChain = getProdEekChain(); -+ auto prodEekChain = getProdEekChain(rpcHardwareInfo.supportedEekCurve); - auto [parsedChain, _, parseErr] = cppbor::parse(prodEekChain); - ASSERT_NE(parsedChain, nullptr) << parseErr; - ASSERT_NE(parsedChain->asArray(), nullptr); -@@ -566,7 +578,7 @@ TEST_P(CertificateRequestTest, NonEmptyIncompleteEekRequest_prodMode) { - - // Build an EEK chain that omits the first self-signed cert. - auto truncatedChain = cppbor::Array(); -- auto [chain, _, parseErr] = cppbor::parse(getProdEekChain()); -+ auto [chain, _, parseErr] = cppbor::parse(getProdEekChain(rpcHardwareInfo.supportedEekCurve)); - ASSERT_TRUE(chain); - auto eekChain = chain->asArray(); - ASSERT_NE(eekChain, nullptr); -@@ -594,6 +606,7 @@ TEST_P(CertificateRequestTest, NonEmptyRequest_prodKeyInTestCert) { - bytevec keysToSignMac; - DeviceInfo deviceInfo; - ProtectedData protectedData; -+ generateTestEekChain(3); - auto status = provisionable_->generateCertificateRequest( - true /* testMode */, keysToSign_, testEekChain_.chain, challenge_, &deviceInfo, - &protectedData, &keysToSignMac); -@@ -612,6 +625,7 @@ TEST_P(CertificateRequestTest, NonEmptyRequest_testKeyInProdCert) { - bytevec keysToSignMac; - DeviceInfo deviceInfo; - ProtectedData protectedData; -+ generateTestEekChain(3); - auto status = provisionable_->generateCertificateRequest( - false /* testMode */, keysToSign_, testEekChain_.chain, challenge_, &deviceInfo, - &protectedData, &keysToSignMac); -diff --git a/security/keymint/support/Android.bp b/security/keymint/support/Android.bp -index 36969bbdb..b3552d38b 100644 ---- a/security/keymint/support/Android.bp -+++ b/security/keymint/support/Android.bp -@@ -66,6 +66,7 @@ cc_library { - "libcppcose_rkp", - "libcrypto", - "libjsoncpp", -+ "android.hardware.security.keymint-V1-ndk", - ], - } - -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 ---- 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[] = { - 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}; -+ - /** - * 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. - */ --ErrMsgOr generateEekChain(size_t length, const bytevec& eekId); -+ErrMsgOr generateEekChain(int32_t supportedEekCurve, size_t length, const bytevec& eekId); - - /** - * Returns the CBOR-encoded, production Google Endpoint Encryption Key chain. - */ --bytevec getProdEekChain(); -+bytevec getProdEekChain(int32_t supportedEekCurve); - - 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 ---- a/security/keymint/support/remote_prov_utils.cpp -+++ b/security/keymint/support/remote_prov_utils.cpp -@@ -17,15 +17,195 @@ - #include - #include - -+#include - #include - #include - #include -+#include -+#include -+#include -+#include - #include -+#include - #include - #include - - namespace aidl::android::hardware::security::keymint::remote_prov { - -+constexpr int kP256AffinePointSize = 32; -+ -+using EC_KEY_Ptr = bssl::UniquePtr; -+using EVP_PKEY_Ptr = bssl::UniquePtr; -+using EVP_PKEY_CTX_Ptr = bssl::UniquePtr; -+ -+ErrMsgOr ecKeyGetPrivateKey(const EC_KEY* ecKey) { -+ // Extract private key. -+ const BIGNUM* bignum = EC_KEY_get0_private_key(ecKey); -+ 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. -+ bytevec privKey(32, 0); -+ BN_bn2bin(bignum, privKey.data() + 32 - size); -+ return privKey; -+} -+ -+ErrMsgOr ecKeyGetPublicKey(const EC_KEY* ecKey) { -+ // Extract public key. -+ 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"; -+ } -+ 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); -+ 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(), -+ 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)); -+ 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) { -+ return "Error decoding publicKey"; -+ } -+ BIGNUM_Ptr x(BN_new()); -+ BIGNUM_Ptr y(BN_new()); -+ 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(), -+ 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(y.get(), pubY.data(), kP256AffinePointSize) != -+ kP256AffinePointSize) { -+ return "Error in converting absolute value of y cordinate to big-endian"; -+ } -+ return std::make_tuple(std::move(pubX), std::move(pubY)); -+} -+ -+ErrMsgOr> generateEc256KeyPair() { -+ auto ec_key = EC_KEY_Ptr(EC_KEY_new()); -+ if (ec_key.get() == nullptr) { -+ return "Failed to allocate ec key"; -+ } -+ -+ 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"; -+ } -+ -+ if (EC_KEY_set_group(ec_key.get(), group.get()) != 1 || -+ EC_KEY_generate_key(ec_key.get()) != 1 || EC_KEY_check_key(ec_key.get()) < 0) { -+ return "Error generating key"; -+ } -+ -+ auto privKey = ecKeyGetPrivateKey(ec_key.get()); -+ if (!privKey) return privKey.moveMessage(); -+ -+ auto pubKey = ecKeyGetPublicKey(ec_key.get()); -+ if (!pubKey) return pubKey.moveMessage(); -+ -+ return std::make_tuple(pubKey.moveValue(), privKey.moveValue()); -+} -+ -+ErrMsgOr> generateX25519KeyPair() { -+ /* Generate X25519 key pair */ -+ bytevec pubKey(X25519_PUBLIC_VALUE_LEN); -+ bytevec privKey(X25519_PRIVATE_KEY_LEN); -+ X25519_keypair(pubKey.data(), privKey.data()); -+ return std::make_tuple(std::move(pubKey), std::move(privKey)); -+} -+ -+ErrMsgOr> generateED25519KeyPair() { -+ /* Generate ED25519 key pair */ -+ bytevec pubKey(ED25519_PUBLIC_KEY_LEN); -+ bytevec privKey(ED25519_PRIVATE_KEY_LEN); -+ ED25519_keypair(pubKey.data(), privKey.data()); -+ return std::make_tuple(std::move(pubKey), std::move(privKey)); -+} -+ -+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."; -+ } -+} -+ -+ErrMsgOr constructCoseKey(int32_t supportedEekCurve, const bytevec& eekId, -+ const bytevec& pubKey) { -+ CoseKeyType keyType; -+ CoseKeyAlgorithm algorithm; -+ CoseKeyCurve curve; -+ 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; -+ curve = (eekId.empty()) ? ED25519 : cppcose::X25519; -+ pubX = pubKey; -+ break; -+ case RpcHardwareInfo::CURVE_P256: { -+ keyType = EC2; -+ algorithm = (eekId.empty()) ? ES256 : ECDH_ES_HKDF_256; -+ curve = P256; -+ auto affineCoordinates = getAffineCoordinates(pubKey); -+ if (!affineCoordinates) return affineCoordinates.moveMessage(); -+ std::tie(pubX, pubY) = affineCoordinates.moveValue(); -+ } break; -+ default: -+ return "Unknown EEK Curve."; -+ } -+ cppbor::Map coseKey = cppbor::Map() -+ .add(CoseKey::KEY_TYPE, keyType) -+ .add(CoseKey::ALGORITHM, algorithm) -+ .add(CoseKey::CURVE, curve) -+ .add(CoseKey::PUBKEY_X, pubX); -+ -+ if (!pubY.empty()) coseKey.add(CoseKey::PUBKEY_Y, pubY); -+ if (!eekId.empty()) coseKey.add(CoseKey::KEY_ID, eekId); -+ -+ return coseKey.canonicalize().encode(); -+} -+ - bytevec kTestMacKey(32 /* count */, 0 /* byte value */); - - bytevec randomBytes(size_t numBytes) { -@@ -34,7 +214,17 @@ bytevec randomBytes(size_t numBytes) { - return retval; - } - --ErrMsgOr generateEekChain(size_t length, const bytevec& eekId) { -+ErrMsgOr constructCoseSign1(int32_t supportedEekCurve, const bytevec& key, -+ const bytevec& payload, const bytevec& aad) { -+ if (supportedEekCurve == RpcHardwareInfo::CURVE_P256) { -+ return constructECDSACoseSign1(key, {} /* protectedParams */, payload, aad); -+ } else { -+ return cppcose::constructCoseSign1(key, payload, aad); -+ } -+} -+ -+ErrMsgOr generateEekChain(int32_t supportedEekCurve, size_t length, -+ const bytevec& eekId) { - if (length < 2) { - return "EEK chain must contain at least 2 certs."; - } -@@ -43,42 +233,31 @@ ErrMsgOr generateEekChain(size_t length, const bytevec& eekId) { - - bytevec prev_priv_key; - for (size_t i = 0; i < length - 1; ++i) { -- bytevec pub_key(ED25519_PUBLIC_KEY_LEN); -- bytevec priv_key(ED25519_PRIVATE_KEY_LEN); -- -- ED25519_keypair(pub_key.data(), priv_key.data()); -+ auto keyPair = generateKeyPair(supportedEekCurve, false); -+ if (!keyPair) keyPair.moveMessage(); -+ auto [pub_key, priv_key] = keyPair.moveValue(); - - // The first signing key is self-signed. - if (prev_priv_key.empty()) prev_priv_key = priv_key; - -- auto coseSign1 = constructCoseSign1(prev_priv_key, -- cppbor::Map() /* payload CoseKey */ -- .add(CoseKey::KEY_TYPE, OCTET_KEY_PAIR) -- .add(CoseKey::ALGORITHM, EDDSA) -- .add(CoseKey::CURVE, ED25519) -- .add(CoseKey::PUBKEY_X, pub_key) -- .canonicalize() -- .encode(), -+ auto coseKey = constructCoseKey(supportedEekCurve, {}, pub_key); -+ if (!coseKey) return coseKey.moveMessage(); -+ -+ 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(); -+ auto [pub_key, priv_key] = keyPair.moveValue(); - -- 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) -- .add(CoseKey::KEY_ID, eekId) -- .add(CoseKey::ALGORITHM, ECDH_ES_HKDF_256) -- .add(CoseKey::CURVE, cppcose::X25519) -- .add(CoseKey::PUBKEY_X, pub_key) -- .canonicalize() -- .encode(), -+ 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) { - return EekChain{eekChain.encode(), pub_key, priv_key}; - } - --bytevec getProdEekChain() { -- bytevec prodEek; -- prodEek.reserve(1 + sizeof(kCoseEncodedRootCert) + sizeof(kCoseEncodedGeekCert)); -- -- // In CBOR encoding, 0x82 indicates an array of two items -- 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)))); -+ } else { -+ 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(); - } - - ErrMsgOr verifyAndParseCoseSign1Cwt(const cppbor::Array* coseSign1, -@@ -122,7 +300,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)) { - return "Unsupported signature algorithm"; - } - -@@ -136,16 +315,35 @@ ErrMsgOr verifyAndParseCoseSign1Cwt(const cppbor::Array* coseSign1, - if (!serializedKey || !serializedKey->asBstr()) return "Could not find key entry"; - - bool selfSigned = signingCoseKey.empty(); -- auto key = -+ bytevec key; -+ if (algorithm->asInt()->value() == EDDSA) { -+ auto key = - CoseKey::parseEd25519(selfSigned ? serializedKey->asBstr()->value() : signingCoseKey); -- if (!key) return "Bad signing key: " + key.moveMessage(); -+ 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"; -+ if (!ED25519_verify(signatureInput.data(), signatureInput.size(), signature->value().data(), -+ key->getBstrValue(CoseKey::PUBKEY_X)->data())) { -+ return "Signature verification failed"; -+ } -+ } else { // P256 -+ auto key = -+ CoseKey::parseP256(selfSigned ? serializedKey->asBstr()->value() : signingCoseKey); -+ if (!key || key->getBstrValue(CoseKey::PUBKEY_X)->empty() || -+ key->getBstrValue(CoseKey::PUBKEY_Y)->empty()) { -+ return "Bad signing key: " + key.moveMessage(); -+ } -+ auto publicKey = key->getEcPublicKey(); -+ if (!publicKey) return publicKey.moveMessage(); -+ -+ bytevec signatureInput = -+ cppbor::Array().add("Signature1").add(*protectedParams).add(aad).add(*payload).encode(); -+ -+ if (!verifyEcdsaDigest(publicKey.moveValue(), sha256(signatureInput), signature->value())) { -+ return "Signature verification failed"; -+ } - } - - return serializedKey->asBstr()->value(); -diff --git a/security/keymint/support/remote_prov_utils_test.cpp b/security/keymint/support/remote_prov_utils_test.cpp -index 8697c5190..0009bf713 100644 ---- a/security/keymint/support/remote_prov_utils_test.cpp -+++ b/security/keymint/support/remote_prov_utils_test.cpp -@@ -14,6 +14,7 @@ - * limitations under the License. - */ - -+#include - #include - #include - #include -@@ -35,13 +36,13 @@ using ::keymaster::validateAndExtractEekPubAndId; - using ::testing::ElementsAreArray; - - TEST(RemoteProvUtilsTest, GenerateEekChainInvalidLength) { -- ASSERT_FALSE(generateEekChain(1, /*eekId=*/{})); -+ ASSERT_FALSE(generateEekChain(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); - ASSERT_TRUE(get_eek_result) << get_eek_result.message(); - - auto& [chain, pubkey, privkey] = *get_eek_result; diff --git a/aosp_integration_patches/system_keymaster.patch b/aosp_integration_patches/system_keymaster.patch deleted file mode 100644 index b994b768..00000000 --- a/aosp_integration_patches/system_keymaster.patch +++ /dev/null @@ -1,441 +0,0 @@ -diff --git a/cppcose/cppcose.cpp b/cppcose/cppcose.cpp -index bfe9928..5009bfe 100644 ---- a/cppcose/cppcose.cpp -+++ b/cppcose/cppcose.cpp -@@ -21,10 +21,17 @@ - - #include - #include -+#include - - #include - - namespace cppcose { -+constexpr int kP256AffinePointSize = 32; -+ -+using EVP_PKEY_Ptr = bssl::UniquePtr; -+using EVP_PKEY_CTX_Ptr = bssl::UniquePtr; -+using ECDSA_SIG_Ptr = bssl::UniquePtr; -+using EC_KEY_Ptr = bssl::UniquePtr; - - namespace { - -@@ -51,6 +58,92 @@ 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) { -+ return "Error creating BIGNUM"; -+ } -+ -+ auto ec_key = EC_KEY_Ptr(EC_KEY_new_by_curve_name(NID_X9_62_prime256v1)); -+ if (EC_KEY_set_private_key(ec_key.get(), bn.get()) != 1) { -+ return "Error setting private key from BIGNUM"; -+ } -+ -+ ECDSA_SIG* sig = 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); -+ bytevec signature(len); -+ unsigned char* p = (unsigned char*)signature.data(); -+ i2d_ECDSA_SIG(sig, &p); -+ ECDSA_SIG_free(sig); -+ return signature; -+} -+ -+ErrMsgOr ecdh(const bytevec& publicKey, const bytevec& privateKey) { -+ 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 (EC_POINT_oct2point(group.get(), point.get(), publicKey.data(), publicKey.size(), nullptr) != -+ 1) { -+ return "Error decoding publicKey"; -+ } -+ auto ecKey = EC_KEY_Ptr(EC_KEY_new()); -+ auto pkey = EVP_PKEY_Ptr(EVP_PKEY_new()); -+ if (ecKey.get() == nullptr || pkey.get() == nullptr) { -+ return "Memory allocation failed"; -+ } -+ if (EC_KEY_set_group(ecKey.get(), group.get()) != 1) { -+ return "Error setting group"; -+ } -+ if (EC_KEY_set_public_key(ecKey.get(), point.get()) != 1) { -+ return "Error setting point"; -+ } -+ if (EVP_PKEY_set1_EC_KEY(pkey.get(), ecKey.get()) != 1) { -+ return "Error setting key"; -+ } -+ -+ auto bn = BIGNUM_Ptr(BN_bin2bn(privateKey.data(), privateKey.size(), nullptr)); -+ if (bn.get() == nullptr) { -+ return "Error creating BIGNUM for private key"; -+ } -+ auto privEcKey = EC_KEY_Ptr(EC_KEY_new_by_curve_name(NID_X9_62_prime256v1)); -+ if (EC_KEY_set_private_key(privEcKey.get(), bn.get()) != 1) { -+ return "Error setting private key from BIGNUM"; -+ } -+ auto privPkey = EVP_PKEY_Ptr(EVP_PKEY_new()); -+ if (EVP_PKEY_set1_EC_KEY(privPkey.get(), privEcKey.get()) != 1) { -+ return "Error setting private key"; -+ } -+ -+ auto ctx = EVP_PKEY_CTX_Ptr(EVP_PKEY_CTX_new(privPkey.get(), NULL)); -+ if (ctx.get() == nullptr) { -+ return "Error creating context"; -+ } -+ -+ if (EVP_PKEY_derive_init(ctx.get()) != 1) { -+ return "Error initializing context"; -+ } -+ -+ if (EVP_PKEY_derive_set_peer(ctx.get(), pkey.get()) != 1) { -+ return "Error setting peer"; -+ } -+ -+ /* Determine buffer length for shared secret */ -+ size_t secretLen = 0; -+ if (EVP_PKEY_derive(ctx.get(), NULL, &secretLen) != 1) { -+ return "Error determing length of shared secret"; -+ } -+ bytevec sharedSecret; -+ sharedSecret.resize(secretLen); -+ -+ if (EVP_PKEY_derive(ctx.get(), sharedSecret.data(), &secretLen) != 1) { -+ return "Error deriving shared secret"; -+ } -+ return sharedSecret; -+} -+ - } // namespace - - ErrMsgOr generateHmacSha256(const bytevec& key, const bytevec& data) { -@@ -134,6 +227,17 @@ ErrMsgOr verifyAndParseCoseMac0(const cppbor::Item* macIt - return payload->value(); - } - -+ErrMsgOr createECDSACoseSign1Signature(const bytevec& key, const bytevec& protectedParams, -+ const bytevec& payload, const bytevec& aad) { -+ bytevec signatureInput = cppbor::Array() -+ .add("Signature1") // -+ .add(protectedParams) -+ .add(aad) -+ .add(payload) -+ .encode(); -+ return signEcdsaDigest(key, sha256(signatureInput)); -+} -+ - 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 - return signature; - } - -+ErrMsgOr constructECDSACoseSign1(const bytevec& key, cppbor::Map protectedParams, -+ const bytevec& payload, const bytevec& aad) { -+ bytevec protParms = protectedParams.add(ALGORITHM, ES256).canonicalize().encode(); -+ auto signature = createECDSACoseSign1Signature(key, protParms, payload, aad); -+ if (!signature) return signature.moveMessage(); -+ -+ return cppbor::Array() -+ .add(std::move(protParms)) -+ .add(cppbor::Map() /* unprotected parameters */) -+ .add(std::move(payload)) -+ .add(std::move(*signature)); -+} -+ - 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, - } - - 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)) { - return "Unsupported signature algorithm"; - } - -@@ -203,17 +321,30 @@ ErrMsgOr verifyAndParseCoseSign1(const cppbor::Array* coseSign1, - } - - bool selfSigned = signingCoseKey.empty(); -- auto key = CoseKey::parseEd25519(selfSigned ? payload->value() : signingCoseKey); -- if (!key || key->getBstrValue(CoseKey::PUBKEY_X)->empty()) { -- return "Bad signing key: " + key.moveMessage(); -- } -- - 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"; -+ if (algorithm->asInt()->value() == EDDSA) { -+ auto key = CoseKey::parseEd25519(selfSigned ? payload->value() : signingCoseKey); -+ if (!key || key->getBstrValue(CoseKey::PUBKEY_X)->empty()) { -+ return "Bad signing key: " + key.moveMessage(); -+ } -+ -+ if (!ED25519_verify(signatureInput.data(), signatureInput.size(), signature->value().data(), -+ key->getBstrValue(CoseKey::PUBKEY_X)->data())) { -+ return "Signature verification failed"; -+ } -+ } else { // P256 -+ auto key = CoseKey::parseP256(selfSigned ? payload->value() : signingCoseKey); -+ if (!key || key->getBstrValue(CoseKey::PUBKEY_X)->empty() || -+ key->getBstrValue(CoseKey::PUBKEY_Y)->empty()) { -+ return "Bad signing key: " + key.moveMessage(); -+ } -+ auto publicKey = key->getEcPublicKey(); -+ if (!publicKey) return publicKey.moveMessage(); -+ -+ if (!verifyEcdsaDigest(publicKey.moveValue(), sha256(signatureInput), signature->value())) { -+ return "Signature verification failed"; -+ } - } - - return payload->value(); -@@ -294,28 +425,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)) { - return "Invalid key type"; - } - - auto& curve = senderCoseKey->asMap()->get(CoseKey::CURVE); -- if (!curve || !curve->asInt() || curve->asInt()->value() != X25519) { -+ if (!curve || !curve->asInt() || -+ (keyType->asInt()->value() == OCTET_KEY_PAIR && curve->asInt()->value() != X25519) || -+ (keyType->asInt()->value() == EC2 && curve->asInt()->value() != P256)) { - return "Unsupported curve"; - } - -- auto& pubkey = senderCoseKey->asMap()->get(CoseKey::PUBKEY_X); -- if (!pubkey || !pubkey->asBstr() || -- pubkey->asBstr()->value().size() != X25519_PUBLIC_VALUE_LEN) { -- return "Invalid X25519 public key"; -+ bytevec publicKey; -+ if (keyType->asInt()->value() == EC2) { -+ auto& pubX = senderCoseKey->asMap()->get(CoseKey::PUBKEY_X); -+ if (!pubX || !pubX->asBstr() || pubX->asBstr()->value().size() != kP256AffinePointSize) { -+ return "Invalid EC public key"; -+ } -+ auto& pubY = senderCoseKey->asMap()->get(CoseKey::PUBKEY_Y); -+ if (!pubY || !pubY->asBstr() || pubY->asBstr()->value().size() != kP256AffinePointSize) { -+ return "Invalid EC public key"; -+ } -+ auto key = CoseKey::getEcPublicKey(pubX->asBstr()->value(), pubY->asBstr()->value()); -+ if (!key) return key.moveMessage(); -+ publicKey = key.moveValue(); -+ } else { -+ auto& pubkey = senderCoseKey->asMap()->get(CoseKey::PUBKEY_X); -+ if (!pubkey || !pubkey->asBstr() || -+ pubkey->asBstr()->value().size() != X25519_PUBLIC_VALUE_LEN) { -+ return "Invalid X25519 public key"; -+ } -+ publicKey = pubkey->asBstr()->value(); - } - - auto& key_id = unprotParms->asMap()->get(KEY_ID); - if (key_id && key_id->asBstr()) { -- return std::make_pair(pubkey->asBstr()->value(), key_id->asBstr()->value()); -+ return std::make_pair(publicKey, key_id->asBstr()->value()); - } - - // If no key ID, just return an empty vector. -- return std::make_pair(pubkey->asBstr()->value(), bytevec{}); -+ return std::make_pair(publicKey, bytevec{}); - } - - ErrMsgOr decryptCoseEncrypt(const bytevec& key, const cppbor::Item* coseEncrypt, -@@ -367,6 +517,43 @@ ErrMsgOr decryptCoseEncrypt(const bytevec& key, const cppbor::Item* cos - return aesGcmDecrypt(key, nonce->asBstr()->value(), aad, ciphertext->asBstr()->value()); - } - -+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); -+ 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(); -+ -+ bytevec retval(SHA256_DIGEST_LENGTH); -+ bytevec salt{}; -+ if (!HKDF(retval.data(), retval.size(), // -+ EVP_sha256(), // -+ rawSharedKey->data(), rawSharedKey->size(), // -+ salt.data(), salt.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 - return plaintext; - } - -+bytevec sha256(const bytevec& data) { -+ bytevec ret(SHA256_DIGEST_LENGTH); -+ SHA256_CTX ctx; -+ SHA256_Init(&ctx); -+ SHA256_Update(&ctx, data.data(), data.size()); -+ SHA256_Final((unsigned char*)ret.data(), &ctx); -+ return ret; -+} -+ -+bool verifyEcdsaDigest(const bytevec& key, const bytevec& digest, const bytevec& signature) { -+ const unsigned char* p = (unsigned char*)signature.data(); -+ auto sig = ECDSA_SIG_Ptr(d2i_ECDSA_SIG(nullptr, &p, signature.size())); -+ if (sig.get() == nullptr) { -+ return false; -+ } -+ -+ 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 (EC_POINT_oct2point(group.get(), point.get(), key.data(), key.size(), nullptr) != 1) { -+ return false; -+ } -+ auto ecKey = EC_KEY_Ptr(EC_KEY_new()); -+ if (ecKey.get() == nullptr) { -+ return false; -+ } -+ if (EC_KEY_set_group(ecKey.get(), group.get()) != 1) { -+ return false; -+ } -+ if (EC_KEY_set_public_key(ecKey.get(), point.get()) != 1) { -+ return false; -+ } -+ -+ int rc = ECDSA_do_verify(digest.data(), digest.size(), sig.get(), ecKey.get()); -+ if (rc != 1) { -+ return false; -+ } -+ return true; -+} -+ - } // namespace cppcose -diff --git a/include/keymaster/cppcose/cppcose.h b/include/keymaster/cppcose/cppcose.h -index 0f97388..03251f1 100644 ---- a/include/keymaster/cppcose/cppcose.h -+++ b/include/keymaster/cppcose/cppcose.h -@@ -24,17 +24,25 @@ - - #include - #include -- -+#include -+#include -+#include - #include - #include - #include - #include -+#include - #include - #include - #include - - namespace cppcose { - -+using BIGNUM_Ptr = bssl::UniquePtr; -+using EC_GROUP_Ptr = bssl::UniquePtr; -+using EC_POINT_Ptr = bssl::UniquePtr; -+using BN_CTX_Ptr = bssl::UniquePtr; -+ - template class ErrMsgOr; - using bytevec = std::vector; - using HmacSha256 = std::array; -@@ -203,6 +211,41 @@ 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"; -+ } -+ 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; -+ } -+ -+ ErrMsgOr getEcPublicKey() { -+ auto pubX = getBstrValue(PUBKEY_X).value(); -+ auto pubY = getBstrValue(PUBKEY_Y).value(); -+ return getEcPublicKey(pubX, pubY); -+ } -+ - 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 - 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); - /** - * Verify and parse a COSE_Sign1 message, returning the payload. - * -@@ -282,7 +327,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); -+bool verifyEcdsaDigest(const bytevec& key, const bytevec& digest, const bytevec& signature); -+bytevec sha256(const bytevec& data); - ErrMsgOr aesGcmEncrypt(const bytevec& key, const bytevec& nonce, - const bytevec& aad, - const bytevec& plaintext);