[openssh-commits] [openssh] 02/07: upstream: Add new structure for signature options

git+noreply at mindrot.org git+noreply at mindrot.org
Mon Nov 25 12:26:01 AEDT 2019


This is an automated email from the git hooks/post-receive script.

djm pushed a commit to branch master
in repository openssh.

commit b7e74ea072919b31391bc0f5ff653f80b9f5e84f
Author: djm at openbsd.org <djm at openbsd.org>
Date:   Mon Nov 25 00:51:37 2019 +0000

    upstream: Add new structure for signature options
    
    This is populated during signature verification with additional fields
    that are present in and covered by the signature. At the moment, it is
    only used to record security key-specific options, especially the flags
    field.
    
    with and ok markus@
    
    OpenBSD-Commit-ID: 338a1f0e04904008836130bedb9ece4faafd4e49
---
 auth2-hostbased.c |  4 ++--
 auth2-pubkey.c    | 11 +++++++++--
 clientloop.c      |  5 +++--
 kexgen.c          |  4 ++--
 kexgexc.c         |  4 ++--
 krl.c             |  4 ++--
 monitor.c         | 14 +++++++++++---
 monitor_wrap.c    | 23 +++++++++++++++++++----
 monitor_wrap.h    |  5 +++--
 ssh-add.c         |  4 ++--
 ssh-ecdsa-sk.c    | 21 ++++++++++++++++++---
 ssh-ed25519-sk.c  | 20 ++++++++++++++++++--
 ssh-keygen.c      | 13 ++++++++++---
 sshkey.c          | 19 ++++++++++++++-----
 sshkey.h          | 18 ++++++++++++++----
 sshsig.c          | 22 ++++++++++++++--------
 sshsig.h          |  6 ++++--
 17 files changed, 147 insertions(+), 50 deletions(-)

