From e2524538f6e5f09690ac674953e10269294cf9d2 Mon Sep 17 00:00:00 2001 From: Jakub Jelen Date: Tue, 5 Nov 2024 12:42:14 +0100 Subject: [PATCH] curve25519: Avoid reading private curve25519 keys from OpenSSL structures The previous code created private key curve25519 in OpenSSL, then exported private key and during key generation, created a new OpenSSL private key object. This is needless amount of copying potentially sensitive data back and forth and this will not work when the private key would be backed with external OpenSSL provider, such as pkcs11 provider or different crypto accelerator handling the private key operations for us. Signed-off-by: Jakub Jelen Reviewed-by: Sahana Prasad --- include/libssh/crypto.h | 4 ++++ src/curve25519.c | 30 +++++++----------------------- src/wrapper.c | 3 +++ 3 files changed, 14 insertions(+), 23 deletions(-) diff --git a/include/libssh/crypto.h b/include/libssh/crypto.h index 8dcf5408..a5111802 100644 --- a/include/libssh/crypto.h +++ b/include/libssh/crypto.h @@ -125,7 +125,11 @@ struct ssh_crypto_struct { ssh_string ecdh_server_pubkey; #endif #ifdef HAVE_CURVE25519 +#ifdef HAVE_LIBCRYPTO + EVP_PKEY *curve25519_privkey; +#else ssh_curve25519_privkey curve25519_privkey; +#endif ssh_curve25519_pubkey curve25519_client_pubkey; ssh_curve25519_pubkey curve25519_server_pubkey; #endif diff --git a/src/curve25519.c b/src/curve25519.c index 3f57f25d..db6c6a9b 100644 --- a/src/curve25519.c +++ b/src/curve25519.c @@ -62,8 +62,8 @@ static int ssh_curve25519_init(ssh_session session) #ifdef HAVE_LIBCRYPTO EVP_PKEY_CTX *pctx = NULL; EVP_PKEY *pkey = NULL; + ssh_curve25519_pubkey *pubkey_loc = NULL; size_t pubkey_len = CURVE25519_PUBKEY_SIZE; - size_t pkey_len = CURVE25519_PRIVKEY_SIZE; pctx = EVP_PKEY_CTX_new_id(EVP_PKEY_X25519, NULL); if (pctx == NULL) { @@ -92,15 +92,12 @@ static int ssh_curve25519_init(ssh_session session) } if (session->server) { - rc = EVP_PKEY_get_raw_public_key(pkey, - session->next_crypto->curve25519_server_pubkey, - &pubkey_len); + pubkey_loc = &session->next_crypto->curve25519_server_pubkey; } else { - rc = EVP_PKEY_get_raw_public_key(pkey, - session->next_crypto->curve25519_client_pubkey, - &pubkey_len); + pubkey_loc = &session->next_crypto->curve25519_client_pubkey; } + rc = EVP_PKEY_get_raw_public_key(pkey, *pubkey_loc, &pubkey_len); if (rc != 1) { SSH_LOG(SSH_LOG_TRACE, "Failed to get X25519 raw public key: %s", @@ -109,18 +106,8 @@ static int ssh_curve25519_init(ssh_session session) return SSH_ERROR; } - rc = EVP_PKEY_get_raw_private_key(pkey, - session->next_crypto->curve25519_privkey, - &pkey_len); - if (rc != 1) { - SSH_LOG(SSH_LOG_TRACE, - "Failed to get X25519 raw private key: %s", - ERR_error_string(ERR_get_error(), NULL)); - EVP_PKEY_free(pkey); - return SSH_ERROR; - } - - EVP_PKEY_free(pkey); + session->next_crypto->curve25519_privkey = pkey; + pkey = NULL; #else rc = ssh_get_random(session->next_crypto->curve25519_privkey, CURVE25519_PRIVKEY_SIZE, 1); @@ -187,9 +174,7 @@ static int ssh_curve25519_build_k(ssh_session session) size_t shared_key_len = sizeof(k); int rc, ret = SSH_ERROR; - pkey = EVP_PKEY_new_raw_private_key(EVP_PKEY_X25519, NULL, - session->next_crypto->curve25519_privkey, - CURVE25519_PRIVKEY_SIZE); + pkey = session->next_crypto->curve25519_privkey; if (pkey == NULL) { SSH_LOG(SSH_LOG_TRACE, "Failed to create X25519 EVP_PKEY: %s", @@ -246,7 +231,6 @@ static int ssh_curve25519_build_k(ssh_session session) } ret = SSH_OK; out: - EVP_PKEY_free(pkey); EVP_PKEY_free(pubkey); EVP_PKEY_CTX_free(pctx); if (ret == SSH_ERROR) { diff --git a/src/wrapper.c b/src/wrapper.c index 90add506..32f2877f 100644 --- a/src/wrapper.c +++ b/src/wrapper.c @@ -188,6 +188,9 @@ void crypto_free(struct ssh_crypto_struct *crypto) #endif crypto->ecdh_privkey = NULL; } +#endif +#ifdef HAVE_LIBCRYPTO + EVP_PKEY_free(crypto->curve25519_privkey); #endif SAFE_FREE(crypto->dh_server_signature); if (crypto->session_id != NULL) {