summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--ssh-dss.c58
-rw-r--r--ssh-ecdsa-sk.c54
-rw-r--r--ssh-ecdsa.c106
-rw-r--r--ssh-ed25519-sk.c44
-rw-r--r--ssh-ed25519.c41
-rw-r--r--ssh-rsa.c108
-rw-r--r--ssh-xmss.c46
-rw-r--r--sshkey.c435
-rw-r--r--sshkey.h20
9 files changed, 640 insertions, 272 deletions
diff --git a/ssh-dss.c b/ssh-dss.c
index fddc29cc..2206bbe6 100644
--- a/ssh-dss.c
+++ b/ssh-dss.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: ssh-dss.c,v 1.39 2020/02/26 13:40:09 jsg Exp $ */
+/* $OpenBSD: ssh-dss.c,v 1.40 2022/10/28 00:35:40 djm Exp $ */
/*
* Copyright (c) 2000 Markus Friedl. All rights reserved.
*
@@ -48,6 +48,32 @@
#define INTBLOB_LEN 20
#define SIGBLOB_LEN (2*INTBLOB_LEN)
+static u_int
+ssh_dss_size(const struct sshkey *key)
+{
+ const BIGNUM *dsa_p;
+
+ if (key->dsa == NULL)
+ return 0;
+ DSA_get0_pqg(key->dsa, &dsa_p, NULL, NULL);
+ return BN_num_bits(dsa_p);
+}
+
+static int
+ssh_dss_alloc(struct sshkey *k)
+{
+ if ((k->dsa = DSA_new()) == NULL)
+ return SSH_ERR_ALLOC_FAIL;
+ return 0;
+}
+
+static void
+ssh_dss_cleanup(struct sshkey *k)
+{
+ DSA_free(k->dsa);
+ k->dsa = NULL;
+}
+
int
ssh_dss_sign(const struct sshkey *key, u_char **sigp, size_t *lenp,
const u_char *data, size_t datalen, u_int compat)
@@ -204,4 +230,34 @@ ssh_dss_verify(const struct sshkey *key,
freezero(sigblob, len);
return ret;
}
+
+static const struct sshkey_impl_funcs sshkey_dss_funcs = {
+ /* .size = */ ssh_dss_size,
+ /* .alloc = */ ssh_dss_alloc,
+ /* .cleanup = */ ssh_dss_cleanup,
+};
+
+const struct sshkey_impl sshkey_dss_impl = {
+ /* .name = */ "ssh-dss",
+ /* .shortname = */ "DSA",
+ /* .sigalg = */ NULL,
+ /* .type = */ KEY_DSA,
+ /* .nid = */ 0,
+ /* .cert = */ 0,
+ /* .sigonly = */ 0,
+ /* .keybits = */ 0,
+ /* .funcs = */ &sshkey_dss_funcs,
+};
+
+const struct sshkey_impl sshkey_dsa_cert_impl = {
+ /* .name = */ "ssh-dss-cert-v01@openssh.com",
+ /* .shortname = */ "DSA-CERT",
+ /* .sigalg = */ NULL,
+ /* .type = */ KEY_DSA_CERT,
+ /* .nid = */ 0,
+ /* .cert = */ 1,
+ /* .sigonly = */ 0,
+ /* .keybits = */ 0,
+ /* .funcs = */ &sshkey_dss_funcs,
+};
#endif /* WITH_OPENSSL */
diff --git a/ssh-ecdsa-sk.c b/ssh-ecdsa-sk.c
index c6927ecb..2f0984f4 100644
--- a/ssh-ecdsa-sk.c
+++ b/ssh-ecdsa-sk.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: ssh-ecdsa-sk.c,v 1.8 2020/06/22 23:44:27 djm Exp $ */
+/* $OpenBSD: ssh-ecdsa-sk.c,v 1.9 2022/10/28 00:35:40 djm Exp $ */
/*
* Copyright (c) 2000 Markus Friedl. All rights reserved.
* Copyright (c) 2010 Damien Miller. All rights reserved.
@@ -61,6 +61,16 @@ ssh_ecdsa_sk_verify(const struct sshkey *key,
}
#else /* OPENSSL_HAS_ECC */
+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;
+}
+
/*
* Check FIDO/W3C webauthn signatures clientData field against the expected
* format and prepare a hash of it for use in signature verification.
@@ -321,4 +331,46 @@ ssh_ecdsa_sk_verify(const struct sshkey *key,
return ret;
}
+static const struct sshkey_impl_funcs sshkey_ecdsa_sk_funcs = {
+ /* .size = */ NULL,
+ /* .alloc = */ NULL,
+ /* .cleanup = */ ssh_ecdsa_sk_cleanup,
+};
+
+const struct sshkey_impl sshkey_ecdsa_sk_impl = {
+ /* .name = */ "sk-ecdsa-sha2-nistp256@openssh.com",
+ /* .shortname = */ "ECDSA-SK",
+ /* .sigalg = */ NULL,
+ /* .type = */ KEY_ECDSA_SK,
+ /* .nid = */ NID_X9_62_prime256v1,
+ /* .cert = */ 0,
+ /* .sigonly = */ 0,
+ /* .keybits = */ 256,
+ /* .funcs = */ &sshkey_ecdsa_sk_funcs,
+};
+
+const struct sshkey_impl sshkey_ecdsa_sk_cert_impl = {
+ /* .name = */ "sk-ecdsa-sha2-nistp256-cert-v01@openssh.com",
+ /* .shortname = */ "ECDSA-SK-CERT",
+ /* .sigalg = */ NULL,
+ /* .type = */ KEY_ECDSA_SK_CERT,
+ /* .nid = */ NID_X9_62_prime256v1,
+ /* .cert = */ 1,
+ /* .sigonly = */ 0,
+ /* .keybits = */ 256,
+ /* .funcs = */ &sshkey_ecdsa_sk_funcs,
+};
+
+const struct sshkey_impl sshkey_ecdsa_sk_webauthn_impl = {
+ /* .name = */ "webauthn-sk-ecdsa-sha2-nistp256@openssh.com",
+ /* .shortname = */ "ECDSA-SK",
+ /* .sigalg = */ NULL,
+ /* .type = */ KEY_ECDSA_SK,
+ /* .nid = */ NID_X9_62_prime256v1,
+ /* .cert = */ 0,
+ /* .sigonly = */ 1,
+ /* .keybits = */ 256,
+ /* .funcs = */ &sshkey_ecdsa_sk_funcs,
+};
+
#endif /* OPENSSL_HAS_ECC */
diff --git a/ssh-ecdsa.c b/ssh-ecdsa.c
index 599c7199..e207e43f 100644
--- a/ssh-ecdsa.c
+++ b/ssh-ecdsa.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: ssh-ecdsa.c,v 1.16 2019/01/21 09:54:11 djm Exp $ */
+/* $OpenBSD: ssh-ecdsa.c,v 1.17 2022/10/28 00:35:40 djm Exp $ */
/*
* Copyright (c) 2000 Markus Friedl. All rights reserved.
* Copyright (c) 2010 Damien Miller. All rights reserved.
@@ -45,6 +45,30 @@
#include "openbsd-compat/openssl-compat.h"
+static u_int
+ssh_ecdsa_size(const struct sshkey *key)
+{
+ switch (key->ecdsa_nid) {
+ case NID_X9_62_prime256v1:
+ return 256;
+ case NID_secp384r1:
+ return 384;
+#ifdef OPENSSL_HAS_NISTP521
+ case NID_secp521r1:
+ return 521;
+#endif
+ default:
+ return 0;
+ }
+}
+
+static void
+ssh_ecdsa_cleanup(struct sshkey *k)
+{
+ EC_KEY_free(k->ecdsa);
+ k->ecdsa = NULL;
+}
+
/* ARGSUSED */
int
ssh_ecdsa_sign(const struct sshkey *key, u_char **sigp, size_t *lenp,
@@ -197,4 +221,84 @@ ssh_ecdsa_verify(const struct sshkey *key,
return ret;
}
+static const struct sshkey_impl_funcs sshkey_ecdsa_funcs = {
+ /* .size = */ ssh_ecdsa_size,
+ /* .alloc = */ NULL,
+ /* .cleanup = */ ssh_ecdsa_cleanup,
+};
+
+const struct sshkey_impl sshkey_ecdsa_nistp256_impl = {
+ /* .name = */ "ecdsa-sha2-nistp256",
+ /* .shortname = */ "ECDSA",
+ /* .sigalg = */ NULL,
+ /* .type = */ KEY_ECDSA,
+ /* .nid = */ NID_X9_62_prime256v1,
+ /* .cert = */ 0,
+ /* .sigonly = */ 0,
+ /* .keybits = */ 0,
+ /* .funcs = */ &sshkey_ecdsa_funcs,
+};
+
+const struct sshkey_impl sshkey_ecdsa_nistp256_cert_impl = {
+ /* .name = */ "ecdsa-sha2-nistp256-cert-v01@openssh.com",
+ /* .shortname = */ "ECDSA-CERT",
+ /* .sigalg = */ NULL,
+ /* .type = */ KEY_ECDSA_CERT,
+ /* .nid = */ NID_X9_62_prime256v1,
+ /* .cert = */ 1,
+ /* .sigonly = */ 0,
+ /* .keybits = */ 0,
+ /* .funcs = */ &sshkey_ecdsa_funcs,
+};
+
+const struct sshkey_impl sshkey_ecdsa_nistp384_impl = {
+ /* .name = */ "ecdsa-sha2-nistp384",
+ /* .shortname = */ "ECDSA",
+ /* .sigalg = */ NULL,
+ /* .type = */ KEY_ECDSA,
+ /* .nid = */ NID_secp384r1,
+ /* .cert = */ 0,
+ /* .sigonly = */ 0,
+ /* .keybits = */ 0,
+ /* .funcs = */ &sshkey_ecdsa_funcs,
+};
+
+const struct sshkey_impl sshkey_ecdsa_nistp384_cert_impl = {
+ /* .name = */ "ecdsa-sha2-nistp384-cert-v01@openssh.com",
+ /* .shortname = */ "ECDSA-CERT",
+ /* .sigalg = */ NULL,
+ /* .type = */ KEY_ECDSA_CERT,
+ /* .nid = */ NID_secp384r1,
+ /* .cert = */ 1,
+ /* .sigonly = */ 0,
+ /* .keybits = */ 0,
+ /* .funcs = */ &sshkey_ecdsa_funcs,
+};
+
+#ifdef OPENSSL_HAS_NISTP521
+const struct sshkey_impl sshkey_ecdsa_nistp521_impl = {
+ /* .name = */ "ecdsa-sha2-nistp521",
+ /* .shortname = */ "ECDSA",
+ /* .sigalg = */ NULL,
+ /* .type = */ KEY_ECDSA,
+ /* .nid = */ NID_secp521r1,
+ /* .cert = */ 0,
+ /* .sigonly = */ 0,
+ /* .keybits = */ 0,
+ /* .funcs = */ &sshkey_ecdsa_funcs,
+};
+
+const struct sshkey_impl sshkey_ecdsa_nistp521_cert_impl = {
+ /* .name = */ "ecdsa-sha2-nistp521-cert-v01@openssh.com",
+ /* .shortname = */ "ECDSA-CERT",
+ /* .sigalg = */ NULL,
+ /* .type = */ KEY_ECDSA_CERT,
+ /* .nid = */ NID_secp521r1,
+ /* .cert = */ 1,
+ /* .sigonly = */ 0,
+ /* .keybits = */ 0,
+ /* .funcs = */ &sshkey_ecdsa_funcs,
+};
+#endif
+
#endif /* WITH_OPENSSL && OPENSSL_HAS_ECC */
diff --git a/ssh-ed25519-sk.c b/ssh-ed25519-sk.c
index 4393ca66..1c21d4bf 100644
--- a/ssh-ed25519-sk.c
+++ b/ssh-ed25519-sk.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: ssh-ed25519-sk.c,v 1.6 2020/10/18 11:32:02 djm Exp $ */
+/* $OpenBSD: ssh-ed25519-sk.c,v 1.7 2022/10/28 00:35:40 djm Exp $ */
/*
* Copyright (c) 2019 Markus Friedl. All rights reserved.
*
@@ -35,6 +35,18 @@
#include "ssh.h"
#include "digest.h"
+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;
+}
+
int
ssh_ed25519_sk_verify(const struct sshkey *key,
const u_char *signature, size_t signaturelen,
@@ -161,3 +173,33 @@ ssh_ed25519_sk_verify(const struct sshkey *key,
free(ktype);
return r;
}
+
+static const struct sshkey_impl_funcs sshkey_ed25519_sk_funcs = {
+ /* .size = */ NULL,
+ /* .alloc = */ NULL,
+ /* .cleanup = */ ssh_ed25519_sk_cleanup,
+};
+
+const struct sshkey_impl sshkey_ed25519_sk_impl = {
+ /* .name = */ "sk-ssh-ed25519@openssh.com",
+ /* .shortname = */ "ED25519-SK",
+ /* .sigalg = */ NULL,
+ /* .type = */ KEY_ED25519_SK,
+ /* .nid = */ 0,
+ /* .cert = */ 0,
+ /* .sigonly = */ 0,
+ /* .keybits = */ 256,
+ /* .funcs = */ &sshkey_ed25519_sk_funcs,
+};
+
+const struct sshkey_impl sshkey_ed25519_sk_cert_impl = {
+ /* .name = */ "sk-ssh-ed25519-cert-v01@openssh.com",
+ /* .shortname = */ "ED25519-SK-CERT",
+ /* .sigalg = */ NULL,
+ /* .type = */ KEY_ED25519_SK_CERT,
+ /* .nid = */ 0,
+ /* .cert = */ 1,
+ /* .sigonly = */ 0,
+ /* .keybits = */ 256,
+ /* .funcs = */ &sshkey_ed25519_sk_funcs,
+};
diff --git a/ssh-ed25519.c b/ssh-ed25519.c
index 4861628c..abd983df 100644
--- a/ssh-ed25519.c
+++ b/ssh-ed25519.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: ssh-ed25519.c,v 1.10 2022/08/26 08:12:56 djm Exp $ */
+/* $OpenBSD: ssh-ed25519.c,v 1.11 2022/10/28 00:35:40 djm Exp $ */
/*
* Copyright (c) 2013 Markus Friedl <markus@openbsd.org>
*
@@ -32,6 +32,15 @@
#include "ssherr.h"
#include "ssh.h"
+static void
+ssh_ed25519_cleanup(struct sshkey *k)
+{
+ freezero(k->ed25519_pk, ED25519_PK_SZ);
+ freezero(k->ed25519_sk, ED25519_SK_SZ);
+ k->ed25519_pk = NULL;
+ k->ed25519_sk = NULL;
+}
+
int
ssh_ed25519_sign(const struct sshkey *key, u_char **sigp, size_t *lenp,
const u_char *data, size_t datalen, u_int compat)
@@ -158,3 +167,33 @@ ssh_ed25519_verify(const struct sshkey *key,
free(ktype);
return r;
}
+
+static const struct sshkey_impl_funcs sshkey_ed25519_funcs = {
+ /* .size = */ NULL,
+ /* .alloc = */ NULL,
+ /* .cleanup = */ ssh_ed25519_cleanup,
+};
+
+const struct sshkey_impl sshkey_ed25519_impl = {
+ /* .name = */ "ssh-ed25519",
+ /* .shortname = */ "ED25519",
+ /* .sigalg = */ NULL,
+ /* .type = */ KEY_ED25519,
+ /* .nid = */ 0,
+ /* .cert = */ 0,
+ /* .sigonly = */ 0,
+ /* .keybits = */ 256,
+ /* .funcs = */ &sshkey_ed25519_funcs,
+};
+
+const struct sshkey_impl sshkey_ed25519_cert_impl = {
+ /* .name = */ "ssh-ed25519-cert-v01@openssh.com",
+ /* .shortname = */ "ED25519-CERT",
+ /* .sigalg = */ NULL,
+ /* .type = */ KEY_ED25519_CERT,
+ /* .nid = */ 0,
+ /* .cert = */ 1,
+ /* .sigonly = */ 0,
+ /* .keybits = */ 256,
+ /* .funcs = */ &sshkey_ed25519_funcs,
+};
diff --git a/ssh-rsa.c b/ssh-rsa.c
index 9b14f9a9..e7225e82 100644
--- a/ssh-rsa.c
+++ b/ssh-rsa.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: ssh-rsa.c,v 1.67 2018/07/03 11:39:54 djm Exp $ */
+/* $OpenBSD: ssh-rsa.c,v 1.69 2022/10/28 00:35:40 djm Exp $ */
/*
* Copyright (c) 2000, 2003 Markus Friedl <markus@openbsd.org>
*
@@ -39,6 +39,32 @@
static int openssh_RSA_verify(int, u_char *, size_t, u_char *, size_t, RSA *);
+static u_int
+ssh_rsa_size(const struct sshkey *key)
+{
+ const BIGNUM *rsa_n;
+
+ if (key->rsa == NULL)
+ return 0;
+ RSA_get0_key(key->rsa, &rsa_n, NULL, NULL);
+ return BN_num_bits(rsa_n);
+}
+
+static int
+ssh_rsa_alloc(struct sshkey *k)
+{
+ if ((k->rsa = RSA_new()) == NULL)
+ return SSH_ERR_ALLOC_FAIL;
+ return 0;
+}
+
+static void
+ssh_rsa_cleanup(struct sshkey *k)
+{
+ RSA_free(k->rsa);
+ k->rsa = NULL;
+}
+
static const char *
rsa_hash_alg_ident(int hash_alg)
{
@@ -446,4 +472,84 @@ done:
freezero(decrypted, rsasize);
return ret;
}
+
+static const struct sshkey_impl_funcs sshkey_rsa_funcs = {
+ /* .size = */ ssh_rsa_size,
+ /* .alloc = */ ssh_rsa_alloc,
+ /* .cleanup = */ ssh_rsa_cleanup,
+};
+
+const struct sshkey_impl sshkey_rsa_impl = {
+ /* .name = */ "ssh-rsa",
+ /* .shortname = */ "RSA",
+ /* .sigalg = */ NULL,
+ /* .type = */ KEY_RSA,
+ /* .nid = */ 0,
+ /* .cert = */ 0,
+ /* .sigonly = */ 0,
+ /* .keybits = */ 0,
+ /* .funcs = */ &sshkey_rsa_funcs,
+};
+
+const struct sshkey_impl sshkey_rsa_cert_impl = {
+ /* .name = */ "ssh-rsa-cert-v01@openssh.com",
+ /* .shortname = */ "RSA-CERT",
+ /* .sigalg = */ NULL,
+ /* .type = */ KEY_RSA_CERT,
+ /* .nid = */ 0,
+ /* .cert = */ 1,
+ /* .sigonly = */ 0,
+ /* .keybits = */ 0,
+ /* .funcs = */ &sshkey_rsa_funcs,
+};
+
+/* SHA2 signature algorithms */
+
+const struct sshkey_impl sshkey_rsa_sha256_impl = {
+ /* .name = */ "rsa-sha2-256",
+ /* .shortname = */ "RSA",
+ /* .sigalg = */ NULL,
+ /* .type = */ KEY_RSA,
+ /* .nid = */ 0,
+ /* .cert = */ 0,
+ /* .sigonly = */ 1,
+ /* .keybits = */ 0,
+ /* .funcs = */ &sshkey_rsa_funcs,
+};
+
+const struct sshkey_impl sshkey_rsa_sha512_impl = {
+ /* .name = */ "rsa-sha2-512",
+ /* .shortname = */ "RSA",
+ /* .sigalg = */ NULL,
+ /* .type = */ KEY_RSA,
+ /* .nid = */ 0,
+ /* .cert = */ 0,
+ /* .sigonly = */ 1,
+ /* .keybits = */ 0,
+ /* .funcs = */ &sshkey_rsa_funcs,
+};
+
+const struct sshkey_impl sshkey_rsa_sha256_cert_impl = {
+ /* .name = */ "rsa-sha2-256-cert-v01@openssh.com",
+ /* .shortname = */ "RSA-CERT",
+ /* .sigalg = */ "rsa-sha2-256",
+ /* .type = */ KEY_RSA_CERT,
+ /* .nid = */ 0,
+ /* .cert = */ 1,
+ /* .sigonly = */ 1,
+ /* .keybits = */ 0,
+ /* .funcs = */ &sshkey_rsa_funcs,
+};
+
+const struct sshkey_impl sshkey_rsa_sha512_cert_impl = {
+ /* .name = */ "rsa-sha2-512-cert-v01@openssh.com",
+ /* .shortname = */ "RSA-CERT",
+ /* .sigalg = */ "rsa-sha2-512",
+ /* .type = */ KEY_RSA_CERT,
+ /* .nid = */ 0,
+ /* .cert = */ 1,
+ /* .sigonly = */ 1,
+ /* .keybits = */ 0,
+ /* .funcs = */ &sshkey_rsa_funcs,
+};
#endif /* WITH_OPENSSL */
diff --git a/ssh-xmss.c b/ssh-xmss.c
index 41ede296..2ac9ee05 100644
--- a/ssh-xmss.c
+++ b/ssh-xmss.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: ssh-xmss.c,v 1.5 2022/04/20 15:59:18 millert Exp $*/
+/* $OpenBSD: ssh-xmss.c,v 1.6 2022/10/28 00:35:40 djm Exp $*/
/*
* Copyright (c) 2017 Stefan-Lukas Gazdag.
* Copyright (c) 2017 Markus Friedl.
@@ -37,6 +37,20 @@
#include "xmss_fast.h"
+static void
+ssh_xmss_cleanup(struct sshkey *k)
+{
+ freezero(k->xmss_pk, sshkey_xmss_pklen(k));
+ freezero(k->xmss_sk, sshkey_xmss_sklen(k));
+ sshkey_xmss_free_state(k);
+ free(k->xmss_name);
+ free(k->xmss_filename);
+ k->xmss_pk = NULL;
+ k->xmss_sk = NULL;
+ k->xmss_name = NULL;
+ k->xmss_filename = NULL;
+}
+
int
ssh_xmss_sign(const struct sshkey *key, u_char **sigp, size_t *lenp,
const u_char *data, size_t datalen, u_int compat)
@@ -184,4 +198,34 @@ ssh_xmss_verify(const struct sshkey *key,
free(ktype);
return r;
}
+
+static const struct sshkey_impl_funcs sshkey_xmss_funcs = {
+ /* .size = */ NULL,
+ /* .alloc = */ NULL,
+ /* .cleanup = */ ssh_xmss_cleanup,
+};
+
+const struct sshkey_impl sshkey_xmss_impl = {
+ /* .name = */ "ssh-xmss@openssh.com",
+ /* .shortname = */ "XMSS",
+ /* .sigalg = */ NULL,
+ /* .type = */ KEY_XMSS,
+ /* .nid = */ 0,
+ /* .cert = */ 0,
+ /* .sigonly = */ 0,
+ /* .keybits = */ 256,
+ /* .funcs = */ &sshkey_xmss_funcs,
+};
+
+const struct sshkey_impl sshkey_xmss_cert_impl = {
+ /* .name = */ "ssh-xmss-cert-v01@openssh.com",
+ /* .shortname = */ "XMSS-CERT",
+ /* .sigalg = */ NULL,
+ /* .type = */ KEY_XMSS_CERT,
+ /* .nid = */ 0,
+ /* .cert = */ 1,
+ /* .sigonly = */ 0,
+ /* .keybits = */ 256,
+ /* .funcs = */ &sshkey_xmss_funcs,
+};
#endif /* WITH_XMSS */
diff --git a/sshkey.c b/sshkey.c
index 77093235..1052108b 100644
--- a/sshkey.c
+++ b/sshkey.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: sshkey.c,v 1.122 2022/09/17 10:30:45 djm Exp $ */
+/* $OpenBSD: sshkey.c,v 1.123 2022/10/28 00:35:40 djm Exp $ */
/*
* Copyright (c) 2000, 2001 Markus Friedl. All rights reserved.
* Copyright (c) 2008 Alexander von Gernler. All rights reserved.
@@ -94,111 +94,132 @@ static int sshkey_from_blob_internal(struct sshbuf *buf,
struct sshkey **keyp, int allow_cert);
/* Supported key types */
-struct keytype {
- const char *name;
- const char *shortname;
- const char *sigalg;
- int type;
- int nid;
- int cert;
- int sigonly;
-};
-static const struct keytype keytypes[] = {
- { "ssh-ed25519", "ED25519", NULL, KEY_ED25519, 0, 0, 0 },
- { "ssh-ed25519-cert-v01@openssh.com", "ED25519-CERT", NULL,
- KEY_ED25519_CERT, 0, 1, 0 },
-#ifdef ENABLE_SK
- { "sk-ssh-ed25519@openssh.com", "ED25519-SK", NULL,
- KEY_ED25519_SK, 0, 0, 0 },
- { "sk-ssh-ed25519-cert-v01@openssh.com", "ED25519-SK-CERT", NULL,
- KEY_ED25519_SK_CERT, 0, 1, 0 },
-#endif
-#ifdef WITH_XMSS
- { "ssh-xmss@openssh.com", "XMSS", NULL, KEY_XMSS, 0, 0, 0 },
- { "ssh-xmss-cert-v01@openssh.com", "XMSS-CERT", NULL,
- KEY_XMSS_CERT, 0, 1, 0 },
-#endif /* WITH_XMSS */
+extern const struct sshkey_impl sshkey_ed25519_impl;
+extern const struct sshkey_impl sshkey_ed25519_cert_impl;
+extern const struct sshkey_impl sshkey_ed25519_sk_impl;
+extern const struct sshkey_impl sshkey_ed25519_sk_cert_impl;
#ifdef WITH_OPENSSL
- { "ssh-rsa", "RSA", NULL, KEY_RSA, 0, 0, 0 },
- { "rsa-sha2-256", "RSA", NULL, KEY_RSA, 0, 0, 1 },
- { "rsa-sha2-512", "RSA", NULL, KEY_RSA, 0, 0, 1 },
- { "ssh-dss", "DSA", NULL, KEY_DSA, 0, 0, 0 },
# ifdef OPENSSL_HAS_ECC
- { "ecdsa-sha2-nistp256", "ECDSA", NULL,
- KEY_ECDSA, NID_X9_62_prime256v1, 0, 0 },
- { "ecdsa-sha2-nistp384", "ECDSA", NULL,
- KEY_ECDSA, NID_secp384r1, 0, 0 },
-# ifdef OPENSSL_HAS_NISTP521
- { "ecdsa-sha2-nistp521", "ECDSA", NULL,
- KEY_ECDSA, NID_secp521r1, 0, 0 },
-# endif /* OPENSSL_HAS_NISTP521 */
# ifdef ENABLE_SK
- { "sk-ecdsa-sha2-nistp256@openssh.com", "ECDSA-SK", NULL,
- KEY_ECDSA_SK, NID_X9_62_prime256v1, 0, 0 },
- { "webauthn-sk-ecdsa-sha2-nistp256@openssh.com", "ECDSA-SK", NULL,
- KEY_ECDSA_SK, NID_X9_62_prime256v1, 0, 1 },
+extern const struct sshkey_impl sshkey_ecdsa_sk_impl;
+extern const struct sshkey_impl sshkey_ecdsa_sk_cert_impl;
+extern const struct sshkey_impl sshkey_ecdsa_sk_webauthn_impl;
# endif /* ENABLE_SK */
+extern const struct sshkey_impl sshkey_ecdsa_nistp256_impl;
+extern const struct sshkey_impl sshkey_ecdsa_nistp256_cert_impl;
+extern const struct sshkey_impl sshkey_ecdsa_nistp384_impl;
+extern const struct sshkey_impl sshkey_ecdsa_nistp384_cert_impl;
+# ifdef OPENSSL_HAS_NISTP521
+extern const struct sshkey_impl sshkey_ecdsa_nistp521_impl;
+extern const struct sshkey_impl sshkey_ecdsa_nistp521_cert_impl;
+# endif /* OPENSSL_HAS_NISTP521 */
# endif /* OPENSSL_HAS_ECC */
- { "ssh-rsa-cert-v01@openssh.com", "RSA-CERT", NULL,
- KEY_RSA_CERT, 0, 1, 0 },
- { "rsa-sha2-256-cert-v01@openssh.com", "RSA-CERT",
- "rsa-sha2-256", KEY_RSA_CERT, 0, 1, 1 },
- { "rsa-sha2-512-cert-v01@openssh.com", "RSA-CERT",
- "rsa-sha2-512", KEY_RSA_CERT, 0, 1, 1 },
- { "ssh-dss-cert-v01@openssh.com", "DSA-CERT", NULL,
- KEY_DSA_CERT, 0, 1, 0 },
+extern const struct sshkey_impl sshkey_rsa_impl;
+extern const struct sshkey_impl sshkey_rsa_cert_impl;
+extern const struct sshkey_impl sshkey_rsa_sha256_impl;
+extern const struct sshkey_impl sshkey_rsa_sha256_cert_impl;
+extern const struct sshkey_impl sshkey_rsa_sha512_impl;
+extern const struct sshkey_impl sshkey_rsa_sha512_cert_impl;
+extern const struct sshkey_impl sshkey_dss_impl;
+extern const struct sshkey_impl sshkey_dsa_cert_impl;
+#endif /* WITH_OPENSSL */
+#ifdef WITH_XMSS
+extern const struct sshkey_impl sshkey_xmss_impl;
+extern const struct sshkey_impl sshkey_xmss_cert_impl;
+#endif
+
+const struct sshkey_impl * const keyimpls[] = {
+ &sshkey_ed25519_impl,
+ &sshkey_ed25519_cert_impl,
+#ifdef ENABLE_SK
+ &sshkey_ed25519_sk_impl,
+ &sshkey_ed25519_sk_cert_impl,
+#endif
+#ifdef WITH_OPENSSL
# ifdef OPENSSL_HAS_ECC
- { "ecdsa-sha2-nistp256-cert-v01@openssh.com", "ECDSA-CERT", NULL,
- KEY_ECDSA_CERT, NID_X9_62_prime256v1, 1, 0 },
- { "ecdsa-sha2-nistp384-cert-v01@openssh.com", "ECDSA-CERT", NULL,
- KEY_ECDSA_CERT, NID_secp384r1, 1, 0 },
+ &sshkey_ecdsa_nistp256_impl,
+ &sshkey_ecdsa_nistp256_cert_impl,
+ &sshkey_ecdsa_nistp384_impl,
+ &sshkey_ecdsa_nistp384_cert_impl,
# ifdef OPENSSL_HAS_NISTP521
- { "ecdsa-sha2-nistp521-cert-v01@openssh.com", "ECDSA-CERT", NULL,
- KEY_ECDSA_CERT, NID_secp521r1, 1, 0 },
+ &sshkey_ecdsa_nistp521_impl,
+ &sshkey_ecdsa_nistp521_cert_impl,
# endif /* OPENSSL_HAS_NISTP521 */
# ifdef ENABLE_SK
- { "sk-ecdsa-sha2-nistp256-cert-v01@openssh.com", "ECDSA-SK-CERT", NULL,
- KEY_ECDSA_SK_CERT, NID_X9_62_prime256v1, 1, 0 },
+ &sshkey_ecdsa_sk_impl,
+ &sshkey_ecdsa_sk_cert_impl,
+ &sshkey_ecdsa_sk_webauthn_impl,
# endif /* ENABLE_SK */
# endif /* OPENSSL_HAS_ECC */
+ &sshkey_dss_impl,
+ &sshkey_dsa_cert_impl,
+ &sshkey_rsa_impl,
+ &sshkey_rsa_cert_impl,
+ &sshkey_rsa_sha256_impl,
+ &sshkey_rsa_sha256_cert_impl,
+ &sshkey_rsa_sha512_impl,
+ &sshkey_rsa_sha512_cert_impl,
#endif /* WITH_OPENSSL */
- { NULL, NULL, NULL, -1, -1, 0, 0 }
+#ifdef WITH_XMSS
+ &sshkey_xmss_impl,
+ &sshkey_xmss_cert_impl,
+#endif
+ NULL
};
+static const struct sshkey_impl *
+sshkey_impl_from_type(int type)
+{
+ int i;
+
+ for (i = 0; keyimpls[i] != NULL; i++) {
+ if (keyimpls[i]->type == type)
+ return keyimpls[i];
+ }
+ return NULL;
+}
+
+static const struct sshkey_impl *
+sshkey_impl_from_type_nid(int type, int nid)
+{
+ int i;
+
+ for (i = 0; keyimpls[i] != NULL; i++) {
+ if (keyimpls[i]->type == type &&
+ (keyimpls[i]->nid == 0 || keyimpls[i]->nid == nid))
+ return keyimpls[i];
+ }
+ return NULL;
+}
+
const char *
sshkey_type(const struct sshkey *k)
{
- const struct keytype *kt;
+ const struct sshkey_impl *impl;
- for (kt = keytypes; kt->type != -1; kt++) {
- if (kt->type == k->type)
- return kt->shortname;
- }
- return "unknown";
+ if ((impl = sshkey_impl_from_type(k->type)) == NULL)
+ return "unknown";
+ return impl->shortname;
}
static const char *
sshkey_ssh_name_from_type_nid(int type, int nid)
{
- const struct keytype *kt;
+ const struct sshkey_impl *impl;
- for (kt = keytypes; kt->type != -1; kt++) {
- if (kt->type == type && (kt->nid == 0 || kt->nid == nid))
- return kt->name;
- }
- return "ssh-unknown";
+ if ((impl = sshkey_impl_from_type_nid(type, nid)) == NULL)
+ return "ssh-unknown";
+ return impl->name;
}
int
sshkey_type_is_cert(int type)
{
- const struct keytype *kt;
+ const struct sshkey_impl *impl;
- for (kt = keytypes; kt->type != -1; kt++) {
- if (kt->type == type)
- return kt->cert;
- }
- return 0;
+ if ((impl = sshkey_impl_from_type(type)) == NULL)
+ return 0;
+ return impl->cert;
}
const char *
@@ -217,13 +238,15 @@ sshkey_ssh_name_plain(const struct sshkey *k)
int
sshkey_type_from_name(const char *name)
{
- const struct keytype *kt;
+ int i;
+ const struct sshkey_impl *impl;
- for (kt = keytypes; kt->type != -1; kt++) {
+ for (i = 0; keyimpls[i] != NULL; i++) {
+ impl = keyimpls[i];
/* Only allow shortname matches for plain key types */
- if ((kt->name != NULL && strcmp(name, kt->name) == 0) ||
- (!kt->cert && strcasecmp(kt->shortname, name) == 0))
- return kt->type;
+ if ((impl->name != NULL && strcmp(name, impl->name) == 0) ||
+ (!impl->cert && strcasecmp(impl->shortname, name) == 0))
+ return impl->type;
}
return KEY_UNSPEC;
}
@@ -244,13 +267,14 @@ key_type_is_ecdsa_variant(int type)
int
sshkey_ecdsa_nid_from_name(const char *name)
{
- const struct keytype *kt;
+ int i;
- for (kt = keytypes; kt->type != -1; kt++) {
- if (!key_type_is_ecdsa_variant(kt->type))
+ for (i = 0; keyimpls[i] != NULL; i++) {
+ if (!key_type_is_ecdsa_variant(keyimpls[i]->type))
continue;
- if (kt->name != NULL && strcmp(name, kt->name) == 0)
- return kt->nid;
+ if (keyimpls[i]->name != NULL &&
+ strcmp(name, keyimpls[i]->name) == 0)
+ return keyimpls[i]->nid;
}
return -1;
}
@@ -282,25 +306,26 @@ char *
sshkey_alg_list(int certs_only, int plain_only, int include_sigonly, char sep)
{
char *tmp, *ret = NULL;
- size_t nlen, rlen = 0;
- const struct keytype *kt;
+ size_t i, nlen, rlen = 0;
+ const struct sshkey_impl *impl;
- for (kt = keytypes; kt->type != -1; kt++) {
- if (kt->name == NULL)
+ for (i = 0; keyimpls[i] != NULL; i++) {
+ impl = keyimpls[i];
+ if (impl->name == NULL)
continue;
- if (!include_sigonly && kt->sigonly)
+ if (!include_sigonly && impl->sigonly)
continue;
- if ((certs_only && !kt->cert) || (plain_only && kt->cert))
+ if ((certs_only && !impl->cert) || (plain_only && impl->cert))
continue;
if (ret != NULL)
ret[rlen++] = sep;
- nlen = strlen(kt->name);
+ nlen = strlen(impl->name);
if ((tmp = realloc(ret, rlen + nlen + 2)) == NULL) {
free(ret);
return NULL;
}
ret = tmp;
- memcpy(ret + rlen, kt->name, nlen + 1);
+ memcpy(ret + rlen, impl->name, nlen + 1);
rlen += nlen;
}
return ret;
@@ -310,8 +335,8 @@ int
sshkey_names_valid2(const char *names, int allow_wildcard)
{
char *s, *cp, *p;
- const struct keytype *kt;
- int type;
+ const struct sshkey_impl *impl;
+ int i, type;
if (names == NULL || strcmp(names, "") == 0)
return 0;
@@ -327,12 +352,15 @@ sshkey_names_valid2(const char *names, int allow_wildcard)
* If any has a positive or negative match then
* the component is accepted.
*/
- for (kt = keytypes; kt->type != -1; kt++) {
- if (match_pattern_list(kt->name,
- p, 0) != 0)
+ impl = NULL;
+ for (i = 0; keyimpls[i] != NULL; i++) {
+ if (match_pattern_list(
+ keyimpls[i]->name, p, 0) != 0) {
+ impl = keyimpls[i];
break;
+ }
}
- if (kt->type != -1)
+ if (impl != NULL)
continue;
}
free(s);
@@ -346,56 +374,24 @@ sshkey_names_valid2(const char *names, int allow_wildcard)
u_int
sshkey_size(const struct sshkey *k)
{
-#ifdef WITH_OPENSSL
- const BIGNUM *rsa_n, *dsa_p;
-#endif /* WITH_OPENSSL */
+ const struct sshkey_impl *impl;
- switch (k->type) {
-#ifdef WITH_OPENSSL
- case KEY_RSA:
- case KEY_RSA_CERT:
- if (k->rsa == NULL)
- return 0;
- RSA_get0_key(k->rsa, &rsa_n, NULL, NULL);
- return BN_num_bits(rsa_n);
- case KEY_DSA:
- case KEY_DSA_CERT:
- if (k->dsa == NULL)
- return 0;
- DSA_get0_pqg(k->dsa, &dsa_p, NULL, NULL);
- return BN_num_bits(dsa_p);
- case KEY_ECDSA:
- case KEY_ECDSA_CERT:
- case KEY_ECDSA_SK:
- case KEY_ECDSA_SK_CERT:
- return sshkey_curve_nid_to_bits(k->ecdsa_nid);
-#endif /* WITH_OPENSSL */
- case KEY_ED25519:
- case KEY_ED25519_CERT:
- case KEY_ED25519_SK:
- case KEY_ED25519_SK_CERT:
- case KEY_XMSS:
- case KEY_XMSS_CERT:
- return 256; /* XXX */
- }
- return 0;
+ if ((impl = sshkey_impl_from_type_nid(k->type, k->ecdsa_nid)) == NULL)
+ return 0;
+ if (impl->funcs->size != NULL)
+ return impl->funcs->size(k);
+ return impl->keybits;
}
static int
sshkey_type_is_valid_ca(int type)
{
- switch (type) {
- case KEY_RSA:
- case KEY_DSA:
- case KEY_ECDSA:
- case KEY_ECDSA_SK:
- case KEY_ED25519:
- case KEY_ED25519_SK:
- case KEY_XMSS:
- return 1;
- default:
+ const struct sshkey_impl *impl;
+
+ if ((impl = sshkey_impl_from_type(type)) == NULL)
return 0;
- }
+ /* All non-certificate types may act as CAs */
+ return !impl->cert;
}
int
@@ -573,63 +569,23 @@ struct sshkey *
sshkey_new(int type)
{
struct sshkey *k;
-#ifdef WITH_OPENSSL
- RSA *rsa;
- DSA *dsa;
-#endif /* WITH_OPENSSL */
+ const struct sshkey_impl *impl = NULL;
+ if (type != KEY_UNSPEC &&
+ (impl = sshkey_impl_from_type(type)) == NULL)
+ return NULL;
+
+ /* All non-certificate types may act as CAs */
if ((k = calloc(1, sizeof(*k))) == NULL)
return NULL;
k->type = type;
- k->ecdsa = NULL;
k->ecdsa_nid = -1;
- k->dsa = NULL;
- k->rsa = NULL;
- k->cert = NULL;
- k->ed25519_sk = NULL;
- k->ed25519_pk = NULL;
- k->xmss_sk = NULL;
- k->xmss_pk = NULL;
- switch (k->type) {
-#ifdef WITH_OPENSSL
- case KEY_RSA:
- case KEY_RSA_CERT:
- if ((rsa = RSA_new()) == NULL) {
+ if (impl != NULL && impl->funcs->alloc != NULL) {
+ if (impl->funcs->alloc(k) != 0) {
free(k);
return NULL;
}
- k->rsa = rsa;
- break;
- case KEY_DSA:
- case KEY_DSA_CERT:
- if ((dsa = DSA_new()) == NULL) {
- free(k);
- return NULL;
- }
- k->dsa = dsa;
- break;
- case KEY_ECDSA:
- case KEY_ECDSA_CERT:
- case KEY_ECDSA_SK:
- case KEY_ECDSA_SK_CERT:
- /* Cannot do anything until we know the group */
- break;
-#endif /* WITH_OPENSSL */
- case KEY_ED25519:
- case KEY_ED25519_CERT:
- case KEY_ED25519_SK:
- case KEY_ED25519_SK_CERT:
- case KEY_XMSS:
- case KEY_XMSS_CERT:
- /* no need to prealloc */
- break;
- case KEY_UNSPEC:
- break;
- default:
- free(k);
- return NULL;
}
-
if (sshkey_is_cert(k)) {
if ((k->cert = cert_new()) == NULL) {
sshkey_free(k);
@@ -643,66 +599,13 @@ sshkey_new(int type)
void
sshkey_free(struct sshkey *k)
{
+ const struct sshkey_impl *impl;
+
if (k == NULL)
return;
- switch (k->type) {
-#ifdef WITH_OPENSSL
- case KEY_RSA:
- case KEY_RSA_CERT:
- RSA_free(k->rsa);
- k->rsa = NULL;
- break;
- case KEY_DSA:
- case KEY_DSA_CERT:
- DSA_free(k->dsa);
- k->dsa = NULL;
- break;
-# ifdef OPENSSL_HAS_ECC
- case KEY_ECDSA_SK:
- case KEY_ECDSA_SK_CERT:
- free(k->sk_application);
- sshbuf_free(k->sk_key_handle);
- sshbuf_free(k->sk_reserved);
- /* FALLTHROUGH */
- case KEY_ECDSA:
- case KEY_ECDSA_CERT:
- EC_KEY_free(k->ecdsa);
- k->ecdsa = NULL;
- break;
-# endif /* OPENSSL_HAS_ECC */
-#endif /* WITH_OPENSSL */
- case KEY_ED25519_SK:
- case KEY_ED25519_SK_CERT:
- free(k->sk_application);
- sshbuf_free(k->sk_key_handle);
- sshbuf_free(k->sk_reserved);
- /* FALLTHROUGH */
- case KEY_ED25519:
- case KEY_ED25519_CERT:
- freezero(k->ed25519_pk, ED25519_PK_SZ);
- k->ed25519_pk = NULL;
- freezero(k->ed25519_sk, ED25519_SK_SZ);
- k->ed25519_sk = NULL;
- break;
-#ifdef WITH_XMSS
- case KEY_XMSS:
- case KEY_XMSS_CERT:
- freezero(k->xmss_pk, sshkey_xmss_pklen(k));
- k->xmss_pk = NULL;
- freezero(k->xmss_sk, sshkey_xmss_sklen(k));
- k->xmss_sk = NULL;
- sshkey_xmss_free_state(k);
- free(k->xmss_name);
- k->xmss_name = NULL;
- free(k->xmss_filename);
- k->xmss_filename = NULL;
- break;
-#endif /* WITH_XMSS */
- case KEY_UNSPEC:
- break;
- default:
- break;
- }
+ if ((impl = sshkey_impl_from_type(k->type)) != NULL &&
+ impl->funcs->cleanup != NULL)
+ impl->funcs->cleanup(k);
if (sshkey_is_cert(k))
cert_free(k->cert);
freezero(k->shielded_private, k->shielded_len);
@@ -1319,16 +1222,18 @@ sshkey_fingerprint(const struct sshkey *k, int dgst_alg,
static int
peek_type_nid(const char *s, size_t l, int *nid)
{
- const struct keytype *kt;
+ const struct sshkey_impl *impl;
+ int i;
- for (kt = keytypes; kt->type != -1; kt++) {
- if (kt->name == NULL || strlen(kt->name) != l)
+ for (i = 0; keyimpls[i] != NULL; i++) {
+ impl = keyimpls[i];
+ if (impl->name == NULL || strlen(impl->name) != l)
continue;
- if (memcmp(s, kt->name, l) == 0) {
+ if (memcmp(s, impl->name, l) == 0) {
*nid = -1;
- if (key_type_is_ecdsa_variant(kt->type))
- *nid = kt->nid;
- return kt->type;
+ if (key_type_is_ecdsa_variant(impl->type))
+ *nid = impl->nid;
+ return impl->type;
}
}
return KEY_UNSPEC;
@@ -2737,17 +2642,19 @@ sshkey_check_cert_sigtype(const struct sshkey *key, const char *allowed)
const char *
sshkey_sigalg_by_name(const char *name)
{
- const struct keytype *kt;
+ const struct sshkey_impl *impl;
+ int i;
- for (kt = keytypes; kt->type != -1; kt++) {
- if (strcmp(kt->name, name) != 0)
+ for (i = 0; keyimpls[i] != NULL; i++) {
+ impl = keyimpls[i];
+ if (strcmp(impl->name, name) != 0)
continue;
- if (kt->sigalg != NULL)
- return kt->sigalg;
- if (!kt->cert)
- return kt->name;
+ if (impl->sigalg != NULL)
+ return impl->sigalg;
+ if (!impl->cert)
+ return impl->name;
return sshkey_ssh_name_from_type_nid(
- sshkey_type_plain(kt->type), kt->nid);
+ sshkey_type_plain(impl->type), impl->nid);
}
return NULL;
}
diff --git a/sshkey.h b/sshkey.h
index be254e6b..3ec0e87b 100644
--- a/sshkey.h
+++ b/sshkey.h
@@ -1,4 +1,4 @@
-/* $OpenBSD: sshkey.h,v 1.52 2022/09/17 10:30:45 djm Exp $ */
+/* $OpenBSD: sshkey.h,v 1.53 2022/10/28 00:35:40 djm Exp $ */
/*
* Copyright (c) 2000, 2001 Markus Friedl. All rights reserved.
@@ -164,6 +164,24 @@ struct sshkey_sig_details {
uint8_t sk_flags; /* U2F signature flags; see ssh-sk.h */
};
+struct sshkey_impl_funcs {
+ u_int (*size)(const struct sshkey *); /* optional */
+ int (*alloc)(struct sshkey *); /* optional */
+ void (*cleanup)(struct sshkey *); /* optional */
+};
+
+struct sshkey_impl {
+ const char *name;
+ const char *shortname;
+ const char *sigalg;
+ int type;
+ int nid;
+ int cert;
+ int sigonly;
+ int keybits;
+ const struct sshkey_impl_funcs *funcs;
+};
+
struct sshkey *sshkey_new(int);
void sshkey_free(struct sshkey *);
int sshkey_equal_public(const struct sshkey *,