From b7e74ea072919b31391bc0f5ff653f80b9f5e84f Mon Sep 17 00:00:00 2001 From: "djm@openbsd.org" Date: Mon, 25 Nov 2019 00:51:37 +0000 Subject: 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 d46047084..5e9b7c65d 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 df12c2c60..2b6986709 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 068506210..880abfda2 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 * Copyright (c) 1995 Tatu Ylonen , 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 bb996b504..69348b964 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 1c65b8a18..323a659b7 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 89cb433bd..aa8318cf1 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 1186c1dd5..40ff43ee2 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 * Copyright 2002 Markus Friedl @@ -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 5b42c0e56..06599e3b1 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 * Copyright 2002 Markus Friedl @@ -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 76330fc60..23ab096aa 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 @@ -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 6b1962bc2..1d85e9d60 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 * Copyright (c) 1995 Tatu Ylonen , 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 f33fac714..b2f31ae2d 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 622cb45c2..d11fde6fd 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 e869989d7..08dd7cb8a 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 * Copyright (c) 1994 Tatu Ylonen , 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 48dd8bea9..920c0dc3c 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 a34a4cb48..56c0a9cdf 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 8c7aba1b9..abba3f67b 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 487db116c..386c8b5d7 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 */ -- cgit v1.2.3