xref: /freebsd/crypto/openssh/ssh-keygen.c (revision 6b3455a7665208c366849f0b2b3bc916fb97516e)
1 /*
2  * Author: Tatu Ylonen <ylo@cs.hut.fi>
3  * Copyright (c) 1994 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
4  *                    All rights reserved
5  * Identity and host key generation and maintenance.
6  *
7  * As far as I am concerned, the code I have written for this software
8  * can be used freely for any purpose.  Any derived versions of this
9  * software must be clearly marked as such, and if the derived work is
10  * incompatible with the protocol description in the RFC file, it must be
11  * called by a name other than "ssh" or "Secure Shell".
12  */
13 
14 #include "includes.h"
15 RCSID("$OpenBSD: ssh-keygen.c,v 1.113 2003/12/22 09:16:58 djm Exp $");
16 
17 #include <openssl/evp.h>
18 #include <openssl/pem.h>
19 
20 #include "xmalloc.h"
21 #include "key.h"
22 #include "rsa.h"
23 #include "authfile.h"
24 #include "uuencode.h"
25 #include "buffer.h"
26 #include "bufaux.h"
27 #include "pathnames.h"
28 #include "log.h"
29 #include "readpass.h"
30 #include "moduli.h"
31 
32 #ifdef SMARTCARD
33 #include "scard.h"
34 #endif
35 #include "dns.h"
36 
37 /* Number of bits in the RSA/DSA key.  This value can be changed on the command line. */
38 int bits = 1024;
39 
40 /*
41  * Flag indicating that we just want to change the passphrase.  This can be
42  * set on the command line.
43  */
44 int change_passphrase = 0;
45 
46 /*
47  * Flag indicating that we just want to change the comment.  This can be set
48  * on the command line.
49  */
50 int change_comment = 0;
51 
52 int quiet = 0;
53 
54 /* Flag indicating that we just want to see the key fingerprint */
55 int print_fingerprint = 0;
56 int print_bubblebabble = 0;
57 
58 /* The identity file name, given on the command line or entered by the user. */
59 char identity_file[1024];
60 int have_identity = 0;
61 
62 /* This is set to the passphrase if given on the command line. */
63 char *identity_passphrase = NULL;
64 
65 /* This is set to the new passphrase if given on the command line. */
66 char *identity_new_passphrase = NULL;
67 
68 /* This is set to the new comment if given on the command line. */
69 char *identity_comment = NULL;
70 
71 /* Dump public key file in format used by real and the original SSH 2 */
72 int convert_to_ssh2 = 0;
73 int convert_from_ssh2 = 0;
74 int print_public = 0;
75 int print_generic = 0;
76 
77 char *key_type_name = NULL;
78 
79 /* argv0 */
80 #ifdef HAVE___PROGNAME
81 extern char *__progname;
82 #else
83 char *__progname;
84 #endif
85 
86 char hostname[MAXHOSTNAMELEN];
87 
88 static void
89 ask_filename(struct passwd *pw, const char *prompt)
90 {
91 	char buf[1024];
92 	char *name = NULL;
93 
94 	if (key_type_name == NULL)
95 		name = _PATH_SSH_CLIENT_ID_RSA;
96 	else
97 		switch (key_type_from_name(key_type_name)) {
98 		case KEY_RSA1:
99 			name = _PATH_SSH_CLIENT_IDENTITY;
100 			break;
101 		case KEY_DSA:
102 			name = _PATH_SSH_CLIENT_ID_DSA;
103 			break;
104 		case KEY_RSA:
105 			name = _PATH_SSH_CLIENT_ID_RSA;
106 			break;
107 		default:
108 			fprintf(stderr, "bad key type");
109 			exit(1);
110 			break;
111 		}
112 
113 	snprintf(identity_file, sizeof(identity_file), "%s/%s", pw->pw_dir, name);
114 	fprintf(stderr, "%s (%s): ", prompt, identity_file);
115 	if (fgets(buf, sizeof(buf), stdin) == NULL)
116 		exit(1);
117 	if (strchr(buf, '\n'))
118 		*strchr(buf, '\n') = 0;
119 	if (strcmp(buf, "") != 0)
120 		strlcpy(identity_file, buf, sizeof(identity_file));
121 	have_identity = 1;
122 }
123 
124 static Key *
125 load_identity(char *filename)
126 {
127 	char *pass;
128 	Key *prv;
129 
130 	prv = key_load_private(filename, "", NULL);
131 	if (prv == NULL) {
132 		if (identity_passphrase)
133 			pass = xstrdup(identity_passphrase);
134 		else
135 			pass = read_passphrase("Enter passphrase: ",
136 			    RP_ALLOW_STDIN);
137 		prv = key_load_private(filename, pass, NULL);
138 		memset(pass, 0, strlen(pass));
139 		xfree(pass);
140 	}
141 	return prv;
142 }
143 
144 #define SSH_COM_PUBLIC_BEGIN		"---- BEGIN SSH2 PUBLIC KEY ----"
145 #define SSH_COM_PUBLIC_END		"---- END SSH2 PUBLIC KEY ----"
146 #define SSH_COM_PRIVATE_BEGIN		"---- BEGIN SSH2 ENCRYPTED PRIVATE KEY ----"
147 #define	SSH_COM_PRIVATE_KEY_MAGIC	0x3f6ff9eb
148 
149 static void
150 do_convert_to_ssh2(struct passwd *pw)
151 {
152 	Key *k;
153 	u_int len;
154 	u_char *blob;
155 	struct stat st;
156 
157 	if (!have_identity)
158 		ask_filename(pw, "Enter file in which the key is");
159 	if (stat(identity_file, &st) < 0) {
160 		perror(identity_file);
161 		exit(1);
162 	}
163 	if ((k = key_load_public(identity_file, NULL)) == NULL) {
164 		if ((k = load_identity(identity_file)) == NULL) {
165 			fprintf(stderr, "load failed\n");
166 			exit(1);
167 		}
168 	}
169 	if (k->type == KEY_RSA1) {
170 		fprintf(stderr, "version 1 keys are not supported\n");
171 		exit(1);
172 	}
173 	if (key_to_blob(k, &blob, &len) <= 0) {
174 		fprintf(stderr, "key_to_blob failed\n");
175 		exit(1);
176 	}
177 	fprintf(stdout, "%s\n", SSH_COM_PUBLIC_BEGIN);
178 	fprintf(stdout,
179 	    "Comment: \"%u-bit %s, converted from OpenSSH by %s@%s\"\n",
180 	    key_size(k), key_type(k),
181 	    pw->pw_name, hostname);
182 	dump_base64(stdout, blob, len);
183 	fprintf(stdout, "%s\n", SSH_COM_PUBLIC_END);
184 	key_free(k);
185 	xfree(blob);
186 	exit(0);
187 }
188 
189 static void
190 buffer_get_bignum_bits(Buffer *b, BIGNUM *value)
191 {
192 	u_int bits = buffer_get_int(b);
193 	u_int bytes = (bits + 7) / 8;
194 
195 	if (buffer_len(b) < bytes)
196 		fatal("buffer_get_bignum_bits: input buffer too small: "
197 		    "need %d have %d", bytes, buffer_len(b));
198 	BN_bin2bn(buffer_ptr(b), bytes, value);
199 	buffer_consume(b, bytes);
200 }
201 
202 static Key *
203 do_convert_private_ssh2_from_blob(u_char *blob, u_int blen)
204 {
205 	Buffer b;
206 	Key *key = NULL;
207 	char *type, *cipher;
208 	u_char *sig, data[] = "abcde12345";
209 	int magic, rlen, ktype, i1, i2, i3, i4;
210 	u_int slen;
211 	u_long e;
212 
213 	buffer_init(&b);
214 	buffer_append(&b, blob, blen);
215 
216 	magic  = buffer_get_int(&b);
217 	if (magic != SSH_COM_PRIVATE_KEY_MAGIC) {
218 		error("bad magic 0x%x != 0x%x", magic, SSH_COM_PRIVATE_KEY_MAGIC);
219 		buffer_free(&b);
220 		return NULL;
221 	}
222 	i1 = buffer_get_int(&b);
223 	type   = buffer_get_string(&b, NULL);
224 	cipher = buffer_get_string(&b, NULL);
225 	i2 = buffer_get_int(&b);
226 	i3 = buffer_get_int(&b);
227 	i4 = buffer_get_int(&b);
228 	debug("ignore (%d %d %d %d)", i1,i2,i3,i4);
229 	if (strcmp(cipher, "none") != 0) {
230 		error("unsupported cipher %s", cipher);
231 		xfree(cipher);
232 		buffer_free(&b);
233 		xfree(type);
234 		return NULL;
235 	}
236 	xfree(cipher);
237 
238 	if (strstr(type, "dsa")) {
239 		ktype = KEY_DSA;
240 	} else if (strstr(type, "rsa")) {
241 		ktype = KEY_RSA;
242 	} else {
243 		xfree(type);
244 		return NULL;
245 	}
246 	key = key_new_private(ktype);
247 	xfree(type);
248 
249 	switch (key->type) {
250 	case KEY_DSA:
251 		buffer_get_bignum_bits(&b, key->dsa->p);
252 		buffer_get_bignum_bits(&b, key->dsa->g);
253 		buffer_get_bignum_bits(&b, key->dsa->q);
254 		buffer_get_bignum_bits(&b, key->dsa->pub_key);
255 		buffer_get_bignum_bits(&b, key->dsa->priv_key);
256 		break;
257 	case KEY_RSA:
258 		e  = buffer_get_char(&b);
259 		debug("e %lx", e);
260 		if (e < 30) {
261 			e <<= 8;
262 			e += buffer_get_char(&b);
263 			debug("e %lx", e);
264 			e <<= 8;
265 			e += buffer_get_char(&b);
266 			debug("e %lx", e);
267 		}
268 		if (!BN_set_word(key->rsa->e, e)) {
269 			buffer_free(&b);
270 			key_free(key);
271 			return NULL;
272 		}
273 		buffer_get_bignum_bits(&b, key->rsa->d);
274 		buffer_get_bignum_bits(&b, key->rsa->n);
275 		buffer_get_bignum_bits(&b, key->rsa->iqmp);
276 		buffer_get_bignum_bits(&b, key->rsa->q);
277 		buffer_get_bignum_bits(&b, key->rsa->p);
278 		rsa_generate_additional_parameters(key->rsa);
279 		break;
280 	}
281 	rlen = buffer_len(&b);
282 	if (rlen != 0)
283 		error("do_convert_private_ssh2_from_blob: "
284 		    "remaining bytes in key blob %d", rlen);
285 	buffer_free(&b);
286 
287 	/* try the key */
288 	key_sign(key, &sig, &slen, data, sizeof(data));
289 	key_verify(key, sig, slen, data, sizeof(data));
290 	xfree(sig);
291 	return key;
292 }
293 
294 static void
295 do_convert_from_ssh2(struct passwd *pw)
296 {
297 	Key *k;
298 	int blen;
299 	u_int len;
300 	char line[1024], *p;
301 	u_char blob[8096];
302 	char encoded[8096];
303 	struct stat st;
304 	int escaped = 0, private = 0, ok;
305 	FILE *fp;
306 
307 	if (!have_identity)
308 		ask_filename(pw, "Enter file in which the key is");
309 	if (stat(identity_file, &st) < 0) {
310 		perror(identity_file);
311 		exit(1);
312 	}
313 	fp = fopen(identity_file, "r");
314 	if (fp == NULL) {
315 		perror(identity_file);
316 		exit(1);
317 	}
318 	encoded[0] = '\0';
319 	while (fgets(line, sizeof(line), fp)) {
320 		if (!(p = strchr(line, '\n'))) {
321 			fprintf(stderr, "input line too long.\n");
322 			exit(1);
323 		}
324 		if (p > line && p[-1] == '\\')
325 			escaped++;
326 		if (strncmp(line, "----", 4) == 0 ||
327 		    strstr(line, ": ") != NULL) {
328 			if (strstr(line, SSH_COM_PRIVATE_BEGIN) != NULL)
329 				private = 1;
330 			if (strstr(line, " END ") != NULL) {
331 				break;
332 			}
333 			/* fprintf(stderr, "ignore: %s", line); */
334 			continue;
335 		}
336 		if (escaped) {
337 			escaped--;
338 			/* fprintf(stderr, "escaped: %s", line); */
339 			continue;
340 		}
341 		*p = '\0';
342 		strlcat(encoded, line, sizeof(encoded));
343 	}
344 	len = strlen(encoded);
345 	if (((len % 4) == 3) &&
346 	    (encoded[len-1] == '=') &&
347 	    (encoded[len-2] == '=') &&
348 	    (encoded[len-3] == '='))
349 		encoded[len-3] = '\0';
350 	blen = uudecode(encoded, blob, sizeof(blob));
351 	if (blen < 0) {
352 		fprintf(stderr, "uudecode failed.\n");
353 		exit(1);
354 	}
355 	k = private ?
356 	    do_convert_private_ssh2_from_blob(blob, blen) :
357 	    key_from_blob(blob, blen);
358 	if (k == NULL) {
359 		fprintf(stderr, "decode blob failed.\n");
360 		exit(1);
361 	}
362 	ok = private ?
363 	    (k->type == KEY_DSA ?
364 		 PEM_write_DSAPrivateKey(stdout, k->dsa, NULL, NULL, 0, NULL, NULL) :
365 		 PEM_write_RSAPrivateKey(stdout, k->rsa, NULL, NULL, 0, NULL, NULL)) :
366 	    key_write(k, stdout);
367 	if (!ok) {
368 		fprintf(stderr, "key write failed");
369 		exit(1);
370 	}
371 	key_free(k);
372 	if (!private)
373 		fprintf(stdout, "\n");
374 	fclose(fp);
375 	exit(0);
376 }
377 
378 static void
379 do_print_public(struct passwd *pw)
380 {
381 	Key *prv;
382 	struct stat st;
383 
384 	if (!have_identity)
385 		ask_filename(pw, "Enter file in which the key is");
386 	if (stat(identity_file, &st) < 0) {
387 		perror(identity_file);
388 		exit(1);
389 	}
390 	prv = load_identity(identity_file);
391 	if (prv == NULL) {
392 		fprintf(stderr, "load failed\n");
393 		exit(1);
394 	}
395 	if (!key_write(prv, stdout))
396 		fprintf(stderr, "key_write failed");
397 	key_free(prv);
398 	fprintf(stdout, "\n");
399 	exit(0);
400 }
401 
402 #ifdef SMARTCARD
403 static void
404 do_upload(struct passwd *pw, const char *sc_reader_id)
405 {
406 	Key *prv = NULL;
407 	struct stat st;
408 	int ret;
409 
410 	if (!have_identity)
411 		ask_filename(pw, "Enter file in which the key is");
412 	if (stat(identity_file, &st) < 0) {
413 		perror(identity_file);
414 		exit(1);
415 	}
416 	prv = load_identity(identity_file);
417 	if (prv == NULL) {
418 		error("load failed");
419 		exit(1);
420 	}
421 	ret = sc_put_key(prv, sc_reader_id);
422 	key_free(prv);
423 	if (ret < 0)
424 		exit(1);
425 	logit("loading key done");
426 	exit(0);
427 }
428 
429 static void
430 do_download(struct passwd *pw, const char *sc_reader_id)
431 {
432 	Key **keys = NULL;
433 	int i;
434 
435 	keys = sc_get_keys(sc_reader_id, NULL);
436 	if (keys == NULL)
437 		fatal("cannot read public key from smartcard");
438 	for (i = 0; keys[i]; i++) {
439 		key_write(keys[i], stdout);
440 		key_free(keys[i]);
441 		fprintf(stdout, "\n");
442 	}
443 	xfree(keys);
444 	exit(0);
445 }
446 #endif /* SMARTCARD */
447 
448 static void
449 do_fingerprint(struct passwd *pw)
450 {
451 	FILE *f;
452 	Key *public;
453 	char *comment = NULL, *cp, *ep, line[16*1024], *fp;
454 	int i, skip = 0, num = 1, invalid = 1;
455 	enum fp_rep rep;
456 	enum fp_type fptype;
457 	struct stat st;
458 
459 	fptype = print_bubblebabble ? SSH_FP_SHA1 : SSH_FP_MD5;
460 	rep =    print_bubblebabble ? SSH_FP_BUBBLEBABBLE : SSH_FP_HEX;
461 
462 	if (!have_identity)
463 		ask_filename(pw, "Enter file in which the key is");
464 	if (stat(identity_file, &st) < 0) {
465 		perror(identity_file);
466 		exit(1);
467 	}
468 	public = key_load_public(identity_file, &comment);
469 	if (public != NULL) {
470 		fp = key_fingerprint(public, fptype, rep);
471 		printf("%u %s %s\n", key_size(public), fp, comment);
472 		key_free(public);
473 		xfree(comment);
474 		xfree(fp);
475 		exit(0);
476 	}
477 	if (comment)
478 		xfree(comment);
479 
480 	f = fopen(identity_file, "r");
481 	if (f != NULL) {
482 		while (fgets(line, sizeof(line), f)) {
483 			i = strlen(line) - 1;
484 			if (line[i] != '\n') {
485 				error("line %d too long: %.40s...", num, line);
486 				skip = 1;
487 				continue;
488 			}
489 			num++;
490 			if (skip) {
491 				skip = 0;
492 				continue;
493 			}
494 			line[i] = '\0';
495 
496 			/* Skip leading whitespace, empty and comment lines. */
497 			for (cp = line; *cp == ' ' || *cp == '\t'; cp++)
498 				;
499 			if (!*cp || *cp == '\n' || *cp == '#')
500 				continue ;
501 			i = strtol(cp, &ep, 10);
502 			if (i == 0 || ep == NULL || (*ep != ' ' && *ep != '\t')) {
503 				int quoted = 0;
504 				comment = cp;
505 				for (; *cp && (quoted || (*cp != ' ' &&
506 				    *cp != '\t')); cp++) {
507 					if (*cp == '\\' && cp[1] == '"')
508 						cp++;	/* Skip both */
509 					else if (*cp == '"')
510 						quoted = !quoted;
511 				}
512 				if (!*cp)
513 					continue;
514 				*cp++ = '\0';
515 			}
516 			ep = cp;
517 			public = key_new(KEY_RSA1);
518 			if (key_read(public, &cp) != 1) {
519 				cp = ep;
520 				key_free(public);
521 				public = key_new(KEY_UNSPEC);
522 				if (key_read(public, &cp) != 1) {
523 					key_free(public);
524 					continue;
525 				}
526 			}
527 			comment = *cp ? cp : comment;
528 			fp = key_fingerprint(public, fptype, rep);
529 			printf("%u %s %s\n", key_size(public), fp,
530 			    comment ? comment : "no comment");
531 			xfree(fp);
532 			key_free(public);
533 			invalid = 0;
534 		}
535 		fclose(f);
536 	}
537 	if (invalid) {
538 		printf("%s is not a public key file.\n", identity_file);
539 		exit(1);
540 	}
541 	exit(0);
542 }
543 
544 /*
545  * Perform changing a passphrase.  The argument is the passwd structure
546  * for the current user.
547  */
548 static void
549 do_change_passphrase(struct passwd *pw)
550 {
551 	char *comment;
552 	char *old_passphrase, *passphrase1, *passphrase2;
553 	struct stat st;
554 	Key *private;
555 
556 	if (!have_identity)
557 		ask_filename(pw, "Enter file in which the key is");
558 	if (stat(identity_file, &st) < 0) {
559 		perror(identity_file);
560 		exit(1);
561 	}
562 	/* Try to load the file with empty passphrase. */
563 	private = key_load_private(identity_file, "", &comment);
564 	if (private == NULL) {
565 		if (identity_passphrase)
566 			old_passphrase = xstrdup(identity_passphrase);
567 		else
568 			old_passphrase =
569 			    read_passphrase("Enter old passphrase: ",
570 			    RP_ALLOW_STDIN);
571 		private = key_load_private(identity_file, old_passphrase,
572 		    &comment);
573 		memset(old_passphrase, 0, strlen(old_passphrase));
574 		xfree(old_passphrase);
575 		if (private == NULL) {
576 			printf("Bad passphrase.\n");
577 			exit(1);
578 		}
579 	}
580 	printf("Key has comment '%s'\n", comment);
581 
582 	/* Ask the new passphrase (twice). */
583 	if (identity_new_passphrase) {
584 		passphrase1 = xstrdup(identity_new_passphrase);
585 		passphrase2 = NULL;
586 	} else {
587 		passphrase1 =
588 			read_passphrase("Enter new passphrase (empty for no "
589 			    "passphrase): ", RP_ALLOW_STDIN);
590 		passphrase2 = read_passphrase("Enter same passphrase again: ",
591 		    RP_ALLOW_STDIN);
592 
593 		/* Verify that they are the same. */
594 		if (strcmp(passphrase1, passphrase2) != 0) {
595 			memset(passphrase1, 0, strlen(passphrase1));
596 			memset(passphrase2, 0, strlen(passphrase2));
597 			xfree(passphrase1);
598 			xfree(passphrase2);
599 			printf("Pass phrases do not match.  Try again.\n");
600 			exit(1);
601 		}
602 		/* Destroy the other copy. */
603 		memset(passphrase2, 0, strlen(passphrase2));
604 		xfree(passphrase2);
605 	}
606 
607 	/* Save the file using the new passphrase. */
608 	if (!key_save_private(private, identity_file, passphrase1, comment)) {
609 		printf("Saving the key failed: %s.\n", identity_file);
610 		memset(passphrase1, 0, strlen(passphrase1));
611 		xfree(passphrase1);
612 		key_free(private);
613 		xfree(comment);
614 		exit(1);
615 	}
616 	/* Destroy the passphrase and the copy of the key in memory. */
617 	memset(passphrase1, 0, strlen(passphrase1));
618 	xfree(passphrase1);
619 	key_free(private);		 /* Destroys contents */
620 	xfree(comment);
621 
622 	printf("Your identification has been saved with the new passphrase.\n");
623 	exit(0);
624 }
625 
626 /*
627  * Print the SSHFP RR.
628  */
629 static void
630 do_print_resource_record(struct passwd *pw, char *hostname)
631 {
632 	Key *public;
633 	char *comment = NULL;
634 	struct stat st;
635 
636 	if (!have_identity)
637 		ask_filename(pw, "Enter file in which the key is");
638 	if (stat(identity_file, &st) < 0) {
639 		perror(identity_file);
640 		exit(1);
641 	}
642 	public = key_load_public(identity_file, &comment);
643 	if (public != NULL) {
644 		export_dns_rr(hostname, public, stdout, print_generic);
645 		key_free(public);
646 		xfree(comment);
647 		exit(0);
648 	}
649 	if (comment)
650 		xfree(comment);
651 
652 	printf("failed to read v2 public key from %s.\n", identity_file);
653 	exit(1);
654 }
655 
656 /*
657  * Change the comment of a private key file.
658  */
659 static void
660 do_change_comment(struct passwd *pw)
661 {
662 	char new_comment[1024], *comment, *passphrase;
663 	Key *private;
664 	Key *public;
665 	struct stat st;
666 	FILE *f;
667 	int fd;
668 
669 	if (!have_identity)
670 		ask_filename(pw, "Enter file in which the key is");
671 	if (stat(identity_file, &st) < 0) {
672 		perror(identity_file);
673 		exit(1);
674 	}
675 	private = key_load_private(identity_file, "", &comment);
676 	if (private == NULL) {
677 		if (identity_passphrase)
678 			passphrase = xstrdup(identity_passphrase);
679 		else if (identity_new_passphrase)
680 			passphrase = xstrdup(identity_new_passphrase);
681 		else
682 			passphrase = read_passphrase("Enter passphrase: ",
683 			    RP_ALLOW_STDIN);
684 		/* Try to load using the passphrase. */
685 		private = key_load_private(identity_file, passphrase, &comment);
686 		if (private == NULL) {
687 			memset(passphrase, 0, strlen(passphrase));
688 			xfree(passphrase);
689 			printf("Bad passphrase.\n");
690 			exit(1);
691 		}
692 	} else {
693 		passphrase = xstrdup("");
694 	}
695 	if (private->type != KEY_RSA1) {
696 		fprintf(stderr, "Comments are only supported for RSA1 keys.\n");
697 		key_free(private);
698 		exit(1);
699 	}
700 	printf("Key now has comment '%s'\n", comment);
701 
702 	if (identity_comment) {
703 		strlcpy(new_comment, identity_comment, sizeof(new_comment));
704 	} else {
705 		printf("Enter new comment: ");
706 		fflush(stdout);
707 		if (!fgets(new_comment, sizeof(new_comment), stdin)) {
708 			memset(passphrase, 0, strlen(passphrase));
709 			key_free(private);
710 			exit(1);
711 		}
712 		if (strchr(new_comment, '\n'))
713 			*strchr(new_comment, '\n') = 0;
714 	}
715 
716 	/* Save the file using the new passphrase. */
717 	if (!key_save_private(private, identity_file, passphrase, new_comment)) {
718 		printf("Saving the key failed: %s.\n", identity_file);
719 		memset(passphrase, 0, strlen(passphrase));
720 		xfree(passphrase);
721 		key_free(private);
722 		xfree(comment);
723 		exit(1);
724 	}
725 	memset(passphrase, 0, strlen(passphrase));
726 	xfree(passphrase);
727 	public = key_from_private(private);
728 	key_free(private);
729 
730 	strlcat(identity_file, ".pub", sizeof(identity_file));
731 	fd = open(identity_file, O_WRONLY | O_CREAT | O_TRUNC, 0644);
732 	if (fd == -1) {
733 		printf("Could not save your public key in %s\n", identity_file);
734 		exit(1);
735 	}
736 	f = fdopen(fd, "w");
737 	if (f == NULL) {
738 		printf("fdopen %s failed", identity_file);
739 		exit(1);
740 	}
741 	if (!key_write(public, f))
742 		fprintf(stderr, "write key failed");
743 	key_free(public);
744 	fprintf(f, " %s\n", new_comment);
745 	fclose(f);
746 
747 	xfree(comment);
748 
749 	printf("The comment in your key file has been changed.\n");
750 	exit(0);
751 }
752 
753 static void
754 usage(void)
755 {
756 	fprintf(stderr, "Usage: %s [options]\n", __progname);
757 	fprintf(stderr, "Options:\n");
758 	fprintf(stderr, "  -b bits     Number of bits in the key to create.\n");
759 	fprintf(stderr, "  -c          Change comment in private and public key files.\n");
760 	fprintf(stderr, "  -e          Convert OpenSSH to IETF SECSH key file.\n");
761 	fprintf(stderr, "  -f filename Filename of the key file.\n");
762 	fprintf(stderr, "  -g          Use generic DNS resource record format.\n");
763 	fprintf(stderr, "  -i          Convert IETF SECSH to OpenSSH key file.\n");
764 	fprintf(stderr, "  -l          Show fingerprint of key file.\n");
765 	fprintf(stderr, "  -p          Change passphrase of private key file.\n");
766 	fprintf(stderr, "  -q          Quiet.\n");
767 	fprintf(stderr, "  -y          Read private key file and print public key.\n");
768 	fprintf(stderr, "  -t type     Specify type of key to create.\n");
769 	fprintf(stderr, "  -B          Show bubblebabble digest of key file.\n");
770 	fprintf(stderr, "  -C comment  Provide new comment.\n");
771 	fprintf(stderr, "  -N phrase   Provide new passphrase.\n");
772 	fprintf(stderr, "  -P phrase   Provide old passphrase.\n");
773 	fprintf(stderr, "  -r hostname Print DNS resource record.\n");
774 #ifdef SMARTCARD
775 	fprintf(stderr, "  -D reader   Download public key from smartcard.\n");
776 	fprintf(stderr, "  -U reader   Upload private key to smartcard.\n");
777 #endif /* SMARTCARD */
778 
779 	fprintf(stderr, "  -G file     Generate candidates for DH-GEX moduli\n");
780 	fprintf(stderr, "  -T file     Screen candidates for DH-GEX moduli\n");
781 
782 	exit(1);
783 }
784 
785 /*
786  * Main program for key management.
787  */
788 int
789 main(int ac, char **av)
790 {
791 	char dotsshdir[MAXPATHLEN], comment[1024], *passphrase1, *passphrase2;
792 	char out_file[MAXPATHLEN], *reader_id = NULL;
793 	char *resource_record_hostname = NULL;
794 	Key *private, *public;
795 	struct passwd *pw;
796 	struct stat st;
797 	int opt, type, fd, download = 0, memory = 0;
798 	int generator_wanted = 0, trials = 100;
799 	int do_gen_candidates = 0, do_screen_candidates = 0;
800 	int log_level = SYSLOG_LEVEL_INFO;
801 	BIGNUM *start = NULL;
802 	FILE *f;
803 
804 	extern int optind;
805 	extern char *optarg;
806 
807 	__progname = ssh_get_progname(av[0]);
808 
809 	SSLeay_add_all_algorithms();
810 	log_init(av[0], SYSLOG_LEVEL_INFO, SYSLOG_FACILITY_USER, 1);
811 
812 	init_rng();
813 	seed_rng();
814 
815 	/* we need this for the home * directory.  */
816 	pw = getpwuid(getuid());
817 	if (!pw) {
818 		printf("You don't exist, go away!\n");
819 		exit(1);
820 	}
821 	if (gethostname(hostname, sizeof(hostname)) < 0) {
822 		perror("gethostname");
823 		exit(1);
824 	}
825 
826 	while ((opt = getopt(ac, av,
827 	    "degiqpclBRvxXyb:f:t:U:D:P:N:C:r:g:T:G:M:S:a:W:")) != -1) {
828 		switch (opt) {
829 		case 'b':
830 			bits = atoi(optarg);
831 			if (bits < 512 || bits > 32768) {
832 				printf("Bits has bad value.\n");
833 				exit(1);
834 			}
835 			break;
836 		case 'l':
837 			print_fingerprint = 1;
838 			break;
839 		case 'B':
840 			print_bubblebabble = 1;
841 			break;
842 		case 'p':
843 			change_passphrase = 1;
844 			break;
845 		case 'c':
846 			change_comment = 1;
847 			break;
848 		case 'f':
849 			strlcpy(identity_file, optarg, sizeof(identity_file));
850 			have_identity = 1;
851 			break;
852 		case 'g':
853 			print_generic = 1;
854 			break;
855 		case 'P':
856 			identity_passphrase = optarg;
857 			break;
858 		case 'N':
859 			identity_new_passphrase = optarg;
860 			break;
861 		case 'C':
862 			identity_comment = optarg;
863 			break;
864 		case 'q':
865 			quiet = 1;
866 			break;
867 		case 'R':
868 			/* unused */
869 			exit(0);
870 			break;
871 		case 'e':
872 		case 'x':
873 			/* export key */
874 			convert_to_ssh2 = 1;
875 			break;
876 		case 'i':
877 		case 'X':
878 			/* import key */
879 			convert_from_ssh2 = 1;
880 			break;
881 		case 'y':
882 			print_public = 1;
883 			break;
884 		case 'd':
885 			key_type_name = "dsa";
886 			break;
887 		case 't':
888 			key_type_name = optarg;
889 			break;
890 		case 'D':
891 			download = 1;
892 		case 'U':
893 			reader_id = optarg;
894 			break;
895 		case 'v':
896 			if (log_level == SYSLOG_LEVEL_INFO)
897 				log_level = SYSLOG_LEVEL_DEBUG1;
898 			else {
899 				if (log_level >= SYSLOG_LEVEL_DEBUG1 &&
900 				    log_level < SYSLOG_LEVEL_DEBUG3)
901 					log_level++;
902 			}
903 			break;
904 		case 'r':
905 			resource_record_hostname = optarg;
906 			break;
907 		case 'W':
908 			generator_wanted = atoi(optarg);
909 			if (generator_wanted < 1)
910 				fatal("Desired generator has bad value.");
911 			break;
912 		case 'a':
913 			trials = atoi(optarg);
914 			if (trials < TRIAL_MINIMUM) {
915 				fatal("Minimum primality trials is %d",
916 				    TRIAL_MINIMUM);
917 			}
918 			break;
919 		case 'M':
920 			memory = atoi(optarg);
921 			if (memory != 0 &&
922 			   (memory < LARGE_MINIMUM || memory > LARGE_MAXIMUM)) {
923 				fatal("Invalid memory amount (min %ld, max %ld)",
924 				    LARGE_MINIMUM, LARGE_MAXIMUM);
925 			}
926 			break;
927 		case 'G':
928 			do_gen_candidates = 1;
929 			strlcpy(out_file, optarg, sizeof(out_file));
930 			break;
931 		case 'T':
932 			do_screen_candidates = 1;
933 			strlcpy(out_file, optarg, sizeof(out_file));
934 			break;
935 		case 'S':
936 			/* XXX - also compare length against bits */
937 			if (BN_hex2bn(&start, optarg) == 0)
938 				fatal("Invalid start point.");
939 			break;
940 		case '?':
941 		default:
942 			usage();
943 		}
944 	}
945 
946 	/* reinit */
947 	log_init(av[0], log_level, SYSLOG_FACILITY_USER, 1);
948 
949 	if (optind < ac) {
950 		printf("Too many arguments.\n");
951 		usage();
952 	}
953 	if (change_passphrase && change_comment) {
954 		printf("Can only have one of -p and -c.\n");
955 		usage();
956 	}
957 	if (print_fingerprint || print_bubblebabble)
958 		do_fingerprint(pw);
959 	if (change_passphrase)
960 		do_change_passphrase(pw);
961 	if (change_comment)
962 		do_change_comment(pw);
963 	if (convert_to_ssh2)
964 		do_convert_to_ssh2(pw);
965 	if (convert_from_ssh2)
966 		do_convert_from_ssh2(pw);
967 	if (print_public)
968 		do_print_public(pw);
969 	if (resource_record_hostname != NULL) {
970 		do_print_resource_record(pw, resource_record_hostname);
971 	}
972 	if (reader_id != NULL) {
973 #ifdef SMARTCARD
974 		if (download)
975 			do_download(pw, reader_id);
976 		else
977 			do_upload(pw, reader_id);
978 #else /* SMARTCARD */
979 		fatal("no support for smartcards.");
980 #endif /* SMARTCARD */
981 	}
982 
983 	if (do_gen_candidates) {
984 		FILE *out = fopen(out_file, "w");
985 
986 		if (out == NULL) {
987 			error("Couldn't open modulus candidate file \"%s\": %s",
988 			    out_file, strerror(errno));
989 			return (1);
990 		}
991 		if (gen_candidates(out, memory, bits, start) != 0)
992 			fatal("modulus candidate generation failed\n");
993 
994 		return (0);
995 	}
996 
997 	if (do_screen_candidates) {
998 		FILE *in;
999 		FILE *out = fopen(out_file, "w");
1000 
1001 		if (have_identity && strcmp(identity_file, "-") != 0) {
1002 			if ((in = fopen(identity_file, "r")) == NULL) {
1003 				fatal("Couldn't open modulus candidate "
1004 				    "file \"%s\": %s", identity_file,
1005 				    strerror(errno));
1006 			}
1007 		} else
1008 			in = stdin;
1009 
1010 		if (out == NULL) {
1011 			fatal("Couldn't open moduli file \"%s\": %s",
1012 			    out_file, strerror(errno));
1013 		}
1014 		if (prime_test(in, out, trials, generator_wanted) != 0)
1015 			fatal("modulus screening failed\n");
1016 		return (0);
1017 	}
1018 
1019 	arc4random_stir();
1020 
1021 	if (key_type_name == NULL) {
1022 		printf("You must specify a key type (-t).\n");
1023 		usage();
1024 	}
1025 	type = key_type_from_name(key_type_name);
1026 	if (type == KEY_UNSPEC) {
1027 		fprintf(stderr, "unknown key type %s\n", key_type_name);
1028 		exit(1);
1029 	}
1030 	if (!quiet)
1031 		printf("Generating public/private %s key pair.\n", key_type_name);
1032 	private = key_generate(type, bits);
1033 	if (private == NULL) {
1034 		fprintf(stderr, "key_generate failed");
1035 		exit(1);
1036 	}
1037 	public  = key_from_private(private);
1038 
1039 	if (!have_identity)
1040 		ask_filename(pw, "Enter file in which to save the key");
1041 
1042 	/* Create ~/.ssh directory if it doesn\'t already exist. */
1043 	snprintf(dotsshdir, sizeof dotsshdir, "%s/%s", pw->pw_dir, _PATH_SSH_USER_DIR);
1044 	if (strstr(identity_file, dotsshdir) != NULL &&
1045 	    stat(dotsshdir, &st) < 0) {
1046 		if (mkdir(dotsshdir, 0700) < 0)
1047 			error("Could not create directory '%s'.", dotsshdir);
1048 		else if (!quiet)
1049 			printf("Created directory '%s'.\n", dotsshdir);
1050 	}
1051 	/* If the file already exists, ask the user to confirm. */
1052 	if (stat(identity_file, &st) >= 0) {
1053 		char yesno[3];
1054 		printf("%s already exists.\n", identity_file);
1055 		printf("Overwrite (y/n)? ");
1056 		fflush(stdout);
1057 		if (fgets(yesno, sizeof(yesno), stdin) == NULL)
1058 			exit(1);
1059 		if (yesno[0] != 'y' && yesno[0] != 'Y')
1060 			exit(1);
1061 	}
1062 	/* Ask for a passphrase (twice). */
1063 	if (identity_passphrase)
1064 		passphrase1 = xstrdup(identity_passphrase);
1065 	else if (identity_new_passphrase)
1066 		passphrase1 = xstrdup(identity_new_passphrase);
1067 	else {
1068 passphrase_again:
1069 		passphrase1 =
1070 			read_passphrase("Enter passphrase (empty for no "
1071 			    "passphrase): ", RP_ALLOW_STDIN);
1072 		passphrase2 = read_passphrase("Enter same passphrase again: ",
1073 		    RP_ALLOW_STDIN);
1074 		if (strcmp(passphrase1, passphrase2) != 0) {
1075 			/*
1076 			 * The passphrases do not match.  Clear them and
1077 			 * retry.
1078 			 */
1079 			memset(passphrase1, 0, strlen(passphrase1));
1080 			memset(passphrase2, 0, strlen(passphrase2));
1081 			xfree(passphrase1);
1082 			xfree(passphrase2);
1083 			printf("Passphrases do not match.  Try again.\n");
1084 			goto passphrase_again;
1085 		}
1086 		/* Clear the other copy of the passphrase. */
1087 		memset(passphrase2, 0, strlen(passphrase2));
1088 		xfree(passphrase2);
1089 	}
1090 
1091 	if (identity_comment) {
1092 		strlcpy(comment, identity_comment, sizeof(comment));
1093 	} else {
1094 		/* Create default commend field for the passphrase. */
1095 		snprintf(comment, sizeof comment, "%s@%s", pw->pw_name, hostname);
1096 	}
1097 
1098 	/* Save the key with the given passphrase and comment. */
1099 	if (!key_save_private(private, identity_file, passphrase1, comment)) {
1100 		printf("Saving the key failed: %s.\n", identity_file);
1101 		memset(passphrase1, 0, strlen(passphrase1));
1102 		xfree(passphrase1);
1103 		exit(1);
1104 	}
1105 	/* Clear the passphrase. */
1106 	memset(passphrase1, 0, strlen(passphrase1));
1107 	xfree(passphrase1);
1108 
1109 	/* Clear the private key and the random number generator. */
1110 	key_free(private);
1111 	arc4random_stir();
1112 
1113 	if (!quiet)
1114 		printf("Your identification has been saved in %s.\n", identity_file);
1115 
1116 	strlcat(identity_file, ".pub", sizeof(identity_file));
1117 	fd = open(identity_file, O_WRONLY | O_CREAT | O_TRUNC, 0644);
1118 	if (fd == -1) {
1119 		printf("Could not save your public key in %s\n", identity_file);
1120 		exit(1);
1121 	}
1122 	f = fdopen(fd, "w");
1123 	if (f == NULL) {
1124 		printf("fdopen %s failed", identity_file);
1125 		exit(1);
1126 	}
1127 	if (!key_write(public, f))
1128 		fprintf(stderr, "write key failed");
1129 	fprintf(f, " %s\n", comment);
1130 	fclose(f);
1131 
1132 	if (!quiet) {
1133 		char *fp = key_fingerprint(public, SSH_FP_MD5, SSH_FP_HEX);
1134 		printf("Your public key has been saved in %s.\n",
1135 		    identity_file);
1136 		printf("The key fingerprint is:\n");
1137 		printf("%s %s\n", fp, comment);
1138 		xfree(fp);
1139 	}
1140 
1141 	key_free(public);
1142 	exit(0);
1143 }
1144