refactor sshkey_private_serialize_opt()
authordjm <djm@openbsd.org>
Fri, 28 Oct 2022 00:44:17 +0000 (00:44 +0000)
committerdjm <djm@openbsd.org>
Fri, 28 Oct 2022 00:44:17 +0000 (00:44 +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/sshd.c
usr.bin/ssh/sshkey.c
usr.bin/ssh/sshkey.h

index 5c3ecd2..85641e4 100644 (file)
@@ -1,4 +1,4 @@
-/* $OpenBSD: ssh-dss.c,v 1.46 2022/10/28 00:43:08 djm Exp $ */
+/* $OpenBSD: ssh-dss.c,v 1.47 2022/10/28 00:44:17 djm Exp $ */
 /*
  * Copyright (c) 2000 Markus Friedl.  All rights reserved.
  *
@@ -117,6 +117,24 @@ ssh_dss_serialize_public(const struct sshkey *key, struct sshbuf *b,
        return 0;
 }
 
+static int
+ssh_dss_serialize_private(const struct sshkey *key, struct sshbuf *b,
+    enum sshkey_serialize_rep opts)
+{
+       int r;
+       const BIGNUM *dsa_priv_key;
+
+       DSA_get0_key(key->dsa, NULL, &dsa_priv_key);
+       if (!sshkey_is_cert(key)) {
+               if ((r = ssh_dss_serialize_public(key, b, opts)) != 0)
+                       return r;
+       }
+       if ((r = sshbuf_put_bignum2(b, dsa_priv_key)) != 0)
+               return r;
+
+       return 0;
+}
+
 static int
 ssh_dss_generate(struct sshkey *k, int bits)
 {
@@ -376,6 +394,7 @@ static const struct sshkey_impl_funcs sshkey_dss_funcs = {
        /* .equal = */          ssh_dss_equal,
        /* .ssh_serialize_public = */ ssh_dss_serialize_public,
        /* .ssh_deserialize_public = */ ssh_dss_deserialize_public,
+       /* .ssh_serialize_private = */ ssh_dss_serialize_private,
        /* .generate = */       ssh_dss_generate,
        /* .copy_public = */    ssh_dss_copy_public,
        /* .sign = */           ssh_dss_sign,
index 0858003..fc53dba 100644 (file)
@@ -1,4 +1,4 @@
-/* $OpenBSD: ssh-ecdsa-sk.c,v 1.15 2022/10/28 00:43:08 djm Exp $ */
+/* $OpenBSD: ssh-ecdsa-sk.c,v 1.16 2022/10/28 00:44:17 djm Exp $ */
 /*
  * Copyright (c) 2000 Markus Friedl.  All rights reserved.
  * Copyright (c) 2010 Damien Miller.  All rights reserved.
@@ -77,6 +77,23 @@ ssh_ecdsa_sk_serialize_public(const struct sshkey *key, struct sshbuf *b,
        return 0;
 }
 
+static int
+ssh_ecdsa_sk_serialize_private(const struct sshkey *key, struct sshbuf *b,
+    enum sshkey_serialize_rep opts)
+{
+       int r;
+
+       if (!sshkey_is_cert(key)) {
+               if ((r = sshkey_ecdsa_funcs.serialize_public(key,
+                   b, opts)) != 0)
+                       return r;
+       }
+       if ((r = sshkey_serialize_private_sk(key, b)) != 0)
+               return r;
+
+       return 0;
+}
+
 static int
 ssh_ecdsa_sk_copy_public(const struct sshkey *from, struct sshkey *to)
 {
@@ -369,6 +386,7 @@ static const struct sshkey_impl_funcs sshkey_ecdsa_sk_funcs = {
        /* .equal = */          ssh_ecdsa_sk_equal,
        /* .ssh_serialize_public = */ ssh_ecdsa_sk_serialize_public,
        /* .ssh_deserialize_public = */ ssh_ecdsa_sk_deserialize_public,
+       /* .ssh_serialize_private = */ ssh_ecdsa_sk_serialize_private,
        /* .generate = */       NULL,
        /* .copy_public = */    ssh_ecdsa_sk_copy_public,
        /* .sign = */           NULL,
index df680de..8c08b23 100644 (file)
@@ -1,4 +1,4 @@
-/* $OpenBSD: ssh-ecdsa.c,v 1.23 2022/10/28 00:43:08 djm Exp $ */
+/* $OpenBSD: ssh-ecdsa.c,v 1.24 2022/10/28 00:44:17 djm Exp $ */
 /*
  * Copyright (c) 2000 Markus Friedl.  All rights reserved.
  * Copyright (c) 2010 Damien Miller.  All rights reserved.
@@ -99,6 +99,22 @@ ssh_ecdsa_serialize_public(const struct sshkey *key, struct sshbuf *b,
        return 0;
 }
 
+static int
+ssh_ecdsa_serialize_private(const struct sshkey *key, struct sshbuf *b,
+    enum sshkey_serialize_rep opts)
+{
+       int r;
+
+       if (!sshkey_is_cert(key)) {
+               if ((r = ssh_ecdsa_serialize_public(key, b, opts)) != 0)
+                       return r;
+       }
+       if ((r = sshbuf_put_bignum2(b,
+           EC_KEY_get0_private_key(key->ecdsa))) != 0)
+               return r;
+       return 0;
+}
+
 static int
 ssh_ecdsa_generate(struct sshkey *k, int bits)
 {
@@ -342,6 +358,7 @@ const struct sshkey_impl_funcs sshkey_ecdsa_funcs = {
        /* .equal = */          ssh_ecdsa_equal,
        /* .ssh_serialize_public = */ ssh_ecdsa_serialize_public,
        /* .ssh_deserialize_public = */ ssh_ecdsa_deserialize_public,
+       /* .ssh_serialize_private = */ ssh_ecdsa_serialize_private,
        /* .generate = */       ssh_ecdsa_generate,
        /* .copy_public = */    ssh_ecdsa_copy_public,
        /* .sign = */           ssh_ecdsa_sign,
index 92ac429..b849c11 100644 (file)
@@ -1,4 +1,4 @@
-/* $OpenBSD: ssh-ed25519-sk.c,v 1.13 2022/10/28 00:43:08 djm Exp $ */
+/* $OpenBSD: ssh-ed25519-sk.c,v 1.14 2022/10/28 00:44:17 djm Exp $ */
 /*
  * Copyright (c) 2019 Markus Friedl.  All rights reserved.
  *
@@ -67,6 +67,20 @@ ssh_ed25519_sk_serialize_public(const struct sshkey *key, struct sshbuf *b,
        return 0;
 }
 
+static int
+ssh_ed25519_sk_serialize_private(const struct sshkey *key, struct sshbuf *b,
+    enum sshkey_serialize_rep opts)
+{
+       int r;
+
+       if ((r = sshkey_ed25519_funcs.serialize_public(key, b, opts)) != 0)
+               return r;
+       if ((r = sshkey_serialize_private_sk(key, b)) != 0)
+               return r;
+
+       return 0;
+}
+
 static int
 ssh_ed25519_sk_copy_public(const struct sshkey *from, struct sshkey *to)
 {
@@ -226,6 +240,7 @@ static const struct sshkey_impl_funcs sshkey_ed25519_sk_funcs = {
        /* .equal = */          ssh_ed25519_sk_equal,
        /* .ssh_serialize_public = */ ssh_ed25519_sk_serialize_public,
        /* .ssh_deserialize_public = */ ssh_ed25519_sk_deserialize_public,
+       /* .ssh_serialize_private = */ ssh_ed25519_sk_serialize_private,
        /* .generate = */       NULL,
        /* .copy_public = */    ssh_ed25519_sk_copy_public,
        /* .sign = */           NULL,
index 7d1e8b2..7eba617 100644 (file)
@@ -1,4 +1,4 @@
-/* $OpenBSD: ssh-ed25519.c,v 1.17 2022/10/28 00:43:08 djm Exp $ */
+/* $OpenBSD: ssh-ed25519.c,v 1.18 2022/10/28 00:44:17 djm Exp $ */
 /*
  * Copyright (c) 2013 Markus Friedl <markus@openbsd.org>
  *
@@ -62,6 +62,19 @@ ssh_ed25519_serialize_public(const struct sshkey *key, struct sshbuf *b,
        return 0;
 }
 
+static int
+ssh_ed25519_serialize_private(const struct sshkey *key, struct sshbuf *b,
+    enum sshkey_serialize_rep opts)
+{
+       int r;
+
+       if ((r = sshbuf_put_string(b, key->ed25519_pk, ED25519_PK_SZ)) != 0 ||
+           (r = sshbuf_put_string(b, key->ed25519_sk, ED25519_SK_SZ)) != 0)
+               return r;
+
+       return 0;
+}
+
 static int
 ssh_ed25519_generate(struct sshkey *k, int bits)
 {
@@ -239,6 +252,7 @@ const struct sshkey_impl_funcs sshkey_ed25519_funcs = {
        /* .equal = */          ssh_ed25519_equal,
        /* .ssh_serialize_public = */ ssh_ed25519_serialize_public,
        /* .ssh_deserialize_public = */ ssh_ed25519_deserialize_public,
+       /* .ssh_serialize_private = */ ssh_ed25519_serialize_private,
        /* .generate = */       ssh_ed25519_generate,
        /* .copy_public = */    ssh_ed25519_copy_public,
        /* .sign = */           ssh_ed25519_sign,
index 9652513..cbb8600 100644 (file)
@@ -1,4 +1,4 @@
-/* $OpenBSD: ssh-rsa.c,v 1.75 2022/10/28 00:43:08 djm Exp $ */
+/* $OpenBSD: ssh-rsa.c,v 1.76 2022/10/28 00:44:17 djm Exp $ */
 /*
  * Copyright (c) 2000, 2003 Markus Friedl <markus@openbsd.org>
  *
@@ -116,6 +116,32 @@ ssh_rsa_serialize_public(const struct sshkey *key, struct sshbuf *b,
        return 0;
 }
 
+static int
+ssh_rsa_serialize_private(const struct sshkey *key, struct sshbuf *b,
+    enum sshkey_serialize_rep opts)
+{
+       int r;
+       const BIGNUM *rsa_n, *rsa_e, *rsa_d, *rsa_iqmp, *rsa_p, *rsa_q;
+
+       RSA_get0_key(key->rsa, &rsa_n, &rsa_e, &rsa_d);
+       RSA_get0_factors(key->rsa, &rsa_p, &rsa_q);
+       RSA_get0_crt_params(key->rsa, NULL, NULL, &rsa_iqmp);
+
+       if (!sshkey_is_cert(key)) {
+               /* Note: can't reuse ssh_rsa_serialize_public: e, n vs. n, e */
+               if ((r = sshbuf_put_bignum2(b, rsa_n)) != 0 ||
+                   (r = sshbuf_put_bignum2(b, rsa_e)) != 0)
+                       return r;
+       }
+       if ((r = sshbuf_put_bignum2(b, rsa_d)) != 0 ||
+           (r = sshbuf_put_bignum2(b, rsa_iqmp)) != 0 ||
+           (r = sshbuf_put_bignum2(b, rsa_p)) != 0 ||
+           (r = sshbuf_put_bignum2(b, rsa_q)) != 0)
+               return r;
+
+       return 0;
+}
+
 static int
 ssh_rsa_generate(struct sshkey *k, int bits)
 {
@@ -618,6 +644,7 @@ static const struct sshkey_impl_funcs sshkey_rsa_funcs = {
        /* .equal = */          ssh_rsa_equal,
        /* .ssh_serialize_public = */ ssh_rsa_serialize_public,
        /* .ssh_deserialize_public = */ ssh_rsa_deserialize_public,
+       /* .ssh_serialize_private = */ ssh_rsa_serialize_private,
        /* .generate = */       ssh_rsa_generate,
        /* .copy_public = */    ssh_rsa_copy_public,
        /* .sign = */           ssh_rsa_sign,
index ebde4c5..2bd2988 100644 (file)
@@ -1,4 +1,4 @@
-/* $OpenBSD: ssh-xmss.c,v 1.12 2022/10/28 00:43:08 djm Exp $*/
+/* $OpenBSD: ssh-xmss.c,v 1.13 2022/10/28 00:44:17 djm Exp $*/
 /*
  * Copyright (c) 2017 Stefan-Lukas Gazdag.
  * Copyright (c) 2017 Markus Friedl.
@@ -78,6 +78,26 @@ ssh_xmss_serialize_public(const struct sshkey *key, struct sshbuf *b,
        return 0;
 }
 
+static int
+ssh_xmss_serialize_private(const struct sshkey *key, struct sshbuf *b,
+    enum sshkey_serialize_rep opts)
+{
+       int r;
+
+       if (key->xmss_name == NULL)
+               return SSH_ERR_INVALID_ARGUMENT;
+       /* Note: can't reuse ssh_xmss_serialize_public because of sk order */
+       if ((r = sshbuf_put_cstring(b, key->xmss_name)) != 0 ||
+           (r = sshbuf_put_string(b, key->xmss_pk,
+           sshkey_xmss_pklen(key))) != 0 ||
+           (r = sshbuf_put_string(b, key->xmss_sk,
+           sshkey_xmss_sklen(key))) != 0 ||
+           (r = sshkey_xmss_serialize_state_opt(key, b, opts)) != 0)
+               return r;
+
+       return 0;
+}
+
 static int
 ssh_xmss_copy_public(const struct sshkey *from, struct sshkey *to)
 {
@@ -293,6 +313,7 @@ static const struct sshkey_impl_funcs sshkey_xmss_funcs = {
        /* .equal = */          ssh_xmss_equal,
        /* .ssh_serialize_public = */ ssh_xmss_serialize_public,
        /* .ssh_deserialize_public = */ ssh_xmss_deserialize_public,
+       /* .ssh_serialize_private = */ ssh_xmss_serialize_private,
        /* .generate = */       sshkey_xmss_generate_private_key,
        /* .copy_public = */    ssh_xmss_copy_public,
        /* .sign = */           ssh_xmss_sign,
index 69111e8..45c7393 100644 (file)
@@ -1,4 +1,4 @@
-/* $OpenBSD: sshd.c,v 1.591 2022/09/17 10:34:29 djm Exp $ */
+/* $OpenBSD: sshd.c,v 1.592 2022/10/28 00:44:17 djm Exp $ */
 /*
  * Author: Tatu Ylonen <ylo@cs.hut.fi>
  * Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
@@ -1426,7 +1426,7 @@ accumulate_host_timing_secret(struct sshbuf *server_cfg,
        if ((buf = sshbuf_new()) == NULL)
                fatal_f("could not allocate buffer");
        if ((r = sshkey_private_serialize(key, buf)) != 0)
-               fatal_fr(r, "decode key");
+               fatal_fr(r, "encode %s key", sshkey_ssh_name(key));
        if (ssh_digest_update(ctx, sshbuf_ptr(buf), sshbuf_len(buf)) != 0)
                fatal_f("ssh_digest_update");
        sshbuf_reset(buf);
index 17d7094..0644d59 100644 (file)
@@ -1,4 +1,4 @@
-/* $OpenBSD: sshkey.c,v 1.131 2022/10/28 00:43:30 djm Exp $ */
+/* $OpenBSD: sshkey.c,v 1.132 2022/10/28 00:44:17 djm Exp $ */
 /*
  * Copyright (c) 2000, 2001 Markus Friedl.  All rights reserved.
  * Copyright (c) 2008 Alexander von Gernler.  All rights reserved.
@@ -2364,6 +2364,21 @@ sshkey_format_cert_validity(const struct sshkey_cert *cert, char *s, size_t l)
        return strlcpy(s, ret, l);
 }
 
+/* Common serialization for FIDO private keys */
+int
+sshkey_serialize_private_sk(const struct sshkey *key, struct sshbuf *b)
+{
+       int r;
+
+       if ((r = sshbuf_put_cstring(b, key->sk_application)) != 0 ||
+           (r = sshbuf_put_u8(b, key->sk_flags)) != 0 ||
+           (r = sshbuf_put_stringb(b, key->sk_key_handle)) != 0 ||
+           (r = sshbuf_put_stringb(b, key->sk_reserved)) != 0)
+               return r;
+
+       return 0;
+}
+
 int
 sshkey_private_serialize_opt(struct sshkey *key, struct sshbuf *buf,
     enum sshkey_serialize_rep opts)
@@ -2371,183 +2386,28 @@ sshkey_private_serialize_opt(struct sshkey *key, struct sshbuf *buf,
        int r = SSH_ERR_INTERNAL_ERROR;
        int was_shielded = sshkey_is_shielded(key);
        struct sshbuf *b = NULL;
-#ifdef WITH_OPENSSL
-       const BIGNUM *rsa_n, *rsa_e, *rsa_d, *rsa_iqmp, *rsa_p, *rsa_q;
-       const BIGNUM *dsa_p, *dsa_q, *dsa_g, *dsa_pub_key, *dsa_priv_key;
-#endif /* WITH_OPENSSL */
+       const struct sshkey_impl *impl;
 
+       if ((impl = sshkey_impl_from_key(key)) == NULL)
+               return SSH_ERR_INTERNAL_ERROR;
        if ((r = sshkey_unshield_private(key)) != 0)
                return r;
        if ((b = sshbuf_new()) == NULL)
                return SSH_ERR_ALLOC_FAIL;
        if ((r = sshbuf_put_cstring(b, sshkey_ssh_name(key))) != 0)
                goto out;
-       switch (key->type) {
-#ifdef WITH_OPENSSL
-       case KEY_RSA:
-               RSA_get0_key(key->rsa, &rsa_n, &rsa_e, &rsa_d);
-               RSA_get0_factors(key->rsa, &rsa_p, &rsa_q);
-               RSA_get0_crt_params(key->rsa, NULL, NULL, &rsa_iqmp);
-               if ((r = sshbuf_put_bignum2(b, rsa_n)) != 0 ||
-                   (r = sshbuf_put_bignum2(b, rsa_e)) != 0 ||
-                   (r = sshbuf_put_bignum2(b, rsa_d)) != 0 ||
-                   (r = sshbuf_put_bignum2(b, rsa_iqmp)) != 0 ||
-                   (r = sshbuf_put_bignum2(b, rsa_p)) != 0 ||
-                   (r = sshbuf_put_bignum2(b, rsa_q)) != 0)
-                       goto out;
-               break;
-       case KEY_RSA_CERT:
-               if (key->cert == NULL || sshbuf_len(key->cert->certblob) == 0) {
-                       r = SSH_ERR_INVALID_ARGUMENT;
-                       goto out;
-               }
-               RSA_get0_key(key->rsa, NULL, NULL, &rsa_d);
-               RSA_get0_factors(key->rsa, &rsa_p, &rsa_q);
-               RSA_get0_crt_params(key->rsa, NULL, NULL, &rsa_iqmp);
-               if ((r = sshbuf_put_stringb(b, key->cert->certblob)) != 0 ||
-                   (r = sshbuf_put_bignum2(b, rsa_d)) != 0 ||
-                   (r = sshbuf_put_bignum2(b, rsa_iqmp)) != 0 ||
-                   (r = sshbuf_put_bignum2(b, rsa_p)) != 0 ||
-                   (r = sshbuf_put_bignum2(b, rsa_q)) != 0)
-                       goto out;
-               break;
-       case KEY_DSA:
-               DSA_get0_pqg(key->dsa, &dsa_p, &dsa_q, &dsa_g);
-               DSA_get0_key(key->dsa, &dsa_pub_key, &dsa_priv_key);
-               if ((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 ||
-                   (r = sshbuf_put_bignum2(b, dsa_priv_key)) != 0)
-                       goto out;
-               break;
-       case KEY_DSA_CERT:
-               if (key->cert == NULL || sshbuf_len(key->cert->certblob) == 0) {
-                       r = SSH_ERR_INVALID_ARGUMENT;
-                       goto out;
-               }
-               DSA_get0_key(key->dsa, NULL, &dsa_priv_key);
-               if ((r = sshbuf_put_stringb(b, key->cert->certblob)) != 0 ||
-                   (r = sshbuf_put_bignum2(b, dsa_priv_key)) != 0)
-                       goto out;
-               break;
-       case KEY_ECDSA:
-               if ((r = sshbuf_put_cstring(b,
-                   sshkey_curve_nid_to_name(key->ecdsa_nid))) != 0 ||
-                   (r = sshbuf_put_eckey(b, key->ecdsa)) != 0 ||
-                   (r = sshbuf_put_bignum2(b,
-                   EC_KEY_get0_private_key(key->ecdsa))) != 0)
-                       goto out;
-               break;
-       case KEY_ECDSA_CERT:
-               if (key->cert == NULL || sshbuf_len(key->cert->certblob) == 0) {
-                       r = SSH_ERR_INVALID_ARGUMENT;
-                       goto out;
-               }
-               if ((r = sshbuf_put_stringb(b, key->cert->certblob)) != 0 ||
-                   (r = sshbuf_put_bignum2(b,
-                   EC_KEY_get0_private_key(key->ecdsa))) != 0)
-                       goto out;
-               break;
-       case KEY_ECDSA_SK:
-               if ((r = sshbuf_put_cstring(b,
-                   sshkey_curve_nid_to_name(key->ecdsa_nid))) != 0 ||
-                   (r = sshbuf_put_eckey(b, key->ecdsa)) != 0 ||
-                   (r = sshbuf_put_cstring(b, key->sk_application)) != 0 ||
-                   (r = sshbuf_put_u8(b, key->sk_flags)) != 0 ||
-                   (r = sshbuf_put_stringb(b, key->sk_key_handle)) != 0 ||
-                   (r = sshbuf_put_stringb(b, key->sk_reserved)) != 0)
-                       goto out;
-               break;
-       case KEY_ECDSA_SK_CERT:
-               if (key->cert == NULL || sshbuf_len(key->cert->certblob) == 0) {
-                       r = SSH_ERR_INVALID_ARGUMENT;
-                       goto out;
-               }
-               if ((r = sshbuf_put_stringb(b, key->cert->certblob)) != 0 ||
-                   (r = sshbuf_put_cstring(b, key->sk_application)) != 0 ||
-                   (r = sshbuf_put_u8(b, key->sk_flags)) != 0 ||
-                   (r = sshbuf_put_stringb(b, key->sk_key_handle)) != 0 ||
-                   (r = sshbuf_put_stringb(b, key->sk_reserved)) != 0)
-                       goto out;
-               break;
-#endif /* WITH_OPENSSL */
-       case KEY_ED25519:
-               if ((r = sshbuf_put_string(b, key->ed25519_pk,
-                   ED25519_PK_SZ)) != 0 ||
-                   (r = sshbuf_put_string(b, key->ed25519_sk,
-                   ED25519_SK_SZ)) != 0)
-                       goto out;
-               break;
-       case KEY_ED25519_CERT:
-               if (key->cert == NULL || sshbuf_len(key->cert->certblob) == 0) {
+       if (sshkey_is_cert(key)) {
+               if (key->cert == NULL ||
+                   sshbuf_len(key->cert->certblob) == 0) {
                        r = SSH_ERR_INVALID_ARGUMENT;
                        goto out;
                }
-               if ((r = sshbuf_put_stringb(b, key->cert->certblob)) != 0 ||
-                   (r = sshbuf_put_string(b, key->ed25519_pk,
-                   ED25519_PK_SZ)) != 0 ||
-                   (r = sshbuf_put_string(b, key->ed25519_sk,
-                   ED25519_SK_SZ)) != 0)
-                       goto out;
-               break;
-       case KEY_ED25519_SK:
-               if ((r = sshbuf_put_string(b, key->ed25519_pk,
-                   ED25519_PK_SZ)) != 0 ||
-                   (r = sshbuf_put_cstring(b, key->sk_application)) != 0 ||
-                   (r = sshbuf_put_u8(b, key->sk_flags)) != 0 ||
-                   (r = sshbuf_put_stringb(b, key->sk_key_handle)) != 0 ||
-                   (r = sshbuf_put_stringb(b, key->sk_reserved)) != 0)
+               if ((r = sshbuf_put_stringb(b, key->cert->certblob)) != 0)
                        goto out;
-               break;
-       case KEY_ED25519_SK_CERT:
-               if (key->cert == NULL || sshbuf_len(key->cert->certblob) == 0) {
-                       r = SSH_ERR_INVALID_ARGUMENT;
-                       goto out;
-               }
-               if ((r = sshbuf_put_stringb(b, key->cert->certblob)) != 0 ||
-                   (r = sshbuf_put_string(b, key->ed25519_pk,
-                   ED25519_PK_SZ)) != 0 ||
-                   (r = sshbuf_put_cstring(b, key->sk_application)) != 0 ||
-                   (r = sshbuf_put_u8(b, key->sk_flags)) != 0 ||
-                   (r = sshbuf_put_stringb(b, key->sk_key_handle)) != 0 ||
-                   (r = sshbuf_put_stringb(b, key->sk_reserved)) != 0)
-                       goto out;
-               break;
-#ifdef WITH_XMSS
-       case KEY_XMSS:
-               if (key->xmss_name == NULL) {
-                       r = SSH_ERR_INVALID_ARGUMENT;
-                       goto out;
-               }
-               if ((r = sshbuf_put_cstring(b, key->xmss_name)) != 0 ||
-                   (r = sshbuf_put_string(b, key->xmss_pk,
-                   sshkey_xmss_pklen(key))) != 0 ||
-                   (r = sshbuf_put_string(b, key->xmss_sk,
-                   sshkey_xmss_sklen(key))) != 0 ||
-                   (r = sshkey_xmss_serialize_state_opt(key, b, opts)) != 0)
-                       goto out;
-               break;
-       case KEY_XMSS_CERT:
-               if (key->cert == NULL || sshbuf_len(key->cert->certblob) == 0 ||
-                   key->xmss_name == NULL) {
-                       r = SSH_ERR_INVALID_ARGUMENT;
-                       goto out;
-               }
-               if ((r = sshbuf_put_stringb(b, key->cert->certblob)) != 0 ||
-                   (r = sshbuf_put_cstring(b, key->xmss_name)) != 0 ||
-                   (r = sshbuf_put_string(b, key->xmss_pk,
-                   sshkey_xmss_pklen(key))) != 0 ||
-                   (r = sshbuf_put_string(b, key->xmss_sk,
-                   sshkey_xmss_sklen(key))) != 0 ||
-                   (r = sshkey_xmss_serialize_state_opt(key, b, opts)) != 0)
-                       goto out;
-               break;
-#endif /* WITH_XMSS */
-       default:
-               r = SSH_ERR_INVALID_ARGUMENT;
-               goto out;
        }
+       if ((r = impl->funcs->serialize_private(key, b, opts)) != 0)
+               goto out;
+
        /*
         * success (but we still need to append the output to buf after
         * possibly re-shielding the private key)
index f8eeed5..ea37713 100644 (file)
@@ -1,4 +1,4 @@
-/* $OpenBSD: sshkey.h,v 1.59 2022/10/28 00:43:08 djm Exp $ */
+/* $OpenBSD: sshkey.h,v 1.60 2022/10/28 00:44:17 djm Exp $ */
 
 /*
  * Copyright (c) 2000, 2001 Markus Friedl.  All rights reserved.
@@ -167,6 +167,8 @@ struct sshkey_impl_funcs {
            enum sshkey_serialize_rep);
        int (*deserialize_public)(const char *, struct sshbuf *,
            struct sshkey *);
+       int (*serialize_private)(const struct sshkey *, struct sshbuf *,
+           enum sshkey_serialize_rep);
        int (*generate)(struct sshkey *, int);  /* optional */
        int (*copy_public)(const struct sshkey *, struct sshkey *);
        int (*sign)(struct sshkey *, u_char **, size_t *,
@@ -318,6 +320,8 @@ 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    sshkey_deserialize_sk(struct sshbuf *b, struct sshkey *key);
+int    sshkey_serialize_private_sk(const struct sshkey *key,
+    struct sshbuf *buf);
 #ifdef WITH_OPENSSL
 int    check_rsa_length(const RSA *rsa); /* XXX remove */
 #endif