xref: /netbsd-src/crypto/external/bsd/openssh/dist/ssh-keygen.c (revision b1c86f5f087524e68db12794ee9c3e3da1ab17a0)
1 /*	$NetBSD: ssh-keygen.c,v 1.3 2009/12/27 01:40:47 christos Exp $	*/
2 /* $OpenBSD: ssh-keygen.c,v 1.174 2009/06/22 05:39:28 dtucker Exp $ */
3 /*
4  * Author: Tatu Ylonen <ylo@cs.hut.fi>
5  * Copyright (c) 1994 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
6  *                    All rights reserved
7  * Identity and host key generation and maintenance.
8  *
9  * As far as I am concerned, the code I have written for this software
10  * can be used freely for any purpose.  Any derived versions of this
11  * software must be clearly marked as such, and if the derived work is
12  * incompatible with the protocol description in the RFC file, it must be
13  * called by a name other than "ssh" or "Secure Shell".
14  */
15 
16 #include "includes.h"
17 __RCSID("$NetBSD: ssh-keygen.c,v 1.3 2009/12/27 01:40:47 christos Exp $");
18 #include <sys/types.h>
19 #include <sys/socket.h>
20 #include <sys/stat.h>
21 #include <sys/param.h>
22 
23 #include <openssl/evp.h>
24 #include <openssl/pem.h>
25 
26 #include <errno.h>
27 #include <fcntl.h>
28 #include <pwd.h>
29 #include <stdio.h>
30 #include <stdlib.h>
31 #include <string.h>
32 #include <unistd.h>
33 
34 #include "xmalloc.h"
35 #include "key.h"
36 #include "rsa.h"
37 #include "authfile.h"
38 #include "uuencode.h"
39 #include "buffer.h"
40 #include "pathnames.h"
41 #include "log.h"
42 #include "misc.h"
43 #include "match.h"
44 #include "hostfile.h"
45 #include "dns.h"
46 
47 #ifdef SMARTCARD
48 #include "scard.h"
49 #endif
50 
51 /* Number of bits in the RSA/DSA key.  This value can be set on the command line. */
52 #define DEFAULT_BITS		2048
53 #define DEFAULT_BITS_DSA	1024
54 u_int32_t bits = 0;
55 
56 /*
57  * Flag indicating that we just want to change the passphrase.  This can be
58  * set on the command line.
59  */
60 int change_passphrase = 0;
61 
62 /*
63  * Flag indicating that we just want to change the comment.  This can be set
64  * on the command line.
65  */
66 int change_comment = 0;
67 
68 int quiet = 0;
69 
70 int log_level = SYSLOG_LEVEL_INFO;
71 
72 /* Flag indicating that we want to hash a known_hosts file */
73 int hash_hosts = 0;
74 /* Flag indicating that we want lookup a host in known_hosts file */
75 int find_host = 0;
76 /* Flag indicating that we want to delete a host from a known_hosts file */
77 int delete_host = 0;
78 
79 /* Flag indicating that we just want to see the key fingerprint */
80 int print_fingerprint = 0;
81 int print_bubblebabble = 0;
82 
83 /* The identity file name, given on the command line or entered by the user. */
84 char identity_file[1024];
85 int have_identity = 0;
86 
87 /* This is set to the passphrase if given on the command line. */
88 char *identity_passphrase = NULL;
89 
90 /* This is set to the new passphrase if given on the command line. */
91 char *identity_new_passphrase = NULL;
92 
93 /* This is set to the new comment if given on the command line. */
94 char *identity_comment = NULL;
95 
96 /* Dump public key file in format used by real and the original SSH 2 */
97 int convert_to_ssh2 = 0;
98 int convert_from_ssh2 = 0;
99 int print_public = 0;
100 int print_generic = 0;
101 
102 char *key_type_name = NULL;
103 
104 /* argv0 */
105 extern char *__progname;
106 
107 char hostname[MAXHOSTNAMELEN];
108 
109 /* moduli.c */
110 int gen_candidates(FILE *, u_int32_t, u_int32_t, BIGNUM *);
111 int prime_test(FILE *, FILE *, u_int32_t, u_int32_t);
112 
113 static void
114 ask_filename(struct passwd *pw, const char *prompt)
115 {
116 	char buf[1024];
117 	char *name = NULL;
118 
119 	if (key_type_name == NULL)
120 		name = _PATH_SSH_CLIENT_ID_RSA;
121 	else {
122 		switch (key_type_from_name(key_type_name)) {
123 		case KEY_RSA1:
124 			name = _PATH_SSH_CLIENT_IDENTITY;
125 			break;
126 		case KEY_DSA:
127 			name = _PATH_SSH_CLIENT_ID_DSA;
128 			break;
129 		case KEY_RSA:
130 			name = _PATH_SSH_CLIENT_ID_RSA;
131 			break;
132 		default:
133 			fprintf(stderr, "bad key type\n");
134 			exit(1);
135 			break;
136 		}
137 	}
138 	snprintf(identity_file, sizeof(identity_file), "%s/%s", pw->pw_dir, name);
139 	fprintf(stderr, "%s (%s): ", prompt, identity_file);
140 	if (fgets(buf, sizeof(buf), stdin) == NULL)
141 		exit(1);
142 	buf[strcspn(buf, "\n")] = '\0';
143 	if (strcmp(buf, "") != 0)
144 		strlcpy(identity_file, buf, sizeof(identity_file));
145 	have_identity = 1;
146 }
147 
148 static Key *
149 load_identity(char *filename)
150 {
151 	char *pass;
152 	Key *prv;
153 
154 	prv = key_load_private(filename, "", NULL);
155 	if (prv == NULL) {
156 		if (identity_passphrase)
157 			pass = xstrdup(identity_passphrase);
158 		else
159 			pass = read_passphrase("Enter passphrase: ",
160 			    RP_ALLOW_STDIN);
161 		prv = key_load_private(filename, pass, NULL);
162 		memset(pass, 0, strlen(pass));
163 		xfree(pass);
164 	}
165 	return prv;
166 }
167 
168 #define SSH_COM_PUBLIC_BEGIN		"---- BEGIN SSH2 PUBLIC KEY ----"
169 #define SSH_COM_PUBLIC_END		"---- END SSH2 PUBLIC KEY ----"
170 #define SSH_COM_PRIVATE_BEGIN		"---- BEGIN SSH2 ENCRYPTED PRIVATE KEY ----"
171 #define	SSH_COM_PRIVATE_KEY_MAGIC	0x3f6ff9eb
172 
173 static void
174 do_convert_to_ssh2(struct passwd *pw)
175 {
176 	Key *k;
177 	u_int len;
178 	u_char *blob;
179 	struct stat st;
180 
181 	if (!have_identity)
182 		ask_filename(pw, "Enter file in which the key is");
183 	if (stat(identity_file, &st) < 0) {
184 		perror(identity_file);
185 		exit(1);
186 	}
187 	if ((k = key_load_public(identity_file, NULL)) == NULL) {
188 		if ((k = load_identity(identity_file)) == NULL) {
189 			fprintf(stderr, "load failed\n");
190 			exit(1);
191 		}
192 	}
193 	if (k->type == KEY_RSA1) {
194 		fprintf(stderr, "version 1 keys are not supported\n");
195 		exit(1);
196 	}
197 	if (key_to_blob(k, &blob, &len) <= 0) {
198 		fprintf(stderr, "key_to_blob failed\n");
199 		exit(1);
200 	}
201 	fprintf(stdout, "%s\n", SSH_COM_PUBLIC_BEGIN);
202 	fprintf(stdout,
203 	    "Comment: \"%u-bit %s, converted from OpenSSH by %s@%s\"\n",
204 	    key_size(k), key_type(k),
205 	    pw->pw_name, hostname);
206 	dump_base64(stdout, blob, len);
207 	fprintf(stdout, "%s\n", SSH_COM_PUBLIC_END);
208 	key_free(k);
209 	xfree(blob);
210 	exit(0);
211 }
212 
213 static void
214 buffer_get_bignum_bits(Buffer *b, BIGNUM *value)
215 {
216 	u_int bignum_bits = buffer_get_int(b);
217 	u_int bytes = (bignum_bits + 7) / 8;
218 
219 	if (buffer_len(b) < bytes)
220 		fatal("buffer_get_bignum_bits: input buffer too small: "
221 		    "need %d have %d", bytes, buffer_len(b));
222 	if (BN_bin2bn(buffer_ptr(b), bytes, value) == NULL)
223 		fatal("buffer_get_bignum_bits: BN_bin2bn failed");
224 	buffer_consume(b, bytes);
225 }
226 
227 static Key *
228 do_convert_private_ssh2_from_blob(u_char *blob, u_int blen)
229 {
230 	Buffer b;
231 	Key *key = NULL;
232 	char *type, *cipher;
233 	u_char *sig, data[] = "abcde12345";
234 	int magic, rlen, ktype, i1, i2, i3, i4;
235 	u_int slen;
236 	u_long e;
237 
238 	buffer_init(&b);
239 	buffer_append(&b, blob, blen);
240 
241 	magic = buffer_get_int(&b);
242 	if (magic != SSH_COM_PRIVATE_KEY_MAGIC) {
243 		error("bad magic 0x%x != 0x%x", magic, SSH_COM_PRIVATE_KEY_MAGIC);
244 		buffer_free(&b);
245 		return NULL;
246 	}
247 	i1 = buffer_get_int(&b);
248 	type   = buffer_get_string(&b, NULL);
249 	cipher = buffer_get_string(&b, NULL);
250 	i2 = buffer_get_int(&b);
251 	i3 = buffer_get_int(&b);
252 	i4 = buffer_get_int(&b);
253 	debug("ignore (%d %d %d %d)", i1, i2, i3, i4);
254 	if (strcmp(cipher, "none") != 0) {
255 		error("unsupported cipher %s", cipher);
256 		xfree(cipher);
257 		buffer_free(&b);
258 		xfree(type);
259 		return NULL;
260 	}
261 	xfree(cipher);
262 
263 	if (strstr(type, "dsa")) {
264 		ktype = KEY_DSA;
265 	} else if (strstr(type, "rsa")) {
266 		ktype = KEY_RSA;
267 	} else {
268 		buffer_free(&b);
269 		xfree(type);
270 		return NULL;
271 	}
272 	key = key_new_private(ktype);
273 	xfree(type);
274 
275 	switch (key->type) {
276 	case KEY_DSA:
277 		buffer_get_bignum_bits(&b, key->dsa->p);
278 		buffer_get_bignum_bits(&b, key->dsa->g);
279 		buffer_get_bignum_bits(&b, key->dsa->q);
280 		buffer_get_bignum_bits(&b, key->dsa->pub_key);
281 		buffer_get_bignum_bits(&b, key->dsa->priv_key);
282 		break;
283 	case KEY_RSA:
284 		e = buffer_get_char(&b);
285 		debug("e %lx", e);
286 		if (e < 30) {
287 			e <<= 8;
288 			e += buffer_get_char(&b);
289 			debug("e %lx", e);
290 			e <<= 8;
291 			e += buffer_get_char(&b);
292 			debug("e %lx", e);
293 		}
294 		if (!BN_set_word(key->rsa->e, e)) {
295 			buffer_free(&b);
296 			key_free(key);
297 			return NULL;
298 		}
299 		buffer_get_bignum_bits(&b, key->rsa->d);
300 		buffer_get_bignum_bits(&b, key->rsa->n);
301 		buffer_get_bignum_bits(&b, key->rsa->iqmp);
302 		buffer_get_bignum_bits(&b, key->rsa->q);
303 		buffer_get_bignum_bits(&b, key->rsa->p);
304 		rsa_generate_additional_parameters(key->rsa);
305 		break;
306 	}
307 	rlen = buffer_len(&b);
308 	if (rlen != 0)
309 		error("do_convert_private_ssh2_from_blob: "
310 		    "remaining bytes in key blob %d", rlen);
311 	buffer_free(&b);
312 
313 	/* try the key */
314 	key_sign(key, &sig, &slen, data, sizeof(data));
315 	key_verify(key, sig, slen, data, sizeof(data));
316 	xfree(sig);
317 	return key;
318 }
319 
320 static int
321 get_line(FILE *fp, char *line, size_t len)
322 {
323 	int c;
324 	size_t pos = 0;
325 
326 	line[0] = '\0';
327 	while ((c = fgetc(fp)) != EOF) {
328 		if (pos >= len - 1) {
329 			fprintf(stderr, "input line too long.\n");
330 			exit(1);
331 		}
332 		switch (c) {
333 		case '\r':
334 			c = fgetc(fp);
335 			if (c != EOF && c != '\n' && ungetc(c, fp) == EOF) {
336 				fprintf(stderr, "unget: %s\n", strerror(errno));
337 				exit(1);
338 			}
339 			return pos;
340 		case '\n':
341 			return pos;
342 		}
343 		line[pos++] = c;
344 		line[pos] = '\0';
345 	}
346 	/* We reached EOF */
347 	return -1;
348 }
349 
350 static void
351 do_convert_from_ssh2(struct passwd *pw)
352 {
353 	Key *k;
354 	int blen;
355 	u_int len;
356 	char line[1024];
357 	u_char blob[8096];
358 	char encoded[8096];
359 	struct stat st;
360 	int escaped = 0, private = 0, ok;
361 	FILE *fp;
362 
363 	if (!have_identity)
364 		ask_filename(pw, "Enter file in which the key is");
365 	if (stat(identity_file, &st) < 0) {
366 		perror(identity_file);
367 		exit(1);
368 	}
369 	fp = fopen(identity_file, "r");
370 	if (fp == NULL) {
371 		perror(identity_file);
372 		exit(1);
373 	}
374 	encoded[0] = '\0';
375 	while ((blen = get_line(fp, line, sizeof(line))) != -1) {
376 		if (line[blen - 1] == '\\')
377 			escaped++;
378 		if (strncmp(line, "----", 4) == 0 ||
379 		    strstr(line, ": ") != NULL) {
380 			if (strstr(line, SSH_COM_PRIVATE_BEGIN) != NULL)
381 				private = 1;
382 			if (strstr(line, " END ") != NULL) {
383 				break;
384 			}
385 			/* fprintf(stderr, "ignore: %s", line); */
386 			continue;
387 		}
388 		if (escaped) {
389 			escaped--;
390 			/* fprintf(stderr, "escaped: %s", line); */
391 			continue;
392 		}
393 		strlcat(encoded, line, sizeof(encoded));
394 	}
395 	len = strlen(encoded);
396 	if (((len % 4) == 3) &&
397 	    (encoded[len-1] == '=') &&
398 	    (encoded[len-2] == '=') &&
399 	    (encoded[len-3] == '='))
400 		encoded[len-3] = '\0';
401 	blen = uudecode(encoded, blob, sizeof(blob));
402 	if (blen < 0) {
403 		fprintf(stderr, "uudecode failed.\n");
404 		exit(1);
405 	}
406 	k = private ?
407 	    do_convert_private_ssh2_from_blob(blob, blen) :
408 	    key_from_blob(blob, blen);
409 	if (k == NULL) {
410 		fprintf(stderr, "decode blob failed.\n");
411 		exit(1);
412 	}
413 	ok = private ?
414 	    (k->type == KEY_DSA ?
415 		 PEM_write_DSAPrivateKey(stdout, k->dsa, NULL, NULL, 0, NULL, NULL) :
416 		 PEM_write_RSAPrivateKey(stdout, k->rsa, NULL, NULL, 0, NULL, NULL)) :
417 	    key_write(k, stdout);
418 	if (!ok) {
419 		fprintf(stderr, "key write failed\n");
420 		exit(1);
421 	}
422 	key_free(k);
423 	if (!private)
424 		fprintf(stdout, "\n");
425 	fclose(fp);
426 	exit(0);
427 }
428 
429 static void
430 do_print_public(struct passwd *pw)
431 {
432 	Key *prv;
433 	struct stat st;
434 
435 	if (!have_identity)
436 		ask_filename(pw, "Enter file in which the key is");
437 	if (stat(identity_file, &st) < 0) {
438 		perror(identity_file);
439 		exit(1);
440 	}
441 	prv = load_identity(identity_file);
442 	if (prv == NULL) {
443 		fprintf(stderr, "load failed\n");
444 		exit(1);
445 	}
446 	if (!key_write(prv, stdout))
447 		fprintf(stderr, "key_write failed");
448 	key_free(prv);
449 	fprintf(stdout, "\n");
450 	exit(0);
451 }
452 
453 #ifdef SMARTCARD
454 static void
455 do_upload(struct passwd *pw, const char *sc_reader_id)
456 {
457 	Key *prv = NULL;
458 	struct stat st;
459 	int ret;
460 
461 	if (!have_identity)
462 		ask_filename(pw, "Enter file in which the key is");
463 	if (stat(identity_file, &st) < 0) {
464 		perror(identity_file);
465 		exit(1);
466 	}
467 	prv = load_identity(identity_file);
468 	if (prv == NULL) {
469 		error("load failed");
470 		exit(1);
471 	}
472 	ret = sc_put_key(prv, sc_reader_id);
473 	key_free(prv);
474 	if (ret < 0)
475 		exit(1);
476 	logit("loading key done");
477 	exit(0);
478 }
479 
480 static void
481 do_download(struct passwd *pw, const char *sc_reader_id)
482 {
483 	Key **keys = NULL;
484 	int i;
485 
486 	keys = sc_get_keys(sc_reader_id, NULL);
487 	if (keys == NULL)
488 		fatal("cannot read public key from smartcard");
489 	for (i = 0; keys[i]; i++) {
490 		key_write(keys[i], stdout);
491 		key_free(keys[i]);
492 		fprintf(stdout, "\n");
493 	}
494 	xfree(keys);
495 	exit(0);
496 }
497 #endif /* SMARTCARD */
498 
499 static void
500 do_fingerprint(struct passwd *pw)
501 {
502 	FILE *f;
503 	Key *public;
504 	char *comment = NULL, *cp, *ep, line[16*1024], *fp, *ra;
505 	int i, skip = 0, num = 0, invalid = 1;
506 	enum fp_rep rep;
507 	enum fp_type fptype;
508 	struct stat st;
509 
510 	fptype = print_bubblebabble ? SSH_FP_SHA1 : SSH_FP_MD5;
511 	rep =    print_bubblebabble ? SSH_FP_BUBBLEBABBLE : SSH_FP_HEX;
512 
513 	if (!have_identity)
514 		ask_filename(pw, "Enter file in which the key is");
515 	if (stat(identity_file, &st) < 0) {
516 		perror(identity_file);
517 		exit(1);
518 	}
519 	public = key_load_public(identity_file, &comment);
520 	if (public != NULL) {
521 		fp = key_fingerprint(public, fptype, rep);
522 		ra = key_fingerprint(public, fptype, SSH_FP_RANDOMART);
523 		printf("%u %s %s (%s)\n", key_size(public), fp, comment,
524 		    key_type(public));
525 		if (log_level >= SYSLOG_LEVEL_VERBOSE)
526 			printf("%s\n", ra);
527 		key_free(public);
528 		xfree(comment);
529 		xfree(ra);
530 		xfree(fp);
531 		exit(0);
532 	}
533 	if (comment) {
534 		xfree(comment);
535 		comment = NULL;
536 	}
537 
538 	f = fopen(identity_file, "r");
539 	if (f != NULL) {
540 		while (fgets(line, sizeof(line), f)) {
541 			if ((cp = strchr(line, '\n')) == NULL) {
542 				error("line %d too long: %.40s...",
543 				    num + 1, line);
544 				skip = 1;
545 				continue;
546 			}
547 			num++;
548 			if (skip) {
549 				skip = 0;
550 				continue;
551 			}
552 			*cp = '\0';
553 
554 			/* Skip leading whitespace, empty and comment lines. */
555 			for (cp = line; *cp == ' ' || *cp == '\t'; cp++)
556 				;
557 			if (!*cp || *cp == '\n' || *cp == '#')
558 				continue;
559 			i = strtol(cp, &ep, 10);
560 			if (i == 0 || ep == NULL || (*ep != ' ' && *ep != '\t')) {
561 				int quoted = 0;
562 				comment = cp;
563 				for (; *cp && (quoted || (*cp != ' ' &&
564 				    *cp != '\t')); cp++) {
565 					if (*cp == '\\' && cp[1] == '"')
566 						cp++;	/* Skip both */
567 					else if (*cp == '"')
568 						quoted = !quoted;
569 				}
570 				if (!*cp)
571 					continue;
572 				*cp++ = '\0';
573 			}
574 			ep = cp;
575 			public = key_new(KEY_RSA1);
576 			if (key_read(public, &cp) != 1) {
577 				cp = ep;
578 				key_free(public);
579 				public = key_new(KEY_UNSPEC);
580 				if (key_read(public, &cp) != 1) {
581 					key_free(public);
582 					continue;
583 				}
584 			}
585 			comment = *cp ? cp : comment;
586 			fp = key_fingerprint(public, fptype, rep);
587 			ra = key_fingerprint(public, fptype, SSH_FP_RANDOMART);
588 			printf("%u %s %s (%s)\n", key_size(public), fp,
589 			    comment ? comment : "no comment", key_type(public));
590 			if (log_level >= SYSLOG_LEVEL_VERBOSE)
591 				printf("%s\n", ra);
592 			xfree(ra);
593 			xfree(fp);
594 			key_free(public);
595 			invalid = 0;
596 		}
597 		fclose(f);
598 	}
599 	if (invalid) {
600 		printf("%s is not a public key file.\n", identity_file);
601 		exit(1);
602 	}
603 	exit(0);
604 }
605 
606 static void
607 print_host(FILE *f, const char *name, Key *public, int hash)
608 {
609 	if (print_fingerprint) {
610 		enum fp_rep rep;
611 		enum fp_type fptype;
612 		char *fp, *ra;
613 
614 		fptype = print_bubblebabble ? SSH_FP_SHA1 : SSH_FP_MD5;
615 		rep =    print_bubblebabble ? SSH_FP_BUBBLEBABBLE : SSH_FP_HEX;
616 		fp = key_fingerprint(public, fptype, rep);
617 		ra = key_fingerprint(public, fptype, SSH_FP_RANDOMART);
618 		printf("%u %s %s (%s)\n", key_size(public), fp, name,
619 		    key_type(public));
620 		if (log_level >= SYSLOG_LEVEL_VERBOSE)
621 			printf("%s\n", ra);
622 		xfree(ra);
623 		xfree(fp);
624 	} else {
625 		if (hash && (name = host_hash(name, NULL, 0)) == NULL)
626 			fatal("hash_host failed");
627 		fprintf(f, "%s ", name);
628 		if (!key_write(public, f))
629 			fatal("key_write failed");
630 		fprintf(f, "\n");
631 	}
632 }
633 
634 static void
635 do_known_hosts(struct passwd *pw, const char *name)
636 {
637 	FILE *in, *out = stdout;
638 	Key *public;
639 	char *cp, *cp2, *kp, *kp2;
640 	char line[16*1024], tmp[MAXPATHLEN], old[MAXPATHLEN];
641 	int c, skip = 0, inplace = 0, num = 0, invalid = 0, has_unhashed = 0;
642 
643 	if (!have_identity) {
644 		cp = tilde_expand_filename(_PATH_SSH_USER_HOSTFILE, pw->pw_uid);
645 		if (strlcpy(identity_file, cp, sizeof(identity_file)) >=
646 		    sizeof(identity_file))
647 			fatal("Specified known hosts path too long");
648 		xfree(cp);
649 		have_identity = 1;
650 	}
651 	if ((in = fopen(identity_file, "r")) == NULL)
652 		fatal("fopen: %s", strerror(errno));
653 
654 	/*
655 	 * Find hosts goes to stdout, hash and deletions happen in-place
656 	 * A corner case is ssh-keygen -HF foo, which should go to stdout
657 	 */
658 	if (!find_host && (hash_hosts || delete_host)) {
659 		if (strlcpy(tmp, identity_file, sizeof(tmp)) >= sizeof(tmp) ||
660 		    strlcat(tmp, ".XXXXXXXXXX", sizeof(tmp)) >= sizeof(tmp) ||
661 		    strlcpy(old, identity_file, sizeof(old)) >= sizeof(old) ||
662 		    strlcat(old, ".old", sizeof(old)) >= sizeof(old))
663 			fatal("known_hosts path too long");
664 		umask(077);
665 		if ((c = mkstemp(tmp)) == -1)
666 			fatal("mkstemp: %s", strerror(errno));
667 		if ((out = fdopen(c, "w")) == NULL) {
668 			c = errno;
669 			unlink(tmp);
670 			fatal("fdopen: %s", strerror(c));
671 		}
672 		inplace = 1;
673 	}
674 
675 	while (fgets(line, sizeof(line), in)) {
676 		if ((cp = strchr(line, '\n')) == NULL) {
677 			error("line %d too long: %.40s...", num + 1, line);
678 			skip = 1;
679 			invalid = 1;
680 			continue;
681 		}
682 		num++;
683 		if (skip) {
684 			skip = 0;
685 			continue;
686 		}
687 		*cp = '\0';
688 
689 		/* Skip leading whitespace, empty and comment lines. */
690 		for (cp = line; *cp == ' ' || *cp == '\t'; cp++)
691 			;
692 		if (!*cp || *cp == '\n' || *cp == '#') {
693 			if (inplace)
694 				fprintf(out, "%s\n", cp);
695 			continue;
696 		}
697 		/* Find the end of the host name portion. */
698 		for (kp = cp; *kp && *kp != ' ' && *kp != '\t'; kp++)
699 			;
700 		if (*kp == '\0' || *(kp + 1) == '\0') {
701 			error("line %d missing key: %.40s...",
702 			    num, line);
703 			invalid = 1;
704 			continue;
705 		}
706 		*kp++ = '\0';
707 		kp2 = kp;
708 
709 		public = key_new(KEY_RSA1);
710 		if (key_read(public, &kp) != 1) {
711 			kp = kp2;
712 			key_free(public);
713 			public = key_new(KEY_UNSPEC);
714 			if (key_read(public, &kp) != 1) {
715 				error("line %d invalid key: %.40s...",
716 				    num, line);
717 				key_free(public);
718 				invalid = 1;
719 				continue;
720 			}
721 		}
722 
723 		if (*cp == HASH_DELIM) {
724 			if (find_host || delete_host) {
725 				cp2 = host_hash(name, cp, strlen(cp));
726 				if (cp2 == NULL) {
727 					error("line %d: invalid hashed "
728 					    "name: %.64s...", num, line);
729 					invalid = 1;
730 					continue;
731 				}
732 				c = (strcmp(cp2, cp) == 0);
733 				if (find_host && c) {
734 					printf("# Host %s found: "
735 					    "line %d type %s\n", name,
736 					    num, key_type(public));
737 					print_host(out, cp, public, 0);
738 				}
739 				if (delete_host && !c)
740 					print_host(out, cp, public, 0);
741 			} else if (hash_hosts)
742 				print_host(out, cp, public, 0);
743 		} else {
744 			if (find_host || delete_host) {
745 				c = (match_hostname(name, cp,
746 				    strlen(cp)) == 1);
747 				if (find_host && c) {
748 					printf("# Host %s found: "
749 					    "line %d type %s\n", name,
750 					    num, key_type(public));
751 					print_host(out, name, public,
752 					    hash_hosts);
753 				}
754 				if (delete_host && !c)
755 					print_host(out, cp, public, 0);
756 			} else if (hash_hosts) {
757 				for (cp2 = strsep(&cp, ",");
758 				    cp2 != NULL && *cp2 != '\0';
759 				    cp2 = strsep(&cp, ",")) {
760 					if (strcspn(cp2, "*?!") != strlen(cp2))
761 						fprintf(stderr, "Warning: "
762 						    "ignoring host name with "
763 						    "metacharacters: %.64s\n",
764 						    cp2);
765 					else
766 						print_host(out, cp2, public, 1);
767 				}
768 				has_unhashed = 1;
769 			}
770 		}
771 		key_free(public);
772 	}
773 	fclose(in);
774 
775 	if (invalid) {
776 		fprintf(stderr, "%s is not a valid known_hosts file.\n",
777 		    identity_file);
778 		if (inplace) {
779 			fprintf(stderr, "Not replacing existing known_hosts "
780 			    "file because of errors\n");
781 			fclose(out);
782 			unlink(tmp);
783 		}
784 		exit(1);
785 	}
786 
787 	if (inplace) {
788 		fclose(out);
789 
790 		/* Backup existing file */
791 		if (unlink(old) == -1 && errno != ENOENT)
792 			fatal("unlink %.100s: %s", old, strerror(errno));
793 		if (link(identity_file, old) == -1)
794 			fatal("link %.100s to %.100s: %s", identity_file, old,
795 			    strerror(errno));
796 		/* Move new one into place */
797 		if (rename(tmp, identity_file) == -1) {
798 			error("rename\"%s\" to \"%s\": %s", tmp, identity_file,
799 			    strerror(errno));
800 			unlink(tmp);
801 			unlink(old);
802 			exit(1);
803 		}
804 
805 		fprintf(stderr, "%s updated.\n", identity_file);
806 		fprintf(stderr, "Original contents retained as %s\n", old);
807 		if (has_unhashed) {
808 			fprintf(stderr, "WARNING: %s contains unhashed "
809 			    "entries\n", old);
810 			fprintf(stderr, "Delete this file to ensure privacy "
811 			    "of hostnames\n");
812 		}
813 	}
814 
815 	exit(0);
816 }
817 
818 /*
819  * Perform changing a passphrase.  The argument is the passwd structure
820  * for the current user.
821  */
822 static void
823 do_change_passphrase(struct passwd *pw)
824 {
825 	char *comment;
826 	char *old_passphrase, *passphrase1, *passphrase2;
827 	struct stat st;
828 	Key *private;
829 
830 	if (!have_identity)
831 		ask_filename(pw, "Enter file in which the key is");
832 	if (stat(identity_file, &st) < 0) {
833 		perror(identity_file);
834 		exit(1);
835 	}
836 	/* Try to load the file with empty passphrase. */
837 	private = key_load_private(identity_file, "", &comment);
838 	if (private == NULL) {
839 		if (identity_passphrase)
840 			old_passphrase = xstrdup(identity_passphrase);
841 		else
842 			old_passphrase =
843 			    read_passphrase("Enter old passphrase: ",
844 			    RP_ALLOW_STDIN);
845 		private = key_load_private(identity_file, old_passphrase,
846 		    &comment);
847 		memset(old_passphrase, 0, strlen(old_passphrase));
848 		xfree(old_passphrase);
849 		if (private == NULL) {
850 			printf("Bad passphrase.\n");
851 			exit(1);
852 		}
853 	}
854 	printf("Key has comment '%s'\n", comment);
855 
856 	/* Ask the new passphrase (twice). */
857 	if (identity_new_passphrase) {
858 		passphrase1 = xstrdup(identity_new_passphrase);
859 		passphrase2 = NULL;
860 	} else {
861 		passphrase1 =
862 			read_passphrase("Enter new passphrase (empty for no "
863 			    "passphrase): ", RP_ALLOW_STDIN);
864 		passphrase2 = read_passphrase("Enter same passphrase again: ",
865 		    RP_ALLOW_STDIN);
866 
867 		/* Verify that they are the same. */
868 		if (strcmp(passphrase1, passphrase2) != 0) {
869 			memset(passphrase1, 0, strlen(passphrase1));
870 			memset(passphrase2, 0, strlen(passphrase2));
871 			xfree(passphrase1);
872 			xfree(passphrase2);
873 			printf("Pass phrases do not match.  Try again.\n");
874 			exit(1);
875 		}
876 		/* Destroy the other copy. */
877 		memset(passphrase2, 0, strlen(passphrase2));
878 		xfree(passphrase2);
879 	}
880 
881 	/* Save the file using the new passphrase. */
882 	if (!key_save_private(private, identity_file, passphrase1, comment)) {
883 		printf("Saving the key failed: %s.\n", identity_file);
884 		memset(passphrase1, 0, strlen(passphrase1));
885 		xfree(passphrase1);
886 		key_free(private);
887 		xfree(comment);
888 		exit(1);
889 	}
890 	/* Destroy the passphrase and the copy of the key in memory. */
891 	memset(passphrase1, 0, strlen(passphrase1));
892 	xfree(passphrase1);
893 	key_free(private);		 /* Destroys contents */
894 	xfree(comment);
895 
896 	printf("Your identification has been saved with the new passphrase.\n");
897 	exit(0);
898 }
899 
900 /*
901  * Print the SSHFP RR.
902  */
903 static int
904 do_print_resource_record(struct passwd *pw, char *fname, char *hname)
905 {
906 	Key *public;
907 	char *comment = NULL;
908 	struct stat st;
909 
910 	if (fname == NULL)
911 		ask_filename(pw, "Enter file in which the key is");
912 	if (stat(fname, &st) < 0) {
913 		if (errno == ENOENT)
914 			return 0;
915 		perror(fname);
916 		exit(1);
917 	}
918 	public = key_load_public(fname, &comment);
919 	if (public != NULL) {
920 		export_dns_rr(hname, public, stdout, print_generic);
921 		key_free(public);
922 		xfree(comment);
923 		return 1;
924 	}
925 	if (comment)
926 		xfree(comment);
927 
928 	printf("failed to read v2 public key from %s.\n", fname);
929 	exit(1);
930 }
931 
932 /*
933  * Change the comment of a private key file.
934  */
935 static void
936 do_change_comment(struct passwd *pw)
937 {
938 	char new_comment[1024], *comment, *passphrase;
939 	Key *private;
940 	Key *public;
941 	struct stat st;
942 	FILE *f;
943 	int fd;
944 
945 	if (!have_identity)
946 		ask_filename(pw, "Enter file in which the key is");
947 	if (stat(identity_file, &st) < 0) {
948 		perror(identity_file);
949 		exit(1);
950 	}
951 	private = key_load_private(identity_file, "", &comment);
952 	if (private == NULL) {
953 		if (identity_passphrase)
954 			passphrase = xstrdup(identity_passphrase);
955 		else if (identity_new_passphrase)
956 			passphrase = xstrdup(identity_new_passphrase);
957 		else
958 			passphrase = read_passphrase("Enter passphrase: ",
959 			    RP_ALLOW_STDIN);
960 		/* Try to load using the passphrase. */
961 		private = key_load_private(identity_file, passphrase, &comment);
962 		if (private == NULL) {
963 			memset(passphrase, 0, strlen(passphrase));
964 			xfree(passphrase);
965 			printf("Bad passphrase.\n");
966 			exit(1);
967 		}
968 	} else {
969 		passphrase = xstrdup("");
970 	}
971 	if (private->type != KEY_RSA1) {
972 		fprintf(stderr, "Comments are only supported for RSA1 keys.\n");
973 		key_free(private);
974 		exit(1);
975 	}
976 	printf("Key now has comment '%s'\n", comment);
977 
978 	if (identity_comment) {
979 		strlcpy(new_comment, identity_comment, sizeof(new_comment));
980 	} else {
981 		printf("Enter new comment: ");
982 		fflush(stdout);
983 		if (!fgets(new_comment, sizeof(new_comment), stdin)) {
984 			memset(passphrase, 0, strlen(passphrase));
985 			key_free(private);
986 			exit(1);
987 		}
988 		new_comment[strcspn(new_comment, "\n")] = '\0';
989 	}
990 
991 	/* Save the file using the new passphrase. */
992 	if (!key_save_private(private, identity_file, passphrase, new_comment)) {
993 		printf("Saving the key failed: %s.\n", identity_file);
994 		memset(passphrase, 0, strlen(passphrase));
995 		xfree(passphrase);
996 		key_free(private);
997 		xfree(comment);
998 		exit(1);
999 	}
1000 	memset(passphrase, 0, strlen(passphrase));
1001 	xfree(passphrase);
1002 	public = key_from_private(private);
1003 	key_free(private);
1004 
1005 	strlcat(identity_file, ".pub", sizeof(identity_file));
1006 	fd = open(identity_file, O_WRONLY | O_CREAT | O_TRUNC, 0644);
1007 	if (fd == -1) {
1008 		printf("Could not save your public key in %s\n", identity_file);
1009 		exit(1);
1010 	}
1011 	f = fdopen(fd, "w");
1012 	if (f == NULL) {
1013 		printf("fdopen %s failed\n", identity_file);
1014 		exit(1);
1015 	}
1016 	if (!key_write(public, f))
1017 		fprintf(stderr, "write key failed\n");
1018 	key_free(public);
1019 	fprintf(f, " %s\n", new_comment);
1020 	fclose(f);
1021 
1022 	xfree(comment);
1023 
1024 	printf("The comment in your key file has been changed.\n");
1025 	exit(0);
1026 }
1027 
1028 static void
1029 usage(void)
1030 {
1031 	fprintf(stderr, "usage: %s [options]\n", __progname);
1032 	fprintf(stderr, "Options:\n");
1033 	fprintf(stderr, "  -a trials   Number of trials for screening DH-GEX moduli.\n");
1034 	fprintf(stderr, "  -B          Show bubblebabble digest of key file.\n");
1035 	fprintf(stderr, "  -b bits     Number of bits in the key to create.\n");
1036 	fprintf(stderr, "  -C comment  Provide new comment.\n");
1037 	fprintf(stderr, "  -c          Change comment in private and public key files.\n");
1038 #ifdef SMARTCARD
1039 	fprintf(stderr, "  -D reader   Download public key from smartcard.\n");
1040 #endif /* SMARTCARD */
1041 	fprintf(stderr, "  -e          Convert OpenSSH to RFC 4716 key file.\n");
1042 	fprintf(stderr, "  -F hostname Find hostname in known hosts file.\n");
1043 	fprintf(stderr, "  -f filename Filename of the key file.\n");
1044 	fprintf(stderr, "  -G file     Generate candidates for DH-GEX moduli.\n");
1045 	fprintf(stderr, "  -g          Use generic DNS resource record format.\n");
1046 	fprintf(stderr, "  -H          Hash names in known_hosts file.\n");
1047 	fprintf(stderr, "  -i          Convert RFC 4716 to OpenSSH key file.\n");
1048 	fprintf(stderr, "  -l          Show fingerprint of key file.\n");
1049 	fprintf(stderr, "  -M memory   Amount of memory (MB) to use for generating DH-GEX moduli.\n");
1050 	fprintf(stderr, "  -N phrase   Provide new passphrase.\n");
1051 	fprintf(stderr, "  -P phrase   Provide old passphrase.\n");
1052 	fprintf(stderr, "  -p          Change passphrase of private key file.\n");
1053 	fprintf(stderr, "  -q          Quiet.\n");
1054 	fprintf(stderr, "  -R hostname Remove host from known_hosts file.\n");
1055 	fprintf(stderr, "  -r hostname Print DNS resource record.\n");
1056 	fprintf(stderr, "  -S start    Start point (hex) for generating DH-GEX moduli.\n");
1057 	fprintf(stderr, "  -T file     Screen candidates for DH-GEX moduli.\n");
1058 	fprintf(stderr, "  -t type     Specify type of key to create.\n");
1059 #ifdef SMARTCARD
1060 	fprintf(stderr, "  -U reader   Upload private key to smartcard.\n");
1061 #endif /* SMARTCARD */
1062 	fprintf(stderr, "  -v          Verbose.\n");
1063 	fprintf(stderr, "  -W gen      Generator to use for generating DH-GEX moduli.\n");
1064 	fprintf(stderr, "  -y          Read private key file and print public key.\n");
1065 
1066 	exit(1);
1067 }
1068 
1069 /*
1070  * Main program for key management.
1071  */
1072 int
1073 main(int argc, char **argv)
1074 {
1075 	char dotsshdir[MAXPATHLEN], comment[1024], *passphrase1, *passphrase2;
1076 	char out_file[MAXPATHLEN], *reader_id = NULL;
1077 	char *rr_hostname = NULL;
1078 	Key *private, *public;
1079 	struct passwd *pw;
1080 	struct stat st;
1081 	int opt, type, fd, download = 0;
1082 	u_int32_t memory = 0, generator_wanted = 0, trials = 100;
1083 	int do_gen_candidates = 0, do_screen_candidates = 0;
1084 	BIGNUM *start = NULL;
1085 	FILE *f;
1086 	const char *errstr;
1087 
1088 	extern int optind;
1089 	extern char *optarg;
1090 
1091 	/* Ensure that fds 0, 1 and 2 are open or directed to /dev/null */
1092 	sanitise_stdfd();
1093 
1094 	SSLeay_add_all_algorithms();
1095 	log_init(argv[0], SYSLOG_LEVEL_INFO, SYSLOG_FACILITY_USER, 1);
1096 
1097 	/* we need this for the home * directory.  */
1098 	pw = getpwuid(getuid());
1099 	if (!pw) {
1100 		printf("You don't exist, go away!\n");
1101 		exit(1);
1102 	}
1103 	if (gethostname(hostname, sizeof(hostname)) < 0) {
1104 		perror("gethostname");
1105 		exit(1);
1106 	}
1107 
1108 	while ((opt = getopt(argc, argv,
1109 	    "degiqpclBHvxXyF:b:f:t:U:D:P:N:C:r:g:R:T:G:M:S:a:W:")) != -1) {
1110 		switch (opt) {
1111 		case 'b':
1112 			bits = (u_int32_t)strtonum(optarg, 768, 32768, &errstr);
1113 			if (errstr)
1114 				fatal("Bits has bad value %s (%s)",
1115 					optarg, errstr);
1116 			break;
1117 		case 'F':
1118 			find_host = 1;
1119 			rr_hostname = optarg;
1120 			break;
1121 		case 'H':
1122 			hash_hosts = 1;
1123 			break;
1124 		case 'R':
1125 			delete_host = 1;
1126 			rr_hostname = optarg;
1127 			break;
1128 		case 'l':
1129 			print_fingerprint = 1;
1130 			break;
1131 		case 'B':
1132 			print_bubblebabble = 1;
1133 			break;
1134 		case 'p':
1135 			change_passphrase = 1;
1136 			break;
1137 		case 'c':
1138 			change_comment = 1;
1139 			break;
1140 		case 'f':
1141 			if (strlcpy(identity_file, optarg, sizeof(identity_file)) >=
1142 			    sizeof(identity_file))
1143 				fatal("Identity filename too long");
1144 			have_identity = 1;
1145 			break;
1146 		case 'g':
1147 			print_generic = 1;
1148 			break;
1149 		case 'P':
1150 			identity_passphrase = optarg;
1151 			break;
1152 		case 'N':
1153 			identity_new_passphrase = optarg;
1154 			break;
1155 		case 'C':
1156 			identity_comment = optarg;
1157 			break;
1158 		case 'q':
1159 			quiet = 1;
1160 			break;
1161 		case 'e':
1162 		case 'x':
1163 			/* export key */
1164 			convert_to_ssh2 = 1;
1165 			break;
1166 		case 'i':
1167 		case 'X':
1168 			/* import key */
1169 			convert_from_ssh2 = 1;
1170 			break;
1171 		case 'y':
1172 			print_public = 1;
1173 			break;
1174 		case 'd':
1175 			key_type_name = "dsa";
1176 			break;
1177 		case 't':
1178 			key_type_name = optarg;
1179 			break;
1180 		case 'D':
1181 			download = 1;
1182 			/*FALLTHROUGH*/
1183 		case 'U':
1184 			reader_id = optarg;
1185 			break;
1186 		case 'v':
1187 			if (log_level == SYSLOG_LEVEL_INFO)
1188 				log_level = SYSLOG_LEVEL_DEBUG1;
1189 			else {
1190 				if (log_level >= SYSLOG_LEVEL_DEBUG1 &&
1191 				    log_level < SYSLOG_LEVEL_DEBUG3)
1192 					log_level++;
1193 			}
1194 			break;
1195 		case 'r':
1196 			rr_hostname = optarg;
1197 			break;
1198 		case 'W':
1199 			generator_wanted = (u_int32_t)strtonum(optarg, 1,
1200 			    UINT_MAX, &errstr);
1201 			if (errstr)
1202 				fatal("Desired generator has bad value: %s (%s)",
1203 					optarg, errstr);
1204 			break;
1205 		case 'a':
1206 			trials = (u_int32_t)strtonum(optarg, 1, UINT_MAX, &errstr);
1207 			if (errstr)
1208 				fatal("Invalid number of trials: %s (%s)",
1209 					optarg, errstr);
1210 			break;
1211 		case 'M':
1212 			memory = (u_int32_t)strtonum(optarg, 1, UINT_MAX, &errstr);
1213 			if (errstr) {
1214 				fatal("Memory limit is %s: %s", errstr, optarg);
1215 			}
1216 			break;
1217 		case 'G':
1218 			do_gen_candidates = 1;
1219 			if (strlcpy(out_file, optarg, sizeof(out_file)) >=
1220 			    sizeof(out_file))
1221 				fatal("Output filename too long");
1222 			break;
1223 		case 'T':
1224 			do_screen_candidates = 1;
1225 			if (strlcpy(out_file, optarg, sizeof(out_file)) >=
1226 			    sizeof(out_file))
1227 				fatal("Output filename too long");
1228 			break;
1229 		case 'S':
1230 			/* XXX - also compare length against bits */
1231 			if (BN_hex2bn(&start, optarg) == 0)
1232 				fatal("Invalid start point.");
1233 			break;
1234 		case '?':
1235 		default:
1236 			usage();
1237 		}
1238 	}
1239 
1240 	/* reinit */
1241 	log_init(argv[0], log_level, SYSLOG_FACILITY_USER, 1);
1242 
1243 	if (optind < argc) {
1244 		printf("Too many arguments.\n");
1245 		usage();
1246 	}
1247 	if (change_passphrase && change_comment) {
1248 		printf("Can only have one of -p and -c.\n");
1249 		usage();
1250 	}
1251 	if (print_fingerprint && (delete_host || hash_hosts)) {
1252 		printf("Cannot use -l with -D or -R.\n");
1253 		usage();
1254 	}
1255 	if (delete_host || hash_hosts || find_host)
1256 		do_known_hosts(pw, rr_hostname);
1257 	if (print_fingerprint || print_bubblebabble)
1258 		do_fingerprint(pw);
1259 	if (change_passphrase)
1260 		do_change_passphrase(pw);
1261 	if (change_comment)
1262 		do_change_comment(pw);
1263 	if (convert_to_ssh2)
1264 		do_convert_to_ssh2(pw);
1265 	if (convert_from_ssh2)
1266 		do_convert_from_ssh2(pw);
1267 	if (print_public)
1268 		do_print_public(pw);
1269 	if (rr_hostname != NULL) {
1270 		unsigned int n = 0;
1271 
1272 		if (have_identity) {
1273 			n = do_print_resource_record(pw,
1274 			    identity_file, rr_hostname);
1275 			if (n == 0) {
1276 				perror(identity_file);
1277 				exit(1);
1278 			}
1279 			exit(0);
1280 		} else {
1281 
1282 			n += do_print_resource_record(pw,
1283 			    _PATH_HOST_RSA_KEY_FILE, rr_hostname);
1284 			n += do_print_resource_record(pw,
1285 			    _PATH_HOST_DSA_KEY_FILE, rr_hostname);
1286 
1287 			if (n == 0)
1288 				fatal("no keys found.");
1289 			exit(0);
1290 		}
1291 	}
1292 	if (reader_id != NULL) {
1293 #ifdef SMARTCARD
1294 		if (download)
1295 			do_download(pw, reader_id);
1296 		else
1297 			do_upload(pw, reader_id);
1298 #else /* SMARTCARD */
1299 		fatal("no support for smartcards.");
1300 #endif /* SMARTCARD */
1301 	}
1302 
1303 	if (do_gen_candidates) {
1304 		FILE *out = fopen(out_file, "w");
1305 
1306 		if (out == NULL) {
1307 			error("Couldn't open modulus candidate file \"%s\": %s",
1308 			    out_file, strerror(errno));
1309 			return (1);
1310 		}
1311 		if (bits == 0)
1312 			bits = DEFAULT_BITS;
1313 		if (gen_candidates(out, memory, bits, start) != 0)
1314 			fatal("modulus candidate generation failed");
1315 
1316 		return (0);
1317 	}
1318 
1319 	if (do_screen_candidates) {
1320 		FILE *in;
1321 		FILE *out = fopen(out_file, "w");
1322 
1323 		if (have_identity && strcmp(identity_file, "-") != 0) {
1324 			if ((in = fopen(identity_file, "r")) == NULL) {
1325 				fatal("Couldn't open modulus candidate "
1326 				    "file \"%s\": %s", identity_file,
1327 				    strerror(errno));
1328 			}
1329 		} else
1330 			in = stdin;
1331 
1332 		if (out == NULL) {
1333 			fatal("Couldn't open moduli file \"%s\": %s",
1334 			    out_file, strerror(errno));
1335 		}
1336 		if (prime_test(in, out, trials, generator_wanted) != 0)
1337 			fatal("modulus screening failed");
1338 		return (0);
1339 	}
1340 
1341 	arc4random_stir();
1342 
1343 	if (key_type_name == NULL)
1344 		key_type_name = "rsa";
1345 
1346 	type = key_type_from_name(key_type_name);
1347 	if (type == KEY_UNSPEC) {
1348 		fprintf(stderr, "unknown key type %s\n", key_type_name);
1349 		exit(1);
1350 	}
1351 	if (bits == 0)
1352 		bits = (type == KEY_DSA) ? DEFAULT_BITS_DSA : DEFAULT_BITS;
1353 	if (type == KEY_DSA && bits != 1024)
1354 		fatal("DSA keys must be 1024 bits");
1355 	if (!quiet)
1356 		printf("Generating public/private %s key pair.\n", key_type_name);
1357 	private = key_generate(type, bits);
1358 	if (private == NULL) {
1359 		fprintf(stderr, "key_generate failed\n");
1360 		exit(1);
1361 	}
1362 	public  = key_from_private(private);
1363 
1364 	if (!have_identity)
1365 		ask_filename(pw, "Enter file in which to save the key");
1366 
1367 	/* Create ~/.ssh directory if it doesn't already exist. */
1368 	snprintf(dotsshdir, sizeof dotsshdir, "%s/%s", pw->pw_dir, _PATH_SSH_USER_DIR);
1369 	if (strstr(identity_file, dotsshdir) != NULL &&
1370 	    stat(dotsshdir, &st) < 0) {
1371 		if (mkdir(dotsshdir, 0700) < 0)
1372 			error("Could not create directory '%s'.", dotsshdir);
1373 		else if (!quiet)
1374 			printf("Created directory '%s'.\n", dotsshdir);
1375 	}
1376 	/* If the file already exists, ask the user to confirm. */
1377 	if (stat(identity_file, &st) >= 0) {
1378 		char yesno[3];
1379 		printf("%s already exists.\n", identity_file);
1380 		printf("Overwrite (y/n)? ");
1381 		fflush(stdout);
1382 		if (fgets(yesno, sizeof(yesno), stdin) == NULL)
1383 			exit(1);
1384 		if (yesno[0] != 'y' && yesno[0] != 'Y')
1385 			exit(1);
1386 	}
1387 	/* Ask for a passphrase (twice). */
1388 	if (identity_passphrase)
1389 		passphrase1 = xstrdup(identity_passphrase);
1390 	else if (identity_new_passphrase)
1391 		passphrase1 = xstrdup(identity_new_passphrase);
1392 	else {
1393 passphrase_again:
1394 		passphrase1 =
1395 			read_passphrase("Enter passphrase (empty for no "
1396 			    "passphrase): ", RP_ALLOW_STDIN);
1397 		passphrase2 = read_passphrase("Enter same passphrase again: ",
1398 		    RP_ALLOW_STDIN);
1399 		if (strcmp(passphrase1, passphrase2) != 0) {
1400 			/*
1401 			 * The passphrases do not match.  Clear them and
1402 			 * retry.
1403 			 */
1404 			memset(passphrase1, 0, strlen(passphrase1));
1405 			memset(passphrase2, 0, strlen(passphrase2));
1406 			xfree(passphrase1);
1407 			xfree(passphrase2);
1408 			printf("Passphrases do not match.  Try again.\n");
1409 			goto passphrase_again;
1410 		}
1411 		/* Clear the other copy of the passphrase. */
1412 		memset(passphrase2, 0, strlen(passphrase2));
1413 		xfree(passphrase2);
1414 	}
1415 
1416 	if (identity_comment) {
1417 		strlcpy(comment, identity_comment, sizeof(comment));
1418 	} else {
1419 		/* Create default comment field for the passphrase. */
1420 		snprintf(comment, sizeof comment, "%s@%s", pw->pw_name, hostname);
1421 	}
1422 
1423 	/* Save the key with the given passphrase and comment. */
1424 	if (!key_save_private(private, identity_file, passphrase1, comment)) {
1425 		printf("Saving the key failed: %s.\n", identity_file);
1426 		memset(passphrase1, 0, strlen(passphrase1));
1427 		xfree(passphrase1);
1428 		exit(1);
1429 	}
1430 	/* Clear the passphrase. */
1431 	memset(passphrase1, 0, strlen(passphrase1));
1432 	xfree(passphrase1);
1433 
1434 	/* Clear the private key and the random number generator. */
1435 	key_free(private);
1436 	arc4random_stir();
1437 
1438 	if (!quiet)
1439 		printf("Your identification has been saved in %s.\n", identity_file);
1440 
1441 	strlcat(identity_file, ".pub", sizeof(identity_file));
1442 	fd = open(identity_file, O_WRONLY | O_CREAT | O_TRUNC, 0644);
1443 	if (fd == -1) {
1444 		printf("Could not save your public key in %s\n", identity_file);
1445 		exit(1);
1446 	}
1447 	f = fdopen(fd, "w");
1448 	if (f == NULL) {
1449 		printf("fdopen %s failed\n", identity_file);
1450 		exit(1);
1451 	}
1452 	if (!key_write(public, f))
1453 		fprintf(stderr, "write key failed\n");
1454 	fprintf(f, " %s\n", comment);
1455 	fclose(f);
1456 
1457 	if (!quiet) {
1458 		char *fp = key_fingerprint(public, SSH_FP_MD5, SSH_FP_HEX);
1459 		char *ra = key_fingerprint(public, SSH_FP_MD5,
1460 		    SSH_FP_RANDOMART);
1461 		printf("Your public key has been saved in %s.\n",
1462 		    identity_file);
1463 		printf("The key fingerprint is:\n");
1464 		printf("%s %s\n", fp, comment);
1465 		printf("The key's randomart image is:\n");
1466 		printf("%s\n", ra);
1467 		xfree(ra);
1468 		xfree(fp);
1469 	}
1470 
1471 	key_free(public);
1472 	exit(0);
1473 }
1474