From 2c55744a56de0ffc81fe445a1e7fc5cd308712b3 Mon Sep 17 00:00:00 2001 From: "markus@openbsd.org" Date: Tue, 12 Nov 2019 19:33:08 +0000 Subject: [PATCH] upstream: enable ed25519 support; ok djm OpenBSD-Commit-ID: 1a399c5b3ef15bd8efb916110cf5a9e0b554ab7e --- authfd.c | 4 +- myproposal.h | 4 +- pathnames.h | 3 +- readconf.c | 4 +- ssh-add.c | 5 +- ssh-agent.c | 4 +- ssh-keygen.c | 25 +++++--- ssh-sk-helper.c | 4 +- sshconnect.c | 4 +- sshconnect2.c | 13 ++-- sshkey.c | 154 +++++++++++++++++++++++++++++++++++++++++++++++- sshkey.h | 7 ++- 12 files changed, 200 insertions(+), 31 deletions(-) diff --git a/authfd.c b/authfd.c index 1f0cd2ab3..e014f765c 100644 --- a/authfd.c +++ b/authfd.c @@ -1,4 +1,4 @@ -/* $OpenBSD: authfd.c,v 1.118 2019/10/31 21:19:14 djm Exp $ */ +/* $OpenBSD: authfd.c,v 1.119 2019/11/12 19:33:08 markus Exp $ */ /* * Author: Tatu Ylonen * Copyright (c) 1995 Tatu Ylonen , Espoo, Finland @@ -484,6 +484,8 @@ ssh_add_identity_constrained(int sock, struct sshkey *key, #endif case KEY_ED25519: case KEY_ED25519_CERT: + case KEY_ED25519_SK: + case KEY_ED25519_SK_CERT: case KEY_XMSS: case KEY_XMSS_CERT: type = constrained ? diff --git a/myproposal.h b/myproposal.h index a22649a2e..90bb67bb3 100644 --- a/myproposal.h +++ b/myproposal.h @@ -1,4 +1,4 @@ -/* $OpenBSD: myproposal.h,v 1.60 2019/11/01 02:32:05 djm Exp $ */ +/* $OpenBSD: myproposal.h,v 1.61 2019/11/12 19:33:08 markus Exp $ */ /* * Copyright (c) 2000 Markus Friedl. All rights reserved. @@ -149,6 +149,7 @@ "ecdsa-sha2-nistp256-cert-v01@openssh.com," \ "ecdsa-sha2-nistp384-cert-v01@openssh.com," \ "ecdsa-sha2-nistp521-cert-v01@openssh.com," \ + "sk-ssh-ed25519-cert-v01@openssh.com," \ "ssh-ed25519-cert-v01@openssh.com," \ "rsa-sha2-512-cert-v01@openssh.com," \ "rsa-sha2-256-cert-v01@openssh.com," \ @@ -157,6 +158,7 @@ "ecdsa-sha2-nistp256," \ "ecdsa-sha2-nistp384," \ "ecdsa-sha2-nistp521," \ + "sk-ssh-ed25519@openssh.com," \ "ssh-ed25519," \ "rsa-sha2-512," \ "rsa-sha2-256," \ diff --git a/pathnames.h b/pathnames.h index 3a1bd1977..f7ca5a75a 100644 --- a/pathnames.h +++ b/pathnames.h @@ -1,4 +1,4 @@ -/* $OpenBSD: pathnames.h,v 1.30 2019/10/31 21:22:01 djm Exp $ */ +/* $OpenBSD: pathnames.h,v 1.31 2019/11/12 19:33:08 markus Exp $ */ /* * Author: Tatu Ylonen @@ -78,6 +78,7 @@ #define _PATH_SSH_CLIENT_ID_ED25519 _PATH_SSH_USER_DIR "/id_ed25519" #define _PATH_SSH_CLIENT_ID_XMSS _PATH_SSH_USER_DIR "/id_xmss" #define _PATH_SSH_CLIENT_ID_ECDSA_SK _PATH_SSH_USER_DIR "/id_ecdsa_sk" +#define _PATH_SSH_CLIENT_ID_ED25519_SK _PATH_SSH_USER_DIR "/id_ed25519_sk" /* * Configuration file in user's home directory. This file need not be diff --git a/readconf.c b/readconf.c index f18194580..3d99367c3 100644 --- a/readconf.c +++ b/readconf.c @@ -1,4 +1,4 @@ -/* $OpenBSD: readconf.c,v 1.310 2019/10/31 21:18:28 djm Exp $ */ +/* $OpenBSD: readconf.c,v 1.311 2019/11/12 19:33:08 markus Exp $ */ /* * Author: Tatu Ylonen * Copyright (c) 1995 Tatu Ylonen , Espoo, Finland @@ -2055,6 +2055,8 @@ fill_default_options(Options * options) #endif add_identity_file(options, "~/", _PATH_SSH_CLIENT_ID_ED25519, 0); + add_identity_file(options, "~/", + _PATH_SSH_CLIENT_ID_ED25519_SK, 0); add_identity_file(options, "~/", _PATH_SSH_CLIENT_ID_XMSS, 0); } if (options->escape_char == -1) diff --git a/ssh-add.c b/ssh-add.c index 3c8849ac4..696b156d5 100644 --- a/ssh-add.c +++ b/ssh-add.c @@ -1,4 +1,4 @@ -/* $OpenBSD: ssh-add.c,v 1.143 2019/10/31 21:19:56 djm Exp $ */ +/* $OpenBSD: ssh-add.c,v 1.144 2019/11/12 19:33:08 markus Exp $ */ /* * Author: Tatu Ylonen * Copyright (c) 1995 Tatu Ylonen , Espoo, Finland @@ -81,6 +81,7 @@ static char *default_files[] = { #endif #endif /* WITH_OPENSSL */ _PATH_SSH_CLIENT_ID_ED25519, + _PATH_SSH_CLIENT_ID_ED25519_SK, _PATH_SSH_CLIENT_ID_XMSS, NULL }; @@ -312,7 +313,7 @@ add_file(int agent_fd, const char *filename, int key_only, int qflag, ssh_free_identitylist(idlist); } - if (sshkey_type_plain(private->type) != KEY_ECDSA_SK) + if (!sshkey_is_sk(private)) skprovider = NULL; /* Don't send constraint for other keys */ else if (skprovider == NULL) { fprintf(stderr, "Cannot load security key %s without " diff --git a/ssh-agent.c b/ssh-agent.c index 07f19c53a..dd9f85ae7 100644 --- a/ssh-agent.c +++ b/ssh-agent.c @@ -1,4 +1,4 @@ -/* $OpenBSD: ssh-agent.c,v 1.239 2019/10/31 21:23:19 djm Exp $ */ +/* $OpenBSD: ssh-agent.c,v 1.240 2019/11/12 19:33:08 markus Exp $ */ /* * Author: Tatu Ylonen * Copyright (c) 1995 Tatu Ylonen , Espoo, Finland @@ -622,7 +622,7 @@ process_add_identity(SocketEntry *e) } } if (sk_provider != NULL) { - if (sshkey_type_plain(k->type) != KEY_ECDSA_SK) { + if (!sshkey_is_sk(k)) { error("Cannot add provider: %s is not a security key", sshkey_type(k)); free(sk_provider); diff --git a/ssh-keygen.c b/ssh-keygen.c index ac34f314b..030b3684e 100644 --- a/ssh-keygen.c +++ b/ssh-keygen.c @@ -1,4 +1,4 @@ -/* $OpenBSD: ssh-keygen.c,v 1.361 2019/11/08 03:54:02 djm Exp $ */ +/* $OpenBSD: ssh-keygen.c,v 1.362 2019/11/12 19:33:08 markus Exp $ */ /* * Author: Tatu Ylonen * Copyright (c) 1994 Tatu Ylonen , Espoo, Finland @@ -287,6 +287,10 @@ ask_filename(struct passwd *pw, const char *prompt) case KEY_ED25519_CERT: name = _PATH_SSH_CLIENT_ID_ED25519; break; + case KEY_ED25519_SK: + case KEY_ED25519_SK_CERT: + name = _PATH_SSH_CLIENT_ID_ED25519_SK; + break; case KEY_XMSS: case KEY_XMSS_CERT: name = _PATH_SSH_CLIENT_ID_XMSS; @@ -3255,16 +3259,23 @@ main(int argc, char **argv) printf("Generating public/private %s key pair.\n", key_type_name); if (type == KEY_ECDSA_SK) { + switch (type) { + case KEY_ECDSA_SK: + case KEY_ED25519_SK: #ifndef ENABLE_SK fatal("Security key support was disabled at compile time"); #else /* ENABLE_SK */ - if (sshsk_enroll(sk_provider, - cert_key_id == NULL ? "ssh:" : cert_key_id, - sk_flags, NULL, &private, NULL) != 0) - exit(1); /* error message already printed */ + if (sshsk_enroll(type, sk_provider, + cert_key_id == NULL ? "ssh:" : cert_key_id, + sk_flags, NULL, &private, NULL) != 0) + exit(1); /* error message already printed */ + break; #endif /* ENABLE_SK */ - } else if ((r = sshkey_generate(type, bits, &private)) != 0) - fatal("sshkey_generate failed"); + default: + if ((r = sshkey_generate(type, bits, &private)) != 0) + fatal("sshkey_generate failed"); + break; + } if ((r = sshkey_from_private(private, &public)) != 0) fatal("sshkey_from_private failed: %s\n", ssh_err(r)); diff --git a/ssh-sk-helper.c b/ssh-sk-helper.c index a996f5898..0acb8d172 100644 --- a/ssh-sk-helper.c +++ b/ssh-sk-helper.c @@ -1,4 +1,4 @@ -/* $OpenBSD: ssh-sk-helper.c,v 1.2 2019/11/12 19:30:50 markus Exp $ */ +/* $OpenBSD: ssh-sk-helper.c,v 1.3 2019/11/12 19:33:08 markus Exp $ */ /* * Copyright (c) 2019 Google LLC * @@ -114,7 +114,7 @@ main(int argc, char **argv) if ((r = sshbuf_froms(req, &kbuf)) != 0 || (r = sshkey_private_deserialize(kbuf, &key)) != 0) fatal("Unable to parse key: %s", ssh_err(r)); - if (sshkey_type_plain(key->type) != KEY_ECDSA_SK) + if (!sshkey_is_sk(key)) fatal("Unsupported key type %s", sshkey_ssh_name(key)); if ((r = sshbuf_get_cstring(req, &provider, NULL)) != 0 || diff --git a/sshconnect.c b/sshconnect.c index 177775f6e..7e9369ee3 100644 --- a/sshconnect.c +++ b/sshconnect.c @@ -1,4 +1,4 @@ -/* $OpenBSD: sshconnect.c,v 1.321 2019/10/31 21:20:38 djm Exp $ */ +/* $OpenBSD: sshconnect.c,v 1.322 2019/11/12 19:33:08 markus Exp $ */ /* * Author: Tatu Ylonen * Copyright (c) 1995 Tatu Ylonen , Espoo, Finland @@ -1425,7 +1425,7 @@ maybe_add_key_to_agent(char *authfile, struct sshkey *private, close(auth_sock); return; } - if (sshkey_type_plain(private->type) == KEY_ECDSA_SK) + if (sshkey_is_sk(private)) skprovider = options.sk_provider; if ((r = ssh_add_identity_constrained(auth_sock, private, comment, 0, (options.add_keys_to_agent == 3), 0, skprovider)) == 0) diff --git a/sshconnect2.c b/sshconnect2.c index 867d463d6..4e5cddf14 100644 --- a/sshconnect2.c +++ b/sshconnect2.c @@ -1,4 +1,4 @@ -/* $OpenBSD: sshconnect2.c,v 1.310 2019/10/31 21:23:19 djm Exp $ */ +/* $OpenBSD: sshconnect2.c,v 1.311 2019/11/12 19:33:08 markus Exp $ */ /* * Copyright (c) 2000 Markus Friedl. All rights reserved. * Copyright (c) 2008 Damien Miller. All rights reserved. @@ -611,7 +611,7 @@ format_identity(Identity *id) if (id->key) { if ((id->key->flags & SSHKEY_FLAG_EXT) != 0) note = " token"; - else if (sshkey_type_plain(id->key->type) == KEY_ECDSA_SK) + else if (sshkey_is_sk(id->key)) note = " security-key"; } xasprintf(&ret, "%s %s%s%s%s%s%s", @@ -1468,8 +1468,7 @@ load_identity_file(Identity *id) quit = 1; break; } - if (private != NULL && - sshkey_type_plain(private->type) == KEY_ECDSA_SK && + if (private != NULL && sshkey_is_sk(private) && options.sk_provider == NULL) { debug("key \"%s\" is a security key, but no " "provider specified", id->filename); @@ -1554,8 +1553,7 @@ pubkey_prepare(Authctxt *authctxt) options.identity_files[i]); continue; } - if (key && sshkey_type_plain(key->type) == KEY_ECDSA_SK && - options.sk_provider == NULL) { + if (key && sshkey_is_sk(key) && options.sk_provider == NULL) { debug("%s: ignoring security key %s as no " "SecurityKeyProvider has been specified", __func__, options.identity_files[i]); @@ -1579,8 +1577,7 @@ pubkey_prepare(Authctxt *authctxt) options.identity_files[i]); continue; } - if (key && sshkey_type_plain(key->type) == KEY_ECDSA_SK && - options.sk_provider == NULL) { + if (key && sshkey_is_sk(key) && options.sk_provider == NULL) { debug("%s: ignoring security key certificate %s as no " "SecurityKeyProvider has been specified", __func__, options.identity_files[i]); diff --git a/sshkey.c b/sshkey.c index 269f37b39..1b66d4ec7 100644 --- a/sshkey.c +++ b/sshkey.c @@ -1,4 +1,4 @@ -/* $OpenBSD: sshkey.c,v 1.89 2019/11/12 19:31:18 markus Exp $ */ +/* $OpenBSD: sshkey.c,v 1.90 2019/11/12 19:33:08 markus Exp $ */ /* * Copyright (c) 2000, 2001 Markus Friedl. All rights reserved. * Copyright (c) 2008 Alexander von Gernler. All rights reserved. @@ -107,6 +107,10 @@ 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 }, + { "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 }, #ifdef WITH_XMSS { "ssh-xmss@openssh.com", "XMSS", NULL, KEY_XMSS, 0, 0, 0 }, { "ssh-xmss-cert-v01@openssh.com", "XMSS-CERT", NULL, @@ -337,6 +341,8 @@ sshkey_size(const struct sshkey *k) #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 */ @@ -353,6 +359,7 @@ sshkey_type_is_valid_ca(int type) case KEY_ECDSA: case KEY_ECDSA_SK: case KEY_ED25519: + case KEY_ED25519_SK: case KEY_XMSS: return 1; default: @@ -368,6 +375,20 @@ sshkey_is_cert(const struct sshkey *k) return sshkey_type_is_cert(k->type); } +int +sshkey_is_sk(const struct sshkey *k) +{ + if (k == NULL) + return 0; + switch (sshkey_type_plain(k->type)) { + case KEY_ECDSA_SK: + case KEY_ED25519_SK: + return 1; + default: + return 0; + } +} + /* Return the cert-less equivalent to a certified key type */ int sshkey_type_plain(int type) @@ -383,6 +404,8 @@ sshkey_type_plain(int type) return KEY_ECDSA_SK; case KEY_ED25519_CERT: return KEY_ED25519; + case KEY_ED25519_SK_CERT: + return KEY_ED25519_SK; case KEY_XMSS_CERT: return KEY_XMSS; default: @@ -563,6 +586,8 @@ sshkey_new(int type) #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 */ @@ -615,6 +640,12 @@ sshkey_free(struct sshkey *k) 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); @@ -734,6 +765,13 @@ sshkey_equal_public(const struct sshkey *a, const struct sshkey *b) 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 && @@ -842,12 +880,18 @@ to_blob_buf(const struct sshkey *key, struct sshbuf *b, int force_plain, 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: @@ -1290,11 +1334,13 @@ sshkey_read(struct sshkey *ret, char **cpp) case KEY_ECDSA: case KEY_ECDSA_SK: case KEY_ED25519: + case KEY_ED25519_SK: case KEY_DSA_CERT: case KEY_ECDSA_CERT: case KEY_ECDSA_SK_CERT: case KEY_RSA_CERT: case KEY_ED25519_CERT: + case KEY_ED25519_SK_CERT: #ifdef WITH_XMSS case KEY_XMSS: case KEY_XMSS_CERT: @@ -1418,6 +1464,13 @@ sshkey_read(struct sshkey *ret, char **cpp) /* XXX */ #endif break; + case KEY_ED25519_SK: + freezero(ret->ed25519_pk, ED25519_PK_SZ); + ret->ed25519_pk = k->ed25519_pk; + ret->sk_application = k->sk_application; + k->ed25519_pk = NULL; + k->sk_application = NULL; + break; #ifdef WITH_XMSS case KEY_XMSS: free(ret->xmss_pk); @@ -1876,6 +1929,8 @@ sshkey_from_private(const struct sshkey *k, struct sshkey **pkp) #endif /* WITH_OPENSSL */ case KEY_ED25519: case KEY_ED25519_CERT: + case KEY_ED25519_SK: + case KEY_ED25519_SK_CERT: if (k->ed25519_pk != NULL) { if ((n->ed25519_pk = malloc(ED25519_PK_SZ)) == NULL) { r = SSH_ERR_ALLOC_FAIL; @@ -1883,6 +1938,12 @@ sshkey_from_private(const struct sshkey *k, struct sshkey **pkp) } memcpy(n->ed25519_pk, k->ed25519_pk, ED25519_PK_SZ); } + if (k->type != KEY_ED25519_SK && + k->type != KEY_ED25519_SK_CERT) + break; + /* Append security-key application string */ + if ((n->sk_application = strdup(k->sk_application)) == NULL) + goto out; break; #ifdef WITH_XMSS case KEY_XMSS: @@ -2444,6 +2505,7 @@ sshkey_from_blob_internal(struct sshbuf *b, struct sshkey **keyp, # endif /* OPENSSL_HAS_ECC */ #endif /* WITH_OPENSSL */ case KEY_ED25519_CERT: + case KEY_ED25519_SK_CERT: /* Skip nonce */ if (sshbuf_get_string_direct(b, NULL, NULL) != 0) { ret = SSH_ERR_INVALID_FORMAT; @@ -2451,6 +2513,7 @@ sshkey_from_blob_internal(struct sshbuf *b, struct sshkey **keyp, } /* FALLTHROUGH */ case KEY_ED25519: + case KEY_ED25519_SK: if ((ret = sshbuf_get_string(b, &pk, &len)) != 0) goto out; if (len != ED25519_PK_SZ) { @@ -2461,6 +2524,17 @@ sshkey_from_blob_internal(struct sshbuf *b, struct sshkey **keyp, ret = SSH_ERR_ALLOC_FAIL; goto out; } + if (type == KEY_ED25519_SK || type == KEY_ED25519_SK_CERT) { + /* Parse additional security-key application string */ + if (sshbuf_get_cstring(b, &key->sk_application, + NULL) != 0) { + ret = SSH_ERR_INVALID_FORMAT; + goto out; + } +#ifdef DEBUG_PK + fprintf(stderr, "App: %s\n", key->sk_application); +#endif + } key->ed25519_pk = pk; pk = NULL; break; @@ -2790,6 +2864,9 @@ sshkey_to_certified(struct sshkey *k) newtype = KEY_ECDSA_SK_CERT; break; #endif /* WITH_OPENSSL */ + case KEY_ED25519_SK: + newtype = KEY_ED25519_SK_CERT; + break; case KEY_ED25519: newtype = KEY_ED25519_CERT; break; @@ -3223,6 +3300,29 @@ sshkey_private_serialize_opt(struct sshkey *key, struct sshbuf *buf, 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) + 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) { @@ -3532,6 +3632,57 @@ sshkey_private_deserialize(struct sshbuf *buf, struct sshkey **kp) k->ed25519_sk = ed25519_sk; ed25519_pk = ed25519_sk = NULL; /* transferred */ break; + case KEY_ED25519_SK: + if ((k = sshkey_new(type)) == NULL) { + r = SSH_ERR_ALLOC_FAIL; + goto out; + } + if ((r = sshbuf_get_string(buf, &ed25519_pk, &pklen)) != 0) + goto out; + if (pklen != ED25519_PK_SZ) { + r = SSH_ERR_INVALID_FORMAT; + goto out; + } + if ((k->sk_key_handle = sshbuf_new()) == NULL || + (k->sk_reserved = sshbuf_new()) == NULL) { + r = SSH_ERR_ALLOC_FAIL; + goto out; + } + if ((r = sshbuf_get_cstring(buf, &k->sk_application, + NULL)) != 0 || + (r = sshbuf_get_u8(buf, &k->sk_flags)) != 0 || + (r = sshbuf_get_stringb(buf, k->sk_key_handle)) != 0 || + (r = sshbuf_get_stringb(buf, k->sk_reserved)) != 0) + goto out; + k->ed25519_pk = ed25519_pk; + ed25519_pk = NULL; + break; + case KEY_ED25519_SK_CERT: + if ((r = sshkey_froms(buf, &k)) != 0 || + (r = sshbuf_get_string(buf, &ed25519_pk, &pklen)) != 0) + goto out; + if (k->type != type) { + r = SSH_ERR_INVALID_FORMAT; + goto out; + } + if (pklen != ED25519_PK_SZ) { + r = SSH_ERR_INVALID_FORMAT; + goto out; + } + if ((k->sk_key_handle = sshbuf_new()) == NULL || + (k->sk_reserved = sshbuf_new()) == NULL) { + r = SSH_ERR_ALLOC_FAIL; + goto out; + } + if ((r = sshbuf_get_cstring(buf, &k->sk_application, + NULL)) != 0 || + (r = sshbuf_get_u8(buf, &k->sk_flags)) != 0 || + (r = sshbuf_get_stringb(buf, k->sk_key_handle)) != 0 || + (r = sshbuf_get_stringb(buf, k->sk_reserved)) != 0) + goto out; + k->ed25519_pk = ed25519_pk; + ed25519_pk = NULL; /* transferred */ + break; #ifdef WITH_XMSS case KEY_XMSS: if ((k = sshkey_new(type)) == NULL) { @@ -4261,6 +4412,7 @@ sshkey_private_to_fileblob(struct sshkey *key, struct sshbuf *blob, break; /* see below */ #endif /* WITH_OPENSSL */ case KEY_ED25519: + case KEY_ED25519_SK: #ifdef WITH_XMSS case KEY_XMSS: #endif /* WITH_XMSS */ diff --git a/sshkey.h b/sshkey.h index 8cd12bd95..1fb8369f0 100644 --- a/sshkey.h +++ b/sshkey.h @@ -1,4 +1,4 @@ -/* $OpenBSD: sshkey.h,v 1.37 2019/11/12 19:29:25 markus Exp $ */ +/* $OpenBSD: sshkey.h,v 1.38 2019/11/12 19:33:08 markus Exp $ */ /* * Copyright (c) 2000, 2001 Markus Friedl. All rights reserved. @@ -129,7 +129,7 @@ struct sshkey { /* KEY_ECDSA and KEY_ECDSA_SK */ int ecdsa_nid; /* NID of curve */ EC_KEY *ecdsa; - /* KEY_ED25519 */ + /* KEY_ED25519 and KEY_ED25519_SK */ u_char *ed25519_sk; u_char *ed25519_pk; /* KEY_XMSS */ @@ -138,7 +138,7 @@ struct sshkey { void *xmss_state; /* depends on xmss_name, opaque */ u_char *xmss_sk; u_char *xmss_pk; - /* KEY_ECDSA_SK */ + /* KEY_ECDSA_SK and KEY_ED25519_SK */ char *sk_application; uint8_t sk_flags; struct sshbuf *sk_key_handle; @@ -180,6 +180,7 @@ int sshkey_unshield_private(struct sshkey *); int sshkey_type_from_name(const char *); int sshkey_is_cert(const struct sshkey *); +int sshkey_is_sk(const struct sshkey *); int sshkey_type_is_cert(int); int sshkey_type_plain(int); int sshkey_to_certified(struct sshkey *);