aboutsummaryrefslogtreecommitdiff
path: root/src/pki_crypto.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/pki_crypto.c')
-rw-r--r--src/pki_crypto.c2162
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", &parameter);
+ 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, &params);
+ 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, &params);
+ 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, &params);
+ 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, &params);
+ 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 */