diff --git a/auth2-hostbased.c b/auth2-hostbased.c
index d4604708..5e9b7c65 100644
--- a/auth2-hostbased.c
+++ b/auth2-hostbased.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: auth2-hostbased.c,v 1.41 2019/09/06 04:53:27 djm Exp $ */
+/* $OpenBSD: auth2-hostbased.c,v 1.42 2019/11/25 00:51:37 djm Exp $ */
 /*
  * Copyright (c) 2000 Markus Friedl.  All rights reserved.
  *
@@ -151,7 +151,7 @@ userauth_hostbased(struct ssh *ssh)
 	if (PRIVSEP(hostbased_key_allowed(ssh, authctxt->pw, cuser,
 	    chost, key)) &&
 	    PRIVSEP(sshkey_verify(key, sig, slen,
-	    sshbuf_ptr(b), sshbuf_len(b), pkalg, ssh->compat)) == 0)
+	    sshbuf_ptr(b), sshbuf_len(b), pkalg, ssh->compat, NULL)) == 0)
 		authenticated = 1;
 
 	auth2_record_key(authctxt, authenticated, key);
diff --git a/auth2-pubkey.c b/auth2-pubkey.c
index df12c2c6..2b698670 100644
--- a/auth2-pubkey.c
+++ b/auth2-pubkey.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: auth2-pubkey.c,v 1.94 2019/09/06 04:53:27 djm Exp $ */
+/* $OpenBSD: auth2-pubkey.c,v 1.95 2019/11/25 00:51:37 djm Exp $ */
 /*
  * Copyright (c) 2000 Markus Friedl.  All rights reserved.
  *
@@ -98,6 +98,7 @@ userauth_pubkey(struct ssh *ssh)
 	int r, pktype;
 	int authenticated = 0;
 	struct sshauthopt *authopts = NULL;
+	struct sshkey_sig_details *sig_details = NULL;
 
 	if ((r = sshpkt_get_u8(ssh, &have_sig)) != 0 ||
 	    (r = sshpkt_get_cstring(ssh, &pkalg, NULL)) != 0 ||
@@ -213,9 +214,14 @@ userauth_pubkey(struct ssh *ssh)
 		    PRIVSEP(sshkey_verify(key, sig, slen,
 		    sshbuf_ptr(b), sshbuf_len(b),
 		    (ssh->compat & SSH_BUG_SIGTYPE) == 0 ? pkalg : NULL,
-		    ssh->compat)) == 0) {
+		    ssh->compat, &sig_details)) == 0) {
 			authenticated = 1;
 		}
+		if (sig_details != NULL) {
+			debug("%s: sk_counter = %u, sk_flags = 0x%02x",
+			    __func__, sig_details->sk_counter,
+			    sig_details->sk_flags);
+		}
 		auth2_record_key(authctxt, authenticated, key);
 	} else {
 		debug("%s: test pkalg %s pkblob %s%s%s",
@@ -266,6 +272,7 @@ done:
 	free(key_s);
 	free(ca_s);
 	free(sig);
+	sshkey_sig_details_free(sig_details);
 	return authenticated;
 }
 
diff --git a/clientloop.c b/clientloop.c
index 06850621..880abfda 100644
--- a/clientloop.c
+++ b/clientloop.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: clientloop.c,v 1.328 2019/11/13 04:47:52 deraadt Exp $ */
+/* $OpenBSD: clientloop.c,v 1.329 2019/11/25 00:51:37 djm Exp $ */
 /*
  * Author: Tatu Ylonen <ylo at cs.hut.fi>
  * Copyright (c) 1995 Tatu Ylonen <ylo at cs.hut.fi>, Espoo, Finland
@@ -2003,7 +2003,8 @@ client_global_hostkeys_private_confirm(struct ssh *ssh, int type,
 		    sshkey_type_plain(ctx->keys[i]->type) == KEY_RSA;
 		if ((r = sshkey_verify(ctx->keys[i], sig, siglen,
 		    sshbuf_ptr(signdata), sshbuf_len(signdata),
-		    use_kexsigtype ? ssh->kex->hostkey_alg : NULL, 0)) != 0) {
+		    use_kexsigtype ? ssh->kex->hostkey_alg : NULL, 0,
+		    NULL)) != 0) {
 			error("%s: server gave bad signature for %s key %zu",
 			    __func__, sshkey_type(ctx->keys[i]), i);
 			goto out;
diff --git a/kexgen.c b/kexgen.c
index bb996b50..69348b96 100644
--- a/kexgen.c
+++ b/kexgen.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: kexgen.c,v 1.3 2019/09/06 05:23:55 djm Exp $ */
+/* $OpenBSD: kexgen.c,v 1.4 2019/11/25 00:51:37 djm Exp $ */
 /*
  * Copyright (c) 2019 Markus Friedl.  All rights reserved.
  *
@@ -212,7 +212,7 @@ input_kex_gen_reply(int type, u_int32_t seq, struct ssh *ssh)
 		goto out;
 
 	if ((r = sshkey_verify(server_host_key, signature, slen, hash, hashlen,
-	    kex->hostkey_alg, ssh->compat)) != 0)
+	    kex->hostkey_alg, ssh->compat, NULL)) != 0)
 		goto out;
 
 	if ((r = kex_derive_keys(ssh, hash, hashlen, shared_secret)) == 0)
diff --git a/kexgexc.c b/kexgexc.c
index 1c65b8a1..323a659b 100644
--- a/kexgexc.c
+++ b/kexgexc.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: kexgexc.c,v 1.34 2019/01/23 00:30:41 djm Exp $ */
+/* $OpenBSD: kexgexc.c,v 1.35 2019/11/25 00:51:37 djm Exp $ */
 /*
  * Copyright (c) 2000 Niels Provos.  All rights reserved.
  * Copyright (c) 2001 Markus Friedl.  All rights reserved.
@@ -199,7 +199,7 @@ input_kex_dh_gex_reply(int type, u_int32_t seq, struct ssh *ssh)
 		goto out;
 
 	if ((r = sshkey_verify(server_host_key, signature, slen, hash,
-	    hashlen, kex->hostkey_alg, ssh->compat)) != 0)
+	    hashlen, kex->hostkey_alg, ssh->compat, NULL)) != 0)
 		goto out;
 
 	if ((r = kex_derive_keys(ssh, hash, hashlen, shared_secret)) == 0)
diff --git a/krl.c b/krl.c
index 89cb433b..aa8318cf 100644
--- a/krl.c
+++ b/krl.c
@@ -14,7 +14,7 @@
  * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
  */
 
-/* $OpenBSD: krl.c,v 1.45 2019/10/31 21:23:19 djm Exp $ */
+/* $OpenBSD: krl.c,v 1.46 2019/11/25 00:51:37 djm Exp $ */
 
 #include "includes.h"
 
