upstream: factor out public key serialization

feedback/ok markus@

OpenBSD-Commit-ID: a3570c4b97290c5662890aea7328d87f55939033
This commit is contained in:
djm@openbsd.org 2022-10-28 00:37:24 +00:00 committed by Damien Miller
parent 1e78844ae2
commit 591fed94e6
No known key found for this signature in database
9 changed files with 166 additions and 101 deletions

View File

@ -1,4 +1,4 @@
/* $OpenBSD: ssh-dss.c,v 1.41 2022/10/28 00:36:31 djm Exp $ */
/* $OpenBSD: ssh-dss.c,v 1.42 2022/10/28 00:37:24 djm Exp $ */
/*
* Copyright (c) 2000 Markus Friedl. All rights reserved.
*
@ -102,6 +102,30 @@ ssh_dss_equal(const struct sshkey *a, const struct sshkey *b)
return 1;
}
static int
ssh_dss_serialize_public(const struct sshkey *key, struct sshbuf *b,
const char *typename, enum sshkey_serialize_rep opts)
{
int r;
const BIGNUM *dsa_p, *dsa_q, *dsa_g, *dsa_pub_key;
if (key->dsa == NULL)
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 (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 ||
(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)
return r;
return 0;
}
int
ssh_dss_sign(const struct sshkey *key, u_char **sigp, size_t *lenp,
const u_char *data, size_t datalen, u_int compat)
@ -264,6 +288,7 @@ static const struct sshkey_impl_funcs sshkey_dss_funcs = {
/* .alloc = */ ssh_dss_alloc,
/* .cleanup = */ ssh_dss_cleanup,
/* .equal = */ ssh_dss_equal,
/* .ssh_serialize_public = */ ssh_dss_serialize_public,
};
const struct sshkey_impl sshkey_dss_impl = {

View File

@ -1,4 +1,4 @@
/* $OpenBSD: ssh-ecdsa-sk.c,v 1.10 2022/10/28 00:36:31 djm Exp $ */
/* $OpenBSD: ssh-ecdsa-sk.c,v 1.11 2022/10/28 00:37:24 djm Exp $ */
/*
* Copyright (c) 2000 Markus Friedl. All rights reserved.
* Copyright (c) 2010 Damien Miller. All rights reserved.
@ -81,6 +81,21 @@ ssh_ecdsa_sk_equal(const struct sshkey *a, const struct sshkey *b)
return 1;
}
static int
ssh_ecdsa_sk_serialize_public(const struct sshkey *key, struct sshbuf *b,
const char *typename, enum sshkey_serialize_rep opts)
{
int r;
if ((r = sshkey_ecdsa_funcs.serialize_public(key, b,
typename, opts)) != 0)
return r;
if ((r = sshkey_serialize_sk(key, b)) != 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.
@ -346,6 +361,7 @@ static const struct sshkey_impl_funcs sshkey_ecdsa_sk_funcs = {
/* .alloc = */ NULL,
/* .cleanup = */ ssh_ecdsa_sk_cleanup,
/* .equal = */ ssh_ecdsa_sk_equal,
/* .ssh_serialize_public = */ ssh_ecdsa_sk_serialize_public,
};
const struct sshkey_impl sshkey_ecdsa_sk_impl = {

View File

@ -1,4 +1,4 @@
/* $OpenBSD: ssh-ecdsa.c,v 1.18 2022/10/28 00:36:31 djm Exp $ */
/* $OpenBSD: ssh-ecdsa.c,v 1.19 2022/10/28 00:37:24 djm Exp $ */
/*
* Copyright (c) 2000 Markus Friedl. All rights reserved.
* Copyright (c) 2010 Damien Miller. All rights reserved.
@ -87,9 +87,27 @@ ssh_ecdsa_equal(const struct sshkey *a, const struct sshkey *b)
return 0;
if (EC_POINT_cmp(grp_a, pub_a, pub_b, NULL) != 0)
return 0;
return 1;
}
static int
ssh_ecdsa_serialize_public(const struct sshkey *key, struct sshbuf *b,
const char *typename, 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,
sshkey_curve_nid_to_name(key->ecdsa_nid))) != 0 ||
(r = sshbuf_put_eckey(b, key->ecdsa)) != 0)
return r;
return 0;
}
/* ARGSUSED */
int
ssh_ecdsa_sign(const struct sshkey *key, u_char **sigp, size_t *lenp,
@ -248,6 +266,7 @@ const struct sshkey_impl_funcs sshkey_ecdsa_funcs = {
/* .alloc = */ NULL,
/* .cleanup = */ ssh_ecdsa_cleanup,
/* .equal = */ ssh_ecdsa_equal,
/* .ssh_serialize_public = */ ssh_ecdsa_serialize_public,
};
const struct sshkey_impl sshkey_ecdsa_nistp256_impl = {

View File

@ -1,4 +1,4 @@
/* $OpenBSD: ssh-ed25519-sk.c,v 1.8 2022/10/28 00:36:31 djm Exp $ */
/* $OpenBSD: ssh-ed25519-sk.c,v 1.9 2022/10/28 00:37:24 djm Exp $ */
/*
* Copyright (c) 2019 Markus Friedl. All rights reserved.
*
@ -55,6 +55,21 @@ ssh_ed25519_sk_equal(const struct sshkey *a, const struct sshkey *b)
return 1;
}
static int
ssh_ed25519_sk_serialize_public(const struct sshkey *key, struct sshbuf *b,
const char *typename, enum sshkey_serialize_rep opts)
{
int r;
if ((r = sshkey_ed25519_funcs.serialize_public(key, b,
typename, opts)) != 0)
return r;
if ((r = sshkey_serialize_sk(key, b)) != 0)
return r;
return 0;
}
int
ssh_ed25519_sk_verify(const struct sshkey *key,
const u_char *signature, size_t signaturelen,
@ -187,6 +202,7 @@ static const struct sshkey_impl_funcs sshkey_ed25519_sk_funcs = {
/* .alloc = */ NULL,
/* .cleanup = */ ssh_ed25519_sk_cleanup,
/* .equal = */ ssh_ed25519_sk_equal,
/* .ssh_serialize_public = */ ssh_ed25519_sk_serialize_public,
};
const struct sshkey_impl sshkey_ed25519_sk_impl = {

View File

@ -1,4 +1,4 @@
/* $OpenBSD: ssh-ed25519.c,v 1.12 2022/10/28 00:36:31 djm Exp $ */
/* $OpenBSD: ssh-ed25519.c,v 1.13 2022/10/28 00:37:24 djm Exp $ */
/*
* Copyright (c) 2013 Markus Friedl <markus@openbsd.org>
*
@ -51,6 +51,21 @@ ssh_ed25519_equal(const struct sshkey *a, const struct sshkey *b)
return 1;
}
static int
ssh_ed25519_serialize_public(const struct sshkey *key, struct sshbuf *b,
const char *typename, 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)
return r;
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)
@ -184,6 +199,7 @@ const struct sshkey_impl_funcs sshkey_ed25519_funcs = {
/* .alloc = */ NULL,
/* .cleanup = */ ssh_ed25519_cleanup,
/* .equal = */ ssh_ed25519_equal,
/* .ssh_serialize_public = */ ssh_ed25519_serialize_public,
};
const struct sshkey_impl sshkey_ed25519_impl = {

View File

@ -1,4 +1,4 @@
/* $OpenBSD: ssh-rsa.c,v 1.70 2022/10/28 00:36:31 djm Exp $ */
/* $OpenBSD: ssh-rsa.c,v 1.71 2022/10/28 00:37:24 djm Exp $ */
/*
* Copyright (c) 2000, 2003 Markus Friedl <markus@openbsd.org>
*
@ -86,6 +86,24 @@ ssh_rsa_equal(const struct sshkey *a, const struct sshkey *b)
return 1;
}
static int
ssh_rsa_serialize_public(const struct sshkey *key, struct sshbuf *b,
const char *typename, enum sshkey_serialize_rep opts)
{
int r;
const BIGNUM *rsa_n, *rsa_e;
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 ||
(r = sshbuf_put_bignum2(b, rsa_n)) != 0)
return r;
return 0;
}
static const char *
rsa_hash_alg_ident(int hash_alg)
{
@ -499,6 +517,7 @@ static const struct sshkey_impl_funcs sshkey_rsa_funcs = {
/* .alloc = */ ssh_rsa_alloc,
/* .cleanup = */ ssh_rsa_cleanup,
/* .equal = */ ssh_rsa_equal,
/* .ssh_serialize_public = */ ssh_rsa_serialize_public,
};
const struct sshkey_impl sshkey_rsa_impl = {

View File

@ -1,4 +1,4 @@
/* $OpenBSD: ssh-xmss.c,v 1.7 2022/10/28 00:36:31 djm Exp $*/
/* $OpenBSD: ssh-xmss.c,v 1.8 2022/10/28 00:37:24 djm Exp $*/
/*
* Copyright (c) 2017 Stefan-Lukas Gazdag.
* Copyright (c) 2017 Markus Friedl.
@ -63,6 +63,25 @@ ssh_xmss_equal(const struct sshkey *a, const struct sshkey *b)
return 1;
}
static int
ssh_xmss_serialize_public(const struct sshkey *key, struct sshbuf *b,
const char *typename, 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 ||
(r = sshbuf_put_string(b, key->xmss_pk,
sshkey_xmss_pklen(key))) != 0 ||
(r = sshkey_xmss_serialize_pk_info(key, b, opts)) != 0)
return r;
return 0;
}
int
ssh_xmss_sign(const struct sshkey *key, u_char **sigp, size_t *lenp,
const u_char *data, size_t datalen, u_int compat)
@ -216,6 +235,7 @@ static const struct sshkey_impl_funcs sshkey_xmss_funcs = {
/* .alloc = */ NULL,
/* .cleanup = */ ssh_xmss_cleanup,
/* .equal = */ ssh_xmss_equal,
/* .ssh_serialize_public = */ ssh_xmss_serialize_public,
};
const struct sshkey_impl sshkey_xmss_impl = {

117
sshkey.c
View File

@ -1,4 +1,4 @@
/* $OpenBSD: sshkey.c,v 1.124 2022/10/28 00:36:31 djm Exp $ */
/* $OpenBSD: sshkey.c,v 1.125 2022/10/28 00:37:24 djm Exp $ */
/*
* Copyright (c) 2000, 2001 Markus Friedl. All rights reserved.
* Copyright (c) 2008 Alexander von Gernler. All rights reserved.
@ -679,116 +679,47 @@ sshkey_equal(const struct sshkey *a, const struct sshkey *b)
return sshkey_equal_public(a, b);
}
/* Serialise common FIDO key parts */
int
sshkey_serialize_sk(const struct sshkey *key, struct sshbuf *b)
{
int r;
if ((r = sshbuf_put_cstring(b, key->sk_application)) != 0)
return r;
return 0;
}
static int
to_blob_buf(const struct sshkey *key, struct sshbuf *b, int force_plain,
enum sshkey_serialize_rep opts)
{
int type, ret = SSH_ERR_INTERNAL_ERROR;
const char *typename;
#ifdef WITH_OPENSSL
const BIGNUM *rsa_n, *rsa_e, *dsa_p, *dsa_q, *dsa_g, *dsa_pub_key;
#endif /* WITH_OPENSSL */
const struct sshkey_impl *impl;
if (key == NULL)
return SSH_ERR_INVALID_ARGUMENT;
if (sshkey_is_cert(key)) {
type = force_plain ? sshkey_type_plain(key->type) : key->type;
if (sshkey_type_is_cert(type)) {
if (key->cert == NULL)
return SSH_ERR_EXPECTED_CERT;
if (sshbuf_len(key->cert->certblob) == 0)
return SSH_ERR_KEY_LACKS_CERTBLOB;
}
type = force_plain ? sshkey_type_plain(key->type) : key->type;
typename = sshkey_ssh_name_from_type_nid(type, key->ecdsa_nid);
switch (type) {
#ifdef WITH_OPENSSL
case KEY_DSA_CERT:
case KEY_ECDSA_CERT:
case KEY_ECDSA_SK_CERT:
case KEY_RSA_CERT:
#endif /* WITH_OPENSSL */
case KEY_ED25519_CERT:
case KEY_ED25519_SK_CERT:
#ifdef WITH_XMSS
case KEY_XMSS_CERT:
#endif /* WITH_XMSS */
/* Use the existing blob */
/* XXX modified flag? */
if ((ret = sshbuf_putb(b, key->cert->certblob)) != 0)
return ret;
break;
#ifdef WITH_OPENSSL
case KEY_DSA:
if (key->dsa == NULL)
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 ||
(ret = sshbuf_put_bignum2(b, dsa_p)) != 0 ||
(ret = sshbuf_put_bignum2(b, dsa_q)) != 0 ||
(ret = sshbuf_put_bignum2(b, dsa_g)) != 0 ||
(ret = sshbuf_put_bignum2(b, dsa_pub_key)) != 0)
return ret;
break;
# ifdef OPENSSL_HAS_ECC
case KEY_ECDSA:
case KEY_ECDSA_SK:
if (key->ecdsa == NULL)
return SSH_ERR_INVALID_ARGUMENT;
if ((ret = sshbuf_put_cstring(b, typename)) != 0 ||
(ret = sshbuf_put_cstring(b,
sshkey_curve_nid_to_name(key->ecdsa_nid))) != 0 ||
(ret = sshbuf_put_eckey(b, key->ecdsa)) != 0)
return ret;
if (type == KEY_ECDSA_SK) {
if ((ret = sshbuf_put_cstring(b,
key->sk_application)) != 0)
return ret;
}
break;
# endif
case KEY_RSA:
if (key->rsa == NULL)
return SSH_ERR_INVALID_ARGUMENT;
RSA_get0_key(key->rsa, &rsa_n, &rsa_e, NULL);
if ((ret = sshbuf_put_cstring(b, typename)) != 0 ||
(ret = sshbuf_put_bignum2(b, rsa_e)) != 0 ||
(ret = sshbuf_put_bignum2(b, rsa_n)) != 0)
return ret;
break;
#endif /* WITH_OPENSSL */
case KEY_ED25519:
case KEY_ED25519_SK:
if (key->ed25519_pk == NULL)
return SSH_ERR_INVALID_ARGUMENT;
if ((ret = sshbuf_put_cstring(b, typename)) != 0 ||
(ret = sshbuf_put_string(b,
key->ed25519_pk, ED25519_PK_SZ)) != 0)
return ret;
if (type == KEY_ED25519_SK) {
if ((ret = sshbuf_put_cstring(b,
key->sk_application)) != 0)
return ret;
}
break;
#ifdef WITH_XMSS
case KEY_XMSS:
if (key->xmss_name == NULL || key->xmss_pk == NULL ||
sshkey_xmss_pklen(key) == 0)
return SSH_ERR_INVALID_ARGUMENT;
if ((ret = sshbuf_put_cstring(b, typename)) != 0 ||
(ret = sshbuf_put_cstring(b, key->xmss_name)) != 0 ||
(ret = sshbuf_put_string(b,
key->xmss_pk, sshkey_xmss_pklen(key))) != 0 ||
(ret = sshkey_xmss_serialize_pk_info(key, b, opts)) != 0)
return ret;
break;
#endif /* WITH_XMSS */
default:
return SSH_ERR_KEY_TYPE_UNKNOWN;
return 0;
}
return 0;
if ((impl = sshkey_impl_from_type(type)) == NULL)
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);
}
int

View File

@ -1,4 +1,4 @@
/* $OpenBSD: sshkey.h,v 1.54 2022/10/28 00:36:31 djm Exp $ */
/* $OpenBSD: sshkey.h,v 1.55 2022/10/28 00:37:24 djm Exp $ */
/*
* Copyright (c) 2000, 2001 Markus Friedl. All rights reserved.
@ -169,6 +169,8 @@ struct sshkey_impl_funcs {
int (*alloc)(struct sshkey *); /* optional */
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);
};
struct sshkey_impl {
@ -309,6 +311,7 @@ void sshkey_sig_details_free(struct sshkey_sig_details *);
#ifdef SSHKEY_INTERNAL
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 ssh_rsa_sign(const struct sshkey *key,
u_char **sigp, size_t *lenp, const u_char *data, size_t datalen,