factor out key generation
authordjm <djm@openbsd.org>
Fri, 28 Oct 2022 00:39:29 +0000 (00:39 +0000)
committerdjm <djm@openbsd.org>
Fri, 28 Oct 2022 00:39:29 +0000 (00:39 +0000)
feedback/ok markus@

usr.bin/ssh/ssh-dss.c
usr.bin/ssh/ssh-ecdsa-sk.c
usr.bin/ssh/ssh-ecdsa.c
usr.bin/ssh/ssh-ed25519-sk.c
usr.bin/ssh/ssh-ed25519.c
usr.bin/ssh/ssh-rsa.c
usr.bin/ssh/ssh-xmss.c
usr.bin/ssh/sshkey-xmss.c
usr.bin/ssh/sshkey-xmss.h
usr.bin/ssh/sshkey.c
usr.bin/ssh/sshkey.h

index fdfc55c..6b2c487 100644 (file)
@@ -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 = {
index 6c663c2..5c844d8 100644 (file)
@@ -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 = {
index af3413e..9e57664 100644 (file)
@@ -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 = {
index 9183a43..7131363 100644 (file)
@@ -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 = {
index a5a37bd..bbf164c 100644 (file)
@@ -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>
  *
@@ -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 = {
index 58c071c..f6aa4bf 100644 (file)
@@ -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>
  *
@@ -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 = {
index aee1edb..30cd89c 100644 (file)
@@ -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 = {
index d3acf57..71660b4 100644 (file)
@@ -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;
index 32a12be..ab8b9c9 100644 (file)
@@ -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);
index ea52028..74ee6b4 100644 (file)
@@ -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
index 87c8005..c90724a 100644 (file)
@@ -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 {