]> git.ipfire.org Git - thirdparty/openssh-portable.git/commitdiff
upstream: factor out sshkey_equal_public()
authordjm@openbsd.org <djm@openbsd.org>
Fri, 28 Oct 2022 00:36:31 +0000 (00:36 +0000)
committerDamien Miller <djm@mindrot.org>
Fri, 28 Oct 2022 01:46:56 +0000 (12:46 +1100)
feedback/ok markus@

OpenBSD-Commit-ID: 1368ba114cb37732fe6ec3d89c7e6d27ea6fdc94

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

index 2206bbe6a951e435271e140a0b35563870e0b615..15d6cea39b05da8cb61fba52f181aad8f95c021b 100644 (file)
--- a/ssh-dss.c
+++ b/ssh-dss.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: ssh-dss.c,v 1.40 2022/10/28 00:35:40 djm Exp $ */
+/* $OpenBSD: ssh-dss.c,v 1.41 2022/10/28 00:36:31 djm Exp $ */
 /*
  * Copyright (c) 2000 Markus Friedl.  All rights reserved.
  *
@@ -74,6 +74,34 @@ ssh_dss_cleanup(struct sshkey *k)
        k->dsa = NULL;
 }
 
+static int
+ssh_dss_equal(const struct sshkey *a, const struct sshkey *b)
+{
+       const BIGNUM *dsa_p_a, *dsa_q_a, *dsa_g_a, *dsa_pub_key_a;
+       const BIGNUM *dsa_p_b, *dsa_q_b, *dsa_g_b, *dsa_pub_key_b;
+
+       if (a->dsa == NULL || b->dsa == NULL)
+               return 0;
+       DSA_get0_pqg(a->dsa, &dsa_p_a, &dsa_q_a, &dsa_g_a);
+       DSA_get0_pqg(b->dsa, &dsa_p_b, &dsa_q_b, &dsa_g_b);
+       DSA_get0_key(a->dsa, &dsa_pub_key_a, NULL);
+       DSA_get0_key(b->dsa, &dsa_pub_key_b, NULL);
+       if (dsa_p_a == NULL || dsa_p_b == NULL ||
+           dsa_q_a == NULL || dsa_q_b == NULL ||
+           dsa_g_a == NULL || dsa_g_b == NULL ||
+           dsa_pub_key_a == NULL || dsa_pub_key_b == NULL)
+               return 0;
+       if (BN_cmp(dsa_p_a, dsa_p_b) != 0)
+               return 0;
+       if (BN_cmp(dsa_q_a, dsa_q_b) != 0)
+               return 0;
+       if (BN_cmp(dsa_g_a, dsa_g_b) != 0)
+               return 0;
+       if (BN_cmp(dsa_pub_key_a, dsa_pub_key_b) != 0)
+               return 0;
+       return 1;
+}
+
 int
 ssh_dss_sign(const struct sshkey *key, u_char **sigp, size_t *lenp,
     const u_char *data, size_t datalen, u_int compat)
@@ -235,6 +263,7 @@ static const struct sshkey_impl_funcs sshkey_dss_funcs = {
        /* .size = */           ssh_dss_size,
        /* .alloc = */          ssh_dss_alloc,
        /* .cleanup = */        ssh_dss_cleanup,
