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