diff --git a/src/dh_crypto.c b/src/dh_crypto.c index 3b3495c1..a847c6a2 100644 --- a/src/dh_crypto.c +++ b/src/dh_crypto.c @@ -30,6 +30,13 @@ #include "openssl/crypto.h" #include "openssl/dh.h" #include "libcrypto-compat.h" +#if OPENSSL_VERSION_NUMBER >= 0x30000000L +#include +#include +#include +#include +#include +#endif /* OPENSSL_VERSION_NUMBER */ extern bignum ssh_dh_generator; extern bignum ssh_dh_group1; @@ -38,13 +45,21 @@ extern bignum ssh_dh_group16; extern bignum ssh_dh_group18; struct dh_ctx { +#if OPENSSL_VERSION_NUMBER < 0x30000000L DH *keypair[2]; +#else + EVP_PKEY *keypair[2]; +#endif /* OPENSSL_VERSION_NUMBER */ }; void ssh_dh_debug_crypto(struct ssh_crypto_struct *c) { #ifdef DEBUG_CRYPTO +#if OPENSSL_VERSION_NUMBER < 0x30000000L const_bignum x = NULL, y = NULL, e = NULL, f = NULL; +#else + bignum x = NULL, y = NULL, e = NULL, f = NULL; +#endif /* OPENSSL_VERSION_NUMBER */ ssh_dh_keypair_get_keys(c->dh_ctx, DH_CLIENT_KEYPAIR, &x, &e); ssh_dh_keypair_get_keys(c->dh_ctx, DH_SERVER_KEYPAIR, &y, &f); @@ -52,6 +67,12 @@ void ssh_dh_debug_crypto(struct ssh_crypto_struct *c) ssh_print_bignum("y", y); ssh_print_bignum("e", e); ssh_print_bignum("f", f); +#if OPENSSL_VERSION_NUMBER >= 0x30000000L + bignum_safe_free(x); + bignum_safe_free(y); + bignum_safe_free(e); + bignum_safe_free(f); +#endif /* OPENSSL_VERSION_NUMBER */ ssh_log_hexdump("Session server cookie", c->server_kex.cookie, 16); ssh_log_hexdump("Session client cookie", c->client_kex.cookie, 16); @@ -59,9 +80,10 @@ void ssh_dh_debug_crypto(struct ssh_crypto_struct *c) #else (void)c; /* UNUSED_PARAM */ -#endif +#endif /* DEBUG_CRYPTO */ } +#if OPENSSL_VERSION_NUMBER < 0x30000000L int ssh_dh_keypair_get_keys(struct dh_ctx *ctx, int peer, const_bignum *priv, const_bignum *pub) { @@ -70,7 +92,9 @@ int ssh_dh_keypair_get_keys(struct dh_ctx *ctx, int peer, (ctx->keypair[peer] == NULL)) { return SSH_ERROR; } + DH_get0_key(ctx->keypair[peer], pub, priv); + if (priv && (*priv == NULL || bignum_num_bits(*priv) == 0)) { return SSH_ERROR; } @@ -81,12 +105,13 @@ int ssh_dh_keypair_get_keys(struct dh_ctx *ctx, int peer, return SSH_OK; } -int ssh_dh_keypair_set_keys(struct dh_ctx *ctx, int peer, - const bignum priv, const bignum pub) +#else +/* If set *priv and *pub should be initialized + * to NULL before calling this function*/ +int ssh_dh_keypair_get_keys(struct dh_ctx *ctx, int peer, + bignum *priv, bignum *pub) { - bignum priv_key = NULL; - bignum pub_key = NULL; - + int rc; if (((peer != DH_CLIENT_KEYPAIR) && (peer != DH_SERVER_KEYPAIR)) || ((priv == NULL) && (pub == NULL)) || (ctx == NULL) || (ctx->keypair[peer] == NULL)) { @@ -94,16 +119,145 @@ int ssh_dh_keypair_set_keys(struct dh_ctx *ctx, int peer, } if (priv) { - priv_key = priv; + rc = EVP_PKEY_get_bn_param(ctx->keypair[peer], + OSSL_PKEY_PARAM_PRIV_KEY, + priv); + if (rc != 1) { + return SSH_ERROR; + } } if (pub) { - pub_key = pub; + rc = EVP_PKEY_get_bn_param(ctx->keypair[peer], + OSSL_PKEY_PARAM_PUB_KEY, + pub); + if (rc != 1) { + return SSH_ERROR; + } + } + if (priv && (*priv == NULL || bignum_num_bits(*priv) == 0)) { + if (pub && (*pub != NULL && bignum_num_bits(*pub) != 0)) { + bignum_safe_free(*pub); + *pub = NULL; + } + return SSH_ERROR; + } + if (pub && (*pub == NULL || bignum_num_bits(*pub) == 0)) { + if (priv) { + bignum_safe_free(*priv); + *priv = NULL; + } + return SSH_ERROR; } - (void)DH_set0_key(ctx->keypair[peer], pub_key, priv_key); return SSH_OK; } +#endif /* OPENSSL_VERSION_NUMBER */ +int ssh_dh_keypair_set_keys(struct dh_ctx *ctx, int peer, + const bignum priv, const bignum pub) +{ +#if OPENSSL_VERSION_NUMBER < 0x30000000L + bignum priv_key = NULL; + bignum pub_key = NULL; +#else + int rc; + OSSL_PARAM *params = NULL, *out_params = NULL, *merged_params = NULL; + OSSL_PARAM_BLD *param_bld = NULL; + EVP_PKEY_CTX *evp_ctx = NULL; +#endif /* OPENSSL_VERSION_NUMBER */ + + if (((peer != DH_CLIENT_KEYPAIR) && (peer != DH_SERVER_KEYPAIR)) || + ((priv == NULL) && (pub == NULL)) || (ctx == NULL) || + (ctx->keypair[peer] == NULL)) { + return SSH_ERROR; + } + +#if OPENSSL_VERSION_NUMBER >= 0x30000000L + rc = EVP_PKEY_todata(ctx->keypair[peer], EVP_PKEY_KEYPAIR, &out_params); + if (rc != 1) { + return SSH_ERROR; + } + + param_bld = OSSL_PARAM_BLD_new(); + if (param_bld == NULL) { + rc = SSH_ERROR; + goto out; + } + + evp_ctx = EVP_PKEY_CTX_new_from_pkey(NULL, ctx->keypair[peer], NULL); + if (evp_ctx == NULL) { + rc = SSH_ERROR; + goto out; + } + + rc = EVP_PKEY_fromdata_init(evp_ctx); + if (rc != 1) { + rc = SSH_ERROR; + goto out; + } +#endif /* OPENSSL_VERSION_NUMBER */ + + if (priv) { +#if OPENSSL_VERSION_NUMBER < 0x30000000L + priv_key = priv; +#else + rc = OSSL_PARAM_BLD_push_BN(param_bld, OSSL_PKEY_PARAM_PRIV_KEY, priv); + if (rc != 1) { + rc = SSH_ERROR; + goto out; + } +#endif /* OPENSSL_VERSION_NUMBER */ + } + if (pub) { +#if OPENSSL_VERSION_NUMBER < 0x30000000L + pub_key = pub; +#else + rc = OSSL_PARAM_BLD_push_BN(param_bld, OSSL_PKEY_PARAM_PUB_KEY, pub); + if (rc != 1) { + rc = SSH_ERROR; + goto out; + } +#endif /* OPENSSL_VERSION_NUMBER */ + } +#if OPENSSL_VERSION_NUMBER < 0x30000000L + (void)DH_set0_key(ctx->keypair[peer], pub_key, priv_key); + + return SSH_OK; +#else + params = OSSL_PARAM_BLD_to_param(param_bld); + if (params == NULL) { + rc = SSH_ERROR; + goto out; + } + OSSL_PARAM_BLD_free(param_bld); + + merged_params = OSSL_PARAM_merge(out_params, params); + if (merged_params == NULL) { + rc = SSH_ERROR; + goto out; + } + + rc = EVP_PKEY_fromdata(evp_ctx, + &(ctx->keypair[peer]), + EVP_PKEY_PUBLIC_KEY, + merged_params); + if (rc != 1) { + rc = SSH_ERROR; + goto out; + } + + rc = SSH_OK; +out: + EVP_PKEY_CTX_free(evp_ctx); + OSSL_PARAM_free(out_params); + OSSL_PARAM_free(params); + OSSL_PARAM_free(merged_params); + + return rc; +#endif /* OPENSSL_VERSION_NUMBER */ +} + +#if OPENSSL_VERSION_NUMBER < 0x30000000L int ssh_dh_get_parameters(struct dh_ctx *ctx, const_bignum *modulus, const_bignum *generator) { @@ -113,18 +267,51 @@ int ssh_dh_get_parameters(struct dh_ctx *ctx, DH_get0_pqg(ctx->keypair[0], modulus, NULL, generator); return SSH_OK; } +#else +int ssh_dh_get_parameters(struct dh_ctx *ctx, + bignum *modulus, bignum *generator) +{ + int rc; + + if (ctx == NULL || ctx->keypair[0] == NULL) { + return SSH_ERROR; + } + + rc = EVP_PKEY_get_bn_param(ctx->keypair[0], OSSL_PKEY_PARAM_FFC_P, (BIGNUM**)modulus); + if (rc != 1) { + return SSH_ERROR; + } + rc = EVP_PKEY_get_bn_param(ctx->keypair[0], OSSL_PKEY_PARAM_FFC_G, (BIGNUM**)generator); + if (rc != 1) { + bignum_safe_free(*modulus); + return SSH_ERROR; + } + + return SSH_OK; +} +#endif /* OPENSSL_VERSION_NUMBER */ int ssh_dh_set_parameters(struct dh_ctx *ctx, const bignum modulus, const bignum generator) { size_t i; int rc; +#if OPENSSL_VERSION_NUMBER >= 0x30000000L + OSSL_PARAM *params = NULL; + OSSL_PARAM_BLD *param_bld = NULL; + EVP_PKEY_CTX *evp_ctx = NULL; +#endif /* OPENSSL_VERSION_NUMBER */ if ((ctx == NULL) || (modulus == NULL) || (generator == NULL)) { return SSH_ERROR; } +#if OPENSSL_VERSION_NUMBER >= 0x30000000L + evp_ctx = EVP_PKEY_CTX_new_from_name(NULL, "DHX", NULL); +#endif + for (i = 0; i < 2; i++) { +#if OPENSSL_VERSION_NUMBER < 0x30000000L bignum p = NULL; bignum g = NULL; @@ -146,16 +333,70 @@ int ssh_dh_set_parameters(struct dh_ctx *ctx, rc = SSH_ERROR; goto done; } +#else + param_bld = OSSL_PARAM_BLD_new(); + + if (param_bld == NULL) { + rc = SSH_ERROR; + goto done; + } + + OSSL_PARAM_BLD_push_BN(param_bld, OSSL_PKEY_PARAM_FFC_P, modulus); + OSSL_PARAM_BLD_push_BN(param_bld, OSSL_PKEY_PARAM_FFC_G, generator); + params = OSSL_PARAM_BLD_to_param(param_bld); + if (params == NULL) { + OSSL_PARAM_BLD_free(param_bld); + rc = SSH_ERROR; + goto done; + } + OSSL_PARAM_BLD_free(param_bld); + + rc = EVP_PKEY_fromdata_init(evp_ctx); + if (rc != 1) { + OSSL_PARAM_free(params); + rc = SSH_ERROR; + goto done; + } + + /* make sure to invalidate existing keys */ + EVP_PKEY_free(ctx->keypair[i]); + ctx->keypair[i] = NULL; + + rc = EVP_PKEY_fromdata(evp_ctx, + &(ctx->keypair[i]), + EVP_PKEY_KEY_PARAMETERS, + params); + if (rc != 1) { + OSSL_PARAM_free(params); + rc = SSH_ERROR; + goto done; + } + + OSSL_PARAM_free(params); +#endif /* OPENSSL_VERSION_NUMBER */ } rc = SSH_OK; +#if OPENSSL_VERSION_NUMBER < 0x30000000L done: if (rc != SSH_OK) { DH_free(ctx->keypair[0]); DH_free(ctx->keypair[1]); + } +#else +done: + EVP_PKEY_CTX_free(evp_ctx); + + if (rc != SSH_OK) { + EVP_PKEY_free(ctx->keypair[0]); + EVP_PKEY_free(ctx->keypair[1]); + } +#endif /* OPENSSL_VERSION_NUMBER */ + if (rc != SSH_OK) { ctx->keypair[0] = NULL; ctx->keypair[1] = NULL; } + return rc; } @@ -202,8 +443,13 @@ int ssh_dh_init_common(struct ssh_crypto_struct *crypto) void ssh_dh_cleanup(struct ssh_crypto_struct *crypto) { if (crypto->dh_ctx != NULL) { +#if OPENSSL_VERSION_NUMBER < 0x30000000L DH_free(crypto->dh_ctx->keypair[0]); DH_free(crypto->dh_ctx->keypair[1]); +#else + EVP_PKEY_free(crypto->dh_ctx->keypair[0]); + EVP_PKEY_free(crypto->dh_ctx->keypair[1]); +#endif /* OPENSSL_VERSION_NUMBER */ free(crypto->dh_ctx); crypto->dh_ctx = NULL; } @@ -221,14 +467,43 @@ void ssh_dh_cleanup(struct ssh_crypto_struct *crypto) int ssh_dh_keypair_gen_keys(struct dh_ctx *dh_ctx, int peer) { int rc; +#if OPENSSL_VERSION_NUMBER >= 0x30000000L + EVP_PKEY_CTX *evp_ctx = NULL; +#endif if ((dh_ctx == NULL) || (dh_ctx->keypair[peer] == NULL)) { return SSH_ERROR; } + +#if OPENSSL_VERSION_NUMBER < 0x30000000L rc = DH_generate_key(dh_ctx->keypair[peer]); if (rc != 1) { return SSH_ERROR; } +#else + evp_ctx = EVP_PKEY_CTX_new_from_pkey(NULL, dh_ctx->keypair[peer], NULL); + if (evp_ctx == NULL) { + return SSH_ERROR; + } + + rc = EVP_PKEY_keygen_init(evp_ctx); + if (rc != 1) { + EVP_PKEY_CTX_free(evp_ctx); + return SSH_ERROR; + } + + rc = EVP_PKEY_generate(evp_ctx, &(dh_ctx->keypair[peer])); + if (rc != 1) { + EVP_PKEY_CTX_free(evp_ctx); + SSH_LOG(SSH_LOG_TRACE, + "Failed to generate DH: %s", + ERR_error_string(ERR_get_error(), NULL)); + return SSH_ERROR; + } + + EVP_PKEY_CTX_free(evp_ctx); +#endif /* OPENSSL_VERSION_NUMBER */ + return SSH_OK; } @@ -247,8 +522,14 @@ int ssh_dh_compute_shared_secret(struct dh_ctx *dh_ctx, int local, int remote, bignum *dest) { unsigned char *kstring = NULL; + int rc; +#if OPENSSL_VERSION_NUMBER < 0x30000000L const_bignum pub_key = NULL; - int klen, rc; + int klen; +#else + size_t klen; + EVP_PKEY_CTX *evp_ctx = NULL; +#endif /* OPENSSL_VERSION_NUMBER */ if ((dh_ctx == NULL) || (dh_ctx->keypair[local] == NULL) || @@ -256,6 +537,7 @@ int ssh_dh_compute_shared_secret(struct dh_ctx *dh_ctx, int local, int remote, return SSH_ERROR; } +#if OPENSSL_VERSION_NUMBER < 0x30000000L kstring = malloc(DH_size(dh_ctx->keypair[local])); if (kstring == NULL) { rc = SSH_ERROR; @@ -273,6 +555,43 @@ int ssh_dh_compute_shared_secret(struct dh_ctx *dh_ctx, int local, int remote, rc = SSH_ERROR; goto done; } +#else + evp_ctx = EVP_PKEY_CTX_new_from_pkey(NULL, dh_ctx->keypair[local], NULL); + + rc = EVP_PKEY_derive_init(evp_ctx); + if (rc != 1) { + rc = SSH_ERROR; + goto done; + } + + rc = EVP_PKEY_derive_set_peer(evp_ctx, dh_ctx->keypair[remote]); + if (rc != 1) { + SSH_LOG(SSH_LOG_TRACE, + "Failed to set peer key: %s", + ERR_error_string(ERR_get_error(), NULL)); + rc = SSH_ERROR; + goto done; + } + + /* getting the size of the secret */ + rc = EVP_PKEY_derive(evp_ctx, kstring, &klen); + if (rc != 1) { + rc = SSH_ERROR; + goto done; + } + + kstring = malloc(klen); + if (kstring == NULL) { + rc = SSH_ERROR; + goto done; + } + + rc = EVP_PKEY_derive(evp_ctx, kstring, &klen); + if (rc != 1) { + rc = SSH_ERROR; + goto done; + } +#endif /* OPENSSL_VERSION_NUMBER */ *dest = BN_bin2bn(kstring, klen, NULL); if (*dest == NULL) { @@ -282,6 +601,9 @@ int ssh_dh_compute_shared_secret(struct dh_ctx *dh_ctx, int local, int remote, rc = SSH_OK; done: +#if OPENSSL_VERSION_NUMBER >= 0x30000000L + EVP_PKEY_CTX_free(evp_ctx); +#endif free(kstring); return rc; } diff --git a/src/ecdh_crypto.c b/src/ecdh_crypto.c index a1de27fd..51084b7a 100644 --- a/src/ecdh_crypto.c +++ b/src/ecdh_crypto.c @@ -30,15 +30,33 @@ #ifdef HAVE_ECDH #include - +/* TODO Change to new API when the OpenSSL will support export of uncompressed EC keys + * https://github.com/openssl/openssl/pull/16624 + * #if OPENSSL_VERSION_NUMBER < 0x30000000L + */ +#if 1 #define NISTP256 NID_X9_62_prime256v1 #define NISTP384 NID_secp384r1 #define NISTP521 NID_secp521r1 +#else +#include +#include +#include +#include "libcrypto-compat.h" +#endif /* OPENSSL_VERSION_NUMBER */ /** @internal * @brief Map the given key exchange enum value to its curve name. */ +/* TODO Change to new API when the OpenSSL will support export of uncompressed EC keys + * https://github.com/openssl/openssl/pull/16624 + * #if OPENSSL_VERSION_NUMBER < 0x30000000L + */ +#if 1 static int ecdh_kex_type_to_curve(enum ssh_key_exchange_e kex_type) { +#else +static const char *ecdh_kex_type_to_curve(enum ssh_key_exchange_e kex_type) { +#endif /* OPENSSL_VERSION_NUMBER */ if (kex_type == SSH_KEX_ECDH_SHA2_NISTP256) { return NISTP256; } else if (kex_type == SSH_KEX_ECDH_SHA2_NISTP384) { @@ -46,39 +64,94 @@ static int ecdh_kex_type_to_curve(enum ssh_key_exchange_e kex_type) { } else if (kex_type == SSH_KEX_ECDH_SHA2_NISTP521) { return NISTP521; } +/* TODO Change to new API when the OpenSSL will support export of uncompressed EC keys + * https://github.com/openssl/openssl/pull/16624 + * #if OPENSSL_VERSION_NUMBER < 0x30000000L + */ +#if 1 return SSH_ERROR; +#else + return NULL; +#endif } /** @internal * @brief Starts ecdh-sha2-nistp256 key exchange */ int ssh_client_ecdh_init(ssh_session session){ + int rc; + ssh_string client_pubkey; +/* TODO Change to new API when the OpenSSL will support export of uncompressed EC keys + * https://github.com/openssl/openssl/pull/16624 + * #if OPENSSL_VERSION_NUMBER < 0x30000000L + */ +#if 1 EC_KEY *key; const EC_GROUP *group; const EC_POINT *pubkey; - ssh_string client_pubkey; int curve; int len; - int rc; bignum_CTX ctx = BN_CTX_new(); + if (ctx == NULL) { + return SSH_ERROR; + } +#else + const char *curve = NULL; + EVP_PKEY *key = NULL; + OSSL_PARAM *out_params = NULL; + const OSSL_PARAM *pubkey_param = NULL; + const uint8_t *pubkey = NULL; + size_t pubkey_len; +#endif /* OPENSSL_VERSION_NUMBER */ rc = ssh_buffer_add_u8(session->out_buffer, SSH2_MSG_KEX_ECDH_INIT); if (rc < 0) { +/* TODO Change to new API when the OpenSSL will support export of uncompressed EC keys + * https://github.com/openssl/openssl/pull/16624 + * #if OPENSSL_VERSION_NUMBER < 0x30000000L + */ +#if 1 BN_CTX_free(ctx); +#endif /* OPENSSL_VERSION_NUMBER */ return SSH_ERROR; } curve = ecdh_kex_type_to_curve(session->next_crypto->kex_type); +/* TODO Change to new API when the OpenSSL will support export of uncompressed EC keys + * https://github.com/openssl/openssl/pull/16624 + * #if OPENSSL_VERSION_NUMBER < 0x30000000L + */ +#if 1 if (curve == SSH_ERROR) { BN_CTX_free(ctx); return SSH_ERROR; } key = EC_KEY_new_by_curve_name(curve); - if (key == NULL) { - BN_CTX_free(ctx); +#else + if (curve == NULL) { return SSH_ERROR; } + + key = EVP_EC_gen(curve); +#endif /* OPENSSL_VERSION_NUMBER */ + + if (key == NULL) { +/* TODO Change to new API when the OpenSSL will support export of uncompressed EC keys + * https://github.com/openssl/openssl/pull/16624 + * #if OPENSSL_VERSION_NUMBER < 0x30000000L + */ +#if 1 + BN_CTX_free(ctx); +#endif /* OPENSSL_VERSION_NUMBER */ + return SSH_ERROR; + } + +/* TODO Change to new API when the OpenSSL will support export of uncompressed EC keys + * https://github.com/openssl/openssl/pull/16624 + * #if OPENSSL_VERSION_NUMBER < 0x30000000L + */ +#if 1 group = EC_KEY_get0_group(key); EC_KEY_generate_key(key); @@ -97,10 +170,51 @@ int ssh_client_ecdh_init(ssh_session session){ EC_POINT_point2oct(group,pubkey,POINT_CONVERSION_UNCOMPRESSED, ssh_string_data(client_pubkey),len,ctx); BN_CTX_free(ctx); +#else + rc = EVP_PKEY_todata(key, EVP_PKEY_PUBLIC_KEY, &out_params); + if (rc != 1) { + EVP_PKEY_free(key); + return SSH_ERROR; + } + + pubkey_param = OSSL_PARAM_locate_const(out_params, OSSL_PKEY_PARAM_PUB_KEY); + if (pubkey_param == NULL) { + EVP_PKEY_free(key); + OSSL_PARAM_free(out_params); + return SSH_ERROR; + } + + rc = OSSL_PARAM_get_octet_string_ptr(pubkey_param, + (const void**)&pubkey, + &pubkey_len); + if (rc != 1) { + OSSL_PARAM_free(out_params); + EVP_PKEY_free(key); + return SSH_ERROR; + } + + client_pubkey = ssh_string_new(pubkey_len); + if (client_pubkey == NULL) { + OSSL_PARAM_free(out_params); + EVP_PKEY_free(key); + return SSH_ERROR; + } + + memcpy(ssh_string_data(client_pubkey), pubkey, pubkey_len); + OSSL_PARAM_free(out_params); +#endif /* OPENSSL_VERSION_NUMBER */ rc = ssh_buffer_add_ssh_string(session->out_buffer,client_pubkey); if (rc < 0) { +/* TODO Change to new API when the OpenSSL will support export of uncompressed EC keys + * https://github.com/openssl/openssl/pull/16624 + * #if OPENSSL_VERSION_NUMBER < 0x30000000L + */ +#if 1 EC_KEY_free(key); +#else + EVP_PKEY_free(key); +#endif /* OPENSSL_VERSION_NUMBER */ SSH_STRING_FREE(client_pubkey); return SSH_ERROR; } @@ -118,7 +232,13 @@ int ssh_client_ecdh_init(ssh_session session){ } int ecdh_build_k(ssh_session session) { - const EC_GROUP *group = EC_KEY_get0_group(session->next_crypto->ecdh_privkey); + struct ssh_crypto_struct *next_crypto = session->next_crypto; +/* TODO Change to new API when the OpenSSL will support export of uncompressed EC keys + * https://github.com/openssl/openssl/pull/16624 + * #if OPENSSL_VERSION_NUMBER < 0x30000000L + */ + #if 1 + const EC_GROUP *group = EC_KEY_get0_group(next_crypto->ecdh_privkey); EC_POINT *pubkey; void *buffer; int rc; @@ -127,7 +247,6 @@ int ecdh_build_k(ssh_session session) { if (ctx == NULL) { return -1; } - pubkey = EC_POINT_new(group); if (pubkey == NULL) { bignum_ctx_free(ctx); @@ -137,14 +256,14 @@ int ecdh_build_k(ssh_session session) { if (session->server) { rc = EC_POINT_oct2point(group, pubkey, - ssh_string_data(session->next_crypto->ecdh_client_pubkey), - ssh_string_len(session->next_crypto->ecdh_client_pubkey), + ssh_string_data(next_crypto->ecdh_client_pubkey), + ssh_string_len(next_crypto->ecdh_client_pubkey), ctx); } else { rc = EC_POINT_oct2point(group, pubkey, - ssh_string_data(session->next_crypto->ecdh_server_pubkey), - ssh_string_len(session->next_crypto->ecdh_server_pubkey), + ssh_string_data(next_crypto->ecdh_server_pubkey), + ssh_string_len(next_crypto->ecdh_server_pubkey), ctx); } bignum_ctx_free(ctx); @@ -162,7 +281,7 @@ int ecdh_build_k(ssh_session session) { rc = ECDH_compute_key(buffer, len, pubkey, - session->next_crypto->ecdh_privkey, + next_crypto->ecdh_privkey, NULL); EC_POINT_clear_free(pubkey); if (rc <= 0) { @@ -170,23 +289,121 @@ int ecdh_build_k(ssh_session session) { return -1; } - bignum_bin2bn(buffer, len, &session->next_crypto->shared_secret); + bignum_bin2bn(buffer, len, &next_crypto->shared_secret); free(buffer); - if (session->next_crypto->shared_secret == NULL) { - EC_KEY_free(session->next_crypto->ecdh_privkey); - session->next_crypto->ecdh_privkey = NULL; +#else + EVP_PKEY *pubkey = NULL; + void *secret = NULL; + size_t secret_len; + int rc; + OSSL_PARAM params[2]; + EVP_PKEY_CTX *dh_ctx = EVP_PKEY_CTX_new_from_pkey(NULL, + next_crypto->ecdh_privkey, + NULL); + EVP_PKEY_CTX *pubkey_ctx = EVP_PKEY_CTX_new_from_pkey(NULL, + next_crypto->ecdh_privkey, + NULL); + if (dh_ctx == NULL || pubkey_ctx == NULL) { + EVP_PKEY_CTX_free(dh_ctx); + EVP_PKEY_CTX_free(pubkey_ctx); return -1; } - EC_KEY_free(session->next_crypto->ecdh_privkey); - session->next_crypto->ecdh_privkey = NULL; + + rc = EVP_PKEY_derive_init(dh_ctx); + if (rc != 1) { + EVP_PKEY_CTX_free(dh_ctx); + EVP_PKEY_CTX_free(pubkey_ctx); + return -1; + } + + rc = EVP_PKEY_fromdata_init(pubkey_ctx); + if (rc != 1) { + EVP_PKEY_CTX_free(dh_ctx); + EVP_PKEY_CTX_free(pubkey_ctx); + return -1; + } + + if (session->server) { + params[0] = OSSL_PARAM_construct_octet_string(OSSL_PKEY_PARAM_PUB_KEY, + ssh_string_data(next_crypto->ecdh_client_pubkey), + ssh_string_len(next_crypto->ecdh_client_pubkey)); + } else { + params[0] = OSSL_PARAM_construct_octet_string(OSSL_PKEY_PARAM_PUB_KEY, + ssh_string_data(next_crypto->ecdh_server_pubkey), + ssh_string_len(next_crypto->ecdh_server_pubkey)); + } + params[1] = OSSL_PARAM_construct_end(); + + rc = EVP_PKEY_fromdata(pubkey_ctx, &pubkey, EVP_PKEY_PUBLIC_KEY, params); + if (rc != 1) { + EVP_PKEY_CTX_free(dh_ctx); + EVP_PKEY_CTX_free(pubkey_ctx); + return -1; + } + + EVP_PKEY_CTX_free(pubkey_ctx); + + rc = EVP_PKEY_derive_set_peer(dh_ctx, pubkey); + if (rc != 1) { + EVP_PKEY_CTX_free(dh_ctx); + return -1; + } + + /* get the max length of the secret */ + rc = EVP_PKEY_derive(dh_ctx, NULL, &secret_len); + if (rc != 1) { + EVP_PKEY_CTX_free(dh_ctx); + return -1; + } + + secret = malloc(secret_len); + if (secret == NULL) { + EVP_PKEY_CTX_free(dh_ctx); + return -1; + } + + rc = EVP_PKEY_derive(dh_ctx, secret, &secret_len); + if (rc != 1) { + EVP_PKEY_CTX_free(dh_ctx); + return -1; + } + + EVP_PKEY_CTX_free(dh_ctx); + + bignum_bin2bn(secret, secret_len, &next_crypto->shared_secret); + free(secret); +#endif /* OPENSSL_VERSION_NUMBER */ + if (next_crypto->shared_secret == NULL) { +/* TODO Change to new API when the OpenSSL will support export of uncompressed EC keys + * https://github.com/openssl/openssl/pull/16624 + * #if OPENSSL_VERSION_NUMBER < 0x30000000L + */ +#if 1 + EC_KEY_free(next_crypto->ecdh_privkey); +#else + EVP_PKEY_free(next_crypto->ecdh_privkey); +#endif /* OPENSSL_VERSION_NUMBER */ + next_crypto->ecdh_privkey = NULL; + return -1; + } +/* TODO Change to new API when the OpenSSL will support export of uncompressed EC keys + * https://github.com/openssl/openssl/pull/16624 + * #if OPENSSL_VERSION_NUMBER < 0x30000000L + */ +#if 1 + EC_KEY_free(next_crypto->ecdh_privkey); +#else + EVP_PKEY_free(next_crypto->ecdh_privkey); +#endif /* OPENSSL_VERSION_NUMBER */ + next_crypto->ecdh_privkey = NULL; #ifdef DEBUG_CRYPTO ssh_log_hexdump("Session server cookie", - session->next_crypto->server_kex.cookie, 16); + next_crypto->server_kex.cookie, 16); ssh_log_hexdump("Session client cookie", - session->next_crypto->client_kex.cookie, 16); - ssh_print_bignum("Shared secret key", session->next_crypto->shared_secret); -#endif + next_crypto->client_kex.cookie, 16); + ssh_print_bignum("Shared secret key", next_crypto->shared_secret); +#endif /* DEBUG_CRYPTO */ return 0; } @@ -200,17 +417,30 @@ SSH_PACKET_CALLBACK(ssh_packet_server_ecdh_init){ /* ECDH keys */ ssh_string q_c_string; ssh_string q_s_string; +/* TODO Change to new API when the OpenSSL will support export of uncompressed EC keys + * https://github.com/openssl/openssl/pull/16624 + * #if OPENSSL_VERSION_NUMBER < 0x30000000L + */ +#if 1 EC_KEY *ecdh_key; const EC_GROUP *group; const EC_POINT *ecdh_pubkey; bignum_CTX ctx; + int curve; + int len; +#else + EVP_PKEY *ecdh_key = NULL; + const void *pubkey_ptr = NULL; + size_t len; + OSSL_PARAM *params = NULL; + const OSSL_PARAM *pubkey = NULL; + const char *curve = NULL; +#endif /* OPENSSL_VERSION_NUMBER */ /* SSH host keys (rsa,dsa,ecdsa) */ ssh_key privkey; enum ssh_digest_e digest = SSH_DIGEST_AUTO; ssh_string sig_blob = NULL; ssh_string pubkey_blob = NULL; - int curve; - int len; int rc; (void)type; (void)user; @@ -224,23 +454,47 @@ SSH_PACKET_CALLBACK(ssh_packet_server_ecdh_init){ } session->next_crypto->ecdh_client_pubkey = q_c_string; - /* Build server's keypair */ - - ctx = BN_CTX_new(); - curve = ecdh_kex_type_to_curve(session->next_crypto->kex_type); +/* TODO Change to new API when the OpenSSL will support export of uncompressed EC keys + * https://github.com/openssl/openssl/pull/16624 + * #if OPENSSL_VERSION_NUMBER < 0x30000000L + */ +#if 1 if (curve == SSH_ERROR) { - BN_CTX_free(ctx); return SSH_ERROR; } +#else + if (curve == NULL) { + return SSH_ERROR; + } +#endif /* OPENSSL_VERSION_NUMBER */ +/* TODO Change to new API when the OpenSSL will support export of uncompressed EC keys + * https://github.com/openssl/openssl/pull/16624 + * #if OPENSSL_VERSION_NUMBER < 0x30000000L + */ +#if 1 ecdh_key = EC_KEY_new_by_curve_name(curve); +#else + ecdh_key = EVP_EC_gen(curve); +#endif /* OPENSSL_VERSION_NUMBER */ if (ecdh_key == NULL) { ssh_set_error_oom(session); - BN_CTX_free(ctx); goto error; } +/* TODO Change to new API when the OpenSSL will support export of uncompressed EC keys + * https://github.com/openssl/openssl/pull/16624 + * #if OPENSSL_VERSION_NUMBER < 0x30000000L + */ +#if 1 + /* Build server's keypair */ + ctx = BN_CTX_new(); + if (ctx == NULL) { + EC_KEY_free(ecdh_key); + return SSH_ERROR; + } + group = EC_KEY_get0_group(ecdh_key); EC_KEY_generate_key(ecdh_key); @@ -251,14 +505,47 @@ SSH_PACKET_CALLBACK(ssh_packet_server_ecdh_init){ NULL, 0, ctx); +#else + rc = EVP_PKEY_todata(ecdh_key, EVP_PKEY_PUBLIC_KEY, ¶ms); + if (rc != 1) { + EVP_PKEY_free(ecdh_key); + return SSH_ERROR; + } + pubkey = OSSL_PARAM_locate_const(params, OSSL_PKEY_PARAM_PUB_KEY); + if (pubkey == NULL) { + OSSL_PARAM_free(params); + EVP_PKEY_free(ecdh_key); + return SSH_ERROR; + } + + rc = OSSL_PARAM_get_octet_string_ptr(pubkey, &pubkey_ptr, &len); + if (rc != 1) { + OSSL_PARAM_free(params); + EVP_PKEY_free(ecdh_key); + return SSH_ERROR; + } +#endif /* OPENSSL_VERSION_NUMBER */ q_s_string = ssh_string_new(len); if (q_s_string == NULL) { +/* TODO Change to new API when the OpenSSL will support export of uncompressed EC keys + * https://github.com/openssl/openssl/pull/16624 + * #if OPENSSL_VERSION_NUMBER < 0x30000000L + */ +#if 1 EC_KEY_free(ecdh_key); BN_CTX_free(ctx); +#else + EVP_PKEY_free(ecdh_key); +#endif /* OPENSSL_VERSION_NUMBER */ goto error; } +/* TODO Change to new API when the OpenSSL will support export of uncompressed EC keys + * https://github.com/openssl/openssl/pull/16624 + * #if OPENSSL_VERSION_NUMBER < 0x30000000L + */ +#if 1 EC_POINT_point2oct(group, ecdh_pubkey, POINT_CONVERSION_UNCOMPRESSED, @@ -266,6 +553,15 @@ SSH_PACKET_CALLBACK(ssh_packet_server_ecdh_init){ len, ctx); BN_CTX_free(ctx); +#else + if (memcpy(ssh_string_data(q_s_string), pubkey_ptr, len)) { + OSSL_PARAM_free(params); + EVP_PKEY_free(ecdh_key); + return SSH_ERROR; + } + + OSSL_PARAM_free(params); +#endif /* OPENSSL_VERSION_NUMBER */ session->next_crypto->ecdh_privkey = ecdh_key; session->next_crypto->ecdh_server_pubkey = q_s_string; diff --git a/src/pki_crypto.c b/src/pki_crypto.c index ffee471b..859d05da 100644 --- a/src/pki_crypto.c +++ b/src/pki_crypto.c @@ -29,14 +29,20 @@ #include "config.h" #include "libssh/priv.h" +#include "libcrypto-compat.h" #include -#include -#include -#include #include +#include +#include +#if OPENSSL_VERSION_NUMBER < 0x30000000L +#include #include -#include "libcrypto-compat.h" +#else +#include +#include +#include +#endif /* OPENSSL_VERSION_NUMBER */ #ifdef HAVE_OPENSSL_EC_H #include @@ -82,6 +88,11 @@ static int pem_get_password(char *buf, int size, int rwflag, void *userdata) { } #ifdef HAVE_OPENSSL_ECC +/* TODO Change to new API when the OpenSSL will support export of uncompressed EC keys + * https://github.com/openssl/openssl/pull/16624 + * #if OPENSSL_VERSION_NUMBER < 0x30000000L + */ +#if 1 static int pki_key_ecdsa_to_nid(EC_KEY *k) { const EC_GROUP *g = EC_KEY_get0_group(k); @@ -94,8 +105,42 @@ static int pki_key_ecdsa_to_nid(EC_KEY *k) return -1; } +#else +static int pki_key_ecdsa_to_nid(EVP_PKEY *k) +{ + char gname[25] = { 0 }; + int nid, rc; + rc = EVP_PKEY_get_utf8_string_param(k, "group", gname, 25, NULL); + if (rc != 1) + return -1; + + if (strcmp(gname, NISTP256) == 0 + || strcmp(gname, "secp256r1") == 0 + || strcmp(gname, "prime256v1") == 0) { + nid = NID_X9_62_prime256v1; + } else if (strcmp(gname, NISTP384) == 0 + || strcmp(gname, "secp384r1") == 0) { + nid = NID_secp384r1; + } else if (strcmp(gname, NISTP521) == 0 + || strcmp(gname, "secp521r1") == 0) { + nid = NID_secp521r1; + } else + return -1; + + return nid; +} +#endif /* OPENSSL_VERSION_NUMBER */ + +/* TODO Change to new API when the OpenSSL will support export of uncompressed EC keys + * https://github.com/openssl/openssl/pull/16624 + * #if OPENSSL_VERSION_NUMBER < 0x30000000L + */ +#if 1 static enum ssh_keytypes_e pki_key_ecdsa_to_key_type(EC_KEY *k) +#else +static enum ssh_keytypes_e pki_key_ecdsa_to_key_type(EVP_PKEY *k) +#endif /* OPENSSL_VERSION_NUMBER */ { int nid; @@ -158,6 +203,11 @@ int pki_key_ecdsa_nid_from_name(const char *name) return -1; } +/* TODO Change to new API when the OpenSSL will support export of uncompressed EC keys + * https://github.com/openssl/openssl/pull/16624 + * #if OPENSSL_VERSION_NUMBER < 0x30000000L + */ +#if 1 static ssh_string make_ecpoint_string(const EC_GROUP *g, const EC_POINT *p) { @@ -192,17 +242,39 @@ static ssh_string make_ecpoint_string(const EC_GROUP *g, return s; } +#endif /* OPENSSL_VERSION_NUMBER */ int pki_privkey_build_ecdsa(ssh_key key, int nid, ssh_string e, ssh_string exp) { +/* TODO Change to new API when the OpenSSL will support export of uncompressed EC keys + * https://github.com/openssl/openssl/pull/16624 + * #if OPENSSL_VERSION_NUMBER < 0x30000000L + */ +#if 1 EC_POINT *p = NULL; const EC_GROUP *g = NULL; int ok; BIGNUM *bexp = NULL; +#else + int rc; + const BIGNUM *expb; + const char *group_name = OSSL_EC_curve_nid2name(nid); + OSSL_PARAM_BLD *param_bld = NULL; + + if (group_name == NULL) { + return -1; + } + expb = ssh_make_string_bn(exp); +#endif /* OPENSSL_VERSION_NUMBER */ key->ecdsa_nid = nid; key->type_c = pki_key_ecdsa_nid_to_name(nid); +/* TODO Change to new API when the OpenSSL will support export of uncompressed EC keys + * https://github.com/openssl/openssl/pull/16624 + * #if OPENSSL_VERSION_NUMBER < 0x30000000L + */ +#if 1 key->ecdsa = EC_KEY_new_by_curve_name(key->ecdsa_nid); if (key->ecdsa == NULL) { return -1; @@ -246,17 +318,57 @@ int pki_privkey_build_ecdsa(ssh_key key, int nid, ssh_string e, ssh_string exp) } return 0; +#else + param_bld = OSSL_PARAM_BLD_new(); + if (param_bld == NULL) + goto err; + + rc = OSSL_PARAM_BLD_push_utf8_string(param_bld, OSSL_PKEY_PARAM_GROUP_NAME, + group_name, strlen(group_name)); + if (rc != 1) + goto err; + rc = OSSL_PARAM_BLD_push_octet_string(param_bld, OSSL_PKEY_PARAM_PUB_KEY, + ssh_string_data(e), ssh_string_len(e)); + if (rc != 1) + goto err; + rc = OSSL_PARAM_BLD_push_BN(param_bld, OSSL_PKEY_PARAM_PRIV_KEY, expb); + if (rc != 1) + goto err; + + rc = evp_build_pkey("EC", param_bld, &(key->key), EVP_PKEY_KEYPAIR); + OSSL_PARAM_BLD_free(param_bld); + + return rc; +err: + OSSL_PARAM_BLD_free(param_bld); + return -1; +#endif /* OPENSSL_VERSION_NUMBER */ } int pki_pubkey_build_ecdsa(ssh_key key, int nid, ssh_string e) { +/* TODO Change to new API when the OpenSSL will support export of uncompressed EC keys + * https://github.com/openssl/openssl/pull/16624 + * #if OPENSSL_VERSION_NUMBER < 0x30000000L + */ +#if 1 EC_POINT *p = NULL; const EC_GROUP *g = NULL; int ok; +#else + int rc; + const char *group_name = OSSL_EC_curve_nid2name(nid); + OSSL_PARAM_BLD *param_bld; +#endif /* OPENSSL_VERSION_NUMBER */ key->ecdsa_nid = nid; key->type_c = pki_key_ecdsa_nid_to_name(nid); +/* TODO Change to new API when the OpenSSL will support export of uncompressed EC keys + * https://github.com/openssl/openssl/pull/16624 + * #if OPENSSL_VERSION_NUMBER < 0x30000000L + */ + #if 1 key->ecdsa = EC_KEY_new_by_curve_name(key->ecdsa_nid); if (key->ecdsa == NULL) { return -1; @@ -287,8 +399,30 @@ int pki_pubkey_build_ecdsa(ssh_key key, int nid, ssh_string e) } return 0; +#else + param_bld = OSSL_PARAM_BLD_new(); + if (param_bld == NULL) + goto err; + + rc = OSSL_PARAM_BLD_push_utf8_string(param_bld, OSSL_PKEY_PARAM_GROUP_NAME, + group_name, strlen(group_name)); + if (rc != 1) + goto err; + rc = OSSL_PARAM_BLD_push_octet_string(param_bld, OSSL_PKEY_PARAM_PUB_KEY, + ssh_string_data(e), ssh_string_len(e)); + if (rc != 1) + goto err; + + rc = evp_build_pkey("EC", param_bld, &(key->key), EVP_PKEY_PUBLIC_KEY); + OSSL_PARAM_BLD_free(param_bld); + + return rc; +err: + OSSL_PARAM_BLD_free(param_bld); + return -1; +#endif /* OPENSSL_VERSION_NUMBER */ } -#endif +#endif /* HAVE_OPENSSL_ECC */ ssh_key pki_key_dup(const ssh_key key, int demote) { @@ -301,8 +435,10 @@ ssh_key pki_key_dup(const ssh_key key, int demote) } #ifdef WITH_PKCS11_URI +#if OPENSSL_VERSION_NUMBER < 0x30000000L new->key = key->key; -#endif +#endif /* OPENSSL_VERSION_NUMBER */ +#endif /* WITH_PKCS11_URI */ new->type = key->type; new->type_c = key->type_c; @@ -314,6 +450,7 @@ ssh_key pki_key_dup(const ssh_key key, int demote) switch (key->type) { case SSH_KEYTYPE_DSS: { +#if OPENSSL_VERSION_NUMBER < 0x30000000L const BIGNUM *p = NULL, *q = NULL, *g = NULL, *pub_key = NULL, *priv_key = NULL; BIGNUM *np, *nq, *ng, *npub_key, *npriv_key; @@ -373,11 +510,17 @@ ssh_key pki_key_dup(const ssh_key key, int demote) goto fail; } } - +#else + rc = evp_dup_dsa_pkey(key, new, demote); + if (rc != SSH_OK) { + goto fail; + } +#endif /* OPENSSL_VERSION_NUMBER */ break; } case SSH_KEYTYPE_RSA: case SSH_KEYTYPE_RSA1: { +#if OPENSSL_VERSION_NUMBER < 0x30000000L const BIGNUM *n = NULL, *e = NULL, *d = NULL; BIGNUM *nn, *ne, *nd; new->rsa = RSA_new(); @@ -473,7 +616,12 @@ ssh_key pki_key_dup(const ssh_key key, int demote) } } } - +#else + rc = evp_dup_rsa_pkey(key, new, demote); + if (rc != SSH_OK) { + goto fail; + } +#endif /* OPENSSL_VERSION_NUMBER */ break; } case SSH_KEYTYPE_ECDSA_P256: @@ -481,7 +629,11 @@ ssh_key pki_key_dup(const ssh_key key, int demote) case SSH_KEYTYPE_ECDSA_P521: #ifdef HAVE_OPENSSL_ECC new->ecdsa_nid = key->ecdsa_nid; - +/* TODO Change to new API when the OpenSSL will support export of uncompressed EC keys + * https://github.com/openssl/openssl/pull/16624 + * #if OPENSSL_VERSION_NUMBER < 0x30000000L + */ +#if 1 /* privkey -> pubkey */ if (demote && ssh_key_is_private(key)) { const EC_POINT *p; @@ -504,8 +656,14 @@ ssh_key pki_key_dup(const ssh_key key, int demote) } else { new->ecdsa = EC_KEY_dup(key->ecdsa); } +#else + rc = evp_dup_ecdsa_pkey(key, new, demote); + if (rc != SSH_OK) { + goto fail; + } +#endif /* OPENSSL_VERSION_NUMBER */ break; -#endif +#endif /* HAVE_OPENSSL_ECC */ case SSH_KEYTYPE_ED25519: rc = pki_ed25519_key_dup(new, key); if (rc != SSH_OK) { @@ -525,24 +683,57 @@ fail: } int pki_key_generate_rsa(ssh_key key, int parameter){ - BIGNUM *e; int rc; +#if OPENSSL_VERSION_NUMBER < 0x30000000L + BIGNUM *e; +#else + OSSL_PARAM params[3]; + EVP_PKEY_CTX *pctx = EVP_PKEY_CTX_new_from_name(NULL, "RSA", NULL); + unsigned e = 65537; +#endif /* OPENSSL_VERSION_NUMBER */ - e = BN_new(); - key->rsa = RSA_new(); +#if OPENSSL_VERSION_NUMBER < 0x30000000L + e = BN_new(); + key->rsa = RSA_new(); - BN_set_word(e, 65537); - rc = RSA_generate_key_ex(key->rsa, parameter, e, NULL); + BN_set_word(e, 65537); + rc = RSA_generate_key_ex(key->rsa, parameter, e, NULL); - BN_free(e); + BN_free(e); - if (rc <= 0 || key->rsa == NULL) - return SSH_ERROR; + if (rc <= 0 || key->rsa == NULL) + return SSH_ERROR; +#else + key->key = NULL; + + rc = EVP_PKEY_keygen_init(pctx); + if (rc != 1) { + EVP_PKEY_CTX_free(pctx); + return SSH_ERROR; + } + + params[0] = OSSL_PARAM_construct_int("bits", ¶meter); + params[1] = OSSL_PARAM_construct_uint("e", &e); + params[2] = OSSL_PARAM_construct_end(); + rc = EVP_PKEY_CTX_set_params(pctx, params); + if (rc != 1) { + EVP_PKEY_CTX_free(pctx); + return SSH_ERROR; + } + + rc = EVP_PKEY_generate(pctx, &(key->key)); + + EVP_PKEY_CTX_free(pctx); + + if (rc != 1 || key->key == NULL) + return SSH_ERROR; +#endif /* OPENSSL_VERSION_NUMBER */ return SSH_OK; } int pki_key_generate_dss(ssh_key key, int parameter){ int rc; +#if OPENSSL_VERSION_NUMBER < 0x30000000L key->dsa = DSA_new(); if (key->dsa == NULL) { return SSH_ERROR; @@ -560,42 +751,145 @@ int pki_key_generate_dss(ssh_key key, int parameter){ return SSH_ERROR; } rc = DSA_generate_key(key->dsa); - if (rc != 1){ + if (rc != 1) { DSA_free(key->dsa); key->dsa=NULL; return SSH_ERROR; } +#else + OSSL_PARAM params[3]; + EVP_PKEY *param_key = NULL; + EVP_PKEY_CTX *pctx = NULL; + EVP_PKEY_CTX *gctx = NULL; + int qbits = parameter < 2048 ? 160 : 256; + + key->key = EVP_PKEY_new(); + if (key->key == NULL) { + return SSH_ERROR; + } + pctx = EVP_PKEY_CTX_new_from_name(NULL, "DSA", NULL); + if (pctx == NULL) { + return SSH_ERROR; + } + + rc = EVP_PKEY_paramgen_init(pctx); + if (rc != 1) { + EVP_PKEY_CTX_free(pctx); + return SSH_ERROR; + } + params[0] = OSSL_PARAM_construct_int("pbits", ¶meter); + params[1] = OSSL_PARAM_construct_int("qbits", &qbits); + params[2] = OSSL_PARAM_construct_end(); + rc = EVP_PKEY_CTX_set_params(pctx, params); + if (rc != 1) { + EVP_PKEY_CTX_free(pctx); + return SSH_ERROR; + } + /* generating the domain parameters */ + rc = EVP_PKEY_generate(pctx, ¶m_key); + if (rc != 1) { + EVP_PKEY_CTX_free(pctx); + EVP_PKEY_free(param_key); + return SSH_ERROR; + } + EVP_PKEY_CTX_free(pctx); + + gctx = EVP_PKEY_CTX_new_from_pkey(NULL, param_key, NULL); + if (gctx == NULL) { + EVP_PKEY_free(param_key); + return SSH_ERROR; + } + + EVP_PKEY_free(param_key); + rc = EVP_PKEY_keygen_init(gctx); + if (rc != 1) { + EVP_PKEY_CTX_free(gctx); + return SSH_ERROR; + } + /* generating the key from the domain parameters */ + rc = EVP_PKEY_generate(gctx, &key->key); + if (rc != 1) { + EVP_PKEY_free(key->key); + key->key = NULL; + EVP_PKEY_CTX_free(gctx); + return SSH_ERROR; + } + EVP_PKEY_CTX_free(gctx); +#endif /* OPENSSL_VERSION_NUMBER */ return SSH_OK; } #ifdef HAVE_OPENSSL_ECC int pki_key_generate_ecdsa(ssh_key key, int parameter) { +/* TODO Change to new API when the OpenSSL will support export of uncompressed EC keys + * https://github.com/openssl/openssl/pull/16624 + * #if OPENSSL_VERSION_NUMBER < 0x30000000L + */ +#if 1 int ok; - +#else + const char *group_name = NULL; +#endif /* OPENSSL_VERSION_NUMBER */ switch (parameter) { + case 256: + key->ecdsa_nid = NID_X9_62_prime256v1; + key->type = SSH_KEYTYPE_ECDSA_P256; +/* TODO Change to new API when the OpenSSL will support export of uncompressed EC keys + * https://github.com/openssl/openssl/pull/16624 + * #if OPENSSL_VERSION_NUMBER >= 0x30000000L + */ +#if 0 + group_name = NISTP256; +#endif /* OPENSSL_VERSION_NUMBER */ + break; case 384: key->ecdsa_nid = NID_secp384r1; key->type = SSH_KEYTYPE_ECDSA_P384; +/* TODO Change to new API when the OpenSSL will support export of uncompressed EC keys + * https://github.com/openssl/openssl/pull/16624 + * #if OPENSSL_VERSION_NUMBER >= 0x30000000L + */ +#if 0 + group_name = NISTP384; +#endif /* OPENSSL_VERSION_NUMBER */ break; case 521: key->ecdsa_nid = NID_secp521r1; key->type = SSH_KEYTYPE_ECDSA_P521; - break; - case 256: - key->ecdsa_nid = NID_X9_62_prime256v1; - key->type = SSH_KEYTYPE_ECDSA_P256; +/* TODO Change to new API when the OpenSSL will support export of uncompressed EC keys + * https://github.com/openssl/openssl/pull/16624 + * #if OPENSSL_VERSION_NUMBER >= 0x30000000L + */ +#if 0 + group_name = NISTP521; +#endif /* OPENSSL_VERSION_NUMBER */ break; default: SSH_LOG(SSH_LOG_WARN, "Invalid parameter %d for ECDSA key " "generation", parameter); return SSH_ERROR; } - +/* TODO Change to new API when the OpenSSL will support export of uncompressed EC keys + * https://github.com/openssl/openssl/pull/16624 + * #if OPENSSL_VERSION_NUMBER < 0x30000000L + */ +#if 1 key->ecdsa = EC_KEY_new_by_curve_name(key->ecdsa_nid); if (key->ecdsa == NULL) { return SSH_ERROR; } +#else + key->key = EVP_EC_gen(group_name); + if (key->key == NULL) { + return SSH_ERROR; + } +#endif /* OPENSSL_VERSION_NUMBER */ +/* TODO Change to new API when the OpenSSL will support export of uncompressed EC keys + * https://github.com/openssl/openssl/pull/16624 + * #if OPENSSL_VERSION_NUMBER < 0x30000000L + */ +#if 1 ok = EC_KEY_generate_key(key->ecdsa); if (!ok) { EC_KEY_free(key->ecdsa); @@ -603,78 +897,108 @@ int pki_key_generate_ecdsa(ssh_key key, int parameter) { } EC_KEY_set_asn1_flag(key->ecdsa, OPENSSL_EC_NAMED_CURVE); - +#endif /* OPENSSL_VERSION_NUMBER */ return SSH_OK; } -#endif +#endif /* HAVE_OPENSSL_ECC */ +/* With OpenSSL 3.0 and higher the parameter 'what' + * is ignored and the comparision is done by OpenSSL + */ int pki_key_compare(const ssh_key k1, const ssh_key k2, enum ssh_keycmp_e what) { - switch (k1->type) { - case SSH_KEYTYPE_DSS: { - const BIGNUM *p1, *p2, *q1, *q2, *g1, *g2, - *pub_key1, *pub_key2, *priv_key1, *priv_key2; - if (DSA_size(k1->dsa) != DSA_size(k2->dsa)) { - return 1; - } - DSA_get0_pqg(k1->dsa, &p1, &q1, &g1); - DSA_get0_pqg(k2->dsa, &p2, &q2, &g2); - if (bignum_cmp(p1, p2) != 0) { - return 1; - } - if (bignum_cmp(q1, q2) != 0) { - return 1; - } - if (bignum_cmp(g1, g2) != 0) { - return 1; - } - DSA_get0_key(k1->dsa, &pub_key1, &priv_key1); - DSA_get0_key(k2->dsa, &pub_key2, &priv_key2); - if (bignum_cmp(pub_key1, pub_key2) != 0) { - return 1; - } +#if OPENSSL_VERSION_NUMBER >= 0x30000000L + int rc; + (void) what; +#endif /* OPENSSL_VERSION_NUMBER */ - if (what == SSH_KEY_CMP_PRIVATE) { - if (bignum_cmp(priv_key1, priv_key2) != 0) { + switch (k1->type) { + case SSH_KEYTYPE_DSS: +#if OPENSSL_VERSION_NUMBER < 0x30000000L + { + const BIGNUM *p1, *p2, *q1, *q2, *g1, *g2, + *pub_key1, *pub_key2, *priv_key1, *priv_key2; + if (DSA_size(k1->dsa) != DSA_size(k2->dsa)) { return 1; } - } - break; - } - case SSH_KEYTYPE_RSA: - case SSH_KEYTYPE_RSA1: { - const BIGNUM *e1, *e2, *n1, *n2, *p1, *p2, *q1, *q2; - if (RSA_size(k1->rsa) != RSA_size(k2->rsa)) { - return 1; - } - RSA_get0_key(k1->rsa, &n1, &e1, NULL); - RSA_get0_key(k2->rsa, &n2, &e2, NULL); - if (bignum_cmp(e1, e2) != 0) { - return 1; - } - if (bignum_cmp(n1, n2) != 0) { - return 1; - } - - if (what == SSH_KEY_CMP_PRIVATE) { - RSA_get0_factors(k1->rsa, &p1, &q1); - RSA_get0_factors(k2->rsa, &p2, &q2); + DSA_get0_pqg(k1->dsa, &p1, &q1, &g1); + DSA_get0_pqg(k2->dsa, &p2, &q2, &g2); if (bignum_cmp(p1, p2) != 0) { return 1; } - if (bignum_cmp(q1, q2) != 0) { return 1; } + if (bignum_cmp(g1, g2) != 0) { + return 1; + } + DSA_get0_key(k1->dsa, &pub_key1, &priv_key1); + DSA_get0_key(k2->dsa, &pub_key2, &priv_key2); + if (bignum_cmp(pub_key1, pub_key2) != 0) { + return 1; + } + + if (what == SSH_KEY_CMP_PRIVATE) { + if (bignum_cmp(priv_key1, priv_key2) != 0) { + return 1; + } + } + break; + } +#endif /* OPENSSL_VERSION_NUMBER */ + case SSH_KEYTYPE_RSA: + case SSH_KEYTYPE_RSA1: +#if OPENSSL_VERSION_NUMBER < 0x30000000L + { + const BIGNUM *e1, *e2, *n1, *n2, *p1, *p2, *q1, *q2; + if (RSA_size(k1->rsa) != RSA_size(k2->rsa)) { + return 1; + } + RSA_get0_key(k1->rsa, &n1, &e1, NULL); + RSA_get0_key(k2->rsa, &n2, &e2, NULL); + if (bignum_cmp(e1, e2) != 0) { + return 1; + } + if (bignum_cmp(n1, n2) != 0) { + return 1; + } + + if (what == SSH_KEY_CMP_PRIVATE) { + RSA_get0_factors(k1->rsa, &p1, &q1); + RSA_get0_factors(k2->rsa, &p2, &q2); + if (bignum_cmp(p1, p2) != 0) { + return 1; + } + + if (bignum_cmp(q1, q2) != 0) { + return 1; + } + } + break; + } +#endif /* OPENSSL_VERSION_NUMBER */ +/* TODO Change to new API when the OpenSSL will support export of uncompressed EC keys + * https://github.com/openssl/openssl/pull/16624 + * delete this part of #if because it gets done below EC + */ +#if OPENSSL_VERSION_NUMBER >= 0x30000000L + rc = EVP_PKEY_eq(k1->key, k2->key); + if (rc != 1) { + return 1; } break; - } +#endif /* OPENSSL_VERSION_NUMBER */ case SSH_KEYTYPE_ECDSA_P256: case SSH_KEYTYPE_ECDSA_P384: case SSH_KEYTYPE_ECDSA_P521: case SSH_KEYTYPE_SK_ECDSA: +/* TODO Change to new API when the OpenSSL will support export of uncompressed EC keys + * https://github.com/openssl/openssl/pull/16624 + * #if OPENSSL_VERSION_NUMBER < 0x30000000L + */ +#if 1 #ifdef HAVE_OPENSSL_ECC { const EC_POINT *p1 = EC_KEY_get0_public_key(k1->ecdsa); @@ -700,10 +1024,21 @@ int pki_key_compare(const ssh_key k1, return 1; } } - break; } -#endif +#endif /* HAVE_OPENSSL_ECC */ +#endif /* OPENSSL_VERSION_NUMBER */ +/* TODO Change to new API when the OpenSSL will support export of uncompressed EC keys + * https://github.com/openssl/openssl/pull/16624 + * else + */ +#if 0 + rc = EVP_PKEY_eq(k1->key, k2->key); + if (rc != 1) { + return 1; + } + break; +#endif /* OPENSSL_VERSION_NUMBER */ case SSH_KEYTYPE_ED25519: case SSH_KEYTYPE_SK_ED25519: /* ed25519 keys handled globaly */ @@ -711,7 +1046,6 @@ int pki_key_compare(const ssh_key k1, default: return 1; } - return 0; } @@ -733,6 +1067,7 @@ ssh_string pki_private_key_to_pem(const ssh_key key, switch (key->type) { case SSH_KEYTYPE_DSS: +#if OPENSSL_VERSION_NUMBER < 0x30000000L pkey = EVP_PKEY_new(); if (pkey == NULL) { goto err; @@ -740,8 +1075,10 @@ ssh_string pki_private_key_to_pem(const ssh_key key, rc = EVP_PKEY_set1_DSA(pkey, key->dsa); break; +#endif /* OPENSSL_VERSION_NUMBER */ case SSH_KEYTYPE_RSA: case SSH_KEYTYPE_RSA1: +#if OPENSSL_VERSION_NUMBER < 0x30000000L pkey = EVP_PKEY_new(); if (pkey == NULL) { goto err; @@ -749,10 +1086,31 @@ ssh_string pki_private_key_to_pem(const ssh_key key, rc = EVP_PKEY_set1_RSA(pkey, key->rsa); break; -#ifdef HAVE_ECC +#endif /* OPENSSL_VERSION_NUMBER */ +/* TODO Change to new API when the OpenSSL will support export of uncompressed EC keys + * https://github.com/openssl/openssl/pull/16624 + * Delete this part, because it is done below HAVE_ECC + */ +#if OPENSSL_VERSION_NUMBER >= 0x30000000L + pkey = key->key; + if (pkey == NULL) { + goto err; + } + + /* Mark the operation as successful as for the other key types */ + rc = 1; + + break; +#endif /* OPENSSL_VERSION_NUMBER */ case SSH_KEYTYPE_ECDSA_P256: case SSH_KEYTYPE_ECDSA_P384: case SSH_KEYTYPE_ECDSA_P521: +#ifdef HAVE_ECC +/* TODO Change to new API when the OpenSSL will support export of uncompressed EC keys + * https://github.com/openssl/openssl/pull/16624 + * #if OPENSSL_VERSION_NUMBER < 0x30000000L + */ +#if 1 pkey = EVP_PKEY_new(); if (pkey == NULL) { goto err; @@ -760,7 +1118,23 @@ ssh_string pki_private_key_to_pem(const ssh_key key, rc = EVP_PKEY_set1_EC_KEY(pkey, key->ecdsa); break; -#endif +#endif /* OPENSSL_VERSION_NUMBER */ +#endif /* HAVE_ECC */ +/* TODO Change to new API when the OpenSSL will support export of uncompressed EC keys + * https://github.com/openssl/openssl/pull/16624 + * #if OPENSSL_VERSION_NUMBER >= 0x30000000L + */ +#if 0 + pkey = key->key; + if (pkey == NULL) { + goto err; + } + + /* Mark the operation as successful as for the other key types */ + rc = 1; + + break; +#endif /* OPENSSL_VERSION_NUMBER */ case SSH_KEYTYPE_ED25519: #ifdef HAVE_OPENSSL_ED25519 /* In OpenSSL, the input is the private key seed only, which means @@ -782,7 +1156,7 @@ ssh_string pki_private_key_to_pem(const ssh_key key, #else SSH_LOG(SSH_LOG_WARN, "PEM output not supported for key type ssh-ed25519"); goto err; -#endif +#endif /* HAVE_OPENSSL_ED25519 */ case SSH_KEYTYPE_DSS_CERT01: case SSH_KEYTYPE_RSA_CERT01: case SSH_KEYTYPE_ECDSA_P256_CERT01: @@ -818,7 +1192,9 @@ ssh_string pki_private_key_to_pem(const ssh_key key, NULL, /* auth_fn */ (void*) passphrase); } - EVP_PKEY_free(pkey); + if (pkey != key->key) { + EVP_PKEY_free(pkey); + } pkey = NULL; if (rc != 1) { @@ -854,20 +1230,22 @@ ssh_key pki_private_key_from_base64(const char *b64_key, void *auth_data) { BIO *mem = NULL; +#if OPENSSL_VERSION_NUMBER < 0x30000000L DSA *dsa = NULL; RSA *rsa = NULL; -#ifdef HAVE_OPENSSL_ED25519 - uint8_t *ed25519 = NULL; -#else - ed25519_privkey *ed25519 = NULL; -#endif - ssh_key key = NULL; - enum ssh_keytypes_e type = SSH_KEYTYPE_UNKNOWN; +#endif /* OPENSSL_VERSION_NUMBER */ #ifdef HAVE_OPENSSL_ECC EC_KEY *ecdsa = NULL; #else void *ecdsa = NULL; -#endif +#endif /* HAVE_OPENSSL_ECC */ +#ifdef HAVE_OPENSSL_ED25519 + uint8_t *ed25519 = NULL; +#else + ed25519_privkey *ed25519 = NULL; +#endif /* HAVE_OPENSSL_ED25519 */ + ssh_key key = NULL; + enum ssh_keytypes_e type = SSH_KEYTYPE_UNKNOWN; EVP_PKEY *pkey = NULL; mem = BIO_new_mem_buf((void*)b64_key, -1); @@ -895,6 +1273,7 @@ ssh_key pki_private_key_from_base64(const char *b64_key, } switch (EVP_PKEY_base_id(pkey)) { case EVP_PKEY_DSA: +#if OPENSSL_VERSION_NUMBER < 0x30000000L dsa = EVP_PKEY_get1_DSA(pkey); if (dsa == NULL) { SSH_LOG(SSH_LOG_WARN, @@ -902,9 +1281,11 @@ ssh_key pki_private_key_from_base64(const char *b64_key, ERR_error_string(ERR_get_error(),NULL)); goto fail; } +#endif type = SSH_KEYTYPE_DSS; break; case EVP_PKEY_RSA: +#if OPENSSL_VERSION_NUMBER < 0x30000000L rsa = EVP_PKEY_get1_RSA(pkey); if (rsa == NULL) { SSH_LOG(SSH_LOG_WARN, @@ -912,10 +1293,16 @@ ssh_key pki_private_key_from_base64(const char *b64_key, ERR_error_string(ERR_get_error(),NULL)); goto fail; } +#endif /* OPENSSL_VERSION_NUMBER */ type = SSH_KEYTYPE_RSA; break; case EVP_PKEY_EC: #ifdef HAVE_OPENSSL_ECC +/* TODO Change to new API when the OpenSSL will support export of uncompressed EC keys + * https://github.com/openssl/openssl/pull/16624 + * #if OPENSSL_VERSION_NUMBER < 0x30000000L + */ +#if 1 ecdsa = EVP_PKEY_get1_EC_KEY(pkey); if (ecdsa == NULL) { SSH_LOG(SSH_LOG_WARN, @@ -923,17 +1310,34 @@ ssh_key pki_private_key_from_base64(const char *b64_key, ERR_error_string(ERR_get_error(), NULL)); goto fail; } +#endif /* OPENSSL_VERSION_NUMBER */ /* pki_privatekey_type_from_string always returns P256 for ECDSA * keys, so we need to figure out the correct type here */ +/* TODO Change to new API when the OpenSSL will support export of uncompressed EC keys + * https://github.com/openssl/openssl/pull/16624 + * #if OPENSSL_VERSION_NUMBER < 0x30000000L + */ +#if 1 type = pki_key_ecdsa_to_key_type(ecdsa); +#else + type = pki_key_ecdsa_to_key_type(pkey); +#endif /* OPENSSL_VERSION_NUMBER */ if (type == SSH_KEYTYPE_UNKNOWN) { SSH_LOG(SSH_LOG_WARN, "Invalid private key."); goto fail; } +/* TODO Change to new API when the OpenSSL will support export of uncompressed EC keys + * https://github.com/openssl/openssl/pull/16624 + * Remove these three lines + */ + /* the EVP_PKEY is not saved to the ssh_key struct */ + EVP_PKEY_free(pkey); + pkey = NULL; + break; -#endif +#endif /* HAVE_OPENSSL_ECC */ #ifdef HAVE_OPENSSL_ED25519 case EVP_PKEY_ED25519: { @@ -968,16 +1372,25 @@ ssh_key pki_private_key_from_base64(const char *b64_key, goto fail; } type = SSH_KEYTYPE_ED25519; + + /* the EVP_PKEY is not saved to the ssh_key struct */ +#if OPENSSL_VERSION_NUMBER >= 0x30000000L + EVP_PKEY_free(pkey); + pkey = NULL; +#endif /* OPENSSL_VERSION_NUMBER */ } break; -#endif +#endif /* HAVE_OPENSSL_ED25519 */ default: - EVP_PKEY_free(pkey); SSH_LOG(SSH_LOG_WARN, "Unknown or invalid private key type %d", EVP_PKEY_base_id(pkey)); + EVP_PKEY_free(pkey); return NULL; } + /* at later version the pkey is saved to ssh_key struct */ +#if OPENSSL_VERSION_NUMBER < 0x30000000L EVP_PKEY_free(pkey); +#endif /* OPENSSL_VERSION_NUMBER */ key = ssh_key_new(); if (key == NULL) { @@ -987,22 +1400,44 @@ ssh_key pki_private_key_from_base64(const char *b64_key, key->type = type; key->type_c = ssh_key_type_to_char(type); key->flags = SSH_KEY_FLAG_PRIVATE | SSH_KEY_FLAG_PUBLIC; +#if OPENSSL_VERSION_NUMBER < 0x30000000L key->dsa = dsa; key->rsa = rsa; +#else + key->key = pkey; +#endif /* OPENSSL_VERSION_NUMBER */ +/* TODO Change to new API when the OpenSSL will support export of uncompressed EC keys + * https://github.com/openssl/openssl/pull/16624 + * Move key->ecdsa line into the #if above this + */ key->ecdsa = ecdsa; key->ed25519_privkey = ed25519; #ifdef HAVE_OPENSSL_ECC if (is_ecdsa_key_type(key->type)) { +/* TODO Change to new API when the OpenSSL will support export of uncompressed EC keys + * https://github.com/openssl/openssl/pull/16624 + * #if OPENSSL_VERSION_NUMBER < 0x30000000L + */ +#if 1 key->ecdsa_nid = pki_key_ecdsa_to_nid(key->ecdsa); +#else + key->ecdsa_nid = pki_key_ecdsa_to_nid(key->key); +#endif /* OPENSSL_VERSION_NUMBER */ } -#endif +#endif /* HAVE_OPENSSL_ECC */ return key; fail: EVP_PKEY_free(pkey); ssh_key_free(key); +#if OPENSSL_VERSION_NUMBER < 0x30000000L DSA_free(dsa); RSA_free(rsa); +#endif /* OPENSSL_VERSION_NUMBER */ +/* TODO Change to new API when the OpenSSL will support export of uncompressed EC keys + * https://github.com/openssl/openssl/pull/16624 + * Move HAVE_OPENSSL_ECC #ifdef inside the #if above + */ #ifdef HAVE_OPENSSL_ECC EC_KEY_free(ecdsa); #endif @@ -1020,8 +1455,14 @@ int pki_privkey_build_dss(ssh_key key, ssh_string privkey) { int rc; +#if OPENSSL_VERSION_NUMBER < 0x30000000L BIGNUM *bp, *bq, *bg, *bpub_key, *bpriv_key; +#else + const BIGNUM *pb, *qb, *gb, *pubb, *privb; + OSSL_PARAM_BLD *param_bld; +#endif /* OPENSSL_VERSION_NUMBER */ +#if OPENSSL_VERSION_NUMBER < 0x30000000L key->dsa = DSA_new(); if (key->dsa == NULL) { return SSH_ERROR; @@ -1053,6 +1494,41 @@ int pki_privkey_build_dss(ssh_key key, fail: DSA_free(key->dsa); return SSH_ERROR; +#else + param_bld = OSSL_PARAM_BLD_new(); + if (param_bld == NULL) + goto err; + + pb = ssh_make_string_bn(p); + qb = ssh_make_string_bn(q); + gb = ssh_make_string_bn(g); + pubb = ssh_make_string_bn(pubkey); + privb = ssh_make_string_bn(privkey); + + rc = OSSL_PARAM_BLD_push_BN(param_bld, OSSL_PKEY_PARAM_FFC_P, pb); + if (rc != 1) + goto err; + rc = OSSL_PARAM_BLD_push_BN(param_bld, OSSL_PKEY_PARAM_FFC_Q, qb); + if (rc != 1) + goto err; + rc = OSSL_PARAM_BLD_push_BN(param_bld, OSSL_PKEY_PARAM_FFC_G, gb); + if (rc != 1) + goto err; + rc = OSSL_PARAM_BLD_push_BN(param_bld, OSSL_PKEY_PARAM_PUB_KEY, pubb); + if (rc != 1) + goto err; + rc = OSSL_PARAM_BLD_push_BN(param_bld, OSSL_PKEY_PARAM_PRIV_KEY, privb); + if (rc != 1) + goto err; + + rc = evp_build_pkey("DSA", param_bld, &(key->key), EVP_PKEY_KEYPAIR); + OSSL_PARAM_BLD_free(param_bld); + + return rc; +err: + OSSL_PARAM_BLD_free(param_bld); + return -1; +#endif /* OPENSSL_VERSION_NUMBER */ } int pki_pubkey_build_dss(ssh_key key, @@ -1061,8 +1537,14 @@ int pki_pubkey_build_dss(ssh_key key, ssh_string g, ssh_string pubkey) { int rc; +#if OPENSSL_VERSION_NUMBER < 0x30000000L BIGNUM *bp = NULL, *bq = NULL, *bg = NULL, *bpub_key = NULL; +#else + const BIGNUM *pb, *qb, *gb, *pubb; + OSSL_PARAM_BLD *param_bld; +#endif /* OPENSSL_VERSION_NUMBER */ +#if OPENSSL_VERSION_NUMBER < 0x30000000L key->dsa = DSA_new(); if (key->dsa == NULL) { return SSH_ERROR; @@ -1093,6 +1575,37 @@ int pki_pubkey_build_dss(ssh_key key, fail: DSA_free(key->dsa); return SSH_ERROR; +#else + param_bld = OSSL_PARAM_BLD_new(); + if (param_bld == NULL) + goto err; + + pb = ssh_make_string_bn(p); + qb = ssh_make_string_bn(q); + gb = ssh_make_string_bn(g); + pubb = ssh_make_string_bn(pubkey); + + rc = OSSL_PARAM_BLD_push_BN(param_bld, OSSL_PKEY_PARAM_FFC_P, pb); + if (rc != 1) + goto err; + rc = OSSL_PARAM_BLD_push_BN(param_bld, OSSL_PKEY_PARAM_FFC_Q, qb); + if (rc != 1) + goto err; + rc = OSSL_PARAM_BLD_push_BN(param_bld, OSSL_PKEY_PARAM_FFC_G, gb); + if (rc != 1) + goto err; + rc = OSSL_PARAM_BLD_push_BN(param_bld, OSSL_PKEY_PARAM_PUB_KEY, pubb); + if (rc != 1) + goto err; + + rc = evp_build_pkey("DSA", param_bld, &(key->key), EVP_PKEY_PUBLIC_KEY); + OSSL_PARAM_BLD_free(param_bld); + + return rc; +err: + OSSL_PARAM_BLD_free(param_bld); + return -1; +#endif /* OPENSSL_VERSION_NUMBER */ } int pki_privkey_build_rsa(ssh_key key, @@ -1104,8 +1617,14 @@ int pki_privkey_build_rsa(ssh_key key, ssh_string q) { int rc; +#if OPENSSL_VERSION_NUMBER < 0x30000000L BIGNUM *be, *bn, *bd/*, *biqmp*/, *bp, *bq; +#else + const BIGNUM *nb, *eb, *db, *pb, *qb; + OSSL_PARAM_BLD *param_bld; +#endif /* OPENSSL_VERSION_NUMBER */ +#if OPENSSL_VERSION_NUMBER < 0x30000000L key->rsa = RSA_new(); if (key->rsa == NULL) { return SSH_ERROR; @@ -1145,14 +1664,57 @@ int pki_privkey_build_rsa(ssh_key key, fail: RSA_free(key->rsa); return SSH_ERROR; +#else + param_bld = OSSL_PARAM_BLD_new(); + if (param_bld == NULL) + goto err; + + nb = ssh_make_string_bn(n); + eb = ssh_make_string_bn(e); + db = ssh_make_string_bn(d); + pb = ssh_make_string_bn(p); + qb = ssh_make_string_bn(q); + + rc = OSSL_PARAM_BLD_push_BN(param_bld, OSSL_PKEY_PARAM_RSA_N, nb); + if (rc != 1) + goto err; + rc = OSSL_PARAM_BLD_push_BN(param_bld, OSSL_PKEY_PARAM_RSA_E, eb); + if (rc != 1) + goto err; + rc = OSSL_PARAM_BLD_push_BN(param_bld, OSSL_PKEY_PARAM_RSA_D, db); + if (rc != 1) + goto err; + + rc = evp_build_pkey("RSA", param_bld, &(key->key), EVP_PKEY_KEYPAIR); + OSSL_PARAM_BLD_free(param_bld); + + rc = EVP_PKEY_set_bn_param(key->key, OSSL_PKEY_PARAM_RSA_FACTOR1, pb); + if (rc != 1) + goto err; + + rc = EVP_PKEY_set_bn_param(key->key, OSSL_PKEY_PARAM_RSA_FACTOR2, qb); + if (rc != 1) + goto err; + + return rc; +err: + OSSL_PARAM_BLD_free(param_bld); + return -1; +#endif /* OPENSSL_VERSION_NUMBER */ } int pki_pubkey_build_rsa(ssh_key key, ssh_string e, ssh_string n) { int rc; +#if OPENSSL_VERSION_NUMBER < 0x30000000L BIGNUM *be = NULL, *bn = NULL; +#else + const BIGNUM *eb, *nb; + OSSL_PARAM_BLD *param_bld; +#endif /* OPENSSL_VERSION_NUMBER */ +#if OPENSSL_VERSION_NUMBER < 0x30000000L key->rsa = RSA_new(); if (key->rsa == NULL) { return SSH_ERROR; @@ -1174,6 +1736,29 @@ int pki_pubkey_build_rsa(ssh_key key, fail: RSA_free(key->rsa); return SSH_ERROR; +#else + nb = ssh_make_string_bn(n); + eb = ssh_make_string_bn(e); + + param_bld = OSSL_PARAM_BLD_new(); + if (param_bld == NULL) + goto err; + + rc = OSSL_PARAM_BLD_push_BN(param_bld, OSSL_PKEY_PARAM_RSA_N, nb); + if (rc != 1) + goto err; + rc = OSSL_PARAM_BLD_push_BN(param_bld, OSSL_PKEY_PARAM_RSA_E, eb); + if (rc != 1) + goto err; + + rc = evp_build_pkey("RSA", param_bld, &(key->key), EVP_PKEY_PUBLIC_KEY); + OSSL_PARAM_BLD_free(param_bld); + + return rc; +err: + OSSL_PARAM_BLD_free(param_bld); + return -1; +#endif /* OPENSSL_VERSION_NUMBER */ } ssh_string pki_publickey_to_blob(const ssh_key key) @@ -1187,6 +1772,11 @@ ssh_string pki_publickey_to_blob(const ssh_key key) ssh_string g = NULL; ssh_string q = NULL; int rc; +#if OPENSSL_VERSION_NUMBER >= 0x30000000L + BIGNUM *bp = NULL, *bq = NULL, *bg = NULL, *bpub_key = NULL, + *bn = NULL, *be = NULL; + OSSL_PARAM *params = NULL; +#endif /* OPENSSL_VERSION_NUMBER */ buffer = ssh_buffer_new(); if (buffer == NULL) { @@ -1217,8 +1807,53 @@ ssh_string pki_publickey_to_blob(const ssh_key key) switch (key->type) { case SSH_KEYTYPE_DSS: { +#if OPENSSL_VERSION_NUMBER < 0x30000000L const BIGNUM *bp, *bq, *bg, *bpub_key; DSA_get0_pqg(key->dsa, &bp, &bq, &bg); + DSA_get0_key(key->dsa, &bpub_key, NULL); +#else + const OSSL_PARAM *out_param = NULL; + rc = EVP_PKEY_todata(key->key, EVP_PKEY_PUBLIC_KEY, ¶ms); + if (rc != 1) { + goto fail; + } + out_param = OSSL_PARAM_locate_const(params, OSSL_PKEY_PARAM_FFC_P); + if (out_param == NULL) { + SSH_LOG(SSH_LOG_WARN, "DSA: No param P has been found"); + goto fail; + } + rc = OSSL_PARAM_get_BN(out_param, &bp); + if (rc != 1) { + goto fail; + } + out_param = OSSL_PARAM_locate_const(params, OSSL_PKEY_PARAM_FFC_Q); + if (out_param == NULL) { + SSH_LOG(SSH_LOG_WARN, "DSA: No param Q has been found"); + goto fail; + } + rc = OSSL_PARAM_get_BN(out_param, &bq); + if (rc != 1) { + goto fail; + } + out_param = OSSL_PARAM_locate_const(params, OSSL_PKEY_PARAM_FFC_G); + if (out_param == NULL) { + SSH_LOG(SSH_LOG_WARN, "DSA: No param G has been found"); + goto fail; + } + rc = OSSL_PARAM_get_BN(out_param, &bg); + if (rc != 1) { + goto fail; + } + out_param = OSSL_PARAM_locate_const(params, OSSL_PKEY_PARAM_PUB_KEY); + if (out_param == NULL) { + SSH_LOG(SSH_LOG_WARN, "DSA: No param PUB_KEY has been found"); + goto fail; + } + rc = OSSL_PARAM_get_BN(out_param, &bpub_key); + if (rc != 1) { + goto fail; + } +#endif /* OPENSSL_VERSION_NUMBER */ p = ssh_make_bignum_string((BIGNUM *)bp); if (p == NULL) { goto fail; @@ -1234,7 +1869,6 @@ ssh_string pki_publickey_to_blob(const ssh_key key) goto fail; } - DSA_get0_key(key->dsa, &bpub_key, NULL); n = ssh_make_bignum_string((BIGNUM *)bpub_key); if (n == NULL) { goto fail; @@ -1265,13 +1899,46 @@ ssh_string pki_publickey_to_blob(const ssh_key key) ssh_string_burn(n); SSH_STRING_FREE(n); n = NULL; +#if OPENSSL_VERSION_NUMBER >= 0x30000000L + bignum_safe_free(bp); + bignum_safe_free(bq); + bignum_safe_free(bg); + bignum_safe_free(bpub_key); + OSSL_PARAM_free(params); +#endif /* OPENSSL_VERSION_NUMBER */ break; } case SSH_KEYTYPE_RSA: case SSH_KEYTYPE_RSA1: { +#if OPENSSL_VERSION_NUMBER < 0x30000000L const BIGNUM *be, *bn; RSA_get0_key(key->rsa, &bn, &be, NULL); +#else + const OSSL_PARAM *out_param = NULL; + rc = EVP_PKEY_todata(key->key, EVP_PKEY_PUBLIC_KEY, ¶ms); + if (rc != 1) { + goto fail; + } + out_param = OSSL_PARAM_locate_const(params, OSSL_PKEY_PARAM_RSA_E); + if (out_param == NULL) { + SSH_LOG(SSH_LOG_WARN, "RSA: No param E has been found"); + goto fail; + } + rc = OSSL_PARAM_get_BN(out_param, &be); + if (rc != 1) { + goto fail; + } + out_param = OSSL_PARAM_locate_const(params, OSSL_PKEY_PARAM_RSA_N); + if (out_param == NULL) { + SSH_LOG(SSH_LOG_WARN, "RSA: No param N has been found"); + goto fail; + } + rc = OSSL_PARAM_get_BN(out_param, &bn); + if (rc != 1) { + goto fail; + } +#endif /* OPENSSL_VERSION_NUMBER */ e = ssh_make_bignum_string((BIGNUM *)be); if (e == NULL) { goto fail; @@ -1295,7 +1962,11 @@ ssh_string pki_publickey_to_blob(const ssh_key key) ssh_string_burn(n); SSH_STRING_FREE(n); n = NULL; - +#if OPENSSL_VERSION_NUMBER >= 0x30000000L + bignum_safe_free(bn); + bignum_safe_free(be); + OSSL_PARAM_free(params); +#endif /* OPENSSL_VERSION_NUMBER */ break; } case SSH_KEYTYPE_ED25519: @@ -1314,19 +1985,35 @@ ssh_string pki_publickey_to_blob(const ssh_key key) case SSH_KEYTYPE_ECDSA_P521: case SSH_KEYTYPE_SK_ECDSA: #ifdef HAVE_OPENSSL_ECC - type_s = ssh_string_from_char(pki_key_ecdsa_nid_to_char(key->ecdsa_nid)); - if (type_s == NULL) { - SSH_BUFFER_FREE(buffer); - return NULL; - } + { +/* TODO Change to new API when the OpenSSL will support export of uncompressed EC keys + * https://github.com/openssl/openssl/pull/16624 + * #if OPENSSL_VERSION_NUMBER >= 0x30000000L + */ +#if 0 + const void *pubkey; + size_t pubkey_len; + OSSL_PARAM *params, *locate_param; +#endif /* OPENSSL_VERSION_NUMBER */ - rc = ssh_buffer_add_ssh_string(buffer, type_s); - SSH_STRING_FREE(type_s); - if (rc < 0) { - SSH_BUFFER_FREE(buffer); - return NULL; - } + type_s = ssh_string_from_char(pki_key_ecdsa_nid_to_char(key->ecdsa_nid)); + if (type_s == NULL) { + SSH_BUFFER_FREE(buffer); + return NULL; + } + rc = ssh_buffer_add_ssh_string(buffer, type_s); + SSH_STRING_FREE(type_s); + if (rc < 0) { + SSH_BUFFER_FREE(buffer); + return NULL; + } + +/* TODO Change to new API when the OpenSSL will support export of uncompressed EC keys + * https://github.com/openssl/openssl/pull/16624 + * #if OPENSSL_VERSION_NUMBER < 0x30000000L + */ +#if 1 #ifdef WITH_PKCS11_URI if (ssh_key_is_private(key) && !EC_KEY_get0_public_key(key->ecdsa)) { SSH_LOG(SSH_LOG_INFO, "It is mandatory to have separate public" @@ -1334,30 +2021,92 @@ ssh_string pki_publickey_to_blob(const ssh_key key) " ECDSA public keys cannot be derived from their private keys."); goto fail; } -#endif - e = make_ecpoint_string(EC_KEY_get0_group(key->ecdsa), - EC_KEY_get0_public_key(key->ecdsa)); - if (e == NULL) { - SSH_BUFFER_FREE(buffer); - return NULL; - } +#endif /* WITH_PKCS11_URI */ + e = make_ecpoint_string(EC_KEY_get0_group(key->ecdsa), + EC_KEY_get0_public_key(key->ecdsa)); +#else + rc = ssh_buffer_add_ssh_string(buffer, type_s); + SSH_STRING_FREE(type_s); + if (rc < 0) { + SSH_BUFFER_FREE(buffer); + return NULL; + } - rc = ssh_buffer_add_ssh_string(buffer, e); - if (rc < 0) { - goto fail; - } + rc = EVP_PKEY_todata(key->key, EVP_PKEY_PUBLIC_KEY, ¶ms); + if (rc < 0) { + OSSL_PARAM_free(params); + goto fail; + } - ssh_string_burn(e); - SSH_STRING_FREE(e); - e = NULL; + locate_param = OSSL_PARAM_locate(params, OSSL_PKEY_PARAM_PUB_KEY); +#ifdef WITH_PKCS11_URI + if (ssh_key_is_private(key) && !locate_param) { + SSH_LOG(SSH_LOG_INFO, "It is mandatory to have separate" + " public ECDSA key objects in the PKCS #11 device." + " Unlike RSA, ECDSA public keys cannot be derived" + " from their private keys."); + goto fail; + } +#endif /* WITH_PKCS11_URI */ + + rc = OSSL_PARAM_get_octet_string_ptr(locate_param, &pubkey, &pubkey_len); + if (rc != 1) { + OSSL_PARAM_free(params); + OSSL_PARAM_free(locate_param); + goto fail; + } + + e = ssh_string_new(pubkey_len); +#endif /* OPENSSL_VERSION_NUMBER */ + if (e == NULL) { + SSH_BUFFER_FREE(buffer); + return NULL; + } + +/* TODO Change to new API when the OpenSSL will support export of uncompressed EC keys + * https://github.com/openssl/openssl/pull/16624 + * #if OPENSSL_VERSION_NUMBER >= 0x30000000L + */ +#if 0 + if (memcpy(ssh_string_data(e), pubkey, pubkey_len) == NULL) { + OSSL_PARAM_free(params); + OSSL_PARAM_free(locate_param); + goto fail; + } +#endif /* OPENSSL_VERSION_NUMBER */ + rc = ssh_buffer_add_ssh_string(buffer, e); + if (rc < 0) { +/* TODO Change to new API when the OpenSSL will support export of uncompressed EC keys + * https://github.com/openssl/openssl/pull/16624 + * #if OPENSSL_VERSION_NUMBER >= 0x30000000L + */ +#if 0 + OSSL_PARAM_free(params); + OSSL_PARAM_free(locate_param); +#endif /* OPENSSL_VERSION_NUMBER */ + goto fail; + } + + ssh_string_burn(e); + SSH_STRING_FREE(e); + e = NULL; +/* TODO Change to new API when the OpenSSL will support export of uncompressed EC keys + * https://github.com/openssl/openssl/pull/16624 + * #if OPENSSL_VERSION_NUMBER >= 0x30000000L + */ +#if 0 + OSSL_PARAM_free(params); + OSSL_PARAM_free(locate_param); +#endif /* OPENSSL_VERSION_NUMBER */ if (key->type == SSH_KEYTYPE_SK_ECDSA && ssh_buffer_add_ssh_string(buffer, key->sk_application) < 0) { goto fail; } - break; -#endif + break; + } +#endif /* HAVE_OPENSSL_ECC */ case SSH_KEYTYPE_UNKNOWN: default: goto fail; @@ -1390,6 +2139,15 @@ fail: SSH_STRING_FREE(q); ssh_string_burn(n); SSH_STRING_FREE(n); +#if OPENSSL_VERSION_NUMBER >= 0x30000000L + bignum_safe_free(bp); + bignum_safe_free(bq); + bignum_safe_free(bg); + bignum_safe_free(bpub_key); + bignum_safe_free(bn); + bignum_safe_free(be); + OSSL_PARAM_free(params); +#endif /* OPENSSL_VERSION_NUMBER */ return NULL; } @@ -1588,7 +2346,7 @@ ssh_string pki_signature_to_blob(const ssh_signature sig) #ifdef HAVE_OPENSSL_ECC sig_blob = pki_ecdsa_signature_to_blob(sig); break; -#endif +#endif /* HAVE_OPENSSL_ECC */ default: case SSH_KEYTYPE_UNKNOWN: SSH_LOG(SSH_LOG_WARN, "Unknown signature key type: %s", sig->type_c); @@ -1610,12 +2368,21 @@ static int pki_signature_from_rsa_blob(const ssh_key pubkey, size_t rsalen = 0; size_t len = ssh_string_len(sig_blob); +#if OPENSSL_VERSION_NUMBER < 0x30000000L if (pubkey->rsa == NULL) { SSH_LOG(SSH_LOG_WARN, "Pubkey RSA field NULL"); goto errout; } rsalen = RSA_size(pubkey->rsa); +#else + if (EVP_PKEY_get_base_id(pubkey->key) != EVP_PKEY_RSA) { + SSH_LOG(SSH_LOG_WARN, "Key has no RSA pubkey"); + goto errout; + } + + rsalen = EVP_PKEY_size(pubkey->key); +#endif /* OPENSSL_VERSION_NUMBER */ if (len > rsalen) { SSH_LOG(SSH_LOG_WARN, "Signature is too big: %lu > %lu", @@ -1627,7 +2394,7 @@ static int pki_signature_from_rsa_blob(const ssh_key pubkey, #ifdef DEBUG_CRYPTO SSH_LOG(SSH_LOG_DEBUG, "RSA signature len: %lu", (unsigned long)len); ssh_log_hexdump("RSA signature", ssh_string_data(sig_blob), len); -#endif +#endif /* DEBUG_CRYPTO */ if (len == rsalen) { sig->raw_sig = ssh_string_copy(sig_blob); @@ -1675,7 +2442,7 @@ static int pki_signature_from_dsa_blob(UNUSED_PARAM(const ssh_key pubkey), BIGNUM *pr = NULL, *ps = NULL; ssh_string r; - ssh_string s; + ssh_string s = NULL; size_t len; @@ -1698,7 +2465,7 @@ static int pki_signature_from_dsa_blob(UNUSED_PARAM(const ssh_key pubkey), #ifdef DEBUG_CRYPTO ssh_log_hexdump("r", ssh_string_data(sig_blob), 20); ssh_log_hexdump("s", (unsigned char *)ssh_string_data(sig_blob) + 20, 20); -#endif +#endif /* DEBUG_CRYPTO */ r = ssh_string_new(20); if (r == NULL) { @@ -2049,6 +2816,7 @@ static EVP_PKEY *pki_key_to_pkey(ssh_key key) switch(key->type) { case SSH_KEYTYPE_DSS: case SSH_KEYTYPE_DSS_CERT01: +#if OPENSSL_VERSION_NUMBER < 0x30000000L if (key->dsa == NULL) { SSH_LOG(SSH_LOG_TRACE, "NULL key->dsa"); goto error; @@ -2061,9 +2829,11 @@ static EVP_PKEY *pki_key_to_pkey(ssh_key key) EVP_PKEY_set1_DSA(pkey, key->dsa); break; +#endif /* OPENSSL_VERSION_NUMBER */ case SSH_KEYTYPE_RSA: case SSH_KEYTYPE_RSA1: case SSH_KEYTYPE_RSA_CERT01: +#if OPENSSL_VERSION_NUMBER < 0x30000000L if (key->rsa == NULL) { SSH_LOG(SSH_LOG_TRACE, "NULL key->rsa"); goto error; @@ -2076,6 +2846,22 @@ static EVP_PKEY *pki_key_to_pkey(ssh_key key) EVP_PKEY_set1_RSA(pkey, key->rsa); break; +/* TODO Change to new API when the OpenSSL will support export of uncompressed EC keys + * https://github.com/openssl/openssl/pull/16624 + * Remove this #else part from here + */ +#else + if (key->key == NULL) { + SSH_LOG(SSH_LOG_TRACE, "NULL key->key"); + goto error; + } + pkey = EVP_PKEY_dup(key->key); + if (pkey == NULL) { + SSH_LOG(SSH_LOG_TRACE, "Out of memory"); + return NULL; + } + break; +#endif /* OPENSSL_VERSION_NUMBER */ case SSH_KEYTYPE_ECDSA_P256: case SSH_KEYTYPE_ECDSA_P384: case SSH_KEYTYPE_ECDSA_P521: @@ -2085,6 +2871,11 @@ static EVP_PKEY *pki_key_to_pkey(ssh_key key) case SSH_KEYTYPE_SK_ECDSA: case SSH_KEYTYPE_SK_ECDSA_CERT01: # if defined(HAVE_OPENSSL_ECC) +/* TODO Change to new API when the OpenSSL will support export of uncompressed EC keys + * https://github.com/openssl/openssl/pull/16624 + * #if OPENSSL_VERSION_NUMBER < 0x30000000L + */ +#if 1 if (key->ecdsa == NULL) { SSH_LOG(SSH_LOG_TRACE, "NULL key->ecdsa"); goto error; @@ -2097,7 +2888,24 @@ static EVP_PKEY *pki_key_to_pkey(ssh_key key) EVP_PKEY_set1_EC_KEY(pkey, key->ecdsa); break; +#endif /* OPENSSL_VERSION_NUMBER */ # endif +/* TODO Change to new API when the OpenSSL will support export of uncompressed EC keys + * https://github.com/openssl/openssl/pull/16624 + * #if OPENSSL_VERSION_NUMBER >= 0x30000000L + */ +#if 0 + if (key->key == NULL) { + SSH_LOG(SSH_LOG_TRACE, "NULL key->key"); + goto error; + } + pkey = EVP_PKEY_dup(key->key); + if (pkey == NULL) { + SSH_LOG(SSH_LOG_TRACE, "Out of memory"); + return NULL; + } + break; +#endif /* OPENSSL_VERSION_NUMBER */ case SSH_KEYTYPE_ED25519: case SSH_KEYTYPE_ED25519_CERT01: case SSH_KEYTYPE_SK_ED25519: @@ -2217,7 +3025,7 @@ ssh_signature pki_sign_data(const ssh_key privkey, } /* Create the context */ - ctx = EVP_MD_CTX_create(); + ctx = EVP_MD_CTX_new(); if (ctx == NULL) { SSH_LOG(SSH_LOG_TRACE, "Out of memory"); goto out; @@ -2294,7 +3102,7 @@ out: explicit_bzero(raw_sig_data, raw_sig_len); } SAFE_FREE(raw_sig_data); - if (pkey != NULL) { + if (pkey != NULL && !(privkey->flags & SSH_KEY_FLAG_PKCS11_URI)) { EVP_PKEY_free(pkey); } return sig; @@ -2378,7 +3186,7 @@ int pki_verify_data_signature(ssh_signature signature, } /* Create the context */ - ctx = EVP_MD_CTX_create(); + ctx = EVP_MD_CTX_new(); if (ctx == NULL) { SSH_LOG(SSH_LOG_TRACE, "Failed to create EVP_MD_CTX: %s", @@ -2422,7 +3230,7 @@ out: if (ctx != NULL) { EVP_MD_CTX_free(ctx); } - if (pkey != NULL) { + if (pkey != NULL && !(pubkey->flags & SSH_KEY_FLAG_PKCS11_URI)) { EVP_PKEY_free(pkey); } return rc; @@ -2605,14 +3413,20 @@ int pki_uri_import(const char *uri_name, { ENGINE *engine = NULL; EVP_PKEY *pkey = NULL; +#if OPENSSL_VERSION_NUMBER < 0x30000000L RSA *rsa = NULL; - ssh_key key = NULL; - enum ssh_keytypes_e type = SSH_KEYTYPE_UNKNOWN; +#endif +/* TODO Change to new API when the OpenSSL will support export of uncompressed EC keys + * https://github.com/openssl/openssl/pull/16624 + * Move HAVE_OPENSSL_ECC #ifdef into #if above + */ #ifdef HAVE_OPENSSL_ECC EC_KEY *ecdsa = NULL; #else void *ecdsa = NULL; #endif + ssh_key key = NULL; + enum ssh_keytypes_e type = SSH_KEYTYPE_UNKNOWN; int ok; ENGINE_load_builtin_engines(); @@ -2669,6 +3483,7 @@ int pki_uri_import(const char *uri_name, switch (EVP_PKEY_base_id(pkey)) { case EVP_PKEY_RSA: +#if OPENSSL_VERSION_NUMBER < 0x30000000L rsa = EVP_PKEY_get1_RSA(pkey); if (rsa == NULL) { SSH_LOG(SSH_LOG_WARN, @@ -2676,10 +3491,16 @@ int pki_uri_import(const char *uri_name, ERR_error_string(ERR_get_error(),NULL)); goto fail; } +#endif /* OPENSSL_VERSION_NUMBER */ type = SSH_KEYTYPE_RSA; break; case EVP_PKEY_EC: #ifdef HAVE_OPENSSL_ECC +/* TODO Change to new API when the OpenSSL will support export of uncompressed EC keys + * https://github.com/openssl/openssl/pull/16624 + * #if OPENSSL_VERSION_NUMBER < 0x30000000L + */ +#if 1 ecdsa = EVP_PKEY_get1_EC_KEY(pkey); if (ecdsa == NULL) { SSH_LOG(SSH_LOG_WARN, @@ -2691,6 +3512,9 @@ int pki_uri_import(const char *uri_name, /* pki_privatekey_type_from_string always returns P256 for ECDSA * keys, so we need to figure out the correct type here */ type = pki_key_ecdsa_to_key_type(ecdsa); +#else + type = pki_key_ecdsa_to_key_type(pkey); +#endif /* OPENSSL_VERSION_NUMBER */ if (type == SSH_KEYTYPE_UNKNOWN) { SSH_LOG(SSH_LOG_WARN, "Invalid pub key."); goto fail; @@ -2712,11 +3536,25 @@ int pki_uri_import(const char *uri_name, } else { key->flags = SSH_KEY_FLAG_PUBLIC | SSH_KEY_FLAG_PKCS11_URI; } +#if OPENSSL_VERSION_NUMBER < 0x30000000L key->rsa = rsa; +#endif +/* TODO Change to new API when the OpenSSL will support export of uncompressed EC keys + * https://github.com/openssl/openssl/pull/16624 + * Move line key->ecdsa into #if above + */ key->ecdsa = ecdsa; #ifdef HAVE_OPENSSL_ECC if (is_ecdsa_key_type(key->type)) { +/* TODO Change to new API when the OpenSSL will support export of uncompressed EC keys + * https://github.com/openssl/openssl/pull/16624 + * #if OPENSSL_VERSION_NUMBER < 0x30000000L + */ +#if 1 key->ecdsa_nid = pki_key_ecdsa_to_nid(key->ecdsa); +#else + key->ecdsa_nid = pki_key_ecdsa_to_nid(key->key); +#endif /* OPENSSL_VERSION_NUMBER */ } #endif @@ -2731,7 +3569,13 @@ fail: ENGINE_free(engine); EVP_PKEY_free(pkey); ssh_key_free(key); +#if OPENSSL_VERSION_NUMBER < 0x30000000L RSA_free(rsa); +#endif +/* TODO Change to new API when the OpenSSL will support export of uncompressed EC keys + * https://github.com/openssl/openssl/pull/16624 + * Move HAVE_OPENSSL_ECC #ifdef into #if above + */ #ifdef HAVE_OPENSSL_ECC EC_KEY_free(ecdsa); #endif