[openssh-commits] [openssh] 03/11: upstream: factor out public key serialization

git+noreply at mindrot.org git+noreply at mindrot.org
Fri Oct 28 12:47:28 AEDT 2022


This is an automated email from the git hooks/post-receive script.

djm pushed a commit to branch master
in repository openssh.

commit 591fed94e66a016acf87f4b7cd416ce812f2abe8
Author: djm at openbsd.org <djm at openbsd.org>
Date:   Fri Oct 28 00:37:24 2022 +0000

    upstream: factor out public key serialization
    
    feedback/ok markus@
    
    OpenBSD-Commit-ID: a3570c4b97290c5662890aea7328d87f55939033
---
 ssh-dss.c        |  27 ++++++++++++-
 ssh-ecdsa-sk.c   |  18 ++++++++-
 ssh-ecdsa.c      |  21 +++++++++-
 ssh-ed25519-sk.c |  18 ++++++++-
 ssh-ed25519.c    |  18 ++++++++-
 ssh-rsa.c        |  21 +++++++++-
 ssh-xmss.c       |  22 ++++++++++-
 sshkey.c         | 117 ++++++++++++-------------------------------------------
 sshkey.h         |   5 ++-
 9 files changed, 166 insertions(+), 101 deletions(-)

diff --git a/ssh-dss.c b/ssh-dss.c
index 15d6cea3..e955fdd5 100644
--- a/ssh-dss.c
+++ b/ssh-dss.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: ssh-dss.c,v 1.41 2022/10/28 00:36:31 djm Exp $ */
+/* $OpenBSD: ssh-dss.c,v 1.42 2022/10/28 00:37:24 djm Exp $ */
 /*
  * Copyright (c) 2000 Markus Friedl.  All rights reserved.
  *
@@ -102,6 +102,30 @@ ssh_dss_equal(const struct sshkey *a, const struct sshkey *b)
 	return 1;
 }
 
+static int
+ssh_dss_serialize_public(const struct sshkey *key, struct sshbuf *b,
+    const char *typename, enum sshkey_serialize_rep opts)
+{
+	int r;
+	const BIGNUM *dsa_p, *dsa_q, *dsa_g, *dsa_pub_key;
+
+	if (key->dsa == NULL)
+		return SSH_ERR_INVALID_ARGUMENT;
+	DSA_get0_pqg(key->dsa, &dsa_p, &dsa_q, &dsa_g);
+	DSA_get0_key(key->dsa, &dsa_pub_key, NULL);
+	if (dsa_p == NULL || dsa_q == NULL ||
+	    dsa_g == NULL || dsa_pub_key == NULL)
+		return SSH_ERR_INTERNAL_ERROR;
+	if ((r = sshbuf_put_cstring(b, typename)) != 0 ||
+	    (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)
+		return r;
+
+	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)
@@ -264,6 +288,7 @@ static const struct sshkey_impl_funcs sshkey_dss_funcs = {
 	/* .alloc = */		ssh_dss_alloc,
 	/* .cleanup = */	ssh_dss_cleanup,
 	/* .equal = */		ssh_dss_equal,