+       /* .equal = */          ssh_dss_equal,
 };
 
 const struct sshkey_impl sshkey_dss_impl = {
index 2f0984f42cb3c2f214f75b5819d58e1c6cd54c55..77a577671897c3d60aa08cdfc55cf6e230bc8148 100644 (file)
@@ -1,4 +1,4 @@
-/* $OpenBSD: ssh-ecdsa-sk.c,v 1.9 2022/10/28 00:35:40 djm Exp $ */
+/* $OpenBSD: ssh-ecdsa-sk.c,v 1.10 2022/10/28 00:36:31 djm Exp $ */
 /*
  * Copyright (c) 2000 Markus Friedl.  All rights reserved.
  * Copyright (c) 2010 Damien Miller.  All rights reserved.
@@ -61,14 +61,24 @@ ssh_ecdsa_sk_verify(const struct sshkey *key,
 }
 #else /* OPENSSL_HAS_ECC */
 
+/* Reuse some ECDSA internals */
+extern struct sshkey_impl_funcs sshkey_ecdsa_funcs;
+
 static void
 ssh_ecdsa_sk_cleanup(struct sshkey *k)
 {
-       free(k->sk_application);
-       sshbuf_free(k->sk_key_handle);
-       sshbuf_free(k->sk_reserved);
-       EC_KEY_free(k->ecdsa);
-       k->ecdsa = NULL;
+       sshkey_sk_cleanup(k);
+       sshkey_ecdsa_funcs.cleanup(k);
+}
+
+static int
+ssh_ecdsa_sk_equal(const struct sshkey *a, const struct sshkey *b)
+{
+       if (!sshkey_sk_fields_equal(a, b))
+               return 0;
+       if (!sshkey_ecdsa_funcs.equal(a, b))
+               return 0;
+       return 1;
 }
 
 /*
@@ -335,6 +345,7 @@ static const struct sshkey_impl_funcs sshkey_ecdsa_sk_funcs = {
        /* .size = */           NULL,
        /* .alloc = */          NULL,
        /* .cleanup = */        ssh_ecdsa_sk_cleanup,
+       /* .equal = */          ssh_ecdsa_sk_equal,
 };
 
 const struct sshkey_impl sshkey_ecdsa_sk_impl = {
index e207e43fd0961ef2a301e6296dfd2bdfc2b750c8..85fa15c4990462b96f3d2e2a1297ac5233e6cad0 100644 (file)
@@ -1,4 +1,4 @@
-/* $OpenBSD: ssh-ecdsa.c,v 1.17 2022/10/28 00:35:40 djm Exp $ */
+/* $OpenBSD: ssh-ecdsa.c,v 1.18 2022/10/28 00:36:31 djm Exp $ */
 /*
  * Copyright (c) 2000 Markus Friedl.  All rights reserved.
  * Copyright (c) 2010 Damien Miller.  All rights reserved.
@@ -69,6 +69,27 @@ ssh_ecdsa_cleanup(struct sshkey *k)
        k->ecdsa = NULL;
 }
 
+static int
+ssh_ecdsa_equal(const struct sshkey *a, const struct sshkey *b)
+{
+       const EC_GROUP *grp_a, *grp_b;
+       const EC_POINT *pub_a, *pub_b;
+
+       if (a->ecdsa == NULL || b->ecdsa == NULL)
+               return 0;
+       if ((grp_a = EC_KEY_get0_group(a->ecdsa)) == NULL ||
+           (grp_b = EC_KEY_get0_group(b->ecdsa)) == NULL)
+               return 0;
+       if ((pub_a = EC_KEY_get0_public_key(a->ecdsa)) == NULL ||
+           (pub_b = EC_KEY_get0_public_key(b->ecdsa)) == NULL)
+               return 0;
+       if (EC_GROUP_cmp(grp_a, grp_b, NULL) != 0)
+               return 0;
+       if (EC_POINT_cmp(grp_a, pub_a, pub_b, NULL) != 0)
+               return 0;
+       return 1;
+}
+
 /* ARGSUSED */
 int
 ssh_ecdsa_sign(const struct sshkey *key, u_char **sigp, size_t *lenp,
@@ -221,10 +242,12 @@ ssh_ecdsa_verify(const struct sshkey *key,
        return ret;
 }
 
-static const struct sshkey_impl_funcs sshkey_ecdsa_funcs = {
+/* NB. not static; used by ECDSA-SK */
+const struct sshkey_impl_funcs sshkey_ecdsa_funcs = {
        /* .size = */           ssh_ecdsa_size,
        /* .alloc = */          NULL,
        /* .cleanup = */        ssh_ecdsa_cleanup,
+       /* .equal = */          ssh_ecdsa_equal,
 };
 
 const struct sshkey_impl sshkey_ecdsa_nistp256_impl = {
index 1c21d4bf50020190673e7dc015efd8178fb2e21a..4c0fc7075285c07af7953e596d9053fb147af30c 100644 (file)
@@ -1,4 +1,4 @@
-/* $OpenBSD: ssh-ed25519-sk.c,v 1.7 2022/10/28 00:35:40 djm Exp $ */
+/* $OpenBSD: ssh-ed25519-sk.c,v 1.8 2022/10/28 00:36:31 djm Exp $ */
 /*
  * Copyright (c) 2019 Markus Friedl.  All rights reserved.
  *
 #include "ssh.h"
 #include "digest.h"
 
+/* Reuse some ED25519 internals */
+extern struct sshkey_impl_funcs sshkey_ed25519_funcs;
+
 static void
 ssh_ed25519_sk_cleanup(struct sshkey *k)
 {
-       free(k->sk_application);
-       sshbuf_free(k->sk_key_handle);
-       sshbuf_free(k->sk_reserved);
-       freezero(k->ed25519_pk, ED25519_PK_SZ);
-       freezero(k->ed25519_sk, ED25519_SK_SZ);
-       k->ed25519_pk = NULL;
-       k->ed25519_sk = NULL;
+       sshkey_sk_cleanup(k);
+       sshkey_ed25519_funcs.cleanup(k);
+}
+
+static int
+ssh_ed25519_sk_equal(const struct sshkey *a, const struct sshkey *b)
+{
+       if (!sshkey_sk_fields_equal(a, b))
+               return 0;
+       if (!sshkey_ed25519_funcs.equal(a, b))
+               return 0;
+       return 1;
 }
 
 int
@@ -178,6 +186,7 @@ static const struct sshkey_impl_funcs sshkey_ed25519_sk_funcs = {
        /* .size = */           NULL,
        /* .alloc = */          NULL,
        /* .cleanup = */        ssh_ed25519_sk_cleanup,
+       /* .equal = */          ssh_ed25519_sk_equal,
 };
 
 const struct sshkey_impl sshkey_ed25519_sk_impl = {
index abd983df9e588ba3ce96980d6463bd3e984c42ab..712cc4022b89c9dcf8a1bbb137d2655ab4c05969 100644 (file)
@@ -1,4 +1,4 @@
-/* $OpenBSD: ssh-ed25519.c,v 1.11 2022/10/28 00:35:40 djm Exp $ */
+/* $OpenBSD: ssh-ed25519.c,v 1.12 2022/10/28 00:36:31 djm Exp $ */
 /*
  * Copyright (c) 2013 Markus Friedl <markus@openbsd.org>
  *
@@ -41,6 +41,16 @@ ssh_ed25519_cleanup(struct sshkey *k)
        k->ed25519_sk = NULL;
 }
 
+static int
+ssh_ed25519_equal(const struct sshkey *a, const struct sshkey *b)
+{
+       if (a->ed25519_pk == NULL || b->ed25519_pk == NULL)
+               return 0;
+       if (memcmp(a->ed25519_pk, b->ed25519_pk, ED25519_PK_SZ) != 0)
+               return 0;
+       return 1;
+}
+
 int
 ssh_ed25519_sign(const struct sshkey *key, u_char **sigp, size_t *lenp,
     const u_char *data, size_t datalen, u_int compat)
@@ -168,10 +178,12 @@ ssh_ed25519_verify(const struct sshkey *key,
        return r;
 }
 
-static const struct sshkey_impl_funcs sshkey_ed25519_funcs = {
+/* NB. not static; used by ED25519-SK */
+const struct sshkey_impl_funcs sshkey_ed25519_funcs = {
        /* .size = */           NULL,
        /* .alloc = */          NULL,
        /* .cleanup = */        ssh_ed25519_cleanup,
+       /* .equal = */          ssh_ed25519_equal,
 };
 
 const struct sshkey_impl sshkey_ed25519_impl = {
index e7225e825207d46cff819df748545bc35099fecb..345d9a8d018ddbe5a73185e77c88ad802a63c481 100644 (file)
--- a/ssh-rsa.c
+++ b/ssh-rsa.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: ssh-rsa.c,v 1.69 2022/10/28 00:35:40 djm Exp $ */
+/* $OpenBSD: ssh-rsa.c,v 1.70 2022/10/28 00:36:31 djm Exp $ */
 /*
  * Copyright (c) 2000, 2003 Markus Friedl <markus@openbsd.org>
  *
@@ -65,6 +65,27 @@ ssh_rsa_cleanup(struct sshkey *k)
        k->rsa = NULL;
 }
 
+static int
+ssh_rsa_equal(const struct sshkey *a, const struct sshkey *b)
+{
+       const BIGNUM *rsa_e_a, *rsa_n_a;
+       const BIGNUM *rsa_e_b, *rsa_n_b;
+
+       if (a->rsa == NULL || b->rsa == NULL)
+               return 0;
+       RSA_get0_key(a->rsa, &rsa_n_a, &rsa_e_a, NULL);
+       RSA_get0_key(b->rsa, &rsa_n_b, &rsa_e_b, NULL);
+       if (rsa_e_a == NULL || rsa_e_b == NULL)
+               return 0;
+       if (rsa_n_a == NULL || rsa_n_b == NULL)
+               return 0;
+       if (BN_cmp(rsa_e_a, rsa_e_b) != 0)
+               return 0;
+       if (BN_cmp(rsa_n_a, rsa_n_b) != 0)
+               return 0;
+       return 1;
+}
+
 static const char *
 rsa_hash_alg_ident(int hash_alg)
 {
@@ -477,6 +498,7 @@ static const struct sshkey_impl_funcs sshkey_rsa_funcs = {
        /* .size = */           ssh_rsa_size,
        /* .alloc = */          ssh_rsa_alloc,
        /* .cleanup = */        ssh_rsa_cleanup,
+       /* .equal = */          ssh_rsa_equal,
 };
 
 const struct sshkey_impl sshkey_rsa_impl = {
index 2ac9ee05e1bb324bd51dc35526ef18aa93b17cff..2bc319797820b8c732318f777da342ae1426fdff 100644 (file)
@@ -1,4 +1,4 @@
-/* $OpenBSD: ssh-xmss.c,v 1.6 2022/10/28 00:35:40 djm Exp $*/
+/* $OpenBSD: ssh-xmss.c,v 1.7 2022/10/28 00:36:31 djm Exp $*/
 /*
  * Copyright (c) 2017 Stefan-Lukas Gazdag.
  * Copyright (c) 2017 Markus Friedl.
@@ -51,6 +51,18 @@ ssh_xmss_cleanup(struct sshkey *k)
        k->xmss_filename = NULL;
 }
 
+static int
+ssh_xmss_equal(const struct sshkey *a, const struct sshkey *b)
+{
+       if (a->xmss_pk == NULL || b->xmss_pk == NULL)
+               return 0;
+       if (sshkey_xmss_pklen(a) != sshkey_xmss_pklen(b))
+               return 0;
+       if (memcmp(a->xmss_pk, b->xmss_pk, sshkey_xmss_pklen(a)) != 0)
+               return 0;
+       return 1;
+}
+
 int
 ssh_xmss_sign(const struct sshkey *key, u_char **sigp, size_t *lenp,
     const u_char *data, size_t datalen, u_int compat)
@@ -203,6 +215,7 @@ static const struct sshkey_impl_funcs sshkey_xmss_funcs = {
        /* .size = */           NULL,
        /* .alloc = */          NULL,
        /* .cleanup = */        ssh_xmss_cleanup,
+       /* .equal = */          ssh_xmss_equal,
 };
 
 const struct sshkey_impl sshkey_xmss_impl = {
index 1052108b5fdc1140e30c4102574b9456f4706ceb..76bab4f996f0200737fe77e98db14ee780ed99a4 100644 (file)
--- a/sshkey.c
+++ b/sshkey.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: sshkey.c,v 1.123 2022/10/28 00:35:40 djm Exp $ */
+/* $OpenBSD: sshkey.c,v 1.124 2022/10/28 00:36:31 djm Exp $ */
 /*
  * Copyright (c) 2000, 2001 Markus Friedl.  All rights reserved.
  * Copyright (c) 2008 Alexander von Gernler.  All rights reserved.
@@ -596,6 +596,17 @@ sshkey_new(int type)
        return k;
 }
 
+/* Frees common FIDO fields */
+void
+sshkey_sk_cleanup(struct sshkey *k)
+{
+       free(k->sk_application);
+       sshbuf_free(k->sk_key_handle);
+       sshbuf_free(k->sk_reserved);
+       k->sk_application = NULL;
+       k->sk_key_handle = k->sk_reserved = NULL;
+}
+
 void
 sshkey_free(struct sshkey *k)
 {
@@ -628,6 +639,17 @@ cert_compare(struct sshkey_cert *a, struct sshkey_cert *b)
        return 1;
 }
 
+/* Compares FIDO-specific pubkey fields only */
+int
+sshkey_sk_fields_equal(const struct sshkey *a, const struct sshkey *b)
+{
+       if (a->sk_application == NULL || b->sk_application == NULL)
+               return 0;
+       if (strcmp(a->sk_application, b->sk_application) != 0)
+               return 0;
+       return 1;
+}
+
 /*
  * Compare public portions of key only, allowing comparisons between
  * certificates and plain keys too.
@@ -635,84 +657,14 @@ cert_compare(struct sshkey_cert *a, struct sshkey_cert *b)
 int
 sshkey_equal_public(const struct sshkey *a, const struct sshkey *b)
 {
-#if defined(WITH_OPENSSL)
-       const BIGNUM *rsa_e_a, *rsa_n_a;
-       const BIGNUM *rsa_e_b, *rsa_n_b;
-       const BIGNUM *dsa_p_a, *dsa_q_a, *dsa_g_a, *dsa_pub_key_a;
-       const BIGNUM *dsa_p_b, *dsa_q_b, *dsa_g_b, *dsa_pub_key_b;
-#endif /* WITH_OPENSSL */
+       const struct sshkey_impl *impl;
 
        if (a == NULL || b == NULL ||
            sshkey_type_plain(a->type) != sshkey_type_plain(b->type))
                return 0;
-
-       switch (a->type) {
-#ifdef WITH_OPENSSL
-       case KEY_RSA_CERT:
-       case KEY_RSA:
-               if (a->rsa == NULL || b->rsa == NULL)
-                       return 0;
-               RSA_get0_key(a->rsa, &rsa_n_a, &rsa_e_a, NULL);
-               RSA_get0_key(b->rsa, &rsa_n_b, &rsa_e_b, NULL);
-               return BN_cmp(rsa_e_a, rsa_e_b) == 0 &&
-                   BN_cmp(rsa_n_a, rsa_n_b) == 0;
-       case KEY_DSA_CERT:
-       case KEY_DSA:
-               if (a->dsa == NULL || b->dsa == NULL)
-                       return 0;
-               DSA_get0_pqg(a->dsa, &dsa_p_a, &dsa_q_a, &dsa_g_a);
-               DSA_get0_pqg(b->dsa, &dsa_p_b, &dsa_q_b, &dsa_g_b);
-               DSA_get0_key(a->dsa, &dsa_pub_key_a, NULL);
-               DSA_get0_key(b->dsa, &dsa_pub_key_b, NULL);
-               return BN_cmp(dsa_p_a, dsa_p_b) == 0 &&
-                   BN_cmp(dsa_q_a, dsa_q_b) == 0 &&
-                   BN_cmp(dsa_g_a, dsa_g_b) == 0 &&
-                   BN_cmp(dsa_pub_key_a, dsa_pub_key_b) == 0;
-# ifdef OPENSSL_HAS_ECC
-       case KEY_ECDSA_SK:
-       case KEY_ECDSA_SK_CERT:
-               if (a->sk_application == NULL || b->sk_application == NULL)
-                       return 0;
-               if (strcmp(a->sk_application, b->sk_application) != 0)
-                       return 0;
-               /* FALLTHROUGH */
-       case KEY_ECDSA_CERT:
-       case KEY_ECDSA:
-               if (a->ecdsa == NULL || b->ecdsa == NULL ||
-                   EC_KEY_get0_public_key(a->ecdsa) == NULL ||
-                   EC_KEY_get0_public_key(b->ecdsa) == NULL)
-                       return 0;
-               if (EC_GROUP_cmp(EC_KEY_get0_group(a->ecdsa),
-                   EC_KEY_get0_group(b->ecdsa), NULL) != 0 ||
-                   EC_POINT_cmp(EC_KEY_get0_group(a->ecdsa),
-                   EC_KEY_get0_public_key(a->ecdsa),
-                   EC_KEY_get0_public_key(b->ecdsa), NULL) != 0)
-                       return 0;
-               return 1;
-# endif /* OPENSSL_HAS_ECC */
-#endif /* WITH_OPENSSL */
-       case KEY_ED25519_SK:
-       case KEY_ED25519_SK_CERT:
-               if (a->sk_application == NULL || b->sk_application == NULL)
-                       return 0;
-               if (strcmp(a->sk_application, b->sk_application) != 0)
-                       return 0;
-               /* FALLTHROUGH */
-       case KEY_ED25519:
-       case KEY_ED25519_CERT:
-               return a->ed25519_pk != NULL && b->ed25519_pk != NULL &&
-                   memcmp(a->ed25519_pk, b->ed25519_pk, ED25519_PK_SZ) == 0;
-#ifdef WITH_XMSS
-       case KEY_XMSS:
-       case KEY_XMSS_CERT:
-               return a->xmss_pk != NULL && b->xmss_pk != NULL &&
-                   sshkey_xmss_pklen(a) == sshkey_xmss_pklen(b) &&
-                   memcmp(a->xmss_pk, b->xmss_pk, sshkey_xmss_pklen(a)) == 0;
-#endif /* WITH_XMSS */
-       default:
+       if ((impl = sshkey_impl_from_type(a->type)) == NULL)
                return 0;
-       }
-       /* NOTREACHED */
+       return impl->funcs->equal(a, b);
 }
 
 int
index 3ec0e87bcb2868460c3556d83311e27dac0e7cf6..b94e332e475d97b8d0a955e4476bb858b3f93395 100644 (file)
--- a/sshkey.h
+++ b/sshkey.h
@@ -1,4 +1,4 @@
-/* $OpenBSD: sshkey.h,v 1.53 2022/10/28 00:35:40 djm Exp $ */
+/* $OpenBSD: sshkey.h,v 1.54 2022/10/28 00:36:31 djm Exp $ */
 
 /*
  * Copyright (c) 2000, 2001 Markus Friedl.  All rights reserved.
@@ -168,6 +168,7 @@ struct sshkey_impl_funcs {
        u_int (*size)(const struct sshkey *);   /* optional */
        int (*alloc)(struct sshkey *);          /* optional */
        void (*cleanup)(struct sshkey *);       /* optional */
+       int (*equal)(const struct sshkey *, const struct sshkey *);
 };
 
 struct sshkey_impl {
@@ -306,6 +307,9 @@ int  sshkey_private_serialize_maxsign(struct sshkey *key,
 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 ssh_rsa_sign(const struct sshkey *key,
     u_char **sigp, size_t *lenp, const u_char *data, size_t datalen,
     const char *ident);