diff options
Diffstat (limited to 'src/pki_crypto.c')
-rw-r--r-- | src/pki_crypto.c | 2162 |
1 files changed, 1190 insertions, 972 deletions
diff --git a/src/pki_crypto.c b/src/pki_crypto.c index 08409209..f4ce8bdf 100644 --- a/src/pki_crypto.c +++ b/src/pki_crypto.c @@ -29,14 +29,24 @@ #include "config.h" #include "libssh/priv.h" +#include "libcrypto-compat.h" #include <openssl/pem.h> -#include <openssl/dsa.h> -#include <openssl/err.h> -#include <openssl/engine.h> #include <openssl/evp.h> +#include <openssl/engine.h> +#include <openssl/err.h> +#if OPENSSL_VERSION_NUMBER < 0x30000000L +#include <openssl/dsa.h> #include <openssl/rsa.h> -#include "libcrypto-compat.h" +#else +#include <openssl/params.h> +#include <openssl/core_names.h> +#include <openssl/param_build.h> +#if defined(WITH_PKCS11_URI) && defined(WITH_PKCS11_PROVIDER) +#include <openssl/store.h> +#include <openssl/provider.h> +#endif +#endif /* OPENSSL_VERSION_NUMBER */ #ifdef HAVE_OPENSSL_EC_H #include <openssl/ec.h> @@ -81,12 +91,24 @@ static int pem_get_password(char *buf, int size, int rwflag, void *userdata) { return 0; } +void pki_key_clean(ssh_key key) +{ + if (key == NULL) + return; + EVP_PKEY_free(key->key); + key->key = NULL; +} + #ifdef HAVE_OPENSSL_ECC +#if OPENSSL_VERSION_NUMBER < 0x30000000L static int pki_key_ecdsa_to_nid(EC_KEY *k) { const EC_GROUP *g = EC_KEY_get0_group(k); int nid; + if (g == NULL) { + return -1; + } nid = EC_GROUP_get_curve_name(g); if (nid) { return nid; @@ -94,8 +116,30 @@ 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 rc; + + rc = EVP_PKEY_get_utf8_string_param(k, + OSSL_PKEY_PARAM_GROUP_NAME, + gname, + 25, + NULL); + if (rc != 1) { + return -1; + } + + return pki_key_ecgroup_name_to_nid(gname); +} +#endif /* OPENSSL_VERSION_NUMBER */ +#if OPENSSL_VERSION_NUMBER < 0x30000000L 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,114 +202,157 @@ int pki_key_ecdsa_nid_from_name(const char *name) return -1; } -static ssh_string make_ecpoint_string(const EC_GROUP *g, - const EC_POINT *p) +int pki_privkey_build_ecdsa(ssh_key key, int nid, ssh_string e, ssh_string exp) { - ssh_string s; - size_t len; - - len = EC_POINT_point2oct(g, - p, - POINT_CONVERSION_UNCOMPRESSED, - NULL, - 0, - NULL); - if (len == 0) { - return NULL; - } + int rc = 0; + BIGNUM *bexp = NULL; - s = ssh_string_new(len); - if (s == NULL) { - return NULL; - } +#if OPENSSL_VERSION_NUMBER < 0x30000000L + EC_POINT *p = NULL; + const EC_GROUP *g = NULL; + EC_KEY *ecdsa = NULL; +#else + const char *group_name = OSSL_EC_curve_nid2name(nid); + OSSL_PARAM_BLD *param_bld = NULL; - len = EC_POINT_point2oct(g, - p, - POINT_CONVERSION_UNCOMPRESSED, - ssh_string_data(s), - ssh_string_len(s), - NULL); - if (len != ssh_string_len(s)) { - SSH_STRING_FREE(s); - return NULL; + if (group_name == NULL) { + return -1; } +#endif /* OPENSSL_VERSION_NUMBER */ - return s; -} - -int pki_privkey_build_ecdsa(ssh_key key, int nid, ssh_string e, ssh_string exp) -{ - EC_POINT *p = NULL; - const EC_GROUP *g = NULL; - int ok; - BIGNUM *bexp = NULL; + bexp = ssh_make_string_bn(exp); + if (bexp == NULL) { + return -1; + } key->ecdsa_nid = nid; key->type_c = pki_key_ecdsa_nid_to_name(nid); - key->ecdsa = EC_KEY_new_by_curve_name(key->ecdsa_nid); - if (key->ecdsa == NULL) { - return -1; +#if OPENSSL_VERSION_NUMBER < 0x30000000L + ecdsa = EC_KEY_new_by_curve_name(key->ecdsa_nid); + if (ecdsa == NULL) { + rc = -1; + goto cleanup; } - g = EC_KEY_get0_group(key->ecdsa); + g = EC_KEY_get0_group(ecdsa); p = EC_POINT_new(g); if (p == NULL) { - return -1; + rc = -1; + goto cleanup; } - ok = EC_POINT_oct2point(g, + rc = EC_POINT_oct2point(g, p, ssh_string_data(e), ssh_string_len(e), NULL); - if (!ok) { - EC_POINT_free(p); - return -1; + if (rc != 1) { + rc = -1; + goto cleanup; } /* EC_KEY_set_public_key duplicates p */ - ok = EC_KEY_set_public_key(key->ecdsa, p); - EC_POINT_free(p); - if (!ok) { - return -1; + rc = EC_KEY_set_public_key(ecdsa, p); + if (rc != 1) { + rc = -1; + goto cleanup; } - bexp = ssh_make_string_bn(exp); - if (bexp == NULL) { - EC_KEY_free(key->ecdsa); - return -1; - } /* EC_KEY_set_private_key duplicates exp */ - ok = EC_KEY_set_private_key(key->ecdsa, bexp); + rc = EC_KEY_set_private_key(ecdsa, bexp); + if (rc != 1) { + rc = -1; + goto cleanup; + } + + key->key = EVP_PKEY_new(); + if (key->key == NULL) { + rc = -1; + goto cleanup; + } + + /* ecdsa will be freed when the EVP_PKEY key->key is freed */ + rc = EVP_PKEY_assign_EC_KEY(key->key, ecdsa); + if (rc != 1) { + rc = -1; + goto cleanup; + } + /* ssh_key is now the owner of this memory */ + ecdsa = NULL; + + /* set rc to 0 if everything went well */ + rc = 0; + +cleanup: + EC_KEY_free(ecdsa); + EC_POINT_free(p); BN_free(bexp); - if (!ok) { - EC_KEY_free(key->ecdsa); - return -1; + return rc; +#else + param_bld = OSSL_PARAM_BLD_new(); + if (param_bld == NULL){ + rc = -1; + goto cleanup; } - return 0; + rc = OSSL_PARAM_BLD_push_utf8_string(param_bld, OSSL_PKEY_PARAM_GROUP_NAME, + group_name, strlen(group_name)); + if (rc != 1) { + rc = -1; + goto cleanup; + } + + 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) { + rc = -1; + goto cleanup; + } + + rc = OSSL_PARAM_BLD_push_BN(param_bld, OSSL_PKEY_PARAM_PRIV_KEY, bexp); + if (rc != 1) { + rc = -1; + goto cleanup; + } + + rc = evp_build_pkey("EC", param_bld, &(key->key), EVP_PKEY_KEYPAIR); + +cleanup: + OSSL_PARAM_BLD_free(param_bld); + BN_free(bexp); + return rc; +#endif /* OPENSSL_VERSION_NUMBER */ } int pki_pubkey_build_ecdsa(ssh_key key, int nid, ssh_string e) { + int rc; +#if OPENSSL_VERSION_NUMBER < 0x30000000L EC_POINT *p = NULL; const EC_GROUP *g = NULL; + EC_KEY *ecdsa = NULL; int ok; +#else + 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); - key->ecdsa = EC_KEY_new_by_curve_name(key->ecdsa_nid); - if (key->ecdsa == NULL) { +#if OPENSSL_VERSION_NUMBER < 0x30000000L + ecdsa = EC_KEY_new_by_curve_name(key->ecdsa_nid); + if (ecdsa == NULL) { return -1; } - g = EC_KEY_get0_group(key->ecdsa); + g = EC_KEY_get0_group(ecdsa); p = EC_POINT_new(g); if (p == NULL) { + EC_KEY_free(ecdsa); return -1; } @@ -275,24 +362,60 @@ int pki_pubkey_build_ecdsa(ssh_key key, int nid, ssh_string e) ssh_string_len(e), NULL); if (!ok) { + EC_KEY_free(ecdsa); EC_POINT_free(p); return -1; } /* EC_KEY_set_public_key duplicates p */ - ok = EC_KEY_set_public_key(key->ecdsa, p); + ok = EC_KEY_set_public_key(ecdsa, p); EC_POINT_free(p); if (!ok) { + EC_KEY_free(ecdsa); + return -1; + } + + key->key = EVP_PKEY_new(); + if (key->key == NULL) { + EC_KEY_free(ecdsa); + return -1; + } + + rc = EVP_PKEY_assign_EC_KEY(key->key, ecdsa); + if (rc != 1) { + EC_KEY_free(ecdsa); return -1; } 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) { - ssh_key new; + ssh_key new = NULL; int rc; new = ssh_key_new(); @@ -300,10 +423,6 @@ ssh_key pki_key_dup(const ssh_key key, int demote) return NULL; } -#ifdef WITH_PKCS11_URI - new->key = key->key; -#endif - new->type = key->type; new->type_c = key->type_c; if (demote) { @@ -313,75 +432,28 @@ ssh_key pki_key_dup(const ssh_key key, int demote) } switch (key->type) { - case SSH_KEYTYPE_DSS: { - const BIGNUM *p = NULL, *q = NULL, *g = NULL, - *pub_key = NULL, *priv_key = NULL; - BIGNUM *np, *nq, *ng, *npub_key, *npriv_key; - new->dsa = DSA_new(); - if (new->dsa == NULL) { - goto fail; - } - - /* - * p = public prime number - * q = public 160-bit subprime, q | p-1 - * g = public generator of subgroup - * pub_key = public key y = g^x - * priv_key = private key x - */ - DSA_get0_pqg(key->dsa, &p, &q, &g); - np = BN_dup(p); - nq = BN_dup(q); - ng = BN_dup(g); - if (np == NULL || nq == NULL || ng == NULL) { - BN_free(np); - BN_free(nq); - BN_free(ng); - goto fail; - } - - /* Memory management of np, nq and ng is transferred to DSA object */ - rc = DSA_set0_pqg(new->dsa, np, nq, ng); - if (rc == 0) { - BN_free(np); - BN_free(nq); - BN_free(ng); - goto fail; - } - - DSA_get0_key(key->dsa, &pub_key, &priv_key); - npub_key = BN_dup(pub_key); - if (npub_key == NULL) { - goto fail; - } - - /* Memory management of npubkey is transferred to DSA object */ - rc = DSA_set0_key(new->dsa, npub_key, NULL); - if (rc == 0) { - goto fail; - } - - if (!demote && (key->flags & SSH_KEY_FLAG_PRIVATE)) { - npriv_key = BN_dup(priv_key); - if (npriv_key == NULL) { - goto fail; - } - - /* Memory management of npriv_key is transferred to DSA object */ - rc = DSA_set0_key(new->dsa, NULL, npriv_key); - if (rc == 0) { - goto fail; - } - } - - 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(); - if (new->rsa == NULL) { + RSA *new_rsa = NULL; + const RSA *key_rsa = EVP_PKEY_get0_RSA(key->key); +#endif /* OPENSSL_VERSION_NUMBER < 0x30000000L */ +#ifdef WITH_PKCS11_URI + /* Take the PKCS#11 keys as they are */ + if (key->flags & SSH_KEY_FLAG_PKCS11_URI && !demote) { + rc = EVP_PKEY_up_ref(key->key); + if (rc != 1) { + goto fail; + } + new->key = key->key; + return new; + } +#endif /* WITH_PKCS11_URI */ +#if OPENSSL_VERSION_NUMBER < 0x30000000L + new_rsa = RSA_new(); + if (new_rsa == NULL) { goto fail; } @@ -395,18 +467,20 @@ ssh_key pki_key_dup(const ssh_key key, int demote) * dmq1 = d mod (q-1) * iqmp = q^-1 mod p */ - RSA_get0_key(key->rsa, &n, &e, &d); + RSA_get0_key(key_rsa, &n, &e, &d); nn = BN_dup(n); ne = BN_dup(e); if (nn == NULL || ne == NULL) { + RSA_free(new_rsa); BN_free(nn); BN_free(ne); goto fail; } /* Memory management of nn and ne is transferred to RSA object */ - rc = RSA_set0_key(new->rsa, nn, ne, NULL); + rc = RSA_set0_key(new_rsa, nn, ne, NULL); if (rc == 0) { + RSA_free(new_rsa); BN_free(nn); BN_free(ne); goto fail; @@ -419,43 +493,48 @@ ssh_key pki_key_dup(const ssh_key key, int demote) nd = BN_dup(d); if (nd == NULL) { + RSA_free(new_rsa); goto fail; } /* Memory management of nd is transferred to RSA object */ - rc = RSA_set0_key(new->rsa, NULL, NULL, nd); + rc = RSA_set0_key(new_rsa, NULL, NULL, nd); if (rc == 0) { + RSA_free(new_rsa); goto fail; } /* p, q, dmp1, dmq1 and iqmp may be NULL in private keys, but the * RSA operations are much faster when these values are available. */ - RSA_get0_factors(key->rsa, &p, &q); + RSA_get0_factors(key_rsa, &p, &q); if (p != NULL && q != NULL) { /* need to set both of them */ np = BN_dup(p); nq = BN_dup(q); if (np == NULL || nq == NULL) { + RSA_free(new_rsa); BN_free(np); BN_free(nq); goto fail; } /* Memory management of np and nq is transferred to RSA object */ - rc = RSA_set0_factors(new->rsa, np, nq); + rc = RSA_set0_factors(new_rsa, np, nq); if (rc == 0) { + RSA_free(new_rsa); BN_free(np); BN_free(nq); goto fail; } } - RSA_get0_crt_params(key->rsa, &dmp1, &dmq1, &iqmp); + RSA_get0_crt_params(key_rsa, &dmp1, &dmq1, &iqmp); if (dmp1 != NULL || dmq1 != NULL || iqmp != NULL) { ndmp1 = BN_dup(dmp1); ndmq1 = BN_dup(dmq1); niqmp = BN_dup(iqmp); if (ndmp1 == NULL || ndmq1 == NULL || niqmp == NULL) { + RSA_free(new_rsa); BN_free(ndmp1); BN_free(ndmq1); BN_free(niqmp); @@ -464,8 +543,9 @@ ssh_key pki_key_dup(const ssh_key key, int demote) /* Memory management of ndmp1, ndmq1 and niqmp is transferred * to RSA object */ - rc = RSA_set0_crt_params(new->rsa, ndmp1, ndmq1, niqmp); + rc = RSA_set0_crt_params(new_rsa, ndmp1, ndmq1, niqmp); if (rc == 0) { + RSA_free(new_rsa); BN_free(ndmp1); BN_free(ndmq1); BN_free(niqmp); @@ -474,6 +554,26 @@ ssh_key pki_key_dup(const ssh_key key, int demote) } } + new->key = EVP_PKEY_new(); + if (new->key == NULL) { + RSA_free(new_rsa); + goto fail; + } + + rc = EVP_PKEY_assign_RSA(new->key, new_rsa); + if (rc != 1) { + EVP_PKEY_free(new->key); + RSA_free(new_rsa); + goto fail; + } + + new_rsa = NULL; +#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,31 +581,73 @@ 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; - +#ifdef WITH_PKCS11_URI + /* Take the PKCS#11 keys as they are */ + if (key->flags & SSH_KEY_FLAG_PKCS11_URI && !demote) { + rc = EVP_PKEY_up_ref(key->key); + if (rc != 1) { + goto fail; + } + new->key = key->key; + return new; + } +#endif /* WITH_PKCS11_URI */ +#if OPENSSL_VERSION_NUMBER < 0x30000000L /* privkey -> pubkey */ if (demote && ssh_key_is_private(key)) { - const EC_POINT *p; + const EC_POINT *p = NULL; + EC_KEY *new_ecdsa = NULL, *old_ecdsa = NULL; int ok; - new->ecdsa = EC_KEY_new_by_curve_name(key->ecdsa_nid); - if (new->ecdsa == NULL) { + new_ecdsa = EC_KEY_new_by_curve_name(key->ecdsa_nid); + if (new_ecdsa == NULL) { goto fail; } - p = EC_KEY_get0_public_key(key->ecdsa); + old_ecdsa = EVP_PKEY_get0_EC_KEY(key->key); + if (old_ecdsa == NULL) { + EC_KEY_free(new_ecdsa); + goto fail; + } + + p = EC_KEY_get0_public_key(old_ecdsa); if (p == NULL) { + EC_KEY_free(new_ecdsa); + goto fail; + } + + ok = EC_KEY_set_public_key(new_ecdsa, p); + if (ok != 1) { + EC_KEY_free(new_ecdsa); goto fail; } - ok = EC_KEY_set_public_key(new->ecdsa, p); - if (!ok) { + new->key = EVP_PKEY_new(); + if (new->key == NULL) { + EC_KEY_free(new_ecdsa); + goto fail; + } + + ok = EVP_PKEY_assign_EC_KEY(new->key, new_ecdsa); + if (ok != 1) { + EC_KEY_free(new_ecdsa); goto fail; } } else { - new->ecdsa = EC_KEY_dup(key->ecdsa); + rc = EVP_PKEY_up_ref(key->key); + if (rc != 1) { + goto fail; + } + new->key = key->key; + } +#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,172 +667,181 @@ fail: } int pki_key_generate_rsa(ssh_key key, int parameter){ - BIGNUM *e; int rc; +#if OPENSSL_VERSION_NUMBER < 0x30000000L + BIGNUM *e = NULL; + RSA *key_rsa = NULL; +#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 */ + +#if OPENSSL_VERSION_NUMBER < 0x30000000L + e = BN_new(); + key_rsa = RSA_new(); + if (key_rsa == NULL) { + return SSH_ERROR; + } - 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; - return SSH_OK; -} + if (rc <= 0 || key_rsa == NULL) { + return SSH_ERROR; + } -int pki_key_generate_dss(ssh_key key, int parameter){ - int rc; -#if OPENSSL_VERSION_NUMBER > 0x00908000L - key->dsa = DSA_new(); - if (key->dsa == NULL) { + key->key = EVP_PKEY_new(); + if (key->key == NULL) { + RSA_free(key_rsa); return SSH_ERROR; } - rc = DSA_generate_parameters_ex(key->dsa, - parameter, - NULL, /* seed */ - 0, /* seed_len */ - NULL, /* counter_ret */ - NULL, /* h_ret */ - NULL); /* cb */ + + rc = EVP_PKEY_assign_RSA(key->key, key_rsa); if (rc != 1) { - DSA_free(key->dsa); - key->dsa = NULL; + RSA_free(key_rsa); + EVP_PKEY_free(key->key); return SSH_ERROR; } + + key_rsa = NULL; #else - key->dsa = DSA_generate_parameters(parameter, NULL, 0, NULL, NULL, - NULL, NULL); - if(key->dsa == NULL){ + key->key = NULL; + + rc = EVP_PKEY_keygen_init(pctx); + if (rc != 1) { + EVP_PKEY_CTX_free(pctx); return SSH_ERROR; } -#endif - rc = DSA_generate_key(key->dsa); - if (rc != 1){ - DSA_free(key->dsa); - key->dsa=NULL; + + 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; } - return SSH_OK; + + 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; } #ifdef HAVE_OPENSSL_ECC -int pki_key_generate_ecdsa(ssh_key key, int parameter) { +int pki_key_generate_ecdsa(ssh_key key, int parameter) +{ +#if OPENSSL_VERSION_NUMBER < 0x30000000L + EC_KEY *ecdsa = NULL; 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; +#if OPENSSL_VERSION_NUMBER >= 0x30000000L + group_name = NISTP256; +#endif /* OPENSSL_VERSION_NUMBER */ + break; case 384: key->ecdsa_nid = NID_secp384r1; key->type = SSH_KEYTYPE_ECDSA_P384; +#if OPENSSL_VERSION_NUMBER >= 0x30000000L + 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; +#if OPENSSL_VERSION_NUMBER >= 0x30000000L + group_name = NISTP521; +#endif /* OPENSSL_VERSION_NUMBER */ break; default: - SSH_LOG(SSH_LOG_WARN, "Invalid parameter %d for ECDSA key " + SSH_LOG(SSH_LOG_TRACE, "Invalid parameter %d for ECDSA key " "generation", parameter); return SSH_ERROR; } +#if OPENSSL_VERSION_NUMBER < 0x30000000L + ecdsa = EC_KEY_new_by_curve_name(key->ecdsa_nid); + if (ecdsa == NULL) { + return SSH_ERROR; + } + ok = EC_KEY_generate_key(ecdsa); + if (!ok) { + EC_KEY_free(ecdsa); + return SSH_ERROR; + } + + EC_KEY_set_asn1_flag(ecdsa, OPENSSL_EC_NAMED_CURVE); - key->ecdsa = EC_KEY_new_by_curve_name(key->ecdsa_nid); - if (key->ecdsa == NULL) { + key->key = EVP_PKEY_new(); + if (key->key == NULL) { + EC_KEY_free(ecdsa); return SSH_ERROR; } - ok = EC_KEY_generate_key(key->ecdsa); - if (!ok) { - EC_KEY_free(key->ecdsa); + ok = EVP_PKEY_assign_EC_KEY(key->key, ecdsa); + if (ok != 1) { return SSH_ERROR; } - EC_KEY_set_asn1_flag(key->ecdsa, OPENSSL_EC_NAMED_CURVE); +#else + key->key = EVP_EC_gen(group_name); + if (key->key == NULL) { + return SSH_ERROR; + } +#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 comparison 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; - } + int rc; - if (what == SSH_KEY_CMP_PRIVATE) { - if (bignum_cmp(priv_key1, priv_key2) != 0) { - 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; - } + (void)what; - 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; - } + switch (ssh_key_type_plain(k1->type)) { case SSH_KEYTYPE_ECDSA_P256: case SSH_KEYTYPE_ECDSA_P384: case SSH_KEYTYPE_ECDSA_P521: case SSH_KEYTYPE_SK_ECDSA: +#if OPENSSL_VERSION_NUMBER < 0x30000000L #ifdef HAVE_OPENSSL_ECC { - const EC_POINT *p1 = EC_KEY_get0_public_key(k1->ecdsa); - const EC_POINT *p2 = EC_KEY_get0_public_key(k2->ecdsa); - const EC_GROUP *g1 = EC_KEY_get0_group(k1->ecdsa); - const EC_GROUP *g2 = EC_KEY_get0_group(k2->ecdsa); + const EC_KEY *ec1 = EVP_PKEY_get0_EC_KEY(k1->key); + const EC_KEY *ec2 = EVP_PKEY_get0_EC_KEY(k2->key); + const EC_POINT *p1 = NULL; + const EC_POINT *p2 = NULL; + const EC_GROUP *g1 = NULL; + const EC_GROUP *g2 = NULL; + + if (ec1 == NULL || ec2 == NULL) { + return 1; + } + + p1 = EC_KEY_get0_public_key(ec1); + p2 = EC_KEY_get0_public_key(ec2); + g1 = EC_KEY_get0_group(ec1); + g2 = EC_KEY_get0_group(ec2); - if (p1 == NULL || p2 == NULL) { + if (p1 == NULL || p2 == NULL || g1 == NULL || g2 == NULL) { return 1; } @@ -703,23 +854,29 @@ int pki_key_compare(const ssh_key k1, } if (what == SSH_KEY_CMP_PRIVATE) { - if (bignum_cmp(EC_KEY_get0_private_key(k1->ecdsa), - EC_KEY_get0_private_key(k2->ecdsa))) { + if (bignum_cmp(EC_KEY_get0_private_key(ec1), + EC_KEY_get0_private_key(ec2))) { return 1; } } - break; } -#endif +#endif /* HAVE_OPENSSL_ECC */ +#endif /* OPENSSL_VERSION_NUMBER */ + case SSH_KEYTYPE_RSA: + case SSH_KEYTYPE_RSA1: + rc = EVP_PKEY_eq(k1->key, k2->key); + if (rc != 1) { + return 1; + } + break; case SSH_KEYTYPE_ED25519: case SSH_KEYTYPE_SK_ED25519: - /* ed25519 keys handled globaly */ + /* ed25519 keys handled globally */ case SSH_KEYTYPE_UNKNOWN: default: return 1; } - return 0; } @@ -740,37 +897,22 @@ ssh_string pki_private_key_to_pem(const ssh_key key, } switch (key->type) { - case SSH_KEYTYPE_DSS: - pkey = EVP_PKEY_new(); - if (pkey == NULL) { - goto err; - } - - rc = EVP_PKEY_set1_DSA(pkey, key->dsa); - break; case SSH_KEYTYPE_RSA: case SSH_KEYTYPE_RSA1: - pkey = EVP_PKEY_new(); - if (pkey == NULL) { - goto err; - } - - rc = EVP_PKEY_set1_RSA(pkey, key->rsa); - break; -#ifdef HAVE_ECC case SSH_KEYTYPE_ECDSA_P256: case SSH_KEYTYPE_ECDSA_P384: case SSH_KEYTYPE_ECDSA_P521: - pkey = EVP_PKEY_new(); - if (pkey == NULL) { + rc = EVP_PKEY_up_ref(key->key); + if (rc != 1) { goto err; } + pkey = key->key; + + /* Mark the operation as successful as for the other key types */ + rc = 1; - rc = EVP_PKEY_set1_EC_KEY(pkey, key->ecdsa); break; -#endif case SSH_KEYTYPE_ED25519: -#ifdef HAVE_OPENSSL_ED25519 /* In OpenSSL, the input is the private key seed only, which means * the first half of the SSH private key (the second half is the * public key) */ @@ -787,11 +929,6 @@ ssh_string pki_private_key_to_pem(const ssh_key key, /* Mark the operation as successful as for the other key types */ rc = 1; break; -#else - SSH_LOG(SSH_LOG_WARN, "PEM output not supported for key type ssh-ed25519"); - goto err; -#endif - case SSH_KEYTYPE_DSS_CERT01: case SSH_KEYTYPE_RSA_CERT01: case SSH_KEYTYPE_ECDSA_P256_CERT01: case SSH_KEYTYPE_ECDSA_P384_CERT01: @@ -799,11 +936,11 @@ ssh_string pki_private_key_to_pem(const ssh_key key, case SSH_KEYTYPE_ED25519_CERT01: case SSH_KEYTYPE_UNKNOWN: default: - SSH_LOG(SSH_LOG_WARN, "Unknown or invalid private key type %d", key->type); + SSH_LOG(SSH_LOG_TRACE, "Unknown or invalid private key type %d", key->type); goto err; } if (rc != 1) { - SSH_LOG(SSH_LOG_WARN, "Failed to initialize EVP_PKEY structure"); + SSH_LOG(SSH_LOG_TRACE, "Failed to initialize EVP_PKEY structure"); goto err; } @@ -830,6 +967,9 @@ ssh_string pki_private_key_to_pem(const ssh_key key, pkey = NULL; if (rc != 1) { + SSH_LOG(SSH_LOG_WARNING, + "Failed to write private key: %s\n", + ERR_error_string(ERR_get_error(), NULL)); goto err; } @@ -840,7 +980,12 @@ ssh_string pki_private_key_to_pem(const ssh_key key, goto err; } - ssh_string_fill(blob, buf->data, buf->length); + rc = ssh_string_fill(blob, buf->data, buf->length); + if (rc < 0) { + ssh_string_free(blob); + goto err; + } + BIO_free(mem); return blob; @@ -857,20 +1002,13 @@ ssh_key pki_private_key_from_base64(const char *b64_key, void *auth_data) { BIO *mem = NULL; - DSA *dsa = NULL; - RSA *rsa = NULL; -#ifdef HAVE_OPENSSL_ED25519 +#if OPENSSL_VERSION_NUMBER < 0x30000000L + EC_KEY *ecdsa = NULL; +#endif /* OPENSSL_VERSION_NUMBER */ uint8_t *ed25519 = NULL; -#else - ed25519_privkey *ed25519 = NULL; -#endif + uint8_t *ed25519_pubkey = NULL; ssh_key key = NULL; enum ssh_keytypes_e type = SSH_KEYTYPE_UNKNOWN; -#ifdef HAVE_OPENSSL_ECC - EC_KEY *ecdsa = NULL; -#else - void *ecdsa = NULL; -#endif EVP_PKEY *pkey = NULL; mem = BIO_new_mem_buf((void*)b64_key, -1); @@ -891,53 +1029,41 @@ ssh_key pki_private_key_from_base64(const char *b64_key, BIO_free(mem); if (pkey == NULL) { - SSH_LOG(SSH_LOG_WARN, - "Parsing private key: %s", + SSH_LOG(SSH_LOG_TRACE, + "Error parsing private key: %s", ERR_error_string(ERR_get_error(), NULL)); return NULL; } switch (EVP_PKEY_base_id(pkey)) { - case EVP_PKEY_DSA: - dsa = EVP_PKEY_get1_DSA(pkey); - if (dsa == NULL) { - SSH_LOG(SSH_LOG_WARN, - "Parsing private key: %s", - ERR_error_string(ERR_get_error(),NULL)); - goto fail; - } - type = SSH_KEYTYPE_DSS; - break; case EVP_PKEY_RSA: - rsa = EVP_PKEY_get1_RSA(pkey); - if (rsa == NULL) { - SSH_LOG(SSH_LOG_WARN, - "Parsing private key: %s", - ERR_error_string(ERR_get_error(),NULL)); - goto fail; - } type = SSH_KEYTYPE_RSA; break; case EVP_PKEY_EC: #ifdef HAVE_OPENSSL_ECC - ecdsa = EVP_PKEY_get1_EC_KEY(pkey); +#if OPENSSL_VERSION_NUMBER < 0x30000000L + ecdsa = EVP_PKEY_get0_EC_KEY(pkey); if (ecdsa == NULL) { - SSH_LOG(SSH_LOG_WARN, - "Parsing private key: %s", + SSH_LOG(SSH_LOG_TRACE, + "Error parsing private key: %s", 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 */ +#if OPENSSL_VERSION_NUMBER < 0x30000000L 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."); + SSH_LOG(SSH_LOG_TRACE, "Invalid private key."); goto fail; } break; -#endif -#ifdef HAVE_OPENSSL_ED25519 +#endif /* HAVE_OPENSSL_ECC */ case EVP_PKEY_ED25519: { size_t key_len; @@ -958,7 +1084,7 @@ ssh_key pki_private_key_from_base64(const char *b64_key, ed25519 = malloc(key_len); if (ed25519 == NULL) { - SSH_LOG(SSH_LOG_WARN, "Out of memory"); + SSH_LOG(SSH_LOG_TRACE, "Out of memory"); goto fail; } @@ -970,17 +1096,32 @@ ssh_key pki_private_key_from_base64(const char *b64_key, ERR_error_string(ERR_get_error(), NULL)); goto fail; } + + /* length matches the private key length */ + ed25519_pubkey = malloc(ED25519_KEY_LEN); + if (ed25519_pubkey == NULL) { + SSH_LOG(SSH_LOG_TRACE, "Out of memory"); + goto fail; + } + + evp_rc = EVP_PKEY_get_raw_public_key(pkey, (uint8_t *)ed25519_pubkey, + &key_len); + if (evp_rc != 1) { + SSH_LOG(SSH_LOG_TRACE, + "Failed to get ed25519 raw public key: %s", + ERR_error_string(ERR_get_error(), NULL)); + goto fail; + } type = SSH_KEYTYPE_ED25519; + } break; -#endif default: - EVP_PKEY_free(pkey); - SSH_LOG(SSH_LOG_WARN, "Unknown or invalid private key type %d", + SSH_LOG(SSH_LOG_TRACE, "Unknown or invalid private key type %d", EVP_PKEY_base_id(pkey)); + EVP_PKEY_free(pkey); return NULL; } - EVP_PKEY_free(pkey); key = ssh_key_new(); if (key == NULL) { @@ -990,164 +1131,207 @@ 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; - key->dsa = dsa; - key->rsa = rsa; - key->ecdsa = ecdsa; + key->key = pkey; key->ed25519_privkey = ed25519; + key->ed25519_pubkey = ed25519_pubkey; #ifdef HAVE_OPENSSL_ECC if (is_ecdsa_key_type(key->type)) { - key->ecdsa_nid = pki_key_ecdsa_to_nid(key->ecdsa); +#if OPENSSL_VERSION_NUMBER < 0x30000000L + key->ecdsa_nid = pki_key_ecdsa_to_nid(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); - DSA_free(dsa); - RSA_free(rsa); -#ifdef HAVE_OPENSSL_ECC - EC_KEY_free(ecdsa); -#endif -#ifdef HAVE_OPENSSL_ED25519 SAFE_FREE(ed25519); -#endif + SAFE_FREE(ed25519_pubkey); return NULL; } -int pki_privkey_build_dss(ssh_key key, +int pki_privkey_build_rsa(ssh_key key, + ssh_string n, + ssh_string e, + ssh_string d, + ssh_string iqmp, ssh_string p, - ssh_string q, - ssh_string g, - ssh_string pubkey, - ssh_string privkey) + ssh_string q) { int rc; - BIGNUM *bp, *bq, *bg, *bpub_key, *bpriv_key; - - key->dsa = DSA_new(); - if (key->dsa == NULL) { + BIGNUM *be = NULL, *bn = NULL, *bd = NULL; + BIGNUM *biqmp = NULL, *bp = NULL, *bq = NULL; + BIGNUM *aux = NULL, *d_consttime = NULL; + BIGNUM *bdmq1 = NULL, *bdmp1 = NULL; + BN_CTX *ctx = NULL; + +#if OPENSSL_VERSION_NUMBER >= 0x30000000L + OSSL_PARAM_BLD *param_bld = OSSL_PARAM_BLD_new(); + if (param_bld == NULL) { return SSH_ERROR; } +#else + RSA *key_rsa = RSA_new(); + if (key_rsa == NULL) { + return SSH_ERROR; + } +#endif /* OPENSSL_VERSION_NUMBER */ + bn = ssh_make_string_bn(n); + be = ssh_make_string_bn(e); + bd = ssh_make_string_bn(d); + biqmp = ssh_make_string_bn(iqmp); bp = ssh_make_string_bn(p); bq = ssh_make_string_bn(q); - bg = ssh_make_string_bn(g); - bpub_key = ssh_make_string_bn(pubkey); - bpriv_key = ssh_make_string_bn(privkey); - if (bp == NULL || bq == NULL || - bg == NULL || bpub_key == NULL) { + if (be == NULL || bn == NULL || bd == NULL || + /*biqmp == NULL ||*/ bp == NULL || bq == NULL) { + rc = SSH_ERROR; goto fail; } - /* Memory management of bp, qq and bg is transferred to DSA object */ - rc = DSA_set0_pqg(key->dsa, bp, bq, bg); - if (rc == 0) { + /* Calculate remaining CRT parameters for OpenSSL to be happy + * taken from OpenSSH */ + if ((ctx = BN_CTX_new()) == NULL) { + rc = SSH_ERROR; goto fail; } - - /* Memory management of bpub_key and bpriv_key is transferred to DSA object */ - rc = DSA_set0_key(key->dsa, bpub_key, bpriv_key); - if (rc == 0) { + if ((aux = BN_new()) == NULL || + (bdmq1 = BN_new()) == NULL || + (bdmp1 = BN_new()) == NULL) { + rc = SSH_ERROR; goto fail; } + if ((d_consttime = BN_dup(bd)) == NULL) { + rc = SSH_ERROR; + goto fail; + } + BN_set_flags(aux, BN_FLG_CONSTTIME); + BN_set_flags(d_consttime, BN_FLG_CONSTTIME); - return SSH_OK; -fail: - DSA_free(key->dsa); - return SSH_ERROR; -} - -int pki_pubkey_build_dss(ssh_key key, - ssh_string p, - ssh_string q, - ssh_string g, - ssh_string pubkey) { - int rc; - BIGNUM *bp = NULL, *bq = NULL, *bg = NULL, *bpub_key = NULL; - - key->dsa = DSA_new(); - if (key->dsa == NULL) { - return SSH_ERROR; + if ((BN_sub(aux, bq, BN_value_one()) == 0) || + (BN_mod(bdmq1, d_consttime, aux, ctx) == 0) || + (BN_sub(aux, bp, BN_value_one()) == 0) || + (BN_mod(bdmp1, d_consttime, aux, ctx) == 0)) { + rc = SSH_ERROR; + goto fail; } - bp = ssh_make_string_bn(p); - bq = ssh_make_string_bn(q); - bg = ssh_make_string_bn(g); - bpub_key = ssh_make_string_bn(pubkey); - if (bp == NULL || bq == NULL || - bg == NULL || bpub_key == NULL) { +#if OPENSSL_VERSION_NUMBER < 0x30000000L + /* Memory management of be, bn and bd is transferred to RSA object */ + rc = RSA_set0_key(key_rsa, bn, be, bd); + if (rc == 0) { goto fail; } - /* Memory management of bp, bq and bg is transferred to DSA object */ - rc = DSA_set0_pqg(key->dsa, bp, bq, bg); + /* Memory management of bp and bq is transferred to RSA object */ + rc = RSA_set0_factors(key_rsa, bp, bq); if (rc == 0) { goto fail; } - /* Memory management of npub_key is transferred to DSA object */ - rc = DSA_set0_key(key->dsa, bpub_key, NULL); + /* p, q, dmp1, dmq1 and iqmp may be NULL in private keys, but the RSA + * operations are much faster when these values are available. + * https://www.openssl.org/docs/man1.0.2/crypto/rsa.html + * And OpenSSL fails to export these keys to PEM if these are missing: + * https://github.com/openssl/openssl/issues/21826 + */ + rc = RSA_set0_crt_params(key_rsa, bdmp1, bdmq1, biqmp); if (rc == 0) { goto fail; } + bignum_safe_free(aux); + bignum_safe_free(d_consttime); + + key->key = EVP_PKEY_new(); + if (key->key == NULL) { + goto fail; + } + + rc = EVP_PKEY_assign_RSA(key->key, key_rsa); + if (rc != 1) { + goto fail; + } return SSH_OK; fail: - DSA_free(key->dsa); + RSA_free(key_rsa); + EVP_PKEY_free(key->key); return SSH_ERROR; -} +#else + rc = OSSL_PARAM_BLD_push_BN(param_bld, OSSL_PKEY_PARAM_RSA_N, bn); + if (rc != 1) { + rc = SSH_ERROR; + goto fail; + } + rc = OSSL_PARAM_BLD_push_BN(param_bld, OSSL_PKEY_PARAM_RSA_E, be); + if (rc != 1) { + rc = SSH_ERROR; + goto fail; + } + rc = OSSL_PARAM_BLD_push_BN(param_bld, OSSL_PKEY_PARAM_RSA_D, bd); + if (rc != 1) { + rc = SSH_ERROR; + goto fail; + } -int pki_privkey_build_rsa(ssh_key key, - ssh_string n, - ssh_string e, - ssh_string d, - UNUSED_PARAM(ssh_string iqmp), - ssh_string p, - ssh_string q) -{ - int rc; - BIGNUM *be, *bn, *bd/*, *biqmp*/, *bp, *bq; + rc = OSSL_PARAM_BLD_push_BN(param_bld, OSSL_PKEY_PARAM_RSA_FACTOR1, bp); + if (rc != 1) { + rc = SSH_ERROR; + goto fail; + } - key->rsa = RSA_new(); - if (key->rsa == NULL) { - return SSH_ERROR; + rc = OSSL_PARAM_BLD_push_BN(param_bld, OSSL_PKEY_PARAM_RSA_FACTOR2, bq); + if (rc != 1) { + rc = SSH_ERROR; + goto fail; } - bn = ssh_make_string_bn(n); - be = ssh_make_string_bn(e); - bd = ssh_make_string_bn(d); - /*biqmp = ssh_make_string_bn(iqmp);*/ - bp = ssh_make_string_bn(p); - bq = ssh_make_string_bn(q); - if (be == NULL || bn == NULL || bd == NULL || - /*biqmp == NULL ||*/ bp == NULL || bq == NULL) { + rc = OSSL_PARAM_BLD_push_BN(param_bld, OSSL_PKEY_PARAM_RSA_EXPONENT1, bdmp1); + if (rc != 1) { + rc = SSH_ERROR; goto fail; } - /* Memory management of be, bn and bd is transferred to RSA object */ - rc = RSA_set0_key(key->rsa, bn, be, bd); - if (rc == 0) { + rc = OSSL_PARAM_BLD_push_BN(param_bld, OSSL_PKEY_PARAM_RSA_EXPONENT2, bdmq1); + if (rc != 1) { + rc = SSH_ERROR; goto fail; } - /* Memory management of bp and bq is transferred to RSA object */ - rc = RSA_set0_factors(key->rsa, bp, bq); - if (rc == 0) { + rc = OSSL_PARAM_BLD_push_BN(param_bld, OSSL_PKEY_PARAM_RSA_COEFFICIENT1, biqmp); + if (rc != 1) { + rc = SSH_ERROR; goto fail; } - /* p, q, dmp1, dmq1 and iqmp may be NULL in private keys, but the RSA - * operations are much faster when these values are available. - * https://www.openssl.org/docs/man1.0.2/crypto/rsa.html - */ - /* RSA_set0_crt_params(key->rsa, biqmp, NULL, NULL); - TODO calculate missing crt_params */ + rc = evp_build_pkey("RSA", param_bld, &(key->key), EVP_PKEY_KEYPAIR); + if (rc != SSH_OK) { + SSH_LOG(SSH_LOG_WARNING, + "Failed to import private key: %s\n", + ERR_error_string(ERR_get_error(), NULL)); + rc = SSH_ERROR; + goto fail; + } - return SSH_OK; fail: - RSA_free(key->rsa); - return SSH_ERROR; + OSSL_PARAM_BLD_free(param_bld); + bignum_safe_free(bn); + bignum_safe_free(be); + bignum_safe_free(bd); + bignum_safe_free(bp); + bignum_safe_free(bq); + bignum_safe_free(biqmp); + + bignum_safe_free(aux); + bignum_safe_free(d_consttime); + bignum_safe_free(bdmp1); + bignum_safe_free(bdmq1); + BN_CTX_free(ctx); + return rc; +#endif /* OPENSSL_VERSION_NUMBER */ } int pki_pubkey_build_rsa(ssh_key key, @@ -1155,31 +1339,71 @@ int pki_pubkey_build_rsa(ssh_key key, ssh_string n) { int rc; BIGNUM *be = NULL, *bn = NULL; - - key->rsa = RSA_new(); - if (key->rsa == NULL) { +#if OPENSSL_VERSION_NUMBER >= 0x30000000L + OSSL_PARAM_BLD *param_bld = OSSL_PARAM_BLD_new(); + if (param_bld == NULL) { return SSH_ERROR; } +#else + RSA *key_rsa = RSA_new(); + if (key_rsa == NULL) { + return SSH_ERROR; + } +#endif /* OPENSSL_VERSION_NUMBER */ be = ssh_make_string_bn(e); bn = ssh_make_string_bn(n); if (be == NULL || bn == NULL) { + rc = SSH_ERROR; goto fail; } +#if OPENSSL_VERSION_NUMBER < 0x30000000L /* Memory management of bn and be is transferred to RSA object */ - rc = RSA_set0_key(key->rsa, bn, be, NULL); + rc = RSA_set0_key(key_rsa, bn, be, NULL); if (rc == 0) { goto fail; } + key->key = EVP_PKEY_new(); + if (key->key == NULL) { + goto fail; + } + + rc = EVP_PKEY_assign_RSA(key->key, key_rsa); + if (rc != 1) { + goto fail; + } + return SSH_OK; fail: - RSA_free(key->rsa); + EVP_PKEY_free(key->key); + RSA_free(key_rsa); return SSH_ERROR; +#else + rc = OSSL_PARAM_BLD_push_BN(param_bld, OSSL_PKEY_PARAM_RSA_N, bn); + if (rc != 1) { + rc = SSH_ERROR; + goto fail; + } + rc = OSSL_PARAM_BLD_push_BN(param_bld, OSSL_PKEY_PARAM_RSA_E, be); + if (rc != 1) { + rc = SSH_ERROR; + goto fail; + } + + rc = evp_build_pkey("RSA", param_bld, &(key->key), EVP_PKEY_PUBLIC_KEY); + +fail: + OSSL_PARAM_BLD_free(param_bld); + bignum_safe_free(bn); + bignum_safe_free(be); + + return rc; +#endif /* OPENSSL_VERSION_NUMBER */ } -ssh_string pki_publickey_to_blob(const ssh_key key) +ssh_string pki_key_to_blob(const ssh_key key, enum ssh_key_e type) { ssh_buffer buffer; ssh_string type_s; @@ -1189,7 +1413,15 @@ ssh_string pki_publickey_to_blob(const ssh_key key) ssh_string p = NULL; ssh_string g = NULL; ssh_string q = NULL; + ssh_string d = NULL; + ssh_string iqmp = NULL; int rc; +#if OPENSSL_VERSION_NUMBER >= 0x30000000L + BIGNUM *bp = NULL, *bq = NULL, *bg = NULL, *bpub_key = NULL, + *bn = NULL, *be = NULL, + *bd = NULL, *biqmp = NULL; + OSSL_PARAM *params = NULL; +#endif /* OPENSSL_VERSION_NUMBER */ buffer = ssh_buffer_new(); if (buffer == NULL) { @@ -1219,62 +1451,37 @@ ssh_string pki_publickey_to_blob(const ssh_key key) } switch (key->type) { - case SSH_KEYTYPE_DSS: { - const BIGNUM *bp, *bq, *bg, *bpub_key; - DSA_get0_pqg(key->dsa, &bp, &bq, &bg); - p = ssh_make_bignum_string((BIGNUM *)bp); - if (p == NULL) { - goto fail; - } - - q = ssh_make_bignum_string((BIGNUM *)bq); - if (q == NULL) { - goto fail; - } - - g = ssh_make_bignum_string((BIGNUM *)bg); - if (g == NULL) { - goto fail; - } - - DSA_get0_key(key->dsa, &bpub_key, NULL); - n = ssh_make_bignum_string((BIGNUM *)bpub_key); - if (n == NULL) { + case SSH_KEYTYPE_RSA: + case SSH_KEYTYPE_RSA1: { +#if OPENSSL_VERSION_NUMBER < 0x30000000L + const BIGNUM *be = NULL, *bn = NULL; + const RSA *key_rsa = EVP_PKEY_get0_RSA(key->key); + 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; } - - if (ssh_buffer_add_ssh_string(buffer, p) < 0) { + out_param = OSSL_PARAM_locate_const(params, OSSL_PKEY_PARAM_RSA_E); + if (out_param == NULL) { + SSH_LOG(SSH_LOG_TRACE, "RSA: No param E has been found"); goto fail; } - if (ssh_buffer_add_ssh_string(buffer, q) < 0) { + rc = OSSL_PARAM_get_BN(out_param, &be); + if (rc != 1) { goto fail; } - if (ssh_buffer_add_ssh_string(buffer, g) < 0) { + out_param = OSSL_PARAM_locate_const(params, OSSL_PKEY_PARAM_RSA_N); + if (out_param == NULL) { + SSH_LOG(SSH_LOG_TRACE, "RSA: No param N has been found"); goto fail; } - if (ssh_buffer_add_ssh_string(buffer, n) < 0) { + rc = OSSL_PARAM_get_BN(out_param, &bn); + if (rc != 1) { goto fail; } - - ssh_string_burn(p); - SSH_STRING_FREE(p); - p = NULL; - ssh_string_burn(g); - SSH_STRING_FREE(g); - g = NULL; - ssh_string_burn(q); - SSH_STRING_FREE(q); - q = NULL; - ssh_string_burn(n); - SSH_STRING_FREE(n); - n = NULL; - - break; - } - case SSH_KEYTYPE_RSA: - case SSH_KEYTYPE_RSA1: { - const BIGNUM *be, *bn; - RSA_get0_key(key->rsa, &bn, &be, NULL); +#endif /* OPENSSL_VERSION_NUMBER */ e = ssh_make_bignum_string((BIGNUM *)be); if (e == NULL) { goto fail; @@ -1285,31 +1492,165 @@ ssh_string pki_publickey_to_blob(const ssh_key key) goto fail; } - if (ssh_buffer_add_ssh_string(buffer, e) < 0) { - goto fail; - } - if (ssh_buffer_add_ssh_string(buffer, n) < 0) { - goto fail; - } + if (type == SSH_KEY_PUBLIC) { + /* The N and E parts are swapped in the public key export ! */ + rc = ssh_buffer_add_ssh_string(buffer, e); + if (rc < 0) { + goto fail; + } + rc = ssh_buffer_add_ssh_string(buffer, n); + if (rc < 0) { + goto fail; + } + } else if (type == SSH_KEY_PRIVATE) { +#if OPENSSL_VERSION_NUMBER < 0x30000000L + const BIGNUM *bd, *biqmp, *bp, *bq; + RSA_get0_key(key_rsa, NULL, NULL, &bd); + RSA_get0_factors(key_rsa, &bp, &bq); + RSA_get0_crt_params(key_rsa, NULL, NULL, &biqmp); +#else + rc = EVP_PKEY_todata(key->key, EVP_PKEY_KEYPAIR, ¶ms); + if (rc != 1) { + goto fail; + } + out_param = OSSL_PARAM_locate_const(params, OSSL_PKEY_PARAM_RSA_D); + if (out_param == NULL) { + SSH_LOG(SSH_LOG_TRACE, "RSA: No param D has been found"); + goto fail; + } + rc = OSSL_PARAM_get_BN(out_param, &bd); + if (rc != 1) { + goto fail; + } + + out_param = OSSL_PARAM_locate_const(params, OSSL_PKEY_PARAM_RSA_FACTOR1); + if (out_param == NULL) { + SSH_LOG(SSH_LOG_TRACE, "RSA: 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_RSA_FACTOR2); + if (out_param == NULL) { + SSH_LOG(SSH_LOG_TRACE, "RSA: 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_RSA_COEFFICIENT1); + if (out_param == NULL) { + SSH_LOG(SSH_LOG_TRACE, "RSA: No param IQMP has been found"); + goto fail; + } + rc = OSSL_PARAM_get_BN(out_param, &biqmp); + if (rc != 1) { + goto fail; + } +#endif /* OPENSSL_VERSION_NUMBER */ + rc = ssh_buffer_add_ssh_string(buffer, n); + if (rc < 0) { + goto fail; + } + rc = ssh_buffer_add_ssh_string(buffer, e); + if (rc < 0) { + goto fail; + } + + d = ssh_make_bignum_string((BIGNUM *)bd); + if (d == NULL) { + goto fail; + } + + iqmp = ssh_make_bignum_string((BIGNUM *)biqmp); + if (iqmp == NULL) { + goto fail; + } + + p = ssh_make_bignum_string((BIGNUM *)bp); + if (p == NULL) { + goto fail; + } + + q = ssh_make_bignum_string((BIGNUM *)bq); + if (q == NULL) { + goto fail; + } + + rc = ssh_buffer_add_ssh_string(buffer, d); + if (rc < 0) { + goto fail; + } + rc = ssh_buffer_add_ssh_string(buffer, iqmp); + if (rc < 0) { + goto fail; + } + rc = ssh_buffer_add_ssh_string(buffer, p); + if (rc < 0) { + goto fail; + } + rc = ssh_buffer_add_ssh_string(buffer, q); + if (rc < 0) { + goto fail; + } + + ssh_string_burn(d); + SSH_STRING_FREE(d); + d = NULL; + ssh_string_burn(iqmp); + SSH_STRING_FREE(iqmp); + iqmp = NULL; + ssh_string_burn(p); + SSH_STRING_FREE(p); + p = NULL; + ssh_string_burn(q); + SSH_STRING_FREE(q); + q = NULL; +#if OPENSSL_VERSION_NUMBER >= 0x30000000L + bignum_safe_free(bd); + bignum_safe_free(biqmp); + bignum_safe_free(bp); + bignum_safe_free(bq); +#endif /* OPENSSL_VERSION_NUMBER */ + } ssh_string_burn(e); SSH_STRING_FREE(e); e = NULL; 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: case SSH_KEYTYPE_SK_ED25519: - rc = pki_ed25519_public_key_to_blob(buffer, key); - if (rc == SSH_ERROR){ - goto fail; - } - if (key->type == SSH_KEYTYPE_SK_ED25519 && - ssh_buffer_add_ssh_string(buffer, key->sk_application) < 0) { - goto fail; + if (type == SSH_KEY_PUBLIC) { + rc = pki_ed25519_public_key_to_blob(buffer, key); + if (rc == SSH_ERROR){ + goto fail; + } + /* public key can contain certificate sk information */ + if (key->type == SSH_KEYTYPE_SK_ED25519) { + rc = ssh_buffer_add_ssh_string(buffer, key->sk_application); + if (rc < 0) { + goto fail; + } + } + } else { + rc = pki_ed25519_private_key_to_blob(buffer, key); + if (rc == SSH_ERROR){ + goto fail; + } } break; case SSH_KEYTYPE_ECDSA_P256: @@ -1317,50 +1658,150 @@ 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; - } + { +#if OPENSSL_VERSION_NUMBER >= 0x30000000L + EC_GROUP *group = NULL; + EC_POINT *point = NULL; + const void *pubkey; + size_t pubkey_len; + OSSL_PARAM *locate_param = NULL; +#else + const EC_GROUP *group = NULL; + const EC_POINT *point = NULL; + const BIGNUM *exp = NULL; + EC_KEY *ec = NULL; +#endif /* OPENSSL_VERSION_NUMBER */ + + 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; - } + rc = ssh_buffer_add_ssh_string(buffer, type_s); + SSH_STRING_FREE(type_s); + if (rc < 0) { + SSH_BUFFER_FREE(buffer); + return NULL; + } +#if OPENSSL_VERSION_NUMBER < 0x30000000L + ec = EVP_PKEY_get0_EC_KEY(key->key); + if (ec == NULL) { + goto fail; + } #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" - " ECDSA key objects in the PKCS #11 device. Unlike RSA," - " 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; - } + if (ssh_key_is_private(key) && !EC_KEY_get0_public_key(ec)) { + SSH_LOG(SSH_LOG_TRACE, "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 */ + group = EC_KEY_get0_group(ec); + point = EC_KEY_get0_public_key(ec); + if (group == NULL || point == NULL) { + goto fail; + } + e = pki_key_make_ecpoint_string(group, point); +#else + rc = EVP_PKEY_todata(key->key, EVP_PKEY_PUBLIC_KEY, ¶ms); + if (rc < 0) { + goto fail; + } - rc = ssh_buffer_add_ssh_string(buffer, e); - if (rc < 0) { - goto fail; - } + 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_TRACE, "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 */ - ssh_string_burn(e); - SSH_STRING_FREE(e); - e = NULL; + rc = OSSL_PARAM_get_octet_string_ptr(locate_param, &pubkey, &pubkey_len); + if (rc != 1) { + goto fail; + } + /* Convert the data to low-level representation */ + group = EC_GROUP_new_by_curve_name_ex(NULL, NULL, key->ecdsa_nid); + point = EC_POINT_new(group); + rc = EC_POINT_oct2point(group, point, pubkey, pubkey_len, NULL); + if (group == NULL || point == NULL || rc != 1) { + EC_GROUP_free(group); + EC_POINT_free(point); + goto fail; + } - if (key->type == SSH_KEYTYPE_SK_ECDSA && - ssh_buffer_add_ssh_string(buffer, key->sk_application) < 0) { - goto fail; - } + e = pki_key_make_ecpoint_string(group, point); + EC_GROUP_free(group); + EC_POINT_free(point); +#endif /* OPENSSL_VERSION_NUMBER */ + if (e == NULL) { + SSH_BUFFER_FREE(buffer); + return NULL; + } - break; -#endif + rc = ssh_buffer_add_ssh_string(buffer, e); + if (rc < 0) { + goto fail; + } + + ssh_string_burn(e); + SSH_STRING_FREE(e); + e = NULL; + if (type == SSH_KEY_PRIVATE) { +#if OPENSSL_VERSION_NUMBER >= 0x30000000L + rc = EVP_PKEY_todata(key->key, EVP_PKEY_KEYPAIR, ¶ms); + if (rc < 0) { + goto fail; + } + + locate_param = OSSL_PARAM_locate(params, OSSL_PKEY_PARAM_PRIV_KEY); + rc = OSSL_PARAM_get_BN(locate_param, &bd); + if (rc != 1) { + goto fail; + } + d = ssh_make_bignum_string((BIGNUM *)bd); + if (d == NULL) { + goto fail; + } + if (ssh_buffer_add_ssh_string(buffer, d) < 0) { + goto fail; + } +#else + exp = EC_KEY_get0_private_key(ec); + if (exp == NULL) { + goto fail; + } + d = ssh_make_bignum_string((BIGNUM *)exp); + if (d == NULL) { + goto fail; + } + rc = ssh_buffer_add_ssh_string(buffer, d); + if (rc < 0) { + goto fail; + } +#endif /* OPENSSL_VERSION_NUMBER */ + ssh_string_burn(d); + SSH_STRING_FREE(d); + d = NULL; + } else if (key->type == SSH_KEYTYPE_SK_ECDSA) { + /* public key can contain certificate sk information */ + rc = ssh_buffer_add_ssh_string(buffer, key->sk_application); + if (rc < 0) { + goto fail; + } + } +#if OPENSSL_VERSION_NUMBER >= 0x30000000L + OSSL_PARAM_free(params); +#endif /* OPENSSL_VERSION_NUMBER */ + break; + } +#endif /* HAVE_OPENSSL_ECC */ case SSH_KEYTYPE_UNKNOWN: default: goto fail; @@ -1393,91 +1834,25 @@ fail: SSH_STRING_FREE(q); ssh_string_burn(n); SSH_STRING_FREE(n); + ssh_string_burn(d); + SSH_STRING_FREE(d); + ssh_string_burn(iqmp); + SSH_STRING_FREE(iqmp); +#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); + bignum_safe_free(bd); + bignum_safe_free(biqmp); + OSSL_PARAM_free(params); +#endif /* OPENSSL_VERSION_NUMBER */ return NULL; } -static ssh_string pki_dsa_signature_to_blob(const ssh_signature sig) -{ - char buffer[40] = { 0 }; - ssh_string sig_blob = NULL; - const BIGNUM *pr = NULL, *ps = NULL; - - ssh_string r = NULL; - int r_len, r_offset_in, r_offset_out; - - ssh_string s = NULL; - int s_len, s_offset_in, s_offset_out; - - const unsigned char *raw_sig_data = NULL; - size_t raw_sig_len; - - DSA_SIG *dsa_sig; - - if (sig == NULL || sig->raw_sig == NULL) { - return NULL; - } - raw_sig_data = ssh_string_data(sig->raw_sig); - if (raw_sig_data == NULL) { - return NULL; - } - raw_sig_len = ssh_string_len(sig->raw_sig); - - dsa_sig = d2i_DSA_SIG(NULL, &raw_sig_data, raw_sig_len); - if (dsa_sig == NULL) { - return NULL; - } - - DSA_SIG_get0(dsa_sig, &pr, &ps); - if (pr == NULL || ps == NULL) { - goto error; - } - - r = ssh_make_bignum_string((BIGNUM *)pr); - if (r == NULL) { - goto error; - } - - s = ssh_make_bignum_string((BIGNUM *)ps); - if (s == NULL) { - goto error; - } - - r_len = ssh_string_len(r); - r_offset_in = (r_len > 20) ? (r_len - 20) : 0; - r_offset_out = (r_len < 20) ? (20 - r_len) : 0; - - s_len = ssh_string_len(s); - s_offset_in = (s_len > 20) ? (s_len - 20) : 0; - s_offset_out = (s_len < 20) ? (20 - s_len) : 0; - - memcpy(buffer + r_offset_out, - ((char *)ssh_string_data(r)) + r_offset_in, - r_len - r_offset_in); - memcpy(buffer + 20 + s_offset_out, - ((char *)ssh_string_data(s)) + s_offset_in, - s_len - s_offset_in); - - DSA_SIG_free(dsa_sig); - SSH_STRING_FREE(r); - SSH_STRING_FREE(s); - - sig_blob = ssh_string_new(40); - if (sig_blob == NULL) { - return NULL; - } - - ssh_string_fill(sig_blob, buffer, 40); - - return sig_blob; - -error: - DSA_SIG_free(dsa_sig); - SSH_STRING_FREE(r); - SSH_STRING_FREE(s); - return NULL; -} - static ssh_string pki_ecdsa_signature_to_blob(const ssh_signature sig) { ssh_string r = NULL; @@ -1544,7 +1919,10 @@ static ssh_string pki_ecdsa_signature_to_blob(const ssh_signature sig) goto error; } - ssh_string_fill(sig_blob, ssh_buffer_get(buf), ssh_buffer_get_len(buf)); + rc = ssh_string_fill(sig_blob, ssh_buffer_get(buf), ssh_buffer_get_len(buf)); + if (rc < 0) { + goto error; + } SSH_STRING_FREE(r); SSH_STRING_FREE(s); @@ -1554,6 +1932,7 @@ static ssh_string pki_ecdsa_signature_to_blob(const ssh_signature sig) return sig_blob; error: + SSH_STRING_FREE(sig_blob); SSH_STRING_FREE(r); SSH_STRING_FREE(s); ECDSA_SIG_free(ecdsa_sig); @@ -1566,9 +1945,6 @@ ssh_string pki_signature_to_blob(const ssh_signature sig) ssh_string sig_blob = NULL; switch(sig->type) { - case SSH_KEYTYPE_DSS: - sig_blob = pki_dsa_signature_to_blob(sig); - break; case SSH_KEYTYPE_RSA: case SSH_KEYTYPE_RSA1: sig_blob = ssh_string_copy(sig->raw_sig); @@ -1582,10 +1958,10 @@ 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); + SSH_LOG(SSH_LOG_TRACE, "Unknown signature key type: %s", sig->type_c); return NULL; } @@ -1604,14 +1980,25 @@ static int pki_signature_from_rsa_blob(const ssh_key pubkey, size_t rsalen = 0; size_t len = ssh_string_len(sig_blob); - if (pubkey->rsa == NULL) { - SSH_LOG(SSH_LOG_WARN, "Pubkey RSA field NULL"); +#if OPENSSL_VERSION_NUMBER < 0x30000000L + const RSA *rsa = EVP_PKEY_get0_RSA(pubkey->key); + + if (rsa == NULL) { + SSH_LOG(SSH_LOG_TRACE, "RSA field NULL"); + goto errout; + } + + rsalen = RSA_size(rsa); +#else + if (EVP_PKEY_get_base_id(pubkey->key) != EVP_PKEY_RSA) { + SSH_LOG(SSH_LOG_TRACE, "Key has no RSA pubkey"); goto errout; } - rsalen = RSA_size(pubkey->rsa); + rsalen = EVP_PKEY_size(pubkey->key); +#endif /* OPENSSL_VERSION_NUMBER */ if (len > rsalen) { - SSH_LOG(SSH_LOG_WARN, + SSH_LOG(SSH_LOG_TRACE, "Signature is too big: %lu > %lu", (unsigned long)len, (unsigned long)rsalen); @@ -1619,9 +2006,9 @@ static int pki_signature_from_rsa_blob(const ssh_key pubkey, } #ifdef DEBUG_CRYPTO - SSH_LOG(SSH_LOG_WARN, "RSA signature len: %lu", (unsigned long)len); + 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); @@ -1661,125 +2048,6 @@ errout: return SSH_ERROR; } -static int pki_signature_from_dsa_blob(UNUSED_PARAM(const ssh_key pubkey), - const ssh_string sig_blob, - ssh_signature sig) -{ - DSA_SIG *dsa_sig = NULL; - BIGNUM *pr = NULL, *ps = NULL; - - ssh_string r; - ssh_string s; - - size_t len; - - int raw_sig_len = 0; - unsigned char *raw_sig_data = NULL; - unsigned char *temp_raw_sig = NULL; - - int rc; - - len = ssh_string_len(sig_blob); - - /* 40 is the dual signature blob len. */ - if (len != 40) { - SSH_LOG(SSH_LOG_WARN, - "Signature has wrong size: %lu", - (unsigned long)len); - goto error; - } - -#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 - - r = ssh_string_new(20); - if (r == NULL) { - goto error; - } - ssh_string_fill(r, ssh_string_data(sig_blob), 20); - - pr = ssh_make_string_bn(r); - ssh_string_burn(r); - SSH_STRING_FREE(r); - if (pr == NULL) { - goto error; - } - - s = ssh_string_new(20); - if (s == NULL) { - goto error; - } - ssh_string_fill(s, (char *)ssh_string_data(sig_blob) + 20, 20); - - ps = ssh_make_string_bn(s); - ssh_string_burn(s); - SSH_STRING_FREE(s); - if (ps == NULL) { - goto error; - } - - dsa_sig = DSA_SIG_new(); - if (dsa_sig == NULL) { - goto error; - } - - /* Memory management of pr and ps is transferred to DSA signature - * object */ - rc = DSA_SIG_set0(dsa_sig, pr, ps); - if (rc == 0) { - goto error; - } - ps = NULL; - pr = NULL; - - /* Get the expected size of the buffer */ - rc = i2d_DSA_SIG(dsa_sig, NULL); - if (rc <= 0) { - goto error; - } - raw_sig_len = rc; - - raw_sig_data = (unsigned char *)calloc(1, raw_sig_len); - if (raw_sig_data == NULL) { - goto error; - } - temp_raw_sig = raw_sig_data; - - /* It is necessary to use a temporary pointer as i2d_* "advances" the - * pointer */ - raw_sig_len = i2d_DSA_SIG(dsa_sig, &temp_raw_sig); - if (raw_sig_len <= 0) { - goto error; - } - - sig->raw_sig = ssh_string_new(raw_sig_len); - if (sig->raw_sig == NULL) { - explicit_bzero(raw_sig_data, raw_sig_len); - goto error; - } - - rc = ssh_string_fill(sig->raw_sig, raw_sig_data, raw_sig_len); - if (rc < 0) { - explicit_bzero(raw_sig_data, raw_sig_len); - goto error; - } - - explicit_bzero(raw_sig_data, raw_sig_len); - SAFE_FREE(raw_sig_data); - DSA_SIG_free(dsa_sig); - - return SSH_OK; - -error: - bignum_safe_free(ps); - bignum_safe_free(pr); - SAFE_FREE(raw_sig_data); - DSA_SIG_free(dsa_sig); - return SSH_ERROR; -} - static int pki_signature_from_ecdsa_blob(UNUSED_PARAM(const ssh_key pubkey), const ssh_string sig_blob, ssh_signature sig) @@ -1838,7 +2106,7 @@ static int pki_signature_from_ecdsa_blob(UNUSED_PARAM(const ssh_key pubkey), if (rlen != 0) { ssh_string_burn(s); SSH_STRING_FREE(s); - SSH_LOG(SSH_LOG_WARN, + SSH_LOG(SSH_LOG_TRACE, "Signature has remaining bytes in inner " "sigblob: %lu", (unsigned long)rlen); @@ -1927,7 +2195,7 @@ ssh_signature pki_signature_from_blob(const ssh_key pubkey, int rc; if (ssh_key_type_plain(pubkey->type) != type) { - SSH_LOG(SSH_LOG_WARN, + SSH_LOG(SSH_LOG_TRACE, "Incompatible public key provided (%d) expecting (%d)", type, pubkey->type); @@ -1944,12 +2212,6 @@ ssh_signature pki_signature_from_blob(const ssh_key pubkey, sig->hash_type = hash_type; switch(type) { - case SSH_KEYTYPE_DSS: - rc = pki_signature_from_dsa_blob(pubkey, sig_blob, sig); - if (rc != SSH_OK) { - goto error; - } - break; case SSH_KEYTYPE_RSA: case SSH_KEYTYPE_RSA1: rc = pki_signature_from_rsa_blob(pubkey, sig_blob, sig); @@ -1981,7 +2243,7 @@ ssh_signature pki_signature_from_blob(const ssh_key pubkey, #endif default: case SSH_KEYTYPE_UNKNOWN: - SSH_LOG(SSH_LOG_WARN, "Unknown signature type"); + SSH_LOG(SSH_LOG_TRACE, "Unknown signature type"); goto error; } @@ -2024,44 +2286,12 @@ static const EVP_MD *pki_digest_to_md(enum ssh_digest_e hash_type) static EVP_PKEY *pki_key_to_pkey(ssh_key key) { EVP_PKEY *pkey = NULL; + int rc = 0; -#ifdef WITH_PKCS11_URI - if (key->flags & SSH_KEY_FLAG_PKCS11_URI) { - pkey = key->key; - return pkey; - } -#endif - - switch(key->type) { - case SSH_KEYTYPE_DSS: - case SSH_KEYTYPE_DSS_CERT01: - if (key->dsa == NULL) { - SSH_LOG(SSH_LOG_TRACE, "NULL key->dsa"); - goto error; - } - pkey = EVP_PKEY_new(); - if (pkey == NULL) { - SSH_LOG(SSH_LOG_TRACE, "Out of memory"); - return NULL; - } - - EVP_PKEY_set1_DSA(pkey, key->dsa); - break; + switch (key->type) { case SSH_KEYTYPE_RSA: case SSH_KEYTYPE_RSA1: case SSH_KEYTYPE_RSA_CERT01: - if (key->rsa == NULL) { - SSH_LOG(SSH_LOG_TRACE, "NULL key->rsa"); - goto error; - } - pkey = EVP_PKEY_new(); - if (pkey == NULL) { - SSH_LOG(SSH_LOG_TRACE, "Out of memory"); - return NULL; - } - - EVP_PKEY_set1_RSA(pkey, key->rsa); - break; case SSH_KEYTYPE_ECDSA_P256: case SSH_KEYTYPE_ECDSA_P384: case SSH_KEYTYPE_ECDSA_P521: @@ -2070,25 +2300,21 @@ static EVP_PKEY *pki_key_to_pkey(ssh_key key) case SSH_KEYTYPE_ECDSA_P521_CERT01: case SSH_KEYTYPE_SK_ECDSA: case SSH_KEYTYPE_SK_ECDSA_CERT01: -# if defined(HAVE_OPENSSL_ECC) - if (key->ecdsa == NULL) { - SSH_LOG(SSH_LOG_TRACE, "NULL key->ecdsa"); + if (key->key == NULL) { + SSH_LOG(SSH_LOG_TRACE, "NULL key->key"); goto error; } - pkey = EVP_PKEY_new(); - if (pkey == NULL) { - SSH_LOG(SSH_LOG_TRACE, "Out of memory"); + rc = EVP_PKEY_up_ref(key->key); + if (rc != 1) { + SSH_LOG(SSH_LOG_TRACE, "Failed to reference EVP_PKEY"); return NULL; } - - EVP_PKEY_set1_EC_KEY(pkey, key->ecdsa); + pkey = key->key; break; -# endif case SSH_KEYTYPE_ED25519: case SSH_KEYTYPE_ED25519_CERT01: case SSH_KEYTYPE_SK_ED25519: case SSH_KEYTYPE_SK_ED25519_CERT01: -# if defined(HAVE_OPENSSL_ED25519) if (ssh_key_is_private(key)) { if (key->ed25519_privkey == NULL) { SSH_LOG(SSH_LOG_TRACE, "NULL key->ed25519_privkey"); @@ -2116,7 +2342,6 @@ static EVP_PKEY *pki_key_to_pkey(ssh_key key) return NULL; } break; -#endif case SSH_KEYTYPE_UNKNOWN: default: SSH_LOG(SSH_LOG_TRACE, "Unknown private key algorithm for type: %d", @@ -2134,7 +2359,7 @@ error: /** * @internal * - * @brief Sign the given input data. The digest of to be signed is calculated + * @brief Sign the given input data. The digest to be signed is calculated * internally as necessary. * * @param[in] privkey The private key to be used for signing. @@ -2172,14 +2397,6 @@ ssh_signature pki_sign_data(const ssh_key privkey, return NULL; } -#ifndef HAVE_OPENSSL_ED25519 - if (privkey->type == SSH_KEYTYPE_ED25519 || - privkey->type == SSH_KEYTYPE_ED25519_CERT01) - { - return pki_do_sign_hash(privkey, input, input_len, hash_type); - } -#endif - /* Set hash algorithm to be used */ md = pki_digest_to_md(hash_type); if (md == NULL) { @@ -2203,7 +2420,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; @@ -2218,7 +2435,6 @@ ssh_signature pki_sign_data(const ssh_key privkey, goto out; } -#ifdef HAVE_OPENSSL_EVP_DIGESTSIGN rc = EVP_DigestSign(ctx, raw_sig_data, &raw_sig_len, input, input_len); if (rc != 1) { SSH_LOG(SSH_LOG_TRACE, @@ -2226,23 +2442,6 @@ ssh_signature pki_sign_data(const ssh_key privkey, ERR_error_string(ERR_get_error(), NULL)); goto out; } -#else - rc = EVP_DigestSignUpdate(ctx, input, input_len); - if (rc != 1) { - SSH_LOG(SSH_LOG_TRACE, - "EVP_DigestSignUpdate() failed: %s", - ERR_error_string(ERR_get_error(), NULL)); - goto out; - } - - rc = EVP_DigestSignFinal(ctx, raw_sig_data, &raw_sig_len); - if (rc != 1) { - SSH_LOG(SSH_LOG_TRACE, - "EVP_DigestSignFinal() failed: %s", - ERR_error_string(ERR_get_error(), NULL)); - goto out; - } -#endif #ifdef DEBUG_CRYPTO ssh_log_hexdump("Generated signature", raw_sig_data, raw_sig_len); @@ -2280,9 +2479,7 @@ out: explicit_bzero(raw_sig_data, raw_sig_len); } SAFE_FREE(raw_sig_data); - if (pkey != NULL) { - EVP_PKEY_free(pkey); - } + EVP_PKEY_free(pkey); return sig; } @@ -2311,15 +2508,15 @@ int pki_verify_data_signature(ssh_signature signature, unsigned char *raw_sig_data = NULL; unsigned int raw_sig_len; + /* Function return code + * Do not change this variable throughout the function until the signature + * is successfully verified! + */ int rc = SSH_ERROR; - int evp_rc; + int ok; if (pubkey == NULL || ssh_key_is_private(pubkey) || input == NULL || - signature == NULL || (signature->raw_sig == NULL -#ifndef HAVE_OPENSSL_ED25519 - && signature->ed25519_sig == NULL -#endif - )) + signature == NULL || signature->raw_sig == NULL) { SSH_LOG(SSH_LOG_TRACE, "Bad parameter provided to " "pki_verify_data_signature()"); @@ -2327,21 +2524,11 @@ int pki_verify_data_signature(ssh_signature signature, } /* Check if public key and hash type are compatible */ - rc = pki_key_check_hash_compatible(pubkey, signature->hash_type); - if (rc != SSH_OK) { + ok = pki_key_check_hash_compatible(pubkey, signature->hash_type); + if (ok != SSH_OK) { return SSH_ERROR; } -#ifndef HAVE_OPENSSL_ED25519 - if (pubkey->type == SSH_KEYTYPE_ED25519 || - pubkey->type == SSH_KEYTYPE_ED25519_CERT01 || - pubkey->type == SSH_KEYTYPE_SK_ED25519 || - pubkey->type == SSH_KEYTYPE_SK_ED25519_CERT01) - { - return pki_ed25519_verify(pubkey, signature, input, input_len); - } -#endif - /* Get the signature to be verified */ raw_sig_data = ssh_string_data(signature->raw_sig); raw_sig_len = ssh_string_len(signature->raw_sig); @@ -2364,7 +2551,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", @@ -2373,48 +2560,69 @@ int pki_verify_data_signature(ssh_signature signature, } /* Verify the signature */ - evp_rc = EVP_DigestVerifyInit(ctx, NULL, md, NULL, pkey); - if (evp_rc != 1){ + ok = EVP_DigestVerifyInit(ctx, NULL, md, NULL, pkey); + if (ok != 1){ SSH_LOG(SSH_LOG_TRACE, "EVP_DigestVerifyInit() failed: %s", ERR_error_string(ERR_get_error(), NULL)); goto out; } -#ifdef HAVE_OPENSSL_EVP_DIGESTVERIFY - evp_rc = EVP_DigestVerify(ctx, raw_sig_data, raw_sig_len, input, input_len); -#else - evp_rc = EVP_DigestVerifyUpdate(ctx, input, input_len); - if (evp_rc != 1) { + ok = EVP_DigestVerify(ctx, raw_sig_data, raw_sig_len, input, input_len); + if (ok != 1) { SSH_LOG(SSH_LOG_TRACE, - "EVP_DigestVerifyUpdate() failed: %s", + "Signature invalid: %s", ERR_error_string(ERR_get_error(), NULL)); goto out; } - evp_rc = EVP_DigestVerifyFinal(ctx, raw_sig_data, raw_sig_len); -#endif - if (evp_rc == 1) { - SSH_LOG(SSH_LOG_TRACE, "Signature valid"); - rc = SSH_OK; - } else { - SSH_LOG(SSH_LOG_TRACE, - "Signature invalid: %s", - ERR_error_string(ERR_get_error(), NULL)); - rc = SSH_ERROR; - } + SSH_LOG(SSH_LOG_TRACE, "Signature valid"); + rc = SSH_OK; out: - if (ctx != NULL) { - EVP_MD_CTX_free(ctx); - } - if (pkey != NULL) { + EVP_MD_CTX_free(ctx); + EVP_PKEY_free(pkey); + return rc; +} + +int ssh_key_size(ssh_key key) +{ + int bits = 0; + EVP_PKEY *pkey = NULL; + + switch (key->type) { + case SSH_KEYTYPE_RSA: + case SSH_KEYTYPE_RSA_CERT01: + case SSH_KEYTYPE_RSA1: + case SSH_KEYTYPE_ECDSA_P256: + case SSH_KEYTYPE_ECDSA_P256_CERT01: + case SSH_KEYTYPE_ECDSA_P384: + case SSH_KEYTYPE_ECDSA_P384_CERT01: + case SSH_KEYTYPE_ECDSA_P521: + case SSH_KEYTYPE_ECDSA_P521_CERT01: + case SSH_KEYTYPE_SK_ECDSA: + case SSH_KEYTYPE_SK_ECDSA_CERT01: + pkey = pki_key_to_pkey(key); + if (pkey == NULL) { + return SSH_ERROR; + } + bits = EVP_PKEY_bits(pkey); EVP_PKEY_free(pkey); + return bits; + case SSH_KEYTYPE_ED25519: + case SSH_KEYTYPE_ED25519_CERT01: + case SSH_KEYTYPE_SK_ED25519: + case SSH_KEYTYPE_SK_ED25519_CERT01: + /* ed25519 keys have fixed size */ + return 255; + case SSH_KEYTYPE_DSS: /* deprecated */ + case SSH_KEYTYPE_DSS_CERT01: /* deprecated */ + case SSH_KEYTYPE_UNKNOWN: + default: + return SSH_ERROR; } - return rc; } -#ifdef HAVE_OPENSSL_ED25519 int pki_key_generate_ed25519(ssh_key key) { int evp_rc; @@ -2499,50 +2707,21 @@ error: return SSH_ERROR; } -#else -ssh_signature pki_do_sign_hash(const ssh_key privkey, - const unsigned char *hash, - size_t hlen, - enum ssh_digest_e hash_type) -{ - ssh_signature sig = NULL; - int rc; - - sig = ssh_signature_new(); - if (sig == NULL) { - return NULL; - } - - sig->type = privkey->type; - sig->type_c = ssh_key_signature_to_char(privkey->type, hash_type); - sig->hash_type = hash_type; - switch(privkey->type) { - case SSH_KEYTYPE_ED25519: - rc = pki_ed25519_sign(privkey, sig, hash, hlen); - if (rc != SSH_OK) { - ssh_signature_free(sig); - return NULL; - } - break; - default: - ssh_signature_free(sig); - return NULL; - } - - return sig; -} -#endif /* HAVE_OPENSSL_ED25519 */ +#ifdef WITH_PKCS11_URI +#ifdef WITH_PKCS11_PROVIDER +static bool pkcs11_provider_failed = false; +#endif /** * @internal * - * @brief Populate the public/private ssh_key from the engine with + * @brief Populate the public/private ssh_key from the engine/provider with * PKCS#11 URIs as the look up. * * @param[in] uri_name The PKCS#11 URI * @param[in] nkey The ssh-key context for - * the key loaded from the engine. + * the key loaded from the engine/provider. * @param[in] key_type The type of the key used. Public/Private. * * @return SSH_OK if ssh-key is valid; SSH_ERROR otherwise. @@ -2551,64 +2730,112 @@ int pki_uri_import(const char *uri_name, ssh_key *nkey, enum ssh_key_e key_type) { - ENGINE *engine = NULL; EVP_PKEY *pkey = NULL; - RSA *rsa = NULL; ssh_key key = NULL; enum ssh_keytypes_e type = SSH_KEYTYPE_UNKNOWN; -#ifdef HAVE_OPENSSL_ECC +#if OPENSSL_VERSION_NUMBER < 0x30000000L && HAVE_OPENSSL_ECC EC_KEY *ecdsa = NULL; -#else - void *ecdsa = NULL; #endif - int ok; - - ENGINE_load_builtin_engines(); +#ifndef WITH_PKCS11_PROVIDER + ENGINE *engine = NULL; - engine = ENGINE_by_id("pkcs11"); + /* Do the init only once */ + engine = pki_get_engine(); if (engine == NULL) { - SSH_LOG(SSH_LOG_WARN, - "Could not load the engine: %s", - ERR_error_string(ERR_get_error(),NULL)); - return SSH_ERROR; - } - SSH_LOG(SSH_LOG_INFO, "Engine loaded successfully"); - - ok = ENGINE_init(engine); - if (!ok) { - SSH_LOG(SSH_LOG_WARN, - "Could not initialize the engine: %s", - ERR_error_string(ERR_get_error(),NULL)); - ENGINE_free(engine); - return SSH_ERROR; + SSH_LOG(SSH_LOG_TRACE, "Failed to initialize engine"); + goto fail; } - SSH_LOG(SSH_LOG_INFO, "Engine init success"); - switch (key_type) { case SSH_KEY_PRIVATE: pkey = ENGINE_load_private_key(engine, uri_name, NULL, NULL); if (pkey == NULL) { - SSH_LOG(SSH_LOG_WARN, + SSH_LOG(SSH_LOG_TRACE, "Could not load key: %s", - ERR_error_string(ERR_get_error(),NULL)); + ERR_error_string(ERR_get_error(), NULL)); goto fail; } break; case SSH_KEY_PUBLIC: pkey = ENGINE_load_public_key(engine, uri_name, NULL, NULL); if (pkey == NULL) { - SSH_LOG(SSH_LOG_WARN, + SSH_LOG(SSH_LOG_TRACE, "Could not load key: %s", - ERR_error_string(ERR_get_error(),NULL)); + ERR_error_string(ERR_get_error(), NULL)); goto fail; } break; default: - SSH_LOG(SSH_LOG_WARN, + SSH_LOG(SSH_LOG_TRACE, "Invalid key type: %d", key_type); goto fail; } +#else /* WITH_PKCS11_PROVIDER */ + OSSL_STORE_CTX *store = NULL; + OSSL_STORE_INFO *info = NULL; + int rv, expect_type = OSSL_STORE_INFO_PKEY; + + /* The provider can be either configured in openssl.cnf or dynamically + * loaded, assuming it does not need any special configuration */ + if (OSSL_PROVIDER_available(NULL, "pkcs11") == 0 && + !pkcs11_provider_failed) { + OSSL_PROVIDER *pkcs11_provider = NULL; + + pkcs11_provider = OSSL_PROVIDER_try_load(NULL, "pkcs11", 1); + if (pkcs11_provider == NULL) { + SSH_LOG(SSH_LOG_TRACE, + "Failed to initialize provider: %s", + ERR_error_string(ERR_get_error(), NULL)); + /* Do not attempt to load it again */ + pkcs11_provider_failed = true; + goto fail; + } + } + + store = OSSL_STORE_open(uri_name, NULL, NULL, NULL, NULL); + if (store == NULL) { + SSH_LOG(SSH_LOG_TRACE, + "Failed to open OpenSSL store: %s", + ERR_error_string(ERR_get_error(), NULL)); + goto fail; + } + if (key_type == SSH_KEY_PUBLIC) { + expect_type = OSSL_STORE_INFO_PUBKEY; + } + rv = OSSL_STORE_expect(store, expect_type); + if (rv != 1) { + SSH_LOG(SSH_LOG_TRACE, + "Failed to set the store preference. Ignoring the error: %s", + ERR_error_string(ERR_get_error(), NULL)); + } + + for (info = OSSL_STORE_load(store); + info != NULL; + info = OSSL_STORE_load(store)) { + int ossl_type = OSSL_STORE_INFO_get_type(info); + + if (ossl_type == OSSL_STORE_INFO_PUBKEY && key_type == SSH_KEY_PUBLIC) { + pkey = OSSL_STORE_INFO_get1_PUBKEY(info); + break; + } else if (ossl_type == OSSL_STORE_INFO_PKEY && + key_type == SSH_KEY_PRIVATE) { + pkey = OSSL_STORE_INFO_get1_PKEY(info); + break; + } else { + SSH_LOG(SSH_LOG_TRACE, + "Ignoring object not matching our type: %d", + ossl_type); + } + } + OSSL_STORE_close(store); + if (pkey == NULL) { + SSH_LOG(SSH_LOG_TRACE, + "No key found in the pkcs11 store: %s", + ERR_error_string(ERR_get_error(), NULL)); + goto fail; + } + +#endif /* WITH_PKCS11_PROVIDER */ key = ssh_key_new(); if (key == NULL) { @@ -2617,20 +2844,14 @@ int pki_uri_import(const char *uri_name, switch (EVP_PKEY_base_id(pkey)) { case EVP_PKEY_RSA: - rsa = EVP_PKEY_get1_RSA(pkey); - if (rsa == NULL) { - SSH_LOG(SSH_LOG_WARN, - "Parsing pub key: %s", - ERR_error_string(ERR_get_error(),NULL)); - goto fail; - } type = SSH_KEYTYPE_RSA; break; case EVP_PKEY_EC: #ifdef HAVE_OPENSSL_ECC - ecdsa = EVP_PKEY_get1_EC_KEY(pkey); +#if OPENSSL_VERSION_NUMBER < 0x30000000L + ecdsa = EVP_PKEY_get0_EC_KEY(pkey); if (ecdsa == NULL) { - SSH_LOG(SSH_LOG_WARN, + SSH_LOG(SSH_LOG_TRACE, "Parsing pub key: %s", ERR_error_string(ERR_get_error(), NULL)); goto fail; @@ -2639,15 +2860,18 @@ 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."); + SSH_LOG(SSH_LOG_TRACE, "Invalid pub key."); goto fail; } break; #endif default: - SSH_LOG(SSH_LOG_WARN, "Unknown or invalid public key type %d", + SSH_LOG(SSH_LOG_TRACE, "Unknown or invalid public key type %d", EVP_PKEY_base_id(pkey)); goto fail; } @@ -2655,36 +2879,30 @@ int pki_uri_import(const char *uri_name, key->key = pkey; key->type = type; key->type_c = ssh_key_type_to_char(type); + key->flags = SSH_KEY_FLAG_PUBLIC | SSH_KEY_FLAG_PKCS11_URI; if (key_type == SSH_KEY_PRIVATE) { - key->flags = SSH_KEY_FLAG_PUBLIC | SSH_KEY_FLAG_PRIVATE | SSH_KEY_FLAG_PKCS11_URI; - } else { - key->flags = SSH_KEY_FLAG_PUBLIC | SSH_KEY_FLAG_PKCS11_URI; + key->flags |= SSH_KEY_FLAG_PRIVATE; } - key->rsa = rsa; - key->ecdsa = ecdsa; #ifdef HAVE_OPENSSL_ECC if (is_ecdsa_key_type(key->type)) { - key->ecdsa_nid = pki_key_ecdsa_to_nid(key->ecdsa); +#if OPENSSL_VERSION_NUMBER < 0x30000000L + key->ecdsa_nid = pki_key_ecdsa_to_nid(ecdsa); +#else + key->ecdsa_nid = pki_key_ecdsa_to_nid(key->key); +#endif /* OPENSSL_VERSION_NUMBER */ } #endif *nkey = key; - ENGINE_finish(engine); - ENGINE_free(engine); return SSH_OK; fail: - ENGINE_finish(engine); - ENGINE_free(engine); EVP_PKEY_free(pkey); ssh_key_free(key); - RSA_free(rsa); -#ifdef HAVE_OPENSSL_ECC - EC_KEY_free(ecdsa); -#endif return SSH_ERROR; } +#endif /* WITH_PKCS11_URI */ #endif /* _PKI_CRYPTO_H */ |