@@ -1079,7 +1079,7 @@ ssh_krl_from_blob(struct sshbuf *buf, struct ssh_krl **krlp,
 		}
 		/* Check signature over entire KRL up to this point */
 		if ((r = sshkey_verify(key, blob, blen,
-		    sshbuf_ptr(buf), sig_off, NULL, 0)) != 0)
+		    sshbuf_ptr(buf), sig_off, NULL, 0, NULL)) != 0)
 			goto out;
 		/* Check if this key has already signed this KRL */
 		for (i = 0; i < nca_used; i++) {
diff --git a/monitor.c b/monitor.c
index 1186c1dd..40ff43ee 100644
--- a/monitor.c
+++ b/monitor.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: monitor.c,v 1.201 2019/11/19 22:21:15 djm Exp $ */
+/* $OpenBSD: monitor.c,v 1.202 2019/11/25 00:51:37 djm Exp $ */
 /*
  * Copyright 2002 Niels Provos <provos at citi.umich.edu>
  * Copyright 2002 Markus Friedl <markus at openbsd.org>
@@ -1391,6 +1391,7 @@ mm_answer_keyverify(struct ssh *ssh, int sock, struct sshbuf *m)
 	char *sigalg;
 	size_t signaturelen, datalen, bloblen;
 	int r, ret, valid_data = 0, encoded_ret;
+	struct sshkey_sig_details *sig_details = NULL;
 
 	if ((r = sshbuf_get_string(m, &blob, &bloblen)) != 0 ||
 	    (r = sshbuf_get_string(m, &signature, &signaturelen)) != 0 ||
@@ -1430,7 +1431,7 @@ mm_answer_keyverify(struct ssh *ssh, int sock, struct sshbuf *m)
 		fatal("%s: bad signature data blob", __func__);
 
 	ret = sshkey_verify(key, signature, signaturelen, data, datalen,
-	    sigalg, ssh->compat);
+	    sigalg, ssh->compat, &sig_details);
 	debug3("%s: %s %p signature %s%s%s", __func__, auth_method, key,
 	    (ret == 0) ? "verified" : "unverified",
 	    (ret != 0) ? ": " : "", (ret != 0) ? ssh_err(ret) : "");
@@ -1450,8 +1451,15 @@ mm_answer_keyverify(struct ssh *ssh, int sock, struct sshbuf *m)
 
 	/* encode ret != 0 as positive integer, since we're sending u32 */
 	encoded_ret = (ret != 0);
-	if ((r = sshbuf_put_u32(m, encoded_ret)) != 0)
+	if ((r = sshbuf_put_u32(m, encoded_ret)) != 0 ||
+	    (r = sshbuf_put_u8(m, sig_details != NULL != 0)) != 0)
 		fatal("%s: buffer error: %s", __func__, ssh_err(r));
+	if (sig_details != NULL) {
+		if ((r = sshbuf_put_u32(m, sig_details->sk_counter)) != 0 ||
+		    (r = sshbuf_put_u8(m, sig_details->sk_flags)) != 0)
+			fatal("%s: buffer error: %s", __func__, ssh_err(r));
+	}
+	sshkey_sig_details_free(sig_details);
 	mm_request_send(sock, MONITOR_ANS_KEYVERIFY, m);
 
 	return ret == 0;
diff --git a/monitor_wrap.c b/monitor_wrap.c
index 5b42c0e5..06599e3b 100644
--- a/monitor_wrap.c
+++ b/monitor_wrap.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: monitor_wrap.c,v 1.115 2019/11/18 16:10:05 naddy Exp $ */
+/* $OpenBSD: monitor_wrap.c,v 1.116 2019/11/25 00:51:37 djm Exp $ */
 /*
  * Copyright 2002 Niels Provos <provos at citi.umich.edu>
  * Copyright 2002 Markus Friedl <markus at openbsd.org>
@@ -495,15 +495,19 @@ mm_key_allowed(enum mm_keytype type, const char *user, const char *host,
 
 int
 mm_sshkey_verify(const struct sshkey *key, const u_char *sig, size_t siglen,
-    const u_char *data, size_t datalen, const char *sigalg, u_int compat)
+    const u_char *data, size_t datalen, const char *sigalg, u_int compat,
+    struct sshkey_sig_details **sig_detailsp)
 {
 	struct sshbuf *m;
 	u_int encoded_ret = 0;
 	int r;
+	u_char sig_details_present, flags;
+	u_int counter;
 
 	debug3("%s entering", __func__);
 
-
+	if (sig_detailsp != NULL)
+		*sig_detailsp = NULL;
 	if ((m = sshbuf_new()) == NULL)
 		fatal("%s: sshbuf_new failed", __func__);
 	if ((r = sshkey_puts(key, m)) != 0 ||
@@ -518,8 +522,19 @@ mm_sshkey_verify(const struct sshkey *key, const u_char *sig, size_t siglen,
 	mm_request_receive_expect(pmonitor->m_recvfd,
 	    MONITOR_ANS_KEYVERIFY, m);
 
-	if ((r = sshbuf_get_u32(m, &encoded_ret)) != 0)
+	if ((r = sshbuf_get_u32(m, &encoded_ret)) != 0 ||
+	    (r = sshbuf_get_u8(m, &sig_details_present)) != 0)
 		fatal("%s: buffer error: %s", __func__, ssh_err(r));
+	if (sig_details_present && encoded_ret == 0) {
+		if ((r = sshbuf_get_u32(m, &counter)) != 0 ||
+		    (r = sshbuf_get_u8(m, &flags)) != 0)
+			fatal("%s: buffer error: %s", __func__, ssh_err(r));
+		if (sig_detailsp != NULL) {
+			*sig_detailsp = xcalloc(1, sizeof(**sig_detailsp));
+			(*sig_detailsp)->sk_counter = counter;
+			(*sig_detailsp)->sk_flags = flags;
+		}
+	}
 
 	sshbuf_free(m);
 
diff --git a/monitor_wrap.h b/monitor_wrap.h
index 76330fc6..23ab096a 100644
--- a/monitor_wrap.h
+++ b/monitor_wrap.h
@@ -1,4 +1,4 @@
-/* $OpenBSD: monitor_wrap.h,v 1.43 2019/10/31 21:23:19 djm Exp $ */
+/* $OpenBSD: monitor_wrap.h,v 1.44 2019/11/25 00:51:37 djm Exp $ */
 
 /*
  * Copyright 2002 Niels Provos <provos at citi.umich.edu>
@@ -38,6 +38,7 @@ struct monitor;
 struct Authctxt;
 struct sshkey;
 struct sshauthopt;
+struct sshkey_sig_details;
 
 void mm_log_handler(LogLevel, const char *, void *);
 int mm_is_monitor(void);
@@ -57,7 +58,7 @@ int mm_user_key_allowed(struct ssh *, struct passwd *, struct sshkey *, int,
 int mm_hostbased_key_allowed(struct ssh *, struct passwd *, const char *,
     const char *, struct sshkey *);
 int mm_sshkey_verify(const struct sshkey *, const u_char *, size_t,
-    const u_char *, size_t, const char *, u_int);
+    const u_char *, size_t, const char *, u_int, struct sshkey_sig_details **);
 
 #ifdef GSSAPI
 OM_uint32 mm_ssh_gssapi_server_ctx(Gssctxt **, gss_OID);
diff --git a/ssh-add.c b/ssh-add.c
index 6b1962bc..1d85e9d6 100644
--- a/ssh-add.c
+++ b/ssh-add.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: ssh-add.c,v 1.146 2019/11/18 16:10:05 naddy Exp $ */
+/* $OpenBSD: ssh-add.c,v 1.147 2019/11/25 00:51:37 djm Exp $ */
 /*
  * Author: Tatu Ylonen <ylo at cs.hut.fi>
  * Copyright (c) 1995 Tatu Ylonen <ylo at cs.hut.fi>, Espoo, Finland
@@ -451,7 +451,7 @@ test_key(int agent_fd, const char *filename)
 		goto done;
 	}
 	if ((r = sshkey_verify(key, sig, slen, data, sizeof(data),
-	    NULL, 0)) != 0) {
+	    NULL, 0, NULL)) != 0) {
 		error("Signature verification failed for %s: %s",
 		    filename, ssh_err(r));
 		goto done;
diff --git a/ssh-ecdsa-sk.c b/ssh-ecdsa-sk.c
index f33fac71..b2f31ae2 100644
--- a/ssh-ecdsa-sk.c
+++ b/ssh-ecdsa-sk.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: ssh-ecdsa-sk.c,v 1.3 2019/11/25 00:38:17 djm Exp $ */
+/* $OpenBSD: ssh-ecdsa-sk.c,v 1.4 2019/11/25 00:51:37 djm Exp $ */
 /*
  * Copyright (c) 2000 Markus Friedl.  All rights reserved.
  * Copyright (c) 2010 Damien Miller.  All rights reserved.
@@ -53,7 +53,8 @@
 int
 ssh_ecdsa_sk_verify(const struct sshkey *key,
     const u_char *signature, size_t signaturelen,
-    const u_char *data, size_t datalen, u_int compat)
+    const u_char *data, size_t datalen, u_int compat,
+    struct sshkey_sig_details **detailsp)
 {
 	ECDSA_SIG *sig = NULL;
 	BIGNUM *sig_r = NULL, *sig_s = NULL;
@@ -63,10 +64,13 @@ ssh_ecdsa_sk_verify(const struct sshkey *key,
 	int ret = SSH_ERR_INTERNAL_ERROR;
 	struct sshbuf *b = NULL, *sigbuf = NULL, *original_signed = NULL;
 	char *ktype = NULL;
+	struct sshkey_sig_details *details = NULL;
 #ifdef DEBUG_SK
 	char *tmp = NULL;
 #endif
 
+	if (detailsp != NULL)
+		*detailsp = NULL;
 	if (key == NULL || key->ecdsa == NULL ||
 	    sshkey_type_plain(key->type) != KEY_ECDSA_SK ||
 	    signature == NULL || signaturelen == 0)
@@ -149,6 +153,12 @@ ssh_ecdsa_sk_verify(const struct sshkey *key,
 	if ((ret = ssh_digest_buffer(SSH_DIGEST_SHA256, original_signed,
 	    sighash, sizeof(sighash))) != 0)
 		goto out;
+	if ((details = calloc(1, sizeof(*details))) == NULL) {
+		ret = SSH_ERR_ALLOC_FAIL;
+		goto out;
+	}
+	details->sk_counter = sig_counter;
+	details->sk_flags = sig_flags;
 #ifdef DEBUG_SK
 	fprintf(stderr, "%s: signed buf:\n", __func__);
 	sshbuf_dump(original_signed, stderr);
@@ -168,13 +178,18 @@ ssh_ecdsa_sk_verify(const struct sshkey *key,
 		ret = SSH_ERR_LIBCRYPTO_ERROR;
 		goto out;
 	}
-
+	/* success */
+	if (detailsp != NULL) {
+		*detailsp = details;
+		details = NULL;
+	}
  out:
 	explicit_bzero(&sig_flags, sizeof(sig_flags));
 	explicit_bzero(&sig_counter, sizeof(sig_counter));
 	explicit_bzero(msghash, sizeof(msghash));
 	explicit_bzero(sighash, sizeof(msghash));
 	explicit_bzero(apphash, sizeof(apphash));
+	sshkey_sig_details_free(details);
 	sshbuf_free(original_signed);
 	sshbuf_free(sigbuf);
 	sshbuf_free(b);
diff --git a/ssh-ed25519-sk.c b/ssh-ed25519-sk.c
index 622cb45c..d11fde6f 100644
--- a/ssh-ed25519-sk.c
+++ b/ssh-ed25519-sk.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: ssh-ed25519-sk.c,v 1.2 2019/11/12 19:34:40 markus Exp $ */
+/* $OpenBSD: ssh-ed25519-sk.c,v 1.3 2019/11/25 00:51:37 djm Exp $ */
 /*
  * Copyright (c) 2019 Markus Friedl.  All rights reserved.
  *
@@ -33,7 +33,8 @@
 int
 ssh_ed25519_sk_verify(const struct sshkey *key,
     const u_char *signature, size_t signaturelen,
-    const u_char *data, size_t datalen, u_int compat)
+    const u_char *data, size_t datalen, u_int compat,
+    struct sshkey_sig_details **detailsp)
 {
 	struct sshbuf *b = NULL;
 	struct sshbuf *encoded = NULL;
@@ -49,6 +50,10 @@ ssh_ed25519_sk_verify(const struct sshkey *key,
 	unsigned long long smlen = 0, mlen = 0;
 	int r = SSH_ERR_INTERNAL_ERROR;
 	int ret;
+	struct sshkey_sig_details *details = NULL;
+
+	if (detailsp != NULL)
+		*detailsp = NULL;
 
 	if (key == NULL ||
 	    sshkey_type_plain(key->type) != KEY_ED25519_SK ||
@@ -84,6 +89,12 @@ ssh_ed25519_sk_verify(const struct sshkey *key,
 		r = SSH_ERR_INVALID_ARGUMENT;
 		goto out;
 	}
+	if ((details = calloc(1, sizeof(*details))) == NULL) {
+		r = SSH_ERR_ALLOC_FAIL;
+		goto out;
+	}
+	details->sk_counter = sig_counter;
+	details->sk_flags = sig_flags;
 	if ((encoded = sshbuf_new()) == NULL) {
 		r = SSH_ERR_ALLOC_FAIL;
 		goto out;
@@ -115,11 +126,16 @@ ssh_ed25519_sk_verify(const struct sshkey *key,
 	/* XXX compare 'm' and 'sm + len' ? */
 	/* success */
 	r = 0;
+	if (detailsp != NULL) {
+		*detailsp = details;
+		details = NULL;
+	}
  out:
 	if (m != NULL) {
 		explicit_bzero(m, smlen); /* NB mlen may be invalid if r != 0 */
 		free(m);
 	}
+	sshkey_sig_details_free(details);
 	sshbuf_free(b);
 	sshbuf_free(encoded);
 	free(ktype);
diff --git a/ssh-keygen.c b/ssh-keygen.c
index e869989d..08dd7cb8 100644
--- a/ssh-keygen.c
+++ b/ssh-keygen.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: ssh-keygen.c,v 1.369 2019/11/18 23:16:49 naddy Exp $ */
+/* $OpenBSD: ssh-keygen.c,v 1.370 2019/11/25 00:51:37 djm Exp $ */
 /*
  * Author: Tatu Ylonen <ylo at cs.hut.fi>
  * Copyright (c) 1994 Tatu Ylonen <ylo at cs.hut.fi>, Espoo, Finland
@@ -584,7 +584,7 @@ do_convert_private_ssh2(struct sshbuf *b)
 	if (sshkey_sign(key, &sig, &slen, data, sizeof(data),
 	    NULL, NULL, 0) != 0 ||
 	    sshkey_verify(key, sig, slen, data, sizeof(data),
-	    NULL, 0) != 0) {
+	    NULL, 0, NULL) != 0) {
 		sshkey_free(key);
 		free(sig);
 		return NULL;
@@ -2657,7 +2657,9 @@ verify(const char *signature, const char *sig_namespace, const char *principal,
 	struct sshbuf *sigbuf = NULL, *abuf = NULL;
 	struct sshkey *sign_key = NULL;
 	char *fp = NULL;
+	struct sshkey_sig_details *sig_details = NULL;
 
+	memset(&sig_details, 0, sizeof(sig_details));
 	if ((abuf = sshbuf_new()) == NULL)
 		fatal("%s: sshbuf_new() failed", __func__);
 
@@ -2675,13 +2677,17 @@ verify(const char *signature, const char *sig_namespace, const char *principal,
 		return r;
 	}
 	if ((r = sshsig_verify_fd(sigbuf, STDIN_FILENO, sig_namespace,
-	    &sign_key)) != 0)
+	    &sign_key, &sig_details)) != 0)
 		goto done; /* sshsig_verify() prints error */
 
 	if ((fp = sshkey_fingerprint(sign_key, fingerprint_hash,
 	    SSH_FP_DEFAULT)) == NULL)
 		fatal("%s: sshkey_fingerprint failed", __func__);
 	debug("Valid (unverified) signature from key %s", fp);
+	if (sig_details != NULL) {
+		debug2("%s: signature details: counter = %u, flags = 0x%02x",
+		    __func__, sig_details->sk_counter, sig_details->sk_flags);
+	}
 	free(fp);
 	fp = NULL;
 
@@ -2726,6 +2732,7 @@ done:
 	sshbuf_free(sigbuf);
 	sshbuf_free(abuf);
 	sshkey_free(sign_key);
+	sshkey_sig_details_free(sig_details);
 	free(fp);
 	return ret;
 }
