[openssh-commits] [openssh] 02/06: upstream: implement attestation verification for ED25519 keys
git+noreply at mindrot.org
git+noreply at mindrot.org
Mon Mar 3 18:18:03 AEDT 2025
This is an automated email from the git hooks/post-receive script.
dtucker pushed a commit to branch master
in repository openssh.
commit 396202180180a4ac16788d469508a348789dafa1
Author: djm at openbsd.org <djm at openbsd.org>
AuthorDate: Fri Dec 6 10:37:42 2024 +0000
upstream: implement attestation verification for ED25519 keys
OpenBSD-Regress-ID: c44fa5cdb434375a8b5545fdb4fc651061afca1f
---
.../ssh-verify-attestation.c | 93 ++++++++++++++++++----
1 file changed, 78 insertions(+), 15 deletions(-)
diff --git a/regress/misc/ssh-verify-attestation/ssh-verify-attestation.c b/regress/misc/ssh-verify-attestation/ssh-verify-attestation.c
index f12306a9..4d82a039 100644
--- a/regress/misc/ssh-verify-attestation/ssh-verify-attestation.c
+++ b/regress/misc/ssh-verify-attestation/ssh-verify-attestation.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: ssh-verify-attestation.c,v 1.1 2024/12/04 16:42:49 djm Exp $ */
+/* $OpenBSD: ssh-verify-attestation.c,v 1.2 2024/12/06 10:37:42 djm Exp $ */
/*
* Copyright (c) 2022-2024 Damien Miller
*
@@ -38,10 +38,11 @@
* 1) It doesn't automatically detect the attestation statement format. It
* assumes the "packed" format used by FIDO2 keys. If that doesn't work,
* then try using the -U option to select the "fido-u2f" format.
- * 2) Only ECDSA keys are currently supported. Ed25519 support is not yet
- * implemented.
+ * 2) It makes assumptions about RK, UV, etc status of the key/cred.
* 3) Probably bugs.
*
+ * Thanks to Markus Friedl and Pedro Martelletto for help getting this
+ * working.
*/
#include "includes.h"
@@ -61,6 +62,7 @@
#include "ssherr.h"
#include "misc.h"
#include "digest.h"
+#include "crypto_api.h"
#include <fido.h>
#include <openssl/x509.h>
@@ -103,12 +105,11 @@ prepare_fido_cred(fido_cred_t *cred, int credtype, const char *attfmt,
error_fr(r, "parse body");
goto out;
}
- debug3_f("blob len=%zu, attestation cert len=%zu, sig len=%zu, "
+ debug3_f("attestation cert len=%zu, sig len=%zu, "
"authdata len=%zu challenge len=%zu", sshbuf_len(attestation_cert),
- sshbuf_len(b), sshbuf_len(sig), sshbuf_len(authdata),
- sshbuf_len(challenge));
+ sshbuf_len(sig), sshbuf_len(authdata), sshbuf_len(challenge));
- fido_cred_set_type(cred, COSE_ES256);
+ fido_cred_set_type(cred, credtype);
fido_cred_set_fmt(cred, attfmt);
fido_cred_set_clientdata(cred, sshbuf_ptr(challenge),
sshbuf_len(challenge));
@@ -259,12 +260,63 @@ cred_matches_key_ecdsa(const fido_cred_t *cred, const struct sshkey *k)
return r;
}
+
+/* copied from sshsk_ed25519_assemble() */
+static int
+cred_matches_key_ed25519(const fido_cred_t *cred, const struct sshkey *k)
+{
+ struct sshkey *key = NULL;
+ const uint8_t *ptr;
+ int r = -1;
+
+ if ((ptr = fido_cred_pubkey_ptr(cred)) == NULL) {
+ error_f("fido_cred_pubkey_ptr failed");
+ goto out;
+ }
+ if (fido_cred_pubkey_len(cred) != ED25519_PK_SZ) {
+ error_f("bad fido_cred_pubkey_len %zu",
+ fido_cred_pubkey_len(cred));
+ goto out;
+ }
+
+ if ((key = sshkey_new(KEY_ED25519_SK)) == NULL) {
+ error_f("sshkey_new failed");
+ r = SSH_ERR_ALLOC_FAIL;
+ goto out;
+ }
+ if ((key->ed25519_pk = malloc(ED25519_PK_SZ)) == NULL) {
+ error_f("malloc failed");
+ r = SSH_ERR_ALLOC_FAIL;
+ goto out;
+ }
+ memcpy(key->ed25519_pk, ptr, ED25519_PK_SZ);
+ key->sk_application = xstrdup(k->sk_application); /* XXX */
+ if (!sshkey_equal_public(key, k)) {
+ error("sshkey_equal_public failed");
+ r = SSH_ERR_INVALID_ARGUMENT;
+ goto out;
+ }
+ r = 0; /* success */
+ out:
+ sshkey_free(key);
+ return r;
+}
+
static int
cred_matches_key(const fido_cred_t *cred, const struct sshkey *k)
{
switch (sshkey_type_plain(k->type)) {
case KEY_ECDSA_SK:
- return cred_matches_key_ecdsa(cred, k);
+ switch (k->ecdsa_nid) {
+ case NID_X9_62_prime256v1:
+ return cred_matches_key_ecdsa(cred, k);
+ break;
+ default:
+ fatal("Unsupported ECDSA key size");
+ }
+ break;
+ case KEY_ED25519_SK:
+ return cred_matches_key_ed25519(cred, k);
default:
error_f("key type %s not supported", sshkey_type(k));
return -1;
@@ -280,7 +332,7 @@ main(int argc, char **argv)
struct sshbuf *attestation = NULL, *challenge = NULL;
struct sshbuf *attestation_cert = NULL;
char *fp;
- const char *attfmt = "packed";
+ const char *attfmt = "packed", *style = NULL;
fido_cred_t *cred = NULL;
int write_attestation_cert = 0;
extern int optind;
@@ -335,7 +387,16 @@ main(int argc, char **argv)
switch (sshkey_type_plain(k->type)) {
case KEY_ECDSA_SK:
- credtype = COSE_ES256;
+ switch (k->ecdsa_nid) {
+ case NID_X9_62_prime256v1:
+ credtype = COSE_ES256;
+ break;
+ default:
+ fatal("Unsupported ECDSA key size");
+ }
+ break;
+ case KEY_ED25519_SK:
+ credtype = COSE_EDDSA;
break;
default:
fatal("unsupported key type %s", sshkey_type(k));
@@ -346,13 +407,15 @@ main(int argc, char **argv)
fatal_r(r, "prepare_fido_cred %s", argv[2]);
if (fido_cred_x5c_ptr(cred) != NULL) {
debug("basic attestation");
- r = fido_cred_verify(cred);
+ if ((r = fido_cred_verify(cred)) != FIDO_OK)
+ fatal("basic attestation failed");
+ style = "basic";
} else {
debug("self attestation");
- r = fido_cred_verify_self(cred);
+ if ((r = fido_cred_verify_self(cred)) != FIDO_OK)
+ fatal("self attestation failed");
+ style = "self";
}
- if (r != FIDO_OK)
- fatal("verification of attestation data failed");
if (cred_matches_key(cred, k) != 0)
fatal("cred authdata does not match key");
@@ -364,7 +427,7 @@ main(int argc, char **argv)
}
sshbuf_free(attestation_cert);
- logit("%s: GOOD", argv[2]);
+ logit("%s: verified %s attestation", argv[2], style);
return (0);
}
--
To stop receiving notification emails like this one, please contact
djm at mindrot.org.
More information about the openssh-commits
mailing list