]> git.ipfire.org Git - thirdparty/openssh-portable.git/commitdiff
upstream: add support for reading ED25519 private keys in PEM PKCS8
authordjm@openbsd.org <djm@openbsd.org>
Wed, 11 Oct 2023 22:41:05 +0000 (22:41 +0000)
committerDamien Miller <djm@mindrot.org>
Wed, 11 Oct 2023 22:59:44 +0000 (09:59 +1100)
format; ok markus@ tb@

OpenBSD-Commit-ID: 01b85c91757e6b057e9b23b8a23f96415c3c7174

configure.ac
sshkey.c

index d8816e3f65de88c2cafa6d173c5c7dca6c33749c..0f457f3bd454093ea09d7f10e60b5a0e27f7ca27 100644 (file)
@@ -3140,6 +3140,30 @@ if test "x$openssl" = "xyes" ; then
                        ecdsa-sha2-nistp521 \
                        ecdsa-sha2-nistp521-cert-v01@openssh.com"
        fi
+
+       # Check libcrypto ED25519 support
+       AC_CHECK_FUNCS([EVP_PKEY_get_raw_public_key])
+       AC_CHECK_FUNCS([EVP_PKEY_get_raw_private_key])
+       AC_MSG_CHECKING([whether OpenSSL has ED25519 support])
+       AC_LINK_IFELSE(
+               [AC_LANG_PROGRAM([[
+       #include <string.h>
+       #include <openssl/evp.h>
+               ]], [[
+               unsigned char buf[64];
+               memset(buf, 0, sizeof(buf));
+               exit(EVP_PKEY_new_raw_private_key(EVP_PKEY_ED25519,
+                   buf, sizeof(buf)) == NULL);
+               ]])],
+               [
+                       AC_MSG_RESULT([no])
+               ],
+               [
+                       AC_MSG_RESULT([yes])
+                       AC_DEFINE([OPENSSL_HAS_ED25519], [1],
+                           [libcrypto has ed25519 support])
+               ]
+       )
 fi
 
 # PKCS11/U2F depend on OpenSSL and dlopen().
index 2d3906ad8475573e51d3551fca743bbe60a5d2f6..33f5e734fbe00ed66d7b1c421a844fd2d88ab067 100644 (file)
--- a/sshkey.c
+++ b/sshkey.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: sshkey.c,v 1.138 2023/08/21 04:36:46 djm Exp $ */
+/* $OpenBSD: sshkey.c,v 1.139 2023/10/11 22:41:05 djm Exp $ */
 /*
  * Copyright (c) 2000, 2001 Markus Friedl.  All rights reserved.
  * Copyright (c) 2008 Alexander von Gernler.  All rights reserved.
@@ -3422,6 +3422,7 @@ sshkey_parse_private_pem_fileblob(struct sshbuf *blob, int type,
        struct sshkey *prv = NULL;
        BIO *bio = NULL;
        int r;
+       size_t len;
 
        if (keyp != NULL)
                *keyp = NULL;
@@ -3500,6 +3501,41 @@ sshkey_parse_private_pem_fileblob(struct sshbuf *blob, int type,
                        sshkey_dump_ec_key(prv->ecdsa);
 # endif
 #endif /* OPENSSL_HAS_ECC */
+#ifdef OPENSSL_HAS_ED25519
+       } else if (EVP_PKEY_base_id(pk) == EVP_PKEY_ED25519 &&
+           (type == KEY_UNSPEC || type == KEY_ED25519)) {
+               if ((prv = sshkey_new(KEY_UNSPEC)) == NULL ||
+                   (prv->ed25519_sk = calloc(1, ED25519_SK_SZ)) == NULL ||
+                   (prv->ed25519_pk = calloc(1, ED25519_PK_SZ)) == NULL) {
+                       r = SSH_ERR_ALLOC_FAIL;
+                       goto out;
+               }
+               prv->type = KEY_ED25519;
+               len = ED25519_PK_SZ;
+               if (!EVP_PKEY_get_raw_public_key(pk, prv->ed25519_pk, &len)) {
+                       r = SSH_ERR_LIBCRYPTO_ERROR;
+                       goto out;
+               }
+               if (len != ED25519_PK_SZ) {
+                       r = SSH_ERR_INVALID_FORMAT;
+                       goto out;
+               }
+               len = ED25519_SK_SZ - ED25519_PK_SZ;
+               if (!EVP_PKEY_get_raw_private_key(pk, prv->ed25519_sk, &len)) {
+                       r = SSH_ERR_LIBCRYPTO_ERROR;
+                       goto out;
+               }
+               if (len != ED25519_SK_SZ - ED25519_PK_SZ) {
+                       r = SSH_ERR_INVALID_FORMAT;
+                       goto out;
+               }
+               /* Append the public key to our private key */
+               memcpy(prv->ed25519_sk + (ED25519_SK_SZ - ED25519_PK_SZ),
+                   prv->ed25519_pk, ED25519_PK_SZ);
+# ifdef DEBUG_PK
+               sshbuf_dump_data(prv->ed25519_sk, ED25519_SK_SZ, stderr);
+# endif
+#endif /* OPENSSL_HAS_ED25519 */
        } else {
                r = SSH_ERR_INVALID_FORMAT;
                goto out;
@@ -3529,7 +3565,6 @@ sshkey_parse_private_fileblob_type(struct sshbuf *blob, int type,
                *commentp = NULL;
 
        switch (type) {
-       case KEY_ED25519:
        case KEY_XMSS:
                /* No fallback for new-format-only keys */
                return sshkey_parse_private2(blob, type, passphrase,