summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDavid Drysdale <drysdale@google.com>2022-05-09 16:43:00 +0100
committerDavid Drysdale <drysdale@google.com>2022-05-10 11:21:11 +0100
commit415260e22f4ee4827a10d3204b8f3438e22ea789 (patch)
tree5a63b141521b6f655f51c5a0a5890a91629818e3
parent9931e2182d308a3a67d65505264a23399fd10772 (diff)
downloadkeymaster-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.cpp32
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();
}