diff --git a/sshkey.c b/sshkey.c
index 48dd8bea..920c0dc3 100644
--- a/sshkey.c
+++ b/sshkey.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: sshkey.c,v 1.95 2019/11/18 06:58:00 djm Exp $ */
+/* $OpenBSD: sshkey.c,v 1.96 2019/11/25 00:51:37 djm Exp $ */
 /*
  * Copyright (c) 2000, 2001 Markus Friedl.  All rights reserved.
  * Copyright (c) 2008 Alexander von Gernler.  All rights reserved.
@@ -2301,7 +2301,7 @@ cert_parse(struct sshbuf *b, struct sshkey *key, struct sshbuf *certbuf)
 		goto out;
 	}
 	if ((ret = sshkey_verify(key->cert->signature_key, sig, slen,
-	    sshbuf_ptr(key->cert->certblob), signed_len, NULL, 0)) != 0)
+	    sshbuf_ptr(key->cert->certblob), signed_len, NULL, 0, NULL)) != 0)
 		goto out;
 	if ((ret = sshkey_get_sigtype(sig, slen,
 	    &key->cert->signature_type)) != 0)
@@ -2796,8 +2796,11 @@ sshkey_sign(struct sshkey *key,
 int
 sshkey_verify(const struct sshkey *key,
     const u_char *sig, size_t siglen,
-    const u_char *data, size_t dlen, const char *alg, u_int compat)
+    const u_char *data, size_t dlen, const char *alg, u_int compat,
+    struct sshkey_sig_details **detailsp)
 {
+	if (detailsp != NULL)
+		*detailsp = NULL;
 	if (siglen == 0 || dlen > SSH_KEY_MAX_SIGN_DATA_SIZE)
 		return SSH_ERR_INVALID_ARGUMENT;
 	switch (key->type) {
@@ -2813,7 +2816,7 @@ sshkey_verify(const struct sshkey *key,
 	case KEY_ECDSA_SK_CERT:
 	case KEY_ECDSA_SK:
 		return ssh_ecdsa_sk_verify(key, sig, siglen, data, dlen,
-		    compat);
+		    compat, detailsp);
 #  endif /* ENABLE_SK */
 # endif /* OPENSSL_HAS_ECC */
 	case KEY_RSA_CERT:
