]> git.ipfire.org Git - thirdparty/openssh-portable.git/commitdiff
upstream: Add new structure for signature options
authordjm@openbsd.org <djm@openbsd.org>
Mon, 25 Nov 2019 00:51:37 +0000 (00:51 +0000)
committerDamien Miller <djm@mindrot.org>
Mon, 25 Nov 2019 01:23:33 +0000 (12:23 +1100)
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

17 files changed:
auth2-hostbased.c
auth2-pubkey.c
clientloop.c
kexgen.c
kexgexc.c
krl.c
monitor.c
monitor_wrap.c
monitor_wrap.h
ssh-add.c
ssh-ecdsa-sk.c
ssh-ed25519-sk.c
ssh-keygen.c
sshkey.c
sshkey.h
sshsig.c
sshsig.h

index d4604708446331960d5dd8e68deb5b8a9a96f5a7..5e9b7c65d32561e1ae523b5557938a24850e5a90 100644 (file)
@@ -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);
index df12c2c60d7d5102e09c539968558b37d997fa2c..2b69867099f44d27a7d5d3c7e4bea6685d14e680 100644 (file)
@@ -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;
 }
 
index 06850621034a3dde691085dfd99aacf2c4cbbc47..880abfda211e481761683daf06f462c4c5cba253 100644 (file)
@@ -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@cs.hut.fi>
  * Copyright (c) 1995 Tatu Ylonen <ylo@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;
index bb996b504d3ac7a0d0e34dcadae18f7d214b0af8..69348b964df82ce547bb515dd8f356fba202c91e 100644 (file)
--- 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)
index 1c65b8a18016557a7d49a78c3d646115f22a5510..323a659b77c54ec069086f7cedf911afb4d33a15 100644 (file)
--- 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 89cb433bd3cbbbd72d7d936ddfef36e03edefab8..aa8318cf1fc6dd93716e5073585eeaee639d3d05 100644 (file)
--- 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++) {
index 1186c1dd555e3663831af468b35e4ad3a03a013c..40ff43ee25fc0742c7579e34363cf9637e7b77bb 100644 (file)
--- 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@citi.umich.edu>
  * Copyright 2002 Markus Friedl <markus@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;
index 5b42c0e56dc30f56a306f3182f1cffd04396eb49..06599e3b1f364ccfee3aeabb6ea6638738d84bfe 100644 (file)
@@ -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@citi.umich.edu>
  * Copyright 2002 Markus Friedl <markus@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);
 
index 76330fc60a76ad9ebdcf69b4b26fb4a0ef572879..23ab096aa6decbace4252f9c16cdd35c03f015cc 100644 (file)
@@ -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@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);
index 6b1962bc2cddad941d5d6e51471b23cc5febd13a..1d85e9d6084dee1d16532c440e3957fd2a153ff2 100644 (file)
--- 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@cs.hut.fi>
  * Copyright (c) 1995 Tatu Ylonen <ylo@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;
index f33fac7146be047e8059864db90f6608bb129538..b2f31ae2de84ae6a818c8530b73d9d131cf81a3c 100644 (file)
@@ -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);
index 622cb45c24539cf344069f089914929f2ad6aae9..d11fde6fda6f0ff8014b7c5af80e67504933426e 100644 (file)
@@ -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);
index e869989d7347c6308e0a4aad4342367ec262e246..08dd7cb8ace4fb92c5d1d7eb51efedc953600feb 100644 (file)
@@ -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@cs.hut.fi>
  * Copyright (c) 1994 Tatu Ylonen <ylo@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;
 }
index 48dd8bea905a67ce0229cbdc35e8616da357e9a8..920c0dc3c17c726c90728dddae298bd45f0962f6 100644 (file)
--- 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
index a34a4cb48578e99a3e5f17f44d8bef8adbf2099e..56c0a9cdf4ac6ca703b2c420045a09ce47e9d148 100644 (file)
--- 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,
index 8c7aba1b93f8fbc9e8ff2a923ce2d000b7b1c615..abba3f67b447be4fce685793d3f5bf8e23fdfda7 100644 (file)
--- 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;
index 487db116c1747641501880c5901ff1245d13e7d4..386c8b5d7997176a880dc7a6ddb063407261a2ba 100644 (file)
--- 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 */