version 1.68, 2018/09/12 01:32:54 |
version 1.69, 2018/09/13 02:08:33 |
|
|
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: |
return BN_num_bits(k->rsa->n); |
if (k->rsa == NULL) |
|
return 0; |
|
RSA_get0_key(k->rsa, &rsa_n, NULL, NULL); |
|
return BN_num_bits(rsa_n); |
case KEY_DSA: |
case KEY_DSA: |
case KEY_DSA_CERT: |
case KEY_DSA_CERT: |
return BN_num_bits(k->dsa->p); |
if (k->dsa == NULL) |
|
return 0; |
|
DSA_get0_pqg(k->dsa, &dsa_p, NULL, NULL); |
|
return BN_num_bits(dsa_p); |
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); |
|
|
#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 || |
if ((rsa = RSA_new()) == NULL) { |
(rsa->n = BN_new()) == NULL || |
|
(rsa->e = BN_new()) == NULL) { |
|
RSA_free(rsa); |
|
free(k); |
free(k); |
return NULL; |
return NULL; |
} |
} |
|
|
break; |
break; |
case KEY_DSA: |
case KEY_DSA: |
case KEY_DSA_CERT: |
case KEY_DSA_CERT: |
if ((dsa = DSA_new()) == NULL || |
if ((dsa = DSA_new()) == NULL) { |
(dsa->p = BN_new()) == NULL || |
|
(dsa->q = BN_new()) == NULL || |
|
(dsa->g = BN_new()) == NULL || |
|
(dsa->pub_key = BN_new()) == NULL) { |
|
DSA_free(dsa); |
|
free(k); |
free(k); |
return NULL; |
return NULL; |
} |
} |
|
|
return k; |
return k; |
} |
} |
|
|
int |
/* XXX garbage-collect this API */ |
sshkey_add_private(struct sshkey *k) |
|
{ |
|
switch (k->type) { |
|
#ifdef WITH_OPENSSL |
|
case KEY_RSA: |
|
case KEY_RSA_CERT: |
|
#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; |
|
break; |
|
case KEY_DSA: |
|
case KEY_DSA_CERT: |
|
if (bn_maybe_alloc_failed(k->dsa->priv_key)) |
|
return SSH_ERR_ALLOC_FAIL; |
|
break; |
|
#undef bn_maybe_alloc_failed |
|
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 * |
struct sshkey * |
sshkey_new_private(int type) |
sshkey_new_private(int type) |
{ |
{ |
|
|
|
|
if (k == NULL) |
if (k == NULL) |
return NULL; |
return NULL; |
if (sshkey_add_private(k) != 0) { |
|
sshkey_free(k); |
|
return NULL; |
|
} |
|
return k; |
return k; |
} |
} |
|
|
|
|
{ |
{ |
#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 || |
|
|
#ifdef WITH_OPENSSL |
#ifdef WITH_OPENSSL |
case KEY_RSA_CERT: |
case KEY_RSA_CERT: |
case KEY_RSA: |
case KEY_RSA: |
return a->rsa != NULL && b->rsa != NULL && |
if (a->rsa == NULL || b->rsa == NULL) |
BN_cmp(a->rsa->e, b->rsa->e) == 0 && |
return 0; |
BN_cmp(a->rsa->n, b->rsa->n) == 0; |
RSA_get0_key(a->rsa, &rsa_n_a, &rsa_e_a, NULL); |
|
RSA_get0_key(b->rsa, &rsa_n_b, &rsa_e_b, NULL); |
|
return BN_cmp(rsa_e_a, rsa_e_b) == 0 && |
|
BN_cmp(rsa_n_a, rsa_n_b) == 0; |
case KEY_DSA_CERT: |
case KEY_DSA_CERT: |
case KEY_DSA: |
case KEY_DSA: |
return a->dsa != NULL && b->dsa != NULL && |
if (a->dsa == NULL || b->dsa == NULL) |
BN_cmp(a->dsa->p, b->dsa->p) == 0 && |
return 0; |
BN_cmp(a->dsa->q, b->dsa->q) == 0 && |
DSA_get0_pqg(a->dsa, &dsa_p_a, &dsa_q_a, &dsa_g_a); |
BN_cmp(a->dsa->g, b->dsa->g) == 0 && |
DSA_get0_pqg(b->dsa, &dsa_p_b, &dsa_q_b, &dsa_g_b); |
BN_cmp(a->dsa->pub_key, b->dsa->pub_key) == 0; |
DSA_get0_key(a->dsa, &dsa_pub_key_a, NULL); |
|
DSA_get0_key(b->dsa, &dsa_pub_key_b, NULL); |
|
return BN_cmp(dsa_p_a, dsa_p_b) == 0 && |
|
BN_cmp(dsa_q_a, dsa_q_b) == 0 && |
|
BN_cmp(dsa_g_a, dsa_g_b) == 0 && |
|
BN_cmp(dsa_pub_key_a, dsa_pub_key_b) == 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 || |
|
|
{ |
{ |
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; |
|
|
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); |
|
DSA_get0_key(key->dsa, &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, key->dsa->p)) != 0 || |
(ret = sshbuf_put_bignum2(b, dsa_p)) != 0 || |
(ret = sshbuf_put_bignum2(b, key->dsa->q)) != 0 || |
(ret = sshbuf_put_bignum2(b, dsa_q)) != 0 || |
(ret = sshbuf_put_bignum2(b, key->dsa->g)) != 0 || |
(ret = sshbuf_put_bignum2(b, dsa_g)) != 0 || |
(ret = sshbuf_put_bignum2(b, key->dsa->pub_key)) != 0) |
(ret = sshbuf_put_bignum2(b, dsa_pub_key)) != 0) |
return ret; |
return ret; |
break; |
break; |
case KEY_ECDSA: |
case KEY_ECDSA: |
|
|
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); |
if ((ret = sshbuf_put_cstring(b, typename)) != 0 || |
if ((ret = sshbuf_put_cstring(b, typename)) != 0 || |
(ret = sshbuf_put_bignum2(b, key->rsa->e)) != 0 || |
(ret = sshbuf_put_bignum2(b, rsa_e)) != 0 || |
(ret = sshbuf_put_bignum2(b, key->rsa->n)) != 0) |
(ret = sshbuf_put_bignum2(b, rsa_n)) != 0) |
return ret; |
return ret; |
break; |
break; |
#endif /* WITH_OPENSSL */ |
#endif /* WITH_OPENSSL */ |
|
|
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; |
if ((BN_copy(n->dsa->p, k->dsa->p) == NULL) || |
goto out; |
(BN_copy(n->dsa->q, k->dsa->q) == NULL) || |
|
(BN_copy(n->dsa->g, k->dsa->g) == NULL) || |
|
(BN_copy(n->dsa->pub_key, k->dsa->pub_key) == NULL)) { |
|
sshkey_free(n); |
|
return SSH_ERR_ALLOC_FAIL; |
|
} |
} |
|
|
|
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; |
if ((BN_copy(n->rsa->n, k->rsa->n) == NULL) || |
goto out; |
(BN_copy(n->rsa->e, k->rsa->e) == NULL)) { |
|
sshkey_free(n); |
|
return SSH_ERR_ALLOC_FAIL; |
|
} |
} |
|
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 (sshkey_is_cert(k) && (r = sshkey_cert_copy(k, n)) != 0) |
if ((ret = sshkey_cert_copy(k, n)) != 0) { |
goto out; |
sshkey_free(n); |
/* success */ |
return ret; |
|
} |
|
} |
|
*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 |
|
|
} |
} |
|
|
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) |
{ |
{ |
|
|
struct sshbuf *copy; |
struct sshbuf *copy; |
#ifdef WITH_OPENSSL |
#ifdef WITH_OPENSSL |
EC_POINT *q = NULL; |
EC_POINT *q = 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 */ |
|
|
ret = SSH_ERR_ALLOC_FAIL; |
ret = SSH_ERR_ALLOC_FAIL; |
goto out; |
goto out; |
} |
} |
if (sshbuf_get_bignum2(b, key->rsa->e) != 0 || |
if ((rsa_e = BN_new()) == NULL || |
sshbuf_get_bignum2(b, key->rsa->n) != 0) { |
(rsa_n = BN_new()) == NULL) { |
|
ret = SSH_ERR_ALLOC_FAIL; |
|
goto out; |
|
} |
|
if (sshbuf_get_bignum2(b, rsa_e) != 0 || |
|
sshbuf_get_bignum2(b, rsa_n) != 0) { |
ret = SSH_ERR_INVALID_FORMAT; |
ret = SSH_ERR_INVALID_FORMAT; |
goto out; |
goto out; |
} |
} |
if (BN_num_bits(key->rsa->n) < SSH_RSA_MINIMUM_MODULUS_SIZE) { |
if (!RSA_set0_key(key->rsa, rsa_n, rsa_e, NULL)) { |
ret = SSH_ERR_KEY_LENGTH; |
ret = SSH_ERR_LIBCRYPTO_ERROR; |
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 |
|
|
ret = SSH_ERR_ALLOC_FAIL; |
ret = SSH_ERR_ALLOC_FAIL; |
goto out; |
goto out; |
} |
} |
if (sshbuf_get_bignum2(b, key->dsa->p) != 0 || |
if ((dsa_p = BN_new()) == NULL || |
sshbuf_get_bignum2(b, key->dsa->q) != 0 || |
(dsa_q = BN_new()) == NULL || |
sshbuf_get_bignum2(b, key->dsa->g) != 0 || |
(dsa_g = BN_new()) == NULL || |
sshbuf_get_bignum2(b, key->dsa->pub_key) != 0) { |
(dsa_pub_key = BN_new()) == NULL) { |
|
ret = SSH_ERR_ALLOC_FAIL; |
|
goto out; |
|
} |
|
if (sshbuf_get_bignum2(b, dsa_p) != 0 || |
|
sshbuf_get_bignum2(b, dsa_q) != 0 || |
|
sshbuf_get_bignum2(b, dsa_g) != 0 || |
|
sshbuf_get_bignum2(b, dsa_pub_key) != 0) { |
ret = SSH_ERR_INVALID_FORMAT; |
ret = SSH_ERR_INVALID_FORMAT; |
goto out; |
goto out; |
} |
} |
|
if (!DSA_set0_pqg(key->dsa, dsa_p, dsa_q, dsa_g)) { |
|
ret = SSH_ERR_LIBCRYPTO_ERROR; |
|
goto out; |
|
} |
|
dsa_p = dsa_q = dsa_g = NULL; /* transferred */ |
|
if (!DSA_set0_key(key->dsa, dsa_pub_key, NULL)) { |
|
ret = SSH_ERR_LIBCRYPTO_ERROR; |
|
goto out; |
|
} |
|
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(pk); |
free(pk); |
#ifdef WITH_OPENSSL |
#ifdef WITH_OPENSSL |
EC_POINT_free(q); |
EC_POINT_free(q); |
|
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; |
} |
} |
|
|
} |
} |
} |
} |
|
|
/* 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 || |
|
(pk->rsa->e = BN_dup(k->rsa->e)) == NULL || |
|
(pk->rsa->n = BN_dup(k->rsa->n)) == NULL) { |
|
ret = SSH_ERR_ALLOC_FAIL; |
|
goto fail; |
|
} |
|
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 || |
|
(pk->dsa->p = BN_dup(k->dsa->p)) == NULL || |
|
(pk->dsa->q = BN_dup(k->dsa->q)) == NULL || |
|
(pk->dsa->g = BN_dup(k->dsa->g)) == NULL || |
|
(pk->dsa->pub_key = BN_dup(k->dsa->pub_key)) == NULL) { |
|
ret = SSH_ERR_ALLOC_FAIL; |
|
goto fail; |
|
} |
|
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) |
|
|
int ret = SSH_ERR_INTERNAL_ERROR; |
int ret = SSH_ERR_INTERNAL_ERROR; |
struct sshbuf *cert = NULL; |
struct sshbuf *cert = NULL; |
char *sigtype = 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) |
|
|
switch (k->type) { |
switch (k->type) { |
#ifdef WITH_OPENSSL |
#ifdef WITH_OPENSSL |
case KEY_DSA_CERT: |
case KEY_DSA_CERT: |
if ((ret = sshbuf_put_bignum2(cert, k->dsa->p)) != 0 || |
DSA_get0_pqg(k->dsa, &dsa_p, &dsa_q, &dsa_g); |
(ret = sshbuf_put_bignum2(cert, k->dsa->q)) != 0 || |
DSA_get0_key(k->dsa, &dsa_pub_key, NULL); |
(ret = sshbuf_put_bignum2(cert, k->dsa->g)) != 0 || |
if ((ret = sshbuf_put_bignum2(cert, dsa_p)) != 0 || |
(ret = sshbuf_put_bignum2(cert, k->dsa->pub_key)) != 0) |
(ret = sshbuf_put_bignum2(cert, dsa_q)) != 0 || |
|
(ret = sshbuf_put_bignum2(cert, dsa_g)) != 0 || |
|
(ret = sshbuf_put_bignum2(cert, dsa_pub_key)) != 0) |
goto out; |
goto out; |
break; |
break; |
case KEY_ECDSA_CERT: |
case KEY_ECDSA_CERT: |
|
|
goto out; |
goto out; |
break; |
break; |
case KEY_RSA_CERT: |
case KEY_RSA_CERT: |
if ((ret = sshbuf_put_bignum2(cert, k->rsa->e)) != 0 || |
RSA_get0_key(k->rsa, &rsa_n, &rsa_e, NULL); |
(ret = sshbuf_put_bignum2(cert, k->rsa->n)) != 0) |
if ((ret = sshbuf_put_bignum2(cert, rsa_e)) != 0 || |
|
(ret = sshbuf_put_bignum2(cert, rsa_n)) != 0) |
goto out; |
goto out; |
break; |
break; |
#endif /* WITH_OPENSSL */ |
#endif /* WITH_OPENSSL */ |
|
|
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: |
if ((r = sshbuf_put_bignum2(b, key->rsa->n)) != 0 || |
RSA_get0_key(key->rsa, &rsa_n, &rsa_e, &rsa_d); |
(r = sshbuf_put_bignum2(b, key->rsa->e)) != 0 || |
RSA_get0_factors(key->rsa, &rsa_p, &rsa_q); |
(r = sshbuf_put_bignum2(b, key->rsa->d)) != 0 || |
RSA_get0_crt_params(key->rsa, NULL, NULL, &rsa_iqmp); |
(r = sshbuf_put_bignum2(b, key->rsa->iqmp)) != 0 || |
if ((r = sshbuf_put_bignum2(b, rsa_n)) != 0 || |
(r = sshbuf_put_bignum2(b, key->rsa->p)) != 0 || |
(r = sshbuf_put_bignum2(b, rsa_e)) != 0 || |
(r = sshbuf_put_bignum2(b, key->rsa->q)) != 0) |
(r = sshbuf_put_bignum2(b, rsa_d)) != 0 || |
|
(r = sshbuf_put_bignum2(b, rsa_iqmp)) != 0 || |
|
(r = sshbuf_put_bignum2(b, rsa_p)) != 0 || |
|
(r = sshbuf_put_bignum2(b, rsa_q)) != 0) |
goto out; |
goto out; |
break; |
break; |
case KEY_RSA_CERT: |
case KEY_RSA_CERT: |
|
|
r = SSH_ERR_INVALID_ARGUMENT; |
r = SSH_ERR_INVALID_ARGUMENT; |
goto out; |
goto out; |
} |
} |
|
RSA_get0_key(key->rsa, NULL, NULL, &rsa_d); |
|
RSA_get0_factors(key->rsa, &rsa_p, &rsa_q); |
|
RSA_get0_crt_params(key->rsa, NULL, NULL, &rsa_iqmp); |
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, key->rsa->d)) != 0 || |
(r = sshbuf_put_bignum2(b, rsa_d)) != 0 || |
(r = sshbuf_put_bignum2(b, key->rsa->iqmp)) != 0 || |
(r = sshbuf_put_bignum2(b, rsa_iqmp)) != 0 || |
(r = sshbuf_put_bignum2(b, key->rsa->p)) != 0 || |
(r = sshbuf_put_bignum2(b, rsa_p)) != 0 || |
(r = sshbuf_put_bignum2(b, key->rsa->q)) != 0) |
(r = sshbuf_put_bignum2(b, rsa_q)) != 0) |
goto out; |
goto out; |
break; |
break; |
case KEY_DSA: |
case KEY_DSA: |
if ((r = sshbuf_put_bignum2(b, key->dsa->p)) != 0 || |
DSA_get0_pqg(key->dsa, &dsa_p, &dsa_q, &dsa_g); |
(r = sshbuf_put_bignum2(b, key->dsa->q)) != 0 || |
DSA_get0_key(key->dsa, &dsa_pub_key, &dsa_priv_key); |
(r = sshbuf_put_bignum2(b, key->dsa->g)) != 0 || |
if ((r = sshbuf_put_bignum2(b, dsa_p)) != 0 || |
(r = sshbuf_put_bignum2(b, key->dsa->pub_key)) != 0 || |
(r = sshbuf_put_bignum2(b, dsa_q)) != 0 || |
(r = sshbuf_put_bignum2(b, key->dsa->priv_key)) != 0) |
(r = sshbuf_put_bignum2(b, dsa_g)) != 0 || |
|
(r = sshbuf_put_bignum2(b, dsa_pub_key)) != 0 || |
|
(r = sshbuf_put_bignum2(b, dsa_priv_key)) != 0) |
goto out; |
goto out; |
break; |
break; |
case KEY_DSA_CERT: |
case KEY_DSA_CERT: |
|
|
r = SSH_ERR_INVALID_ARGUMENT; |
r = SSH_ERR_INVALID_ARGUMENT; |
goto out; |
goto out; |
} |
} |
|
DSA_get0_key(key->dsa, NULL, &dsa_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, key->dsa->priv_key)) != 0) |
(r = sshbuf_put_bignum2(b, dsa_priv_key)) != 0) |
goto out; |
goto out; |
break; |
break; |
case KEY_ECDSA: |
case KEY_ECDSA: |
|
|
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) |
|
|
r = SSH_ERR_ALLOC_FAIL; |
r = SSH_ERR_ALLOC_FAIL; |
goto out; |
goto out; |
} |
} |
if ((r = sshbuf_get_bignum2(buf, k->dsa->p)) != 0 || |
if ((dsa_p = BN_new()) == NULL || |
(r = sshbuf_get_bignum2(buf, k->dsa->q)) != 0 || |
(dsa_q = BN_new()) == NULL || |
(r = sshbuf_get_bignum2(buf, k->dsa->g)) != 0 || |
(dsa_g = BN_new()) == NULL || |
(r = sshbuf_get_bignum2(buf, k->dsa->pub_key)) != 0 || |
(dsa_pub_key = BN_new()) == NULL || |
(r = sshbuf_get_bignum2(buf, k->dsa->priv_key)) != 0) |
(dsa_priv_key = BN_new()) == NULL) { |
|
r = SSH_ERR_ALLOC_FAIL; |
goto out; |
goto out; |
|
} |
|
if ((r = sshbuf_get_bignum2(buf, dsa_p)) != 0 || |
|
(r = sshbuf_get_bignum2(buf, dsa_q)) != 0 || |
|
(r = sshbuf_get_bignum2(buf, dsa_g)) != 0 || |
|
(r = sshbuf_get_bignum2(buf, dsa_pub_key)) != 0 || |
|
(r = sshbuf_get_bignum2(buf, dsa_priv_key)) != 0) |
|
goto out; |
|
if (!DSA_set0_pqg(k->dsa, dsa_p, dsa_q, dsa_g)) { |
|
r = SSH_ERR_LIBCRYPTO_ERROR; |
|
goto out; |
|
} |
|
dsa_p = dsa_q = dsa_g = NULL; /* transferred */ |
|
if (!DSA_set0_key(k->dsa, dsa_pub_key, dsa_priv_key)) { |
|
r = SSH_ERR_LIBCRYPTO_ERROR; |
|
goto out; |
|
} |
|
dsa_pub_key = dsa_priv_key = NULL; /* transferred */ |
break; |
break; |
case KEY_DSA_CERT: |
case KEY_DSA_CERT: |
|
if ((dsa_priv_key = BN_new()) == NULL) { |
|
r = SSH_ERR_ALLOC_FAIL; |
|
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, dsa_priv_key)) != 0) |
(r = sshbuf_get_bignum2(buf, k->dsa->priv_key)) != 0) |
|
goto out; |
goto out; |
|
if (!DSA_set0_key(k->dsa, NULL, dsa_priv_key)) { |
|
r = SSH_ERR_LIBCRYPTO_ERROR; |
|
goto out; |
|
} |
|
dsa_priv_key = NULL; /* transferred */ |
break; |
break; |
case KEY_ECDSA: |
case KEY_ECDSA: |
if ((k = sshkey_new_private(type)) == NULL) { |
if ((k = sshkey_new_private(type)) == NULL) { |
|
|
goto out; |
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_ALLOC_FAIL; |
r = SSH_ERR_ALLOC_FAIL; |
goto out; |
goto out; |
} |
} |
if ((r = sshbuf_get_bignum2(buf, k->rsa->n)) != 0 || |
if ((rsa_n = BN_new()) == NULL || |
(r = sshbuf_get_bignum2(buf, k->rsa->e)) != 0 || |
(rsa_e = BN_new()) == NULL || |
(r = sshbuf_get_bignum2(buf, k->rsa->d)) != 0 || |
(rsa_d = BN_new()) == NULL || |
(r = sshbuf_get_bignum2(buf, k->rsa->iqmp)) != 0 || |
(rsa_iqmp = BN_new()) == NULL || |
(r = sshbuf_get_bignum2(buf, k->rsa->p)) != 0 || |
(rsa_p = BN_new()) == NULL || |
(r = sshbuf_get_bignum2(buf, k->rsa->q)) != 0 || |
(rsa_q = BN_new()) == NULL) { |
(r = ssh_rsa_generate_additional_parameters(k)) != 0) |
r = SSH_ERR_ALLOC_FAIL; |
goto out; |
goto out; |
if (BN_num_bits(k->rsa->n) < SSH_RSA_MINIMUM_MODULUS_SIZE) { |
} |
r = SSH_ERR_KEY_LENGTH; |
if ((r = sshbuf_get_bignum2(buf, rsa_n)) != 0 || |
|
(r = sshbuf_get_bignum2(buf, rsa_e)) != 0 || |
|
(r = sshbuf_get_bignum2(buf, rsa_d)) != 0 || |
|
(r = sshbuf_get_bignum2(buf, rsa_iqmp)) != 0 || |
|
(r = sshbuf_get_bignum2(buf, rsa_p)) != 0 || |
|
(r = sshbuf_get_bignum2(buf, rsa_q)) != 0) |
goto out; |
goto out; |
|
if (!RSA_set0_key(k->rsa, rsa_n, rsa_e, rsa_d)) { |
|
r = SSH_ERR_LIBCRYPTO_ERROR; |
|
goto out; |
} |
} |
|
rsa_n = rsa_e = rsa_d = NULL; /* transferred */ |
|
if (!RSA_set0_factors(k->rsa, rsa_p, rsa_q)) { |
|
r = SSH_ERR_LIBCRYPTO_ERROR; |
|
goto out; |
|
} |
|
rsa_p = rsa_q = NULL; /* transferred */ |
|
if ((r = check_rsa_length(k->rsa)) != 0) |
|
goto out; |
|
if ((r = ssh_rsa_complete_crt_parameters(k, rsa_iqmp)) != 0) |
|
goto out; |
break; |
break; |
case KEY_RSA_CERT: |
case KEY_RSA_CERT: |
|
if ((rsa_d = BN_new()) == NULL || |
|
(rsa_iqmp = BN_new()) == NULL || |
|
(rsa_p = BN_new()) == NULL || |
|
(rsa_q = BN_new()) == NULL) { |
|
r = SSH_ERR_ALLOC_FAIL; |
|
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, rsa_d)) != 0 || |
(r = sshbuf_get_bignum2(buf, k->rsa->d)) != 0 || |
(r = sshbuf_get_bignum2(buf, rsa_iqmp)) != 0 || |
(r = sshbuf_get_bignum2(buf, k->rsa->iqmp)) != 0 || |
(r = sshbuf_get_bignum2(buf, rsa_p)) != 0 || |
(r = sshbuf_get_bignum2(buf, k->rsa->p)) != 0 || |
(r = sshbuf_get_bignum2(buf, rsa_q)) != 0) |
(r = sshbuf_get_bignum2(buf, k->rsa->q)) != 0 || |
|
(r = ssh_rsa_generate_additional_parameters(k)) != 0) |
|
goto out; |
goto out; |
if (BN_num_bits(k->rsa->n) < SSH_RSA_MINIMUM_MODULUS_SIZE) { |
if (!RSA_set0_key(k->rsa, NULL, NULL, rsa_d)) { |
r = SSH_ERR_KEY_LENGTH; |
r = SSH_ERR_LIBCRYPTO_ERROR; |
goto out; |
goto out; |
} |
} |
|
rsa_d = NULL; /* transferred */ |
|
if (!RSA_set0_factors(k->rsa, rsa_p, rsa_q)) { |
|
r = SSH_ERR_LIBCRYPTO_ERROR; |
|
goto out; |
|
} |
|
rsa_p = rsa_q = NULL; /* transferred */ |
|
if ((r = check_rsa_length(k->rsa)) != 0) |
|
goto out; |
|
if ((r = ssh_rsa_complete_crt_parameters(k, rsa_iqmp)) != 0) |
|
goto out; |
break; |
break; |
#endif /* WITH_OPENSSL */ |
#endif /* WITH_OPENSSL */ |
case KEY_ED25519: |
case KEY_ED25519: |
|
|
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; |
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); |
|
|
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: |
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: |
|
|
r = convert_libcrypto_error(); |
r = convert_libcrypto_error(); |
goto out; |
goto out; |
} |
} |
if (pk->type == 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; |
|
|
r = SSH_ERR_LIBCRYPTO_ERROR; |
r = SSH_ERR_LIBCRYPTO_ERROR; |
goto out; |
goto out; |
} |
} |
if (BN_num_bits(prv->rsa->n) < 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 (pk->type == 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; |
|
|
#ifdef DEBUG_PK |
#ifdef DEBUG_PK |
DSA_print_fp(stderr, prv->dsa, 8); |
DSA_print_fp(stderr, prv->dsa, 8); |
#endif |
#endif |
} else if (pk->type == 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; |