@@ -2826,7 +2829,7 @@ sshkey_verify(const struct sshkey *key,
 	case KEY_ED25519_SK:
 	case KEY_ED25519_SK_CERT:
 		return ssh_ed25519_sk_verify(key, sig, siglen, data, dlen,
-		    compat);
+		    compat, detailsp);
 #ifdef WITH_XMSS
 	case KEY_XMSS:
 	case KEY_XMSS_CERT:
@@ -4661,6 +4664,12 @@ sshkey_parse_private_fileblob(struct sshbuf *buffer, const char *passphrase,
 	    passphrase, keyp, commentp);
 }
 
+void
+sshkey_sig_details_free(struct sshkey_sig_details *details)
+{
+	freezero(details, sizeof(*details));
+}
+
 #ifdef WITH_XMSS
 /*
  * serialize the key with the current state and forward the state
diff --git a/sshkey.h b/sshkey.h
index a34a4cb4..56c0a9cd 100644
--- a/sshkey.h
+++ b/sshkey.h
@@ -1,4 +1,4 @@
-/* $OpenBSD: sshkey.h,v 1.39 2019/11/13 07:53:10 markus Exp $ */
+/* $OpenBSD: sshkey.h,v 1.40 2019/11/25 00:51:37 djm Exp $ */
 
 /*
  * Copyright (c) 2000, 2001 Markus Friedl.  All rights reserved.
@@ -156,6 +156,12 @@ struct sshkey {
 #define	ED25519_SK_SZ	crypto_sign_ed25519_SECRETKEYBYTES
 #define	ED25519_PK_SZ	crypto_sign_ed25519_PUBLICKEYBYTES
 
+/* Additional fields contained in signature */
+struct sshkey_sig_details {
+	uint32_t sk_counter;	/* U2F signature counter */
+	uint8_t sk_flags;	/* U2F signature flags; see ssh-sk.h */
+};
+
 struct sshkey	*sshkey_new(int);
 void		 sshkey_free(struct sshkey *);
 int		 sshkey_equal_public(const struct sshkey *,
@@ -230,7 +236,7 @@ int	 sshkey_putb_plain(const struct sshkey *, struct sshbuf *);
 int	 sshkey_sign(struct sshkey *, u_char **, size_t *,
     const u_char *, size_t, const char *, const char *, u_int);
 int	 sshkey_verify(const struct sshkey *, const u_char *, size_t,
-    const u_char *, size_t, const char *, u_int);
+    const u_char *, size_t, const char *, u_int, struct sshkey_sig_details **);
 int	 sshkey_check_sigtype(const u_char *, size_t, const char *);
 const char *sshkey_sigalg_by_name(const char *);
 int	 sshkey_get_sigtype(const u_char *, size_t, char **);
