summaryrefslogtreecommitdiff
path: root/security/keymint/aidl/vts/functional/KeyMintTest.cpp
diff options
context:
space:
mode:
authorDaniel Norman <danielnorman@google.com>2021-02-19 00:13:25 +0000
committerGerrit Code Review <noreply-gerritcodereview@google.com>2021-02-19 00:13:25 +0000
commit7b82a0f697d0cf832803a80f7ed2128002b54dec (patch)
tree62e68f2885e6a7a73bf3386e8459f8fe98528ade /security/keymint/aidl/vts/functional/KeyMintTest.cpp
parent5e442ab95232c604b382e6b7a773629f392ed224 (diff)
parentf86b976dba9b016816efa57156e791fffd498d64 (diff)
Merge "Merge SP1A.210208.001" into s-keystone-qcom-dev
Diffstat (limited to 'security/keymint/aidl/vts/functional/KeyMintTest.cpp')
-rw-r--r--security/keymint/aidl/vts/functional/KeyMintTest.cpp470
1 files changed, 468 insertions, 2 deletions
diff --git a/security/keymint/aidl/vts/functional/KeyMintTest.cpp b/security/keymint/aidl/vts/functional/KeyMintTest.cpp
index e7c94f37a0..c849bade2e 100644
--- a/security/keymint/aidl/vts/functional/KeyMintTest.cpp
+++ b/security/keymint/aidl/vts/functional/KeyMintTest.cpp
@@ -20,9 +20,11 @@
#include <signal.h>
#include <iostream>
+#include <openssl/ec.h>
#include <openssl/evp.h>
#include <openssl/mem.h>
#include <openssl/x509.h>
+#include <openssl/x509v3.h>
#include <cutils/properties.h>
@@ -560,7 +562,7 @@ TEST_P(NewKeyGenerationTest, Rsa) {
}
/*
- * NewKeyGenerationTest.Rsa
+ * NewKeyGenerationTest.RsaWithAttestation
*
* Verifies that keymint can generate all required RSA key sizes, and that the resulting keys
* have correct characteristics.
@@ -605,6 +607,100 @@ TEST_P(NewKeyGenerationTest, RsaWithAttestation) {
}
/*
+ * NewKeyGenerationTest.LimitedUsageRsa
+ *
+ * Verifies that KeyMint can generate all required RSA key sizes with limited usage, and that the
+ * resulting keys have correct characteristics.
+ */
+TEST_P(NewKeyGenerationTest, LimitedUsageRsa) {
+ for (auto key_size : ValidKeySizes(Algorithm::RSA)) {
+ vector<uint8_t> key_blob;
+ vector<KeyCharacteristics> key_characteristics;
+ ASSERT_EQ(ErrorCode::OK, GenerateKey(AuthorizationSetBuilder()
+ .RsaSigningKey(key_size, 65537)
+ .Digest(Digest::NONE)
+ .Padding(PaddingMode::NONE)
+ .Authorization(TAG_USAGE_COUNT_LIMIT, 1),
+ &key_blob, &key_characteristics));
+
+ ASSERT_GT(key_blob.size(), 0U);
+ CheckBaseParams(key_characteristics);
+
+ AuthorizationSet crypto_params = SecLevelAuthorizations(key_characteristics);
+
+ EXPECT_TRUE(crypto_params.Contains(TAG_ALGORITHM, Algorithm::RSA));
+ EXPECT_TRUE(crypto_params.Contains(TAG_KEY_SIZE, key_size))
+ << "Key size " << key_size << "missing";
+ EXPECT_TRUE(crypto_params.Contains(TAG_RSA_PUBLIC_EXPONENT, 65537U));
+
+ // Check the usage count limit tag appears in the authorizations.
+ AuthorizationSet auths;
+ for (auto& entry : key_characteristics) {
+ auths.push_back(AuthorizationSet(entry.authorizations));
+ }
+ EXPECT_TRUE(auths.Contains(TAG_USAGE_COUNT_LIMIT, 1U))
+ << "key usage count limit " << 1U << " missing";
+
+ CheckedDeleteKey(&key_blob);
+ }
+}
+
+/*
+ * NewKeyGenerationTest.LimitedUsageRsaWithAttestation
+ *
+ * Verifies that KeyMint can generate all required RSA key sizes with limited usage, and that the
+ * resulting keys have correct characteristics and attestation.
+ */
+TEST_P(NewKeyGenerationTest, LimitedUsageRsaWithAttestation) {
+ for (auto key_size : ValidKeySizes(Algorithm::RSA)) {
+ auto challenge = "hello";
+ auto app_id = "foo";
+
+ vector<uint8_t> key_blob;
+ vector<KeyCharacteristics> key_characteristics;
+ ASSERT_EQ(ErrorCode::OK, GenerateKey(AuthorizationSetBuilder()
+ .RsaSigningKey(key_size, 65537)
+ .Digest(Digest::NONE)
+ .Padding(PaddingMode::NONE)
+ .AttestationChallenge(challenge)
+ .AttestationApplicationId(app_id)
+ .Authorization(TAG_NO_AUTH_REQUIRED)
+ .Authorization(TAG_USAGE_COUNT_LIMIT, 1),
+ &key_blob, &key_characteristics));
+
+ ASSERT_GT(key_blob.size(), 0U);
+ CheckBaseParams(key_characteristics);
+
+ AuthorizationSet crypto_params = SecLevelAuthorizations(key_characteristics);
+
+ EXPECT_TRUE(crypto_params.Contains(TAG_ALGORITHM, Algorithm::RSA));
+ EXPECT_TRUE(crypto_params.Contains(TAG_KEY_SIZE, key_size))
+ << "Key size " << key_size << "missing";
+ EXPECT_TRUE(crypto_params.Contains(TAG_RSA_PUBLIC_EXPONENT, 65537U));
+
+ // Check the usage count limit tag appears in the authorizations.
+ AuthorizationSet auths;
+ for (auto& entry : key_characteristics) {
+ auths.push_back(AuthorizationSet(entry.authorizations));
+ }
+ EXPECT_TRUE(auths.Contains(TAG_USAGE_COUNT_LIMIT, 1U))
+ << "key usage count limit " << 1U << " missing";
+
+ // Check the usage count limit tag also appears in the attestation.
+ EXPECT_TRUE(verify_chain(cert_chain_));
+ ASSERT_GT(cert_chain_.size(), 0);
+
+ AuthorizationSet hw_enforced = HwEnforcedAuthorizations(key_characteristics);
+ AuthorizationSet sw_enforced = SwEnforcedAuthorizations(key_characteristics);
+ EXPECT_TRUE(verify_attestation_record(challenge, app_id, //
+ sw_enforced, hw_enforced, SecLevel(),
+ cert_chain_[0].encodedCertificate));
+
+ CheckedDeleteKey(&key_blob);
+ }
+}
+
+/*
* NewKeyGenerationTest.NoInvalidRsaSizes
*
* Verifies that keymint cannot generate any RSA key sizes that are designated as invalid.
@@ -664,6 +760,43 @@ TEST_P(NewKeyGenerationTest, Ecdsa) {
}
/*
+ * NewKeyGenerationTest.LimitedUsageEcdsa
+ *
+ * Verifies that KeyMint can generate all required EC key sizes with limited usage, and that the
+ * resulting keys have correct characteristics.
+ */
+TEST_P(NewKeyGenerationTest, LimitedUsageEcdsa) {
+ for (auto key_size : ValidKeySizes(Algorithm::EC)) {
+ vector<uint8_t> key_blob;
+ vector<KeyCharacteristics> key_characteristics;
+ ASSERT_EQ(ErrorCode::OK, GenerateKey(AuthorizationSetBuilder()
+ .EcdsaSigningKey(key_size)
+ .Digest(Digest::NONE)
+ .Authorization(TAG_USAGE_COUNT_LIMIT, 1),
+ &key_blob, &key_characteristics));
+
+ ASSERT_GT(key_blob.size(), 0U);
+ CheckBaseParams(key_characteristics);
+
+ AuthorizationSet crypto_params = SecLevelAuthorizations(key_characteristics);
+
+ EXPECT_TRUE(crypto_params.Contains(TAG_ALGORITHM, Algorithm::EC));
+ EXPECT_TRUE(crypto_params.Contains(TAG_KEY_SIZE, key_size))
+ << "Key size " << key_size << "missing";
+
+ // Check the usage count limit tag appears in the authorizations.
+ AuthorizationSet auths;
+ for (auto& entry : key_characteristics) {
+ auths.push_back(AuthorizationSet(entry.authorizations));
+ }
+ EXPECT_TRUE(auths.Contains(TAG_USAGE_COUNT_LIMIT, 1U))
+ << "key usage count limit " << 1U << " missing";
+
+ CheckedDeleteKey(&key_blob);
+ }
+}
+
+/*
* NewKeyGenerationTest.EcdsaDefaultSize
*
* Verifies that failing to specify a key size for EC key generation returns
@@ -778,6 +911,44 @@ TEST_P(NewKeyGenerationTest, Hmac) {
}
/*
+ * NewKeyGenerationTest.LimitedUsageHmac
+ *
+ * Verifies that KeyMint supports all required digests with limited usage Hmac, and that the
+ * resulting keys have correct characteristics.
+ */
+TEST_P(NewKeyGenerationTest, LimitedUsageHmac) {
+ for (auto digest : ValidDigests(false /* withNone */, true /* withMD5 */)) {
+ vector<uint8_t> key_blob;
+ vector<KeyCharacteristics> key_characteristics;
+ constexpr size_t key_size = 128;
+ ASSERT_EQ(ErrorCode::OK, GenerateKey(AuthorizationSetBuilder()
+ .HmacKey(key_size)
+ .Digest(digest)
+ .Authorization(TAG_MIN_MAC_LENGTH, 128)
+ .Authorization(TAG_USAGE_COUNT_LIMIT, 1),
+ &key_blob, &key_characteristics));
+
+ ASSERT_GT(key_blob.size(), 0U);
+ CheckBaseParams(key_characteristics);
+
+ AuthorizationSet crypto_params = SecLevelAuthorizations(key_characteristics);
+ EXPECT_TRUE(crypto_params.Contains(TAG_ALGORITHM, Algorithm::HMAC));
+ EXPECT_TRUE(crypto_params.Contains(TAG_KEY_SIZE, key_size))
+ << "Key size " << key_size << "missing";
+
+ // Check the usage count limit tag appears in the authorizations.
+ AuthorizationSet auths;
+ for (auto& entry : key_characteristics) {
+ auths.push_back(AuthorizationSet(entry.authorizations));
+ }
+ EXPECT_TRUE(auths.Contains(TAG_USAGE_COUNT_LIMIT, 1U))
+ << "key usage count limit " << 1U << " missing";
+
+ CheckedDeleteKey(&key_blob);
+ }
+}
+
+/*
* NewKeyGenerationTest.HmacCheckKeySizes
*
* Verifies that keymint supports all key sizes, and rejects all invalid key sizes.
@@ -4151,7 +4322,7 @@ TEST_P(MaxOperationsTest, TestLimitAes) {
}
/*
- * MaxOperationsTest.TestLimitAes
+ * MaxOperationsTest.TestLimitRsa
*
* Verifies that the max uses per boot tag works correctly with RSA keys.
*/
@@ -4178,6 +4349,186 @@ TEST_P(MaxOperationsTest, TestLimitRsa) {
INSTANTIATE_KEYMINT_AIDL_TEST(MaxOperationsTest);
+typedef KeyMintAidlTestBase UsageCountLimitTest;
+
+/*
+ * UsageCountLimitTest.TestSingleUseAes
+ *
+ * Verifies that the usage count limit tag = 1 works correctly with AES keys.
+ */
+TEST_P(UsageCountLimitTest, TestSingleUseAes) {
+ if (SecLevel() == SecurityLevel::STRONGBOX) return;
+
+ ASSERT_EQ(ErrorCode::OK, GenerateKey(AuthorizationSetBuilder()
+ .Authorization(TAG_NO_AUTH_REQUIRED)
+ .AesEncryptionKey(128)
+ .EcbMode()
+ .Padding(PaddingMode::NONE)
+ .Authorization(TAG_USAGE_COUNT_LIMIT, 1)));
+
+ // Check the usage count limit tag appears in the authorizations.
+ AuthorizationSet auths;
+ for (auto& entry : key_characteristics_) {
+ auths.push_back(AuthorizationSet(entry.authorizations));
+ }
+ EXPECT_TRUE(auths.Contains(TAG_USAGE_COUNT_LIMIT, 1U))
+ << "key usage count limit " << 1U << " missing";
+
+ string message = "1234567890123456";
+ auto params = AuthorizationSetBuilder().EcbMode().Padding(PaddingMode::NONE);
+
+ AuthorizationSet hardware_auths = HwEnforcedAuthorizations(key_characteristics_);
+ AuthorizationSet keystore_auths =
+ SecLevelAuthorizations(key_characteristics_, SecurityLevel::KEYSTORE);
+
+ // First usage of AES key should work.
+ EncryptMessage(message, params);
+
+ if (hardware_auths.Contains(TAG_USAGE_COUNT_LIMIT, 1U)) {
+ // Usage count limit tag is enforced by hardware. After using the key, the key blob
+ // must be invalidated from secure storage (such as RPMB partition).
+ EXPECT_EQ(ErrorCode::INVALID_KEY_BLOB, Begin(KeyPurpose::ENCRYPT, params));
+ } else {
+ // Usage count limit tag is enforced by keystore, keymint does nothing.
+ EXPECT_TRUE(keystore_auths.Contains(TAG_USAGE_COUNT_LIMIT, 1U));
+ EXPECT_EQ(ErrorCode::OK, Begin(KeyPurpose::ENCRYPT, params));
+ }
+}
+
+/*
+ * UsageCountLimitTest.TestLimitedUseAes
+ *
+ * Verifies that the usage count limit tag > 1 works correctly with AES keys.
+ */
+TEST_P(UsageCountLimitTest, TestLimitedUseAes) {
+ if (SecLevel() == SecurityLevel::STRONGBOX) return;
+
+ ASSERT_EQ(ErrorCode::OK, GenerateKey(AuthorizationSetBuilder()
+ .Authorization(TAG_NO_AUTH_REQUIRED)
+ .AesEncryptionKey(128)
+ .EcbMode()
+ .Padding(PaddingMode::NONE)
+ .Authorization(TAG_USAGE_COUNT_LIMIT, 3)));
+
+ // Check the usage count limit tag appears in the authorizations.
+ AuthorizationSet auths;
+ for (auto& entry : key_characteristics_) {
+ auths.push_back(AuthorizationSet(entry.authorizations));
+ }
+ EXPECT_TRUE(auths.Contains(TAG_USAGE_COUNT_LIMIT, 3U))
+ << "key usage count limit " << 3U << " missing";
+
+ string message = "1234567890123456";
+ auto params = AuthorizationSetBuilder().EcbMode().Padding(PaddingMode::NONE);
+
+ AuthorizationSet hardware_auths = HwEnforcedAuthorizations(key_characteristics_);
+ AuthorizationSet keystore_auths =
+ SecLevelAuthorizations(key_characteristics_, SecurityLevel::KEYSTORE);
+
+ EncryptMessage(message, params);
+ EncryptMessage(message, params);
+ EncryptMessage(message, params);
+
+ if (hardware_auths.Contains(TAG_USAGE_COUNT_LIMIT, 3U)) {
+ // Usage count limit tag is enforced by hardware. After using the key, the key blob
+ // must be invalidated from secure storage (such as RPMB partition).
+ EXPECT_EQ(ErrorCode::INVALID_KEY_BLOB, Begin(KeyPurpose::ENCRYPT, params));
+ } else {
+ // Usage count limit tag is enforced by keystore, keymint does nothing.
+ EXPECT_TRUE(keystore_auths.Contains(TAG_USAGE_COUNT_LIMIT, 3U));
+ EXPECT_EQ(ErrorCode::OK, Begin(KeyPurpose::ENCRYPT, params));
+ }
+}
+
+/*
+ * UsageCountLimitTest.TestSingleUseRsa
+ *
+ * Verifies that the usage count limit tag = 1 works correctly with RSA keys.
+ */
+TEST_P(UsageCountLimitTest, TestSingleUseRsa) {
+ if (SecLevel() == SecurityLevel::STRONGBOX) return;
+
+ ASSERT_EQ(ErrorCode::OK, GenerateKey(AuthorizationSetBuilder()
+ .Authorization(TAG_NO_AUTH_REQUIRED)
+ .RsaSigningKey(1024, 65537)
+ .NoDigestOrPadding()
+ .Authorization(TAG_USAGE_COUNT_LIMIT, 1)));
+
+ // Check the usage count limit tag appears in the authorizations.
+ AuthorizationSet auths;
+ for (auto& entry : key_characteristics_) {
+ auths.push_back(AuthorizationSet(entry.authorizations));
+ }
+ EXPECT_TRUE(auths.Contains(TAG_USAGE_COUNT_LIMIT, 1U))
+ << "key usage count limit " << 1U << " missing";
+
+ string message = "1234567890123456";
+ auto params = AuthorizationSetBuilder().NoDigestOrPadding();
+
+ AuthorizationSet hardware_auths = HwEnforcedAuthorizations(key_characteristics_);
+ AuthorizationSet keystore_auths =
+ SecLevelAuthorizations(key_characteristics_, SecurityLevel::KEYSTORE);
+
+ // First usage of RSA key should work.
+ SignMessage(message, params);
+
+ if (hardware_auths.Contains(TAG_USAGE_COUNT_LIMIT, 1U)) {
+ // Usage count limit tag is enforced by hardware. After using the key, the key blob
+ // must be invalidated from secure storage (such as RPMB partition).
+ EXPECT_EQ(ErrorCode::INVALID_KEY_BLOB, Begin(KeyPurpose::SIGN, params));
+ } else {
+ // Usage count limit tag is enforced by keystore, keymint does nothing.
+ EXPECT_TRUE(keystore_auths.Contains(TAG_USAGE_COUNT_LIMIT, 1U));
+ EXPECT_EQ(ErrorCode::OK, Begin(KeyPurpose::SIGN, params));
+ }
+}
+
+/*
+ * UsageCountLimitTest.TestLimitUseRsa
+ *
+ * Verifies that the usage count limit tag > 1 works correctly with RSA keys.
+ */
+TEST_P(UsageCountLimitTest, TestLimitUseRsa) {
+ if (SecLevel() == SecurityLevel::STRONGBOX) return;
+
+ ASSERT_EQ(ErrorCode::OK, GenerateKey(AuthorizationSetBuilder()
+ .Authorization(TAG_NO_AUTH_REQUIRED)
+ .RsaSigningKey(1024, 65537)
+ .NoDigestOrPadding()
+ .Authorization(TAG_USAGE_COUNT_LIMIT, 3)));
+
+ // Check the usage count limit tag appears in the authorizations.
+ AuthorizationSet auths;
+ for (auto& entry : key_characteristics_) {
+ auths.push_back(AuthorizationSet(entry.authorizations));
+ }
+ EXPECT_TRUE(auths.Contains(TAG_USAGE_COUNT_LIMIT, 3U))
+ << "key usage count limit " << 3U << " missing";
+
+ string message = "1234567890123456";
+ auto params = AuthorizationSetBuilder().NoDigestOrPadding();
+
+ AuthorizationSet hardware_auths = HwEnforcedAuthorizations(key_characteristics_);
+ AuthorizationSet keystore_auths =
+ SecLevelAuthorizations(key_characteristics_, SecurityLevel::KEYSTORE);
+
+ SignMessage(message, params);
+ SignMessage(message, params);
+ SignMessage(message, params);
+
+ if (hardware_auths.Contains(TAG_USAGE_COUNT_LIMIT, 3U)) {
+ // Usage count limit tag is enforced by hardware. After using the key, the key blob
+ // must be invalidated from secure storage (such as RPMB partition).
+ EXPECT_EQ(ErrorCode::INVALID_KEY_BLOB, Begin(KeyPurpose::SIGN, params));
+ } else {
+ // Usage count limit tag is enforced by keystore, keymint does nothing.
+ EXPECT_TRUE(keystore_auths.Contains(TAG_USAGE_COUNT_LIMIT, 3U));
+ EXPECT_EQ(ErrorCode::OK, Begin(KeyPurpose::SIGN, params));
+ }
+}
+
+INSTANTIATE_KEYMINT_AIDL_TEST(UsageCountLimitTest);
+
typedef KeyMintAidlTestBase AddEntropyTest;
/*
@@ -4424,6 +4775,121 @@ TEST_P(TransportLimitTest, LargeFinishInput) {
INSTANTIATE_KEYMINT_AIDL_TEST(TransportLimitTest);
+typedef KeyMintAidlTestBase KeyAgreementTest;
+
+int CurveToOpenSslCurveName(EcCurve curve) {
+ switch (curve) {
+ case EcCurve::P_224:
+ return NID_secp224r1;
+ case EcCurve::P_256:
+ return NID_X9_62_prime256v1;
+ case EcCurve::P_384:
+ return NID_secp384r1;
+ case EcCurve::P_521:
+ return NID_secp521r1;
+ }
+}
+
+/*
+ * KeyAgreementTest.Ecdh
+ *
+ * Verifies that ECDH works for all curves
+ */
+TEST_P(KeyAgreementTest, Ecdh) {
+ // Because it's possible to use this API with keys on different curves, we
+ // check all N^2 combinations where N is the number of supported
+ // curves.
+ //
+ // This is not a big deal as N is 4 so we only do 16 runs. If we end up with a
+ // lot more curves we can be smart about things and just pick |otherCurve| so
+ // it's not |curve| and that way we end up with only 2*N runs
+ //
+ for (auto curve : ValidCurves()) {
+ for (auto localCurve : ValidCurves()) {
+ // Generate EC key locally (with access to private key material)
+ auto ecKey = EC_KEY_Ptr(EC_KEY_new());
+ int curveName = CurveToOpenSslCurveName(localCurve);
+ auto group = EC_GROUP_Ptr(EC_GROUP_new_by_curve_name(curveName));
+ ASSERT_NE(group, nullptr);
+ ASSERT_EQ(EC_KEY_set_group(ecKey.get(), group.get()), 1);
+ ASSERT_EQ(EC_KEY_generate_key(ecKey.get()), 1);
+ auto pkey = EVP_PKEY_Ptr(EVP_PKEY_new());
+ ASSERT_EQ(EVP_PKEY_set1_EC_KEY(pkey.get(), ecKey.get()), 1);
+
+ // Get encoded form of the public part of the locally generated key...
+ unsigned char* p = nullptr;
+ int encodedPublicKeySize = i2d_PUBKEY(pkey.get(), &p);
+ ASSERT_GT(encodedPublicKeySize, 0);
+ vector<uint8_t> encodedPublicKey(
+ reinterpret_cast<const uint8_t*>(p),
+ reinterpret_cast<const uint8_t*>(p + encodedPublicKeySize));
+ OPENSSL_free(p);
+
+ // Generate EC key in KeyMint (only access to public key material)
+ vector<uint8_t> challenge = {0x41, 0x42};
+ EXPECT_EQ(
+ ErrorCode::OK,
+ GenerateKey(AuthorizationSetBuilder()
+ .Authorization(TAG_NO_AUTH_REQUIRED)
+ .Authorization(TAG_EC_CURVE, curve)
+ .Authorization(TAG_PURPOSE, KeyPurpose::AGREE_KEY)
+ .Authorization(TAG_ALGORITHM, Algorithm::EC)
+ .Authorization(TAG_ATTESTATION_APPLICATION_ID, {0x61, 0x62})
+ .Authorization(TAG_ATTESTATION_CHALLENGE, challenge)))
+ << "Failed to generate key";
+ ASSERT_GT(cert_chain_.size(), 0);
+ X509_Ptr kmKeyCert(parse_cert_blob(cert_chain_[0].encodedCertificate));
+ ASSERT_NE(kmKeyCert, nullptr);
+ // Check that keyAgreement (bit 4) is set in KeyUsage
+ EXPECT_TRUE((X509_get_key_usage(kmKeyCert.get()) & X509v3_KU_KEY_AGREEMENT) != 0);
+ auto kmPkey = EVP_PKEY_Ptr(X509_get_pubkey(kmKeyCert.get()));
+ ASSERT_NE(kmPkey, nullptr);
+ if (dump_Attestations) {
+ for (size_t n = 0; n < cert_chain_.size(); n++) {
+ std::cout << bin2hex(cert_chain_[n].encodedCertificate) << std::endl;
+ }
+ }
+
+ // Now that we have the two keys, we ask KeyMint to perform ECDH...
+ if (curve != localCurve) {
+ // If the keys are using different curves KeyMint should fail with
+ // ErrorCode:INVALID_ARGUMENT. Check that.
+ EXPECT_EQ(ErrorCode::OK, Begin(KeyPurpose::AGREE_KEY, AuthorizationSetBuilder()));
+ string ZabFromKeyMintStr;
+ EXPECT_EQ(ErrorCode::INVALID_ARGUMENT,
+ Finish(string(encodedPublicKey.begin(), encodedPublicKey.end()),
+ &ZabFromKeyMintStr));
+
+ } else {
+ // Otherwise if the keys are using the same curve, it should work.
+ EXPECT_EQ(ErrorCode::OK, Begin(KeyPurpose::AGREE_KEY, AuthorizationSetBuilder()));
+ string ZabFromKeyMintStr;
+ EXPECT_EQ(ErrorCode::OK,
+ Finish(string(encodedPublicKey.begin(), encodedPublicKey.end()),
+ &ZabFromKeyMintStr));
+ vector<uint8_t> ZabFromKeyMint(ZabFromKeyMintStr.begin(), ZabFromKeyMintStr.end());
+
+ // Perform local ECDH between the two keys so we can check if we get the same Zab..
+ auto ctx = EVP_PKEY_CTX_Ptr(EVP_PKEY_CTX_new(pkey.get(), nullptr));
+ ASSERT_NE(ctx, nullptr);
+ ASSERT_EQ(EVP_PKEY_derive_init(ctx.get()), 1);
+ ASSERT_EQ(EVP_PKEY_derive_set_peer(ctx.get(), kmPkey.get()), 1);
+ size_t ZabFromTestLen = 0;
+ ASSERT_EQ(EVP_PKEY_derive(ctx.get(), nullptr, &ZabFromTestLen), 1);
+ vector<uint8_t> ZabFromTest;
+ ZabFromTest.resize(ZabFromTestLen);
+ ASSERT_EQ(EVP_PKEY_derive(ctx.get(), ZabFromTest.data(), &ZabFromTestLen), 1);
+
+ EXPECT_EQ(ZabFromKeyMint, ZabFromTest);
+ }
+
+ CheckedDeleteKey();
+ }
+ }
+}
+
+INSTANTIATE_KEYMINT_AIDL_TEST(KeyAgreementTest);
+
} // namespace aidl::android::hardware::security::keymint::test
int main(int argc, char** argv) {