summaryrefslogtreecommitdiff
path: root/ssh-add.c
diff options
context:
space:
mode:
authormarkus@openbsd.org <markus@openbsd.org>2018-02-23 15:58:37 +0000
committerDamien Miller <djm@mindrot.org>2018-02-26 11:40:41 +1100
commit1b11ea7c58cd5c59838b5fa574cd456d6047b2d4 (patch)
tree7e96cb41b5234b9d327f7c8f41392f09aed0994e /ssh-add.c
parent7d330a1ac02076de98cfc8fda05353d57b603755 (diff)
upstream: Add experimental support for PQC XMSS keys (Extended
Hash-Based Signatures) The code is not compiled in by default (see WITH_XMSS in Makefile.inc) Joint work with stefan-lukas_gazdag at genua.eu See https://tools.ietf.org/html/draft-irtf-cfrg-xmss-hash-based-signatures-12 ok djm@ OpenBSD-Commit-ID: ef3eccb96762a5d6f135d7daeef608df7776a7ac
Diffstat (limited to 'ssh-add.c')
-rw-r--r--ssh-add.c74
1 files changed, 69 insertions, 5 deletions
diff --git a/ssh-add.c b/ssh-add.c
index 2afd48330..adcc45998 100644
--- a/ssh-add.c
+++ b/ssh-add.c
@@ -1,4 +1,4 @@
1/* $OpenBSD: ssh-add.c,v 1.134 2017/08/29 09:42:29 dlg Exp $ */ 1/* $OpenBSD: ssh-add.c,v 1.135 2018/02/23 15:58:37 markus Exp $ */
2/* 2/*
3 * Author: Tatu Ylonen <ylo@cs.hut.fi> 3 * Author: Tatu Ylonen <ylo@cs.hut.fi>
4 * Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland 4 * Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
@@ -78,6 +78,7 @@ static char *default_files[] = {
78#endif 78#endif
79#endif /* WITH_OPENSSL */ 79#endif /* WITH_OPENSSL */
80 _PATH_SSH_CLIENT_ID_ED25519, 80 _PATH_SSH_CLIENT_ID_ED25519,
81 _PATH_SSH_CLIENT_ID_XMSS,
81 NULL 82 NULL
82}; 83};
83 84
@@ -89,6 +90,10 @@ static int lifetime = 0;
89/* User has to confirm key use */ 90/* User has to confirm key use */
90static int confirm = 0; 91static int confirm = 0;
91 92
93/* Maximum number of signatures (XMSS) */
94static u_int maxsign = 0;
95static u_int minleft = 0;
96
92/* we keep a cache of one passphrase */ 97/* we keep a cache of one passphrase */
93static char *pass = NULL; 98static char *pass = NULL;
94static void 99static void
@@ -190,7 +195,10 @@ add_file(int agent_fd, const char *filename, int key_only, int qflag)
190 char *comment = NULL; 195 char *comment = NULL;
191 char msg[1024], *certpath = NULL; 196 char msg[1024], *certpath = NULL;
192 int r, fd, ret = -1; 197 int r, fd, ret = -1;
198 size_t i;
199 u_int32_t left;
193 struct sshbuf *keyblob; 200 struct sshbuf *keyblob;
201 struct ssh_identitylist *idlist;
194 202
195 if (strcmp(filename, "-") == 0) { 203 if (strcmp(filename, "-") == 0) {
196 fd = STDIN_FILENO; 204 fd = STDIN_FILENO;
@@ -268,8 +276,40 @@ add_file(int agent_fd, const char *filename, int key_only, int qflag)
268 comment = xstrdup(filename); 276 comment = xstrdup(filename);
269 sshbuf_free(keyblob); 277 sshbuf_free(keyblob);
270 278
279 /* For XMSS */
280 if ((r = sshkey_set_filename(private, filename)) != 0) {
281 fprintf(stderr, "Could not add filename to private key: %s (%s)\n",
282 filename, comment);
283 goto out;
284 }
285 if (maxsign && minleft &&
286 (r = ssh_fetch_identitylist(agent_fd, &idlist)) == 0) {
287 for (i = 0; i < idlist->nkeys; i++) {
288 if (!sshkey_equal_public(idlist->keys[i], private))
289 continue;
290 left = sshkey_signatures_left(idlist->keys[i]);
291 if (left < minleft) {
292 fprintf(stderr,
293 "Only %d signatures left.\n", left);
294 break;
295 }
296 fprintf(stderr, "Skipping update: ");
297 if (left == minleft) {
298 fprintf(stderr,
299 "required signatures left (%d).\n", left);
300 } else {
301 fprintf(stderr,
302 "more signatures left (%d) than"
303 " required (%d).\n", left, minleft);
304 }
305 ssh_free_identitylist(idlist);
306 goto out;
307 }
308 ssh_free_identitylist(idlist);
309 }
310
271 if ((r = ssh_add_identity_constrained(agent_fd, private, comment, 311 if ((r = ssh_add_identity_constrained(agent_fd, private, comment,
272 lifetime, confirm)) == 0) { 312 lifetime, confirm, maxsign)) == 0) {
273 fprintf(stderr, "Identity added: %s (%s)\n", filename, comment); 313 fprintf(stderr, "Identity added: %s (%s)\n", filename, comment);
274 ret = 0; 314 ret = 0;
275 if (lifetime != 0) 315 if (lifetime != 0)
@@ -317,7 +357,7 @@ add_file(int agent_fd, const char *filename, int key_only, int qflag)
317 sshkey_free(cert); 357 sshkey_free(cert);
318 358
319 if ((r = ssh_add_identity_constrained(agent_fd, private, comment, 359 if ((r = ssh_add_identity_constrained(agent_fd, private, comment,
320 lifetime, confirm)) != 0) { 360 lifetime, confirm, maxsign)) != 0) {
321 error("Certificate %s (%s) add failed: %s", certpath, 361 error("Certificate %s (%s) add failed: %s", certpath,
322 private->cert->key_id, ssh_err(r)); 362 private->cert->key_id, ssh_err(r));
323 goto out; 363 goto out;
@@ -368,6 +408,7 @@ list_identities(int agent_fd, int do_fp)
368 char *fp; 408 char *fp;
369 int r; 409 int r;
370 struct ssh_identitylist *idlist; 410 struct ssh_identitylist *idlist;
411 u_int32_t left;
371 size_t i; 412 size_t i;
372 413
373 if ((r = ssh_fetch_identitylist(agent_fd, &idlist)) != 0) { 414 if ((r = ssh_fetch_identitylist(agent_fd, &idlist)) != 0) {
@@ -392,7 +433,12 @@ list_identities(int agent_fd, int do_fp)
392 ssh_err(r)); 433 ssh_err(r));
393 continue; 434 continue;
394 } 435 }
395 fprintf(stdout, " %s\n", idlist->comments[i]); 436 fprintf(stdout, " %s", idlist->comments[i]);
437 left = sshkey_signatures_left(idlist->keys[i]);
438 if (left > 0)
439 fprintf(stdout,
440 " [signatures left %d]", left);
441 fprintf(stdout, "\n");
396 } 442 }
397 } 443 }
398 ssh_free_identitylist(idlist); 444 ssh_free_identitylist(idlist);
@@ -454,6 +500,8 @@ usage(void)
454 fprintf(stderr, " -L List public key parameters of all identities.\n"); 500 fprintf(stderr, " -L List public key parameters of all identities.\n");
455 fprintf(stderr, " -k Load only keys and not certificates.\n"); 501 fprintf(stderr, " -k Load only keys and not certificates.\n");
456 fprintf(stderr, " -c Require confirmation to sign using identities\n"); 502 fprintf(stderr, " -c Require confirmation to sign using identities\n");
503 fprintf(stderr, " -m minleft Maxsign is only changed if less than minleft are left (for XMSS)\n");
504 fprintf(stderr, " -M maxsign Maximum number of signatures allowed (for XMSS)\n");
457 fprintf(stderr, " -t life Set lifetime (in seconds) when adding identities.\n"); 505 fprintf(stderr, " -t life Set lifetime (in seconds) when adding identities.\n");
458 fprintf(stderr, " -d Delete identity.\n"); 506 fprintf(stderr, " -d Delete identity.\n");
459 fprintf(stderr, " -D Delete all identities.\n"); 507 fprintf(stderr, " -D Delete all identities.\n");
@@ -500,7 +548,7 @@ main(int argc, char **argv)
500 exit(2); 548 exit(2);
501 } 549 }
502 550
503 while ((ch = getopt(argc, argv, "klLcdDxXE:e:qs:t:")) != -1) { 551 while ((ch = getopt(argc, argv, "klLcdDxXE:e:M:m:qs:t:")) != -1) {
504 switch (ch) { 552 switch (ch) {
505 case 'E': 553 case 'E':
506 fingerprint_hash = ssh_digest_alg_by_name(optarg); 554 fingerprint_hash = ssh_digest_alg_by_name(optarg);
@@ -525,6 +573,22 @@ main(int argc, char **argv)
525 case 'c': 573 case 'c':
526 confirm = 1; 574 confirm = 1;
527 break; 575 break;
576 case 'm':
577 minleft = (int)strtonum(optarg, 1, UINT_MAX, NULL);
578 if (minleft == 0) {
579 usage();
580 ret = 1;
581 goto done;
582 }
583 break;
584 case 'M':
585 maxsign = (int)strtonum(optarg, 1, UINT_MAX, NULL);
586 if (maxsign == 0) {
587 usage();
588 ret = 1;
589 goto done;
590 }
591 break;
528 case 'd': 592 case 'd':
529 deleting = 1; 593 deleting = 1;
530 break; 594 break;