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);