]> git.ipfire.org Git - thirdparty/openssh-portable.git/commitdiff
upstream: enable ed25519 support; ok djm
authormarkus@openbsd.org <markus@openbsd.org>
Tue, 12 Nov 2019 19:33:08 +0000 (19:33 +0000)
committerDamien Miller <djm@mindrot.org>
Tue, 12 Nov 2019 21:54:09 +0000 (08:54 +1100)
OpenBSD-Commit-ID: 1a399c5b3ef15bd8efb916110cf5a9e0b554ab7e

12 files changed:
authfd.c
myproposal.h
pathnames.h
readconf.c
ssh-add.c
ssh-agent.c
ssh-keygen.c
ssh-sk-helper.c
sshconnect.c
sshconnect2.c
sshkey.c
sshkey.h

index 1f0cd2ab335266729c79ef91d267ed870da41f2d..e014f765c232d692dd2dec0e4b08995879104bd7 100644 (file)
--- 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 <ylo@cs.hut.fi>
  * Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, 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 ?
index a22649a2e76cd64b2fd1bf57854f8f5b2adbb813..90bb67bb368affac0c69a4bd2f557a9da75b8626 100644 (file)
@@ -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.
        "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," \
        "ecdsa-sha2-nistp256," \
        "ecdsa-sha2-nistp384," \
        "ecdsa-sha2-nistp521," \
+       "sk-ssh-ed25519@openssh.com," \
        "ssh-ed25519," \
        "rsa-sha2-512," \
        "rsa-sha2-256," \
index 3a1bd197768fb60279ae7e5012880ee8601e6a3d..f7ca5a75a0d2ec763c5863c33dae13445816dfad 100644 (file)
@@ -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 <ylo@cs.hut.fi>
@@ -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
index f181945804d6316bb30ab29d2ab434d533934289..3d99367c35845a70609990479914f95be6884813 100644 (file)
@@ -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 <ylo@cs.hut.fi>
  * Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, 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)
index 3c8849ac423d20b87aef019237df4460ba0c5997..696b156d569e40a91cebc6ef1514d8948adc434c 100644 (file)
--- 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 <ylo@cs.hut.fi>
  * Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, 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 "
index 07f19c53ad0df1bc2f49aa5a450850c32ff57d26..dd9f85ae700dd84b782198aa2bde583e72419310 100644 (file)
@@ -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 <ylo@cs.hut.fi>
  * Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, 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);
index ac34f314b0b5c0fe2eda3bd7d3e27df5684e7b2e..030b3684e23bdbf8384ed7dc0edd6f7d712643f4 100644 (file)
@@ -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 <ylo@cs.hut.fi>
  * Copyright (c) 1994 Tatu Ylonen <ylo@cs.hut.fi>, 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));
 
index a996f5898193dedd8ff23e2603030fde4b9c3444..0acb8d1728af1323ae1637e10de9eea426933665 100644 (file)
@@ -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 ||
index 177775f6e4e629a740ad844942834261db275f50..7e9369ee31ccf986bde0608dc2a4875b5da30462 100644 (file)
@@ -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 <ylo@cs.hut.fi>
  * Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, 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)
index 867d463d6a4df6c75d07e1cbd92a544bb05f5ba4..4e5cddf1403e56a93dd60b41918deedb9e53ac03 100644 (file)
@@ -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]);
index 269f37b396e4d0762ef4df9f073df9516d400c10..1b66d4ec7841f3c59f10489f6735ff7d20e67f9f 100644 (file)
--- 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 */
index 8cd12bd955ae6b9af53b4fdd58161dfb1fccce2c..1fb8369f08b60ecdf1931665e465735d80d38a0c 100644 (file)
--- 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 *);