diff options
author | David Drysdale <drysdale@google.com> | 2022-05-09 16:43:00 +0100 |
---|---|---|
committer | David Drysdale <drysdale@google.com> | 2022-05-10 11:21:11 +0100 |
commit | 415260e22f4ee4827a10d3204b8f3438e22ea789 (patch) | |
tree | 5a63b141521b6f655f51c5a0a5890a91629818e3 | |
parent | 9931e2182d308a3a67d65505264a23399fd10772 (diff) | |
download | keymaster-415260e22f4ee4827a10d3204b8f3438e22ea789.tar.gz |
Expect x25519 data as SubjectPublicKeyInfo
Expect that the data for an X25519 key agreement operations should
arrive in the form of a SubjectPublicKeyInfo ASN1 structure rather than
just a raw key. This is more convenient and more consistent with the
expectations for other EC keys (using NIST curves).
Now that x25519 public keys are arriving in a SubjectPublicKeyInfo
envelope, make sure the correct error code is emitted when they
trigger a failure when erroneously attempting to perform key agreement
against a NIST curve private key.
Test: VtsAidlKeyMintTargetTest
Bug: 231959070
Change-Id: I0d515a7d3b7124288d36cbd219e3679fa5137f0c
Merged-In: I0d515a7d3b7124288d36cbd219e3679fa5137f0c
Ignore-AOSP-First: already in aosp/master
-rw-r--r-- | km_openssl/ecdh_operation.cpp | 32 |
1 files changed, 27 insertions, 5 deletions
diff --git a/km_openssl/ecdh_operation.cpp b/km_openssl/ecdh_operation.cpp index 13f6d6f..47f7361 100644 --- a/km_openssl/ecdh_operation.cpp +++ b/km_openssl/ecdh_operation.cpp @@ -50,7 +50,7 @@ keymaster_error_t EcdhOperation::Finish(const AuthorizationSet& /*additional_par EVP_PKEY* pkeyRaw = d2i_PUBKEY(nullptr, &encodedPublicKey, input.available_read()); if (pkeyRaw == nullptr) { LOG_E("Error decoding key", 0); - return TranslateLastOpenSslError(); + return KM_ERROR_INVALID_ARGUMENT; } auto pkey = EVP_PKEY_Ptr(pkeyRaw); @@ -65,7 +65,7 @@ keymaster_error_t EcdhOperation::Finish(const AuthorizationSet& /*additional_par } if (EVP_PKEY_derive_set_peer(ctx.get(), pkey.get()) != 1) { LOG_E("Error setting peer key", 0); - return TranslateLastOpenSslError(); + return KM_ERROR_INVALID_ARGUMENT; } size_t sharedSecretLen = 0; if (EVP_PKEY_derive(ctx.get(), nullptr, &sharedSecretLen) != 1) { @@ -88,10 +88,32 @@ keymaster_error_t EcdhOperation::Finish(const AuthorizationSet& /*additional_par keymaster_error_t X25519Operation::Finish(const AuthorizationSet& /*additional_params*/, const Buffer& input, const Buffer& /*signature*/, AuthorizationSet* /*output_params*/, Buffer* output) { - if (input.available_read() != X25519_PUBLIC_VALUE_LEN) { - LOG_E("Invalid length %d of peer key", input.available_read()); + // Retrieve the peer X25519 key from within the ASN.1 SubjectPublicKeyInfo. + const unsigned char* encodedPublicKey = input.begin(); + EVP_PKEY* pkeyRaw = d2i_PUBKEY(nullptr, &encodedPublicKey, input.available_read()); + if (pkeyRaw == nullptr) { + LOG_E("Error decoding key", 0); + return KM_ERROR_INVALID_ARGUMENT; + } + auto pkey = EVP_PKEY_Ptr(pkeyRaw); + + int pkey_type = EVP_PKEY_id(pkey.get()); + if (pkey_type != EVP_PKEY_X25519) { + LOG_E("Unexpected peer public key type %d", pkey_type); return KM_ERROR_INVALID_ARGUMENT; } + + size_t pub_key_len = X25519_PUBLIC_VALUE_LEN; + uint8_t pub_key[X25519_PUBLIC_VALUE_LEN]; + if (EVP_PKEY_get_raw_public_key(pkey.get(), pub_key, &pub_key_len) == 0) { + LOG_E("Error extracting key", 0); + return KM_ERROR_INVALID_ARGUMENT; + } + if (pub_key_len != X25519_PUBLIC_VALUE_LEN) { + LOG_E("Invalid length %d of peer key", pub_key_len); + return KM_ERROR_INVALID_ARGUMENT; + } + size_t key_len = X25519_PRIVATE_KEY_LEN; uint8_t priv_key[X25519_PRIVATE_KEY_LEN]; if (EVP_PKEY_get_raw_private_key(ecdh_key_.get(), priv_key, &key_len) == 0) { @@ -104,7 +126,7 @@ keymaster_error_t X25519Operation::Finish(const AuthorizationSet& /*additional_p LOG_E("Error reserving data in output buffer", 0); return KM_ERROR_MEMORY_ALLOCATION_FAILED; } - if (X25519(output->peek_write(), priv_key, input.begin()) != 1) { + if (X25519(output->peek_write(), priv_key, pub_key) != 1) { LOG_E("Error deriving key", 0); return TranslateLastOpenSslError(); } |