[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