diff --git a/aosp_integration_patches_aosp_12_r15/device_google_cuttlefish.patch b/aosp_integration_patches_aosp_12_r15/device_google_cuttlefish.patch new file mode 100644 index 00000000..b0fca48f --- /dev/null +++ b/aosp_integration_patches_aosp_12_r15/device_google_cuttlefish.patch @@ -0,0 +1,62 @@ +diff --git a/shared/device.mk b/shared/device.mk +index 8647d0175..d1955772f 100644 +--- a/shared/device.mk ++++ b/shared/device.mk +@@ -538,6 +538,10 @@ endif + PRODUCT_PACKAGES += \ + $(LOCAL_KEYMINT_PRODUCT_PACKAGE) + ++PRODUCT_PACKAGES += \ ++ android.hardware.security.keymint-service.strongbox ++ ++ + # Keymint configuration + PRODUCT_COPY_FILES += \ + frameworks/native/data/etc/android.software.device_id_attestation.xml:$(TARGET_COPY_OUT_VENDOR)/etc/permissions/android.software.device_id_attestation.xml +diff --git a/shared/sepolicy/vendor/file_contexts b/shared/sepolicy/vendor/file_contexts +index 20538a50f..2b74242f7 100644 +--- a/shared/sepolicy/vendor/file_contexts ++++ b/shared/sepolicy/vendor/file_contexts +@@ -87,6 +87,7 @@ + /vendor/bin/hw/android\.hardware\.input\.classifier@1\.0-service.default u:object_r:hal_input_classifier_default_exec:s0 + /vendor/bin/hw/android\.hardware\.thermal@2\.0-service\.mock u:object_r:hal_thermal_default_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\.oemlock-service.example u:object_r:hal_oemlock_default_exec: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..09d0da267 +--- /dev/null ++++ b/shared/sepolicy/vendor/hal_keymint_strongbox.te +@@ -0,0 +1,15 @@ ++type hal_keymint_strongbox, domain; ++hal_server_domain(hal_keymint_strongbox, hal_keymint) ++ ++type hal_keymint_strongbox_exec, exec_type, vendor_file_type, file_type; ++init_daemon_domain(hal_keymint_strongbox) ++ ++vndbinder_use(hal_keymint_strongbox) ++get_prop(hal_keymint_strongbox, vendor_security_patch_level_prop); ++ ++# Allow access to sockets ++allow hal_keymint_strongbox self:tcp_socket { connect create write read getattr getopt setopt }; ++allow hal_keymint_strongbox port_type:tcp_socket name_connect; ++allow hal_keymint_strongbox port:tcp_socket { name_connect }; ++allow hal_keymint_strongbox vendor_data_file:file { open read getattr }; ++ +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_aosp_12_r15/hardware_interfaces.patch b/aosp_integration_patches_aosp_12_r15/hardware_interfaces.patch new file mode 100644 index 00000000..bf456260 --- /dev/null +++ b/aosp_integration_patches_aosp_12_r15/hardware_interfaces.patch @@ -0,0 +1,1213 @@ +diff --git a/compatibility_matrices/compatibility_matrix.6.xml b/compatibility_matrices/compatibility_matrix.6.xml +index aee2c5164..1391bbf54 100644 +--- a/compatibility_matrices/compatibility_matrix.6.xml ++++ b/compatibility_matrices/compatibility_matrix.6.xml +@@ -349,6 +349,13 @@ + default + + ++ ++ android.hardware.security.keymint ++ ++ IRemotelyProvisionedComponent ++ strongbox ++ ++ + + android.hardware.light + 1 +diff --git a/compatibility_matrices/compatibility_matrix.current.xml b/compatibility_matrices/compatibility_matrix.current.xml +index 8b6e8414d..4955db7d7 100644 +--- a/compatibility_matrices/compatibility_matrix.current.xml ++++ b/compatibility_matrices/compatibility_matrix.current.xml +@@ -66,7 +66,7 @@ + + IEvsEnumerator + default +- [a-z]+/[0-9]+ ++ [a-z]/[0-9] + + + +@@ -168,7 +168,7 @@ + 2.4-7 + + ICameraProvider +- [^/]+/[0-9]+ ++ [^/]/[0-9] + + + +@@ -349,6 +349,13 @@ + default + + ++ ++ android.hardware.security.keymint ++ ++ IRemotelyProvisionedComponent ++ strongbox ++ ++ + + android.hardware.light + 1 +@@ -511,6 +518,15 @@ + strongbox + + ++ ++ android.hardware.security.sharedsecret ++ 1 ++ ++ ISharedSecret ++ strongbox ++ ++ ++ + + android.hardware.sensors + 1.0 +diff --git a/security/keymint/aidl/vts/functional/AttestKeyTest.cpp b/security/keymint/aidl/vts/functional/AttestKeyTest.cpp +index 26ed34427..2d5bc9575 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() + .RsaSigningKey(2048, 65537) + .AttestKey() +@@ -209,7 +209,13 @@ 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 +303,7 @@ TEST_P(AttestKeyTest, RsaAttestKeyChaining) { + attest_key_opt = attest_key; + } + +- EXPECT_EQ(ErrorCode::OK, ++ auto result = + GenerateKey(AuthorizationSetBuilder() + .RsaSigningKey(2048, 65537) + .AttestKey() +@@ -308,8 +314,13 @@ 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); + ASSERT_GT(cert_chain_list[i].size(), 0); +@@ -369,7 +380,7 @@ TEST_P(AttestKeyTest, EcAttestKeyChaining) { + attest_key_opt = attest_key; + } + +- EXPECT_EQ(ErrorCode::OK, ++ auto result = + GenerateKey(AuthorizationSetBuilder() + .EcdsaSigningKey(EcCurve::P_256) + .AttestKey() +@@ -380,8 +391,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); + ASSERT_GT(cert_chain_list[i].size(), 0); +@@ -442,35 +458,40 @@ TEST_P(AttestKeyTest, AlternateAttestKeyChaining) { + attest_key.keyBlob = key_blob_list[i - 1]; + attest_key_opt = attest_key; + } +- ++ ErrorCode result; + if ((i & 0x1) == 1) { +- EXPECT_EQ(ErrorCode::OK, +- GenerateKey(AuthorizationSetBuilder() +- .EcdsaSigningKey(EcCurve::P_256) +- .AttestKey() +- .AttestationChallenge("foo") +- .AttestationApplicationId("bar") +- .Authorization(TAG_CERTIFICATE_SERIAL, serial_blob) +- .Authorization(TAG_CERTIFICATE_SUBJECT, subject_der) +- .Authorization(TAG_NO_AUTH_REQUIRED) +- .SetDefaultValidity(), +- attest_key_opt, &key_blob_list[i], &attested_key_characteristics, +- &cert_chain_list[i])); ++ result = ++ GenerateKey(AuthorizationSetBuilder() ++ .EcdsaSigningKey(EcCurve::P_256) ++ .AttestKey() ++ .AttestationChallenge("foo") ++ .AttestationApplicationId("bar") ++ .Authorization(TAG_CERTIFICATE_SERIAL, serial_blob) ++ .Authorization(TAG_CERTIFICATE_SUBJECT, subject_der) ++ .Authorization(TAG_NO_AUTH_REQUIRED) ++ .SetDefaultValidity(), ++ attest_key_opt, &key_blob_list[i], &attested_key_characteristics, ++ &cert_chain_list[i]); + } else { +- EXPECT_EQ(ErrorCode::OK, +- GenerateKey(AuthorizationSetBuilder() +- .RsaSigningKey(2048, 65537) +- .AttestKey() +- .AttestationChallenge("foo") +- .AttestationApplicationId("bar") +- .Authorization(TAG_CERTIFICATE_SERIAL, serial_blob) +- .Authorization(TAG_CERTIFICATE_SUBJECT, subject_der) +- .Authorization(TAG_NO_AUTH_REQUIRED) +- .SetDefaultValidity(), +- attest_key_opt, &key_blob_list[i], &attested_key_characteristics, +- &cert_chain_list[i])); ++ result = ++ GenerateKey(AuthorizationSetBuilder() ++ .RsaSigningKey(2048, 65537) ++ .AttestKey() ++ .AttestationChallenge("foo") ++ .AttestationApplicationId("bar") ++ .Authorization(TAG_CERTIFICATE_SERIAL, serial_blob) ++ .Authorization(TAG_CERTIFICATE_SUBJECT, subject_der) ++ .Authorization(TAG_NO_AUTH_REQUIRED) ++ .SetDefaultValidity(), ++ attest_key_opt, &key_blob_list[i], &attested_key_characteristics, ++ &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); + ASSERT_GT(cert_chain_list[i].size(), 0); +diff --git a/security/keymint/aidl/vts/functional/KeyMintAidlTestBase.cpp b/security/keymint/aidl/vts/functional/KeyMintAidlTestBase.cpp +index 20324117b..741bcf8f6 100644 +--- a/security/keymint/aidl/vts/functional/KeyMintAidlTestBase.cpp ++++ b/security/keymint/aidl/vts/functional/KeyMintAidlTestBase.cpp +@@ -1145,6 +1145,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 ec3fcf6a3..0561a9b94 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 5a87b8385..d30f9dae9 100644 +--- a/security/keymint/aidl/vts/functional/KeyMintTest.cpp ++++ b/security/keymint/aidl/vts/functional/KeyMintTest.cpp +@@ -902,8 +902,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) +@@ -913,8 +913,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); +@@ -1031,8 +1037,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) +@@ -1041,8 +1046,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) { +@@ -1143,15 +1154,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); + } + + /* +@@ -1261,8 +1278,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) +@@ -1273,7 +1290,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); +@@ -1404,8 +1428,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) +@@ -1414,7 +1438,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); +@@ -1491,6 +1523,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); + +@@ -1540,8 +1578,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); + } + } + +@@ -1577,6 +1621,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); + +@@ -1655,13 +1706,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); + } + + /* +@@ -1718,14 +1775,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); +@@ -3755,25 +3819,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(); + } + } + +@@ -6255,7 +6321,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; + } +@@ -6263,12 +6329,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(); + } + +@@ -6367,7 +6433,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() +@@ -6376,7 +6441,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); +@@ -6456,14 +6520,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); ++ } ++ + } + + /* +@@ -6479,14 +6553,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 38f358686..74e44c7b4 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 9e218b6a3..73fb8c277 100644 +--- a/security/keymint/support/Android.bp ++++ b/security/keymint/support/Android.bp +@@ -62,6 +62,7 @@ cc_library { + "libcppcose_rkp", + "libcrypto", + "libjsoncpp", ++ "android.hardware.security.keymint-V1-ndk_platform", + ], + } + +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_aosp_12_r15/system_keymaster.patch b/aosp_integration_patches_aosp_12_r15/system_keymaster.patch new file mode 100644 index 00000000..b994b768 --- /dev/null +++ b/aosp_integration_patches_aosp_12_r15/system_keymaster.patch @@ -0,0 +1,441 @@ +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); diff --git a/aosp_integration_patches_aosp_12_r15/system_security.patch b/aosp_integration_patches_aosp_12_r15/system_security.patch new file mode 100644 index 00000000..22956d5e --- /dev/null +++ b/aosp_integration_patches_aosp_12_r15/system_security.patch @@ -0,0 +1,13 @@ +diff --git a/keystore2/src/km_compat/km_compat.cpp b/keystore2/src/km_compat/km_compat.cpp +index 64849c1..40ca554 100644 +--- a/keystore2/src/km_compat/km_compat.cpp ++++ b/keystore2/src/km_compat/km_compat.cpp +@@ -1314,7 +1314,7 @@ KeymasterDevices initializeKeymasters() { + CHECK(serviceManager.get()) << "Failed to get ServiceManager"; + auto result = enumerateKeymasterDevices(serviceManager.get()); + auto softKeymaster = result[SecurityLevel::SOFTWARE]; +- if (!result[SecurityLevel::TRUSTED_ENVIRONMENT]) { ++ if ((!result[SecurityLevel::TRUSTED_ENVIRONMENT]) && (!result[SecurityLevel::STRONGBOX])) { + result = enumerateKeymasterDevices(serviceManager.get()); + } + if (softKeymaster) result[SecurityLevel::SOFTWARE] = softKeymaster; diff --git a/aosp_integration_patches_aosp_12_r15/system_sepolicy.patch b/aosp_integration_patches_aosp_12_r15/system_sepolicy.patch new file mode 100644 index 00000000..f533e8c7 --- /dev/null +++ b/aosp_integration_patches_aosp_12_r15/system_sepolicy.patch @@ -0,0 +1,40 @@ +diff --git a/prebuilts/api/31.0/public/hal_neverallows.te b/prebuilts/api/31.0/public/hal_neverallows.te +index 105689b8a..275f9a5c2 100644 +--- a/prebuilts/api/31.0/public/hal_neverallows.te ++++ b/prebuilts/api/31.0/public/hal_neverallows.te +@@ -9,6 +9,7 @@ neverallow { + -hal_wifi_supplicant_server + -hal_telephony_server + -hal_uwb_server ++ -hal_keymint_server + } self:global_capability_class_set { net_admin net_raw }; + + # Unless a HAL's job is to communicate over the network, or control network +@@ -27,6 +28,7 @@ neverallow { + -hal_wifi_supplicant_server + -hal_telephony_server + -hal_uwb_server ++ -hal_keymint_server + } domain:{ tcp_socket udp_socket rawip_socket } *; + + # The UWB HAL is not actually a networking HAL but may need to bring up and down +diff --git a/public/hal_neverallows.te b/public/hal_neverallows.te +index 105689b8a..275f9a5c2 100644 +--- a/public/hal_neverallows.te ++++ b/public/hal_neverallows.te +@@ -9,6 +9,7 @@ neverallow { + -hal_wifi_supplicant_server + -hal_telephony_server + -hal_uwb_server ++ -hal_keymint_server + } self:global_capability_class_set { net_admin net_raw }; + + # Unless a HAL's job is to communicate over the network, or control network +@@ -27,6 +28,7 @@ neverallow { + -hal_wifi_supplicant_server + -hal_telephony_server + -hal_uwb_server ++ -hal_keymint_server + } domain:{ tcp_socket udp_socket rawip_socket } *; + + # The UWB HAL is not actually a networking HAL but may need to bring up and down