@@ -270,6 +276,8 @@ int	 sshkey_forward_state(const struct sshkey *, u_int32_t, sshkey_printfn *);
 int	 sshkey_private_serialize_maxsign(struct sshkey *key, struct sshbuf *buf,
     u_int32_t maxsign, sshkey_printfn *pr);
 
+void	 sshkey_sig_details_free(struct sshkey_sig_details *);
+
 #ifdef SSHKEY_INTERNAL
 int ssh_rsa_sign(const struct sshkey *key,
     u_char **sigp, size_t *lenp, const u_char *data, size_t datalen,
@@ -289,7 +297,8 @@ int ssh_ecdsa_verify(const struct sshkey *key,
     const u_char *data, size_t datalen, u_int compat);
 int ssh_ecdsa_sk_verify(const struct sshkey *key,
     const u_char *signature, size_t signaturelen,
-    const u_char *data, size_t datalen, u_int compat);
+    const u_char *data, size_t datalen, u_int compat,
+    struct sshkey_sig_details **detailsp);
 int ssh_ed25519_sign(const struct sshkey *key, u_char **sigp, size_t *lenp,
     const u_char *data, size_t datalen, u_int compat);
 int ssh_ed25519_verify(const struct sshkey *key,
@@ -297,7 +306,8 @@ int ssh_ed25519_verify(const struct sshkey *key,
     const u_char *data, size_t datalen, u_int compat);
 int ssh_ed25519_sk_verify(const struct sshkey *key,
     const u_char *signature, size_t signaturelen,
-    const u_char *data, size_t datalen, u_int compat);
+    const u_char *data, size_t datalen, u_int compat,
+    struct sshkey_sig_details **detailsp);
 int ssh_xmss_sign(const struct sshkey *key, u_char **sigp, size_t *lenp,
     const u_char *data, size_t datalen, u_int compat);
 int ssh_xmss_verify(const struct sshkey *key,
diff --git a/sshsig.c b/sshsig.c
index 8c7aba1b..abba3f67 100644
--- a/sshsig.c
+++ b/sshsig.c
@@ -286,7 +286,7 @@ sshsig_peek_hashalg(struct sshbuf *signature, char **hashalgp)
 static int
 sshsig_wrap_verify(struct sshbuf *signature, const char *hashalg,
     const struct sshbuf *h_message, const char *expect_namespace,
-    struct sshkey **sign_keyp)
+    struct sshkey **sign_keyp, struct sshkey_sig_details **sig_details)
 {
 	int r = SSH_ERR_INTERNAL_ERROR;
 	struct sshbuf *buf = NULL, *toverify = NULL;
@@ -296,6 +296,8 @@ sshsig_wrap_verify(struct sshbuf *signature, const char *hashalg,
 	size_t siglen;
 
 	debug("%s: verify message length %zu", __func__, sshbuf_len(h_message));
+	if (sig_details != NULL)
+		*sig_details = NULL;
 	if (sign_keyp != NULL)
 		*sign_keyp = NULL;
 
@@ -361,7 +363,7 @@ sshsig_wrap_verify(struct sshbuf *signature, const char *hashalg,
 		}
 	}
 	if ((r = sshkey_verify(key, sig, siglen, sshbuf_ptr(toverify),
-	    sshbuf_len(toverify), NULL, 0)) != 0) {
+	    sshbuf_len(toverify), NULL, 0, sig_details)) != 0) {
 		error("Signature verification failed: %s", ssh_err(r));
 		goto done;
 	}
