diff --git a/ssh-add.1 b/ssh-add.1 index d4e1c603b..9dc44fa74 100644 --- a/ssh-add.1 +++ b/ssh-add.1 @@ -1,4 +1,4 @@ -.\" $OpenBSD: ssh-add.1,v 1.69 2019/01/21 12:53:35 djm Exp $ +.\" $OpenBSD: ssh-add.1,v 1.70 2019/10/31 21:19:56 djm Exp $ .\" .\" Author: Tatu Ylonen .\" Copyright (c) 1995 Tatu Ylonen , Espoo, Finland @@ -35,7 +35,7 @@ .\" (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF .\" THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. .\" -.Dd $Mdocdate: January 21 2019 $ +.Dd $Mdocdate: October 31 2019 $ .Dt SSH-ADD 1 .Os .Sh NAME @@ -46,6 +46,7 @@ .Op Fl cDdkLlqvXx .Op Fl E Ar fingerprint_hash .Op Fl t Ar life +.Op Fl S Ar provider .Op Ar .Nm ssh-add .Fl s Ar pkcs11 @@ -134,6 +135,11 @@ Be quiet after a successful operation. .It Fl s Ar pkcs11 Add keys provided by the PKCS#11 shared library .Ar pkcs11 . +.It Fl S Ar provider +Specifies a path to a security key provider library that will be used when +adding any security key-hosted keys, overriding the default of using the +.Ev "SSH_SK_PROVIDER" +environment variable to specify a provider. .It Fl T Ar pubkey ... Tests whether the private keys that correspond to the specified .Ar pubkey @@ -189,6 +195,9 @@ to make this work.) Identifies the path of a .Ux Ns -domain socket used to communicate with the agent. +.It Ev SSH_SK_PROVIDER +Specifies the path to a security key provider library used to interact with +hardware security keys. .El .Sh FILES .Bl -tag -width Ds diff --git a/ssh-add.c b/ssh-add.c index 2c65d0272..3c8849ac4 100644 --- a/ssh-add.c +++ b/ssh-add.c @@ -1,4 +1,4 @@ -/* $OpenBSD: ssh-add.c,v 1.142 2019/10/31 21:19:15 djm Exp $ */ +/* $OpenBSD: ssh-add.c,v 1.143 2019/10/31 21:19:56 djm Exp $ */ /* * Author: Tatu Ylonen * Copyright (c) 1995 Tatu Ylonen , Espoo, Finland @@ -77,6 +77,7 @@ static char *default_files[] = { _PATH_SSH_CLIENT_ID_DSA, #ifdef OPENSSL_HAS_ECC _PATH_SSH_CLIENT_ID_ECDSA, + _PATH_SSH_CLIENT_ID_ECDSA_SK, #endif #endif /* WITH_OPENSSL */ _PATH_SSH_CLIENT_ID_ED25519, @@ -191,7 +192,8 @@ delete_all(int agent_fd, int qflag) } static int -add_file(int agent_fd, const char *filename, int key_only, int qflag) +add_file(int agent_fd, const char *filename, int key_only, int qflag, + const char *skprovider) { struct sshkey *private, *cert; char *comment = NULL; @@ -310,8 +312,16 @@ add_file(int agent_fd, const char *filename, int key_only, int qflag) ssh_free_identitylist(idlist); } + if (sshkey_type_plain(private->type) != KEY_ECDSA_SK) + skprovider = NULL; /* Don't send constraint for other keys */ + else if (skprovider == NULL) { + fprintf(stderr, "Cannot load security key %s without " + "provider\n", filename); + goto out; + } + if ((r = ssh_add_identity_constrained(agent_fd, private, comment, - lifetime, confirm, maxsign, NULL)) == 0) { + lifetime, confirm, maxsign, skprovider)) == 0) { ret = 0; if (!qflag) { fprintf(stderr, "Identity added: %s (%s)\n", @@ -364,7 +374,7 @@ add_file(int agent_fd, const char *filename, int key_only, int qflag) sshkey_free(cert); if ((r = ssh_add_identity_constrained(agent_fd, private, comment, - lifetime, confirm, maxsign, NULL)) != 0) { + lifetime, confirm, maxsign, skprovider)) != 0) { error("Certificate %s (%s) add failed: %s", certpath, private->cert->key_id, ssh_err(r)); goto out; @@ -529,13 +539,14 @@ lock_agent(int agent_fd, int lock) } static int -do_file(int agent_fd, int deleting, int key_only, char *file, int qflag) +do_file(int agent_fd, int deleting, int key_only, char *file, int qflag, + const char *skprovider) { if (deleting) { if (delete_file(agent_fd, file, key_only, qflag) == -1) return -1; } else { - if (add_file(agent_fd, file, key_only, qflag) == -1) + if (add_file(agent_fd, file, key_only, qflag, skprovider) == -1) return -1; } return 0; @@ -561,6 +572,7 @@ usage(void) 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, " -S provider Specify security key provider.\n"); fprintf(stderr, " -q Be quiet after a successful operation.\n"); fprintf(stderr, " -v Be more verbose.\n"); } @@ -571,7 +583,7 @@ main(int argc, char **argv) extern char *optarg; extern int optind; int agent_fd; - char *pkcs11provider = NULL; + char *pkcs11provider = NULL, *skprovider = NULL; int r, i, ch, deleting = 0, ret = 0, key_only = 0; int xflag = 0, lflag = 0, Dflag = 0, qflag = 0, Tflag = 0; SyslogFacility log_facility = SYSLOG_FACILITY_AUTH; @@ -600,7 +612,9 @@ main(int argc, char **argv) exit(2); } - while ((ch = getopt(argc, argv, "vklLcdDTxXE:e:M:m:qs:t:")) != -1) { + skprovider = getenv("SSH_SK_PROVIDER"); + + while ((ch = getopt(argc, argv, "vklLcdDTxXE:e:M:m:qs:S:t:")) != -1) { switch (ch) { case 'v': if (log_level == SYSLOG_LEVEL_INFO) @@ -656,6 +670,9 @@ main(int argc, char **argv) case 's': pkcs11provider = optarg; break; + case 'S': + skprovider = optarg; + break; case 'e': deleting = 1; pkcs11provider = optarg; @@ -732,7 +749,7 @@ main(int argc, char **argv) if (stat(buf, &st) == -1) continue; if (do_file(agent_fd, deleting, key_only, buf, - qflag) == -1) + qflag, skprovider) == -1) ret = 1; else count++; @@ -742,7 +759,7 @@ main(int argc, char **argv) } else { for (i = 0; i < argc; i++) { if (do_file(agent_fd, deleting, key_only, - argv[i], qflag) == -1) + argv[i], qflag, skprovider) == -1) ret = 1; } }