mirror of
git://anongit.mindrot.org/openssh.git
synced 2024-11-27 05:46:36 +08:00
upstream: refactor sshkey_from_blob_internal()
feedback/ok markus@ OpenBSD-Commit-ID: 1f46c0cbb8060ee9666a02749594ad6658c8e283
This commit is contained in:
parent
7d00799c93
commit
a1deb6cdbb
45
ssh-dss.c
45
ssh-dss.c
@ -1,4 +1,4 @@
|
||||
/* $OpenBSD: ssh-dss.c,v 1.44 2022/10/28 00:41:17 djm Exp $ */
|
||||
/* $OpenBSD: ssh-dss.c,v 1.45 2022/10/28 00:41:52 djm Exp $ */
|
||||
/*
|
||||
* Copyright (c) 2000 Markus Friedl. All rights reserved.
|
||||
*
|
||||
@ -104,7 +104,7 @@ ssh_dss_equal(const struct sshkey *a, const struct sshkey *b)
|
||||
|
||||
static int
|
||||
ssh_dss_serialize_public(const struct sshkey *key, struct sshbuf *b,
|
||||
const char *typename, enum sshkey_serialize_rep opts)
|
||||
enum sshkey_serialize_rep opts)
|
||||
{
|
||||
int r;
|
||||
const BIGNUM *dsa_p, *dsa_q, *dsa_g, *dsa_pub_key;
|
||||
@ -116,8 +116,7 @@ ssh_dss_serialize_public(const struct sshkey *key, struct sshbuf *b,
|
||||
if (dsa_p == NULL || dsa_q == NULL ||
|
||||
dsa_g == NULL || dsa_pub_key == NULL)
|
||||
return SSH_ERR_INTERNAL_ERROR;
|
||||
if ((r = sshbuf_put_cstring(b, typename)) != 0 ||
|
||||
(r = sshbuf_put_bignum2(b, dsa_p)) != 0 ||
|
||||
if ((r = sshbuf_put_bignum2(b, dsa_p)) != 0 ||
|
||||
(r = sshbuf_put_bignum2(b, dsa_q)) != 0 ||
|
||||
(r = sshbuf_put_bignum2(b, dsa_g)) != 0 ||
|
||||
(r = sshbuf_put_bignum2(b, dsa_pub_key)) != 0)
|
||||
@ -181,6 +180,43 @@ ssh_dss_copy_public(const struct sshkey *from, struct sshkey *to)
|
||||
return r;
|
||||
}
|
||||
|
||||
static int
|
||||
ssh_dss_deserialize_public(const char *ktype, struct sshbuf *b,
|
||||
struct sshkey *key)
|
||||
{
|
||||
int ret = SSH_ERR_INTERNAL_ERROR;
|
||||
BIGNUM *dsa_p = NULL, *dsa_q = NULL, *dsa_g = NULL, *dsa_pub_key = NULL;
|
||||
|
||||
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;
|
||||
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
|
||||
DSA_print_fp(stderr, key->dsa, 8);
|
||||
#endif
|
||||
/* success */
|
||||
ret = 0;
|
||||
out:
|
||||
BN_clear_free(dsa_p);
|
||||
BN_clear_free(dsa_q);
|
||||
BN_clear_free(dsa_g);
|
||||
BN_clear_free(dsa_pub_key);
|
||||
return ret;
|
||||
}
|
||||
|
||||
int
|
||||
ssh_dss_sign(const struct sshkey *key, u_char **sigp, size_t *lenp,
|
||||
const u_char *data, size_t datalen, u_int compat)
|
||||
@ -344,6 +380,7 @@ static const struct sshkey_impl_funcs sshkey_dss_funcs = {
|
||||
/* .cleanup = */ ssh_dss_cleanup,
|
||||
/* .equal = */ ssh_dss_equal,
|
||||
/* .ssh_serialize_public = */ ssh_dss_serialize_public,
|
||||
/* .ssh_deserialize_public = */ ssh_dss_deserialize_public,
|
||||
/* .generate = */ ssh_dss_generate,
|
||||
/* .copy_public = */ ssh_dss_copy_public,
|
||||
};
|
||||
|
@ -1,4 +1,4 @@
|
||||
/* $OpenBSD: ssh-ecdsa-sk.c,v 1.13 2022/10/28 00:41:17 djm Exp $ */
|
||||
/* $OpenBSD: ssh-ecdsa-sk.c,v 1.14 2022/10/28 00:41:52 djm Exp $ */
|
||||
/*
|
||||
* Copyright (c) 2000 Markus Friedl. All rights reserved.
|
||||
* Copyright (c) 2010 Damien Miller. All rights reserved.
|
||||
@ -83,12 +83,11 @@ ssh_ecdsa_sk_equal(const struct sshkey *a, const struct sshkey *b)
|
||||
|
||||
static int
|
||||
ssh_ecdsa_sk_serialize_public(const struct sshkey *key, struct sshbuf *b,
|
||||
const char *typename, enum sshkey_serialize_rep opts)
|
||||
enum sshkey_serialize_rep opts)
|
||||
{
|
||||
int r;
|
||||
|
||||
if ((r = sshkey_ecdsa_funcs.serialize_public(key, b,
|
||||
typename, opts)) != 0)
|
||||
if ((r = sshkey_ecdsa_funcs.serialize_public(key, b, opts)) != 0)
|
||||
return r;
|
||||
if ((r = sshkey_serialize_sk(key, b)) != 0)
|
||||
return r;
|
||||
@ -108,6 +107,19 @@ ssh_ecdsa_sk_copy_public(const struct sshkey *from, struct sshkey *to)
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int
|
||||
ssh_ecdsa_sk_deserialize_public(const char *ktype, struct sshbuf *b,
|
||||
struct sshkey *key)
|
||||
{
|
||||
int r;
|
||||
|
||||
if ((r = sshkey_ecdsa_funcs.deserialize_public(ktype, b, key)) != 0)
|
||||
return r;
|
||||
if ((r = sshkey_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.
|
||||
@ -374,6 +386,7 @@ static const struct sshkey_impl_funcs sshkey_ecdsa_sk_funcs = {
|
||||
/* .cleanup = */ ssh_ecdsa_sk_cleanup,
|
||||
/* .equal = */ ssh_ecdsa_sk_equal,
|
||||
/* .ssh_serialize_public = */ ssh_ecdsa_sk_serialize_public,
|
||||
/* .ssh_deserialize_public = */ ssh_ecdsa_sk_deserialize_public,
|
||||
/* .generate = */ NULL,
|
||||
/* .copy_public = */ ssh_ecdsa_sk_copy_public,
|
||||
};
|
||||
|
58
ssh-ecdsa.c
58
ssh-ecdsa.c
@ -1,4 +1,4 @@
|
||||
/* $OpenBSD: ssh-ecdsa.c,v 1.21 2022/10/28 00:41:17 djm Exp $ */
|
||||
/* $OpenBSD: ssh-ecdsa.c,v 1.22 2022/10/28 00:41:52 djm Exp $ */
|
||||
/*
|
||||
* Copyright (c) 2000 Markus Friedl. All rights reserved.
|
||||
* Copyright (c) 2010 Damien Miller. All rights reserved.
|
||||
@ -93,14 +93,13 @@ ssh_ecdsa_equal(const struct sshkey *a, const struct sshkey *b)
|
||||
|
||||
static int
|
||||
ssh_ecdsa_serialize_public(const struct sshkey *key, struct sshbuf *b,
|
||||
const char *typename, enum sshkey_serialize_rep opts)
|
||||
enum sshkey_serialize_rep opts)
|
||||
{
|
||||
int r;
|
||||
|
||||
if (key->ecdsa == NULL)
|
||||
return SSH_ERR_INVALID_ARGUMENT;
|
||||
if ((r = sshbuf_put_cstring(b, typename)) != 0 ||
|
||||
(r = sshbuf_put_cstring(b,
|
||||
if ((r = sshbuf_put_cstring(b,
|
||||
sshkey_curve_nid_to_name(key->ecdsa_nid))) != 0 ||
|
||||
(r = sshbuf_put_eckey(b, key->ecdsa)) != 0)
|
||||
return r;
|
||||
@ -138,6 +137,56 @@ ssh_ecdsa_copy_public(const struct sshkey *from, struct sshkey *to)
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int
|
||||
ssh_ecdsa_deserialize_public(const char *ktype, struct sshbuf *b,
|
||||
struct sshkey *key)
|
||||
{
|
||||
int ret = SSH_ERR_INTERNAL_ERROR;
|
||||
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;
|
||||
goto out;
|
||||
}
|
||||
if (key->ecdsa_nid != sshkey_curve_name_to_nid(curve)) {
|
||||
ret = SSH_ERR_EC_CURVE_MISMATCH;
|
||||
goto out;
|
||||
}
|
||||
EC_KEY_free(key->ecdsa);
|
||||
if ((key->ecdsa = EC_KEY_new_by_curve_name(key->ecdsa_nid)) == NULL) {
|
||||
ret = SSH_ERR_EC_CURVE_INVALID;
|
||||
goto out;
|
||||
}
|
||||
if ((q = EC_POINT_new(EC_KEY_get0_group(key->ecdsa))) == NULL) {
|
||||
ret = SSH_ERR_ALLOC_FAIL;
|
||||
goto out;
|
||||
}
|
||||
if (sshbuf_get_ec(b, q, EC_KEY_get0_group(key->ecdsa)) != 0) {
|
||||
ret = SSH_ERR_INVALID_FORMAT;
|
||||
goto out;
|
||||
}
|
||||
if (sshkey_ec_validate_public(EC_KEY_get0_group(key->ecdsa), q) != 0) {
|
||||
ret = SSH_ERR_KEY_INVALID_EC_VALUE;
|
||||
goto out;
|
||||
}
|
||||
if (EC_KEY_set_public_key(key->ecdsa, q) != 1) {
|
||||
/* XXX assume it is a allocation error */
|
||||
ret = SSH_ERR_ALLOC_FAIL;
|
||||
goto out;
|
||||
}
|
||||
#ifdef DEBUG_PK
|
||||
sshkey_dump_ec_point(EC_KEY_get0_group(key->ecdsa), q);
|
||||
#endif
|
||||
/* success */
|
||||
ret = 0;
|
||||
out:
|
||||
free(curve);
|
||||
EC_POINT_free(q);
|
||||
return ret;
|
||||
}
|
||||
|
||||
/* ARGSUSED */
|
||||
int
|
||||
ssh_ecdsa_sign(const struct sshkey *key, u_char **sigp, size_t *lenp,
|
||||
@ -297,6 +346,7 @@ const struct sshkey_impl_funcs sshkey_ecdsa_funcs = {
|
||||
/* .cleanup = */ ssh_ecdsa_cleanup,
|
||||
/* .equal = */ ssh_ecdsa_equal,
|
||||
/* .ssh_serialize_public = */ ssh_ecdsa_serialize_public,
|
||||
/* .ssh_deserialize_public = */ ssh_ecdsa_deserialize_public,
|
||||
/* .generate = */ ssh_ecdsa_generate,
|
||||
/* .copy_public = */ ssh_ecdsa_copy_public,
|
||||
};
|
||||
|
@ -1,4 +1,4 @@
|
||||
/* $OpenBSD: ssh-ed25519-sk.c,v 1.11 2022/10/28 00:41:17 djm Exp $ */
|
||||
/* $OpenBSD: ssh-ed25519-sk.c,v 1.12 2022/10/28 00:41:52 djm Exp $ */
|
||||
/*
|
||||
* Copyright (c) 2019 Markus Friedl. All rights reserved.
|
||||
*
|
||||
@ -57,12 +57,11 @@ ssh_ed25519_sk_equal(const struct sshkey *a, const struct sshkey *b)
|
||||
|
||||
static int
|
||||
ssh_ed25519_sk_serialize_public(const struct sshkey *key, struct sshbuf *b,
|
||||
const char *typename, enum sshkey_serialize_rep opts)
|
||||
enum sshkey_serialize_rep opts)
|
||||
{
|
||||
int r;
|
||||
|
||||
if ((r = sshkey_ed25519_funcs.serialize_public(key, b,
|
||||
typename, opts)) != 0)
|
||||
if ((r = sshkey_ed25519_funcs.serialize_public(key, b, opts)) != 0)
|
||||
return r;
|
||||
if ((r = sshkey_serialize_sk(key, b)) != 0)
|
||||
return r;
|
||||
@ -82,6 +81,19 @@ ssh_ed25519_sk_copy_public(const struct sshkey *from, struct sshkey *to)
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int
|
||||
ssh_ed25519_sk_deserialize_public(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_deserialize_sk(b, key)) != 0)
|
||||
return r;
|
||||
return 0;
|
||||
}
|
||||
|
||||
int
|
||||
ssh_ed25519_sk_verify(const struct sshkey *key,
|
||||
const u_char *signature, size_t signaturelen,
|
||||
@ -215,6 +227,7 @@ static const struct sshkey_impl_funcs sshkey_ed25519_sk_funcs = {
|
||||
/* .cleanup = */ ssh_ed25519_sk_cleanup,
|
||||
/* .equal = */ ssh_ed25519_sk_equal,
|
||||
/* .ssh_serialize_public = */ ssh_ed25519_sk_serialize_public,
|
||||
/* .ssh_deserialize_public = */ ssh_ed25519_sk_deserialize_public,
|
||||
/* .generate = */ NULL,
|
||||
/* .copy_public = */ ssh_ed25519_sk_copy_public,
|
||||
};
|
||||
|
@ -1,4 +1,4 @@
|
||||
/* $OpenBSD: ssh-ed25519.c,v 1.15 2022/10/28 00:41:17 djm Exp $ */
|
||||
/* $OpenBSD: ssh-ed25519.c,v 1.16 2022/10/28 00:41:52 djm Exp $ */
|
||||
/*
|
||||
* Copyright (c) 2013 Markus Friedl <markus@openbsd.org>
|
||||
*
|
||||
@ -53,14 +53,13 @@ ssh_ed25519_equal(const struct sshkey *a, const struct sshkey *b)
|
||||
|
||||
static int
|
||||
ssh_ed25519_serialize_public(const struct sshkey *key, struct sshbuf *b,
|
||||
const char *typename, enum sshkey_serialize_rep opts)
|
||||
enum sshkey_serialize_rep opts)
|
||||
{
|
||||
int r;
|
||||
|
||||
if (key->ed25519_pk == NULL)
|
||||
return SSH_ERR_INVALID_ARGUMENT;
|
||||
if ((r = sshbuf_put_cstring(b, typename)) != 0 ||
|
||||
(r = sshbuf_put_string(b, key->ed25519_pk, ED25519_PK_SZ)) != 0)
|
||||
if ((r = sshbuf_put_string(b, key->ed25519_pk, ED25519_PK_SZ)) != 0)
|
||||
return r;
|
||||
|
||||
return 0;
|
||||
@ -87,6 +86,24 @@ ssh_ed25519_copy_public(const struct sshkey *from, struct sshkey *to)
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int
|
||||
ssh_ed25519_deserialize_public(const char *ktype, struct sshbuf *b,
|
||||
struct sshkey *key)
|
||||
{
|
||||
u_char *pk = NULL;
|
||||
size_t len = 0;
|
||||
int r;
|
||||
|
||||
if ((r = sshbuf_get_string(b, &pk, &len)) != 0)
|
||||
return r;
|
||||
if (len != ED25519_PK_SZ) {
|
||||
freezero(pk, len);
|
||||
return SSH_ERR_INVALID_FORMAT;
|
||||
}
|
||||
key->ed25519_pk = pk;
|
||||
return 0;
|
||||
}
|
||||
|
||||
int
|
||||
ssh_ed25519_sign(const struct sshkey *key, u_char **sigp, size_t *lenp,
|
||||
const u_char *data, size_t datalen, u_int compat)
|
||||
@ -221,6 +238,7 @@ const struct sshkey_impl_funcs sshkey_ed25519_funcs = {
|
||||
/* .cleanup = */ ssh_ed25519_cleanup,
|
||||
/* .equal = */ ssh_ed25519_equal,
|
||||
/* .ssh_serialize_public = */ ssh_ed25519_serialize_public,
|
||||
/* .ssh_deserialize_public = */ ssh_ed25519_deserialize_public,
|
||||
/* .generate = */ ssh_ed25519_generate,
|
||||
/* .copy_public = */ ssh_ed25519_copy_public,
|
||||
};
|
||||
|
58
ssh-rsa.c
58
ssh-rsa.c
@ -1,4 +1,4 @@
|
||||
/* $OpenBSD: ssh-rsa.c,v 1.73 2022/10/28 00:41:17 djm Exp $ */
|
||||
/* $OpenBSD: ssh-rsa.c,v 1.74 2022/10/28 00:41:52 djm Exp $ */
|
||||
/*
|
||||
* Copyright (c) 2000, 2003 Markus Friedl <markus@openbsd.org>
|
||||
*
|
||||
@ -39,6 +39,26 @@
|
||||
|
||||
static int openssh_RSA_verify(int, u_char *, size_t, u_char *, size_t, RSA *);
|
||||
|
||||
int
|
||||
sshkey_check_rsa_length(const struct sshkey *k, int min_size)
|
||||
{
|
||||
#ifdef WITH_OPENSSL
|
||||
const BIGNUM *rsa_n;
|
||||
int nbits;
|
||||
|
||||
if (k == NULL || k->rsa == NULL ||
|
||||
(k->type != KEY_RSA && k->type != KEY_RSA_CERT))
|
||||
return 0;
|
||||
RSA_get0_key(k->rsa, &rsa_n, NULL, NULL);
|
||||
nbits = BN_num_bits(rsa_n);
|
||||
if (nbits < SSH_RSA_MINIMUM_MODULUS_SIZE ||
|
||||
(min_size > 0 && nbits < min_size))
|
||||
return SSH_ERR_KEY_LENGTH;
|
||||
#endif /* WITH_OPENSSL */
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
static u_int
|
||||
ssh_rsa_size(const struct sshkey *key)
|
||||
{
|
||||
@ -88,7 +108,7 @@ ssh_rsa_equal(const struct sshkey *a, const struct sshkey *b)
|
||||
|
||||
static int
|
||||
ssh_rsa_serialize_public(const struct sshkey *key, struct sshbuf *b,
|
||||
const char *typename, enum sshkey_serialize_rep opts)
|
||||
enum sshkey_serialize_rep opts)
|
||||
{
|
||||
int r;
|
||||
const BIGNUM *rsa_n, *rsa_e;
|
||||
@ -96,8 +116,7 @@ ssh_rsa_serialize_public(const struct sshkey *key, struct sshbuf *b,
|
||||
if (key->rsa == NULL)
|
||||
return SSH_ERR_INVALID_ARGUMENT;
|
||||
RSA_get0_key(key->rsa, &rsa_n, &rsa_e, NULL);
|
||||
if ((r = sshbuf_put_cstring(b, typename)) != 0 ||
|
||||
(r = sshbuf_put_bignum2(b, rsa_e)) != 0 ||
|
||||
if ((r = sshbuf_put_bignum2(b, rsa_e)) != 0 ||
|
||||
(r = sshbuf_put_bignum2(b, rsa_n)) != 0)
|
||||
return r;
|
||||
|
||||
@ -158,6 +177,36 @@ ssh_rsa_copy_public(const struct sshkey *from, struct sshkey *to)
|
||||
return r;
|
||||
}
|
||||
|
||||
static int
|
||||
ssh_rsa_deserialize_public(const char *ktype, struct sshbuf *b,
|
||||
struct sshkey *key)
|
||||
{
|
||||
int ret = SSH_ERR_INTERNAL_ERROR;
|
||||
BIGNUM *rsa_n = NULL, *rsa_e = NULL;
|
||||
|
||||
if (sshbuf_get_bignum2(b, &rsa_e) != 0 ||
|
||||
sshbuf_get_bignum2(b, &rsa_n) != 0) {
|
||||
ret = SSH_ERR_INVALID_FORMAT;
|
||||
goto out;
|
||||
}
|
||||
if (!RSA_set0_key(key->rsa, rsa_n, rsa_e, NULL)) {
|
||||
ret = SSH_ERR_LIBCRYPTO_ERROR;
|
||||
goto out;
|
||||
}
|
||||
rsa_n = rsa_e = NULL; /* transferred */
|
||||
if ((ret = sshkey_check_rsa_length(key, 0)) != 0)
|
||||
goto out;
|
||||
#ifdef DEBUG_PK
|
||||
RSA_print_fp(stderr, key->rsa, 8);
|
||||
#endif
|
||||
/* success */
|
||||
ret = 0;
|
||||
out:
|
||||
BN_clear_free(rsa_n);
|
||||
BN_clear_free(rsa_e);
|
||||
return ret;
|
||||
}
|
||||
|
||||
static const char *
|
||||
rsa_hash_alg_ident(int hash_alg)
|
||||
{
|
||||
@ -572,6 +621,7 @@ static const struct sshkey_impl_funcs sshkey_rsa_funcs = {
|
||||
/* .cleanup = */ ssh_rsa_cleanup,
|
||||
/* .equal = */ ssh_rsa_equal,
|
||||
/* .ssh_serialize_public = */ ssh_rsa_serialize_public,
|
||||
/* .ssh_deserialize_public = */ ssh_rsa_deserialize_public,
|
||||
/* .generate = */ ssh_rsa_generate,
|
||||
/* .copy_public = */ ssh_rsa_copy_public,
|
||||
};
|
||||
|
40
ssh-xmss.c
40
ssh-xmss.c
@ -1,4 +1,4 @@
|
||||
/* $OpenBSD: ssh-xmss.c,v 1.10 2022/10/28 00:41:17 djm Exp $*/
|
||||
/* $OpenBSD: ssh-xmss.c,v 1.11 2022/10/28 00:41:52 djm Exp $*/
|
||||
/*
|
||||
* Copyright (c) 2017 Stefan-Lukas Gazdag.
|
||||
* Copyright (c) 2017 Markus Friedl.
|
||||
@ -65,15 +65,14 @@ ssh_xmss_equal(const struct sshkey *a, const struct sshkey *b)
|
||||
|
||||
static int
|
||||
ssh_xmss_serialize_public(const struct sshkey *key, struct sshbuf *b,
|
||||
const char *typename, enum sshkey_serialize_rep opts)
|
||||
enum sshkey_serialize_rep opts)
|
||||
{
|
||||
int r;
|
||||
|
||||
if (key->xmss_name == NULL || key->xmss_pk == NULL ||
|
||||
sshkey_xmss_pklen(key) == 0)
|
||||
return SSH_ERR_INVALID_ARGUMENT;
|
||||
if ((r = sshbuf_put_cstring(b, typename)) != 0 ||
|
||||
(r = sshbuf_put_cstring(b, key->xmss_name)) != 0 ||
|
||||
if ((r = sshbuf_put_cstring(b, key->xmss_name)) != 0 ||
|
||||
(r = sshbuf_put_string(b, key->xmss_pk,
|
||||
sshkey_xmss_pklen(key))) != 0 ||
|
||||
(r = sshkey_xmss_serialize_pk_info(key, b, opts)) != 0)
|
||||
@ -107,6 +106,38 @@ ssh_xmss_copy_public(const struct sshkey *from, struct sshkey *to)
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int
|
||||
ssh_xmss_deserialize_public(const char *ktype, struct sshbuf *b,
|
||||
struct sshkey *key)
|
||||
{
|
||||
size_t len = 0;
|
||||
char *xmss_name = NULL;
|
||||
u_char *pk = NULL;
|
||||
int ret = SSH_ERR_INTERNAL_ERROR;
|
||||
|
||||
if ((ret = sshbuf_get_cstring(b, &xmss_name, NULL)) != 0)
|
||||
goto out;
|
||||
if ((ret = sshkey_xmss_init(key, xmss_name)) != 0)
|
||||
goto out;
|
||||
if ((ret = sshbuf_get_string(b, &pk, &len)) != 0)
|
||||
goto out;
|
||||
if (len == 0 || len != sshkey_xmss_pklen(key)) {
|
||||
ret = SSH_ERR_INVALID_FORMAT;
|
||||
goto out;
|
||||
}
|
||||
key->xmss_pk = pk;
|
||||
pk = NULL;
|
||||
if (!sshkey_is_cert(key) &&
|
||||
(ret = sshkey_xmss_deserialize_pk_info(key, b)) != 0)
|
||||
goto out;
|
||||
/* success */
|
||||
ret = 0;
|
||||
out:
|
||||
free(xmss_name);
|
||||
freezero(pk, len);
|
||||
return ret;
|
||||
}
|
||||
|
||||
int
|
||||
ssh_xmss_sign(const struct sshkey *key, u_char **sigp, size_t *lenp,
|
||||
const u_char *data, size_t datalen, u_int compat)
|
||||
@ -261,6 +292,7 @@ static const struct sshkey_impl_funcs sshkey_xmss_funcs = {
|
||||
/* .cleanup = */ ssh_xmss_cleanup,
|
||||
/* .equal = */ ssh_xmss_equal,
|
||||
/* .ssh_serialize_public = */ ssh_xmss_serialize_public,
|
||||
/* .ssh_deserialize_public = */ ssh_xmss_deserialize_public,
|
||||
/* .generate = */ sshkey_xmss_generate_private_key,
|
||||
/* .copy_public = */ ssh_xmss_copy_public,
|
||||
};
|
||||
|
258
sshkey.c
258
sshkey.c
@ -1,4 +1,4 @@
|
||||
/* $OpenBSD: sshkey.c,v 1.128 2022/10/28 00:41:17 djm Exp $ */
|
||||
/* $OpenBSD: sshkey.c,v 1.129 2022/10/28 00:41:52 djm Exp $ */
|
||||
/*
|
||||
* Copyright (c) 2000, 2001 Markus Friedl. All rights reserved.
|
||||
* Copyright (c) 2008 Alexander von Gernler. All rights reserved.
|
||||
@ -734,7 +734,9 @@ to_blob_buf(const struct sshkey *key, struct sshbuf *b, int force_plain,
|
||||
return SSH_ERR_KEY_TYPE_UNKNOWN;
|
||||
|
||||
typename = sshkey_ssh_name_from_type_nid(type, key->ecdsa_nid);
|
||||
return impl->funcs->serialize_public(key, b, typename, opts);
|
||||
if ((ret = sshbuf_put_cstring(b, typename)) != 0)
|
||||
return ret;
|
||||
return impl->funcs->serialize_public(key, b, opts);
|
||||
}
|
||||
|
||||
int
|
||||
@ -1833,21 +1835,11 @@ cert_parse(struct sshbuf *b, struct sshkey *key, struct sshbuf *certbuf)
|
||||
}
|
||||
|
||||
int
|
||||
sshkey_check_rsa_length(const struct sshkey *k, int min_size)
|
||||
sshkey_deserialize_sk(struct sshbuf *b, struct sshkey *key)
|
||||
{
|
||||
#ifdef WITH_OPENSSL
|
||||
const BIGNUM *rsa_n;
|
||||
int nbits;
|
||||
|
||||
if (k == NULL || k->rsa == NULL ||
|
||||
(k->type != KEY_RSA && k->type != KEY_RSA_CERT))
|
||||
return 0;
|
||||
RSA_get0_key(k->rsa, &rsa_n, NULL, NULL);
|
||||
nbits = BN_num_bits(rsa_n);
|
||||
if (nbits < SSH_RSA_MINIMUM_MODULUS_SIZE ||
|
||||
(min_size > 0 && nbits < min_size))
|
||||
return SSH_ERR_KEY_LENGTH;
|
||||
#endif /* WITH_OPENSSL */
|
||||
/* Parse additional security-key application string */
|
||||
if (sshbuf_get_cstring(b, &key->sk_application, NULL) != 0)
|
||||
return SSH_ERR_INVALID_FORMAT;
|
||||
return 0;
|
||||
}
|
||||
|
||||
@ -1856,18 +1848,10 @@ sshkey_from_blob_internal(struct sshbuf *b, struct sshkey **keyp,
|
||||
int allow_cert)
|
||||
{
|
||||
int type, ret = SSH_ERR_INTERNAL_ERROR;
|
||||
char *ktype = NULL, *curve = NULL, *xmss_name = NULL;
|
||||
char *ktype = NULL;
|
||||
struct sshkey *key = NULL;
|
||||
size_t len;
|
||||
u_char *pk = NULL;
|
||||
struct sshbuf *copy;
|
||||
#if defined(WITH_OPENSSL)
|
||||
BIGNUM *rsa_n = NULL, *rsa_e = NULL;
|
||||
BIGNUM *dsa_p = NULL, *dsa_q = NULL, *dsa_g = NULL, *dsa_pub_key = NULL;
|
||||
# if defined(OPENSSL_HAS_ECC)
|
||||
EC_POINT *q = NULL;
|
||||
# endif /* OPENSSL_HAS_ECC */
|
||||
#endif /* WITH_OPENSSL */
|
||||
const struct sshkey_impl *impl;
|
||||
|
||||
#ifdef DEBUG_PK /* XXX */
|
||||
sshbuf_dump(b, stderr);
|
||||
@ -1888,203 +1872,23 @@ sshkey_from_blob_internal(struct sshbuf *b, struct sshkey **keyp,
|
||||
ret = SSH_ERR_KEY_CERT_INVALID_SIGN_KEY;
|
||||
goto out;
|
||||
}
|
||||
switch (type) {
|
||||
#ifdef WITH_OPENSSL
|
||||
case KEY_RSA_CERT:
|
||||
/* Skip nonce */
|
||||
if (sshbuf_get_string_direct(b, NULL, NULL) != 0) {
|
||||
ret = SSH_ERR_INVALID_FORMAT;
|
||||
goto out;
|
||||
}
|
||||
/* FALLTHROUGH */
|
||||
case KEY_RSA:
|
||||
if ((key = sshkey_new(type)) == 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;
|
||||
goto out;
|
||||
}
|
||||
if (!RSA_set0_key(key->rsa, rsa_n, rsa_e, NULL)) {
|
||||
ret = SSH_ERR_LIBCRYPTO_ERROR;
|
||||
goto out;
|
||||
}
|
||||
rsa_n = rsa_e = NULL; /* transferred */
|
||||
if ((ret = sshkey_check_rsa_length(key, 0)) != 0)
|
||||
goto out;
|
||||
#ifdef DEBUG_PK
|
||||
RSA_print_fp(stderr, key->rsa, 8);
|
||||
#endif
|
||||
break;
|
||||
case KEY_DSA_CERT:
|
||||
/* Skip nonce */
|
||||
if (sshbuf_get_string_direct(b, NULL, NULL) != 0) {
|
||||
ret = SSH_ERR_INVALID_FORMAT;
|
||||
goto out;
|
||||
}
|
||||
/* FALLTHROUGH */
|
||||
case KEY_DSA:
|
||||
if ((key = sshkey_new(type)) == 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;
|
||||
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
|
||||
DSA_print_fp(stderr, key->dsa, 8);
|
||||
#endif
|
||||
break;
|
||||
# ifdef OPENSSL_HAS_ECC
|
||||
case KEY_ECDSA_CERT:
|
||||
case KEY_ECDSA_SK_CERT:
|
||||
/* Skip nonce */
|
||||
if (sshbuf_get_string_direct(b, NULL, NULL) != 0) {
|
||||
ret = SSH_ERR_INVALID_FORMAT;
|
||||
goto out;
|
||||
}
|
||||
/* FALLTHROUGH */
|
||||
case KEY_ECDSA:
|
||||
case KEY_ECDSA_SK:
|
||||
if ((key = sshkey_new(type)) == NULL) {
|
||||
ret = SSH_ERR_ALLOC_FAIL;
|
||||
goto out;
|
||||
}
|
||||
key->ecdsa_nid = sshkey_ecdsa_nid_from_name(ktype);
|
||||
if (sshbuf_get_cstring(b, &curve, NULL) != 0) {
|
||||
ret = SSH_ERR_INVALID_FORMAT;
|
||||
goto out;
|
||||
}
|
||||
if (key->ecdsa_nid != sshkey_curve_name_to_nid(curve)) {
|
||||
ret = SSH_ERR_EC_CURVE_MISMATCH;
|
||||
goto out;
|
||||
}
|
||||
EC_KEY_free(key->ecdsa);
|
||||
if ((key->ecdsa = EC_KEY_new_by_curve_name(key->ecdsa_nid))
|
||||
== NULL) {
|
||||
ret = SSH_ERR_EC_CURVE_INVALID;
|
||||
goto out;
|
||||
}
|
||||
if ((q = EC_POINT_new(EC_KEY_get0_group(key->ecdsa))) == NULL) {
|
||||
ret = SSH_ERR_ALLOC_FAIL;
|
||||
goto out;
|
||||
}
|
||||
if (sshbuf_get_ec(b, q, EC_KEY_get0_group(key->ecdsa)) != 0) {
|
||||
ret = SSH_ERR_INVALID_FORMAT;
|
||||
goto out;
|
||||
}
|
||||
if (sshkey_ec_validate_public(EC_KEY_get0_group(key->ecdsa),
|
||||
q) != 0) {
|
||||
ret = SSH_ERR_KEY_INVALID_EC_VALUE;
|
||||
goto out;
|
||||
}
|
||||
if (EC_KEY_set_public_key(key->ecdsa, q) != 1) {
|
||||
/* XXX assume it is a allocation error */
|
||||
ret = SSH_ERR_ALLOC_FAIL;
|
||||
goto out;
|
||||
}
|
||||
#ifdef DEBUG_PK
|
||||
sshkey_dump_ec_point(EC_KEY_get0_group(key->ecdsa), q);
|
||||
#endif
|
||||
if (type == KEY_ECDSA_SK || type == KEY_ECDSA_SK_CERT) {
|
||||
/* Parse additional security-key application string */
|
||||
if (sshbuf_get_cstring(b, &key->sk_application,
|
||||
NULL) != 0) {
|
||||
ret = SSH_ERR_INVALID_FORMAT;
|
||||
goto out;
|
||||
}
|
||||
#ifdef DEBUG_PK
|
||||
fprintf(stderr, "App: %s\n", key->sk_application);
|
||||
#endif
|
||||
}
|
||||
break;
|
||||
# endif /* OPENSSL_HAS_ECC */
|
||||
#endif /* WITH_OPENSSL */
|
||||
case KEY_ED25519_CERT:
|
||||
case KEY_ED25519_SK_CERT:
|
||||
/* Skip nonce */
|
||||
if (sshbuf_get_string_direct(b, NULL, NULL) != 0) {
|
||||
ret = SSH_ERR_INVALID_FORMAT;
|
||||
goto out;
|
||||
}
|
||||
/* FALLTHROUGH */
|
||||
case KEY_ED25519:
|
||||
case KEY_ED25519_SK:
|
||||
if ((ret = sshbuf_get_string(b, &pk, &len)) != 0)
|
||||
goto out;
|
||||
if (len != ED25519_PK_SZ) {
|
||||
ret = SSH_ERR_INVALID_FORMAT;
|
||||
goto out;
|
||||
}
|
||||
if ((key = sshkey_new(type)) == NULL) {
|
||||
ret = SSH_ERR_ALLOC_FAIL;
|
||||
goto out;
|
||||
}
|
||||
if (type == KEY_ED25519_SK || type == KEY_ED25519_SK_CERT) {
|
||||
/* Parse additional security-key application string */
|
||||
if (sshbuf_get_cstring(b, &key->sk_application,
|
||||
NULL) != 0) {
|
||||
ret = SSH_ERR_INVALID_FORMAT;
|
||||
goto out;
|
||||
}
|
||||
#ifdef DEBUG_PK
|
||||
fprintf(stderr, "App: %s\n", key->sk_application);
|
||||
#endif
|
||||
}
|
||||
key->ed25519_pk = pk;
|
||||
pk = NULL;
|
||||
break;
|
||||
#ifdef WITH_XMSS
|
||||
case KEY_XMSS_CERT:
|
||||
/* Skip nonce */
|
||||
if (sshbuf_get_string_direct(b, NULL, NULL) != 0) {
|
||||
ret = SSH_ERR_INVALID_FORMAT;
|
||||
goto out;
|
||||
}
|
||||
/* FALLTHROUGH */
|
||||
case KEY_XMSS:
|
||||
if ((ret = sshbuf_get_cstring(b, &xmss_name, NULL)) != 0)
|
||||
goto out;
|
||||
if ((key = sshkey_new(type)) == NULL) {
|
||||
ret = SSH_ERR_ALLOC_FAIL;
|
||||
goto out;
|
||||
}
|
||||
if ((ret = sshkey_xmss_init(key, xmss_name)) != 0)
|
||||
goto out;
|
||||
if ((ret = sshbuf_get_string(b, &pk, &len)) != 0)
|
||||
goto out;
|
||||
if (len == 0 || len != sshkey_xmss_pklen(key)) {
|
||||
ret = SSH_ERR_INVALID_FORMAT;
|
||||
goto out;
|
||||
}
|
||||
key->xmss_pk = pk;
|
||||
pk = NULL;
|
||||
if (type != KEY_XMSS_CERT &&
|
||||
(ret = sshkey_xmss_deserialize_pk_info(key, b)) != 0)
|
||||
goto out;
|
||||
break;
|
||||
#endif /* WITH_XMSS */
|
||||
case KEY_UNSPEC:
|
||||
default:
|
||||
if ((impl = sshkey_impl_from_type(type)) == NULL) {
|
||||
ret = SSH_ERR_KEY_TYPE_UNKNOWN;
|
||||
goto out;
|
||||
}
|
||||
if ((key = sshkey_new(type)) == NULL) {
|
||||
ret = SSH_ERR_ALLOC_FAIL;
|
||||
goto out;
|
||||
}
|
||||
if (sshkey_type_is_cert(type)) {
|
||||
/* Skip nonce that preceeds all certificates */
|
||||
if (sshbuf_get_string_direct(b, NULL, NULL) != 0) {
|
||||
ret = SSH_ERR_INVALID_FORMAT;
|
||||
goto out;
|
||||
}
|
||||
}
|
||||
if ((ret = impl->funcs->deserialize_public(ktype, b, key)) != 0)
|
||||
goto out;
|
||||
|
||||
/* Parse certificate potion */
|
||||
if (sshkey_is_cert(key) && (ret = cert_parse(b, key, copy)) != 0)
|
||||
@ -2102,21 +1906,7 @@ sshkey_from_blob_internal(struct sshbuf *b, struct sshkey **keyp,
|
||||
out:
|
||||
sshbuf_free(copy);
|
||||
sshkey_free(key);
|
||||
free(xmss_name);
|
||||
free(ktype);
|
||||
free(curve);
|
||||
free(pk);
|
||||
#if defined(WITH_OPENSSL)
|
||||
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);
|
||||
# if defined(OPENSSL_HAS_ECC)
|
||||
EC_POINT_free(q);
|
||||
# endif /* OPENSSL_HAS_ECC */
|
||||
#endif /* WITH_OPENSSL */
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
10
sshkey.h
10
sshkey.h
@ -1,4 +1,4 @@
|
||||
/* $OpenBSD: sshkey.h,v 1.57 2022/10/28 00:41:17 djm Exp $ */
|
||||
/* $OpenBSD: sshkey.h,v 1.58 2022/10/28 00:41:52 djm Exp $ */
|
||||
|
||||
/*
|
||||
* Copyright (c) 2000, 2001 Markus Friedl. All rights reserved.
|
||||
@ -170,7 +170,9 @@ struct sshkey_impl_funcs {
|
||||
void (*cleanup)(struct sshkey *); /* optional */
|
||||
int (*equal)(const struct sshkey *, const struct sshkey *);
|
||||
int (*serialize_public)(const struct sshkey *, struct sshbuf *,
|
||||
const char *, enum sshkey_serialize_rep);
|
||||
enum sshkey_serialize_rep);
|
||||
int (*deserialize_public)(const char *, struct sshbuf *,
|
||||
struct sshkey *);
|
||||
int (*generate)(struct sshkey *, int); /* optional */
|
||||
int (*copy_public)(const struct sshkey *, struct sshkey *);
|
||||
};
|
||||
@ -315,6 +317,10 @@ int sshkey_sk_fields_equal(const struct sshkey *a, const struct sshkey *b);
|
||||
void sshkey_sk_cleanup(struct sshkey *k);
|
||||
int sshkey_serialize_sk(const struct sshkey *key, struct sshbuf *b);
|
||||
int sshkey_copy_public_sk(const struct sshkey *from, struct sshkey *to);
|
||||
int sshkey_deserialize_sk(struct sshbuf *b, struct sshkey *key);
|
||||
#ifdef WITH_OPENSSL
|
||||
int check_rsa_length(const RSA *rsa); /* XXX remove */
|
||||
#endif
|
||||
|
||||
int ssh_rsa_sign(const struct sshkey *key,
|
||||
u_char **sigp, size_t *lenp, const u_char *data, size_t datalen,
|
||||
|
Loading…
Reference in New Issue
Block a user