From b6025feb5ae4d7a3bac25b25ea94cdcc87366a3d Mon Sep 17 00:00:00 2001 From: djm Date: Fri, 28 Oct 2022 00:39:29 +0000 Subject: [PATCH] factor out key generation feedback/ok markus@ --- usr.bin/ssh/ssh-dss.c | 21 +++++- usr.bin/ssh/ssh-ecdsa-sk.c | 3 +- usr.bin/ssh/ssh-ecdsa.c | 21 +++++- usr.bin/ssh/ssh-ed25519-sk.c | 3 +- usr.bin/ssh/ssh-ed25519.c | 13 +++- usr.bin/ssh/ssh-rsa.c | 31 +++++++- usr.bin/ssh/ssh-xmss.c | 3 +- usr.bin/ssh/sshkey-xmss.c | 4 +- usr.bin/ssh/sshkey-xmss.h | 4 +- usr.bin/ssh/sshkey.c | 137 ++++------------------------------- usr.bin/ssh/sshkey.h | 3 +- 11 files changed, 108 insertions(+), 135 deletions(-) diff --git a/usr.bin/ssh/ssh-dss.c b/usr.bin/ssh/ssh-dss.c index fdfc55ce8c7..6b2c48750c8 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.42 2022/10/28 00:37:24 djm Exp $ */ +/* $OpenBSD: ssh-dss.c,v 1.43 2022/10/28 00:39:29 djm Exp $ */ /* * Copyright (c) 2000 Markus Friedl. All rights reserved. * @@ -118,6 +118,24 @@ ssh_dss_serialize_public(const struct sshkey *key, struct sshbuf *b, return 0; } +static int +ssh_dss_generate(struct sshkey *k, int bits) +{ + DSA *private; + + if (bits != 1024) + return SSH_ERR_KEY_LENGTH; + if ((private = DSA_new()) == NULL) + return SSH_ERR_ALLOC_FAIL; + if (!DSA_generate_parameters_ex(private, bits, NULL, 0, NULL, + NULL, NULL) || !DSA_generate_key(private)) { + DSA_free(private); + return SSH_ERR_LIBCRYPTO_ERROR; + } + k->dsa = private; + 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) @@ -281,6 +299,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, + /* .generate = */ ssh_dss_generate, }; 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 6c663c20cba..5c844d8baac 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.11 2022/10/28 00:37:24 djm Exp $ */ +/* $OpenBSD: ssh-ecdsa-sk.c,v 1.12 2022/10/28 00:39:29 djm Exp $ */ /* * Copyright (c) 2000 Markus Friedl. All rights reserved. * Copyright (c) 2010 Damien Miller. All rights reserved. @@ -344,6 +344,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, + /* .generate = */ NULL, }; 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 af3413efffa..9e576648354 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.19 2022/10/28 00:37:24 djm Exp $ */ +/* $OpenBSD: ssh-ecdsa.c,v 1.20 2022/10/28 00:39:29 djm Exp $ */ /* * Copyright (c) 2000 Markus Friedl. All rights reserved. * Copyright (c) 2010 Damien Miller. All rights reserved. @@ -100,6 +100,24 @@ ssh_ecdsa_serialize_public(const struct sshkey *key, struct sshbuf *b, return 0; } +static int +ssh_ecdsa_generate(struct sshkey *k, int bits) +{ + EC_KEY *private; + + if ((k->ecdsa_nid = sshkey_ecdsa_bits_to_nid(bits)) == -1) + return SSH_ERR_KEY_LENGTH; + if ((private = EC_KEY_new_by_curve_name(k->ecdsa_nid)) == NULL) + return SSH_ERR_ALLOC_FAIL; + if (EC_KEY_generate_key(private) != 1) { + EC_KEY_free(private); + return SSH_ERR_LIBCRYPTO_ERROR; + } + EC_KEY_set_asn1_flag(private, OPENSSL_EC_NAMED_CURVE); + k->ecdsa = private; + return 0; +} + /* ARGSUSED */ int ssh_ecdsa_sign(const struct sshkey *key, u_char **sigp, size_t *lenp, @@ -259,6 +277,7 @@ const struct sshkey_impl_funcs sshkey_ecdsa_funcs = { /* .cleanup = */ ssh_ecdsa_cleanup, /* .equal = */ ssh_ecdsa_equal, /* .ssh_serialize_public = */ ssh_ecdsa_serialize_public, + /* .generate = */ ssh_ecdsa_generate, }; 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 9183a4394a7..7131363f4a2 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.9 2022/10/28 00:37:24 djm Exp $ */ +/* $OpenBSD: ssh-ed25519-sk.c,v 1.10 2022/10/28 00:39:29 djm Exp $ */ /* * Copyright (c) 2019 Markus Friedl. All rights reserved. * @@ -201,6 +201,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, + /* .generate = */ NULL, }; 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 a5a37bd40c6..bbf164c8c42 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.13 2022/10/28 00:37:24 djm Exp $ */ +/* $OpenBSD: ssh-ed25519.c,v 1.14 2022/10/28 00:39:29 djm Exp $ */ /* * Copyright (c) 2013 Markus Friedl * @@ -63,6 +63,16 @@ ssh_ed25519_serialize_public(const struct sshkey *key, struct sshbuf *b, return 0; } +static int +ssh_ed25519_generate(struct sshkey *k, int bits) +{ + if ((k->ed25519_pk = malloc(ED25519_PK_SZ)) == NULL || + (k->ed25519_sk = malloc(ED25519_SK_SZ)) == NULL) + return SSH_ERR_ALLOC_FAIL; + crypto_sign_ed25519_keypair(k->ed25519_pk, k->ed25519_sk); + 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) @@ -197,6 +207,7 @@ const struct sshkey_impl_funcs sshkey_ed25519_funcs = { /* .cleanup = */ ssh_ed25519_cleanup, /* .equal = */ ssh_ed25519_equal, /* .ssh_serialize_public = */ ssh_ed25519_serialize_public, + /* .generate = */ ssh_ed25519_generate, }; const struct sshkey_impl sshkey_ed25519_impl = { diff --git a/usr.bin/ssh/ssh-rsa.c b/usr.bin/ssh/ssh-rsa.c index 58c071c95bd..f6aa4bfef63 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.71 2022/10/28 00:37:24 djm Exp $ */ +/* $OpenBSD: ssh-rsa.c,v 1.72 2022/10/28 00:39:29 djm Exp $ */ /* * Copyright (c) 2000, 2003 Markus Friedl * @@ -97,6 +97,34 @@ ssh_rsa_serialize_public(const struct sshkey *key, struct sshbuf *b, return 0; } +static int +ssh_rsa_generate(struct sshkey *k, int bits) +{ + RSA *private = NULL; + BIGNUM *f4 = NULL; + int ret = SSH_ERR_INTERNAL_ERROR; + + if (bits < SSH_RSA_MINIMUM_MODULUS_SIZE || + bits > SSHBUF_MAX_BIGNUM * 8) + return SSH_ERR_KEY_LENGTH; + if ((private = RSA_new()) == NULL || (f4 = BN_new()) == NULL) { + ret = SSH_ERR_ALLOC_FAIL; + goto out; + } + if (!BN_set_word(f4, RSA_F4) || + !RSA_generate_key_ex(private, bits, f4, NULL)) { + ret = SSH_ERR_LIBCRYPTO_ERROR; + goto out; + } + k->rsa = private; + private = NULL; + ret = 0; + out: + RSA_free(private); + BN_free(f4); + return ret; +} + static const char * rsa_hash_alg_ident(int hash_alg) { @@ -511,6 +539,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, + /* .generate = */ ssh_rsa_generate, }; const struct sshkey_impl sshkey_rsa_impl = { diff --git a/usr.bin/ssh/ssh-xmss.c b/usr.bin/ssh/ssh-xmss.c index aee1edbd951..30cd89c7f1b 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.8 2022/10/28 00:37:24 djm Exp $*/ +/* $OpenBSD: ssh-xmss.c,v 1.9 2022/10/28 00:39:29 djm Exp $*/ /* * Copyright (c) 2017 Stefan-Lukas Gazdag. * Copyright (c) 2017 Markus Friedl. @@ -233,6 +233,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, + /* .generate = */ sshkey_xmss_generate_private_key, }; const struct sshkey_impl sshkey_xmss_impl = { diff --git a/usr.bin/ssh/sshkey-xmss.c b/usr.bin/ssh/sshkey-xmss.c index d3acf5739b6..71660b44387 100644 --- a/usr.bin/ssh/sshkey-xmss.c +++ b/usr.bin/ssh/sshkey-xmss.c @@ -1,4 +1,4 @@ -/* $OpenBSD: sshkey-xmss.c,v 1.11 2021/04/03 06:18:41 djm Exp $ */ +/* $OpenBSD: sshkey-xmss.c,v 1.12 2022/10/28 00:39:29 djm Exp $ */ /* * Copyright (c) 2017 Markus Friedl. All rights reserved. * @@ -359,7 +359,7 @@ sshkey_xmss_deserialize_pk_info(struct sshkey *k, struct sshbuf *b) } int -sshkey_xmss_generate_private_key(struct sshkey *k, u_int bits) +sshkey_xmss_generate_private_key(struct sshkey *k, int bits) { int r; const char *name; diff --git a/usr.bin/ssh/sshkey-xmss.h b/usr.bin/ssh/sshkey-xmss.h index 32a12be620b..ab8b9c905a9 100644 --- a/usr.bin/ssh/sshkey-xmss.h +++ b/usr.bin/ssh/sshkey-xmss.h @@ -1,4 +1,4 @@ -/* $OpenBSD: sshkey-xmss.h,v 1.3 2021/04/03 06:18:41 djm Exp $ */ +/* $OpenBSD: sshkey-xmss.h,v 1.4 2022/10/28 00:39:29 djm Exp $ */ /* * Copyright (c) 2017 Markus Friedl. All rights reserved. * @@ -34,7 +34,7 @@ size_t sshkey_xmss_pklen(const struct sshkey *); size_t sshkey_xmss_sklen(const struct sshkey *); int sshkey_xmss_init(struct sshkey *, const char *); void sshkey_xmss_free_state(struct sshkey *); -int sshkey_xmss_generate_private_key(struct sshkey *, u_int); +int sshkey_xmss_generate_private_key(struct sshkey *, int); int sshkey_xmss_serialize_state(const struct sshkey *, struct sshbuf *); int sshkey_xmss_serialize_state_opt(const struct sshkey *, struct sshbuf *, enum sshkey_serialize_rep); diff --git a/usr.bin/ssh/sshkey.c b/usr.bin/ssh/sshkey.c index ea52028e614..74ee6b4409a 100644 --- a/usr.bin/ssh/sshkey.c +++ b/usr.bin/ssh/sshkey.c @@ -1,4 +1,4 @@ -/* $OpenBSD: sshkey.c,v 1.126 2022/10/28 00:38:58 djm Exp $ */ +/* $OpenBSD: sshkey.c,v 1.127 2022/10/28 00:39:29 djm Exp $ */ /* * Copyright (c) 2000, 2001 Markus Friedl. All rights reserved. * Copyright (c) 2008 Alexander von Gernler. All rights reserved. @@ -1265,65 +1265,6 @@ sshkey_cert_type(const struct sshkey *k) } #ifdef WITH_OPENSSL -static int -rsa_generate_private_key(u_int bits, RSA **rsap) -{ - RSA *private = NULL; - BIGNUM *f4 = NULL; - int ret = SSH_ERR_INTERNAL_ERROR; - - if (rsap == NULL) - return SSH_ERR_INVALID_ARGUMENT; - if (bits < SSH_RSA_MINIMUM_MODULUS_SIZE || - bits > SSHBUF_MAX_BIGNUM * 8) - return SSH_ERR_KEY_LENGTH; - *rsap = NULL; - if ((private = RSA_new()) == NULL || (f4 = BN_new()) == NULL) { - ret = SSH_ERR_ALLOC_FAIL; - goto out; - } - if (!BN_set_word(f4, RSA_F4) || - !RSA_generate_key_ex(private, bits, f4, NULL)) { - ret = SSH_ERR_LIBCRYPTO_ERROR; - goto out; - } - *rsap = private; - private = NULL; - ret = 0; - out: - RSA_free(private); - BN_free(f4); - return ret; -} - -static int -dsa_generate_private_key(u_int bits, DSA **dsap) -{ - DSA *private; - int ret = SSH_ERR_INTERNAL_ERROR; - - if (dsap == NULL) - return SSH_ERR_INVALID_ARGUMENT; - if (bits != 1024) - return SSH_ERR_KEY_LENGTH; - if ((private = DSA_new()) == NULL) { - ret = SSH_ERR_ALLOC_FAIL; - goto out; - } - *dsap = NULL; - if (!DSA_generate_parameters_ex(private, bits, NULL, 0, NULL, - NULL, NULL) || !DSA_generate_key(private)) { - ret = SSH_ERR_LIBCRYPTO_ERROR; - goto out; - } - *dsap = private; - private = NULL; - ret = 0; - out: - DSA_free(private); - return ret; -} - int sshkey_ecdsa_key_to_nid(EC_KEY *k) { @@ -1366,33 +1307,6 @@ sshkey_ecdsa_key_to_nid(EC_KEY *k) return nids[i]; } -static int -ecdsa_generate_private_key(u_int bits, int *nid, EC_KEY **ecdsap) -{ - EC_KEY *private; - int ret = SSH_ERR_INTERNAL_ERROR; - - if (nid == NULL || ecdsap == NULL) - return SSH_ERR_INVALID_ARGUMENT; - if ((*nid = sshkey_ecdsa_bits_to_nid(bits)) == -1) - return SSH_ERR_KEY_LENGTH; - *ecdsap = NULL; - if ((private = EC_KEY_new_by_curve_name(*nid)) == NULL) { - ret = SSH_ERR_ALLOC_FAIL; - goto out; - } - if (EC_KEY_generate_key(private) != 1) { - ret = SSH_ERR_LIBCRYPTO_ERROR; - goto out; - } - EC_KEY_set_asn1_flag(private, OPENSSL_EC_NAMED_CURVE); - *ecdsap = private; - private = NULL; - ret = 0; - out: - EC_KEY_free(private); - return ret; -} #endif /* WITH_OPENSSL */ int @@ -1400,48 +1314,25 @@ sshkey_generate(int type, u_int bits, struct sshkey **keyp) { struct sshkey *k; int ret = SSH_ERR_INTERNAL_ERROR; + const struct sshkey_impl *impl; - if (keyp == NULL) + if (keyp == NULL || sshkey_type_is_cert(type)) return SSH_ERR_INVALID_ARGUMENT; *keyp = NULL; + if ((impl = sshkey_impl_from_type(type)) == NULL) + return SSH_ERR_KEY_TYPE_UNKNOWN; + if (impl->funcs->generate == NULL) + return SSH_ERR_FEATURE_UNSUPPORTED; if ((k = sshkey_new(KEY_UNSPEC)) == NULL) return SSH_ERR_ALLOC_FAIL; - switch (type) { - case KEY_ED25519: - if ((k->ed25519_pk = malloc(ED25519_PK_SZ)) == NULL || - (k->ed25519_sk = malloc(ED25519_SK_SZ)) == NULL) { - ret = SSH_ERR_ALLOC_FAIL; - break; - } - crypto_sign_ed25519_keypair(k->ed25519_pk, k->ed25519_sk); - ret = 0; - break; -#ifdef WITH_XMSS - case KEY_XMSS: - ret = sshkey_xmss_generate_private_key(k, bits); - break; -#endif /* WITH_XMSS */ -#ifdef WITH_OPENSSL - case KEY_DSA: - ret = dsa_generate_private_key(bits, &k->dsa); - break; - case KEY_ECDSA: - ret = ecdsa_generate_private_key(bits, &k->ecdsa_nid, - &k->ecdsa); - break; - case KEY_RSA: - ret = rsa_generate_private_key(bits, &k->rsa); - break; -#endif /* WITH_OPENSSL */ - default: - ret = SSH_ERR_INVALID_ARGUMENT; - } - if (ret == 0) { - k->type = type; - *keyp = k; - } else + k->type = type; + if ((ret = impl->funcs->generate(k, bits)) != 0) { sshkey_free(k); - return ret; + return ret; + } + /* success */ + *keyp = k; + return 0; } int diff --git a/usr.bin/ssh/sshkey.h b/usr.bin/ssh/sshkey.h index 87c8005ab18..c90724ac575 100644 --- a/usr.bin/ssh/sshkey.h +++ b/usr.bin/ssh/sshkey.h @@ -1,4 +1,4 @@ -/* $OpenBSD: sshkey.h,v 1.55 2022/10/28 00:37:24 djm Exp $ */ +/* $OpenBSD: sshkey.h,v 1.56 2022/10/28 00:39:29 djm Exp $ */ /* * Copyright (c) 2000, 2001 Markus Friedl. All rights reserved. @@ -165,6 +165,7 @@ struct sshkey_impl_funcs { int (*equal)(const struct sshkey *, const struct sshkey *); int (*serialize_public)(const struct sshkey *, struct sshbuf *, const char *, enum sshkey_serialize_rep); + int (*generate)(struct sshkey *, int); /* optional */ }; struct sshkey_impl {