@@ -453,15 +455,17 @@ sshsig_signb(struct sshkey *key, const char *hashalg, const char *sk_provider,
 
 int
 sshsig_verifyb(struct sshbuf *signature, const struct sshbuf *message,
-    const char *expect_namespace, struct sshkey **sign_keyp)
+    const char *expect_namespace, struct sshkey **sign_keyp,
+    struct sshkey_sig_details **sig_details)
 {
 	struct sshbuf *b = NULL;
 	int r = SSH_ERR_INTERNAL_ERROR;
 	char *hashalg = NULL;
 
+	if (sig_details != NULL)
+		*sig_details = NULL;
 	if (sign_keyp != NULL)
 		*sign_keyp = NULL;
-
 	if ((r = sshsig_peek_hashalg(signature, &hashalg)) != 0)
 		return r;
 	debug("%s: signature made with hash \"%s\"", __func__, hashalg);
@@ -470,7 +474,7 @@ sshsig_verifyb(struct sshbuf *signature, const struct sshbuf *message,
 		goto out;
 	}
 	if ((r = sshsig_wrap_verify(signature, hashalg, b, expect_namespace,
-	    sign_keyp)) != 0)
+	    sign_keyp, sig_details)) != 0)
 		goto out;
 	/* success */
 	r = 0;
