diff options
author | djm@openbsd.org <djm@openbsd.org> | 2023-10-11 22:41:05 +0000 |
---|---|---|
committer | Damien Miller <djm@mindrot.org> | 2023-10-12 09:59:44 +1100 |
commit | 76e91e7238cdc5662bc818e2a48d466283840d23 (patch) | |
tree | bfa428fc915ee1286c8bd12217bbd815ad157b87 | |
parent | fc77c8e352c0f44125425c05265e3a00c183d78a (diff) |
upstream: add support for reading ED25519 private keys in PEM PKCS8
format; ok markus@ tb@
OpenBSD-Commit-ID: 01b85c91757e6b057e9b23b8a23f96415c3c7174
-rw-r--r-- | configure.ac | 24 | ||||
-rw-r--r-- | sshkey.c | 39 |
2 files changed, 61 insertions, 2 deletions
diff --git a/configure.ac b/configure.ac index d8816e3f..0f457f3b 100644 --- a/configure.ac +++ b/configure.ac @@ -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(). @@ -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, |