From 0d39f00105eecca4f63b291d76f6e8313b38ae32 Mon Sep 17 00:00:00 2001 From: djm Date: Fri, 28 Oct 2022 00:41:17 +0000 Subject: [PATCH] refactor sshkey_from_private() feedback/ok markus@ --- usr.bin/ssh/ssh-dss.c | 40 +++++++++- usr.bin/ssh/ssh-ecdsa-sk.c | 15 +++- usr.bin/ssh/ssh-ecdsa.c | 15 +++- usr.bin/ssh/ssh-ed25519-sk.c | 15 +++- usr.bin/ssh/ssh-ed25519.c | 14 +++- usr.bin/ssh/ssh-rsa.c | 29 +++++++- usr.bin/ssh/ssh-xmss.c | 28 ++++++- usr.bin/ssh/sshkey.c | 137 ++++------------------------------- usr.bin/ssh/sshkey.h | 4 +- 9 files changed, 166 insertions(+), 131 deletions(-) diff --git a/usr.bin/ssh/ssh-dss.c b/usr.bin/ssh/ssh-dss.c index 6b2c48750c8..2dba1ed1d2c 100644 --- a/usr.bin/ssh/ssh-dss.c +++ b/usr.bin/ssh/ssh-dss.c @@ -1,4 +1,4 @@ -/* $OpenBSD: ssh-dss.c,v 1.43 2022/10/28 00:39:29 djm Exp $ */ +/* $OpenBSD: ssh-dss.c,v 1.44 2022/10/28 00:41:17 djm Exp $ */ /* * Copyright (c) 2000 Markus Friedl. All rights reserved. * @@ -136,6 +136,43 @@ ssh_dss_generate(struct sshkey *k, int bits) return 0; } +static int +ssh_dss_copy_public(const struct sshkey *from, struct sshkey *to) +{ + 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; + int r = SSH_ERR_INTERNAL_ERROR; + + DSA_get0_pqg(from->dsa, &dsa_p, &dsa_q, &dsa_g); + DSA_get0_key(from->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(to->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(to->dsa, dsa_pub_key_dup, NULL)) { + r = SSH_ERR_LIBCRYPTO_ERROR; + goto out; + } + dsa_pub_key_dup = NULL; /* transferred */ + /* success */ + r = 0; + out: + 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; +} + int ssh_dss_sign(const struct sshkey *key, u_char **sigp, size_t *lenp, const u_char *data, size_t datalen, u_int compat) @@ -300,6 +337,7 @@ static const struct sshkey_impl_funcs sshkey_dss_funcs = { /* .equal = */ ssh_dss_equal, /* .ssh_serialize_public = */ ssh_dss_serialize_public, /* .generate = */ ssh_dss_generate, + /* .copy_public = */ ssh_dss_copy_public, }; const struct sshkey_impl sshkey_dss_impl = { diff --git a/usr.bin/ssh/ssh-ecdsa-sk.c b/usr.bin/ssh/ssh-ecdsa-sk.c index 5c844d8baac..f3692b0b7fb 100644 --- a/usr.bin/ssh/ssh-ecdsa-sk.c +++ b/usr.bin/ssh/ssh-ecdsa-sk.c @@ -1,4 +1,4 @@ -/* $OpenBSD: ssh-ecdsa-sk.c,v 1.12 2022/10/28 00:39:29 djm Exp $ */ +/* $OpenBSD: ssh-ecdsa-sk.c,v 1.13 2022/10/28 00:41:17 djm Exp $ */ /* * Copyright (c) 2000 Markus Friedl. All rights reserved. * Copyright (c) 2010 Damien Miller. All rights reserved. @@ -78,6 +78,18 @@ ssh_ecdsa_sk_serialize_public(const struct sshkey *key, struct sshbuf *b, return 0; } +static int +ssh_ecdsa_sk_copy_public(const struct sshkey *from, struct sshkey *to) +{ + int r; + + if ((r = sshkey_ecdsa_funcs.copy_public(from, to)) != 0) + return r; + if ((r = sshkey_copy_public_sk(from, to)) != 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. @@ -345,6 +357,7 @@ static const struct sshkey_impl_funcs sshkey_ecdsa_sk_funcs = { /* .equal = */ ssh_ecdsa_sk_equal, /* .ssh_serialize_public = */ ssh_ecdsa_sk_serialize_public, /* .generate = */ NULL, + /* .copy_public = */ ssh_ecdsa_sk_copy_public, }; const struct sshkey_impl sshkey_ecdsa_sk_impl = { diff --git a/usr.bin/ssh/ssh-ecdsa.c b/usr.bin/ssh/ssh-ecdsa.c index 9e576648354..b2b03205d13 100644 --- a/usr.bin/ssh/ssh-ecdsa.c +++ b/usr.bin/ssh/ssh-ecdsa.c @@ -1,4 +1,4 @@ -/* $OpenBSD: ssh-ecdsa.c,v 1.20 2022/10/28 00:39:29 djm Exp $ */ +/* $OpenBSD: ssh-ecdsa.c,v 1.21 2022/10/28 00:41:17 djm Exp $ */ /* * Copyright (c) 2000 Markus Friedl. All rights reserved. * Copyright (c) 2010 Damien Miller. All rights reserved. @@ -118,6 +118,18 @@ ssh_ecdsa_generate(struct sshkey *k, int bits) return 0; } +static int +ssh_ecdsa_copy_public(const struct sshkey *from, struct sshkey *to) +{ + to->ecdsa_nid = from->ecdsa_nid; + if ((to->ecdsa = EC_KEY_new_by_curve_name(from->ecdsa_nid)) == NULL) + return SSH_ERR_ALLOC_FAIL; + if (EC_KEY_set_public_key(to->ecdsa, + EC_KEY_get0_public_key(from->ecdsa)) != 1) + return SSH_ERR_LIBCRYPTO_ERROR; /* caller will free k->ecdsa */ + return 0; +} + /* ARGSUSED */ int ssh_ecdsa_sign(const struct sshkey *key, u_char **sigp, size_t *lenp, @@ -278,6 +290,7 @@ const struct sshkey_impl_funcs sshkey_ecdsa_funcs = { /* .equal = */ ssh_ecdsa_equal, /* .ssh_serialize_public = */ ssh_ecdsa_serialize_public, /* .generate = */ ssh_ecdsa_generate, + /* .copy_public = */ ssh_ecdsa_copy_public, }; const struct sshkey_impl sshkey_ecdsa_nistp256_impl = { diff --git a/usr.bin/ssh/ssh-ed25519-sk.c b/usr.bin/ssh/ssh-ed25519-sk.c index 7131363f4a2..99676d96a84 100644 --- a/usr.bin/ssh/ssh-ed25519-sk.c +++ b/usr.bin/ssh/ssh-ed25519-sk.c @@ -1,4 +1,4 @@ -/* $OpenBSD: ssh-ed25519-sk.c,v 1.10 2022/10/28 00:39:29 djm Exp $ */ +/* $OpenBSD: ssh-ed25519-sk.c,v 1.11 2022/10/28 00:41:17 djm Exp $ */ /* * Copyright (c) 2019 Markus Friedl. All rights reserved. * @@ -68,6 +68,18 @@ ssh_ed25519_sk_serialize_public(const struct sshkey *key, struct sshbuf *b, return 0; } +static int +ssh_ed25519_sk_copy_public(const struct sshkey *from, struct sshkey *to) +{ + int r; + + if ((r = sshkey_ed25519_funcs.copy_public(from, to)) != 0) + return r; + if ((r = sshkey_copy_public_sk(from, to)) != 0) + return r; + return 0; +} + int ssh_ed25519_sk_verify(const struct sshkey *key, const u_char *signature, size_t signaturelen, @@ -202,6 +214,7 @@ static const struct sshkey_impl_funcs sshkey_ed25519_sk_funcs = { /* .equal = */ ssh_ed25519_sk_equal, /* .ssh_serialize_public = */ ssh_ed25519_sk_serialize_public, /* .generate = */ NULL, + /* .copy_public = */ ssh_ed25519_sk_copy_public, }; const struct sshkey_impl sshkey_ed25519_sk_impl = { diff --git a/usr.bin/ssh/ssh-ed25519.c b/usr.bin/ssh/ssh-ed25519.c index bbf164c8c42..db1dc96f379 100644 --- a/usr.bin/ssh/ssh-ed25519.c +++ b/usr.bin/ssh/ssh-ed25519.c @@ -1,4 +1,4 @@ -/* $OpenBSD: ssh-ed25519.c,v 1.14 2022/10/28 00:39:29 djm Exp $ */ +/* $OpenBSD: ssh-ed25519.c,v 1.15 2022/10/28 00:41:17 djm Exp $ */ /* * Copyright (c) 2013 Markus Friedl * @@ -73,6 +73,17 @@ ssh_ed25519_generate(struct sshkey *k, int bits) return 0; } +static int +ssh_ed25519_copy_public(const struct sshkey *from, struct sshkey *to) +{ + if (from->ed25519_pk == NULL) + return 0; /* XXX SSH_ERR_INTERNAL_ERROR ? */ + if ((to->ed25519_pk = malloc(ED25519_PK_SZ)) == NULL) + return SSH_ERR_ALLOC_FAIL; + memcpy(to->ed25519_pk, from->ed25519_pk, ED25519_PK_SZ); + 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) @@ -208,6 +219,7 @@ const struct sshkey_impl_funcs sshkey_ed25519_funcs = { /* .equal = */ ssh_ed25519_equal, /* .ssh_serialize_public = */ ssh_ed25519_serialize_public, /* .generate = */ ssh_ed25519_generate, + /* .copy_public = */ ssh_ed25519_copy_public, }; const struct sshkey_impl sshkey_ed25519_impl = { diff --git a/usr.bin/ssh/ssh-rsa.c b/usr.bin/ssh/ssh-rsa.c index f6aa4bfef63..f13a082555b 100644 --- a/usr.bin/ssh/ssh-rsa.c +++ b/usr.bin/ssh/ssh-rsa.c @@ -1,4 +1,4 @@ -/* $OpenBSD: ssh-rsa.c,v 1.72 2022/10/28 00:39:29 djm Exp $ */ +/* $OpenBSD: ssh-rsa.c,v 1.73 2022/10/28 00:41:17 djm Exp $ */ /* * Copyright (c) 2000, 2003 Markus Friedl * @@ -125,6 +125,32 @@ ssh_rsa_generate(struct sshkey *k, int bits) return ret; } +static int +ssh_rsa_copy_public(const struct sshkey *from, struct sshkey *to) +{ + const BIGNUM *rsa_n, *rsa_e; + BIGNUM *rsa_n_dup = NULL, *rsa_e_dup = NULL; + int r = SSH_ERR_INTERNAL_ERROR; + + RSA_get0_key(from->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(to->rsa, rsa_n_dup, rsa_e_dup, NULL)) { + r = SSH_ERR_LIBCRYPTO_ERROR; + goto out; + } + rsa_n_dup = rsa_e_dup = NULL; /* transferred */ + /* success */ + r = 0; + out: + BN_clear_free(rsa_n_dup); + BN_clear_free(rsa_e_dup); + return r; +} + static const char * rsa_hash_alg_ident(int hash_alg) { @@ -540,6 +566,7 @@ static const struct sshkey_impl_funcs sshkey_rsa_funcs = { /* .equal = */ ssh_rsa_equal, /* .ssh_serialize_public = */ ssh_rsa_serialize_public, /* .generate = */ ssh_rsa_generate, + /* .copy_public = */ ssh_rsa_copy_public, }; const struct sshkey_impl sshkey_rsa_impl = { diff --git a/usr.bin/ssh/ssh-xmss.c b/usr.bin/ssh/ssh-xmss.c index 30cd89c7f1b..7a3bec7c7f0 100644 --- a/usr.bin/ssh/ssh-xmss.c +++ b/usr.bin/ssh/ssh-xmss.c @@ -1,4 +1,4 @@ -/* $OpenBSD: ssh-xmss.c,v 1.9 2022/10/28 00:39:29 djm Exp $*/ +/* $OpenBSD: ssh-xmss.c,v 1.10 2022/10/28 00:41:17 djm Exp $*/ /* * Copyright (c) 2017 Stefan-Lukas Gazdag. * Copyright (c) 2017 Markus Friedl. @@ -79,6 +79,31 @@ ssh_xmss_serialize_public(const struct sshkey *key, struct sshbuf *b, return 0; } +static int +ssh_xmss_copy_public(const struct sshkey *from, struct sshkey *to) +{ + int r = SSH_ERR_INTERNAL_ERROR; + u_int32_t left; + size_t pklen; + + if ((r = sshkey_xmss_init(to, from->xmss_name)) != 0) + return r; + if (from->xmss_pk == NULL) + return 0; /* XXX SSH_ERR_INTERNAL_ERROR ? */ + + if ((pklen = sshkey_xmss_pklen(from)) == 0 || + sshkey_xmss_pklen(to) != pklen) + return SSH_ERR_INTERNAL_ERROR; + if ((to->xmss_pk = malloc(pklen)) == NULL) + return SSH_ERR_ALLOC_FAIL; + memcpy(to->xmss_pk, from->xmss_pk, pklen); + /* simulate number of signatures left on pubkey */ + left = sshkey_xmss_signatures_left(from); + if (left) + sshkey_xmss_enable_maxsign(to, left); + 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) @@ -234,6 +259,7 @@ static const struct sshkey_impl_funcs sshkey_xmss_funcs = { /* .equal = */ ssh_xmss_equal, /* .ssh_serialize_public = */ ssh_xmss_serialize_public, /* .generate = */ sshkey_xmss_generate_private_key, + /* .copy_public = */ ssh_xmss_copy_public, }; const struct sshkey_impl sshkey_xmss_impl = { diff --git a/usr.bin/ssh/sshkey.c b/usr.bin/ssh/sshkey.c index 74ee6b4409a..7a6daeb8a6d 100644 --- a/usr.bin/ssh/sshkey.c +++ b/usr.bin/ssh/sshkey.c @@ -1,4 +1,4 @@ -/* $OpenBSD: sshkey.c,v 1.127 2022/10/28 00:39:29 djm Exp $ */ +/* $OpenBSD: sshkey.c,v 1.128 2022/10/28 00:41:17 djm Exp $ */ /* * Copyright (c) 2000, 2001 Markus Friedl. All rights reserved. * Copyright (c) 2008 Alexander von Gernler. All rights reserved. @@ -1405,131 +1405,31 @@ sshkey_cert_copy(const struct sshkey *from_key, struct sshkey *to_key) return r; } +int +sshkey_copy_public_sk(const struct sshkey *from, struct sshkey *to) +{ + /* Append security-key application string */ + if ((to->sk_application = strdup(from->sk_application)) == NULL) + return SSH_ERR_ALLOC_FAIL; + return 0; +} + int sshkey_from_private(const struct sshkey *k, struct sshkey **pkp) { struct sshkey *n = NULL; 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 */ + const struct sshkey_impl *impl; *pkp = NULL; + if ((impl = sshkey_impl_from_key(k)) == NULL) + return SSH_ERR_KEY_TYPE_UNKNOWN; if ((n = sshkey_new(k->type)) == NULL) { r = SSH_ERR_ALLOC_FAIL; goto out; } - switch (k->type) { -#ifdef WITH_OPENSSL - case KEY_DSA: - case KEY_DSA_CERT: - 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; - case KEY_ECDSA: - case KEY_ECDSA_CERT: - case KEY_ECDSA_SK: - case KEY_ECDSA_SK_CERT: - n->ecdsa_nid = k->ecdsa_nid; - n->ecdsa = EC_KEY_new_by_curve_name(k->ecdsa_nid); - if (n->ecdsa == NULL) { - r = SSH_ERR_ALLOC_FAIL; - goto out; - } - if (EC_KEY_set_public_key(n->ecdsa, - EC_KEY_get0_public_key(k->ecdsa)) != 1) { - r = SSH_ERR_LIBCRYPTO_ERROR; - goto out; - } - if (k->type != KEY_ECDSA_SK && k->type != KEY_ECDSA_SK_CERT) - break; - /* Append security-key application string */ - if ((n->sk_application = strdup(k->sk_application)) == NULL) - goto out; - break; - case KEY_RSA: - case KEY_RSA_CERT: - 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; -#endif /* WITH_OPENSSL */ - case KEY_ED25519: - case KEY_ED25519_CERT: - case KEY_ED25519_SK: - case KEY_ED25519_SK_CERT: - if (k->ed25519_pk != NULL) { - if ((n->ed25519_pk = malloc(ED25519_PK_SZ)) == NULL) { - r = SSH_ERR_ALLOC_FAIL; - goto out; - } - memcpy(n->ed25519_pk, k->ed25519_pk, ED25519_PK_SZ); - } - if (k->type != KEY_ED25519_SK && - k->type != KEY_ED25519_SK_CERT) - break; - /* Append security-key application string */ - if ((n->sk_application = strdup(k->sk_application)) == NULL) - goto out; - break; -#ifdef WITH_XMSS - case KEY_XMSS: - case KEY_XMSS_CERT: - if ((r = sshkey_xmss_init(n, k->xmss_name)) != 0) - goto out; - if (k->xmss_pk != NULL) { - u_int32_t left; - size_t pklen = sshkey_xmss_pklen(k); - if (pklen == 0 || sshkey_xmss_pklen(n) != pklen) { - r = SSH_ERR_INTERNAL_ERROR; - goto out; - } - if ((n->xmss_pk = malloc(pklen)) == NULL) { - r = SSH_ERR_ALLOC_FAIL; - goto out; - } - memcpy(n->xmss_pk, k->xmss_pk, pklen); - /* simulate number of signatures left on pubkey */ - left = sshkey_xmss_signatures_left(k); - if (left) - sshkey_xmss_enable_maxsign(n, left); - } - break; -#endif /* WITH_XMSS */ - default: - r = SSH_ERR_KEY_TYPE_UNKNOWN; + if ((r = impl->funcs->copy_public(k, n)) != 0) goto out; - } if (sshkey_is_cert(k) && (r = sshkey_cert_copy(k, n)) != 0) goto out; /* success */ @@ -1538,15 +1438,6 @@ sshkey_from_private(const struct sshkey *k, struct sshkey **pkp) r = 0; out: sshkey_free(n); -#ifdef WITH_OPENSSL - 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); -#endif /* WITH_OPENSSL */ - return r; } diff --git a/usr.bin/ssh/sshkey.h b/usr.bin/ssh/sshkey.h index c90724ac575..899614dbe30 100644 --- a/usr.bin/ssh/sshkey.h +++ b/usr.bin/ssh/sshkey.h @@ -1,4 +1,4 @@ -/* $OpenBSD: sshkey.h,v 1.56 2022/10/28 00:39:29 djm Exp $ */ +/* $OpenBSD: sshkey.h,v 1.57 2022/10/28 00:41:17 djm Exp $ */ /* * Copyright (c) 2000, 2001 Markus Friedl. All rights reserved. @@ -166,6 +166,7 @@ struct sshkey_impl_funcs { int (*serialize_public)(const struct sshkey *, struct sshbuf *, const char *, enum sshkey_serialize_rep); int (*generate)(struct sshkey *, int); /* optional */ + int (*copy_public)(const struct sshkey *, struct sshkey *); }; struct sshkey_impl { @@ -307,6 +308,7 @@ void sshkey_sig_details_free(struct sshkey_sig_details *); 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 ssh_rsa_sign(const struct sshkey *key, u_char **sigp, size_t *lenp, const u_char *data, size_t datalen, -- 2.20.1