Reputation: 39
Most of the API that EC_KEY*
functions like EC_KEY_get0_public_key
have been deprecated in OpenSSL 3.0, so as far as I know there's no way but to use the EVP interface. I want to export the public key to a buffer, calculate a MAC over it and then verify the MAC before using the key for a DH key exchange at the recipient end.
I could get a EVP_PKEY
object with the generated EC key but I cannot figure out how to extract the public key (raw bytes) and the group name in a way that I can reconstruct for an ECDH key exchange.
void generateAndExport() {
/* params have been set */
EVP_PKEY_CTX *keygen_ctx;
EC_PKEY *ec_key;
size_t pubkey_size;
if (!(keygen_ctx = EVP_PKEY_CTX_new(ec_params, NULL)))
return -1;
if (!EVP_PKEY_keygen_init(keygen_ctx))
return -1;
if (!EVP_PKEY_keygen(keygen_ctx, &ec_key))
return -1;
pubkey_size = 0;
/* Query the buffer size */
if (!EVP_PKEY_get_octet_string_param(
ec_key, OSSL_PKEY_PARAM_PUB_KEY, NULL, 0, &pubkey_size))
return -1;
/* Allocate the buffer for the public key */
if (!(ec_pub = calloc(1, pubkey_size)))
return -1;
/* Get the public key */
if (!EVP_PKEY_get_octet_string_param(ec_key,
OSSL_PKEY_PARAM_PUB_KEY, ec_pub,
pubkey_size, &pubkey_size))
return -1;
/* calculate a MAC over the public key */
cleanup:
EVP_PKEY_CTX_free(keygen_ctx);
EVP_PKEY_free(ec_key);
return 0;
}
Edit: This seems to be the correct code for doing exactly what I wanted. If anyone would like to know, here is the code I used for recovering the public key and deriving a shared secret:
void deriveSharedSecret(EVP_PKEY *priv,
unsigned char *pkey,
size_t pkey_len,
unsigned char *group_name,
unsigned char **shared_key,
size_t *shared_key_len) {
EVP_PKEY_CTX *derive_ctx = NULL;
EVP_PKEY *peer_key = NULL;
CHECK(pkey && (pkey_len > 0));
CHECK(!(peer_key = EVP_PKEY_new_raw_public_key(
EVP_PKEY_EC,
NULL,
pkey,
pkey_len)));
CHECK(derive_ctx = EVP_PKEY_CTX_new(priv, NULL));
CHECK(EVP_PKEY_derive_init(derive_ctx));
CHECK(EVP_PKEY_CTX_set_group_name(derive_ctx, group_name));
CHECK(EVP_PKEY_derive_set_peer(derive_ctx, peer_key));
/* Query buffer size for shared secret */
*shared_key_len = 0;
CHECK(EVP_PKEY_derive(derive_ctx, NULL, shared_key_len));
if (!(*shared_key = calloc(1, *shared_key_len)))
return -1;
CHECK(EVP_PKEY_derive(derive_ctx, *shared_key, shared_key_len));
EVP_PKEY_free(peer_key);
EVP_PKEY_CTX_free(derive_ctx);
return 0;
}
Also, to get the group name:
unsigned char groupname[MAX_GROUP_NAME_SIZE];
size_t groupname_len;
CHECK(EVP_PKEY_get_octet_string_param(
ec_key,
OSSL_PKEY_PARAM_GROUP_NAME,
groupname,
0,
&groupname_len));
Upvotes: 0
Views: 130