From aa22c20e0c36c2fc610cfcc793b0d14079c38814 Mon Sep 17 00:00:00 2001 From: "djm@openbsd.org" Date: Sun, 20 Jan 2019 22:03:29 +0000 Subject: upstream: add option to test whether keys in an agent are usable, by performing a signature and a verification using each key "ssh-add -T pubkey [...]" work by markus@, ok djm@ OpenBSD-Commit-ID: 931b888a600b6a883f65375bd5f73a4776c6d19b --- ssh-add.c | 52 +++++++++++++++++++++++++++++++++++++++++++++++++--- 1 file changed, 49 insertions(+), 3 deletions(-) (limited to 'ssh-add.c') diff --git a/ssh-add.c b/ssh-add.c index 50165e7d..eb2552ad 100644 --- a/ssh-add.c +++ b/ssh-add.c @@ -1,4 +1,4 @@ -/* $OpenBSD: ssh-add.c,v 1.136 2018/09/19 02:03:02 djm Exp $ */ +/* $OpenBSD: ssh-add.c,v 1.137 2019/01/20 22:03:29 djm Exp $ */ /* * Author: Tatu Ylonen * Copyright (c) 1995 Tatu Ylonen , Espoo, Finland @@ -417,6 +417,40 @@ update_card(int agent_fd, int add, const char *id, int qflag) return ret; } +static int +test_key(int agent_fd, const char *filename) +{ + struct sshkey *key = NULL; + u_char *sig = NULL; + size_t slen = 0; + int r, ret = -1; + char data[1024]; + + if ((r = sshkey_load_public(filename, &key, NULL)) != 0) { + error("Couldn't read public key %s: %s", filename, ssh_err(r)); + return -1; + } + arc4random_buf(data, sizeof(data)); + if ((r = ssh_agent_sign(agent_fd, key, &sig, &slen, data, sizeof(data), + NULL, 0)) != 0) { + error("Agent signature failed for %s: %s", + filename, ssh_err(r)); + goto done; + } + if ((r = sshkey_verify(key, sig, slen, data, sizeof(data), + NULL, 0)) != 0) { + error("Signature verification failed for %s: %s", + filename, ssh_err(r)); + goto done; + } + /* success */ + ret = 0; + done: + free(sig); + sshkey_free(key); + return ret; +} + static int list_identities(int agent_fd, int do_fp) { @@ -524,6 +558,7 @@ usage(void) fprintf(stderr, " -X Unlock agent.\n"); fprintf(stderr, " -s pkcs11 Add keys from PKCS#11 provider.\n"); fprintf(stderr, " -e pkcs11 Remove keys provided by PKCS#11 provider.\n"); + fprintf(stderr, " -T pubkey Test if ssh-agent can access matching private key.\n"); fprintf(stderr, " -q Be quiet after a successful operation.\n"); } @@ -535,7 +570,7 @@ main(int argc, char **argv) int agent_fd; char *pkcs11provider = NULL; int r, i, ch, deleting = 0, ret = 0, key_only = 0; - int xflag = 0, lflag = 0, Dflag = 0, qflag = 0; + int xflag = 0, lflag = 0, Dflag = 0, qflag = 0, Tflag = 0; ssh_malloc_init(); /* must be called before any mallocs */ /* Ensure that fds 0, 1 and 2 are open or directed to /dev/null */ @@ -559,7 +594,7 @@ main(int argc, char **argv) exit(2); } - while ((ch = getopt(argc, argv, "klLcdDxXE:e:M:m:qs:t:")) != -1) { + while ((ch = getopt(argc, argv, "klLcdDTxXE:e:M:m:qs:t:")) != -1) { switch (ch) { case 'E': fingerprint_hash = ssh_digest_alg_by_name(optarg); @@ -623,6 +658,9 @@ main(int argc, char **argv) case 'q': qflag = 1; break; + case 'T': + Tflag = 1; + break; default: usage(); ret = 1; @@ -648,6 +686,14 @@ main(int argc, char **argv) argc -= optind; argv += optind; + if (Tflag) { + if (argc <= 0) + fatal("no keys to test"); + for (r = i = 0; i < argc; i++) + r |= test_key(agent_fd, argv[i]); + ret = r == 0 ? 0 : 1; + goto done; + } if (pkcs11provider != NULL) { if (update_card(agent_fd, !deleting, pkcs11provider, qflag) == -1) -- cgit v1.2.1