jcs's openbsd hax
openbsd
1/* $OpenBSD: ssh-keygen.c,v 1.489 2026/02/11 17:05:32 dtucker Exp $ */
2/*
3 * Author: Tatu Ylonen <ylo@cs.hut.fi>
4 * Copyright (c) 1994 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
5 * All rights reserved
6 * Identity and host key generation and maintenance.
7 *
8 * As far as I am concerned, the code I have written for this software
9 * can be used freely for any purpose. Any derived versions of this
10 * software must be clearly marked as such, and if the derived work is
11 * incompatible with the protocol description in the RFC file, it must be
12 * called by a name other than "ssh" or "Secure Shell".
13 */
14
15#include <sys/types.h>
16#include <sys/socket.h>
17#include <sys/stat.h>
18
19#ifdef WITH_OPENSSL
20#include <openssl/bn.h>
21#include <openssl/evp.h>
22#include <openssl/pem.h>
23#endif
24
25#include <stdint.h>
26#include <errno.h>
27#include <fcntl.h>
28#include <netdb.h>
29#include <paths.h>
30#include <pwd.h>
31#include <stdarg.h>
32#include <stdio.h>
33#include <stdlib.h>
34#include <string.h>
35#include <unistd.h>
36#include <limits.h>
37#include <locale.h>
38#include <time.h>
39
40#include "xmalloc.h"
41#include "sshkey.h"
42#include "authfile.h"
43#include "sshbuf.h"
44#include "pathnames.h"
45#include "log.h"
46#include "misc.h"
47#include "match.h"
48#include "hostfile.h"
49#include "dns.h"
50#include "ssh.h"
51#include "ssh2.h"
52#include "ssherr.h"
53#include "atomicio.h"
54#include "krl.h"
55#include "digest.h"
56#include "utf8.h"
57#include "authfd.h"
58#include "sshsig.h"
59#include "ssh-sk.h"
60#include "sk-api.h" /* XXX for SSH_SK_USER_PRESENCE_REQD; remove */
61#include "cipher.h"
62
63#ifdef ENABLE_PKCS11
64#include "ssh-pkcs11.h"
65#endif
66
67#define DEFAULT_KEY_TYPE_NAME "ed25519"
68
69/*
70 * Default number of bits in the RSA and ECDSA keys. These value can be
71 * overridden on the command line.
72 *
73 * These values provide security equivalent to at least 128 bits of security
74 * according to NIST Special Publication 800-57: Recommendation for Key
75 * Management Part 1 rev 4 section 5.6.1.
76 */
77#define DEFAULT_BITS 3072
78#define DEFAULT_BITS_ECDSA 256
79
80static int quiet = 0;
81
82/* Flag indicating that we just want to see the key fingerprint */
83static int print_fingerprint = 0;
84static int print_bubblebabble = 0;
85
86/* Hash algorithm to use for fingerprints. */
87static int fingerprint_hash = SSH_FP_HASH_DEFAULT;
88
89/* The identity file name, given on the command line or entered by the user. */
90static char identity_file[PATH_MAX];
91static int have_identity = 0;
92
93/* This is set to the passphrase if given on the command line. */
94static char *identity_passphrase = NULL;
95
96/* This is set to the new passphrase if given on the command line. */
97static char *identity_new_passphrase = NULL;
98
99/* Key type when certifying */
100static u_int cert_key_type = SSH2_CERT_TYPE_USER;
101
102/* "key ID" of signed key */
103static char *cert_key_id = NULL;
104
105/* Comma-separated list of principal names for certifying keys */
106static char *cert_principals = NULL;
107
108/* Validity period for certificates */
109static u_int64_t cert_valid_from = 0;
110static u_int64_t cert_valid_to = ~0ULL;
111
112/* Certificate options */
113#define CERTOPT_X_FWD (1)
114#define CERTOPT_AGENT_FWD (1<<1)
115#define CERTOPT_PORT_FWD (1<<2)
116#define CERTOPT_PTY (1<<3)
117#define CERTOPT_USER_RC (1<<4)
118#define CERTOPT_NO_REQUIRE_USER_PRESENCE (1<<5)
119#define CERTOPT_REQUIRE_VERIFY (1<<6)
120#define CERTOPT_DEFAULT (CERTOPT_X_FWD|CERTOPT_AGENT_FWD| \
121 CERTOPT_PORT_FWD|CERTOPT_PTY|CERTOPT_USER_RC)
122static u_int32_t certflags_flags = CERTOPT_DEFAULT;
123static char *certflags_command = NULL;
124static char *certflags_src_addr = NULL;
125
126/* Arbitrary extensions specified by user */
127struct cert_ext {
128 char *key;
129 char *val;
130 int crit;
131};
132static struct cert_ext *cert_ext;
133static size_t ncert_ext;
134
135/* Conversion to/from various formats */
136enum {
137 FMT_RFC4716,
138 FMT_PKCS8,
139 FMT_PEM
140} convert_format = FMT_RFC4716;
141
142static char *key_type_name = NULL;
143
144/* Load key from this PKCS#11 provider */
145static char *pkcs11provider = NULL;
146
147/* FIDO/U2F provider to use */
148static char *sk_provider = NULL;
149
150/* Format for writing private keys */
151static int private_key_format = SSHKEY_PRIVATE_OPENSSH;
152
153/* Cipher for new-format private keys */
154static char *openssh_format_cipher = NULL;
155
156/* Number of KDF rounds to derive new format keys. */
157static int rounds = 0;
158
159/* argv0 */
160extern char *__progname;
161
162static char hostname[NI_MAXHOST];
163
164#ifdef WITH_OPENSSL
165/* moduli.c */
166int gen_candidates(FILE *, u_int32_t, BIGNUM *);
167int prime_test(FILE *, FILE *, u_int32_t, u_int32_t, char *, unsigned long,
168 unsigned long);
169#endif
170
171static void
172type_bits_valid(int type, const char *name, u_int32_t *bitsp)
173{
174 if (type == KEY_UNSPEC)
175 fatal("unknown key type %s", key_type_name);
176 if (*bitsp == 0) {
177#ifdef WITH_OPENSSL
178 int nid;
179
180 switch(type) {
181 case KEY_ECDSA:
182 if (name != NULL &&
183 (nid = sshkey_ecdsa_nid_from_name(name)) > 0)
184 *bitsp = sshkey_curve_nid_to_bits(nid);
185 if (*bitsp == 0)
186 *bitsp = DEFAULT_BITS_ECDSA;
187 break;
188 case KEY_RSA:
189 *bitsp = DEFAULT_BITS;
190 break;
191 }
192#endif
193 }
194#ifdef WITH_OPENSSL
195 switch (type) {
196 case KEY_RSA:
197 if (*bitsp < SSH_RSA_MINIMUM_MODULUS_SIZE)
198 fatal("Invalid RSA key length: minimum is %d bits",
199 SSH_RSA_MINIMUM_MODULUS_SIZE);
200 else if (*bitsp > OPENSSL_RSA_MAX_MODULUS_BITS)
201 fatal("Invalid RSA key length: maximum is %d bits",
202 OPENSSL_RSA_MAX_MODULUS_BITS);
203 break;
204 case KEY_ECDSA:
205 if (sshkey_ecdsa_bits_to_nid(*bitsp) == -1)
206 fatal("Invalid ECDSA key length: valid lengths are "
207 "256, 384 or 521 bits");
208 }
209#endif
210}
211
212/*
213 * Checks whether a file exists and, if so, asks the user whether they wish
214 * to overwrite it.
215 * Returns nonzero if the file does not already exist or if the user agrees to
216 * overwrite, or zero otherwise.
217 */
218static int
219confirm_overwrite(const char *filename)
220{
221 char yesno[3];
222 struct stat st;
223
224 if (stat(filename, &st) != 0)
225 return 1;
226 printf("%s already exists.\n", filename);
227 printf("Overwrite (y/n)? ");
228 fflush(stdout);
229 if (fgets(yesno, sizeof(yesno), stdin) == NULL)
230 return 0;
231 if (yesno[0] != 'y' && yesno[0] != 'Y')
232 return 0;
233 return 1;
234}
235
236static void
237ask_filename(struct passwd *pw, const char *prompt)
238{
239 char buf[1024];
240 char *name = NULL;
241
242 if (key_type_name == NULL)
243 name = _PATH_SSH_CLIENT_ID_ED25519;
244 else {
245 switch (sshkey_type_from_shortname(key_type_name)) {
246 case KEY_ECDSA_CERT:
247 case KEY_ECDSA:
248 name = _PATH_SSH_CLIENT_ID_ECDSA;
249 break;
250 case KEY_ECDSA_SK_CERT:
251 case KEY_ECDSA_SK:
252 name = _PATH_SSH_CLIENT_ID_ECDSA_SK;
253 break;
254 case KEY_RSA_CERT:
255 case KEY_RSA:
256 name = _PATH_SSH_CLIENT_ID_RSA;
257 break;
258 case KEY_ED25519:
259 case KEY_ED25519_CERT:
260 name = _PATH_SSH_CLIENT_ID_ED25519;
261 break;
262 case KEY_ED25519_SK:
263 case KEY_ED25519_SK_CERT:
264 name = _PATH_SSH_CLIENT_ID_ED25519_SK;
265 break;
266 default:
267 fatal("bad key type");
268 }
269 }
270 snprintf(identity_file, sizeof(identity_file),
271 "%s/%s", pw->pw_dir, name);
272 printf("%s (%s): ", prompt, identity_file);
273 fflush(stdout);
274 if (fgets(buf, sizeof(buf), stdin) == NULL)
275 exit(1);
276 buf[strcspn(buf, "\n")] = '\0';
277 if (strcmp(buf, "") != 0)
278 strlcpy(identity_file, buf, sizeof(identity_file));
279 have_identity = 1;
280}
281
282static struct sshkey *
283load_identity(const char *filename, char **commentp)
284{
285 char *prompt, *pass;
286 struct sshkey *prv;
287 int r;
288
289 if (commentp != NULL)
290 *commentp = NULL;
291 if ((r = sshkey_load_private(filename, "", &prv, commentp)) == 0)
292 return prv;
293 if (r != SSH_ERR_KEY_WRONG_PASSPHRASE)
294 fatal_r(r, "Load key \"%s\"", filename);
295 if (identity_passphrase)
296 pass = xstrdup(identity_passphrase);
297 else {
298 xasprintf(&prompt, "Enter passphrase for \"%s\": ", filename);
299 pass = read_passphrase(prompt, RP_ALLOW_STDIN);
300 free(prompt);
301 }
302 r = sshkey_load_private(filename, pass, &prv, commentp);
303 freezero(pass, strlen(pass));
304 if (r != 0)
305 fatal_r(r, "Load key \"%s\"", filename);
306 return prv;
307}
308
309#define SSH_COM_PUBLIC_BEGIN "---- BEGIN SSH2 PUBLIC KEY ----"
310#define SSH_COM_PUBLIC_END "---- END SSH2 PUBLIC KEY ----"
311#define SSH_COM_PRIVATE_BEGIN "---- BEGIN SSH2 ENCRYPTED PRIVATE KEY ----"
312#define SSH_COM_PRIVATE_KEY_MAGIC 0x3f6ff9eb
313
314#ifdef WITH_OPENSSL
315static void
316do_convert_to_ssh2(struct passwd *pw, struct sshkey *k)
317{
318 struct sshbuf *b;
319 char comment[61], *b64;
320 int r;
321
322 if ((b = sshbuf_new()) == NULL)
323 fatal_f("sshbuf_new failed");
324 if ((r = sshkey_putb(k, b)) != 0)
325 fatal_fr(r, "put key");
326 if ((b64 = sshbuf_dtob64_string(b, 1)) == NULL)
327 fatal_f("sshbuf_dtob64_string failed");
328
329 /* Comment + surrounds must fit into 72 chars (RFC 4716 sec 3.3) */
330 snprintf(comment, sizeof(comment),
331 "%u-bit %s, converted by %s@%s from OpenSSH",
332 sshkey_size(k), sshkey_type(k),
333 pw->pw_name, hostname);
334
335 sshkey_free(k);
336 sshbuf_free(b);
337
338 fprintf(stdout, "%s\n", SSH_COM_PUBLIC_BEGIN);
339 fprintf(stdout, "Comment: \"%s\"\n%s", comment, b64);
340 fprintf(stdout, "%s\n", SSH_COM_PUBLIC_END);
341 free(b64);
342}
343
344static void
345do_convert_to_pkcs8(struct sshkey *k)
346{
347 switch (sshkey_type_plain(k->type)) {
348 case KEY_RSA:
349 if (!PEM_write_RSA_PUBKEY(stdout,
350 EVP_PKEY_get0_RSA(k->pkey)))
351 fatal("PEM_write_RSA_PUBKEY failed");
352 break;
353 case KEY_ECDSA:
354 if (!PEM_write_EC_PUBKEY(stdout,
355 EVP_PKEY_get0_EC_KEY(k->pkey)))
356 fatal("PEM_write_EC_PUBKEY failed");
357 break;
358 default:
359 fatal_f("unsupported key type %s", sshkey_type(k));
360 }
361}
362
363static void
364do_convert_to_pem(struct sshkey *k)
365{
366 switch (sshkey_type_plain(k->type)) {
367 case KEY_RSA:
368 if (!PEM_write_RSAPublicKey(stdout,
369 EVP_PKEY_get0_RSA(k->pkey)))
370 fatal("PEM_write_RSAPublicKey failed");
371 break;
372 case KEY_ECDSA:
373 if (!PEM_write_EC_PUBKEY(stdout,
374 EVP_PKEY_get0_EC_KEY(k->pkey)))
375 fatal("PEM_write_EC_PUBKEY failed");
376 break;
377 default:
378 fatal_f("unsupported key type %s", sshkey_type(k));
379 }
380}
381
382static void
383do_convert_to(struct passwd *pw)
384{
385 struct sshkey *k;
386 struct stat st;
387 int r;
388
389 if (!have_identity)
390 ask_filename(pw, "Enter file in which the key is");
391 if (stat(identity_file, &st) == -1)
392 fatal("%s: %s: %s", __progname, identity_file, strerror(errno));
393 if ((r = sshkey_load_public(identity_file, &k, NULL)) != 0)
394 k = load_identity(identity_file, NULL);
395 switch (convert_format) {
396 case FMT_RFC4716:
397 do_convert_to_ssh2(pw, k);
398 break;
399 case FMT_PKCS8:
400 do_convert_to_pkcs8(k);
401 break;
402 case FMT_PEM:
403 do_convert_to_pem(k);
404 break;
405 default:
406 fatal_f("unknown key format %d", convert_format);
407 }
408}
409
410/*
411 * This is almost exactly the bignum1 encoding, but with 32 bit for length
412 * instead of 16.
413 */
414static void
415buffer_get_bignum_bits(struct sshbuf *b, BIGNUM *value)
416{
417 u_int bytes, bignum_bits;
418 int r;
419
420 if ((r = sshbuf_get_u32(b, &bignum_bits)) != 0)
421 fatal_fr(r, "parse");
422 bytes = (bignum_bits + 7) / 8;
423 if (sshbuf_len(b) < bytes)
424 fatal_f("input buffer too small: need %d have %zu",
425 bytes, sshbuf_len(b));
426 if (BN_bin2bn(sshbuf_ptr(b), bytes, value) == NULL)
427 fatal_f("BN_bin2bn failed");
428 if ((r = sshbuf_consume(b, bytes)) != 0)
429 fatal_fr(r, "consume");
430}
431
432static struct sshkey *
433do_convert_private_ssh2(struct sshbuf *b)
434{
435 struct sshkey *key = NULL;
436 char *type, *cipher;
437 const char *alg = NULL;
438 u_char e1, e2, e3, *sig = NULL, data[] = "abcde12345";
439 int r, rlen, ktype;
440 u_int magic, i1, i2, i3, i4;
441 size_t slen;
442 u_long e;
443 BIGNUM *rsa_n = NULL, *rsa_e = NULL, *rsa_d = NULL;
444 BIGNUM *rsa_p = NULL, *rsa_q = NULL, *rsa_iqmp = NULL;
445 BIGNUM *rsa_dmp1 = NULL, *rsa_dmq1 = NULL;
446 RSA *rsa = NULL;
447
448 if ((r = sshbuf_get_u32(b, &magic)) != 0)
449 fatal_fr(r, "parse magic");
450
451 if (magic != SSH_COM_PRIVATE_KEY_MAGIC) {
452 error("bad magic 0x%x != 0x%x", magic,
453 SSH_COM_PRIVATE_KEY_MAGIC);
454 return NULL;
455 }
456 if ((r = sshbuf_get_u32(b, &i1)) != 0 ||
457 (r = sshbuf_get_cstring(b, &type, NULL)) != 0 ||
458 (r = sshbuf_get_cstring(b, &cipher, NULL)) != 0 ||
459 (r = sshbuf_get_u32(b, &i2)) != 0 ||
460 (r = sshbuf_get_u32(b, &i3)) != 0 ||
461 (r = sshbuf_get_u32(b, &i4)) != 0)
462 fatal_fr(r, "parse");
463 debug("ignore (%d %d %d %d)", i1, i2, i3, i4);
464 if (strcmp(cipher, "none") != 0) {
465 error("unsupported cipher %s", cipher);
466 free(cipher);
467 free(type);
468 return NULL;
469 }
470 free(cipher);
471
472 if (strstr(type, "rsa")) {
473 ktype = KEY_RSA;
474 } else {
475 free(type);
476 return NULL;
477 }
478 if ((key = sshkey_new(ktype)) == NULL)
479 fatal("sshkey_new failed");
480 free(type);
481
482 switch (key->type) {
483 case KEY_RSA:
484 if ((r = sshbuf_get_u8(b, &e1)) != 0 ||
485 (e1 < 30 && (r = sshbuf_get_u8(b, &e2)) != 0) ||
486 (e1 < 30 && (r = sshbuf_get_u8(b, &e3)) != 0))
487 fatal_fr(r, "parse RSA");
488 e = e1;
489 debug("e %lx", e);
490 if (e < 30) {
491 e <<= 8;
492 e += e2;
493 debug("e %lx", e);
494 e <<= 8;
495 e += e3;
496 debug("e %lx", e);
497 }
498 if ((rsa_e = BN_new()) == NULL)
499 fatal_f("BN_new");
500 if (!BN_set_word(rsa_e, e)) {
501 BN_clear_free(rsa_e);
502 sshkey_free(key);
503 return NULL;
504 }
505 if ((rsa_n = BN_new()) == NULL ||
506 (rsa_d = BN_new()) == NULL ||
507 (rsa_p = BN_new()) == NULL ||
508 (rsa_q = BN_new()) == NULL ||
509 (rsa_iqmp = BN_new()) == NULL)
510 fatal_f("BN_new");
511 buffer_get_bignum_bits(b, rsa_d);
512 buffer_get_bignum_bits(b, rsa_n);
513 buffer_get_bignum_bits(b, rsa_iqmp);
514 buffer_get_bignum_bits(b, rsa_q);
515 buffer_get_bignum_bits(b, rsa_p);
516 if ((r = ssh_rsa_complete_crt_parameters(rsa_d, rsa_p, rsa_q,
517 rsa_iqmp, &rsa_dmp1, &rsa_dmq1)) != 0)
518 fatal_fr(r, "generate RSA CRT parameters");
519 EVP_PKEY_free(key->pkey);
520 if ((key->pkey = EVP_PKEY_new()) == NULL)
521 fatal_f("EVP_PKEY_new failed");
522 if ((rsa = RSA_new()) == NULL)
523 fatal_f("RSA_new failed");
524 if (!RSA_set0_key(rsa, rsa_n, rsa_e, rsa_d))
525 fatal_f("RSA_set0_key failed");
526 rsa_n = rsa_e = rsa_d = NULL; /* transferred */
527 if (!RSA_set0_factors(rsa, rsa_p, rsa_q))
528 fatal_f("RSA_set0_factors failed");
529 rsa_p = rsa_q = NULL; /* transferred */
530 if (RSA_set0_crt_params(rsa, rsa_dmp1, rsa_dmq1, rsa_iqmp) != 1)
531 fatal_f("RSA_set0_crt_params failed");
532 rsa_dmp1 = rsa_dmq1 = rsa_iqmp = NULL;
533 if (EVP_PKEY_set1_RSA(key->pkey, rsa) != 1)
534 fatal_f("EVP_PKEY_set1_RSA failed");
535 RSA_free(rsa);
536 alg = "rsa-sha2-256";
537 break;
538 }
539 rlen = sshbuf_len(b);
540 if (rlen != 0)
541 error_f("remaining bytes in key blob %d", rlen);
542
543 /* try the key */
544 if ((r = sshkey_sign(key, &sig, &slen, data, sizeof(data),
545 alg, NULL, NULL, 0)) != 0)
546 error_fr(r, "signing with converted key failed");
547 else if ((r = sshkey_verify(key, sig, slen, data, sizeof(data),
548 alg, 0, NULL)) != 0)
549 error_fr(r, "verification with converted key failed");
550 if (r != 0) {
551 sshkey_free(key);
552 free(sig);
553 return NULL;
554 }
555 free(sig);
556 return key;
557}
558
559static int
560get_line(FILE *fp, char *line, size_t len)
561{
562 int c;
563 size_t pos = 0;
564
565 line[0] = '\0';
566 while ((c = fgetc(fp)) != EOF) {
567 if (pos >= len - 1)
568 fatal("input line too long.");
569 switch (c) {
570 case '\r':
571 c = fgetc(fp);
572 if (c != EOF && c != '\n' && ungetc(c, fp) == EOF)
573 fatal("unget: %s", strerror(errno));
574 return pos;
575 case '\n':
576 return pos;
577 }
578 line[pos++] = c;
579 line[pos] = '\0';
580 }
581 /* We reached EOF */
582 return -1;
583}
584
585static void
586do_convert_from_ssh2(struct passwd *pw, struct sshkey **k, int *private)
587{
588 int r, blen, escaped = 0;
589 u_int len;
590 char line[1024];
591 struct sshbuf *buf;
592 char encoded[8096];
593 FILE *fp;
594
595 if ((buf = sshbuf_new()) == NULL)
596 fatal("sshbuf_new failed");
597 if ((fp = fopen(identity_file, "r")) == NULL)
598 fatal("%s: %s: %s", __progname, identity_file, strerror(errno));
599 encoded[0] = '\0';
600 while ((blen = get_line(fp, line, sizeof(line))) != -1) {
601 if (blen > 0 && line[blen - 1] == '\\')
602 escaped++;
603 if (strncmp(line, "----", 4) == 0 ||
604 strstr(line, ": ") != NULL) {
605 if (strstr(line, SSH_COM_PRIVATE_BEGIN) != NULL)
606 *private = 1;
607 if (strstr(line, " END ") != NULL) {
608 break;
609 }
610 /* fprintf(stderr, "ignore: %s", line); */
611 continue;
612 }
613 if (escaped) {
614 escaped--;
615 /* fprintf(stderr, "escaped: %s", line); */
616 continue;
617 }
618 strlcat(encoded, line, sizeof(encoded));
619 }
620 len = strlen(encoded);
621 if (((len % 4) == 3) &&
622 (encoded[len-1] == '=') &&
623 (encoded[len-2] == '=') &&
624 (encoded[len-3] == '='))
625 encoded[len-3] = '\0';
626 if ((r = sshbuf_b64tod(buf, encoded)) != 0)
627 fatal_fr(r, "base64 decode");
628 if (*private) {
629 if ((*k = do_convert_private_ssh2(buf)) == NULL)
630 fatal_f("private key conversion failed");
631 } else if ((r = sshkey_fromb(buf, k)) != 0)
632 fatal_fr(r, "parse key");
633 sshbuf_free(buf);
634 fclose(fp);
635}
636
637static void
638do_convert_from_pkcs8(struct sshkey **k, int *private)
639{
640 EVP_PKEY *pubkey;
641 FILE *fp;
642
643 if ((fp = fopen(identity_file, "r")) == NULL)
644 fatal("%s: %s: %s", __progname, identity_file, strerror(errno));
645 if ((pubkey = PEM_read_PUBKEY(fp, NULL, NULL, NULL)) == NULL) {
646 fatal_f("%s is not a recognised public key format",
647 identity_file);
648 }
649 fclose(fp);
650 switch (EVP_PKEY_base_id(pubkey)) {
651 case EVP_PKEY_RSA:
652 if ((*k = sshkey_new(KEY_UNSPEC)) == NULL)
653 fatal("sshkey_new failed");
654 (*k)->type = KEY_RSA;
655 (*k)->pkey = pubkey;
656 pubkey = NULL;
657 break;
658 case EVP_PKEY_EC:
659 if ((*k = sshkey_new(KEY_UNSPEC)) == NULL)
660 fatal("sshkey_new failed");
661 if (((*k)->ecdsa_nid = sshkey_ecdsa_fixup_group(pubkey)) == -1)
662 fatal("sshkey_ecdsa_fixup_group failed");
663 (*k)->type = KEY_ECDSA;
664 (*k)->pkey = pubkey;
665 pubkey = NULL;
666 break;
667 default:
668 fatal_f("unsupported pubkey type %d",
669 EVP_PKEY_base_id(pubkey));
670 }
671 EVP_PKEY_free(pubkey);
672}
673
674static void
675do_convert_from_pem(struct sshkey **k, int *private)
676{
677 FILE *fp;
678 RSA *rsa;
679
680 if ((fp = fopen(identity_file, "r")) == NULL)
681 fatal("%s: %s: %s", __progname, identity_file, strerror(errno));
682 if ((rsa = PEM_read_RSAPublicKey(fp, NULL, NULL, NULL)) != NULL) {
683 if ((*k = sshkey_new(KEY_UNSPEC)) == NULL)
684 fatal("sshkey_new failed");
685 if (((*k)->pkey = EVP_PKEY_new()) == NULL)
686 fatal("EVP_PKEY_new failed");
687 (*k)->type = KEY_RSA;
688 if (EVP_PKEY_set1_RSA((*k)->pkey, rsa) != 1)
689 fatal("EVP_PKEY_set1_RSA failed");
690 RSA_free(rsa);
691 fclose(fp);
692 return;
693 }
694 fatal_f("unrecognised raw private key format");
695}
696
697static void
698do_convert_from(struct passwd *pw)
699{
700 struct sshkey *k = NULL;
701 int r, private = 0, ok = 0;
702 struct stat st;
703
704 if (!have_identity)
705 ask_filename(pw, "Enter file in which the key is");
706 if (stat(identity_file, &st) == -1)
707 fatal("%s: %s: %s", __progname, identity_file, strerror(errno));
708
709 switch (convert_format) {
710 case FMT_RFC4716:
711 do_convert_from_ssh2(pw, &k, &private);
712 break;
713 case FMT_PKCS8:
714 do_convert_from_pkcs8(&k, &private);
715 break;
716 case FMT_PEM:
717 do_convert_from_pem(&k, &private);
718 break;
719 default:
720 fatal_f("unknown key format %d", convert_format);
721 }
722
723 if (!private) {
724 if ((r = sshkey_write(k, stdout)) == 0)
725 ok = 1;
726 if (ok)
727 fprintf(stdout, "\n");
728 } else {
729 switch (k->type) {
730 case KEY_ECDSA:
731 ok = PEM_write_ECPrivateKey(stdout,
732 EVP_PKEY_get0_EC_KEY(k->pkey), NULL, NULL, 0,
733 NULL, NULL);
734 break;
735 case KEY_RSA:
736 ok = PEM_write_RSAPrivateKey(stdout,
737 EVP_PKEY_get0_RSA(k->pkey), NULL, NULL, 0,
738 NULL, NULL);
739 break;
740 default:
741 fatal_f("unsupported key type %s", sshkey_type(k));
742 }
743 }
744
745 if (!ok)
746 fatal("key write failed");
747 sshkey_free(k);
748}
749#endif
750
751static void
752do_print_public(struct passwd *pw)
753{
754 struct sshkey *prv;
755 struct stat st;
756 int r;
757 char *comment = NULL;
758
759 if (!have_identity)
760 ask_filename(pw, "Enter file in which the key is");
761 if (stat(identity_file, &st) == -1)
762 fatal("%s: %s", identity_file, strerror(errno));
763 prv = load_identity(identity_file, &comment);
764 if ((r = sshkey_write(prv, stdout)) != 0)
765 fatal_fr(r, "write key");
766 if (comment != NULL && *comment != '\0')
767 fprintf(stdout, " %s", comment);
768 fprintf(stdout, "\n");
769 if (sshkey_is_sk(prv)) {
770 debug("sk_application: \"%s\", sk_flags 0x%02x",
771 prv->sk_application, prv->sk_flags);
772 }
773 sshkey_free(prv);
774 free(comment);
775 exit(0);
776}
777
778static void
779do_download(struct passwd *pw)
780{
781#ifdef ENABLE_PKCS11
782 struct sshkey **keys = NULL;
783 int i, nkeys;
784 enum sshkey_fp_rep rep;
785 int fptype;
786 char *fp, *ra, **comments = NULL;
787
788 fptype = print_bubblebabble ? SSH_DIGEST_SHA1 : fingerprint_hash;
789 rep = print_bubblebabble ? SSH_FP_BUBBLEBABBLE : SSH_FP_DEFAULT;
790
791 pkcs11_init(1);
792 nkeys = pkcs11_add_provider(pkcs11provider, NULL, &keys, &comments);
793 if (nkeys <= 0)
794 fatal("cannot read public key from pkcs11");
795 for (i = 0; i < nkeys; i++) {
796 if (print_fingerprint) {
797 fp = sshkey_fingerprint(keys[i], fptype, rep);
798 ra = sshkey_fingerprint(keys[i], fingerprint_hash,
799 SSH_FP_RANDOMART);
800 if (fp == NULL || ra == NULL)
801 fatal_f("sshkey_fingerprint fail");
802 printf("%u %s %s (PKCS11 key)\n", sshkey_size(keys[i]),
803 fp, sshkey_type(keys[i]));
804 if (log_level_get() >= SYSLOG_LEVEL_VERBOSE)
805 printf("%s\n", ra);
806 free(ra);
807 free(fp);
808 } else {
809 (void) sshkey_write(keys[i], stdout); /* XXX check */
810 fprintf(stdout, "%s%s\n",
811 *(comments[i]) == '\0' ? "" : " ", comments[i]);
812 }
813 free(comments[i]);
814 sshkey_free(keys[i]);
815 }
816 free(comments);
817 free(keys);
818 pkcs11_terminate();
819 exit(0);
820#else
821 fatal("no pkcs11 support");
822#endif /* ENABLE_PKCS11 */
823}
824
825static struct sshkey *
826try_read_key(char **cpp)
827{
828 struct sshkey *ret;
829 int r;
830
831 if ((ret = sshkey_new(KEY_UNSPEC)) == NULL)
832 fatal("sshkey_new failed");
833 if ((r = sshkey_read(ret, cpp)) == 0)
834 return ret;
835 /* Not a key */
836 sshkey_free(ret);
837 return NULL;
838}
839
840static void
841fingerprint_one_key(const struct sshkey *public, const char *comment)
842{
843 char *fp = NULL, *ra = NULL;
844 enum sshkey_fp_rep rep;
845 int fptype;
846
847 fptype = print_bubblebabble ? SSH_DIGEST_SHA1 : fingerprint_hash;
848 rep = print_bubblebabble ? SSH_FP_BUBBLEBABBLE : SSH_FP_DEFAULT;
849 fp = sshkey_fingerprint(public, fptype, rep);
850 ra = sshkey_fingerprint(public, fingerprint_hash, SSH_FP_RANDOMART);
851 if (fp == NULL || ra == NULL)
852 fatal_f("sshkey_fingerprint failed");
853 mprintf("%u %s %s (%s)\n", sshkey_size(public), fp,
854 comment ? comment : "no comment", sshkey_type(public));
855 if (log_level_get() >= SYSLOG_LEVEL_VERBOSE)
856 printf("%s\n", ra);
857 free(ra);
858 free(fp);
859}
860
861static void
862fingerprint_private(const char *path)
863{
864 struct stat st;
865 char *comment = NULL;
866 struct sshkey *privkey = NULL, *pubkey = NULL;
867 int r;
868
869 if (stat(identity_file, &st) == -1)
870 fatal("%s: %s", path, strerror(errno));
871 if ((r = sshkey_load_public(path, &pubkey, &comment)) != 0)
872 debug_r(r, "load public \"%s\"", path);
873 if (pubkey == NULL || comment == NULL || *comment == '\0') {
874 free(comment);
875 if ((r = sshkey_load_private(path, NULL,
876 &privkey, &comment)) != 0)
877 debug_r(r, "load private \"%s\"", path);
878 }
879 if (pubkey == NULL && privkey == NULL)
880 fatal("%s is not a key file.", path);
881
882 fingerprint_one_key(pubkey == NULL ? privkey : pubkey, comment);
883 sshkey_free(pubkey);
884 sshkey_free(privkey);
885 free(comment);
886}
887
888static void
889do_fingerprint(struct passwd *pw)
890{
891 FILE *f;
892 struct sshkey *public = NULL;
893 char *comment = NULL, *cp, *ep, *line = NULL;
894 size_t linesize = 0;
895 int i, invalid = 1;
896 const char *path;
897 u_long lnum = 0;
898
899 if (!have_identity)
900 ask_filename(pw, "Enter file in which the key is");
901 path = identity_file;
902
903 if (strcmp(identity_file, "-") == 0) {
904 f = stdin;
905 path = "(stdin)";
906 } else if ((f = fopen(path, "r")) == NULL)
907 fatal("%s: %s: %s", __progname, path, strerror(errno));
908
909 while (getline(&line, &linesize, f) != -1) {
910 lnum++;
911 cp = line;
912 cp[strcspn(cp, "\r\n")] = '\0';
913 /* Trim leading space and comments */
914 cp = line + strspn(line, " \t");
915 if (*cp == '#' || *cp == '\0')
916 continue;
917
918 /*
919 * Input may be plain keys, private keys, authorized_keys
920 * or known_hosts.
921 */
922
923 /*
924 * Try private keys first. Assume a key is private if
925 * "SSH PRIVATE KEY" appears on the first line and we're
926 * not reading from stdin (XXX support private keys on stdin).
927 */
928 if (lnum == 1 && strcmp(identity_file, "-") != 0 &&
929 strstr(cp, "PRIVATE KEY") != NULL) {
930 free(line);
931 fclose(f);
932 fingerprint_private(path);
933 exit(0);
934 }
935
936 /*
937 * If it's not a private key, then this must be prepared to
938 * accept a public key prefixed with a hostname or options.
939 * Try a bare key first, otherwise skip the leading stuff.
940 */
941 comment = NULL;
942 if ((public = try_read_key(&cp)) == NULL) {
943 i = strtol(cp, &ep, 10);
944 if (i == 0 || ep == NULL ||
945 (*ep != ' ' && *ep != '\t')) {
946 int quoted = 0;
947
948 comment = cp;
949 for (; *cp && (quoted || (*cp != ' ' &&
950 *cp != '\t')); cp++) {
951 if (*cp == '\\' && cp[1] == '"')
952 cp++; /* Skip both */
953 else if (*cp == '"')
954 quoted = !quoted;
955 }
956 if (!*cp)
957 continue;
958 *cp++ = '\0';
959 }
960 }
961 /* Retry after parsing leading hostname/key options */
962 if (public == NULL && (public = try_read_key(&cp)) == NULL) {
963 debug("%s:%lu: not a public key", path, lnum);
964 continue;
965 }
966
967 /* Find trailing comment, if any */
968 for (; *cp == ' ' || *cp == '\t'; cp++)
969 ;
970 if (*cp != '\0' && *cp != '#')
971 comment = cp;
972
973 fingerprint_one_key(public, comment);
974 sshkey_free(public);
975 invalid = 0; /* One good key in the file is sufficient */
976 }
977 fclose(f);
978 free(line);
979
980 if (invalid)
981 fatal("%s is not a public key file.", path);
982 exit(0);
983}
984
985static void
986do_gen_all_hostkeys(struct passwd *pw)
987{
988 struct {
989 char *key_type;
990 char *key_type_display;
991 char *path;
992 } key_types[] = {
993#ifdef WITH_OPENSSL
994 { "rsa", "RSA" ,_PATH_HOST_RSA_KEY_FILE },
995 { "ecdsa", "ECDSA",_PATH_HOST_ECDSA_KEY_FILE },
996#endif /* WITH_OPENSSL */
997 { "ed25519", "ED25519",_PATH_HOST_ED25519_KEY_FILE },
998 { NULL, NULL, NULL }
999 };
1000
1001 u_int32_t bits = 0;
1002 int first = 0;
1003 struct stat st;
1004 struct sshkey *private, *public;
1005 char comment[1024], *prv_tmp, *pub_tmp, *prv_file, *pub_file;
1006 int i, type, fd, r;
1007
1008 for (i = 0; key_types[i].key_type; i++) {
1009 public = private = NULL;
1010 prv_tmp = pub_tmp = prv_file = pub_file = NULL;
1011
1012 xasprintf(&prv_file, "%s%s",
1013 identity_file, key_types[i].path);
1014
1015 /* Check whether private key exists and is not zero-length */
1016 if (stat(prv_file, &st) == 0) {
1017 if (st.st_size != 0)
1018 goto next;
1019 } else if (errno != ENOENT) {
1020 error("Could not stat %s: %s", key_types[i].path,
1021 strerror(errno));
1022 goto failnext;
1023 }
1024
1025 /*
1026 * Private key doesn't exist or is invalid; proceed with
1027 * key generation.
1028 */
1029 xasprintf(&prv_tmp, "%s%s.XXXXXXXXXX",
1030 identity_file, key_types[i].path);
1031 xasprintf(&pub_tmp, "%s%s.pub.XXXXXXXXXX",
1032 identity_file, key_types[i].path);
1033 xasprintf(&pub_file, "%s%s.pub",
1034 identity_file, key_types[i].path);
1035
1036 if (first == 0) {
1037 first = 1;
1038 printf("%s: generating new host keys: ", __progname);
1039 }
1040 printf("%s ", key_types[i].key_type_display);
1041 fflush(stdout);
1042 type = sshkey_type_from_shortname(key_types[i].key_type);
1043 if ((fd = mkstemp(prv_tmp)) == -1) {
1044 error("Could not save your private key in %s: %s",
1045 prv_tmp, strerror(errno));
1046 goto failnext;
1047 }
1048 (void)close(fd); /* just using mkstemp() to reserve a name */
1049 bits = 0;
1050 type_bits_valid(type, NULL, &bits);
1051 if ((r = sshkey_generate(type, bits, &private)) != 0) {
1052 error_r(r, "sshkey_generate failed");
1053 goto failnext;
1054 }
1055 if ((r = sshkey_from_private(private, &public)) != 0)
1056 fatal_fr(r, "sshkey_from_private");
1057 snprintf(comment, sizeof comment, "%s@%s", pw->pw_name,
1058 hostname);
1059 if ((r = sshkey_save_private(private, prv_tmp, "",
1060 comment, private_key_format, openssh_format_cipher,
1061 rounds)) != 0) {
1062 error_r(r, "Saving key \"%s\" failed", prv_tmp);
1063 goto failnext;
1064 }
1065 if ((fd = mkstemp(pub_tmp)) == -1) {
1066 error("Could not save your public key in %s: %s",
1067 pub_tmp, strerror(errno));
1068 goto failnext;
1069 }
1070 (void)fchmod(fd, 0644);
1071 (void)close(fd);
1072 if ((r = sshkey_save_public(public, pub_tmp, comment)) != 0) {
1073 error_r(r, "Unable to save public key to %s",
1074 identity_file);
1075 goto failnext;
1076 }
1077
1078 /* Rename temporary files to their permanent locations. */
1079 if (rename(pub_tmp, pub_file) != 0) {
1080 error("Unable to move %s into position: %s",
1081 pub_file, strerror(errno));
1082 goto failnext;
1083 }
1084 if (rename(prv_tmp, prv_file) != 0) {
1085 error("Unable to move %s into position: %s",
1086 key_types[i].path, strerror(errno));
1087 failnext:
1088 first = 0;
1089 goto next;
1090 }
1091 next:
1092 sshkey_free(private);
1093 sshkey_free(public);
1094 free(prv_tmp);
1095 free(pub_tmp);
1096 free(prv_file);
1097 free(pub_file);
1098 }
1099 if (first != 0)
1100 printf("\n");
1101}
1102
1103struct known_hosts_ctx {
1104 const char *host; /* Hostname searched for in find/delete case */
1105 FILE *out; /* Output file, stdout for find_hosts case */
1106 int has_unhashed; /* When hashing, original had unhashed hosts */
1107 int found_key; /* For find/delete, host was found */
1108 int invalid; /* File contained invalid items; don't delete */
1109 int hash_hosts; /* Hash hostnames as we go */
1110 int find_host; /* Search for specific hostname */
1111 int delete_host; /* Delete host from known_hosts */
1112};
1113
1114static int
1115known_hosts_hash(struct hostkey_foreach_line *l, void *_ctx)
1116{
1117 struct known_hosts_ctx *ctx = (struct known_hosts_ctx *)_ctx;
1118 char *hashed, *cp, *hosts, *ohosts;
1119 int has_wild = l->hosts && strcspn(l->hosts, "*?!") != strlen(l->hosts);
1120 int was_hashed = l->hosts && l->hosts[0] == HASH_DELIM;
1121
1122 switch (l->status) {
1123 case HKF_STATUS_OK:
1124 case HKF_STATUS_MATCHED:
1125 /*
1126 * Don't hash hosts already hashed, with wildcard
1127 * characters or a CA/revocation marker.
1128 */
1129 if (was_hashed || has_wild || l->marker != MRK_NONE) {
1130 fprintf(ctx->out, "%s\n", l->line);
1131 if (has_wild && !ctx->find_host) {
1132 logit("%s:%lu: ignoring host name "
1133 "with wildcard: %.64s", l->path,
1134 l->linenum, l->hosts);
1135 }
1136 return 0;
1137 }
1138 /*
1139 * Split any comma-separated hostnames from the host list,
1140 * hash and store separately.
1141 */
1142 ohosts = hosts = xstrdup(l->hosts);
1143 while ((cp = strsep(&hosts, ",")) != NULL && *cp != '\0') {
1144 lowercase(cp);
1145 if ((hashed = host_hash(cp, NULL, 0)) == NULL)
1146 fatal("hash_host failed");
1147 fprintf(ctx->out, "%s %s\n", hashed, l->rawkey);
1148 free(hashed);
1149 ctx->has_unhashed = 1;
1150 }
1151 free(ohosts);
1152 return 0;
1153 case HKF_STATUS_INVALID:
1154 /* Retain invalid lines, but mark file as invalid. */
1155 ctx->invalid = 1;
1156 logit("%s:%lu: invalid line", l->path, l->linenum);
1157 /* FALLTHROUGH */
1158 default:
1159 fprintf(ctx->out, "%s\n", l->line);
1160 return 0;
1161 }
1162 /* NOTREACHED */
1163 return -1;
1164}
1165
1166static int
1167known_hosts_find_delete(struct hostkey_foreach_line *l, void *_ctx)
1168{
1169 struct known_hosts_ctx *ctx = (struct known_hosts_ctx *)_ctx;
1170 enum sshkey_fp_rep rep;
1171 int fptype;
1172 char *fp = NULL, *ra = NULL;
1173
1174 fptype = print_bubblebabble ? SSH_DIGEST_SHA1 : fingerprint_hash;
1175 rep = print_bubblebabble ? SSH_FP_BUBBLEBABBLE : SSH_FP_DEFAULT;
1176
1177 if (l->status == HKF_STATUS_MATCHED) {
1178 if (ctx->delete_host) {
1179 if (l->marker != MRK_NONE) {
1180 /* Don't remove CA and revocation lines */
1181 fprintf(ctx->out, "%s\n", l->line);
1182 } else {
1183 /*
1184 * Hostname matches and has no CA/revoke
1185 * marker, delete it by *not* writing the
1186 * line to ctx->out.
1187 */
1188 ctx->found_key = 1;
1189 if (!quiet)
1190 printf("# Host %s found: line %lu\n",
1191 ctx->host, l->linenum);
1192 }
1193 return 0;
1194 } else if (ctx->find_host) {
1195 ctx->found_key = 1;
1196 if (!quiet) {
1197 printf("# Host %s found: line %lu %s\n",
1198 ctx->host,
1199 l->linenum, l->marker == MRK_CA ? "CA" :
1200 (l->marker == MRK_REVOKE ? "REVOKED" : ""));
1201 }
1202 if (ctx->hash_hosts)
1203 known_hosts_hash(l, ctx);
1204 else if (print_fingerprint) {
1205 fp = sshkey_fingerprint(l->key, fptype, rep);
1206 ra = sshkey_fingerprint(l->key,
1207 fingerprint_hash, SSH_FP_RANDOMART);
1208 if (fp == NULL || ra == NULL)
1209 fatal_f("sshkey_fingerprint failed");
1210 mprintf("%s %s %s%s%s\n", ctx->host,
1211 sshkey_type(l->key), fp,
1212 l->comment[0] ? " " : "",
1213 l->comment);
1214 if (log_level_get() >= SYSLOG_LEVEL_VERBOSE)
1215 printf("%s\n", ra);
1216 free(ra);
1217 free(fp);
1218 } else
1219 fprintf(ctx->out, "%s\n", l->line);
1220 return 0;
1221 }
1222 } else if (ctx->delete_host) {
1223 /* Retain non-matching hosts when deleting */
1224 if (l->status == HKF_STATUS_INVALID) {
1225 ctx->invalid = 1;
1226 logit("%s:%lu: invalid line", l->path, l->linenum);
1227 }
1228 fprintf(ctx->out, "%s\n", l->line);
1229 }
1230 return 0;
1231}
1232
1233static void
1234do_known_hosts(struct passwd *pw, const char *name, int find_host,
1235 int delete_host, int hash_hosts)
1236{
1237 char *cp, tmp[PATH_MAX], old[PATH_MAX];
1238 int r, fd, oerrno, inplace = 0;
1239 struct known_hosts_ctx ctx;
1240 u_int foreach_options;
1241 struct stat sb;
1242
1243 if (!have_identity) {
1244 cp = tilde_expand_filename(_PATH_SSH_USER_HOSTFILE, pw->pw_uid);
1245 if (strlcpy(identity_file, cp, sizeof(identity_file)) >=
1246 sizeof(identity_file))
1247 fatal("Specified known hosts path too long");
1248 free(cp);
1249 have_identity = 1;
1250 }
1251 if (stat(identity_file, &sb) != 0)
1252 fatal("Cannot stat %s: %s", identity_file, strerror(errno));
1253
1254 memset(&ctx, 0, sizeof(ctx));
1255 ctx.out = stdout;
1256 ctx.host = name;
1257 ctx.hash_hosts = hash_hosts;
1258 ctx.find_host = find_host;
1259 ctx.delete_host = delete_host;
1260
1261 /*
1262 * Find hosts goes to stdout, hash and deletions happen in-place
1263 * A corner case is ssh-keygen -HF foo, which should go to stdout
1264 */
1265 if (!find_host && (hash_hosts || delete_host)) {
1266 if (strlcpy(tmp, identity_file, sizeof(tmp)) >= sizeof(tmp) ||
1267 strlcat(tmp, ".XXXXXXXXXX", sizeof(tmp)) >= sizeof(tmp) ||
1268 strlcpy(old, identity_file, sizeof(old)) >= sizeof(old) ||
1269 strlcat(old, ".old", sizeof(old)) >= sizeof(old))
1270 fatal("known_hosts path too long");
1271 umask(077);
1272 if ((fd = mkstemp(tmp)) == -1)
1273 fatal("mkstemp: %s", strerror(errno));
1274 if ((ctx.out = fdopen(fd, "w")) == NULL) {
1275 oerrno = errno;
1276 unlink(tmp);
1277 fatal("fdopen: %s", strerror(oerrno));
1278 }
1279 (void)fchmod(fd, sb.st_mode & 0644);
1280 inplace = 1;
1281 }
1282 /* XXX support identity_file == "-" for stdin */
1283 foreach_options = find_host ? HKF_WANT_MATCH : 0;
1284 foreach_options |= print_fingerprint ? HKF_WANT_PARSE_KEY : 0;
1285 if ((r = hostkeys_foreach(identity_file, (find_host || !hash_hosts) ?
1286 known_hosts_find_delete : known_hosts_hash, &ctx, name, NULL,
1287 foreach_options, 0)) != 0) {
1288 if (inplace)
1289 unlink(tmp);
1290 fatal_fr(r, "hostkeys_foreach");
1291 }
1292
1293 if (inplace)
1294 fclose(ctx.out);
1295
1296 if (ctx.invalid) {
1297 error("%s is not a valid known_hosts file.", identity_file);
1298 if (inplace) {
1299 error("Not replacing existing known_hosts "
1300 "file because of errors");
1301 unlink(tmp);
1302 }
1303 exit(1);
1304 } else if (delete_host && !ctx.found_key) {
1305 logit("Host %s not found in %s", name, identity_file);
1306 if (inplace)
1307 unlink(tmp);
1308 } else if (inplace) {
1309 /* Backup existing file */
1310 if (unlink(old) == -1 && errno != ENOENT)
1311 fatal("unlink %.100s: %s", old, strerror(errno));
1312 if (link(identity_file, old) == -1)
1313 fatal("link %.100s to %.100s: %s", identity_file, old,
1314 strerror(errno));
1315 /* Move new one into place */
1316 if (rename(tmp, identity_file) == -1) {
1317 error("rename\"%s\" to \"%s\": %s", tmp, identity_file,
1318 strerror(errno));
1319 unlink(tmp);
1320 unlink(old);
1321 exit(1);
1322 }
1323
1324 printf("%s updated.\n", identity_file);
1325 printf("Original contents retained as %s\n", old);
1326 if (ctx.has_unhashed) {
1327 logit("WARNING: %s contains unhashed entries", old);
1328 logit("Delete this file to ensure privacy "
1329 "of hostnames");
1330 }
1331 }
1332
1333 exit (find_host && !ctx.found_key);
1334}
1335
1336/*
1337 * Perform changing a passphrase. The argument is the passwd structure
1338 * for the current user.
1339 */
1340static void
1341do_change_passphrase(struct passwd *pw)
1342{
1343 char *comment;
1344 char *old_passphrase, *passphrase1, *passphrase2;
1345 struct stat st;
1346 struct sshkey *private;
1347 int r;
1348
1349 if (!have_identity)
1350 ask_filename(pw, "Enter file in which the key is");
1351 if (stat(identity_file, &st) == -1)
1352 fatal("%s: %s", identity_file, strerror(errno));
1353 /* Try to load the file with empty passphrase. */
1354 r = sshkey_load_private(identity_file, "", &private, &comment);
1355 if (r == SSH_ERR_KEY_WRONG_PASSPHRASE) {
1356 if (identity_passphrase)
1357 old_passphrase = xstrdup(identity_passphrase);
1358 else
1359 old_passphrase =
1360 read_passphrase("Enter old passphrase: ",
1361 RP_ALLOW_STDIN);
1362 r = sshkey_load_private(identity_file, old_passphrase,
1363 &private, &comment);
1364 freezero(old_passphrase, strlen(old_passphrase));
1365 if (r != 0)
1366 goto badkey;
1367 } else if (r != 0) {
1368 badkey:
1369 fatal_r(r, "Failed to load key %s", identity_file);
1370 }
1371 if (comment)
1372 mprintf("Key has comment '%s'\n", comment);
1373
1374 /* Ask the new passphrase (twice). */
1375 if (identity_new_passphrase) {
1376 passphrase1 = xstrdup(identity_new_passphrase);
1377 passphrase2 = NULL;
1378 } else {
1379 passphrase1 =
1380 read_passphrase("Enter new passphrase (empty for no "
1381 "passphrase): ", RP_ALLOW_STDIN);
1382 passphrase2 = read_passphrase("Enter same passphrase again: ",
1383 RP_ALLOW_STDIN);
1384
1385 /* Verify that they are the same. */
1386 if (strcmp(passphrase1, passphrase2) != 0) {
1387 explicit_bzero(passphrase1, strlen(passphrase1));
1388 explicit_bzero(passphrase2, strlen(passphrase2));
1389 free(passphrase1);
1390 free(passphrase2);
1391 printf("Pass phrases do not match. Try again.\n");
1392 exit(1);
1393 }
1394 /* Destroy the other copy. */
1395 freezero(passphrase2, strlen(passphrase2));
1396 }
1397
1398 /* Save the file using the new passphrase. */
1399 if ((r = sshkey_save_private(private, identity_file, passphrase1,
1400 comment, private_key_format, openssh_format_cipher, rounds)) != 0) {
1401 error_r(r, "Saving key \"%s\" failed", identity_file);
1402 freezero(passphrase1, strlen(passphrase1));
1403 sshkey_free(private);
1404 free(comment);
1405 exit(1);
1406 }
1407 /* Destroy the passphrase and the copy of the key in memory. */
1408 freezero(passphrase1, strlen(passphrase1));
1409 sshkey_free(private); /* Destroys contents */
1410 free(comment);
1411
1412 printf("Your identification has been saved with the new passphrase.\n");
1413 exit(0);
1414}
1415
1416/*
1417 * Print the SSHFP RR.
1418 */
1419static int
1420do_print_resource_record(struct passwd *pw, char *fname, char *hname,
1421 int print_generic, char * const *opts, size_t nopts)
1422{
1423 struct sshkey *public;
1424 char *comment = NULL;
1425 const char *p;
1426 struct stat st;
1427 int r, hash = -1;
1428 size_t i;
1429
1430 for (i = 0; i < nopts; i++) {
1431 if ((p = strprefix(opts[i], "hashalg=", 1)) != NULL) {
1432 if ((hash = ssh_digest_alg_by_name(p)) == -1)
1433 fatal("Unsupported hash algorithm");
1434 } else {
1435 error("Invalid option \"%s\"", opts[i]);
1436 return SSH_ERR_INVALID_ARGUMENT;
1437 }
1438 }
1439 if (fname == NULL)
1440 fatal_f("no filename");
1441 if (stat(fname, &st) == -1) {
1442 if (errno == ENOENT)
1443 return 0;
1444 fatal("%s: %s", fname, strerror(errno));
1445 }
1446 if ((r = sshkey_load_public(fname, &public, &comment)) != 0)
1447 fatal_r(r, "Failed to read v2 public key from \"%s\"", fname);
1448 export_dns_rr(hname, public, stdout, print_generic, hash);
1449 sshkey_free(public);
1450 free(comment);
1451 return 1;
1452}
1453
1454/*
1455 * Change the comment of a private key file.
1456 */
1457static void
1458do_change_comment(struct passwd *pw, const char *identity_comment)
1459{
1460 char new_comment[1024], *comment, *passphrase;
1461 struct sshkey *private;
1462 struct sshkey *public;
1463 struct stat st;
1464 int r;
1465
1466 if (!have_identity)
1467 ask_filename(pw, "Enter file in which the key is");
1468 if (stat(identity_file, &st) == -1)
1469 fatal("%s: %s", identity_file, strerror(errno));
1470 if ((r = sshkey_load_private(identity_file, "",
1471 &private, &comment)) == 0)
1472 passphrase = xstrdup("");
1473 else if (r != SSH_ERR_KEY_WRONG_PASSPHRASE)
1474 fatal_r(r, "Cannot load private key \"%s\"", identity_file);
1475 else {
1476 if (identity_passphrase)
1477 passphrase = xstrdup(identity_passphrase);
1478 else if (identity_new_passphrase)
1479 passphrase = xstrdup(identity_new_passphrase);
1480 else
1481 passphrase = read_passphrase("Enter passphrase: ",
1482 RP_ALLOW_STDIN);
1483 /* Try to load using the passphrase. */
1484 if ((r = sshkey_load_private(identity_file, passphrase,
1485 &private, &comment)) != 0) {
1486 freezero(passphrase, strlen(passphrase));
1487 fatal_r(r, "Cannot load private key \"%s\"",
1488 identity_file);
1489 }
1490 }
1491
1492 if (private->type != KEY_ED25519 &&
1493 private_key_format != SSHKEY_PRIVATE_OPENSSH) {
1494 error("Comments are only supported for keys stored in "
1495 "the new format (-o).");
1496 explicit_bzero(passphrase, strlen(passphrase));
1497 sshkey_free(private);
1498 exit(1);
1499 }
1500 if (comment)
1501 printf("Old comment: %s\n", comment);
1502 else
1503 printf("No existing comment\n");
1504
1505 if (identity_comment) {
1506 strlcpy(new_comment, identity_comment, sizeof(new_comment));
1507 } else {
1508 printf("New comment: ");
1509 fflush(stdout);
1510 if (!fgets(new_comment, sizeof(new_comment), stdin)) {
1511 explicit_bzero(passphrase, strlen(passphrase));
1512 sshkey_free(private);
1513 exit(1);
1514 }
1515 new_comment[strcspn(new_comment, "\n")] = '\0';
1516 }
1517 if (comment != NULL && strcmp(comment, new_comment) == 0) {
1518 printf("No change to comment\n");
1519 free(passphrase);
1520 sshkey_free(private);
1521 free(comment);
1522 exit(0);
1523 }
1524
1525 /* Save the file using the new passphrase. */
1526 if ((r = sshkey_save_private(private, identity_file, passphrase,
1527 new_comment, private_key_format, openssh_format_cipher,
1528 rounds)) != 0) {
1529 error_r(r, "Saving key \"%s\" failed", identity_file);
1530 freezero(passphrase, strlen(passphrase));
1531 sshkey_free(private);
1532 free(comment);
1533 exit(1);
1534 }
1535 freezero(passphrase, strlen(passphrase));
1536 if ((r = sshkey_from_private(private, &public)) != 0)
1537 fatal_fr(r, "sshkey_from_private");
1538 sshkey_free(private);
1539
1540 strlcat(identity_file, ".pub", sizeof(identity_file));
1541 if ((r = sshkey_save_public(public, identity_file, new_comment)) != 0)
1542 fatal_r(r, "Unable to save public key to %s", identity_file);
1543 sshkey_free(public);
1544 free(comment);
1545
1546 if (strlen(new_comment) > 0)
1547 printf("Comment '%s' applied\n", new_comment);
1548 else
1549 printf("Comment removed\n");
1550
1551 exit(0);
1552}
1553
1554static void
1555cert_ext_add(const char *key, const char *value, int iscrit)
1556{
1557 cert_ext = xreallocarray(cert_ext, ncert_ext + 1, sizeof(*cert_ext));
1558 cert_ext[ncert_ext].key = xstrdup(key);
1559 cert_ext[ncert_ext].val = value == NULL ? NULL : xstrdup(value);
1560 cert_ext[ncert_ext].crit = iscrit;
1561 ncert_ext++;
1562}
1563
1564/* qsort(3) comparison function for certificate extensions */
1565static int
1566cert_ext_cmp(const void *_a, const void *_b)
1567{
1568 const struct cert_ext *a = (const struct cert_ext *)_a;
1569 const struct cert_ext *b = (const struct cert_ext *)_b;
1570 int r;
1571
1572 if (a->crit != b->crit)
1573 return (a->crit < b->crit) ? -1 : 1;
1574 if ((r = strcmp(a->key, b->key)) != 0)
1575 return r;
1576 if ((a->val == NULL) != (b->val == NULL))
1577 return (a->val == NULL) ? -1 : 1;
1578 if (a->val != NULL && (r = strcmp(a->val, b->val)) != 0)
1579 return r;
1580 return 0;
1581}
1582
1583#define OPTIONS_CRITICAL 1
1584#define OPTIONS_EXTENSIONS 2
1585static void
1586prepare_options_buf(struct sshbuf *c, int which)
1587{
1588 struct sshbuf *b;
1589 size_t i;
1590 int r;
1591 const struct cert_ext *ext;
1592
1593 if ((b = sshbuf_new()) == NULL)
1594 fatal_f("sshbuf_new failed");
1595 sshbuf_reset(c);
1596 for (i = 0; i < ncert_ext; i++) {
1597 ext = &cert_ext[i];
1598 if ((ext->crit && (which & OPTIONS_EXTENSIONS)) ||
1599 (!ext->crit && (which & OPTIONS_CRITICAL)))
1600 continue;
1601 if (ext->val == NULL) {
1602 /* flag option */
1603 debug3_f("%s", ext->key);
1604 if ((r = sshbuf_put_cstring(c, ext->key)) != 0 ||
1605 (r = sshbuf_put_string(c, NULL, 0)) != 0)
1606 fatal_fr(r, "prepare flag");
1607 } else {
1608 /* key/value option */
1609 debug3_f("%s=%s", ext->key, ext->val);
1610 sshbuf_reset(b);
1611 if ((r = sshbuf_put_cstring(c, ext->key)) != 0 ||
1612 (r = sshbuf_put_cstring(b, ext->val)) != 0 ||
1613 (r = sshbuf_put_stringb(c, b)) != 0)
1614 fatal_fr(r, "prepare k/v");
1615 }
1616 }
1617 sshbuf_free(b);
1618}
1619
1620static void
1621finalise_cert_exts(void)
1622{
1623 /* critical options */
1624 if (certflags_command != NULL)
1625 cert_ext_add("force-command", certflags_command, 1);
1626 if (certflags_src_addr != NULL)
1627 cert_ext_add("source-address", certflags_src_addr, 1);
1628 if ((certflags_flags & CERTOPT_REQUIRE_VERIFY) != 0)
1629 cert_ext_add("verify-required", NULL, 1);
1630 /* extensions */
1631 if ((certflags_flags & CERTOPT_X_FWD) != 0)
1632 cert_ext_add("permit-X11-forwarding", NULL, 0);
1633 if ((certflags_flags & CERTOPT_AGENT_FWD) != 0)
1634 cert_ext_add("permit-agent-forwarding", NULL, 0);
1635 if ((certflags_flags & CERTOPT_PORT_FWD) != 0)
1636 cert_ext_add("permit-port-forwarding", NULL, 0);
1637 if ((certflags_flags & CERTOPT_PTY) != 0)
1638 cert_ext_add("permit-pty", NULL, 0);
1639 if ((certflags_flags & CERTOPT_USER_RC) != 0)
1640 cert_ext_add("permit-user-rc", NULL, 0);
1641 if ((certflags_flags & CERTOPT_NO_REQUIRE_USER_PRESENCE) != 0)
1642 cert_ext_add("no-touch-required", NULL, 0);
1643 /* order lexically by key */
1644 if (ncert_ext > 0)
1645 qsort(cert_ext, ncert_ext, sizeof(*cert_ext), cert_ext_cmp);
1646}
1647
1648static struct sshkey *
1649load_pkcs11_key(char *path)
1650{
1651#ifdef ENABLE_PKCS11
1652 struct sshkey **keys = NULL, *public, *private = NULL;
1653 int r, i, nkeys;
1654
1655 if ((r = sshkey_load_public(path, &public, NULL)) != 0)
1656 fatal_r(r, "Couldn't load CA public key \"%s\"", path);
1657
1658 nkeys = pkcs11_add_provider(pkcs11provider, identity_passphrase,
1659 &keys, NULL);
1660 debug3_f("%d keys", nkeys);
1661 if (nkeys <= 0)
1662 fatal("cannot read public key from pkcs11");
1663 for (i = 0; i < nkeys; i++) {
1664 if (sshkey_equal_public(public, keys[i])) {
1665 private = keys[i];
1666 continue;
1667 }
1668 sshkey_free(keys[i]);
1669 }
1670 free(keys);
1671 sshkey_free(public);
1672 return private;
1673#else
1674 fatal("no pkcs11 support");
1675#endif /* ENABLE_PKCS11 */
1676}
1677
1678/* Signer for sshkey_certify_custom that uses the agent */
1679static int
1680agent_signer(struct sshkey *key, u_char **sigp, size_t *lenp,
1681 const u_char *data, size_t datalen,
1682 const char *alg, const char *provider, const char *pin,
1683 u_int compat, void *ctx)
1684{
1685 int *agent_fdp = (int *)ctx;
1686
1687 return ssh_agent_sign(*agent_fdp, key, sigp, lenp,
1688 data, datalen, alg, compat);
1689}
1690
1691static void
1692do_ca_sign(struct passwd *pw, const char *ca_key_path, int prefer_agent,
1693 unsigned long long cert_serial, int cert_serial_autoinc,
1694 int argc, char **argv)
1695{
1696 int r, i, key_in_agent = 0, agent_fd = -1;
1697 u_int n;
1698 struct sshkey *ca, *public;
1699 char valid[64], *otmp, *tmp, *cp, *out, *comment;
1700 char *ca_fp = NULL, **plist = NULL, *pin = NULL;
1701 struct ssh_identitylist *agent_ids;
1702 size_t j;
1703 struct notifier_ctx *notifier = NULL;
1704
1705#ifdef ENABLE_PKCS11
1706 pkcs11_init(1);
1707#endif
1708 tmp = tilde_expand_filename(ca_key_path, pw->pw_uid);
1709 if (pkcs11provider != NULL) {
1710 /* If a PKCS#11 token was specified then try to use it */
1711 if ((ca = load_pkcs11_key(tmp)) == NULL)
1712 fatal("No PKCS#11 key matching %s found", ca_key_path);
1713 } else if (prefer_agent) {
1714 /*
1715 * Agent signature requested. Try to use agent after making
1716 * sure the public key specified is actually present in the
1717 * agent.
1718 */
1719 if ((r = sshkey_load_public(tmp, &ca, NULL)) != 0)
1720 fatal_r(r, "Cannot load CA public key %s", tmp);
1721 if ((r = ssh_get_authentication_socket(&agent_fd)) != 0)
1722 fatal_r(r, "Cannot use public key for CA signature");
1723 if ((r = ssh_fetch_identitylist(agent_fd, &agent_ids)) != 0)
1724 fatal_r(r, "Retrieve agent key list");
1725 for (j = 0; j < agent_ids->nkeys; j++) {
1726 if (sshkey_equal(ca, agent_ids->keys[j])) {
1727 key_in_agent = 1;
1728 /* Replace the CA key with the agent one */
1729 sshkey_free(ca);
1730 ca = agent_ids->keys[j];
1731 agent_ids->keys[j] = NULL;
1732 break;
1733 }
1734 }
1735 if (!key_in_agent)
1736 fatal("CA key %s not found in agent", tmp);
1737 ssh_free_identitylist(agent_ids);
1738 } else {
1739 /* CA key is assumed to be a private key on the filesystem */
1740 ca = load_identity(tmp, NULL);
1741 if (sshkey_is_sk(ca) &&
1742 (ca->sk_flags & SSH_SK_USER_VERIFICATION_REQD)) {
1743 if ((pin = read_passphrase("Enter PIN for CA key: ",
1744 RP_ALLOW_STDIN)) == NULL)
1745 fatal_f("couldn't read PIN");
1746 }
1747 }
1748 free(tmp);
1749
1750 if (key_type_name != NULL) {
1751 if (sshkey_type_from_shortname(key_type_name) != ca->type) {
1752 fatal("CA key type %s doesn't match specified %s",
1753 sshkey_ssh_name(ca), key_type_name);
1754 }
1755 } else if (ca->type == KEY_RSA) {
1756 /* Default to a good signature algorithm */
1757 key_type_name = "rsa-sha2-512";
1758 }
1759 ca_fp = sshkey_fingerprint(ca, fingerprint_hash, SSH_FP_DEFAULT);
1760
1761 finalise_cert_exts();
1762 for (i = 0; i < argc; i++) {
1763 /* Split list of principals */
1764 n = 0;
1765 if (cert_principals != NULL) {
1766 otmp = tmp = xstrdup(cert_principals);
1767 plist = NULL;
1768 for (; (cp = strsep(&tmp, ",")) != NULL; n++) {
1769 plist = xreallocarray(plist, n + 1, sizeof(*plist));
1770 if (*(plist[n] = xstrdup(cp)) == '\0')
1771 fatal("Empty principal name");
1772 }
1773 free(otmp);
1774 }
1775 if (n > SSHKEY_CERT_MAX_PRINCIPALS)
1776 fatal("Too many certificate principals specified");
1777
1778 tmp = tilde_expand_filename(argv[i], pw->pw_uid);
1779 if ((r = sshkey_load_public(tmp, &public, &comment)) != 0)
1780 fatal_r(r, "load pubkey \"%s\"", tmp);
1781 if (sshkey_is_cert(public))
1782 fatal_f("key \"%s\" type %s cannot be certified",
1783 tmp, sshkey_type(public));
1784
1785 /* Prepare certificate to sign */
1786 if ((r = sshkey_to_certified(public)) != 0)
1787 fatal_r(r, "Could not upgrade key %s to certificate", tmp);
1788 public->cert->type = cert_key_type;
1789 public->cert->serial = (u_int64_t)cert_serial;
1790 public->cert->key_id = xstrdup(cert_key_id);
1791 public->cert->nprincipals = n;
1792 public->cert->principals = plist;
1793 public->cert->valid_after = cert_valid_from;
1794 public->cert->valid_before = cert_valid_to;
1795 prepare_options_buf(public->cert->critical, OPTIONS_CRITICAL);
1796 prepare_options_buf(public->cert->extensions,
1797 OPTIONS_EXTENSIONS);
1798 if ((r = sshkey_from_private(ca,
1799 &public->cert->signature_key)) != 0)
1800 fatal_r(r, "sshkey_from_private (ca key)");
1801
1802 if (key_in_agent) {
1803 if ((r = sshkey_certify_custom(public, ca,
1804 key_type_name, sk_provider, NULL, agent_signer,
1805 &agent_fd)) != 0)
1806 fatal_r(r, "Couldn't certify %s via agent", tmp);
1807 } else {
1808 if (sshkey_is_sk(ca) &&
1809 (ca->sk_flags & SSH_SK_USER_PRESENCE_REQD)) {
1810 notifier = notify_start(0,
1811 "Confirm user presence for key %s %s",
1812 sshkey_type(ca), ca_fp);
1813 }
1814 r = sshkey_certify(public, ca, key_type_name,
1815 sk_provider, pin);
1816 notify_complete(notifier, "User presence confirmed");
1817 if (r != 0)
1818 fatal_r(r, "Couldn't certify key %s", tmp);
1819 }
1820
1821 if ((cp = strrchr(tmp, '.')) != NULL && strcmp(cp, ".pub") == 0)
1822 *cp = '\0';
1823 xasprintf(&out, "%s-cert.pub", tmp);
1824 free(tmp);
1825
1826 if ((r = sshkey_save_public(public, out, comment)) != 0) {
1827 fatal_r(r, "Unable to save public key to %s",
1828 identity_file);
1829 }
1830
1831 if (!quiet) {
1832 sshkey_format_cert_validity(public->cert,
1833 valid, sizeof(valid));
1834 logit("Signed %s key %s: id \"%s\" serial %llu%s%s "
1835 "valid %s", sshkey_cert_type(public),
1836 out, public->cert->key_id,
1837 (unsigned long long)public->cert->serial,
1838 cert_principals != NULL ? " for " : "",
1839 cert_principals != NULL ? cert_principals : "",
1840 valid);
1841 }
1842
1843 sshkey_free(public);
1844 free(out);
1845 free(comment);
1846 if (cert_serial_autoinc)
1847 cert_serial++;
1848 }
1849 if (pin != NULL)
1850 freezero(pin, strlen(pin));
1851 sshkey_free(ca);
1852 free(ca_fp);
1853#ifdef ENABLE_PKCS11
1854 pkcs11_terminate();
1855#endif
1856}
1857
1858static u_int64_t
1859parse_relative_time(const char *s, time_t now)
1860{
1861 int64_t mul, secs;
1862
1863 mul = *s == '-' ? -1 : 1;
1864
1865 if ((secs = convtime(s + 1)) == -1)
1866 fatal("Invalid relative certificate time %s", s);
1867 if (mul == -1 && secs > now)
1868 fatal("Certificate time %s cannot be represented", s);
1869 return now + (u_int64_t)(secs * mul);
1870}
1871
1872static void
1873parse_hex_u64(const char *s, uint64_t *up)
1874{
1875 char *ep;
1876 unsigned long long ull;
1877
1878 errno = 0;
1879 ull = strtoull(s, &ep, 16);
1880 if (*s == '\0' || *ep != '\0')
1881 fatal("Invalid certificate time: not a number");
1882 if (errno == ERANGE && ull == ULONG_MAX)
1883 fatal_fr(SSH_ERR_SYSTEM_ERROR, "Invalid certificate time");
1884 *up = (uint64_t)ull;
1885}
1886
1887static void
1888parse_cert_times(char *timespec)
1889{
1890 char *from, *to;
1891 time_t now = time(NULL);
1892 int64_t secs;
1893
1894 /* +timespec relative to now */
1895 if (*timespec == '+' && strchr(timespec, ':') == NULL) {
1896 if ((secs = convtime(timespec + 1)) == -1)
1897 fatal("Invalid relative certificate life %s", timespec);
1898 cert_valid_to = now + secs;
1899 /*
1900 * Backdate certificate one minute to avoid problems on hosts
1901 * with poorly-synchronised clocks.
1902 */
1903 cert_valid_from = ((now - 59)/ 60) * 60;
1904 return;
1905 }
1906
1907 /*
1908 * from:to, where
1909 * from := [+-]timespec | YYYYMMDD | YYYYMMDDHHMMSS | 0x... | "always"
1910 * to := [+-]timespec | YYYYMMDD | YYYYMMDDHHMMSS | 0x... | "forever"
1911 */
1912 from = xstrdup(timespec);
1913 to = strchr(from, ':');
1914 if (to == NULL || from == to || *(to + 1) == '\0')
1915 fatal("Invalid certificate life specification %s", timespec);
1916 *to++ = '\0';
1917
1918 if (*from == '-' || *from == '+')
1919 cert_valid_from = parse_relative_time(from, now);
1920 else if (strcmp(from, "always") == 0)
1921 cert_valid_from = 0;
1922 else if (strncmp(from, "0x", 2) == 0)
1923 parse_hex_u64(from, &cert_valid_from);
1924 else if (parse_absolute_time(from, &cert_valid_from) != 0)
1925 fatal("Invalid from time \"%s\"", from);
1926
1927 if (*to == '-' || *to == '+')
1928 cert_valid_to = parse_relative_time(to, now);
1929 else if (strcmp(to, "forever") == 0)
1930 cert_valid_to = ~(u_int64_t)0;
1931 else if (strncmp(to, "0x", 2) == 0)
1932 parse_hex_u64(to, &cert_valid_to);
1933 else if (parse_absolute_time(to, &cert_valid_to) != 0)
1934 fatal("Invalid to time \"%s\"", to);
1935
1936 if (cert_valid_to <= cert_valid_from)
1937 fatal("Empty certificate validity interval");
1938 free(from);
1939}
1940
1941static void
1942add_cert_option(char *opt)
1943{
1944 char *val, *cp;
1945 const char *p;
1946 int iscrit = 0;
1947
1948 if (strcasecmp(opt, "clear") == 0)
1949 certflags_flags = 0;
1950 else if (strcasecmp(opt, "no-x11-forwarding") == 0)
1951 certflags_flags &= ~CERTOPT_X_FWD;
1952 else if (strcasecmp(opt, "permit-x11-forwarding") == 0)
1953 certflags_flags |= CERTOPT_X_FWD;
1954 else if (strcasecmp(opt, "no-agent-forwarding") == 0)
1955 certflags_flags &= ~CERTOPT_AGENT_FWD;
1956 else if (strcasecmp(opt, "permit-agent-forwarding") == 0)
1957 certflags_flags |= CERTOPT_AGENT_FWD;
1958 else if (strcasecmp(opt, "no-port-forwarding") == 0)
1959 certflags_flags &= ~CERTOPT_PORT_FWD;
1960 else if (strcasecmp(opt, "permit-port-forwarding") == 0)
1961 certflags_flags |= CERTOPT_PORT_FWD;
1962 else if (strcasecmp(opt, "no-pty") == 0)
1963 certflags_flags &= ~CERTOPT_PTY;
1964 else if (strcasecmp(opt, "permit-pty") == 0)
1965 certflags_flags |= CERTOPT_PTY;
1966 else if (strcasecmp(opt, "no-user-rc") == 0)
1967 certflags_flags &= ~CERTOPT_USER_RC;
1968 else if (strcasecmp(opt, "permit-user-rc") == 0)
1969 certflags_flags |= CERTOPT_USER_RC;
1970 else if (strcasecmp(opt, "touch-required") == 0)
1971 certflags_flags &= ~CERTOPT_NO_REQUIRE_USER_PRESENCE;
1972 else if (strcasecmp(opt, "no-touch-required") == 0)
1973 certflags_flags |= CERTOPT_NO_REQUIRE_USER_PRESENCE;
1974 else if (strcasecmp(opt, "no-verify-required") == 0)
1975 certflags_flags &= ~CERTOPT_REQUIRE_VERIFY;
1976 else if (strcasecmp(opt, "verify-required") == 0)
1977 certflags_flags |= CERTOPT_REQUIRE_VERIFY;
1978 else if ((p = strprefix(opt, "force-command=", 1)) != NULL) {
1979 if (*p == '\0')
1980 fatal("Empty force-command option");
1981 if (certflags_command != NULL)
1982 fatal("force-command already specified");
1983 certflags_command = xstrdup(p);
1984 } else if ((p = strprefix(opt, "source-address=", 1)) != NULL) {
1985 if (*p == '\0')
1986 fatal("Empty source-address option");
1987 if (certflags_src_addr != NULL)
1988 fatal("source-address already specified");
1989 if (addr_match_cidr_list(NULL, p) != 0)
1990 fatal("Invalid source-address list");
1991 certflags_src_addr = xstrdup(p);
1992 } else if (strprefix(opt, "extension:", 1) != NULL ||
1993 (iscrit = (strprefix(opt, "critical:", 1) != NULL))) {
1994 val = xstrdup(strchr(opt, ':') + 1);
1995 if ((cp = strchr(val, '=')) != NULL)
1996 *cp++ = '\0';
1997 cert_ext_add(val, cp, iscrit);
1998 free(val);
1999 } else
2000 fatal("Unsupported certificate option \"%s\"", opt);
2001}
2002
2003static void
2004show_options(struct sshbuf *optbuf, int in_critical)
2005{
2006 char *name, *arg, *hex;
2007 struct sshbuf *options, *option = NULL;
2008 int r;
2009
2010 if ((options = sshbuf_fromb(optbuf)) == NULL)
2011 fatal_f("sshbuf_fromb failed");
2012 while (sshbuf_len(options) != 0) {
2013 sshbuf_free(option);
2014 option = NULL;
2015 if ((r = sshbuf_get_cstring(options, &name, NULL)) != 0 ||
2016 (r = sshbuf_froms(options, &option)) != 0)
2017 fatal_fr(r, "parse option");
2018 printf(" %s", name);
2019 if (!in_critical &&
2020 (strcmp(name, "permit-X11-forwarding") == 0 ||
2021 strcmp(name, "permit-agent-forwarding") == 0 ||
2022 strcmp(name, "permit-port-forwarding") == 0 ||
2023 strcmp(name, "permit-pty") == 0 ||
2024 strcmp(name, "permit-user-rc") == 0 ||
2025 strcmp(name, "no-touch-required") == 0)) {
2026 printf("\n");
2027 } else if (in_critical &&
2028 (strcmp(name, "force-command") == 0 ||
2029 strcmp(name, "source-address") == 0)) {
2030 if ((r = sshbuf_get_cstring(option, &arg, NULL)) != 0)
2031 fatal_fr(r, "parse critical");
2032 printf(" %s\n", arg);
2033 free(arg);
2034 } else if (in_critical &&
2035 strcmp(name, "verify-required") == 0) {
2036 printf("\n");
2037 } else if (sshbuf_len(option) > 0) {
2038 hex = sshbuf_dtob16(option);
2039 printf(" UNKNOWN OPTION: %s (len %zu)\n",
2040 hex, sshbuf_len(option));
2041 sshbuf_reset(option);
2042 free(hex);
2043 } else
2044 printf(" UNKNOWN FLAG OPTION\n");
2045 free(name);
2046 if (sshbuf_len(option) != 0)
2047 fatal("Option corrupt: extra data at end");
2048 }
2049 sshbuf_free(option);
2050 sshbuf_free(options);
2051}
2052
2053static void
2054print_cert(struct sshkey *key)
2055{
2056 char valid[64], *key_fp, *ca_fp;
2057 u_int i;
2058
2059 key_fp = sshkey_fingerprint(key, fingerprint_hash, SSH_FP_DEFAULT);
2060 ca_fp = sshkey_fingerprint(key->cert->signature_key,
2061 fingerprint_hash, SSH_FP_DEFAULT);
2062 if (key_fp == NULL || ca_fp == NULL)
2063 fatal_f("sshkey_fingerprint fail");
2064 sshkey_format_cert_validity(key->cert, valid, sizeof(valid));
2065
2066 printf(" Type: %s %s certificate\n", sshkey_ssh_name(key),
2067 sshkey_cert_type(key));
2068 printf(" Public key: %s %s\n", sshkey_type(key), key_fp);
2069 printf(" Signing CA: %s %s (using %s)\n",
2070 sshkey_type(key->cert->signature_key), ca_fp,
2071 key->cert->signature_type);
2072 printf(" Key ID: \"%s\"\n", key->cert->key_id);
2073 printf(" Serial: %llu\n", (unsigned long long)key->cert->serial);
2074 printf(" Valid: %s\n", valid);
2075 printf(" Principals: ");
2076 if (key->cert->nprincipals == 0)
2077 printf("(none)\n");
2078 else {
2079 for (i = 0; i < key->cert->nprincipals; i++)
2080 printf("\n %s",
2081 key->cert->principals[i]);
2082 printf("\n");
2083 }
2084 printf(" Critical Options: ");
2085 if (sshbuf_len(key->cert->critical) == 0)
2086 printf("(none)\n");
2087 else {
2088 printf("\n");
2089 show_options(key->cert->critical, 1);
2090 }
2091 printf(" Extensions: ");
2092 if (sshbuf_len(key->cert->extensions) == 0)
2093 printf("(none)\n");
2094 else {
2095 printf("\n");
2096 show_options(key->cert->extensions, 0);
2097 }
2098}
2099
2100static void
2101do_show_cert(struct passwd *pw)
2102{
2103 struct sshkey *key = NULL;
2104 struct stat st;
2105 int r, is_stdin = 0, ok = 0;
2106 FILE *f;
2107 char *cp, *line = NULL;
2108 const char *path;
2109 size_t linesize = 0;
2110 u_long lnum = 0;
2111
2112 if (!have_identity)
2113 ask_filename(pw, "Enter file in which the key is");
2114 if (strcmp(identity_file, "-") != 0 && stat(identity_file, &st) == -1)
2115 fatal("%s: %s: %s", __progname, identity_file, strerror(errno));
2116
2117 path = identity_file;
2118 if (strcmp(path, "-") == 0) {
2119 f = stdin;
2120 path = "(stdin)";
2121 is_stdin = 1;
2122 } else if ((f = fopen(identity_file, "r")) == NULL)
2123 fatal("fopen %s: %s", identity_file, strerror(errno));
2124
2125 while (getline(&line, &linesize, f) != -1) {
2126 lnum++;
2127 sshkey_free(key);
2128 key = NULL;
2129 /* Trim leading space and comments */
2130 cp = line + strspn(line, " \t");
2131 if (*cp == '#' || *cp == '\0')
2132 continue;
2133 if ((key = sshkey_new(KEY_UNSPEC)) == NULL)
2134 fatal("sshkey_new");
2135 if ((r = sshkey_read(key, &cp)) != 0) {
2136 error_r(r, "%s:%lu: invalid key", path, lnum);
2137 continue;
2138 }
2139 if (!sshkey_is_cert(key)) {
2140 error("%s:%lu is not a certificate", path, lnum);
2141 continue;
2142 }
2143 ok = 1;
2144 if (!is_stdin && lnum == 1)
2145 printf("%s:\n", path);
2146 else
2147 printf("%s:%lu:\n", path, lnum);
2148 print_cert(key);
2149 }
2150 free(line);
2151 sshkey_free(key);
2152 fclose(f);
2153 exit(ok ? 0 : 1);
2154}
2155
2156static void
2157load_krl(const char *path, struct ssh_krl **krlp)
2158{
2159 struct sshbuf *krlbuf;
2160 int r;
2161
2162 if ((r = sshbuf_load_file(path, &krlbuf)) != 0)
2163 fatal_r(r, "Unable to load KRL %s", path);
2164 /* XXX check sigs */
2165 if ((r = ssh_krl_from_blob(krlbuf, krlp)) != 0 ||
2166 *krlp == NULL)
2167 fatal_r(r, "Invalid KRL file %s", path);
2168 sshbuf_free(krlbuf);
2169}
2170
2171static void
2172hash_to_blob(const char *cp, u_char **blobp, size_t *lenp,
2173 const char *file, u_long lnum)
2174{
2175 char *tmp;
2176 size_t tlen;
2177 struct sshbuf *b;
2178 int r;
2179
2180 if ((cp = strprefix(cp, "SHA256:", 0)) == NULL)
2181 fatal("%s:%lu: unsupported hash algorithm", file, lnum);
2182
2183 /*
2184 * OpenSSH base64 hashes omit trailing '='
2185 * characters; put them back for decode.
2186 */
2187 if ((tlen = strlen(cp)) >= SIZE_MAX - 5)
2188 fatal_f("hash too long: %zu bytes", tlen);
2189 tmp = xmalloc(tlen + 4 + 1);
2190 strlcpy(tmp, cp, tlen + 1);
2191 while ((tlen % 4) != 0) {
2192 tmp[tlen++] = '=';
2193 tmp[tlen] = '\0';
2194 }
2195 if ((b = sshbuf_new()) == NULL)
2196 fatal_f("sshbuf_new failed");
2197 if ((r = sshbuf_b64tod(b, tmp)) != 0)
2198 fatal_r(r, "%s:%lu: decode hash failed", file, lnum);
2199 free(tmp);
2200 *lenp = sshbuf_len(b);
2201 *blobp = xmalloc(*lenp);
2202 memcpy(*blobp, sshbuf_ptr(b), *lenp);
2203 sshbuf_free(b);
2204}
2205
2206static void
2207update_krl_from_file(struct passwd *pw, const char *file, int wild_ca,
2208 const struct sshkey *ca, struct ssh_krl *krl)
2209{
2210 struct sshkey *key = NULL;
2211 u_long lnum = 0;
2212 char *path, *cp, *ep, *line = NULL;
2213 u_char *blob = NULL;
2214 size_t blen = 0, linesize = 0;
2215 unsigned long long serial, serial2;
2216 int i, was_explicit_key, was_sha1, was_sha256, was_hash, r;
2217 FILE *krl_spec;
2218
2219 path = tilde_expand_filename(file, pw->pw_uid);
2220 if (strcmp(path, "-") == 0) {
2221 krl_spec = stdin;
2222 free(path);
2223 path = xstrdup("(standard input)");
2224 } else if ((krl_spec = fopen(path, "r")) == NULL)
2225 fatal("fopen %s: %s", path, strerror(errno));
2226
2227 if (!quiet)
2228 printf("Revoking from %s\n", path);
2229 while (getline(&line, &linesize, krl_spec) != -1) {
2230 if (linesize >= INT_MAX) {
2231 fatal_f("%s contains unparsable line, len=%zu",
2232 path, linesize);
2233 }
2234 lnum++;
2235 was_explicit_key = was_sha1 = was_sha256 = was_hash = 0;
2236 cp = line + strspn(line, " \t");
2237 /* Trim trailing space, comments and strip \n */
2238 for (i = 0, r = -1; cp[i] != '\0'; i++) {
2239 if (cp[i] == '#' || cp[i] == '\n') {
2240 cp[i] = '\0';
2241 break;
2242 }
2243 if (cp[i] == ' ' || cp[i] == '\t') {
2244 /* Remember the start of a span of whitespace */
2245 if (r == -1)
2246 r = i;
2247 } else
2248 r = -1;
2249 }
2250 if (r != -1)
2251 cp[r] = '\0';
2252 if (*cp == '\0')
2253 continue;
2254 if (strncasecmp(cp, "serial:", 7) == 0) {
2255 if (ca == NULL && !wild_ca) {
2256 fatal("revoking certificates by serial number "
2257 "requires specification of a CA key");
2258 }
2259 cp += 7;
2260 cp = cp + strspn(cp, " \t");
2261 errno = 0;
2262 serial = strtoull(cp, &ep, 0);
2263 if (*cp == '\0' || (*ep != '\0' && *ep != '-'))
2264 fatal("%s:%lu: invalid serial \"%s\"",
2265 path, lnum, cp);
2266 if (errno == ERANGE && serial == ULLONG_MAX)
2267 fatal("%s:%lu: serial out of range",
2268 path, lnum);
2269 serial2 = serial;
2270 if (*ep == '-') {
2271 cp = ep + 1;
2272 errno = 0;
2273 serial2 = strtoull(cp, &ep, 0);
2274 if (*cp == '\0' || *ep != '\0')
2275 fatal("%s:%lu: invalid serial \"%s\"",
2276 path, lnum, cp);
2277 if (errno == ERANGE && serial2 == ULLONG_MAX)
2278 fatal("%s:%lu: serial out of range",
2279 path, lnum);
2280 if (serial2 <= serial)
2281 fatal("%s:%lu: invalid serial range "
2282 "%llu:%llu", path, lnum,
2283 (unsigned long long)serial,
2284 (unsigned long long)serial2);
2285 }
2286 if (ssh_krl_revoke_cert_by_serial_range(krl,
2287 ca, serial, serial2) != 0) {
2288 fatal_f("revoke serial failed");
2289 }
2290 } else if (strncasecmp(cp, "id:", 3) == 0) {
2291 if (ca == NULL && !wild_ca) {
2292 fatal("revoking certificates by key ID "
2293 "requires specification of a CA key");
2294 }
2295 cp += 3;
2296 cp = cp + strspn(cp, " \t");
2297 if (ssh_krl_revoke_cert_by_key_id(krl, ca, cp) != 0)
2298 fatal_f("revoke key ID failed");
2299 } else if (strncasecmp(cp, "hash:", 5) == 0) {
2300 cp += 5;
2301 cp = cp + strspn(cp, " \t");
2302 hash_to_blob(cp, &blob, &blen, file, lnum);
2303 if ((r = ssh_krl_revoke_key_sha256(krl,
2304 blob, blen)) != 0)
2305 fatal_fr(r, "revoke key failed");
2306 free(blob);
2307 blob = NULL;
2308 blen = 0;
2309 } else {
2310 if (strncasecmp(cp, "key:", 4) == 0) {
2311 cp += 4;
2312 cp = cp + strspn(cp, " \t");
2313 was_explicit_key = 1;
2314 } else if (strncasecmp(cp, "sha1:", 5) == 0) {
2315 cp += 5;
2316 cp = cp + strspn(cp, " \t");
2317 was_sha1 = 1;
2318 } else if (strncasecmp(cp, "sha256:", 7) == 0) {
2319 cp += 7;
2320 cp = cp + strspn(cp, " \t");
2321 was_sha256 = 1;
2322 /*
2323 * Just try to process the line as a key.
2324 * Parsing will fail if it isn't.
2325 */
2326 }
2327 if ((key = sshkey_new(KEY_UNSPEC)) == NULL)
2328 fatal("sshkey_new");
2329 if ((r = sshkey_read(key, &cp)) != 0)
2330 fatal_r(r, "%s:%lu: invalid key", path, lnum);
2331 if (was_explicit_key)
2332 r = ssh_krl_revoke_key_explicit(krl, key);
2333 else if (was_sha1) {
2334 if (sshkey_fingerprint_raw(key,
2335 SSH_DIGEST_SHA1, &blob, &blen) != 0) {
2336 fatal("%s:%lu: fingerprint failed",
2337 file, lnum);
2338 }
2339 r = ssh_krl_revoke_key_sha1(krl, blob, blen);
2340 } else if (was_sha256) {
2341 if (sshkey_fingerprint_raw(key,
2342 SSH_DIGEST_SHA256, &blob, &blen) != 0) {
2343 fatal("%s:%lu: fingerprint failed",
2344 file, lnum);
2345 }
2346 r = ssh_krl_revoke_key_sha256(krl, blob, blen);
2347 } else
2348 r = ssh_krl_revoke_key(krl, key);
2349 if (r != 0)
2350 fatal_fr(r, "revoke key failed");
2351 freezero(blob, blen);
2352 blob = NULL;
2353 blen = 0;
2354 sshkey_free(key);
2355 }
2356 }
2357 if (strcmp(path, "-") != 0)
2358 fclose(krl_spec);
2359 free(line);
2360 free(path);
2361}
2362
2363static void
2364do_gen_krl(struct passwd *pw, int updating, const char *ca_key_path,
2365 unsigned long long krl_version, const char *krl_comment,
2366 int argc, char **argv)
2367{
2368 struct ssh_krl *krl;
2369 struct stat sb;
2370 struct sshkey *ca = NULL;
2371 int i, r, wild_ca = 0;
2372 char *tmp;
2373 struct sshbuf *kbuf;
2374
2375 if (*identity_file == '\0')
2376 fatal("KRL generation requires an output file");
2377 if (stat(identity_file, &sb) == -1) {
2378 if (errno != ENOENT)
2379 fatal("Cannot access KRL \"%s\": %s",
2380 identity_file, strerror(errno));
2381 if (updating)
2382 fatal("KRL \"%s\" does not exist", identity_file);
2383 }
2384 if (ca_key_path != NULL) {
2385 if (strcasecmp(ca_key_path, "none") == 0)
2386 wild_ca = 1;
2387 else {
2388 tmp = tilde_expand_filename(ca_key_path, pw->pw_uid);
2389 if ((r = sshkey_load_public(tmp, &ca, NULL)) != 0)
2390 fatal_r(r, "Cannot load CA public key %s", tmp);
2391 free(tmp);
2392 }
2393 }
2394
2395 if (updating)
2396 load_krl(identity_file, &krl);
2397 else if ((krl = ssh_krl_init()) == NULL)
2398 fatal("couldn't create KRL");
2399
2400 if (krl_version != 0)
2401 ssh_krl_set_version(krl, krl_version);
2402 if (krl_comment != NULL)
2403 ssh_krl_set_comment(krl, krl_comment);
2404
2405 for (i = 0; i < argc; i++)
2406 update_krl_from_file(pw, argv[i], wild_ca, ca, krl);
2407
2408 if ((kbuf = sshbuf_new()) == NULL)
2409 fatal("sshbuf_new failed");
2410 if (ssh_krl_to_blob(krl, kbuf) != 0)
2411 fatal("Couldn't generate KRL");
2412 if ((r = sshbuf_write_file(identity_file, kbuf)) != 0)
2413 fatal("write %s: %s", identity_file, strerror(errno));
2414 sshbuf_free(kbuf);
2415 ssh_krl_free(krl);
2416 sshkey_free(ca);
2417}
2418
2419static void
2420do_check_krl(struct passwd *pw, int print_krl, int argc, char **argv)
2421{
2422 int i, r, ret = 0;
2423 char *comment;
2424 struct ssh_krl *krl;
2425 struct sshkey *k;
2426
2427 if (*identity_file == '\0')
2428 fatal("KRL checking requires an input file");
2429 load_krl(identity_file, &krl);
2430 if (print_krl)
2431 krl_dump(krl, stdout);
2432 for (i = 0; i < argc; i++) {
2433 if ((r = sshkey_load_public(argv[i], &k, &comment)) != 0)
2434 fatal_r(r, "Cannot load public key %s", argv[i]);
2435 r = ssh_krl_check_key(krl, k);
2436 printf("%s%s%s%s: %s\n", argv[i],
2437 *comment ? " (" : "", comment, *comment ? ")" : "",
2438 r == 0 ? "ok" : "REVOKED");
2439 if (r != 0)
2440 ret = 1;
2441 sshkey_free(k);
2442 free(comment);
2443 }
2444 ssh_krl_free(krl);
2445 exit(ret);
2446}
2447
2448static struct sshkey *
2449load_sign_key(const char *keypath, const struct sshkey *pubkey)
2450{
2451 size_t i, slen, plen = strlen(keypath);
2452 char *privpath = xstrdup(keypath);
2453 static const char * const suffixes[] = { "-cert.pub", ".pub", NULL };
2454 struct sshkey *ret = NULL, *privkey = NULL;
2455 int r, waspub = 0;
2456 struct stat st;
2457
2458 /*
2459 * If passed a public key filename, then try to locate the corresponding
2460 * private key. This lets us specify certificates on the command-line
2461 * and have ssh-keygen find the appropriate private key.
2462 */
2463 for (i = 0; suffixes[i]; i++) {
2464 slen = strlen(suffixes[i]);
2465 if (plen <= slen ||
2466 strcmp(privpath + plen - slen, suffixes[i]) != 0)
2467 continue;
2468 privpath[plen - slen] = '\0';
2469 debug_f("%s looks like a public key, using private key "
2470 "path %s instead", keypath, privpath);
2471 waspub = 1;
2472 }
2473 if (waspub && stat(privpath, &st) != 0 && errno == ENOENT)
2474 fatal("No private key found for public key \"%s\"", keypath);
2475 if ((r = sshkey_load_private(privpath, "", &privkey, NULL)) != 0 &&
2476 (r != SSH_ERR_KEY_WRONG_PASSPHRASE)) {
2477 debug_fr(r, "load private key \"%s\"", privpath);
2478 fatal("No private key found for \"%s\"", privpath);
2479 } else if (privkey == NULL)
2480 privkey = load_identity(privpath, NULL);
2481
2482 if (!sshkey_equal_public(pubkey, privkey)) {
2483 error("Public key %s doesn't match private %s",
2484 keypath, privpath);
2485 goto done;
2486 }
2487 if (sshkey_is_cert(pubkey) && !sshkey_is_cert(privkey)) {
2488 /*
2489 * Graft the certificate onto the private key to make
2490 * it capable of signing.
2491 */
2492 if ((r = sshkey_to_certified(privkey)) != 0) {
2493 error_fr(r, "sshkey_to_certified");
2494 goto done;
2495 }
2496 if ((r = sshkey_cert_copy(pubkey, privkey)) != 0) {
2497 error_fr(r, "sshkey_cert_copy");
2498 goto done;
2499 }
2500 }
2501 /* success */
2502 ret = privkey;
2503 privkey = NULL;
2504 done:
2505 sshkey_free(privkey);
2506 free(privpath);
2507 return ret;
2508}
2509
2510static int
2511sign_one(struct sshkey *signkey, const char *filename, int fd,
2512 const char *sig_namespace, const char *hashalg, sshsig_signer *signer,
2513 void *signer_ctx)
2514{
2515 struct sshbuf *sigbuf = NULL, *abuf = NULL;
2516 int r = SSH_ERR_INTERNAL_ERROR, wfd = -1, oerrno;
2517 char *wfile = NULL, *asig = NULL, *fp = NULL;
2518 char *pin = NULL, *prompt = NULL;
2519
2520 if (!quiet) {
2521 if (fd == STDIN_FILENO)
2522 fprintf(stderr, "Signing data on standard input\n");
2523 else
2524 fprintf(stderr, "Signing file %s\n", filename);
2525 }
2526 if (signer == NULL && sshkey_is_sk(signkey)) {
2527 if ((signkey->sk_flags & SSH_SK_USER_VERIFICATION_REQD)) {
2528 xasprintf(&prompt, "Enter PIN for %s key: ",
2529 sshkey_type(signkey));
2530 if ((pin = read_passphrase(prompt,
2531 RP_ALLOW_STDIN)) == NULL)
2532 fatal_f("couldn't read PIN");
2533 }
2534 if ((signkey->sk_flags & SSH_SK_USER_PRESENCE_REQD)) {
2535 if ((fp = sshkey_fingerprint(signkey, fingerprint_hash,
2536 SSH_FP_DEFAULT)) == NULL)
2537 fatal_f("fingerprint failed");
2538 fprintf(stderr, "Confirm user presence for key %s %s\n",
2539 sshkey_type(signkey), fp);
2540 free(fp);
2541 }
2542 }
2543 if ((r = sshsig_sign_fd(signkey, hashalg, sk_provider, pin,
2544 fd, sig_namespace, &sigbuf, signer, signer_ctx)) != 0) {
2545 error_r(r, "Signing %s failed", filename);
2546 goto out;
2547 }
2548 if ((r = sshsig_armor(sigbuf, &abuf)) != 0) {
2549 error_fr(r, "sshsig_armor");
2550 goto out;
2551 }
2552 if ((asig = sshbuf_dup_string(abuf)) == NULL) {
2553 error_f("buffer error");
2554 r = SSH_ERR_ALLOC_FAIL;
2555 goto out;
2556 }
2557
2558 if (fd == STDIN_FILENO) {
2559 fputs(asig, stdout);
2560 fflush(stdout);
2561 } else {
2562 xasprintf(&wfile, "%s.sig", filename);
2563 if (confirm_overwrite(wfile)) {
2564 if ((wfd = open(wfile, O_WRONLY|O_CREAT|O_TRUNC,
2565 0666)) == -1) {
2566 oerrno = errno;
2567 error("Cannot open %s: %s",
2568 wfile, strerror(errno));
2569 errno = oerrno;
2570 r = SSH_ERR_SYSTEM_ERROR;
2571 goto out;
2572 }
2573 if (atomicio(vwrite, wfd, asig,
2574 strlen(asig)) != strlen(asig)) {
2575 oerrno = errno;
2576 error("Cannot write to %s: %s",
2577 wfile, strerror(errno));
2578 errno = oerrno;
2579 r = SSH_ERR_SYSTEM_ERROR;
2580 goto out;
2581 }
2582 if (!quiet) {
2583 fprintf(stderr, "Write signature to %s\n",
2584 wfile);
2585 }
2586 }
2587 }
2588 /* success */
2589 r = 0;
2590 out:
2591 free(wfile);
2592 free(prompt);
2593 free(asig);
2594 if (pin != NULL)
2595 freezero(pin, strlen(pin));
2596 sshbuf_free(abuf);
2597 sshbuf_free(sigbuf);
2598 if (wfd != -1)
2599 close(wfd);
2600 return r;
2601}
2602
2603static int
2604sig_process_opts(char * const *opts, size_t nopts, char **hashalgp,
2605 uint64_t *verify_timep, int *print_pubkey)
2606{
2607 size_t i;
2608 time_t now;
2609 const char *p;
2610
2611 if (verify_timep != NULL)
2612 *verify_timep = 0;
2613 if (print_pubkey != NULL)
2614 *print_pubkey = 0;
2615 if (hashalgp != NULL)
2616 *hashalgp = NULL;
2617 for (i = 0; i < nopts; i++) {
2618 if (hashalgp != NULL &&
2619 (p = strprefix(opts[i], "hashalg=", 1)) != NULL) {
2620 *hashalgp = xstrdup(p);
2621 } else if (verify_timep &&
2622 (p = strprefix(opts[i], "verify-time=", 1)) != NULL) {
2623 if (parse_absolute_time(p, verify_timep) != 0 ||
2624 *verify_timep == 0) {
2625 error("Invalid \"verify-time\" option");
2626 return SSH_ERR_INVALID_ARGUMENT;
2627 }
2628 } else if (print_pubkey &&
2629 strcasecmp(opts[i], "print-pubkey") == 0) {
2630 *print_pubkey = 1;
2631 } else {
2632 error("Invalid option \"%s\"", opts[i]);
2633 return SSH_ERR_INVALID_ARGUMENT;
2634 }
2635 }
2636 if (verify_timep && *verify_timep == 0) {
2637 if ((now = time(NULL)) < 0) {
2638 error("Time is before epoch");
2639 return SSH_ERR_INVALID_ARGUMENT;
2640 }
2641 *verify_timep = (uint64_t)now;
2642 }
2643 return 0;
2644}
2645
2646
2647static int
2648sig_sign(const char *keypath, const char *sig_namespace, int require_agent,
2649 int argc, char **argv, char * const *opts, size_t nopts)
2650{
2651 int i, fd = -1, r, ret = -1;
2652 int agent_fd = -1;
2653 struct sshkey *pubkey = NULL, *privkey = NULL, *signkey = NULL;
2654 sshsig_signer *signer = NULL;
2655 char *hashalg = NULL;
2656
2657 /* Check file arguments. */
2658 for (i = 0; i < argc; i++) {
2659 if (strcmp(argv[i], "-") != 0)
2660 continue;
2661 if (i > 0 || argc > 1)
2662 fatal("Cannot sign mix of paths and standard input");
2663 }
2664
2665 if (sig_process_opts(opts, nopts, &hashalg, NULL, NULL) != 0)
2666 goto done; /* error already logged */
2667
2668 if ((r = sshkey_load_public(keypath, &pubkey, NULL)) != 0) {
2669 error_r(r, "Couldn't load public key %s", keypath);
2670 goto done;
2671 }
2672
2673 if ((r = ssh_get_authentication_socket(&agent_fd)) != 0) {
2674 if (require_agent)
2675 fatal("Couldn't get agent socket");
2676 debug_r(r, "Couldn't get agent socket");
2677 } else {
2678 if ((r = ssh_agent_has_key(agent_fd, pubkey)) == 0)
2679 signer = agent_signer;
2680 else {
2681 if (require_agent)
2682 fatal("Couldn't find key in agent");
2683 debug_r(r, "Couldn't find key in agent");
2684 }
2685 }
2686
2687 if (signer == NULL) {
2688 /* Not using agent - try to load private key */
2689 if ((privkey = load_sign_key(keypath, pubkey)) == NULL)
2690 goto done;
2691 signkey = privkey;
2692 } else {
2693 /* Will use key in agent */
2694 signkey = pubkey;
2695 }
2696
2697 if (argc == 0) {
2698 if ((r = sign_one(signkey, "(stdin)", STDIN_FILENO,
2699 sig_namespace, hashalg, signer, &agent_fd)) != 0)
2700 goto done;
2701 } else {
2702 for (i = 0; i < argc; i++) {
2703 if (strcmp(argv[i], "-") == 0)
2704 fd = STDIN_FILENO;
2705 else if ((fd = open(argv[i], O_RDONLY)) == -1) {
2706 error("Cannot open %s for signing: %s",
2707 argv[i], strerror(errno));
2708 goto done;
2709 }
2710 if ((r = sign_one(signkey, argv[i], fd, sig_namespace,
2711 hashalg, signer, &agent_fd)) != 0)
2712 goto done;
2713 if (fd != STDIN_FILENO)
2714 close(fd);
2715 fd = -1;
2716 }
2717 }
2718
2719 ret = 0;
2720done:
2721 if (fd != -1 && fd != STDIN_FILENO)
2722 close(fd);
2723 sshkey_free(pubkey);
2724 sshkey_free(privkey);
2725 free(hashalg);
2726 return ret;
2727}
2728
2729static int
2730sig_verify(const char *signature, const char *sig_namespace,
2731 const char *principal, const char *allowed_keys, const char *revoked_keys,
2732 char * const *opts, size_t nopts)
2733{
2734 int r, ret = -1;
2735 int print_pubkey = 0;
2736 struct sshbuf *sigbuf = NULL, *abuf = NULL;
2737 struct sshkey *sign_key = NULL;
2738 char *fp = NULL;
2739 struct sshkey_sig_details *sig_details = NULL;
2740 uint64_t verify_time = 0;
2741
2742 if (sig_process_opts(opts, nopts, NULL, &verify_time,
2743 &print_pubkey) != 0)
2744 goto done; /* error already logged */
2745
2746 memset(&sig_details, 0, sizeof(sig_details));
2747 if ((r = sshbuf_load_file(signature, &abuf)) != 0) {
2748 error_r(r, "Couldn't read signature file");
2749 goto done;
2750 }
2751
2752 if ((r = sshsig_dearmor(abuf, &sigbuf)) != 0) {
2753 error_fr(r, "sshsig_armor");
2754 goto done;
2755 }
2756 if ((r = sshsig_verify_fd(sigbuf, STDIN_FILENO, sig_namespace,
2757 &sign_key, &sig_details)) != 0)
2758 goto done; /* sshsig_verify() prints error */
2759
2760 if ((fp = sshkey_fingerprint(sign_key, fingerprint_hash,
2761 SSH_FP_DEFAULT)) == NULL)
2762 fatal_f("sshkey_fingerprint failed");
2763 debug("Valid (unverified) signature from key %s", fp);
2764 if (sig_details != NULL) {
2765 debug2_f("signature details: counter = %u, flags = 0x%02x",
2766 sig_details->sk_counter, sig_details->sk_flags);
2767 }
2768 free(fp);
2769 fp = NULL;
2770
2771 if (revoked_keys != NULL) {
2772 if ((r = sshkey_check_revoked(sign_key, revoked_keys)) != 0) {
2773 debug3_fr(r, "sshkey_check_revoked");
2774 goto done;
2775 }
2776 }
2777
2778 if (allowed_keys != NULL && (r = sshsig_check_allowed_keys(allowed_keys,
2779 sign_key, principal, sig_namespace, verify_time)) != 0) {
2780 debug3_fr(r, "sshsig_check_allowed_keys");
2781 goto done;
2782 }
2783 /* success */
2784 ret = 0;
2785done:
2786 if (!quiet) {
2787 if (ret == 0) {
2788 if ((fp = sshkey_fingerprint(sign_key, fingerprint_hash,
2789 SSH_FP_DEFAULT)) == NULL)
2790 fatal_f("sshkey_fingerprint failed");
2791 if (principal == NULL) {
2792 printf("Good \"%s\" signature with %s key %s\n",
2793 sig_namespace, sshkey_type(sign_key), fp);
2794
2795 } else {
2796 printf("Good \"%s\" signature for %s with %s key %s\n",
2797 sig_namespace, principal,
2798 sshkey_type(sign_key), fp);
2799 }
2800 } else {
2801 printf("Could not verify signature.\n");
2802 }
2803 }
2804 /* Print the signature key if requested */
2805 if (ret == 0 && print_pubkey && sign_key != NULL) {
2806 if ((r = sshkey_write(sign_key, stdout)) == 0)
2807 fputc('\n', stdout);
2808 else {
2809 error_r(r, "Could not print public key.\n");
2810 ret = -1;
2811 }
2812 }
2813 sshbuf_free(sigbuf);
2814 sshbuf_free(abuf);
2815 sshkey_free(sign_key);
2816 sshkey_sig_details_free(sig_details);
2817 free(fp);
2818 return ret;
2819}
2820
2821static int
2822sig_find_principals(const char *signature, const char *allowed_keys,
2823 char * const *opts, size_t nopts)
2824{
2825 int r, ret = -1;
2826 struct sshbuf *sigbuf = NULL, *abuf = NULL;
2827 struct sshkey *sign_key = NULL;
2828 char *principals = NULL, *cp, *tmp;
2829 uint64_t verify_time = 0;
2830
2831 if (sig_process_opts(opts, nopts, NULL, &verify_time, NULL) != 0)
2832 goto done; /* error already logged */
2833
2834 if ((r = sshbuf_load_file(signature, &abuf)) != 0) {
2835 error_r(r, "Couldn't read signature file");
2836 goto done;
2837 }
2838 if ((r = sshsig_dearmor(abuf, &sigbuf)) != 0) {
2839 error_fr(r, "sshsig_armor");
2840 goto done;
2841 }
2842 if ((r = sshsig_get_pubkey(sigbuf, &sign_key)) != 0) {
2843 error_fr(r, "sshsig_get_pubkey");
2844 goto done;
2845 }
2846 if ((r = sshsig_find_principals(allowed_keys, sign_key,
2847 verify_time, &principals)) != 0) {
2848 if (r != SSH_ERR_KEY_NOT_FOUND)
2849 error_fr(r, "sshsig_find_principal");
2850 goto done;
2851 }
2852 ret = 0;
2853done:
2854 if (ret == 0 ) {
2855 /* Emit matching principals one per line */
2856 tmp = principals;
2857 while ((cp = strsep(&tmp, ",")) != NULL && *cp != '\0')
2858 puts(cp);
2859 } else {
2860 fprintf(stderr, "No principal matched.\n");
2861 }
2862 sshbuf_free(sigbuf);
2863 sshbuf_free(abuf);
2864 sshkey_free(sign_key);
2865 free(principals);
2866 return ret;
2867}
2868
2869static int
2870sig_match_principals(const char *allowed_keys, char *principal,
2871 char * const *opts, size_t nopts)
2872{
2873 int r;
2874 char **principals = NULL;
2875 size_t i, nprincipals = 0;
2876
2877 if ((r = sig_process_opts(opts, nopts, NULL, NULL, NULL)) != 0)
2878 return r; /* error already logged */
2879
2880 if ((r = sshsig_match_principals(allowed_keys, principal,
2881 &principals, &nprincipals)) != 0) {
2882 debug_f("match: %s", ssh_err(r));
2883 fprintf(stderr, "No principal matched.\n");
2884 return r;
2885 }
2886 for (i = 0; i < nprincipals; i++) {
2887 printf("%s\n", principals[i]);
2888 free(principals[i]);
2889 }
2890 free(principals);
2891
2892 return 0;
2893}
2894
2895static void
2896do_moduli_gen(const char *out_file, char **opts, size_t nopts)
2897{
2898#ifdef WITH_OPENSSL
2899 /* Moduli generation/screening */
2900 BIGNUM *start = NULL;
2901 int moduli_bits = 0;
2902 FILE *out;
2903 size_t i;
2904 const char *errstr, *p;
2905
2906 /* Parse options */
2907 for (i = 0; i < nopts; i++) {
2908 if ((p = strprefix(opts[i], "start=", 0)) != NULL) {
2909 /* XXX - also compare length against bits */
2910 if (BN_hex2bn(&start, p) == 0)
2911 fatal("Invalid start point.");
2912 } else if ((p = strprefix(opts[i], "bits=", 0)) != NULL) {
2913 moduli_bits = (int)strtonum(p, 1, INT_MAX, &errstr);
2914 if (errstr) {
2915 fatal("Invalid number: %s (%s)", p, errstr);
2916 }
2917 } else {
2918 fatal("Option \"%s\" is unsupported for moduli "
2919 "generation", opts[i]);
2920 }
2921 }
2922
2923 if (strcmp(out_file, "-") == 0)
2924 out = stdout;
2925 else if ((out = fopen(out_file, "w")) == NULL) {
2926 fatal("Couldn't open modulus candidate file \"%s\": %s",
2927 out_file, strerror(errno));
2928 }
2929 setvbuf(out, NULL, _IOLBF, 0);
2930
2931 if (moduli_bits == 0)
2932 moduli_bits = DEFAULT_BITS;
2933 if (gen_candidates(out, moduli_bits, start) != 0)
2934 fatal("modulus candidate generation failed");
2935#else /* WITH_OPENSSL */
2936 fatal("Moduli generation is not supported");
2937#endif /* WITH_OPENSSL */
2938}
2939
2940static void
2941do_moduli_screen(const char *out_file, char **opts, size_t nopts)
2942{
2943#ifdef WITH_OPENSSL
2944 /* Moduli generation/screening */
2945 char *checkpoint = NULL;
2946 u_int32_t generator_wanted = 0;
2947 unsigned long start_lineno = 0, lines_to_process = 0;
2948 int prime_tests = 0;
2949 FILE *out, *in = stdin;
2950 size_t i;
2951 const char *errstr, *p;
2952
2953 /* Parse options */
2954 for (i = 0; i < nopts; i++) {
2955 if ((p = strprefix(opts[i], "lines=", 0)) != NULL) {
2956 lines_to_process = strtoul(p, NULL, 10);
2957 } else if ((p = strprefix(opts[i], "start-line=", 0)) != NULL) {
2958 start_lineno = strtoul(p, NULL, 10);
2959 } else if ((p = strprefix(opts[i], "checkpoint=", 0)) != NULL) {
2960 free(checkpoint);
2961 checkpoint = xstrdup(p);
2962 } else if ((p = strprefix(opts[i], "generator=", 0)) != NULL) {
2963 generator_wanted = (u_int32_t)strtonum(p, 1, UINT_MAX,
2964 &errstr);
2965 if (errstr != NULL) {
2966 fatal("Generator invalid: %s (%s)", p, errstr);
2967 }
2968 } else if ((p = strprefix(opts[i], "prime-tests=", 0)) != NULL) {
2969 prime_tests = (int)strtonum(p, 1, INT_MAX, &errstr);
2970 if (errstr) {
2971 fatal("Invalid number: %s (%s)", p, errstr);
2972 }
2973 } else {
2974 fatal("Option \"%s\" is unsupported for moduli "
2975 "screening", opts[i]);
2976 }
2977 }
2978
2979 if (have_identity && strcmp(identity_file, "-") != 0) {
2980 if ((in = fopen(identity_file, "r")) == NULL) {
2981 fatal("Couldn't open modulus candidate "
2982 "file \"%s\": %s", identity_file,
2983 strerror(errno));
2984 }
2985 }
2986
2987 if (strcmp(out_file, "-") == 0)
2988 out = stdout;
2989 else if ((out = fopen(out_file, "a")) == NULL) {
2990 fatal("Couldn't open moduli file \"%s\": %s",
2991 out_file, strerror(errno));
2992 }
2993 setvbuf(out, NULL, _IOLBF, 0);
2994 if (prime_test(in, out, prime_tests == 0 ? 100 : prime_tests,
2995 generator_wanted, checkpoint,
2996 start_lineno, lines_to_process) != 0)
2997 fatal("modulus screening failed");
2998 if (in != stdin)
2999 (void)fclose(in);
3000 free(checkpoint);
3001#else /* WITH_OPENSSL */
3002 fatal("Moduli screening is not supported");
3003#endif /* WITH_OPENSSL */
3004}
3005
3006/* Read and confirm a passphrase */
3007static char *
3008read_check_passphrase(const char *prompt1, const char *prompt2,
3009 const char *retry_prompt)
3010{
3011 char *passphrase1, *passphrase2;
3012
3013 for (;;) {
3014 passphrase1 = read_passphrase(prompt1, RP_ALLOW_STDIN);
3015 passphrase2 = read_passphrase(prompt2, RP_ALLOW_STDIN);
3016 if (strcmp(passphrase1, passphrase2) == 0) {
3017 freezero(passphrase2, strlen(passphrase2));
3018 return passphrase1;
3019 }
3020 /* The passphrases do not match. Clear them and retry. */
3021 freezero(passphrase1, strlen(passphrase1));
3022 freezero(passphrase2, strlen(passphrase2));
3023 fputs(retry_prompt, stdout);
3024 fputc('\n', stdout);
3025 fflush(stdout);
3026 }
3027 /* NOTREACHED */
3028 return NULL;
3029}
3030
3031static char *
3032private_key_passphrase(const char *path)
3033{
3034 char *prompt, *ret;
3035
3036 if (identity_passphrase)
3037 return xstrdup(identity_passphrase);
3038 if (identity_new_passphrase)
3039 return xstrdup(identity_new_passphrase);
3040
3041 xasprintf(&prompt, "Enter passphrase for \"%s\" "
3042 "(empty for no passphrase): ", path);
3043 ret = read_check_passphrase(prompt,
3044 "Enter same passphrase again: ",
3045 "Passphrases do not match. Try again.");
3046 free(prompt);
3047 return ret;
3048}
3049
3050static char *
3051sk_suffix(const char *application, const uint8_t *user, size_t userlen)
3052{
3053 char *ret, *cp;
3054 const char *p;
3055 size_t slen, i;
3056
3057 /* Trim off URL-like preamble */
3058 if ((p = strprefix(application, "ssh://", 0)) != NULL)
3059 ret = xstrdup(p);
3060 else if ((p = strprefix(application, "ssh:", 0)) != NULL)
3061 ret = xstrdup(p);
3062 else
3063 ret = xstrdup(application);
3064
3065 /* Count trailing zeros in user */
3066 for (i = 0; i < userlen; i++) {
3067 if (user[userlen - i - 1] != 0)
3068 break;
3069 }
3070 if (i >= userlen)
3071 return ret; /* user-id was default all-zeros */
3072
3073 /* Append user-id, escaping non-UTF-8 characters */
3074 slen = userlen - i;
3075 if (asmprintf(&cp, INT_MAX, NULL, "%.*s", (int)slen, user) == -1)
3076 fatal_f("asmprintf failed");
3077 /* Don't emit a user-id that contains path or control characters */
3078 if (strchr(cp, '/') != NULL || strstr(cp, "..") != NULL ||
3079 strchr(cp, '\\') != NULL) {
3080 free(cp);
3081 cp = tohex(user, slen);
3082 }
3083 xextendf(&ret, "_", "%s", cp);
3084 free(cp);
3085 return ret;
3086}
3087
3088static int
3089do_download_sk(const char *skprovider, const char *device)
3090{
3091 struct sshsk_resident_key **srks;
3092 size_t nsrks, i;
3093 int r, ret = -1;
3094 char *fp, *pin = NULL, *pass = NULL, *path, *pubpath;
3095 const char *ext;
3096 struct sshkey *key;
3097
3098 if (skprovider == NULL)
3099 fatal("Cannot download keys without provider");
3100
3101 pin = read_passphrase("Enter PIN for authenticator: ", RP_ALLOW_STDIN);
3102 if (!quiet) {
3103 printf("You may need to touch your authenticator "
3104 "to authorize key download.\n");
3105 }
3106 if ((r = sshsk_load_resident(skprovider, device, pin, 0,
3107 &srks, &nsrks)) != 0) {
3108 if (pin != NULL)
3109 freezero(pin, strlen(pin));
3110 error_r(r, "Unable to load resident keys");
3111 return -1;
3112 }
3113 if (nsrks == 0)
3114 logit("No keys to download");
3115 if (pin != NULL)
3116 freezero(pin, strlen(pin));
3117
3118 for (i = 0; i < nsrks; i++) {
3119 key = srks[i]->key;
3120 if (key->type != KEY_ECDSA_SK && key->type != KEY_ED25519_SK) {
3121 error("Unsupported key type %s (%d)",
3122 sshkey_type(key), key->type);
3123 continue;
3124 }
3125 if ((fp = sshkey_fingerprint(key, fingerprint_hash,
3126 SSH_FP_DEFAULT)) == NULL)
3127 fatal_f("sshkey_fingerprint failed");
3128 debug_f("key %zu: %s %s %s (flags 0x%02x)", i,
3129 sshkey_type(key), fp, key->sk_application, key->sk_flags);
3130 ext = sk_suffix(key->sk_application,
3131 srks[i]->user_id, srks[i]->user_id_len);
3132 xasprintf(&path, "id_%s_rk%s%s",
3133 key->type == KEY_ECDSA_SK ? "ecdsa_sk" : "ed25519_sk",
3134 *ext == '\0' ? "" : "_", ext);
3135
3136 /* If the file already exists, ask the user to confirm. */
3137 if (!confirm_overwrite(path)) {
3138 free(path);
3139 break;
3140 }
3141
3142 /* Save the key with the application string as the comment */
3143 if (pass == NULL)
3144 pass = private_key_passphrase(path);
3145 if ((r = sshkey_save_private(key, path, pass,
3146 key->sk_application, private_key_format,
3147 openssh_format_cipher, rounds)) != 0) {
3148 error_r(r, "Saving key \"%s\" failed", path);
3149 free(path);
3150 break;
3151 }
3152 if (!quiet) {
3153 printf("Saved %s key%s%s to %s\n", sshkey_type(key),
3154 *ext != '\0' ? " " : "",
3155 *ext != '\0' ? key->sk_application : "",
3156 path);
3157 }
3158
3159 /* Save public key too */
3160 xasprintf(&pubpath, "%s.pub", path);
3161 free(path);
3162 if ((r = sshkey_save_public(key, pubpath,
3163 key->sk_application)) != 0) {
3164 error_r(r, "Saving public key \"%s\" failed", pubpath);
3165 free(pubpath);
3166 break;
3167 }
3168 free(pubpath);
3169 }
3170
3171 if (i >= nsrks)
3172 ret = 0; /* success */
3173 if (pass != NULL)
3174 freezero(pass, strlen(pass));
3175 sshsk_free_resident_keys(srks, nsrks);
3176 return ret;
3177}
3178
3179static void
3180save_attestation(struct sshbuf *attest, const char *path)
3181{
3182 mode_t omask;
3183 int r;
3184
3185 if (path == NULL)
3186 return; /* nothing to do */
3187 if (attest == NULL || sshbuf_len(attest) == 0)
3188 fatal("Enrollment did not return attestation data");
3189 omask = umask(077);
3190 r = sshbuf_write_file(path, attest);
3191 umask(omask);
3192 if (r != 0)
3193 fatal_r(r, "Unable to write attestation data \"%s\"", path);
3194 if (!quiet)
3195 printf("Your FIDO attestation certificate has been saved in "
3196 "%s\n", path);
3197}
3198
3199static int
3200confirm_sk_overwrite(const char *application, const char *user)
3201{
3202 char yesno[3];
3203
3204 printf("A resident key scoped to '%s' with user id '%s' already "
3205 "exists.\n", application == NULL ? "ssh:" : application,
3206 user == NULL ? "null" : user);
3207 printf("Overwrite key in token (y/n)? ");
3208 fflush(stdout);
3209 if (fgets(yesno, sizeof(yesno), stdin) == NULL)
3210 return 0;
3211 if (yesno[0] != 'y' && yesno[0] != 'Y')
3212 return 0;
3213 return 1;
3214}
3215
3216static void
3217usage(void)
3218{
3219 fprintf(stderr,
3220 "usage: ssh-keygen [-q] [-a rounds] [-b bits] [-C comment] [-f output_keyfile]\n"
3221 " [-m format] [-N new_passphrase] [-O option]\n"
3222 " [-t ecdsa | ecdsa-sk | ed25519 | ed25519-sk | rsa]\n"
3223 " [-w provider] [-Z cipher]\n"
3224 " ssh-keygen -p [-a rounds] [-f keyfile] [-m format] [-N new_passphrase]\n"
3225 " [-P old_passphrase] [-Z cipher]\n"
3226#ifdef WITH_OPENSSL
3227 " ssh-keygen -i [-f input_keyfile] [-m key_format]\n"
3228 " ssh-keygen -e [-f input_keyfile] [-m key_format]\n"
3229#endif
3230 " ssh-keygen -y [-f input_keyfile]\n"
3231 " ssh-keygen -c [-a rounds] [-C comment] [-f keyfile] [-P passphrase]\n"
3232 " ssh-keygen -l [-v] [-E fingerprint_hash] [-f input_keyfile]\n"
3233 " ssh-keygen -B [-f input_keyfile]\n");
3234#ifdef ENABLE_PKCS11
3235 fprintf(stderr,
3236 " ssh-keygen -D pkcs11\n");
3237#endif
3238 fprintf(stderr,
3239 " ssh-keygen -F hostname [-lv] [-f known_hosts_file]\n"
3240 " ssh-keygen -H [-f known_hosts_file]\n"
3241 " ssh-keygen -K [-a rounds] [-w provider]\n"
3242 " ssh-keygen -R hostname [-f known_hosts_file]\n"
3243 " ssh-keygen -r hostname [-g] [-f input_keyfile]\n"
3244#ifdef WITH_OPENSSL
3245 " ssh-keygen -M generate [-O option] output_file\n"
3246 " ssh-keygen -M screen [-f input_file] [-O option] output_file\n"
3247#endif
3248 " ssh-keygen -I certificate_identity -s ca_key [-hU] [-D pkcs11_provider]\n"
3249 " [-n principals] [-O option] [-V validity_interval]\n"
3250 " [-z serial_number] file ...\n"
3251 " ssh-keygen -L [-f input_keyfile]\n"
3252 " ssh-keygen -A [-a rounds] [-f prefix_path]\n"
3253 " ssh-keygen -k -f krl_file [-u] [-s ca_public] [-z version_number]\n"
3254 " file ...\n"
3255 " ssh-keygen -Q [-l] -f krl_file [file ...]\n"
3256 " ssh-keygen -Y find-principals -s signature_file -f allowed_signers_file\n"
3257 " ssh-keygen -Y match-principals -I signer_identity -f allowed_signers_file\n"
3258 " ssh-keygen -Y check-novalidate -n namespace -s signature_file\n"
3259 " ssh-keygen -Y sign -f key_file -n namespace file [-O option] ...\n"
3260 " ssh-keygen -Y verify -f allowed_signers_file -I signer_identity\n"
3261 " -n namespace -s signature_file [-r krl_file] [-O option]\n");
3262 exit(1);
3263}
3264
3265/*
3266 * Main program for key management.
3267 */
3268int
3269main(int argc, char **argv)
3270{
3271 char comment[1024], *passphrase = NULL;
3272 char *rr_hostname = NULL, *ep, *fp, *ra;
3273 struct sshkey *private = NULL, *public = NULL;
3274 struct passwd *pw;
3275 int ret = 0, r, opt, type;
3276 int change_passphrase = 0, change_comment = 0, show_cert = 0;
3277 int find_host = 0, delete_host = 0, hash_hosts = 0;
3278 int gen_all_hostkeys = 0, gen_krl = 0, update_krl = 0, check_krl = 0;
3279 int prefer_agent = 0, convert_to = 0, convert_from = 0;
3280 int print_public = 0, print_generic = 0, cert_serial_autoinc = 0;
3281 int do_gen_candidates = 0, do_screen_candidates = 0, download_sk = 0;
3282 unsigned long long cert_serial = 0;
3283 char *identity_comment = NULL, *ca_key_path = NULL, **opts = NULL;
3284 char *sk_application = NULL, *sk_device = NULL, *sk_user = NULL;
3285 char *sk_attestation_path = NULL;
3286 struct sshbuf *challenge = NULL, *attest = NULL;
3287 size_t i, nopts = 0;
3288 u_int32_t bits = 0;
3289 uint8_t sk_flags = SSH_SK_USER_PRESENCE_REQD;
3290 const char *errstr, *p;
3291 int log_level = SYSLOG_LEVEL_INFO;
3292 char *sign_op = NULL;
3293
3294 extern int optind;
3295 extern char *optarg;
3296
3297 /* Ensure that fds 0, 1 and 2 are open or directed to /dev/null */
3298 sanitise_stdfd();
3299
3300 log_init(argv[0], SYSLOG_LEVEL_INFO, SYSLOG_FACILITY_USER, 1);
3301
3302 setlocale(LC_CTYPE, "");
3303
3304 /* we need this for the home * directory. */
3305 pw = getpwuid(getuid());
3306 if (!pw)
3307 fatal("No user exists for uid %lu", (u_long)getuid());
3308 pw = pwcopy(pw);
3309 if (gethostname(hostname, sizeof(hostname)) == -1)
3310 fatal("gethostname: %s", strerror(errno));
3311
3312 sk_provider = getenv("SSH_SK_PROVIDER");
3313
3314 /* Remaining characters: dGjJSTWx */
3315 while ((opt = getopt(argc, argv, "ABHKLQUXceghiklopquvy"
3316 "C:D:E:F:I:M:N:O:P:R:V:Y:Z:"
3317 "a:b:f:g:m:n:r:s:t:w:z:")) != -1) {
3318 switch (opt) {
3319 case 'A':
3320 gen_all_hostkeys = 1;
3321 break;
3322 case 'b':
3323 bits = (u_int32_t)strtonum(optarg, 1, UINT32_MAX,
3324 &errstr);
3325 if (errstr)
3326 fatal("Bits has bad value %s (%s)",
3327 optarg, errstr);
3328 break;
3329 case 'E':
3330 fingerprint_hash = ssh_digest_alg_by_name(optarg);
3331 if (fingerprint_hash == -1)
3332 fatal("Invalid hash algorithm \"%s\"", optarg);
3333 break;
3334 case 'F':
3335 find_host = 1;
3336 rr_hostname = optarg;
3337 break;
3338 case 'H':
3339 hash_hosts = 1;
3340 break;
3341 case 'I':
3342 cert_key_id = optarg;
3343 break;
3344 case 'R':
3345 delete_host = 1;
3346 rr_hostname = optarg;
3347 break;
3348 case 'L':
3349 show_cert = 1;
3350 break;
3351 case 'l':
3352 print_fingerprint = 1;
3353 break;
3354 case 'B':
3355 print_bubblebabble = 1;
3356 break;
3357 case 'm':
3358 if (strcasecmp(optarg, "RFC4716") == 0 ||
3359 strcasecmp(optarg, "ssh2") == 0) {
3360 convert_format = FMT_RFC4716;
3361 break;
3362 }
3363 if (strcasecmp(optarg, "PKCS8") == 0) {
3364 convert_format = FMT_PKCS8;
3365 private_key_format = SSHKEY_PRIVATE_PKCS8;
3366 break;
3367 }
3368 if (strcasecmp(optarg, "PEM") == 0) {
3369 convert_format = FMT_PEM;
3370 private_key_format = SSHKEY_PRIVATE_PEM;
3371 break;
3372 }
3373 fatal("Unsupported conversion format \"%s\"", optarg);
3374 case 'n':
3375 cert_principals = optarg;
3376 break;
3377 case 'o':
3378 /* no-op; new format is already the default */
3379 break;
3380 case 'p':
3381 change_passphrase = 1;
3382 break;
3383 case 'c':
3384 change_comment = 1;
3385 break;
3386 case 'f':
3387 if (strlcpy(identity_file, optarg,
3388 sizeof(identity_file)) >= sizeof(identity_file))
3389 fatal("Identity filename too long");
3390 have_identity = 1;
3391 break;
3392 case 'g':
3393 print_generic = 1;
3394 break;
3395 case 'K':
3396 download_sk = 1;
3397 break;
3398 case 'P':
3399 identity_passphrase = optarg;
3400 break;
3401 case 'N':
3402 identity_new_passphrase = optarg;
3403 break;
3404 case 'Q':
3405 check_krl = 1;
3406 break;
3407 case 'O':
3408 opts = xrecallocarray(opts, nopts, nopts + 1,
3409 sizeof(*opts));
3410 opts[nopts++] = xstrdup(optarg);
3411 break;
3412 case 'Z':
3413 openssh_format_cipher = optarg;
3414 if (cipher_by_name(openssh_format_cipher) == NULL)
3415 fatal("Invalid OpenSSH-format cipher '%s'",
3416 openssh_format_cipher);
3417 break;
3418 case 'C':
3419 identity_comment = optarg;
3420 break;
3421 case 'q':
3422 quiet = 1;
3423 break;
3424 case 'e':
3425 /* export key */
3426 convert_to = 1;
3427 break;
3428 case 'h':
3429 cert_key_type = SSH2_CERT_TYPE_HOST;
3430 certflags_flags = 0;
3431 break;
3432 case 'k':
3433 gen_krl = 1;
3434 break;
3435 case 'i':
3436 case 'X':
3437 /* import key */
3438 convert_from = 1;
3439 break;
3440 case 'y':
3441 print_public = 1;
3442 break;
3443 case 's':
3444 ca_key_path = optarg;
3445 break;
3446 case 't':
3447 key_type_name = optarg;
3448 break;
3449 case 'D':
3450 pkcs11provider = optarg;
3451 break;
3452 case 'U':
3453 prefer_agent = 1;
3454 break;
3455 case 'u':
3456 update_krl = 1;
3457 break;
3458 case 'v':
3459 if (log_level == SYSLOG_LEVEL_INFO)
3460 log_level = SYSLOG_LEVEL_DEBUG1;
3461 else {
3462 if (log_level >= SYSLOG_LEVEL_DEBUG1 &&
3463 log_level < SYSLOG_LEVEL_DEBUG3)
3464 log_level++;
3465 }
3466 break;
3467 case 'r':
3468 rr_hostname = optarg;
3469 break;
3470 case 'a':
3471 rounds = (int)strtonum(optarg, 1, INT_MAX, &errstr);
3472 if (errstr)
3473 fatal("Invalid number: %s (%s)",
3474 optarg, errstr);
3475 break;
3476 case 'V':
3477 parse_cert_times(optarg);
3478 break;
3479 case 'Y':
3480 sign_op = optarg;
3481 break;
3482 case 'w':
3483 sk_provider = optarg;
3484 break;
3485 case 'z':
3486 errno = 0;
3487 if (*optarg == '+') {
3488 cert_serial_autoinc = 1;
3489 optarg++;
3490 }
3491 cert_serial = strtoull(optarg, &ep, 10);
3492 if (*optarg < '0' || *optarg > '9' || *ep != '\0' ||
3493 (errno == ERANGE && cert_serial == ULLONG_MAX))
3494 fatal("Invalid serial number \"%s\"", optarg);
3495 break;
3496 case 'M':
3497 if (strcmp(optarg, "generate") == 0)
3498 do_gen_candidates = 1;
3499 else if (strcmp(optarg, "screen") == 0)
3500 do_screen_candidates = 1;
3501 else
3502 fatal("Unsupported moduli option %s", optarg);
3503 break;
3504 default:
3505 usage();
3506 }
3507 }
3508
3509 if (sk_provider == NULL)
3510 sk_provider = "internal";
3511
3512 /* reinit */
3513 log_init(argv[0], log_level, SYSLOG_FACILITY_USER, 1);
3514
3515 argv += optind;
3516 argc -= optind;
3517
3518 if (sign_op != NULL) {
3519 if (strprefix(sign_op, "find-principals", 0) != NULL) {
3520 if (ca_key_path == NULL) {
3521 error("Too few arguments for find-principals:"
3522 "missing signature file");
3523 exit(1);
3524 }
3525 if (!have_identity) {
3526 error("Too few arguments for find-principals:"
3527 "missing allowed keys file");
3528 exit(1);
3529 }
3530 ret = sig_find_principals(ca_key_path, identity_file,
3531 opts, nopts);
3532 goto done;
3533 } else if (strprefix(sign_op, "match-principals", 0) != NULL) {
3534 if (!have_identity) {
3535 error("Too few arguments for match-principals:"
3536 "missing allowed keys file");
3537 exit(1);
3538 }
3539 if (cert_key_id == NULL) {
3540 error("Too few arguments for match-principals: "
3541 "missing principal ID");
3542 exit(1);
3543 }
3544 ret = sig_match_principals(identity_file, cert_key_id,
3545 opts, nopts);
3546 goto done;
3547 } else if (strprefix(sign_op, "sign", 0) != NULL) {
3548 /* NB. cert_principals is actually namespace, via -n */
3549 if (cert_principals == NULL ||
3550 *cert_principals == '\0') {
3551 error("Too few arguments for sign: "
3552 "missing namespace");
3553 exit(1);
3554 }
3555 if (!have_identity) {
3556 error("Too few arguments for sign: "
3557 "missing key");
3558 exit(1);
3559 }
3560 ret = sig_sign(identity_file, cert_principals,
3561 prefer_agent, argc, argv, opts, nopts);
3562 goto done;
3563 } else if (strprefix(sign_op, "check-novalidate", 0) != NULL) {
3564 /* NB. cert_principals is actually namespace, via -n */
3565 if (cert_principals == NULL ||
3566 *cert_principals == '\0') {
3567 error("Too few arguments for check-novalidate: "
3568 "missing namespace");
3569 exit(1);
3570 }
3571 if (ca_key_path == NULL) {
3572 error("Too few arguments for check-novalidate: "
3573 "missing signature file");
3574 exit(1);
3575 }
3576 ret = sig_verify(ca_key_path, cert_principals,
3577 NULL, NULL, NULL, opts, nopts);
3578 goto done;
3579 } else if (strprefix(sign_op, "verify", 0) != NULL) {
3580 /* NB. cert_principals is actually namespace, via -n */
3581 if (cert_principals == NULL ||
3582 *cert_principals == '\0') {
3583 error("Too few arguments for verify: "
3584 "missing namespace");
3585 exit(1);
3586 }
3587 if (ca_key_path == NULL) {
3588 error("Too few arguments for verify: "
3589 "missing signature file");
3590 exit(1);
3591 }
3592 if (!have_identity) {
3593 error("Too few arguments for sign: "
3594 "missing allowed keys file");
3595 exit(1);
3596 }
3597 if (cert_key_id == NULL) {
3598 error("Too few arguments for verify: "
3599 "missing principal identity");
3600 exit(1);
3601 }
3602 ret = sig_verify(ca_key_path, cert_principals,
3603 cert_key_id, identity_file, rr_hostname,
3604 opts, nopts);
3605 goto done;
3606 }
3607 error("Unsupported operation for -Y: \"%s\"", sign_op);
3608 usage();
3609 /* NOTREACHED */
3610 }
3611
3612 if (ca_key_path != NULL) {
3613 if (argc < 1 && !gen_krl) {
3614 error("Too few arguments.");
3615 usage();
3616 }
3617 } else if (argc > 0 && !gen_krl && !check_krl &&
3618 !do_gen_candidates && !do_screen_candidates) {
3619 error("Too many arguments.");
3620 usage();
3621 }
3622 if (change_passphrase && change_comment) {
3623 error("Can only have one of -p and -c.");
3624 usage();
3625 }
3626 if (print_fingerprint && (delete_host || hash_hosts)) {
3627 error("Cannot use -l with -H or -R.");
3628 usage();
3629 }
3630 if (gen_krl) {
3631 do_gen_krl(pw, update_krl, ca_key_path,
3632 cert_serial, identity_comment, argc, argv);
3633 goto done;
3634 }
3635 if (check_krl) {
3636 do_check_krl(pw, print_fingerprint, argc, argv);
3637 goto done;
3638 }
3639 if (ca_key_path != NULL) {
3640 if (cert_key_id == NULL)
3641 fatal("Must specify key id (-I) when certifying");
3642 if (cert_principals == NULL) {
3643 /*
3644 * Ideally this would be a fatal(), but we need to
3645 * be able to generate such certificates for testing
3646 * even though they will be rejected.
3647 */
3648 error("Warning: certificate will contain no "
3649 "principals (-n)");
3650 }
3651 for (i = 0; i < nopts; i++)
3652 add_cert_option(opts[i]);
3653 do_ca_sign(pw, ca_key_path, prefer_agent,
3654 cert_serial, cert_serial_autoinc, argc, argv);
3655 goto done;
3656 }
3657 if (show_cert)
3658 do_show_cert(pw);
3659 if (delete_host || hash_hosts || find_host) {
3660 do_known_hosts(pw, rr_hostname, find_host,
3661 delete_host, hash_hosts);
3662 }
3663 if (pkcs11provider != NULL)
3664 do_download(pw);
3665 if (download_sk) {
3666 for (i = 0; i < nopts; i++) {
3667 if ((p = strprefix(opts[i], "device=", 1)) != NULL) {
3668 sk_device = xstrdup(p);
3669 } else {
3670 fatal("Option \"%s\" is unsupported for "
3671 "FIDO authenticator download", opts[i]);
3672 }
3673 }
3674 ret = do_download_sk(sk_provider, sk_device);
3675 goto done;
3676 }
3677 if (print_fingerprint || print_bubblebabble)
3678 do_fingerprint(pw);
3679 if (change_passphrase)
3680 do_change_passphrase(pw);
3681 if (change_comment)
3682 do_change_comment(pw, identity_comment);
3683#ifdef WITH_OPENSSL
3684 if (convert_to) {
3685 do_convert_to(pw);
3686 goto done;
3687 }
3688 if (convert_from) {
3689 do_convert_from(pw);
3690 goto done;
3691 }
3692#else /* WITH_OPENSSL */
3693 if (convert_to || convert_from)
3694 fatal("key conversion disabled at compile time");
3695#endif /* WITH_OPENSSL */
3696 if (print_public)
3697 do_print_public(pw);
3698 if (rr_hostname != NULL) {
3699 unsigned int n = 0;
3700
3701 if (have_identity) {
3702 n = do_print_resource_record(pw, identity_file,
3703 rr_hostname, print_generic, opts, nopts);
3704 if (n == 0)
3705 fatal("%s: %s", identity_file, strerror(errno));
3706 exit(0);
3707 } else {
3708
3709 n += do_print_resource_record(pw,
3710 _PATH_HOST_RSA_KEY_FILE, rr_hostname,
3711 print_generic, opts, nopts);
3712 n += do_print_resource_record(pw,
3713 _PATH_HOST_ECDSA_KEY_FILE, rr_hostname,
3714 print_generic, opts, nopts);
3715 n += do_print_resource_record(pw,
3716 _PATH_HOST_ED25519_KEY_FILE, rr_hostname,
3717 print_generic, opts, nopts);
3718 if (n == 0)
3719 fatal("no keys found.");
3720 exit(0);
3721 }
3722 }
3723
3724 if (do_gen_candidates || do_screen_candidates) {
3725 if (argc <= 0)
3726 fatal("No output file specified");
3727 else if (argc > 1)
3728 fatal("Too many output files specified");
3729 }
3730 if (do_gen_candidates) {
3731 do_moduli_gen(argv[0], opts, nopts);
3732 goto done;
3733 }
3734 if (do_screen_candidates) {
3735 do_moduli_screen(argv[0], opts, nopts);
3736 goto done;
3737 }
3738
3739 if (gen_all_hostkeys) {
3740 do_gen_all_hostkeys(pw);
3741 goto done;
3742 }
3743
3744 if (key_type_name == NULL)
3745 key_type_name = DEFAULT_KEY_TYPE_NAME;
3746
3747 type = sshkey_type_from_shortname(key_type_name);
3748 type_bits_valid(type, key_type_name, &bits);
3749
3750 if (!quiet)
3751 printf("Generating public/private %s key pair.\n",
3752 key_type_name);
3753 switch (type) {
3754 case KEY_ECDSA_SK:
3755 case KEY_ED25519_SK:
3756 for (i = 0; i < nopts; i++) {
3757 if (strcasecmp(opts[i], "no-touch-required") == 0) {
3758 sk_flags &= ~SSH_SK_USER_PRESENCE_REQD;
3759 } else if (strcasecmp(opts[i], "verify-required") == 0) {
3760 sk_flags |= SSH_SK_USER_VERIFICATION_REQD;
3761 } else if (strcasecmp(opts[i], "resident") == 0) {
3762 sk_flags |= SSH_SK_RESIDENT_KEY;
3763 } else if ((p = strprefix(opts[i], "device=", 1))
3764 != NULL ) {
3765 sk_device = xstrdup(p);
3766 } else if ((p = strprefix(opts[i], "user=", 1))
3767 != NULL) {
3768 sk_user = xstrdup(p);
3769 } else if ((p = strprefix(opts[i], "challenge=", 1))
3770 != NULL) {
3771 if ((r = sshbuf_load_file(p,
3772 &challenge)) != 0) {
3773 fatal_r(r, "Unable to load FIDO "
3774 "enrollment challenge \"%s\"", p);
3775 }
3776 } else if (strncasecmp(opts[i],
3777 "write-attestation=", 18) == 0) {
3778 sk_attestation_path = opts[i] + 18;
3779 } else if (strncasecmp(opts[i],
3780 "application=", 12) == 0) {
3781 sk_application = xstrdup(opts[i] + 12);
3782 if (strncmp(sk_application, "ssh:", 4) != 0) {
3783 fatal("FIDO application string must "
3784 "begin with \"ssh:\"");
3785 }
3786 } else {
3787 fatal("Option \"%s\" is unsupported for "
3788 "FIDO authenticator enrollment", opts[i]);
3789 }
3790 }
3791 if ((attest = sshbuf_new()) == NULL)
3792 fatal("sshbuf_new failed");
3793 r = 0;
3794 for (i = 0 ;;) {
3795 if (!quiet) {
3796 printf("You may need to touch your "
3797 "authenticator%s to authorize key "
3798 "generation.\n",
3799 r == 0 ? "" : " again");
3800 }
3801 fflush(stdout);
3802 r = sshsk_enroll(type, sk_provider, sk_device,
3803 sk_application == NULL ? "ssh:" : sk_application,
3804 sk_user, sk_flags, passphrase, challenge,
3805 &private, attest);
3806 if (r == 0)
3807 break;
3808 if (r == SSH_ERR_KEY_BAD_PERMISSIONS &&
3809 (sk_flags & SSH_SK_RESIDENT_KEY) != 0 &&
3810 (sk_flags & SSH_SK_FORCE_OPERATION) == 0 &&
3811 confirm_sk_overwrite(sk_application, sk_user)) {
3812 sk_flags |= SSH_SK_FORCE_OPERATION;
3813 continue;
3814 }
3815 if (r != SSH_ERR_KEY_WRONG_PASSPHRASE)
3816 fatal_r(r, "Key enrollment failed");
3817 else if (passphrase != NULL) {
3818 error("PIN incorrect");
3819 freezero(passphrase, strlen(passphrase));
3820 passphrase = NULL;
3821 }
3822 if (++i >= 3)
3823 fatal("Too many incorrect PINs");
3824 passphrase = read_passphrase("Enter PIN for "
3825 "authenticator: ", RP_ALLOW_STDIN);
3826 }
3827 if (passphrase != NULL) {
3828 freezero(passphrase, strlen(passphrase));
3829 passphrase = NULL;
3830 }
3831 break;
3832 default:
3833 if ((r = sshkey_generate(type, bits, &private)) != 0)
3834 fatal("sshkey_generate failed");
3835 break;
3836 }
3837 if ((r = sshkey_from_private(private, &public)) != 0)
3838 fatal_r(r, "sshkey_from_private");
3839
3840 if (!have_identity)
3841 ask_filename(pw, "Enter file in which to save the key");
3842
3843 /* Create ~/.ssh directory if it doesn't already exist. */
3844 hostfile_create_user_ssh_dir(identity_file, !quiet);
3845
3846 /* If the file already exists, ask the user to confirm. */
3847 if (!confirm_overwrite(identity_file))
3848 exit(1);
3849
3850 /* Determine the passphrase for the private key */
3851 passphrase = private_key_passphrase(identity_file);
3852 if (identity_comment) {
3853 strlcpy(comment, identity_comment, sizeof(comment));
3854 } else {
3855 /* Create default comment field for the passphrase. */
3856 snprintf(comment, sizeof comment, "%s@%s", pw->pw_name, hostname);
3857 }
3858
3859 /* Save the key with the given passphrase and comment. */
3860 if ((r = sshkey_save_private(private, identity_file, passphrase,
3861 comment, private_key_format, openssh_format_cipher, rounds)) != 0) {
3862 error_r(r, "Saving key \"%s\" failed", identity_file);
3863 freezero(passphrase, strlen(passphrase));
3864 exit(1);
3865 }
3866 freezero(passphrase, strlen(passphrase));
3867 sshkey_free(private);
3868
3869 if (!quiet) {
3870 printf("Your identification has been saved in %s\n",
3871 identity_file);
3872 }
3873
3874 strlcat(identity_file, ".pub", sizeof(identity_file));
3875 if ((r = sshkey_save_public(public, identity_file, comment)) != 0)
3876 fatal_r(r, "Unable to save public key to %s", identity_file);
3877
3878 if (!quiet) {
3879 fp = sshkey_fingerprint(public, fingerprint_hash,
3880 SSH_FP_DEFAULT);
3881 ra = sshkey_fingerprint(public, fingerprint_hash,
3882 SSH_FP_RANDOMART);
3883 if (fp == NULL || ra == NULL)
3884 fatal("sshkey_fingerprint failed");
3885 printf("Your public key has been saved in %s\n",
3886 identity_file);
3887 printf("The key fingerprint is:\n");
3888 printf("%s %s\n", fp, comment);
3889 printf("The key's randomart image is:\n");
3890 printf("%s\n", ra);
3891 free(ra);
3892 free(fp);
3893 }
3894
3895 if (sk_attestation_path != NULL)
3896 save_attestation(attest, sk_attestation_path);
3897
3898 done:
3899 sshbuf_free(attest);
3900 sshkey_free(public);
3901 pwfree(pw);
3902 exit(ret);
3903}