version 1.14, 2018/04/06 18:59:00 |
version 1.14.2.1, 2019/06/10 21:41:12 |
|
|
/* $NetBSD$ */ |
/* $NetBSD$ */ |
/* $OpenBSD: sshkey.c,v 1.64 2018/03/22 07:05:48 markus Exp $ */ |
/* $OpenBSD: sshkey.c,v 1.73 2019/01/21 09:54:11 djm Exp $ */ |
/* |
/* |
* Copyright (c) 2000, 2001 Markus Friedl. All rights reserved. |
* Copyright (c) 2000, 2001 Markus Friedl. All rights reserved. |
* Copyright (c) 2008 Alexander von Gernler. All rights reserved. |
* Copyright (c) 2008 Alexander von Gernler. All rights reserved. |
Line 77 int sshkey_private_serialize_opt(const s |
|
Line 77 int sshkey_private_serialize_opt(const s |
|
struct sshbuf *buf, enum sshkey_serialize_rep); |
struct sshbuf *buf, enum sshkey_serialize_rep); |
static int sshkey_from_blob_internal(struct sshbuf *buf, |
static int sshkey_from_blob_internal(struct sshbuf *buf, |
struct sshkey **keyp, int allow_cert); |
struct sshkey **keyp, int allow_cert); |
|
static int get_sigtype(const u_char *sig, size_t siglen, char **sigtypep); |
|
|
/* Supported key types */ |
/* Supported key types */ |
struct keytype { |
struct keytype { |
const char *name; |
const char *name; |
const char *shortname; |
const char *shortname; |
|
const char *sigalg; |
int type; |
int type; |
int nid; |
int nid; |
int cert; |
int cert; |
int sigonly; |
int sigonly; |
}; |
}; |
static const struct keytype keytypes[] = { |
static const struct keytype keytypes[] = { |
{ "ssh-ed25519", "ED25519", KEY_ED25519, 0, 0, 0 }, |
{ "ssh-ed25519", "ED25519", NULL, KEY_ED25519, 0, 0, 0 }, |
{ "ssh-ed25519-cert-v01@openssh.com", "ED25519-CERT", |
{ "ssh-ed25519-cert-v01@openssh.com", "ED25519-CERT", NULL, |
KEY_ED25519_CERT, 0, 1, 0 }, |
KEY_ED25519_CERT, 0, 1, 0 }, |
#ifdef WITH_XMSS |
#ifdef WITH_XMSS |
{ "ssh-xmss@openssh.com", "XMSS", KEY_XMSS, 0, 0, 0 }, |
{ "ssh-xmss@openssh.com", "XMSS", NULL, KEY_XMSS, 0, 0, 0 }, |
{ "ssh-xmss-cert-v01@openssh.com", "XMSS-CERT", |
{ "ssh-xmss-cert-v01@openssh.com", "XMSS-CERT", NULL, |
KEY_XMSS_CERT, 0, 1, 0 }, |
KEY_XMSS_CERT, 0, 1, 0 }, |
#endif /* WITH_XMSS */ |
#endif /* WITH_XMSS */ |
#ifdef WITH_OPENSSL |
#ifdef WITH_OPENSSL |
{ "ssh-rsa", "RSA", KEY_RSA, 0, 0, 0 }, |
{ "ssh-rsa", "RSA", NULL, KEY_RSA, 0, 0, 0 }, |
{ "rsa-sha2-256", "RSA", KEY_RSA, 0, 0, 1 }, |
{ "rsa-sha2-256", "RSA", NULL, KEY_RSA, 0, 0, 1 }, |
{ "rsa-sha2-512", "RSA", KEY_RSA, 0, 0, 1 }, |
{ "rsa-sha2-512", "RSA", NULL, KEY_RSA, 0, 0, 1 }, |
{ "ssh-dss", "DSA", KEY_DSA, 0, 0, 0 }, |
{ "ssh-dss", "DSA", NULL, KEY_DSA, 0, 0, 0 }, |
{ "ecdsa-sha2-nistp256", "ECDSA", KEY_ECDSA, NID_X9_62_prime256v1, 0, 0 }, |
{ "ecdsa-sha2-nistp256", "ECDSA", NULL, |
{ "ecdsa-sha2-nistp384", "ECDSA", KEY_ECDSA, NID_secp384r1, 0, 0 }, |
KEY_ECDSA, NID_X9_62_prime256v1, 0, 0 }, |
{ "ecdsa-sha2-nistp521", "ECDSA", KEY_ECDSA, NID_secp521r1, 0, 0 }, |
{ "ecdsa-sha2-nistp384", "ECDSA", NULL, |
{ "ssh-rsa-cert-v01@openssh.com", "RSA-CERT", KEY_RSA_CERT, 0, 1, 0 }, |
KEY_ECDSA, NID_secp384r1, 0, 0 }, |
{ "ssh-dss-cert-v01@openssh.com", "DSA-CERT", KEY_DSA_CERT, 0, 1, 0 }, |
{ "ecdsa-sha2-nistp521", "ECDSA", NULL, |
{ "ecdsa-sha2-nistp256-cert-v01@openssh.com", "ECDSA-CERT", |
KEY_ECDSA, NID_secp521r1, 0, 0 }, |
|
{ "ssh-rsa-cert-v01@openssh.com", "RSA-CERT", NULL, |
|
KEY_RSA_CERT, 0, 1, 0 }, |
|
{ "rsa-sha2-256-cert-v01@openssh.com", "RSA-CERT", |
|
"rsa-sha2-256", KEY_RSA_CERT, 0, 1, 1 }, |
|
{ "rsa-sha2-512-cert-v01@openssh.com", "RSA-CERT", |
|
"rsa-sha2-512", KEY_RSA_CERT, 0, 1, 1 }, |
|
{ "ssh-dss-cert-v01@openssh.com", "DSA-CERT", NULL, |
|
KEY_DSA_CERT, 0, 1, 0 }, |
|
{ "ecdsa-sha2-nistp256-cert-v01@openssh.com", "ECDSA-CERT", NULL, |
KEY_ECDSA_CERT, NID_X9_62_prime256v1, 1, 0 }, |
KEY_ECDSA_CERT, NID_X9_62_prime256v1, 1, 0 }, |
{ "ecdsa-sha2-nistp384-cert-v01@openssh.com", "ECDSA-CERT", |
{ "ecdsa-sha2-nistp384-cert-v01@openssh.com", "ECDSA-CERT", NULL, |
KEY_ECDSA_CERT, NID_secp384r1, 1, 0 }, |
KEY_ECDSA_CERT, NID_secp384r1, 1, 0 }, |
{ "ecdsa-sha2-nistp521-cert-v01@openssh.com", "ECDSA-CERT", |
{ "ecdsa-sha2-nistp521-cert-v01@openssh.com", "ECDSA-CERT", NULL, |
KEY_ECDSA_CERT, NID_secp521r1, 1, 0 }, |
KEY_ECDSA_CERT, NID_secp521r1, 1, 0 }, |
#endif /* WITH_OPENSSL */ |
#endif /* WITH_OPENSSL */ |
{ NULL, NULL, -1, -1, 0, 0 } |
{ NULL, NULL, NULL, -1, -1, 0, 0 } |
}; |
}; |
|
|
const char * |
const char * |
Line 261 sshkey_names_valid2(const char *names, i |
|
Line 272 sshkey_names_valid2(const char *names, i |
|
u_int |
u_int |
sshkey_size(const struct sshkey *k) |
sshkey_size(const struct sshkey *k) |
{ |
{ |
|
#ifdef WITH_OPENSSL |
|
const BIGNUM *rsa_n, *dsa_p; |
|
#endif /* WITH_OPENSSL */ |
|
|
switch (k->type) { |
switch (k->type) { |
#ifdef WITH_OPENSSL |
#ifdef WITH_OPENSSL |
case KEY_RSA: |
case KEY_RSA: |
case KEY_RSA_CERT: |
case KEY_RSA_CERT: |
#if OPENSSL_VERSION_NUMBER >= 0x10100000UL |
if (k->rsa == NULL) |
return RSA_bits(k->rsa); |
return 0; |
#else |
RSA_get0_key(k->rsa, &rsa_n, NULL, NULL); |
return BN_num_bits(k->rsa->n); |
return BN_num_bits(rsa_n); |
#endif |
|
case KEY_DSA: |
case KEY_DSA: |
case KEY_DSA_CERT: |
case KEY_DSA_CERT: |
#if OPENSSL_VERSION_NUMBER >= 0x10100000UL |
if (k->dsa == NULL) |
return DSA_bits(k->dsa); |
return 0; |
#else |
DSA_get0_pqg(k->dsa, &dsa_p, NULL, NULL); |
return BN_num_bits(k->dsa->p); |
return BN_num_bits(dsa_p); |
#endif |
|
case KEY_ECDSA: |
case KEY_ECDSA: |
case KEY_ECDSA_CERT: |
case KEY_ECDSA_CERT: |
return sshkey_curve_nid_to_bits(k->ecdsa_nid); |
return sshkey_curve_nid_to_bits(k->ecdsa_nid); |
Line 426 cert_free(struct sshkey_cert *cert) |
|
Line 439 cert_free(struct sshkey_cert *cert) |
|
free(cert->principals[i]); |
free(cert->principals[i]); |
free(cert->principals); |
free(cert->principals); |
sshkey_free(cert->signature_key); |
sshkey_free(cert->signature_key); |
|
free(cert->signature_type); |
freezero(cert, sizeof(*cert)); |
freezero(cert, sizeof(*cert)); |
} |
} |
|
|
|
|
cert->key_id = NULL; |
cert->key_id = NULL; |
cert->principals = NULL; |
cert->principals = NULL; |
cert->signature_key = NULL; |
cert->signature_key = NULL; |
|
cert->signature_type = NULL; |
return cert; |
return cert; |
} |
} |
|
|
Line 473 sshkey_new(int type) |
|
Line 488 sshkey_new(int type) |
|
#ifdef WITH_OPENSSL |
#ifdef WITH_OPENSSL |
case KEY_RSA: |
case KEY_RSA: |
case KEY_RSA_CERT: |
case KEY_RSA_CERT: |
{ |
if ((rsa = RSA_new()) == NULL) { |
BIGNUM *n=NULL, *e=NULL; /* just allocate */ |
|
if ((rsa = RSA_new()) == NULL || |
|
(n = BN_new()) == NULL || |
|
(e = BN_new()) == NULL) { |
|
BN_free(n); |
|
BN_free(e); |
|
if (rsa != NULL) |
|
RSA_free(rsa); |
|
free(k); |
free(k); |
return NULL; |
return NULL; |
} |
} |
BN_clear(n); BN_clear(e); |
|
if (RSA_set0_key(rsa, n, e, NULL) == 0) |
|
return NULL; |
|
n = e = NULL; |
|
} |
|
k->rsa = rsa; |
k->rsa = rsa; |
break; |
break; |
case KEY_DSA: |
case KEY_DSA: |
case KEY_DSA_CERT: |
case KEY_DSA_CERT: |
{ |
if ((dsa = DSA_new()) == NULL) { |
BIGNUM *p=NULL, *q=NULL, *g=NULL, *pubkey=NULL; /* just allocate */ |
|
if ((dsa = DSA_new()) == NULL || |
|
(p = BN_new()) == NULL || |
|
(q = BN_new()) == NULL || |
|
(g = BN_new()) == NULL || |
|
(pubkey = BN_new()) == NULL) { |
|
BN_free(p); |
|
BN_free(q); |
|
BN_free(g); |
|
BN_free(pubkey); |
|
if (dsa != NULL) |
|
DSA_free(dsa); |
|
free(k); |
free(k); |
return NULL; |
return NULL; |
} |
} |
if (DSA_set0_pqg(dsa, p, q, g) == 0) { |
|
BN_free(p); BN_free(q); BN_free(g); |
|
BN_free(pubkey); |
|
return NULL; |
|
} |
|
p = q = g = NULL; |
|
if (DSA_set0_key(dsa, pubkey, NULL) == 0) { |
|
BN_free(pubkey); |
|
return NULL; |
|
} |
|
pubkey = NULL; |
|
} |
|
k->dsa = dsa; |
k->dsa = dsa; |
break; |
break; |
case KEY_ECDSA: |
case KEY_ECDSA: |
Line 552 sshkey_new(int type) |
|
Line 530 sshkey_new(int type) |
|
return k; |
return k; |
} |
} |
|
|
int |
|
sshkey_add_private(struct sshkey *k) |
|
{ |
|
switch (k->type) { |
|
#ifdef WITH_OPENSSL |
|
case KEY_RSA: |
|
case KEY_RSA_CERT: |
|
#if OPENSSL_VERSION_NUMBER >= 0x10100000UL |
|
/* Allocate BIGNUM. This is a mess. |
|
For OpenSSL 1.1.x API these shouldn't be mandatory, |
|
but some regression tests for non-NULL pointer of |
|
the data. */ |
|
#define new_or_dup(bn, nbn) \ |
|
if (bn == NULL) { \ |
|
if ((nbn = BN_new()) == NULL) \ |
|
return SSH_ERR_ALLOC_FAIL; \ |
|
} else { \ |
|
/* otherwise use-after-free will occur */ \ |
|
if ((nbn = BN_dup(bn)) == NULL) \ |
|
return SSH_ERR_ALLOC_FAIL; \ |
|
} |
|
{ |
|
const BIGNUM *d, *iqmp, *q, *p, *dmq1, *dmp1; /* allocate if NULL */ |
|
BIGNUM *nd, *niqmp, *nq, *np, *ndmq1, *ndmp1; |
|
|
|
RSA_get0_key(k->rsa, NULL, NULL, &d); |
|
RSA_get0_factors(k->rsa, &p, &q); |
|
RSA_get0_crt_params(k->rsa, &dmp1, &dmq1, &iqmp); |
|
|
|
new_or_dup(d, nd); |
|
new_or_dup(iqmp, niqmp); |
|
new_or_dup(q, nq); |
|
new_or_dup(p, np); |
|
new_or_dup(dmq1, ndmq1); |
|
new_or_dup(dmp1, ndmp1); |
|
|
|
if (RSA_set0_key(k->rsa, NULL, NULL, nd) == 0) |
|
goto error1; |
|
nd = NULL; |
|
if (RSA_set0_factors(k->rsa, np, nq) == 0) |
|
goto error1; |
|
np = nq = NULL; |
|
if (RSA_set0_crt_params(k->rsa, ndmp1, ndmq1, niqmp) == 0) { |
|
error1: |
|
BN_free(nd); |
|
BN_free(np); BN_free(nq); |
|
BN_free(ndmp1); BN_free(ndmq1); BN_free(niqmp); |
|
return SSH_ERR_LIBCRYPTO_ERROR; |
|
} |
|
ndmp1 = ndmq1 = niqmp = NULL; |
|
} |
|
#else |
|
#define bn_maybe_alloc_failed(p) (p == NULL && (p = BN_new()) == NULL) |
|
if (bn_maybe_alloc_failed(k->rsa->d) || |
|
bn_maybe_alloc_failed(k->rsa->iqmp) || |
|
bn_maybe_alloc_failed(k->rsa->q) || |
|
bn_maybe_alloc_failed(k->rsa->p) || |
|
bn_maybe_alloc_failed(k->rsa->dmq1) || |
|
bn_maybe_alloc_failed(k->rsa->dmp1)) |
|
return SSH_ERR_ALLOC_FAIL; |
|
#endif |
|
break; |
|
case KEY_DSA: |
|
case KEY_DSA_CERT: |
|
#if OPENSSL_VERSION_NUMBER >= 0x10100000UL |
|
{ |
|
const BIGNUM *priv_key; |
|
BIGNUM *npriv_key; |
|
DSA_get0_key(k->dsa, NULL, &priv_key); |
|
new_or_dup(priv_key, npriv_key); |
|
if (DSA_set0_key(k->dsa, NULL, npriv_key) == 0) { |
|
BN_free(npriv_key); |
|
return SSH_ERR_LIBCRYPTO_ERROR; |
|
} |
|
} |
|
#else |
|
if (bn_maybe_alloc_failed(k->dsa->priv_key)) |
|
return SSH_ERR_ALLOC_FAIL; |
|
#endif |
|
break; |
|
#undef bn_maybe_alloc_failed |
|
#undef new_or_dup |
|
case KEY_ECDSA: |
|
case KEY_ECDSA_CERT: |
|
/* Cannot do anything until we know the group */ |
|
break; |
|
#endif /* WITH_OPENSSL */ |
|
case KEY_ED25519: |
|
case KEY_ED25519_CERT: |
|
case KEY_XMSS: |
|
case KEY_XMSS_CERT: |
|
/* no need to prealloc */ |
|
break; |
|
case KEY_UNSPEC: |
|
break; |
|
default: |
|
return SSH_ERR_INVALID_ARGUMENT; |
|
} |
|
return 0; |
|
} |
|
|
|
struct sshkey * |
|
sshkey_new_private(int type) |
|
{ |
|
struct sshkey *k = sshkey_new(type); |
|
|
|
if (k == NULL) |
|
return NULL; |
|
if (sshkey_add_private(k) != 0) { |
|
sshkey_free(k); |
|
return NULL; |
|
} |
|
return k; |
|
} |
|
|
|
void |
void |
sshkey_free(struct sshkey *k) |
sshkey_free(struct sshkey *k) |
{ |
{ |
Line 745 sshkey_equal_public(const struct sshkey |
|
Line 608 sshkey_equal_public(const struct sshkey |
|
{ |
{ |
#ifdef WITH_OPENSSL |
#ifdef WITH_OPENSSL |
BN_CTX *bnctx; |
BN_CTX *bnctx; |
|
const BIGNUM *rsa_e_a, *rsa_n_a; |
|
const BIGNUM *rsa_e_b, *rsa_n_b; |
|
const BIGNUM *dsa_p_a, *dsa_q_a, *dsa_g_a, *dsa_pub_key_a; |
|
const BIGNUM *dsa_p_b, *dsa_q_b, *dsa_g_b, *dsa_pub_key_b; |
#endif /* WITH_OPENSSL */ |
#endif /* WITH_OPENSSL */ |
|
|
if (a == NULL || b == NULL || |
if (a == NULL || b == NULL || |
Line 755 sshkey_equal_public(const struct sshkey |
|
Line 622 sshkey_equal_public(const struct sshkey |
|
#ifdef WITH_OPENSSL |
#ifdef WITH_OPENSSL |
case KEY_RSA_CERT: |
case KEY_RSA_CERT: |
case KEY_RSA: |
case KEY_RSA: |
{ |
if (a->rsa == NULL || b->rsa == NULL) |
const BIGNUM *a_e, *b_e, *a_n, *b_n; |
return 0; |
const BIGNUM *a_d, *b_d; |
RSA_get0_key(a->rsa, &rsa_n_a, &rsa_e_a, NULL); |
if (a->rsa == NULL) return 0; |
RSA_get0_key(b->rsa, &rsa_n_b, &rsa_e_b, NULL); |
if (b->rsa == NULL) return 0; |
return BN_cmp(rsa_e_a, rsa_e_b) == 0 && |
RSA_get0_key(a->rsa, &a_n, &a_e, &a_d); |
BN_cmp(rsa_n_a, rsa_n_b) == 0; |
RSA_get0_key(b->rsa, &b_n, &b_e, &b_d); |
|
return |
|
BN_cmp(a_e, b_e) == 0 && |
|
BN_cmp(a_n, b_n) == 0; |
|
} |
|
case KEY_DSA_CERT: |
case KEY_DSA_CERT: |
case KEY_DSA: |
case KEY_DSA: |
{ |
if (a->dsa == NULL || b->dsa == NULL) |
const BIGNUM *a_p, *a_q, *a_g, *a_pub_key; |
return 0; |
const BIGNUM *b_p, *b_q, *b_g, *b_pub_key; |
DSA_get0_pqg(a->dsa, &dsa_p_a, &dsa_q_a, &dsa_g_a); |
if (a->dsa == NULL) return 0; |
DSA_get0_pqg(b->dsa, &dsa_p_b, &dsa_q_b, &dsa_g_b); |
if (b->dsa == NULL) return 0; |
DSA_get0_key(a->dsa, &dsa_pub_key_a, NULL); |
DSA_get0_pqg(a->dsa, &a_p, &a_q, &a_g); |
DSA_get0_key(b->dsa, &dsa_pub_key_b, NULL); |
DSA_get0_pqg(b->dsa, &b_p, &b_q, &b_g); |
return BN_cmp(dsa_p_a, dsa_p_b) == 0 && |
DSA_get0_key(a->dsa, &a_pub_key, NULL); |
BN_cmp(dsa_q_a, dsa_q_b) == 0 && |
DSA_get0_key(b->dsa, &b_pub_key, NULL); |
BN_cmp(dsa_g_a, dsa_g_b) == 0 && |
return |
BN_cmp(dsa_pub_key_a, dsa_pub_key_b) == 0; |
BN_cmp(a_p, b_p) == 0 && |
|
BN_cmp(a_q, b_q) == 0 && |
|
BN_cmp(a_g, b_g) == 0 && |
|
BN_cmp(a_pub_key, b_pub_key) == 0; |
|
} |
|
case KEY_ECDSA_CERT: |
case KEY_ECDSA_CERT: |
case KEY_ECDSA: |
case KEY_ECDSA: |
if (a->ecdsa == NULL || b->ecdsa == NULL || |
if (a->ecdsa == NULL || b->ecdsa == NULL || |
Line 837 to_blob_buf(const struct sshkey *key, st |
|
Line 694 to_blob_buf(const struct sshkey *key, st |
|
{ |
{ |
int type, ret = SSH_ERR_INTERNAL_ERROR; |
int type, ret = SSH_ERR_INTERNAL_ERROR; |
const char *typename; |
const char *typename; |
|
#ifdef WITH_OPENSSL |
|
const BIGNUM *rsa_n, *rsa_e, *dsa_p, *dsa_q, *dsa_g, *dsa_pub_key; |
|
#endif /* WITH_OPENSSL */ |
|
|
if (key == NULL) |
if (key == NULL) |
return SSH_ERR_INVALID_ARGUMENT; |
return SSH_ERR_INVALID_ARGUMENT; |
Line 869 to_blob_buf(const struct sshkey *key, st |
|
Line 729 to_blob_buf(const struct sshkey *key, st |
|
case KEY_DSA: |
case KEY_DSA: |
if (key->dsa == NULL) |
if (key->dsa == NULL) |
return SSH_ERR_INVALID_ARGUMENT; |
return SSH_ERR_INVALID_ARGUMENT; |
{ |
DSA_get0_pqg(key->dsa, &dsa_p, &dsa_q, &dsa_g); |
const BIGNUM *p, *q, *g, *pub_key; |
DSA_get0_key(key->dsa, &dsa_pub_key, NULL); |
DSA_get0_pqg(key->dsa, &p, &q, &g); |
|
DSA_get0_key(key->dsa, &pub_key, NULL); |
|
if ((ret = sshbuf_put_cstring(b, typename)) != 0 || |
if ((ret = sshbuf_put_cstring(b, typename)) != 0 || |
(ret = sshbuf_put_bignum2(b, p)) != 0 || |
(ret = sshbuf_put_bignum2(b, dsa_p)) != 0 || |
(ret = sshbuf_put_bignum2(b, q)) != 0 || |
(ret = sshbuf_put_bignum2(b, dsa_q)) != 0 || |
(ret = sshbuf_put_bignum2(b, g)) != 0 || |
(ret = sshbuf_put_bignum2(b, dsa_g)) != 0 || |
(ret = sshbuf_put_bignum2(b, pub_key)) != 0) |
(ret = sshbuf_put_bignum2(b, dsa_pub_key)) != 0) |
return ret; |
return ret; |
} |
|
break; |
break; |
case KEY_ECDSA: |
case KEY_ECDSA: |
if (key->ecdsa == NULL) |
if (key->ecdsa == NULL) |
Line 893 to_blob_buf(const struct sshkey *key, st |
|
Line 750 to_blob_buf(const struct sshkey *key, st |
|
case KEY_RSA: |
case KEY_RSA: |
if (key->rsa == NULL) |
if (key->rsa == NULL) |
return SSH_ERR_INVALID_ARGUMENT; |
return SSH_ERR_INVALID_ARGUMENT; |
{ |
RSA_get0_key(key->rsa, &rsa_n, &rsa_e, NULL); |
const BIGNUM *e, *n; |
|
RSA_get0_key(key->rsa, &n, &e, NULL); |
|
if ((ret = sshbuf_put_cstring(b, typename)) != 0 || |
if ((ret = sshbuf_put_cstring(b, typename)) != 0 || |
(ret = sshbuf_put_bignum2(b, e)) != 0 || |
(ret = sshbuf_put_bignum2(b, rsa_e)) != 0 || |
(ret = sshbuf_put_bignum2(b, n)) != 0) |
(ret = sshbuf_put_bignum2(b, rsa_n)) != 0) |
return ret; |
return ret; |
} |
|
break; |
break; |
#endif /* WITH_OPENSSL */ |
#endif /* WITH_OPENSSL */ |
case KEY_ED25519: |
case KEY_ED25519: |
Line 1641 dsa_generate_private_key(u_int bits, DSA |
|
Line 1495 dsa_generate_private_key(u_int bits, DSA |
|
int |
int |
sshkey_ecdsa_key_to_nid(EC_KEY *k) |
sshkey_ecdsa_key_to_nid(EC_KEY *k) |
{ |
{ |
EC_GROUP *eg; |
EC_GROUP *eg = NULL; /* XXXGCC: unneeded init */ |
int nids[] = { |
int nids[] = { |
NID_X9_62_prime256v1, |
NID_X9_62_prime256v1, |
NID_secp384r1, |
NID_secp384r1, |
Line 1770 sshkey_cert_copy(const struct sshkey *fr |
|
Line 1624 sshkey_cert_copy(const struct sshkey *fr |
|
u_int i; |
u_int i; |
const struct sshkey_cert *from; |
const struct sshkey_cert *from; |
struct sshkey_cert *to; |
struct sshkey_cert *to; |
int ret = SSH_ERR_INTERNAL_ERROR; |
int r = SSH_ERR_INTERNAL_ERROR; |
|
|
if (to_key->cert != NULL) { |
|
cert_free(to_key->cert); |
|
to_key->cert = NULL; |
|
} |
|
|
|
if ((from = from_key->cert) == NULL) |
if (to_key == NULL || (from = from_key->cert) == NULL) |
return SSH_ERR_INVALID_ARGUMENT; |
return SSH_ERR_INVALID_ARGUMENT; |
|
|
if ((to = to_key->cert = cert_new()) == NULL) |
if ((to = cert_new()) == NULL) |
return SSH_ERR_ALLOC_FAIL; |
return SSH_ERR_ALLOC_FAIL; |
|
|
if ((ret = sshbuf_putb(to->certblob, from->certblob)) != 0 || |
if ((r = sshbuf_putb(to->certblob, from->certblob)) != 0 || |
(ret = sshbuf_putb(to->critical, from->critical)) != 0 || |
(r = sshbuf_putb(to->critical, from->critical)) != 0 || |
(ret = sshbuf_putb(to->extensions, from->extensions)) != 0) |
(r = sshbuf_putb(to->extensions, from->extensions)) != 0) |
return ret; |
goto out; |
|
|
to->serial = from->serial; |
to->serial = from->serial; |
to->type = from->type; |
to->type = from->type; |
if (from->key_id == NULL) |
if (from->key_id == NULL) |
to->key_id = NULL; |
to->key_id = NULL; |
else if ((to->key_id = strdup(from->key_id)) == NULL) |
else if ((to->key_id = strdup(from->key_id)) == NULL) { |
return SSH_ERR_ALLOC_FAIL; |
r = SSH_ERR_ALLOC_FAIL; |
|
goto out; |
|
} |
to->valid_after = from->valid_after; |
to->valid_after = from->valid_after; |
to->valid_before = from->valid_before; |
to->valid_before = from->valid_before; |
if (from->signature_key == NULL) |
if (from->signature_key == NULL) |
to->signature_key = NULL; |
to->signature_key = NULL; |
else if ((ret = sshkey_from_private(from->signature_key, |
else if ((r = sshkey_from_private(from->signature_key, |
&to->signature_key)) != 0) |
&to->signature_key)) != 0) |
return ret; |
goto out; |
|
if (from->signature_type != NULL && |
if (from->nprincipals > SSHKEY_CERT_MAX_PRINCIPALS) |
(to->signature_type = strdup(from->signature_type)) == NULL) { |
return SSH_ERR_INVALID_ARGUMENT; |
r = SSH_ERR_ALLOC_FAIL; |
|
goto out; |
|
} |
|
if (from->nprincipals > SSHKEY_CERT_MAX_PRINCIPALS) { |
|
r = SSH_ERR_INVALID_ARGUMENT; |
|
goto out; |
|
} |
if (from->nprincipals > 0) { |
if (from->nprincipals > 0) { |
if ((to->principals = calloc(from->nprincipals, |
if ((to->principals = calloc(from->nprincipals, |
sizeof(*to->principals))) == NULL) |
sizeof(*to->principals))) == NULL) { |
return SSH_ERR_ALLOC_FAIL; |
r = SSH_ERR_ALLOC_FAIL; |
|
goto out; |
|
} |
for (i = 0; i < from->nprincipals; i++) { |
for (i = 0; i < from->nprincipals; i++) { |
to->principals[i] = strdup(from->principals[i]); |
to->principals[i] = strdup(from->principals[i]); |
if (to->principals[i] == NULL) { |
if (to->principals[i] == NULL) { |
to->nprincipals = i; |
to->nprincipals = i; |
return SSH_ERR_ALLOC_FAIL; |
r = SSH_ERR_ALLOC_FAIL; |
|
goto out; |
} |
} |
} |
} |
} |
} |
to->nprincipals = from->nprincipals; |
to->nprincipals = from->nprincipals; |
return 0; |
|
|
/* success */ |
|
cert_free(to_key->cert); |
|
to_key->cert = to; |
|
to = NULL; |
|
r = 0; |
|
out: |
|
cert_free(to); |
|
return r; |
} |
} |
|
|
int |
int |
sshkey_from_private(const struct sshkey *k, struct sshkey **pkp) |
sshkey_from_private(const struct sshkey *k, struct sshkey **pkp) |
{ |
{ |
struct sshkey *n = NULL; |
struct sshkey *n = NULL; |
int ret = SSH_ERR_INTERNAL_ERROR; |
int r = SSH_ERR_INTERNAL_ERROR; |
|
#ifdef WITH_OPENSSL |
|
const BIGNUM *rsa_n, *rsa_e; |
|
BIGNUM *rsa_n_dup = NULL, *rsa_e_dup = NULL; |
|
const BIGNUM *dsa_p, *dsa_q, *dsa_g, *dsa_pub_key; |
|
BIGNUM *dsa_p_dup = NULL, *dsa_q_dup = NULL, *dsa_g_dup = NULL; |
|
BIGNUM *dsa_pub_key_dup = NULL; |
|
#endif /* WITH_OPENSSL */ |
|
|
*pkp = NULL; |
*pkp = NULL; |
switch (k->type) { |
switch (k->type) { |
#ifdef WITH_OPENSSL |
#ifdef WITH_OPENSSL |
case KEY_DSA: |
case KEY_DSA: |
case KEY_DSA_CERT: |
case KEY_DSA_CERT: |
if ((n = sshkey_new(k->type)) == NULL) |
if ((n = sshkey_new(k->type)) == NULL) { |
return SSH_ERR_ALLOC_FAIL; |
r = SSH_ERR_ALLOC_FAIL; |
{ |
goto out; |
const BIGNUM *p, *q, *g, *pub_key, *priv_key; |
|
BIGNUM *cp=NULL, *cq=NULL, *cg=NULL, *cpub_key=NULL; |
|
DSA_get0_pqg(k->dsa, &p, &q, &g); |
|
DSA_get0_key(k->dsa, &pub_key, &priv_key); |
|
if ((cp = BN_dup(p)) == NULL || |
|
(cq = BN_dup(q)) == NULL || |
|
(cg = BN_dup(g)) == NULL || |
|
(cpub_key = BN_dup(pub_key)) == NULL) { |
|
BN_free(cp); BN_free(cq); BN_free(cg); |
|
BN_free(cpub_key); |
|
sshkey_free(n); |
|
return SSH_ERR_ALLOC_FAIL; |
|
} |
|
if (DSA_set0_pqg(n->dsa, cp, cq, cg) == 0) |
|
goto error1; |
|
cp = cq = cg = NULL; |
|
if (DSA_set0_key(n->dsa, cpub_key, NULL) == 0) { |
|
error1: |
|
BN_free(cp); BN_free(cq); BN_free(cg); |
|
BN_free(cpub_key); |
|
sshkey_free(n); |
|
return SSH_ERR_LIBCRYPTO_ERROR; |
|
} |
} |
cpub_key = NULL; |
|
|
DSA_get0_pqg(k->dsa, &dsa_p, &dsa_q, &dsa_g); |
|
DSA_get0_key(k->dsa, &dsa_pub_key, NULL); |
|
if ((dsa_p_dup = BN_dup(dsa_p)) == NULL || |
|
(dsa_q_dup = BN_dup(dsa_q)) == NULL || |
|
(dsa_g_dup = BN_dup(dsa_g)) == NULL || |
|
(dsa_pub_key_dup = BN_dup(dsa_pub_key)) == NULL) { |
|
r = SSH_ERR_ALLOC_FAIL; |
|
goto out; |
} |
} |
|
if (!DSA_set0_pqg(n->dsa, dsa_p_dup, dsa_q_dup, dsa_g_dup)) { |
|
r = SSH_ERR_LIBCRYPTO_ERROR; |
|
goto out; |
|
} |
|
dsa_p_dup = dsa_q_dup = dsa_g_dup = NULL; /* transferred */ |
|
if (!DSA_set0_key(n->dsa, dsa_pub_key_dup, NULL)) { |
|
r = SSH_ERR_LIBCRYPTO_ERROR; |
|
goto out; |
|
} |
|
dsa_pub_key_dup = NULL; /* transferred */ |
|
|
break; |
break; |
case KEY_ECDSA: |
case KEY_ECDSA: |
case KEY_ECDSA_CERT: |
case KEY_ECDSA_CERT: |
if ((n = sshkey_new(k->type)) == NULL) |
if ((n = sshkey_new(k->type)) == NULL) { |
return SSH_ERR_ALLOC_FAIL; |
r = SSH_ERR_ALLOC_FAIL; |
|
goto out; |
|
} |
n->ecdsa_nid = k->ecdsa_nid; |
n->ecdsa_nid = k->ecdsa_nid; |
n->ecdsa = EC_KEY_new_by_curve_name(k->ecdsa_nid); |
n->ecdsa = EC_KEY_new_by_curve_name(k->ecdsa_nid); |
if (n->ecdsa == NULL) { |
if (n->ecdsa == NULL) { |
sshkey_free(n); |
r = SSH_ERR_ALLOC_FAIL; |
return SSH_ERR_ALLOC_FAIL; |
goto out; |
} |
} |
if (EC_KEY_set_public_key(n->ecdsa, |
if (EC_KEY_set_public_key(n->ecdsa, |
EC_KEY_get0_public_key(k->ecdsa)) != 1) { |
EC_KEY_get0_public_key(k->ecdsa)) != 1) { |
sshkey_free(n); |
r = SSH_ERR_LIBCRYPTO_ERROR; |
return SSH_ERR_LIBCRYPTO_ERROR; |
goto out; |
} |
} |
break; |
break; |
case KEY_RSA: |
case KEY_RSA: |
case KEY_RSA_CERT: |
case KEY_RSA_CERT: |
if ((n = sshkey_new(k->type)) == NULL) |
if ((n = sshkey_new(k->type)) == NULL) { |
return SSH_ERR_ALLOC_FAIL; |
r = SSH_ERR_ALLOC_FAIL; |
{ |
goto out; |
const BIGNUM *nn, *e, *d; |
|
BIGNUM *cn=NULL, *ce=NULL; |
|
RSA_get0_key(k->rsa, &nn, &e, &d); |
|
if ((cn = BN_dup(nn)) == NULL || |
|
(ce = BN_dup(e)) == NULL ) { |
|
BN_free(cn); BN_free(ce); |
|
sshkey_free(n); |
|
return SSH_ERR_ALLOC_FAIL; |
|
} |
|
if (RSA_set0_key(n->rsa, cn, ce, NULL) == 0) { |
|
BN_free(cn); BN_free(ce); |
|
sshkey_free(n); |
|
return SSH_ERR_LIBCRYPTO_ERROR; |
|
} |
} |
cn = ce = NULL; |
RSA_get0_key(k->rsa, &rsa_n, &rsa_e, NULL); |
|
if ((rsa_n_dup = BN_dup(rsa_n)) == NULL || |
|
(rsa_e_dup = BN_dup(rsa_e)) == NULL) { |
|
r = SSH_ERR_ALLOC_FAIL; |
|
goto out; |
|
} |
|
if (!RSA_set0_key(n->rsa, rsa_n_dup, rsa_e_dup, NULL)) { |
|
r = SSH_ERR_LIBCRYPTO_ERROR; |
|
goto out; |
} |
} |
|
rsa_n_dup = rsa_e_dup = NULL; /* transferred */ |
break; |
break; |
#endif /* WITH_OPENSSL */ |
#endif /* WITH_OPENSSL */ |
case KEY_ED25519: |
case KEY_ED25519: |
case KEY_ED25519_CERT: |
case KEY_ED25519_CERT: |
if ((n = sshkey_new(k->type)) == NULL) |
if ((n = sshkey_new(k->type)) == NULL) { |
return SSH_ERR_ALLOC_FAIL; |
r = SSH_ERR_ALLOC_FAIL; |
|
goto out; |
|
} |
if (k->ed25519_pk != NULL) { |
if (k->ed25519_pk != NULL) { |
if ((n->ed25519_pk = malloc(ED25519_PK_SZ)) == NULL) { |
if ((n->ed25519_pk = malloc(ED25519_PK_SZ)) == NULL) { |
sshkey_free(n); |
r = SSH_ERR_ALLOC_FAIL; |
return SSH_ERR_ALLOC_FAIL; |
goto out; |
} |
} |
memcpy(n->ed25519_pk, k->ed25519_pk, ED25519_PK_SZ); |
memcpy(n->ed25519_pk, k->ed25519_pk, ED25519_PK_SZ); |
} |
} |
|
|
#ifdef WITH_XMSS |
#ifdef WITH_XMSS |
case KEY_XMSS: |
case KEY_XMSS: |
case KEY_XMSS_CERT: |
case KEY_XMSS_CERT: |
if ((n = sshkey_new(k->type)) == NULL) |
if ((n = sshkey_new(k->type)) == NULL) { |
return SSH_ERR_ALLOC_FAIL; |
r = SSH_ERR_ALLOC_FAIL; |
if ((ret = sshkey_xmss_init(n, k->xmss_name)) != 0) { |
goto out; |
sshkey_free(n); |
|
return ret; |
|
} |
} |
|
if ((r = sshkey_xmss_init(n, k->xmss_name)) != 0) |
|
goto out; |
if (k->xmss_pk != NULL) { |
if (k->xmss_pk != NULL) { |
size_t pklen = sshkey_xmss_pklen(k); |
size_t pklen = sshkey_xmss_pklen(k); |
if (pklen == 0 || sshkey_xmss_pklen(n) != pklen) { |
if (pklen == 0 || sshkey_xmss_pklen(n) != pklen) { |
sshkey_free(n); |
r = SSH_ERR_INTERNAL_ERROR; |
return SSH_ERR_INTERNAL_ERROR; |
goto out; |
} |
} |
if ((n->xmss_pk = malloc(pklen)) == NULL) { |
if ((n->xmss_pk = malloc(pklen)) == NULL) { |
sshkey_free(n); |
r = SSH_ERR_ALLOC_FAIL; |
return SSH_ERR_ALLOC_FAIL; |
goto out; |
} |
} |
memcpy(n->xmss_pk, k->xmss_pk, pklen); |
memcpy(n->xmss_pk, k->xmss_pk, pklen); |
} |
} |
break; |
break; |
#endif /* WITH_XMSS */ |
#endif /* WITH_XMSS */ |
default: |
default: |
return SSH_ERR_KEY_TYPE_UNKNOWN; |
r = SSH_ERR_KEY_TYPE_UNKNOWN; |
} |
goto out; |
if (sshkey_is_cert(k)) { |
|
if ((ret = sshkey_cert_copy(k, n)) != 0) { |
|
sshkey_free(n); |
|
return ret; |
|
} |
|
} |
} |
|
if (sshkey_is_cert(k) && (r = sshkey_cert_copy(k, n)) != 0) |
|
goto out; |
|
/* success */ |
*pkp = n; |
*pkp = n; |
return 0; |
n = NULL; |
|
r = 0; |
|
out: |
|
sshkey_free(n); |
|
BN_clear_free(rsa_n_dup); |
|
BN_clear_free(rsa_e_dup); |
|
BN_clear_free(dsa_p_dup); |
|
BN_clear_free(dsa_q_dup); |
|
BN_clear_free(dsa_g_dup); |
|
BN_clear_free(dsa_pub_key_dup); |
|
|
|
return r; |
} |
} |
|
|
static int |
static int |
Line 2058 cert_parse(struct sshbuf *b, struct sshk |
|
Line 1939 cert_parse(struct sshbuf *b, struct sshk |
|
if ((ret = sshkey_verify(key->cert->signature_key, sig, slen, |
if ((ret = sshkey_verify(key->cert->signature_key, sig, slen, |
sshbuf_ptr(key->cert->certblob), signed_len, NULL, 0)) != 0) |
sshbuf_ptr(key->cert->certblob), signed_len, NULL, 0)) != 0) |
goto out; |
goto out; |
|
if ((ret = get_sigtype(sig, slen, &key->cert->signature_type)) != 0) |
|
goto out; |
|
|
/* Success */ |
/* Success */ |
ret = 0; |
ret = 0; |
Line 2071 cert_parse(struct sshbuf *b, struct sshk |
|
Line 1954 cert_parse(struct sshbuf *b, struct sshk |
|
} |
} |
|
|
static int |
static int |
|
check_rsa_length(const RSA *rsa) |
|
{ |
|
const BIGNUM *rsa_n; |
|
|
|
RSA_get0_key(rsa, &rsa_n, NULL, NULL); |
|
if (BN_num_bits(rsa_n) < SSH_RSA_MINIMUM_MODULUS_SIZE) |
|
return SSH_ERR_KEY_LENGTH; |
|
return 0; |
|
} |
|
|
|
static int |
sshkey_from_blob_internal(struct sshbuf *b, struct sshkey **keyp, |
sshkey_from_blob_internal(struct sshbuf *b, struct sshkey **keyp, |
int allow_cert) |
int allow_cert) |
{ |
{ |
Line 2081 sshkey_from_blob_internal(struct sshbuf |
|
Line 1975 sshkey_from_blob_internal(struct sshbuf |
|
u_char *pk = NULL; |
u_char *pk = NULL; |
struct sshbuf *copy; |
struct sshbuf *copy; |
#ifdef WITH_OPENSSL |
#ifdef WITH_OPENSSL |
EC_POINT *qq = NULL; |
EC_POINT *q = NULL, *qq = NULL; |
|
BIGNUM *rsa_n = NULL, *rsa_e = NULL; |
|
BIGNUM *dsa_p = NULL, *dsa_q = NULL, *dsa_g = NULL, *dsa_pub_key = NULL; |
#endif /* WITH_OPENSSL */ |
#endif /* WITH_OPENSSL */ |
|
|
#ifdef DEBUG_PK /* XXX */ |
#ifdef DEBUG_PK /* XXX */ |
Line 2117 sshkey_from_blob_internal(struct sshbuf |
|
Line 2013 sshkey_from_blob_internal(struct sshbuf |
|
ret = SSH_ERR_ALLOC_FAIL; |
ret = SSH_ERR_ALLOC_FAIL; |
goto out; |
goto out; |
} |
} |
{ |
if (sshbuf_get_bignum2(b, &rsa_e) != 0 || |
BIGNUM *e=NULL, *n=NULL; |
sshbuf_get_bignum2(b, &rsa_n) != 0) { |
if ((e = BN_new()) == NULL || |
|
(n = BN_new()) == NULL ) { |
|
ret = SSH_ERR_ALLOC_FAIL; |
|
BN_free(e); BN_free(n); |
|
goto out; |
|
} |
|
if (sshbuf_get_bignum2(b, e) != 0 || |
|
sshbuf_get_bignum2(b, n) != 0) { |
|
ret = SSH_ERR_INVALID_FORMAT; |
ret = SSH_ERR_INVALID_FORMAT; |
BN_free(e); BN_free(n); |
|
goto out; |
goto out; |
} |
} |
if (RSA_set0_key(key->rsa, n, e, NULL) == 0) { |
if (!RSA_set0_key(key->rsa, rsa_n, rsa_e, NULL)) { |
BN_free(e); BN_free(n); |
ret = SSH_ERR_LIBCRYPTO_ERROR; |
return SSH_ERR_LIBCRYPTO_ERROR; |
|
} |
|
n = e = NULL; |
|
} |
|
if (RSA_bits(key->rsa) < SSH_RSA_MINIMUM_MODULUS_SIZE) { |
|
ret = SSH_ERR_KEY_LENGTH; |
|
goto out; |
goto out; |
} |
} |
|
rsa_n = rsa_e = NULL; /* transferred */ |
|
if ((ret = check_rsa_length(key->rsa)) != 0) |
|
goto out; |
#ifdef DEBUG_PK |
#ifdef DEBUG_PK |
RSA_print_fp(stderr, key->rsa, 8); |
RSA_print_fp(stderr, key->rsa, 8); |
#endif |
#endif |
Line 2157 sshkey_from_blob_internal(struct sshbuf |
|
Line 2041 sshkey_from_blob_internal(struct sshbuf |
|
ret = SSH_ERR_ALLOC_FAIL; |
ret = SSH_ERR_ALLOC_FAIL; |
goto out; |
goto out; |
} |
} |
{ |
if (sshbuf_get_bignum2(b, &dsa_p) != 0 || |
BIGNUM *p=NULL, *q=NULL, *g=NULL, *pub_key=NULL; |
sshbuf_get_bignum2(b, &dsa_q) != 0 || |
if ((p = BN_new()) == NULL || |
sshbuf_get_bignum2(b, &dsa_g) != 0 || |
(q = BN_new()) == NULL || |
sshbuf_get_bignum2(b, &dsa_pub_key) != 0) { |
(g = BN_new()) == NULL || |
|
(pub_key = BN_new()) == NULL) { |
|
ret = SSH_ERR_ALLOC_FAIL; |
|
goto error1; |
|
} |
|
if (sshbuf_get_bignum2(b, p) != 0 || |
|
sshbuf_get_bignum2(b, q) != 0 || |
|
sshbuf_get_bignum2(b, g) != 0 || |
|
sshbuf_get_bignum2(b, pub_key) != 0) { |
|
ret = SSH_ERR_INVALID_FORMAT; |
ret = SSH_ERR_INVALID_FORMAT; |
goto error1; |
goto out; |
} |
} |
if (DSA_set0_pqg(key->dsa, p, q, g) == 0) { |
if (!DSA_set0_pqg(key->dsa, dsa_p, dsa_q, dsa_g)) { |
ret = SSH_ERR_LIBCRYPTO_ERROR; |
ret = SSH_ERR_LIBCRYPTO_ERROR; |
goto error1; |
goto out; |
} |
} |
p = q = g = NULL; |
dsa_p = dsa_q = dsa_g = NULL; /* transferred */ |
if (DSA_set0_key(key->dsa, pub_key, NULL) == 0) { |
if (!DSA_set0_key(key->dsa, dsa_pub_key, NULL)) { |
ret = SSH_ERR_LIBCRYPTO_ERROR; |
ret = SSH_ERR_LIBCRYPTO_ERROR; |
error1: |
|
BN_free(p); BN_free(q); BN_free(g); |
|
BN_free(pub_key); |
|
goto out; |
goto out; |
} |
} |
pub_key = NULL; |
dsa_pub_key = NULL; /* transferred */ |
} |
|
#ifdef DEBUG_PK |
#ifdef DEBUG_PK |
DSA_print_fp(stderr, key->dsa, 8); |
DSA_print_fp(stderr, key->dsa, 8); |
#endif |
#endif |
|
|
free(curve); |
free(curve); |
free(pk); |
free(pk); |
#ifdef WITH_OPENSSL |
#ifdef WITH_OPENSSL |
if (qq != NULL) |
EC_POINT_free(q); |
EC_POINT_free(qq); |
BN_clear_free(rsa_n); |
|
BN_clear_free(rsa_e); |
|
BN_clear_free(dsa_p); |
|
BN_clear_free(dsa_q); |
|
BN_clear_free(dsa_g); |
|
BN_clear_free(dsa_pub_key); |
#endif /* WITH_OPENSSL */ |
#endif /* WITH_OPENSSL */ |
return ret; |
return ret; |
} |
} |
Line 2357 sshkey_froms(struct sshbuf *buf, struct |
|
Line 2233 sshkey_froms(struct sshbuf *buf, struct |
|
return r; |
return r; |
} |
} |
|
|
int |
static int |
sshkey_sigtype(const u_char *sig, size_t siglen, char **sigtypep) |
get_sigtype(const u_char *sig, size_t siglen, char **sigtypep) |
{ |
{ |
int r; |
int r; |
struct sshbuf *b = NULL; |
struct sshbuf *b = NULL; |
Line 2382 sshkey_sigtype(const u_char *sig, size_t |
|
Line 2258 sshkey_sigtype(const u_char *sig, size_t |
|
return r; |
return r; |
} |
} |
|
|
|
/* |
|
* |
|
* Checks whether a certificate's signature type is allowed. |
|
* Returns 0 (success) if the certificate signature type appears in the |
|
* "allowed" pattern-list, or the key is not a certificate to begin with. |
|
* Otherwise returns a ssherr.h code. |
|
*/ |
|
int |
|
sshkey_check_cert_sigtype(const struct sshkey *key, const char *allowed) |
|
{ |
|
if (key == NULL || allowed == NULL) |
|
return SSH_ERR_INVALID_ARGUMENT; |
|
if (!sshkey_type_is_cert(key->type)) |
|
return 0; |
|
if (key->cert == NULL || key->cert->signature_type == NULL) |
|
return SSH_ERR_INVALID_ARGUMENT; |
|
if (match_pattern_list(key->cert->signature_type, allowed, 0) != 1) |
|
return SSH_ERR_SIGN_ALG_UNSUPPORTED; |
|
return 0; |
|
} |
|
|
|
/* |
|
* Returns the expected signature algorithm for a given public key algorithm. |
|
*/ |
|
const char * |
|
sshkey_sigalg_by_name(const char *name) |
|
{ |
|
const struct keytype *kt; |
|
|
|
for (kt = keytypes; kt->type != -1; kt++) { |
|
if (strcmp(kt->name, name) != 0) |
|
continue; |
|
if (kt->sigalg != NULL) |
|
return kt->sigalg; |
|
if (!kt->cert) |
|
return kt->name; |
|
return sshkey_ssh_name_from_type_nid( |
|
sshkey_type_plain(kt->type), kt->nid); |
|
} |
|
return NULL; |
|
} |
|
|
|
/* |
|
* Verifies that the signature algorithm appearing inside the signature blob |
|
* matches that which was requested. |
|
*/ |
|
int |
|
sshkey_check_sigtype(const u_char *sig, size_t siglen, |
|
const char *requested_alg) |
|
{ |
|
const char *expected_alg; |
|
char *sigtype = NULL; |
|
int r; |
|
|
|
if (requested_alg == NULL) |
|
return 0; |
|
if ((expected_alg = sshkey_sigalg_by_name(requested_alg)) == NULL) |
|
return SSH_ERR_INVALID_ARGUMENT; |
|
if ((r = get_sigtype(sig, siglen, &sigtype)) != 0) |
|
return r; |
|
r = strcmp(expected_alg, sigtype) == 0; |
|
free(sigtype); |
|
return r ? 0 : SSH_ERR_SIGN_ALG_UNSUPPORTED; |
|
} |
|
|
int |
int |
sshkey_sign(const struct sshkey *key, |
sshkey_sign(const struct sshkey *key, |
u_char **sigp, size_t *lenp, |
u_char **sigp, size_t *lenp, |
Line 2454 sshkey_verify(const struct sshkey *key, |
|
Line 2395 sshkey_verify(const struct sshkey *key, |
|
} |
} |
} |
} |
|
|
/* Converts a private to a public key */ |
|
int |
|
sshkey_demote(const struct sshkey *k, struct sshkey **dkp) |
|
{ |
|
struct sshkey *pk; |
|
int ret = SSH_ERR_INTERNAL_ERROR; |
|
|
|
*dkp = NULL; |
|
if ((pk = calloc(1, sizeof(*pk))) == NULL) |
|
return SSH_ERR_ALLOC_FAIL; |
|
pk->type = k->type; |
|
pk->flags = k->flags; |
|
pk->ecdsa_nid = k->ecdsa_nid; |
|
pk->dsa = NULL; |
|
pk->ecdsa = NULL; |
|
pk->rsa = NULL; |
|
pk->ed25519_pk = NULL; |
|
pk->ed25519_sk = NULL; |
|
pk->xmss_pk = NULL; |
|
pk->xmss_sk = NULL; |
|
|
|
switch (k->type) { |
|
#ifdef WITH_OPENSSL |
|
case KEY_RSA_CERT: |
|
if ((ret = sshkey_cert_copy(k, pk)) != 0) |
|
goto fail; |
|
/* FALLTHROUGH */ |
|
case KEY_RSA: |
|
if ((pk->rsa = RSA_new()) == NULL ){ |
|
ret = SSH_ERR_ALLOC_FAIL; |
|
goto fail; |
|
} |
|
{ |
|
const BIGNUM *ke, *kn; |
|
BIGNUM *pke=NULL, *pkn=NULL; |
|
RSA_get0_key(k->rsa, &kn, &ke, NULL); |
|
if ((pke = BN_dup(ke)) == NULL || |
|
(pkn = BN_dup(kn)) == NULL) { |
|
ret = SSH_ERR_ALLOC_FAIL; |
|
BN_free(pke); BN_free(pkn); |
|
goto fail; |
|
} |
|
if (RSA_set0_key(pk->rsa, pkn, pke, NULL) == 0) { |
|
ret = SSH_ERR_LIBCRYPTO_ERROR; |
|
BN_free(pke); BN_free(pkn); |
|
goto fail; |
|
} |
|
pkn = pke = NULL; |
|
} |
|
break; |
|
case KEY_DSA_CERT: |
|
if ((ret = sshkey_cert_copy(k, pk)) != 0) |
|
goto fail; |
|
/* FALLTHROUGH */ |
|
case KEY_DSA: |
|
if ((pk->dsa = DSA_new()) == NULL ) { |
|
ret = SSH_ERR_ALLOC_FAIL; |
|
goto fail; |
|
} |
|
{ |
|
const BIGNUM *kp, *kq, *kg, *kpub_key; |
|
BIGNUM *pkp=NULL, *pkq=NULL, *pkg=NULL, *pkpub_key=NULL; |
|
DSA_get0_pqg(k->dsa, &kp, &kq, &kg); |
|
DSA_get0_key(k->dsa, &kpub_key, NULL); |
|
if ((pkp = BN_dup(kp)) == NULL || |
|
(pkq = BN_dup(kq)) == NULL || |
|
(pkg = BN_dup(kg)) == NULL || |
|
(pkpub_key = BN_dup(kpub_key)) == NULL) { |
|
ret = SSH_ERR_ALLOC_FAIL; |
|
goto error1; |
|
} |
|
if (DSA_set0_pqg(pk->dsa, pkp, pkq, pkg) == 0) { |
|
ret = SSH_ERR_LIBCRYPTO_ERROR; |
|
goto error1; |
|
} |
|
pkp = pkq = pkg = NULL; |
|
if (DSA_set0_key(pk->dsa, pkpub_key, NULL) == 0) { |
|
ret = SSH_ERR_LIBCRYPTO_ERROR; |
|
error1: |
|
BN_free(pkp); BN_free(pkq); BN_free(pkg); |
|
BN_free(pkpub_key); |
|
goto fail; |
|
} |
|
pkpub_key = NULL; |
|
} |
|
break; |
|
case KEY_ECDSA_CERT: |
|
if ((ret = sshkey_cert_copy(k, pk)) != 0) |
|
goto fail; |
|
/* FALLTHROUGH */ |
|
case KEY_ECDSA: |
|
pk->ecdsa = EC_KEY_new_by_curve_name(pk->ecdsa_nid); |
|
if (pk->ecdsa == NULL) { |
|
ret = SSH_ERR_ALLOC_FAIL; |
|
goto fail; |
|
} |
|
if (EC_KEY_set_public_key(pk->ecdsa, |
|
EC_KEY_get0_public_key(k->ecdsa)) != 1) { |
|
ret = SSH_ERR_LIBCRYPTO_ERROR; |
|
goto fail; |
|
} |
|
break; |
|
#endif /* WITH_OPENSSL */ |
|
case KEY_ED25519_CERT: |
|
if ((ret = sshkey_cert_copy(k, pk)) != 0) |
|
goto fail; |
|
/* FALLTHROUGH */ |
|
case KEY_ED25519: |
|
if (k->ed25519_pk != NULL) { |
|
if ((pk->ed25519_pk = malloc(ED25519_PK_SZ)) == NULL) { |
|
ret = SSH_ERR_ALLOC_FAIL; |
|
goto fail; |
|
} |
|
memcpy(pk->ed25519_pk, k->ed25519_pk, ED25519_PK_SZ); |
|
} |
|
break; |
|
#ifdef WITH_XMSS |
|
case KEY_XMSS_CERT: |
|
if ((ret = sshkey_cert_copy(k, pk)) != 0) |
|
goto fail; |
|
/* FALLTHROUGH */ |
|
case KEY_XMSS: |
|
if ((ret = sshkey_xmss_init(pk, k->xmss_name)) != 0) |
|
goto fail; |
|
if (k->xmss_pk != NULL) { |
|
size_t pklen = sshkey_xmss_pklen(k); |
|
|
|
if (pklen == 0 || sshkey_xmss_pklen(pk) != pklen) { |
|
ret = SSH_ERR_INTERNAL_ERROR; |
|
goto fail; |
|
} |
|
if ((pk->xmss_pk = malloc(pklen)) == NULL) { |
|
ret = SSH_ERR_ALLOC_FAIL; |
|
goto fail; |
|
} |
|
memcpy(pk->xmss_pk, k->xmss_pk, pklen); |
|
} |
|
break; |
|
#endif /* WITH_XMSS */ |
|
default: |
|
ret = SSH_ERR_KEY_TYPE_UNKNOWN; |
|
fail: |
|
sshkey_free(pk); |
|
return ret; |
|
} |
|
*dkp = pk; |
|
return 0; |
|
} |
|
|
|
/* Convert a plain key to their _CERT equivalent */ |
/* Convert a plain key to their _CERT equivalent */ |
int |
int |
sshkey_to_certified(struct sshkey *k) |
sshkey_to_certified(struct sshkey *k) |
Line 2659 sshkey_certify_custom(struct sshkey *k, |
|
Line 2451 sshkey_certify_custom(struct sshkey *k, |
|
u_char *ca_blob = NULL, *sig_blob = NULL, nonce[32]; |
u_char *ca_blob = NULL, *sig_blob = NULL, nonce[32]; |
size_t i, ca_len, sig_len; |
size_t i, ca_len, sig_len; |
int ret = SSH_ERR_INTERNAL_ERROR; |
int ret = SSH_ERR_INTERNAL_ERROR; |
struct sshbuf *cert; |
struct sshbuf *cert = NULL; |
|
char *sigtype = NULL; |
|
#ifdef WITH_OPENSSL |
|
const BIGNUM *rsa_n, *rsa_e, *dsa_p, *dsa_q, *dsa_g, *dsa_pub_key; |
|
#endif /* WITH_OPENSSL */ |
|
|
if (k == NULL || k->cert == NULL || |
if (k == NULL || k->cert == NULL || |
k->cert->certblob == NULL || ca == NULL) |
k->cert->certblob == NULL || ca == NULL) |
Line 2669 sshkey_certify_custom(struct sshkey *k, |
|
Line 2465 sshkey_certify_custom(struct sshkey *k, |
|
if (!sshkey_type_is_valid_ca(ca->type)) |
if (!sshkey_type_is_valid_ca(ca->type)) |
return SSH_ERR_KEY_CERT_INVALID_SIGN_KEY; |
return SSH_ERR_KEY_CERT_INVALID_SIGN_KEY; |
|
|
|
/* |
|
* If no alg specified as argument but a signature_type was set, |
|
* then prefer that. If both were specified, then they must match. |
|
*/ |
|
if (alg == NULL) |
|
alg = k->cert->signature_type; |
|
else if (k->cert->signature_type != NULL && |
|
strcmp(alg, k->cert->signature_type) != 0) |
|
return SSH_ERR_INVALID_ARGUMENT; |
|
|
if ((ret = sshkey_to_blob(ca, &ca_blob, &ca_len)) != 0) |
if ((ret = sshkey_to_blob(ca, &ca_blob, &ca_len)) != 0) |
return SSH_ERR_KEY_CERT_INVALID_SIGN_KEY; |
return SSH_ERR_KEY_CERT_INVALID_SIGN_KEY; |
|
|
Line 2686 sshkey_certify_custom(struct sshkey *k, |
|
Line 2492 sshkey_certify_custom(struct sshkey *k, |
|
switch (k->type) { |
switch (k->type) { |
#ifdef WITH_OPENSSL |
#ifdef WITH_OPENSSL |
case KEY_DSA_CERT: |
case KEY_DSA_CERT: |
{ |
DSA_get0_pqg(k->dsa, &dsa_p, &dsa_q, &dsa_g); |
const BIGNUM *p, *q, *g, *pub_key; |
DSA_get0_key(k->dsa, &dsa_pub_key, NULL); |
DSA_get0_pqg(k->dsa, &p, &q, &g); |
if ((ret = sshbuf_put_bignum2(cert, dsa_p)) != 0 || |
DSA_get0_key(k->dsa, &pub_key, NULL); |
(ret = sshbuf_put_bignum2(cert, dsa_q)) != 0 || |
if ((ret = sshbuf_put_bignum2(cert, p)) != 0 || |
(ret = sshbuf_put_bignum2(cert, dsa_g)) != 0 || |
(ret = sshbuf_put_bignum2(cert, q)) != 0 || |
(ret = sshbuf_put_bignum2(cert, dsa_pub_key)) != 0) |
(ret = sshbuf_put_bignum2(cert, g)) != 0 || |
|
(ret = sshbuf_put_bignum2(cert, pub_key)) != 0) { |
|
goto out; |
goto out; |
} |
|
} |
|
break; |
break; |
case KEY_ECDSA_CERT: |
case KEY_ECDSA_CERT: |
if ((ret = sshbuf_put_cstring(cert, |
if ((ret = sshbuf_put_cstring(cert, |
Line 2707 sshkey_certify_custom(struct sshkey *k, |
|
Line 2509 sshkey_certify_custom(struct sshkey *k, |
|
goto out; |
goto out; |
break; |
break; |
case KEY_RSA_CERT: |
case KEY_RSA_CERT: |
{ |
RSA_get0_key(k->rsa, &rsa_n, &rsa_e, NULL); |
const BIGNUM *e, *n; |
if ((ret = sshbuf_put_bignum2(cert, rsa_e)) != 0 || |
RSA_get0_key(k->rsa, &n, &e, NULL); |
(ret = sshbuf_put_bignum2(cert, rsa_n)) != 0) |
if (n == NULL || e == NULL || |
|
(ret = sshbuf_put_bignum2(cert, e)) != 0 || |
|
(ret = sshbuf_put_bignum2(cert, n)) != 0) { |
|
goto out; |
goto out; |
} |
|
} |
|
break; |
break; |
#endif /* WITH_OPENSSL */ |
#endif /* WITH_OPENSSL */ |
case KEY_ED25519_CERT: |
case KEY_ED25519_CERT: |
Line 2767 sshkey_certify_custom(struct sshkey *k, |
|
Line 2564 sshkey_certify_custom(struct sshkey *k, |
|
if ((ret = signer(ca, &sig_blob, &sig_len, sshbuf_ptr(cert), |
if ((ret = signer(ca, &sig_blob, &sig_len, sshbuf_ptr(cert), |
sshbuf_len(cert), alg, 0, signer_ctx)) != 0) |
sshbuf_len(cert), alg, 0, signer_ctx)) != 0) |
goto out; |
goto out; |
|
/* Check and update signature_type against what was actually used */ |
|
if ((ret = get_sigtype(sig_blob, sig_len, &sigtype)) != 0) |
|
goto out; |
|
if (alg != NULL && strcmp(alg, sigtype) != 0) { |
|
ret = SSH_ERR_SIGN_ALG_UNSUPPORTED; |
|
goto out; |
|
} |
|
if (k->cert->signature_type == NULL) { |
|
k->cert->signature_type = sigtype; |
|
sigtype = NULL; |
|
} |
/* Append signature and we are done */ |
/* Append signature and we are done */ |
if ((ret = sshbuf_put_string(cert, sig_blob, sig_len)) != 0) |
if ((ret = sshbuf_put_string(cert, sig_blob, sig_len)) != 0) |
goto out; |
goto out; |
Line 2777 sshkey_certify_custom(struct sshkey *k, |
|
Line 2584 sshkey_certify_custom(struct sshkey *k, |
|
sshbuf_reset(cert); |
sshbuf_reset(cert); |
free(sig_blob); |
free(sig_blob); |
free(ca_blob); |
free(ca_blob); |
|
free(sigtype); |
sshbuf_free(principals); |
sshbuf_free(principals); |
return ret; |
return ret; |
} |
} |
Line 2896 sshkey_private_serialize_opt(const struc |
|
Line 2704 sshkey_private_serialize_opt(const struc |
|
enum sshkey_serialize_rep opts) |
enum sshkey_serialize_rep opts) |
{ |
{ |
int r = SSH_ERR_INTERNAL_ERROR; |
int r = SSH_ERR_INTERNAL_ERROR; |
|
#ifdef WITH_OPENSSL |
|
const BIGNUM *rsa_n, *rsa_e, *rsa_d, *rsa_iqmp, *rsa_p, *rsa_q; |
|
const BIGNUM *dsa_p, *dsa_q, *dsa_g, *dsa_pub_key, *dsa_priv_key; |
|
#endif /* WITH_OPENSSL */ |
|
|
if ((r = sshbuf_put_cstring(b, sshkey_ssh_name(key))) != 0) |
if ((r = sshbuf_put_cstring(b, sshkey_ssh_name(key))) != 0) |
goto out; |
goto out; |
switch (key->type) { |
switch (key->type) { |
#ifdef WITH_OPENSSL |
#ifdef WITH_OPENSSL |
case KEY_RSA: |
case KEY_RSA: |
{ |
RSA_get0_key(key->rsa, &rsa_n, &rsa_e, &rsa_d); |
const BIGNUM *n, *e, *d, *iqmp, *p, *q; |
RSA_get0_factors(key->rsa, &rsa_p, &rsa_q); |
RSA_get0_key(key->rsa, &n, &e, &d); |
RSA_get0_crt_params(key->rsa, NULL, NULL, &rsa_iqmp); |
RSA_get0_crt_params(key->rsa, NULL, NULL, &iqmp); |
if ((r = sshbuf_put_bignum2(b, rsa_n)) != 0 || |
RSA_get0_factors(key->rsa, &p, &q); |
(r = sshbuf_put_bignum2(b, rsa_e)) != 0 || |
if ((r = sshbuf_put_bignum2(b, n)) != 0 || |
(r = sshbuf_put_bignum2(b, rsa_d)) != 0 || |
(r = sshbuf_put_bignum2(b, e)) != 0 || |
(r = sshbuf_put_bignum2(b, rsa_iqmp)) != 0 || |
(r = sshbuf_put_bignum2(b, d)) != 0 || |
(r = sshbuf_put_bignum2(b, rsa_p)) != 0 || |
(r = sshbuf_put_bignum2(b, iqmp)) != 0 || |
(r = sshbuf_put_bignum2(b, rsa_q)) != 0) |
(r = sshbuf_put_bignum2(b, p)) != 0 || |
|
(r = sshbuf_put_bignum2(b, q)) != 0) { |
|
goto out; |
goto out; |
} |
|
} |
|
break; |
break; |
case KEY_RSA_CERT: |
case KEY_RSA_CERT: |
if (key->cert == NULL || sshbuf_len(key->cert->certblob) == 0) { |
if (key->cert == NULL || sshbuf_len(key->cert->certblob) == 0) { |
r = SSH_ERR_INVALID_ARGUMENT; |
r = SSH_ERR_INVALID_ARGUMENT; |
goto out; |
goto out; |
} |
} |
{ |
RSA_get0_key(key->rsa, NULL, NULL, &rsa_d); |
const BIGNUM *d, *iqmp, *p, *q; |
RSA_get0_factors(key->rsa, &rsa_p, &rsa_q); |
RSA_get0_key(key->rsa, NULL, NULL, &d); |
RSA_get0_crt_params(key->rsa, NULL, NULL, &rsa_iqmp); |
RSA_get0_crt_params(key->rsa, NULL, NULL, &iqmp); |
|
RSA_get0_factors(key->rsa, &p, &q); |
|
if ((r = sshbuf_put_stringb(b, key->cert->certblob)) != 0 || |
if ((r = sshbuf_put_stringb(b, key->cert->certblob)) != 0 || |
(r = sshbuf_put_bignum2(b, d)) != 0 || |
(r = sshbuf_put_bignum2(b, rsa_d)) != 0 || |
(r = sshbuf_put_bignum2(b, iqmp)) != 0 || |
(r = sshbuf_put_bignum2(b, rsa_iqmp)) != 0 || |
(r = sshbuf_put_bignum2(b, p)) != 0 || |
(r = sshbuf_put_bignum2(b, rsa_p)) != 0 || |
(r = sshbuf_put_bignum2(b, q)) != 0) { |
(r = sshbuf_put_bignum2(b, rsa_q)) != 0) |
goto out; |
goto out; |
} |
|
} |
|
break; |
break; |
case KEY_DSA: |
case KEY_DSA: |
{ |
DSA_get0_pqg(key->dsa, &dsa_p, &dsa_q, &dsa_g); |
const BIGNUM *p, *q, *g, *pub_key, *priv_key; |
DSA_get0_key(key->dsa, &dsa_pub_key, &dsa_priv_key); |
DSA_get0_pqg(key->dsa, &p, &q, &g); |
if ((r = sshbuf_put_bignum2(b, dsa_p)) != 0 || |
DSA_get0_key(key->dsa, &pub_key, &priv_key); |
(r = sshbuf_put_bignum2(b, dsa_q)) != 0 || |
if ((r = sshbuf_put_bignum2(b, p)) != 0 || |
(r = sshbuf_put_bignum2(b, dsa_g)) != 0 || |
(r = sshbuf_put_bignum2(b, q)) != 0 || |
(r = sshbuf_put_bignum2(b, dsa_pub_key)) != 0 || |
(r = sshbuf_put_bignum2(b, g)) != 0 || |
(r = sshbuf_put_bignum2(b, dsa_priv_key)) != 0) |
(r = sshbuf_put_bignum2(b, pub_key)) != 0 || |
|
(r = sshbuf_put_bignum2(b, priv_key)) != 0) { |
|
goto out; |
goto out; |
} |
|
} |
|
break; |
break; |
case KEY_DSA_CERT: |
case KEY_DSA_CERT: |
if (key->cert == NULL || sshbuf_len(key->cert->certblob) == 0) { |
if (key->cert == NULL || sshbuf_len(key->cert->certblob) == 0) { |
r = SSH_ERR_INVALID_ARGUMENT; |
r = SSH_ERR_INVALID_ARGUMENT; |
goto out; |
goto out; |
} |
} |
{ |
DSA_get0_key(key->dsa, NULL, &dsa_priv_key); |
const BIGNUM *priv_key; |
|
DSA_get0_key(key->dsa, NULL, &priv_key); |
|
if ((r = sshbuf_put_stringb(b, key->cert->certblob)) != 0 || |
if ((r = sshbuf_put_stringb(b, key->cert->certblob)) != 0 || |
(r = sshbuf_put_bignum2(b, priv_key)) != 0) { |
(r = sshbuf_put_bignum2(b, dsa_priv_key)) != 0) |
goto out; |
goto out; |
} |
|
} |
|
break; |
break; |
case KEY_ECDSA: |
case KEY_ECDSA: |
if ((r = sshbuf_put_cstring(b, |
if ((r = sshbuf_put_cstring(b, |
Line 3060 sshkey_private_deserialize(struct sshbuf |
|
Line 2856 sshkey_private_deserialize(struct sshbuf |
|
u_char *xmss_pk = NULL, *xmss_sk = NULL; |
u_char *xmss_pk = NULL, *xmss_sk = NULL; |
#ifdef WITH_OPENSSL |
#ifdef WITH_OPENSSL |
BIGNUM *exponent = NULL; |
BIGNUM *exponent = NULL; |
|
BIGNUM *rsa_n = NULL, *rsa_e = NULL, *rsa_d = NULL; |
|
BIGNUM *rsa_iqmp = NULL, *rsa_p = NULL, *rsa_q = NULL; |
|
BIGNUM *dsa_p = NULL, *dsa_q = NULL, *dsa_g = NULL; |
|
BIGNUM *dsa_pub_key = NULL, *dsa_priv_key = NULL; |
#endif /* WITH_OPENSSL */ |
#endif /* WITH_OPENSSL */ |
|
|
if (kp != NULL) |
if (kp != NULL) |
Line 3070 sshkey_private_deserialize(struct sshbuf |
|
Line 2870 sshkey_private_deserialize(struct sshbuf |
|
switch (type) { |
switch (type) { |
#ifdef WITH_OPENSSL |
#ifdef WITH_OPENSSL |
case KEY_DSA: |
case KEY_DSA: |
if ((k = sshkey_new_private(type)) == NULL) { |
if ((k = sshkey_new(type)) == NULL) { |
r = SSH_ERR_ALLOC_FAIL; |
r = SSH_ERR_ALLOC_FAIL; |
goto out; |
goto out; |
} |
} |
{ |
if ((r = sshbuf_get_bignum2(buf, &dsa_p)) != 0 || |
BIGNUM *p=NULL, *q=NULL, *g=NULL, *pub_key=NULL, *priv_key=NULL; |
(r = sshbuf_get_bignum2(buf, &dsa_q)) != 0 || |
if ((p = BN_new()) == NULL || |
(r = sshbuf_get_bignum2(buf, &dsa_g)) != 0 || |
(q = BN_new()) == NULL || |
(r = sshbuf_get_bignum2(buf, &dsa_pub_key)) != 0 || |
(g = BN_new()) == NULL || |
(r = sshbuf_get_bignum2(buf, &dsa_priv_key)) != 0) |
(pub_key = BN_new()) == NULL || |
goto out; |
(priv_key = BN_new()) == NULL) { |
if (!DSA_set0_pqg(k->dsa, dsa_p, dsa_q, dsa_g)) { |
r = SSH_ERR_ALLOC_FAIL; |
|
goto error1; |
|
} |
|
if (p == NULL || q == NULL || g == NULL || |
|
pub_key == NULL || priv_key == NULL || |
|
(r = sshbuf_get_bignum2(buf, p)) != 0 || |
|
(r = sshbuf_get_bignum2(buf, q)) != 0 || |
|
(r = sshbuf_get_bignum2(buf, g)) != 0 || |
|
(r = sshbuf_get_bignum2(buf, pub_key)) != 0 || |
|
(r = sshbuf_get_bignum2(buf, priv_key)) != 0) { |
|
goto error1; |
|
} |
|
if (DSA_set0_pqg(k->dsa, p, q, g) == 0) { |
|
r = SSH_ERR_LIBCRYPTO_ERROR; |
r = SSH_ERR_LIBCRYPTO_ERROR; |
goto error1; |
goto out; |
} |
} |
p = q = g = NULL; |
dsa_p = dsa_q = dsa_g = NULL; /* transferred */ |
if (DSA_set0_key(k->dsa, pub_key, priv_key) == 0) { |
if (!DSA_set0_key(k->dsa, dsa_pub_key, dsa_priv_key)) { |
r = SSH_ERR_LIBCRYPTO_ERROR; |
r = SSH_ERR_LIBCRYPTO_ERROR; |
error1: |
|
BN_free(p); BN_free(q); BN_free(g); |
|
BN_free(pub_key); BN_free(priv_key); |
|
goto out; |
goto out; |
} |
} |
pub_key = priv_key = NULL; |
dsa_pub_key = dsa_priv_key = NULL; /* transferred */ |
} |
|
break; |
break; |
case KEY_DSA_CERT: |
case KEY_DSA_CERT: |
{ |
if ((r = sshkey_froms(buf, &k)) != 0 || |
BIGNUM *priv_key=NULL; |
(r = sshbuf_get_bignum2(buf, &dsa_priv_key)) != 0) |
if ((priv_key = BN_new()) == NULL) { |
|
r = SSH_ERR_ALLOC_FAIL; |
|
goto out; |
|
} |
|
if (priv_key == NULL || |
|
(r = sshkey_froms(buf, &k)) != 0 || |
|
(r = sshkey_add_private(k)) != 0 || |
|
(r = sshbuf_get_bignum2(buf, priv_key)) != 0) { |
|
BN_free(priv_key); |
|
goto out; |
goto out; |
} |
if (!DSA_set0_key(k->dsa, NULL, dsa_priv_key)) { |
if (DSA_set0_key(k->dsa, NULL, priv_key) == 0) { |
|
r = SSH_ERR_LIBCRYPTO_ERROR; |
r = SSH_ERR_LIBCRYPTO_ERROR; |
BN_free(priv_key); |
|
goto out; |
goto out; |
} |
} |
priv_key = NULL; |
dsa_priv_key = NULL; /* transferred */ |
} |
|
break; |
break; |
case KEY_ECDSA: |
case KEY_ECDSA: |
if ((k = sshkey_new_private(type)) == NULL) { |
if ((k = sshkey_new(type)) == NULL) { |
r = SSH_ERR_ALLOC_FAIL; |
r = SSH_ERR_ALLOC_FAIL; |
goto out; |
goto out; |
} |
} |
|
|
goto out; |
goto out; |
} |
} |
k->ecdsa = EC_KEY_new_by_curve_name(k->ecdsa_nid); |
k->ecdsa = EC_KEY_new_by_curve_name(k->ecdsa_nid); |
if (k->ecdsa == NULL || (exponent = BN_new()) == NULL) { |
if (k->ecdsa == NULL) { |
r = SSH_ERR_LIBCRYPTO_ERROR; |
r = SSH_ERR_LIBCRYPTO_ERROR; |
goto out; |
goto out; |
} |
} |
if ((r = sshbuf_get_eckey(buf, k->ecdsa)) != 0 || |
if ((r = sshbuf_get_eckey(buf, k->ecdsa)) != 0 || |
(r = sshbuf_get_bignum2(buf, exponent))) |
(r = sshbuf_get_bignum2(buf, &exponent))) |
goto out; |
goto out; |
if (EC_KEY_set_private_key(k->ecdsa, exponent) != 1) { |
if (EC_KEY_set_private_key(k->ecdsa, exponent) != 1) { |
r = SSH_ERR_LIBCRYPTO_ERROR; |
r = SSH_ERR_LIBCRYPTO_ERROR; |
|
|
goto out; |
goto out; |
break; |
break; |
case KEY_ECDSA_CERT: |
case KEY_ECDSA_CERT: |
if ((exponent = BN_new()) == NULL) { |
|
r = SSH_ERR_LIBCRYPTO_ERROR; |
|
goto out; |
|
} |
|
if ((r = sshkey_froms(buf, &k)) != 0 || |
if ((r = sshkey_froms(buf, &k)) != 0 || |
(r = sshkey_add_private(k)) != 0 || |
(r = sshbuf_get_bignum2(buf, &exponent)) != 0) |
(r = sshbuf_get_bignum2(buf, exponent)) != 0) |
|
goto out; |
goto out; |
if (EC_KEY_set_private_key(k->ecdsa, exponent) != 1) { |
if (EC_KEY_set_private_key(k->ecdsa, exponent) != 1) { |
r = SSH_ERR_LIBCRYPTO_ERROR; |
r = SSH_ERR_LIBCRYPTO_ERROR; |
|
|
goto out; |
goto out; |
break; |
break; |
case KEY_RSA: |
case KEY_RSA: |
if ((k = sshkey_new_private(type)) == NULL) { |
if ((k = sshkey_new(type)) == NULL) { |
r = SSH_ERR_ALLOC_FAIL; |
r = SSH_ERR_ALLOC_FAIL; |
goto out; |
goto out; |
} |
} |
{ |
if ((r = sshbuf_get_bignum2(buf, &rsa_n)) != 0 || |
BIGNUM *n=NULL, *e=NULL, *d=NULL, *iqmp=NULL, *p=NULL, *q=NULL; |
(r = sshbuf_get_bignum2(buf, &rsa_e)) != 0 || |
BIGNUM *dmp1=NULL, *dmq1=NULL; /* dummy for RSA_set0_crt_params */ |
(r = sshbuf_get_bignum2(buf, &rsa_d)) != 0 || |
if ((n = BN_new()) == NULL || |
(r = sshbuf_get_bignum2(buf, &rsa_iqmp)) != 0 || |
(e = BN_new()) == NULL || |
(r = sshbuf_get_bignum2(buf, &rsa_p)) != 0 || |
(d = BN_new()) == NULL || |
(r = sshbuf_get_bignum2(buf, &rsa_q)) != 0) |
(iqmp = BN_new()) == NULL || |
goto out; |
(p = BN_new()) == NULL || |
if (!RSA_set0_key(k->rsa, rsa_n, rsa_e, rsa_d)) { |
(q = BN_new()) == NULL || |
|
(dmp1 = BN_new()) == NULL || |
|
(dmq1 = BN_new()) == NULL) { |
|
r = SSH_ERR_ALLOC_FAIL; |
|
goto error2; |
|
} |
|
BN_clear(dmp1); BN_clear(dmq1); |
|
if ((r = sshbuf_get_bignum2(buf, n)) != 0 || |
|
(r = sshbuf_get_bignum2(buf, e)) != 0 || |
|
(r = sshbuf_get_bignum2(buf, d)) != 0 || |
|
(r = sshbuf_get_bignum2(buf, iqmp)) != 0 || |
|
(r = sshbuf_get_bignum2(buf, p)) != 0 || |
|
(r = sshbuf_get_bignum2(buf, q)) != 0) { |
|
goto error2; |
|
} |
|
if (RSA_set0_key(k->rsa, n, e, d) == 0) { |
|
r = SSH_ERR_LIBCRYPTO_ERROR; |
|
goto error2; |
|
} |
|
n = e = d = NULL; |
|
/* dmp1,dmpq1 should be non NULL to set iqmp value */ |
|
if (RSA_set0_crt_params(k->rsa, dmp1, dmq1, iqmp) == 0) { |
|
r = SSH_ERR_LIBCRYPTO_ERROR; |
r = SSH_ERR_LIBCRYPTO_ERROR; |
goto error2; |
goto out; |
} |
} |
dmp1 = dmq1 = iqmp = NULL; |
rsa_n = rsa_e = rsa_d = NULL; /* transferred */ |
if (RSA_set0_factors(k->rsa, p, q) == 0) { |
if (!RSA_set0_factors(k->rsa, rsa_p, rsa_q)) { |
r = SSH_ERR_LIBCRYPTO_ERROR; |
r = SSH_ERR_LIBCRYPTO_ERROR; |
error2: |
|
BN_free(n); BN_free(e); BN_free(d); |
|
BN_free(iqmp); |
|
BN_free(p); BN_free(q); |
|
BN_free(dmp1); BN_free(dmq1); |
|
goto out; |
goto out; |
} |
} |
p = q = NULL; |
rsa_p = rsa_q = NULL; /* transferred */ |
if ((r = ssh_rsa_generate_additional_parameters(k)) != 0) { |
if ((r = check_rsa_length(k->rsa)) != 0) |
goto out; |
goto out; |
} |
if ((r = ssh_rsa_complete_crt_parameters(k, rsa_iqmp)) != 0) |
} |
|
if (RSA_bits(k->rsa) < SSH_RSA_MINIMUM_MODULUS_SIZE) { |
|
r = SSH_ERR_KEY_LENGTH; |
|
goto out; |
goto out; |
} |
|
break; |
break; |
case KEY_RSA_CERT: |
case KEY_RSA_CERT: |
{ |
|
BIGNUM *d=NULL, *iqmp=NULL, *p=NULL, *q=NULL; |
|
BIGNUM *dmp1=NULL, *dmq1=NULL; /* dummy for RSA_set0_crt_params */ |
|
if ((d = BN_new()) == NULL || |
|
(iqmp = BN_new()) == NULL || |
|
(p = BN_new()) == NULL || |
|
(q = BN_new()) == NULL || |
|
(dmp1 = BN_new()) == NULL || |
|
(dmq1 = BN_new()) == NULL) { |
|
r = SSH_ERR_ALLOC_FAIL; |
|
goto error3; |
|
} |
|
BN_clear(dmp1); BN_clear(dmq1); |
|
if ((r = sshkey_froms(buf, &k)) != 0 || |
if ((r = sshkey_froms(buf, &k)) != 0 || |
(r = sshkey_add_private(k)) != 0 || |
(r = sshbuf_get_bignum2(buf, &rsa_d)) != 0 || |
(r = sshbuf_get_bignum2(buf, d)) != 0 || |
(r = sshbuf_get_bignum2(buf, &rsa_iqmp)) != 0 || |
(r = sshbuf_get_bignum2(buf, iqmp)) != 0 || |
(r = sshbuf_get_bignum2(buf, &rsa_p)) != 0 || |
(r = sshbuf_get_bignum2(buf, p)) != 0 || |
(r = sshbuf_get_bignum2(buf, &rsa_q)) != 0) |
(r = sshbuf_get_bignum2(buf, q)) != 0) { |
goto out; |
goto error3; |
if (!RSA_set0_key(k->rsa, NULL, NULL, rsa_d)) { |
} |
|
if (RSA_set0_key(k->rsa, NULL, NULL, d) == 0) { |
|
r = SSH_ERR_LIBCRYPTO_ERROR; |
|
goto error3; |
|
} |
|
/* dmp1,dmpq1 should be non NULL to set value */ |
|
if (RSA_set0_crt_params(k->rsa, dmp1, dmq1, iqmp) == 0) { |
|
r = SSH_ERR_LIBCRYPTO_ERROR; |
r = SSH_ERR_LIBCRYPTO_ERROR; |
goto error3; |
goto out; |
} |
} |
dmp1 = dmq1 = iqmp = NULL; |
rsa_d = NULL; /* transferred */ |
if (RSA_set0_factors(k->rsa, p, q) == 0) { |
if (!RSA_set0_factors(k->rsa, rsa_p, rsa_q)) { |
r = SSH_ERR_LIBCRYPTO_ERROR; |
r = SSH_ERR_LIBCRYPTO_ERROR; |
error3: |
|
BN_free(d); BN_free(iqmp); |
|
BN_free(p); BN_free(q); |
|
BN_free(dmp1); BN_free(dmq1); |
|
goto out; |
goto out; |
} |
} |
p = q = NULL; |
rsa_p = rsa_q = NULL; /* transferred */ |
if ((r = ssh_rsa_generate_additional_parameters(k)) != 0) |
if ((r = check_rsa_length(k->rsa)) != 0) |
goto out; |
goto out; |
} |
if ((r = ssh_rsa_complete_crt_parameters(k, rsa_iqmp)) != 0) |
if (RSA_bits(k->rsa) < SSH_RSA_MINIMUM_MODULUS_SIZE) { |
|
r = SSH_ERR_KEY_LENGTH; |
|
goto out; |
goto out; |
} |
|
break; |
break; |
#endif /* WITH_OPENSSL */ |
#endif /* WITH_OPENSSL */ |
case KEY_ED25519: |
case KEY_ED25519: |
if ((k = sshkey_new_private(type)) == NULL) { |
if ((k = sshkey_new(type)) == NULL) { |
r = SSH_ERR_ALLOC_FAIL; |
r = SSH_ERR_ALLOC_FAIL; |
goto out; |
goto out; |
} |
} |
|
|
break; |
break; |
case KEY_ED25519_CERT: |
case KEY_ED25519_CERT: |
if ((r = sshkey_froms(buf, &k)) != 0 || |
if ((r = sshkey_froms(buf, &k)) != 0 || |
(r = sshkey_add_private(k)) != 0 || |
|
(r = sshbuf_get_string(buf, &ed25519_pk, &pklen)) != 0 || |
(r = sshbuf_get_string(buf, &ed25519_pk, &pklen)) != 0 || |
(r = sshbuf_get_string(buf, &ed25519_sk, &sklen)) != 0) |
(r = sshbuf_get_string(buf, &ed25519_sk, &sklen)) != 0) |
goto out; |
goto out; |
|
|
break; |
break; |
#ifdef WITH_XMSS |
#ifdef WITH_XMSS |
case KEY_XMSS: |
case KEY_XMSS: |
if ((k = sshkey_new_private(type)) == NULL) { |
if ((k = sshkey_new(type)) == NULL) { |
r = SSH_ERR_ALLOC_FAIL; |
r = SSH_ERR_ALLOC_FAIL; |
goto out; |
goto out; |
} |
} |
|
|
break; |
break; |
case KEY_XMSS_CERT: |
case KEY_XMSS_CERT: |
if ((r = sshkey_froms(buf, &k)) != 0 || |
if ((r = sshkey_froms(buf, &k)) != 0 || |
(r = sshkey_add_private(k)) != 0 || |
|
(r = sshbuf_get_cstring(buf, &xmss_name, NULL)) != 0 || |
(r = sshbuf_get_cstring(buf, &xmss_name, NULL)) != 0 || |
(r = sshbuf_get_string(buf, &xmss_pk, &pklen)) != 0 || |
(r = sshbuf_get_string(buf, &xmss_pk, &pklen)) != 0 || |
(r = sshbuf_get_string(buf, &xmss_sk, &sklen)) != 0) |
(r = sshbuf_get_string(buf, &xmss_sk, &sklen)) != 0) |
|
|
free(curve); |
free(curve); |
#ifdef WITH_OPENSSL |
#ifdef WITH_OPENSSL |
BN_clear_free(exponent); |
BN_clear_free(exponent); |
|
BN_clear_free(dsa_p); |
|
BN_clear_free(dsa_q); |
|
BN_clear_free(dsa_g); |
|
BN_clear_free(dsa_pub_key); |
|
BN_clear_free(dsa_priv_key); |
|
BN_clear_free(rsa_n); |
|
BN_clear_free(rsa_e); |
|
BN_clear_free(rsa_d); |
|
BN_clear_free(rsa_p); |
|
BN_clear_free(rsa_q); |
|
BN_clear_free(rsa_iqmp); |
#endif /* WITH_OPENSSL */ |
#endif /* WITH_OPENSSL */ |
sshkey_free(k); |
sshkey_free(k); |
freezero(ed25519_pk, pklen); |
freezero(ed25519_pk, pklen); |
Line 4044 translate_libcrypto_error(unsigned long |
|
Line 3761 translate_libcrypto_error(unsigned long |
|
switch (pem_reason) { |
switch (pem_reason) { |
case EVP_R_BAD_DECRYPT: |
case EVP_R_BAD_DECRYPT: |
return SSH_ERR_KEY_WRONG_PASSPHRASE; |
return SSH_ERR_KEY_WRONG_PASSPHRASE; |
|
#ifdef EVP_R_BN_DECODE_ERROR |
|
case EVP_R_BN_DECODE_ERROR: |
|
#endif |
case EVP_R_DECODE_ERROR: |
case EVP_R_DECODE_ERROR: |
#ifdef EVP_R_PRIVATE_KEY_DECODE_ERROR |
#ifdef EVP_R_PRIVATE_KEY_DECODE_ERROR |
case EVP_R_PRIVATE_KEY_DECODE_ERROR: |
case EVP_R_PRIVATE_KEY_DECODE_ERROR: |
Line 4083 convert_libcrypto_error(void) |
|
Line 3803 convert_libcrypto_error(void) |
|
} |
} |
|
|
static int |
static int |
|
pem_passphrase_cb(char *buf, int size, int rwflag, void *u) |
|
{ |
|
char *p = (char *)u; |
|
size_t len; |
|
|
|
if (p == NULL || (len = strlen(p)) == 0) |
|
return -1; |
|
if (size < 0 || len > (size_t)size) |
|
return -1; |
|
memcpy(buf, p, len); |
|
return (int)len; |
|
} |
|
|
|
static int |
sshkey_parse_private_pem_fileblob(struct sshbuf *blob, int type, |
sshkey_parse_private_pem_fileblob(struct sshbuf *blob, int type, |
const char *passphrase, struct sshkey **keyp) |
const char *passphrase, struct sshkey **keyp) |
{ |
{ |
Line 4103 sshkey_parse_private_pem_fileblob(struct |
|
Line 3837 sshkey_parse_private_pem_fileblob(struct |
|
} |
} |
|
|
clear_libcrypto_errors(); |
clear_libcrypto_errors(); |
if ((pk = PEM_read_bio_PrivateKey(bio, NULL, NULL, |
if ((pk = PEM_read_bio_PrivateKey(bio, NULL, pem_passphrase_cb, |
__UNCONST(passphrase))) == NULL) { |
__UNCONST(passphrase))) == NULL) { |
r = convert_libcrypto_error(); |
/* |
|
* libcrypto may return various ASN.1 errors when attempting |
|
* to parse a key with an incorrect passphrase. |
|
* Treat all format errors as "incorrect passphrase" if a |
|
* passphrase was supplied. |
|
*/ |
|
if (passphrase != NULL && *passphrase != '\0') |
|
r = SSH_ERR_KEY_WRONG_PASSPHRASE; |
|
else |
|
r = convert_libcrypto_error(); |
goto out; |
goto out; |
} |
} |
if (EVP_PKEY_id(pk) == EVP_PKEY_RSA && |
if (EVP_PKEY_base_id(pk) == EVP_PKEY_RSA && |
(type == KEY_UNSPEC || type == KEY_RSA)) { |
(type == KEY_UNSPEC || type == KEY_RSA)) { |
if ((prv = sshkey_new(KEY_UNSPEC)) == NULL) { |
if ((prv = sshkey_new(KEY_UNSPEC)) == NULL) { |
r = SSH_ERR_ALLOC_FAIL; |
r = SSH_ERR_ALLOC_FAIL; |
Line 4123 sshkey_parse_private_pem_fileblob(struct |
|
Line 3866 sshkey_parse_private_pem_fileblob(struct |
|
r = SSH_ERR_LIBCRYPTO_ERROR; |
r = SSH_ERR_LIBCRYPTO_ERROR; |
goto out; |
goto out; |
} |
} |
if (RSA_bits(prv->rsa) < SSH_RSA_MINIMUM_MODULUS_SIZE) { |
if ((r = check_rsa_length(prv->rsa)) != 0) |
r = SSH_ERR_KEY_LENGTH; |
|
goto out; |
goto out; |
} |
} else if (EVP_PKEY_base_id(pk) == EVP_PKEY_DSA && |
} else if (EVP_PKEY_id(pk) == EVP_PKEY_DSA && |
|
(type == KEY_UNSPEC || type == KEY_DSA)) { |
(type == KEY_UNSPEC || type == KEY_DSA)) { |
if ((prv = sshkey_new(KEY_UNSPEC)) == NULL) { |
if ((prv = sshkey_new(KEY_UNSPEC)) == NULL) { |
r = SSH_ERR_ALLOC_FAIL; |
r = SSH_ERR_ALLOC_FAIL; |
Line 4138 sshkey_parse_private_pem_fileblob(struct |
|
Line 3879 sshkey_parse_private_pem_fileblob(struct |
|
#ifdef DEBUG_PK |
#ifdef DEBUG_PK |
DSA_print_fp(stderr, prv->dsa, 8); |
DSA_print_fp(stderr, prv->dsa, 8); |
#endif |
#endif |
} else if (EVP_PKEY_id(pk) == EVP_PKEY_EC && |
} else if (EVP_PKEY_base_id(pk) == EVP_PKEY_EC && |
(type == KEY_UNSPEC || type == KEY_ECDSA)) { |
(type == KEY_UNSPEC || type == KEY_ECDSA)) { |
if ((prv = sshkey_new(KEY_UNSPEC)) == NULL) { |
if ((prv = sshkey_new(KEY_UNSPEC)) == NULL) { |
r = SSH_ERR_ALLOC_FAIL; |
r = SSH_ERR_ALLOC_FAIL; |