+	/* .ssh_serialize_public = */ ssh_dss_serialize_public,
 };
 
 const struct sshkey_impl sshkey_dss_impl = {
diff --git a/ssh-ecdsa-sk.c b/ssh-ecdsa-sk.c
index 77a57767..228e1b09 100644
--- a/ssh-ecdsa-sk.c
+++ b/ssh-ecdsa-sk.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: ssh-ecdsa-sk.c,v 1.10 2022/10/28 00:36:31 djm Exp $ */
+/* $OpenBSD: ssh-ecdsa-sk.c,v 1.11 2022/10/28 00:37:24 djm Exp $ */
 /*
  * Copyright (c) 2000 Markus Friedl.  All rights reserved.
  * Copyright (c) 2010 Damien Miller.  All rights reserved.
@@ -81,6 +81,21 @@ ssh_ecdsa_sk_equal(const struct sshkey *a, const struct sshkey *b)
 	return 1;
 }
 
+static int
+ssh_ecdsa_sk_serialize_public(const struct sshkey *key, struct sshbuf *b,
+    const char *typename, enum sshkey_serialize_rep opts)
+{
+	int r;
+
+	if ((r = sshkey_ecdsa_funcs.serialize_public(key, b,
+	    typename, opts)) != 0)
+		return r;
+	if ((r = sshkey_serialize_sk(key, b)) != 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.
@@ -346,6 +361,7 @@ static const struct sshkey_impl_funcs sshkey_ecdsa_sk_funcs = {
 	/* .alloc = */		NULL,
 	/* .cleanup = */	ssh_ecdsa_sk_cleanup,
 	/* .equal = */		ssh_ecdsa_sk_equal,
+	/* .ssh_serialize_public = */ ssh_ecdsa_sk_serialize_public,
 };
 
 const struct sshkey_impl sshkey_ecdsa_sk_impl = {
diff --git a/ssh-ecdsa.c b/ssh-ecdsa.c
index 85fa15c4..24f66bdc 100644
--- a/ssh-ecdsa.c
+++ b/ssh-ecdsa.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: ssh-ecdsa.c,v 1.18 2022/10/28 00:36:31 djm Exp $ */
+/* $OpenBSD: ssh-ecdsa.c,v 1.19 2022/10/28 00:37:24 djm Exp $ */
 /*
  * Copyright (c) 2000 Markus Friedl.  All rights reserved.
  * Copyright (c) 2010 Damien Miller.  All rights reserved.
@@ -87,9 +87,27 @@ ssh_ecdsa_equal(const struct sshkey *a, const struct sshkey *b)
 		return 0;
 	if (EC_POINT_cmp(grp_a, pub_a, pub_b, NULL) != 0)
 		return 0;
+
 	return 1;
 }
 
+static int
+ssh_ecdsa_serialize_public(const struct sshkey *key, struct sshbuf *b,
+    const char *typename, enum sshkey_serialize_rep opts)
+{
+	int r;
+
+	if (key->ecdsa == NULL)
+		return SSH_ERR_INVALID_ARGUMENT;
+	if ((r = sshbuf_put_cstring(b, typename)) != 0 ||
+	    (r = sshbuf_put_cstring(b,
+	    sshkey_curve_nid_to_name(key->ecdsa_nid))) != 0 ||
+	    (r = sshbuf_put_eckey(b, key->ecdsa)) != 0)
+		return r;
+
+	return 0;
+}
+
 /* ARGSUSED */
 int
 ssh_ecdsa_sign(const struct sshkey *key, u_char **sigp, size_t *lenp,
@@ -248,6 +266,7 @@ const struct sshkey_impl_funcs sshkey_ecdsa_funcs = {
 	/* .alloc = */		NULL,
 	/* .cleanup = */	ssh_ecdsa_cleanup,
 	/* .equal = */		ssh_ecdsa_equal,
+	/* .ssh_serialize_public = */ ssh_ecdsa_serialize_public,
 };
 
 const struct sshkey_impl sshkey_ecdsa_nistp256_impl = {
diff --git a/ssh-ed25519-sk.c b/ssh-ed25519-sk.c
index 4c0fc707..b95227c0 100644
--- a/ssh-ed25519-sk.c
+++ b/ssh-ed25519-sk.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: ssh-ed25519-sk.c,v 1.8 2022/10/28 00:36:31 djm Exp $ */
+/* $OpenBSD: ssh-ed25519-sk.c,v 1.9 2022/10/28 00:37:24 djm Exp $ */
 /*
  * Copyright (c) 2019 Markus Friedl.  All rights reserved.
  *
@@ -55,6 +55,21 @@ ssh_ed25519_sk_equal(const struct sshkey *a, const struct sshkey *b)
 	return 1;
 }
 
+static int
+ssh_ed25519_sk_serialize_public(const struct sshkey *key, struct sshbuf *b,
+    const char *typename, enum sshkey_serialize_rep opts)
+{
+	int r;
+
+	if ((r = sshkey_ed25519_funcs.serialize_public(key, b,
+	    typename, opts)) != 0)
+		return r;
+	if ((r = sshkey_serialize_sk(key, b)) != 0)
+		return r;
+
+	return 0;
+}
+
 int
 ssh_ed25519_sk_verify(const struct sshkey *key,
     const u_char *signature, size_t signaturelen,
@@ -187,6 +202,7 @@ static const struct sshkey_impl_funcs sshkey_ed25519_sk_funcs = {
 	/* .alloc = */		NULL,
 	/* .cleanup = */	ssh_ed25519_sk_cleanup,
 	/* .equal = */		ssh_ed25519_sk_equal,
+	/* .ssh_serialize_public = */ ssh_ed25519_sk_serialize_public,
 };
 
 const struct sshkey_impl sshkey_ed25519_sk_impl = {
diff --git a/ssh-ed25519.c b/ssh-ed25519.c
index 712cc402..72c85000 100644
--- a/ssh-ed25519.c
+++ b/ssh-ed25519.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: ssh-ed25519.c,v 1.12 2022/10/28 00:36:31 djm Exp $ */
+/* $OpenBSD: ssh-ed25519.c,v 1.13 2022/10/28 00:37:24 djm Exp $ */
 /*
  * Copyright (c) 2013 Markus Friedl <markus at openbsd.org>
  *
@@ -51,6 +51,21 @@ ssh_ed25519_equal(const struct sshkey *a, const struct sshkey *b)
 	return 1;
 }
 
+static int
+ssh_ed25519_serialize_public(const struct sshkey *key, struct sshbuf *b,
+    const char *typename, enum sshkey_serialize_rep opts)
+{
+	int r;
+
+	if (key->ed25519_pk == NULL)
+		return SSH_ERR_INVALID_ARGUMENT;
+	if ((r = sshbuf_put_cstring(b, typename)) != 0 ||
+	    (r = sshbuf_put_string(b, key->ed25519_pk, ED25519_PK_SZ)) != 0)
+		return r;
+
+	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)
@@ -184,6 +199,7 @@ const struct sshkey_impl_funcs sshkey_ed25519_funcs = {
 	/* .alloc = */		NULL,
 	/* .cleanup = */	ssh_ed25519_cleanup,
 	/* .equal = */		ssh_ed25519_equal,
+	/* .ssh_serialize_public = */ ssh_ed25519_serialize_public,
 };
 
 const struct sshkey_impl sshkey_ed25519_impl = {
diff --git a/ssh-rsa.c b/ssh-rsa.c
index 345d9a8d..4ece09f7 100644
--- a/ssh-rsa.c
+++ b/ssh-rsa.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: ssh-rsa.c,v 1.70 2022/10/28 00:36:31 djm Exp $ */
+/* $OpenBSD: ssh-rsa.c,v 1.71 2022/10/28 00:37:24 djm Exp $ */
 /*
  * Copyright (c) 2000, 2003 Markus Friedl <markus at openbsd.org>
  *
@@ -86,6 +86,24 @@ ssh_rsa_equal(const struct sshkey *a, const struct sshkey *b)
 	return 1;
 }
 
+static int
+ssh_rsa_serialize_public(const struct sshkey *key, struct sshbuf *b,
+    const char *typename, enum sshkey_serialize_rep opts)
+{
+	int r;
+	const BIGNUM *rsa_n, *rsa_e;
+
+	if (key->rsa == NULL)
+		return SSH_ERR_INVALID_ARGUMENT;
+	RSA_get0_key(key->rsa, &rsa_n, &rsa_e, NULL);
+	if ((r = sshbuf_put_cstring(b, typename)) != 0 ||
+	    (r = sshbuf_put_bignum2(b, rsa_e)) != 0 ||
+	    (r = sshbuf_put_bignum2(b, rsa_n)) != 0)
+		return r;
+
+	return 0;
+}
+
 static const char *
 rsa_hash_alg_ident(int hash_alg)
 {
@@ -499,6 +517,7 @@ static const struct sshkey_impl_funcs sshkey_rsa_funcs = {
 	/* .alloc = */		ssh_rsa_alloc,
 	/* .cleanup = */	ssh_rsa_cleanup,
 	/* .equal = */		ssh_rsa_equal,
+	/* .ssh_serialize_public = */ ssh_rsa_serialize_public,
 };
 
 const struct sshkey_impl sshkey_rsa_impl = {
diff --git a/ssh-xmss.c b/ssh-xmss.c
index 2bc31979..7031baf9 100644
--- a/ssh-xmss.c
+++ b/ssh-xmss.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: ssh-xmss.c,v 1.7 2022/10/28 00:36:31 djm Exp $*/
+/* $OpenBSD: ssh-xmss.c,v 1.8 2022/10/28 00:37:24 djm Exp $*/
 /*
  * Copyright (c) 2017 Stefan-Lukas Gazdag.
  * Copyright (c) 2017 Markus Friedl.
@@ -63,6 +63,25 @@ ssh_xmss_equal(const struct sshkey *a, const struct sshkey *b)
 	return 1;
 }
 
+static int
+ssh_xmss_serialize_public(const struct sshkey *key, struct sshbuf *b,
+    const char *typename, enum sshkey_serialize_rep opts)
+{
+	int r;
+
+	if (key->xmss_name == NULL || key->xmss_pk == NULL ||
+	    sshkey_xmss_pklen(key) == 0)
+		return SSH_ERR_INVALID_ARGUMENT;
+	if ((r = sshbuf_put_cstring(b, typename)) != 0 ||
+	    (r = sshbuf_put_cstring(b, key->xmss_name)) != 0 ||
+	    (r = sshbuf_put_string(b, key->xmss_pk,
+	    sshkey_xmss_pklen(key))) != 0 ||
+	    (r = sshkey_xmss_serialize_pk_info(key, b, opts)) != 0)
+		return r;
+
+	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)
@@ -216,6 +235,7 @@ static const struct sshkey_impl_funcs sshkey_xmss_funcs = {
 	/* .alloc = */		NULL,
 	/* .cleanup = */	ssh_xmss_cleanup,
 	/* .equal = */		ssh_xmss_equal,
+	/* .ssh_serialize_public = */ ssh_xmss_serialize_public,
 };
 
 const struct sshkey_impl sshkey_xmss_impl = {
diff --git a/sshkey.c b/sshkey.c
index 76bab4f9..b4130f2a 100644
--- a/sshkey.c
+++ b/sshkey.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: sshkey.c,v 1.124 2022/10/28 00:36:31 djm Exp $ */
+/* $OpenBSD: sshkey.c,v 1.125 2022/10/28 00:37:24 djm Exp $ */
 /*
  * Copyright (c) 2000, 2001 Markus Friedl.  All rights reserved.
  * Copyright (c) 2008 Alexander von Gernler.  All rights reserved.
@@ -679,116 +679,47 @@ sshkey_equal(const struct sshkey *a, const struct sshkey *b)
 	return sshkey_equal_public(a, b);
 }
 
+
+/* Serialise common FIDO key parts */
+int
+sshkey_serialize_sk(const struct sshkey *key, struct sshbuf *b)
+{
+	int r;
+
+	if ((r = sshbuf_put_cstring(b, key->sk_application)) != 0)
+		return r;
+
+	return 0;
+}
+
 static int
 to_blob_buf(const struct sshkey *key, struct sshbuf *b, int force_plain,
   enum sshkey_serialize_rep opts)
 {
 	int type, ret = SSH_ERR_INTERNAL_ERROR;
 	const char *typename;
-#ifdef WITH_OPENSSL
-	const BIGNUM *rsa_n, *rsa_e, *dsa_p, *dsa_q, *dsa_g, *dsa_pub_key;
-#endif /* WITH_OPENSSL */
+	const struct sshkey_impl *impl;
 
 	if (key == NULL)
 		return SSH_ERR_INVALID_ARGUMENT;
 
-	if (sshkey_is_cert(key)) {
+	type = force_plain ? sshkey_type_plain(key->type) : key->type;
+
+	if (sshkey_type_is_cert(type)) {
 		if (key->cert == NULL)
 			return SSH_ERR_EXPECTED_CERT;
 		if (sshbuf_len(key->cert->certblob) == 0)
 			return SSH_ERR_KEY_LACKS_CERTBLOB;
-	}
-	type = force_plain ? sshkey_type_plain(key->type) : key->type;
-	typename = sshkey_ssh_name_from_type_nid(type, key->ecdsa_nid);
-
-	switch (type) {
-#ifdef WITH_OPENSSL
-	case KEY_DSA_CERT:
-	case KEY_ECDSA_CERT:
-	case KEY_ECDSA_SK_CERT:
-	case KEY_RSA_CERT:
-#endif /* WITH_OPENSSL */
-	case KEY_ED25519_CERT:
-	case KEY_ED25519_SK_CERT:
-#ifdef WITH_XMSS
-	case KEY_XMSS_CERT:
-#endif /* WITH_XMSS */
 		/* Use the existing blob */
-		/* XXX modified flag? */
 		if ((ret = sshbuf_putb(b, key->cert->certblob)) != 0)
 			return ret;
-		break;
-#ifdef WITH_OPENSSL
-	case KEY_DSA:
-		if (key->dsa == NULL)
-			return SSH_ERR_INVALID_ARGUMENT;
-		DSA_get0_pqg(key->dsa, &dsa_p, &dsa_q, &dsa_g);
-		DSA_get0_key(key->dsa, &dsa_pub_key, NULL);
-		if ((ret = sshbuf_put_cstring(b, typename)) != 0 ||
-		    (ret = sshbuf_put_bignum2(b, dsa_p)) != 0 ||
-		    (ret = sshbuf_put_bignum2(b, dsa_q)) != 0 ||
-		    (ret = sshbuf_put_bignum2(b, dsa_g)) != 0 ||
-		    (ret = sshbuf_put_bignum2(b, dsa_pub_key)) != 0)
-			return ret;
-		break;
-# ifdef OPENSSL_HAS_ECC
-	case KEY_ECDSA:
-	case KEY_ECDSA_SK:
-		if (key->ecdsa == NULL)
-			return SSH_ERR_INVALID_ARGUMENT;
-		if ((ret = sshbuf_put_cstring(b, typename)) != 0 ||
-		    (ret = sshbuf_put_cstring(b,
-		    sshkey_curve_nid_to_name(key->ecdsa_nid))) != 0 ||
-		    (ret = sshbuf_put_eckey(b, key->ecdsa)) != 0)
-			return ret;
-		if (type == KEY_ECDSA_SK) {
-			if ((ret = sshbuf_put_cstring(b,
-			    key->sk_application)) != 0)
-				return ret;
-		}
-		break;
-# endif
-	case KEY_RSA:
-		if (key->rsa == NULL)
-			return SSH_ERR_INVALID_ARGUMENT;
-		RSA_get0_key(key->rsa, &rsa_n, &rsa_e, NULL);
-		if ((ret = sshbuf_put_cstring(b, typename)) != 0 ||
-		    (ret = sshbuf_put_bignum2(b, rsa_e)) != 0 ||
-		    (ret = sshbuf_put_bignum2(b, rsa_n)) != 0)
-			return ret;
-		break;
-#endif /* WITH_OPENSSL */
-	case KEY_ED25519:
-	case KEY_ED25519_SK:
-		if (key->ed25519_pk == NULL)
-			return SSH_ERR_INVALID_ARGUMENT;
-		if ((ret = sshbuf_put_cstring(b, typename)) != 0 ||
-		    (ret = sshbuf_put_string(b,
-		    key->ed25519_pk, ED25519_PK_SZ)) != 0)
-			return ret;
-		if (type == KEY_ED25519_SK) {
-			if ((ret = sshbuf_put_cstring(b,
-			    key->sk_application)) != 0)
-				return ret;
-		}
-		break;
-#ifdef WITH_XMSS
-	case KEY_XMSS:
-		if (key->xmss_name == NULL || key->xmss_pk == NULL ||
-		    sshkey_xmss_pklen(key) == 0)
-			return SSH_ERR_INVALID_ARGUMENT;
-		if ((ret = sshbuf_put_cstring(b, typename)) != 0 ||
-		    (ret = sshbuf_put_cstring(b, key->xmss_name)) != 0 ||
-		    (ret = sshbuf_put_string(b,
-		    key->xmss_pk, sshkey_xmss_pklen(key))) != 0 ||
-		    (ret = sshkey_xmss_serialize_pk_info(key, b, opts)) != 0)
-			return ret;
-		break;
-#endif /* WITH_XMSS */
-	default:
-		return SSH_ERR_KEY_TYPE_UNKNOWN;
+		return 0;
 	}
-	return 0;
+	if ((impl = sshkey_impl_from_type(type)) == NULL)
+		return SSH_ERR_KEY_TYPE_UNKNOWN;
+
+	typename = sshkey_ssh_name_from_type_nid(type, key->ecdsa_nid);
+	return impl->funcs->serialize_public(key, b, typename, opts);
 }
 
 int
diff --git a/sshkey.h b/sshkey.h
index b94e332e..03d82aed 100644
--- a/sshkey.h
+++ b/sshkey.h
@@ -1,4 +1,4 @@
-/* $OpenBSD: sshkey.h,v 1.54 2022/10/28 00:36:31 djm Exp $ */
+/* $OpenBSD: sshkey.h,v 1.55 2022/10/28 00:37:24 djm Exp $ */
 
 /*
  * Copyright (c) 2000, 2001 Markus Friedl.  All rights reserved.
@@ -169,6 +169,8 @@ struct sshkey_impl_funcs {
 	int (*alloc)(struct sshkey *);		/* optional */
 	void (*cleanup)(struct sshkey *);	/* optional */
 	int (*equal)(const struct sshkey *, const struct sshkey *);
+	int (*serialize_public)(const struct sshkey *, struct sshbuf *,
+	    const char *, enum sshkey_serialize_rep);
 };
 
 struct sshkey_impl {
@@ -309,6 +311,7 @@ void	 sshkey_sig_details_free(struct sshkey_sig_details *);
 #ifdef SSHKEY_INTERNAL
 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 ssh_rsa_sign(const struct sshkey *key,
     u_char **sigp, size_t *lenp, const u_char *data, size_t datalen,

-- 
To stop receiving notification emails like this one, please contact
djm at mindrot.org.


More information about the openssh-commits mailing list