@@ -579,15 +583,17 @@ sshsig_sign_fd(struct sshkey *key, const char *hashalg, const char *sk_provider,
 
 int
 sshsig_verify_fd(struct sshbuf *signature, int fd,
-    const char *expect_namespace, struct sshkey **sign_keyp)
+    const char *expect_namespace, struct sshkey **sign_keyp,
+    struct sshkey_sig_details **sig_details)
 {
 	struct sshbuf *b = NULL;
 	int r = SSH_ERR_INTERNAL_ERROR;
 	char *hashalg = NULL;
 
+	if (sig_details != NULL)
+		*sig_details = NULL;
 	if (sign_keyp != NULL)
 		*sign_keyp = NULL;
-
 	if ((r = sshsig_peek_hashalg(signature, &hashalg)) != 0)
 		return r;
 	debug("%s: signature made with hash \"%s\"", __func__, hashalg);
@@ -596,7 +602,7 @@ sshsig_verify_fd(struct sshbuf *signature, int fd,
 		goto out;
 	}
 	if ((r = sshsig_wrap_verify(signature, hashalg, b, expect_namespace,
-	    sign_keyp)) != 0)
+	    sign_keyp, sig_details)) != 0)
 		goto out;
 	/* success */
 	r = 0;
diff --git a/sshsig.h b/sshsig.h
index 487db116..386c8b5d 100644
--- a/sshsig.h
+++ b/sshsig.h
@@ -20,6 +20,7 @@
 struct sshbuf;
 struct sshkey;
 struct sshsigopt;
+struct sshkey_sig_details;
 
 typedef int sshsig_signer(struct sshkey *, u_char **, size_t *,
     const u_char *, size_t, const char *, const char *, u_int, void *);
@@ -43,7 +44,7 @@ int sshsig_signb(struct sshkey *key, const char *hashalg,
  */
 int sshsig_verifyb(struct sshbuf *signature,
     const struct sshbuf *message, const char *sig_namespace,
-    struct sshkey **sign_keyp);
+    struct sshkey **sign_keyp, struct sshkey_sig_details **sig_details);
 
 /* File/FD-oriented API */
 
@@ -62,7 +63,8 @@ int sshsig_sign_fd(struct sshkey *key, const char *hashalg,
  * Returns 0 on success or a negative SSH_ERR_* error code on failure.
  */
 int sshsig_verify_fd(struct sshbuf *signature, int fd,
-    const char *sig_namespace, struct sshkey **sign_keyp);
+    const char *sig_namespace, struct sshkey **sign_keyp,
+    struct sshkey_sig_details **sig_details);
 
 /* Utility functions */
 

-- 
To stop receiving notification emails like this one, please contact
djm at mindrot.org.


More information about the openssh-commits mailing list