diff options
author | djm@openbsd.org <djm@openbsd.org> | 2022-10-28 02:39:29 +0200 |
---|---|---|
committer | Damien Miller <djm@mindrot.org> | 2022-10-28 03:46:58 +0200 |
commit | 262647c2e920492ca57f1b9320d74f4a0f6e482b (patch) | |
tree | 1ce89f627b8230d5ce9611ebe698e5b3f4338fa1 | |
parent | upstream: refactor and simplify sshkey_read() (diff) | |
download | openssh-262647c2e920492ca57f1b9320d74f4a0f6e482b.tar.xz openssh-262647c2e920492ca57f1b9320d74f4a0f6e482b.zip |
upstream: factor out key generation
feedback/ok markus@
OpenBSD-Commit-ID: 5b4211bff4de8d9adb84bc72857a8c42c44e7ceb
-rw-r--r-- | ssh-dss.c | 21 | ||||
-rw-r--r-- | ssh-ecdsa-sk.c | 3 | ||||
-rw-r--r-- | ssh-ecdsa.c | 21 | ||||
-rw-r--r-- | ssh-ed25519-sk.c | 3 | ||||
-rw-r--r-- | ssh-ed25519.c | 13 | ||||
-rw-r--r-- | ssh-rsa.c | 31 | ||||
-rw-r--r-- | ssh-xmss.c | 3 | ||||
-rw-r--r-- | sshkey-xmss.c | 4 | ||||
-rw-r--r-- | sshkey-xmss.h | 4 | ||||
-rw-r--r-- | sshkey.c | 140 | ||||
-rw-r--r-- | sshkey.h | 3 |
11 files changed, 108 insertions, 138 deletions
@@ -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. * @@ -126,6 +126,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) @@ -289,6 +307,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/ssh-ecdsa-sk.c b/ssh-ecdsa-sk.c index 228e1b093..cbc9b0e1c 100644 --- a/ssh-ecdsa-sk.c +++ b/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. @@ -362,6 +362,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/ssh-ecdsa.c b/ssh-ecdsa.c index 24f66bdc0..16a8ea877 100644 --- a/ssh-ecdsa.c +++ b/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. @@ -108,6 +108,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, @@ -267,6 +285,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/ssh-ed25519-sk.c b/ssh-ed25519-sk.c index b95227c0f..6236ee12a 100644 --- a/ssh-ed25519-sk.c +++ b/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. * @@ -203,6 +203,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/ssh-ed25519.c b/ssh-ed25519.c index 72c850000..f2a38c280 100644 --- a/ssh-ed25519.c +++ b/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 <markus@openbsd.org> * @@ -66,6 +66,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) @@ -200,6 +210,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 = { @@ -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 <markus@openbsd.org> * @@ -104,6 +104,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) { @@ -518,6 +546,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/ssh-xmss.c b/ssh-xmss.c index 7031baf9d..da8b4cc30 100644 --- a/ssh-xmss.c +++ b/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. @@ -236,6 +236,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/sshkey-xmss.c b/sshkey-xmss.c index f5235ef2f..818aba905 100644 --- a/sshkey-xmss.c +++ b/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. * @@ -365,7 +365,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/sshkey-xmss.h b/sshkey-xmss.h index 32a12be62..ab8b9c905 100644 --- a/sshkey-xmss.h +++ b/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); @@ -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. @@ -1295,65 +1295,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; -} - # ifdef OPENSSL_HAS_ECC int sshkey_ecdsa_key_to_nid(EC_KEY *k) @@ -1398,34 +1339,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 /* OPENSSL_HAS_ECC */ #endif /* WITH_OPENSSL */ @@ -1434,50 +1347,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; -# ifdef OPENSSL_HAS_ECC - case KEY_ECDSA: - ret = ecdsa_generate_private_key(bits, &k->ecdsa_nid, - &k->ecdsa); - break; -# endif /* OPENSSL_HAS_ECC */ - 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 @@ -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. @@ -171,6 +171,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 { |