Skip to content

Commit

Permalink
refactor sshkey_private_deserialize
Browse files Browse the repository at this point in the history
  • Loading branch information
djmdjm committed Sep 20, 2022
1 parent 4b9f16d commit 82842ed
Show file tree
Hide file tree
Showing 9 changed files with 250 additions and 269 deletions.
22 changes: 22 additions & 0 deletions ssh-dss.c
Expand Up @@ -227,6 +227,27 @@ ssh_dss_deserialize_public(const char *ktype, struct sshbuf *b,
return ret;
}

static int
ssh_dss_deserialize_private(const char *ktype, struct sshbuf *b,
struct sshkey *key)
{
int r;
BIGNUM *dsa_priv_key = NULL;

if (!sshkey_is_cert(key)) {
if ((r = ssh_dss_deserialize_public(ktype, b, key)) != 0)
return r;
}

if ((r = sshbuf_get_bignum2(b, &dsa_priv_key)) != 0)
return r;
if (!DSA_set0_key(key->dsa, NULL, dsa_priv_key)) {
BN_clear_free(dsa_priv_key);
return SSH_ERR_LIBCRYPTO_ERROR;
}
return 0;
}

static int
ssh_dss_sign(struct sshkey *key,
u_char **sigp, size_t *lenp,
Expand Down Expand Up @@ -395,6 +416,7 @@ static const struct sshkey_impl_funcs sshkey_dss_funcs = {
/* .ssh_serialize_public = */ ssh_dss_serialize_public,
/* .ssh_deserialize_public = */ ssh_dss_deserialize_public,
/* .ssh_serialize_private = */ ssh_dss_serialize_private,
/* .ssh_deserialize_private = */ ssh_dss_deserialize_private,
/* .generate = */ ssh_dss_generate,
/* .copy_public = */ ssh_dss_copy_public,
/* .sign = */ ssh_dss_sign,
Expand Down
18 changes: 18 additions & 0 deletions ssh-ecdsa-sk.c
Expand Up @@ -119,6 +119,23 @@ ssh_ecdsa_sk_deserialize_public(const char *ktype, struct sshbuf *b,
return 0;
}

static int
ssh_ecdsa_sk_deserialize_private(const char *ktype, struct sshbuf *b,
struct sshkey *key)
{
int r;

if (!sshkey_is_cert(key)) {
if ((r = sshkey_ecdsa_funcs.deserialize_public(ktype,
b, key)) != 0)
return r;
}
if ((r = sshkey_private_deserialize_sk(b, key)) != 0)
return r;

return 0;
}

/*
* Check FIDO/W3C webauthn signatures clientData field against the expected
* format and prepare a hash of it for use in signature verification.
Expand Down Expand Up @@ -387,6 +404,7 @@ static const struct sshkey_impl_funcs sshkey_ecdsa_sk_funcs = {
/* .ssh_serialize_public = */ ssh_ecdsa_sk_serialize_public,
/* .ssh_deserialize_public = */ ssh_ecdsa_sk_deserialize_public,
/* .ssh_serialize_private = */ ssh_ecdsa_sk_serialize_private,
/* .ssh_deserialize_private = */ ssh_ecdsa_sk_deserialize_private,
/* .generate = */ NULL,
/* .copy_public = */ ssh_ecdsa_sk_copy_public,
/* .sign = */ NULL,
Expand Down
72 changes: 46 additions & 26 deletions ssh-ecdsa.c
Expand Up @@ -149,50 +149,69 @@ static int
ssh_ecdsa_deserialize_public(const char *ktype, struct sshbuf *b,
struct sshkey *key)
{
int ret = SSH_ERR_INTERNAL_ERROR;
int r;
char *curve = NULL;
EC_POINT *q = NULL;

key->ecdsa_nid = sshkey_ecdsa_nid_from_name(ktype);
if (sshbuf_get_cstring(b, &curve, NULL) != 0) {
ret = SSH_ERR_INVALID_FORMAT;
if ((key->ecdsa_nid = sshkey_ecdsa_nid_from_name(ktype)) == -1)
return SSH_ERR_INVALID_ARGUMENT;
if ((r = sshbuf_get_cstring(b, &curve, NULL)) != 0)
goto out;
}
if (key->ecdsa_nid != sshkey_curve_name_to_nid(curve)) {
ret = SSH_ERR_EC_CURVE_MISMATCH;
r = SSH_ERR_EC_CURVE_MISMATCH;
goto out;
}
EC_KEY_free(key->ecdsa);
key->ecdsa = NULL;
if ((key->ecdsa = EC_KEY_new_by_curve_name(key->ecdsa_nid)) == NULL) {
ret = SSH_ERR_EC_CURVE_INVALID;
r = SSH_ERR_LIBCRYPTO_ERROR;
goto out;
}
if ((q = EC_POINT_new(EC_KEY_get0_group(key->ecdsa))) == NULL) {
ret = SSH_ERR_ALLOC_FAIL;
if ((r = sshbuf_get_eckey(b, key->ecdsa)) != 0)
goto out;
}
if (sshbuf_get_ec(b, q, EC_KEY_get0_group(key->ecdsa)) != 0) {
ret = SSH_ERR_INVALID_FORMAT;
if (sshkey_ec_validate_public(EC_KEY_get0_group(key->ecdsa),
EC_KEY_get0_public_key(key->ecdsa)) != 0) {
r = SSH_ERR_KEY_INVALID_EC_VALUE;
goto out;
}
if (sshkey_ec_validate_public(EC_KEY_get0_group(key->ecdsa), q) != 0) {
ret = SSH_ERR_KEY_INVALID_EC_VALUE;
goto out;
/* success */
r = 0;
#ifdef DEBUG_PK
sshkey_dump_ec_point(EC_KEY_get0_group(key->ecdsa),
EC_KEY_get0_public_key(key->ecdsa));
#endif
out:
free(curve);
if (r != 0) {
EC_KEY_free(key->ecdsa);
key->ecdsa = NULL;
}
if (EC_KEY_set_public_key(key->ecdsa, q) != 1) {
/* XXX assume it is a allocation error */
ret = SSH_ERR_ALLOC_FAIL;
return r;
}

static int
ssh_ecdsa_deserialize_private(const char *ktype, struct sshbuf *b,
struct sshkey *key)
{
int r;
BIGNUM *exponent = NULL;

if (!sshkey_is_cert(key)) {
if ((r = ssh_ecdsa_deserialize_public(ktype, b, key)) != 0)
return r;
}
if ((r = sshbuf_get_bignum2(b, &exponent)) != 0)
goto out;
if (EC_KEY_set_private_key(key->ecdsa, exponent) != 1) {
r = SSH_ERR_LIBCRYPTO_ERROR;
goto out;
}
#ifdef DEBUG_PK
sshkey_dump_ec_point(EC_KEY_get0_group(key->ecdsa), q);
#endif
if ((r = sshkey_ec_validate_private(key->ecdsa)) != 0)
goto out;
/* success */
ret = 0;
r = 0;
out:
free(curve);
EC_POINT_free(q);
return ret;
BN_clear_free(exponent);
return r;
}

/* ARGSUSED */
Expand Down Expand Up @@ -359,6 +378,7 @@ const struct sshkey_impl_funcs sshkey_ecdsa_funcs = {
/* .ssh_serialize_public = */ ssh_ecdsa_serialize_public,
/* .ssh_deserialize_public = */ ssh_ecdsa_deserialize_public,
/* .ssh_serialize_private = */ ssh_ecdsa_serialize_private,
/* .ssh_deserialize_private = */ ssh_ecdsa_deserialize_private,
/* .generate = */ ssh_ecdsa_generate,
/* .copy_public = */ ssh_ecdsa_copy_public,
/* .sign = */ ssh_ecdsa_sign,
Expand Down
14 changes: 14 additions & 0 deletions ssh-ed25519-sk.c
Expand Up @@ -106,6 +106,19 @@ ssh_ed25519_sk_deserialize_public(const char *ktype, struct sshbuf *b,
return 0;
}

static int
ssh_ed25519_sk_deserialize_private(const char *ktype, struct sshbuf *b,
struct sshkey *key)
{
int r;

if ((r = sshkey_ed25519_funcs.deserialize_public(ktype, b, key)) != 0)
return r;
if ((r = sshkey_private_deserialize_sk(b, key)) != 0)
return r;
return 0;
}

static int
ssh_ed25519_sk_verify(const struct sshkey *key,
const u_char *sig, size_t siglen,
Expand Down Expand Up @@ -241,6 +254,7 @@ static const struct sshkey_impl_funcs sshkey_ed25519_sk_funcs = {
/* .ssh_serialize_public = */ ssh_ed25519_sk_serialize_public,
/* .ssh_deserialize_public = */ ssh_ed25519_sk_deserialize_public,
/* .ssh_serialize_private = */ ssh_ed25519_sk_serialize_private,
/* .ssh_deserialize_private = */ ssh_ed25519_sk_deserialize_private,
/* .generate = */ NULL,
/* .copy_public = */ ssh_ed25519_sk_copy_public,
/* .sign = */ NULL,
Expand Down
26 changes: 26 additions & 0 deletions ssh-ed25519.c
Expand Up @@ -114,6 +114,31 @@ ssh_ed25519_deserialize_public(const char *ktype, struct sshbuf *b,
return 0;
}

static int
ssh_ed25519_deserialize_private(const char *ktype, struct sshbuf *b,
struct sshkey *key)
{
int r;
size_t sklen = 0;
u_char *ed25519_sk = NULL;

if ((r = ssh_ed25519_deserialize_public(NULL, b, key)) != 0)
goto out;
if ((r = sshbuf_get_string(b, &ed25519_sk, &sklen)) != 0)
goto out;
if (sklen != ED25519_SK_SZ) {
r = SSH_ERR_INVALID_FORMAT;
goto out;
}
key->ed25519_sk = ed25519_sk;
ed25519_sk = NULL; /* transferred */
/* success */
r = 0;
out:
freezero(ed25519_sk, sklen);
return r;
}

static int
ssh_ed25519_sign(struct sshkey *key,
u_char **sigp, size_t *lenp,
Expand Down Expand Up @@ -253,6 +278,7 @@ const struct sshkey_impl_funcs sshkey_ed25519_funcs = {
/* .ssh_serialize_public = */ ssh_ed25519_serialize_public,
/* .ssh_deserialize_public = */ ssh_ed25519_deserialize_public,
/* .ssh_serialize_private = */ ssh_ed25519_serialize_private,
/* .ssh_deserialize_private = */ ssh_ed25519_deserialize_private,
/* .generate = */ ssh_ed25519_generate,
/* .copy_public = */ ssh_ed25519_copy_public,
/* .sign = */ ssh_ed25519_sign,
Expand Down
55 changes: 55 additions & 0 deletions ssh-rsa.c
Expand Up @@ -226,6 +226,60 @@ ssh_rsa_deserialize_public(const char *ktype, struct sshbuf *b,
return ret;
}

static int
ssh_rsa_deserialize_private(const char *ktype, struct sshbuf *b,
struct sshkey *key)
{
int r;
BIGNUM *rsa_n = NULL, *rsa_e = NULL, *rsa_d = NULL;
BIGNUM *rsa_iqmp = NULL, *rsa_p = NULL, *rsa_q = NULL;

/* Note: can't reuse ssh_rsa_deserialize_public: e, n vs. n, e */
if (!sshkey_is_cert(key)) {
if ((r = sshbuf_get_bignum2(b, &rsa_n)) != 0 ||
(r = sshbuf_get_bignum2(b, &rsa_e)) != 0)
goto out;
if (!RSA_set0_key(key->rsa, rsa_n, rsa_e, NULL)) {
r = SSH_ERR_LIBCRYPTO_ERROR;
goto out;
}
rsa_n = rsa_e = NULL; /* transferred */
}
if ((r = sshbuf_get_bignum2(b, &rsa_d)) != 0 ||
(r = sshbuf_get_bignum2(b, &rsa_iqmp)) != 0 ||
(r = sshbuf_get_bignum2(b, &rsa_p)) != 0 ||
(r = sshbuf_get_bignum2(b, &rsa_q)) != 0)
goto out;
if (!RSA_set0_key(key->rsa, NULL, NULL, rsa_d)) {
r = SSH_ERR_LIBCRYPTO_ERROR;
goto out;
}
rsa_d = NULL; /* transferred */
if (!RSA_set0_factors(key->rsa, rsa_p, rsa_q)) {
r = SSH_ERR_LIBCRYPTO_ERROR;
goto out;
}
rsa_p = rsa_q = NULL; /* transferred */
if ((r = sshkey_check_rsa_length(key, 0)) != 0)
goto out;
if ((r = ssh_rsa_complete_crt_parameters(key, rsa_iqmp)) != 0)
goto out;
if (RSA_blinding_on(key->rsa, NULL) != 1) {
r = SSH_ERR_LIBCRYPTO_ERROR;
goto out;
}
/* success */
r = 0;
out:
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);
return r;
}

static const char *
rsa_hash_alg_ident(int hash_alg)
{
Expand Down Expand Up @@ -645,6 +699,7 @@ static const struct sshkey_impl_funcs sshkey_rsa_funcs = {
/* .ssh_serialize_public = */ ssh_rsa_serialize_public,
/* .ssh_deserialize_public = */ ssh_rsa_deserialize_public,
/* .ssh_serialize_private = */ ssh_rsa_serialize_private,
/* .ssh_deserialize_private = */ ssh_rsa_deserialize_private,
/* .generate = */ ssh_rsa_generate,
/* .copy_public = */ ssh_rsa_copy_public,
/* .sign = */ ssh_rsa_sign,
Expand Down
38 changes: 38 additions & 0 deletions ssh-xmss.c
Expand Up @@ -155,6 +155,43 @@ ssh_xmss_deserialize_public(const char *ktype, struct sshbuf *b,
return ret;
}

static int
ssh_xmss_deserialize_private(const char *ktype, struct sshbuf *b,
struct sshkey *key)
{
int r;
char *xmss_name = NULL;
size_t pklen = 0, sklen = 0;
u_char *xmss_pk = NULL, *xmss_sk = NULL;

/* Note: can't reuse ssh_xmss_deserialize_public because of sk order */
if ((r = sshbuf_get_cstring(b, &xmss_name, NULL)) != 0 ||
(r = sshbuf_get_string(b, &xmss_pk, &pklen)) != 0 ||
(r = sshbuf_get_string(b, &xmss_sk, &sklen)) != 0)
goto out;
if (!sshkey_is_cert(key) &&
(r = sshkey_xmss_init(key, xmss_name)) != 0)
goto out;
if (pklen != sshkey_xmss_pklen(key) ||
sklen != sshkey_xmss_sklen(key)) {
r = SSH_ERR_INVALID_FORMAT;
goto out;
}
key->xmss_pk = xmss_pk;
key->xmss_sk = xmss_sk;
xmss_pk = xmss_sk = NULL;
/* optional internal state */
if ((r = sshkey_xmss_deserialize_state_opt(key, b)) != 0)
goto out;
/* success */
r = 0;
out:
free(xmss_name);
freezero(xmss_pk, pklen);
freezero(xmss_sk, sklen);
return r;
}

static int
ssh_xmss_sign(struct sshkey *key,
u_char **sigp, size_t *lenp,
Expand Down Expand Up @@ -314,6 +351,7 @@ static const struct sshkey_impl_funcs sshkey_xmss_funcs = {
/* .ssh_serialize_public = */ ssh_xmss_serialize_public,
/* .ssh_deserialize_public = */ ssh_xmss_deserialize_public,
/* .ssh_serialize_private = */ ssh_xmss_serialize_private,
/* .ssh_deserialize_private = */ ssh_xmss_deserialize_private,
/* .generate = */ sshkey_xmss_generate_private_key,
/* .copy_public = */ ssh_xmss_copy_publie,
/* .sign = */ ssh_xmss_sign,
Expand Down

0 comments on commit 82842ed

Please sign in to comment.