summaryrefslogtreecommitdiff
path: root/ssh-keygen.c
diff options
context:
space:
mode:
Diffstat (limited to 'ssh-keygen.c')
-rw-r--r--ssh-keygen.c281
1 files changed, 228 insertions, 53 deletions
diff --git a/ssh-keygen.c b/ssh-keygen.c
index de7c4409d..be08fbda6 100644
--- a/ssh-keygen.c
+++ b/ssh-keygen.c
@@ -1,4 +1,4 @@
1/* $OpenBSD: ssh-keygen.c,v 1.192 2010/06/23 02:59:02 djm Exp $ */ 1/* $OpenBSD: ssh-keygen.c,v 1.193 2010/06/29 23:15:30 djm Exp $ */
2/* 2/*
3 * Author: Tatu Ylonen <ylo@cs.hut.fi> 3 * Author: Tatu Ylonen <ylo@cs.hut.fi>
4 * Copyright (c) 1994 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland 4 * Copyright (c) 1994 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
@@ -133,14 +133,20 @@ u_int32_t certflags_flags = CERTOPT_DEFAULT;
133char *certflags_command = NULL; 133char *certflags_command = NULL;
134char *certflags_src_addr = NULL; 134char *certflags_src_addr = NULL;
135 135
136/* Dump public key file in format used by real and the original SSH 2 */ 136/* Conversion to/from various formats */
137int convert_to_ssh2 = 0; 137int convert_to = 0;
138int convert_from_ssh2 = 0; 138int convert_from = 0;
139enum {
140 FMT_RFC4716,
141 FMT_PKCS8,
142 FMT_PEM
143} convert_format = FMT_RFC4716;
139int print_public = 0; 144int print_public = 0;
140int print_generic = 0; 145int print_generic = 0;
141 146
142char *key_type_name = NULL; 147char *key_type_name = NULL;
143 148
149
144/* argv0 */ 150/* argv0 */
145extern char *__progname; 151extern char *__progname;
146 152
@@ -215,30 +221,12 @@ load_identity(char *filename)
215#define SSH_COM_PRIVATE_KEY_MAGIC 0x3f6ff9eb 221#define SSH_COM_PRIVATE_KEY_MAGIC 0x3f6ff9eb
216 222
217static void 223static void
218do_convert_to_ssh2(struct passwd *pw) 224do_convert_to_ssh2(struct passwd *pw, Key *k)
219{ 225{
220 Key *k;
221 u_int len; 226 u_int len;
222 u_char *blob; 227 u_char *blob;
223 char comment[61]; 228 char comment[61];
224 struct stat st;
225 229
226 if (!have_identity)
227 ask_filename(pw, "Enter file in which the key is");
228 if (stat(identity_file, &st) < 0) {
229 perror(identity_file);
230 exit(1);
231 }
232 if ((k = key_load_public(identity_file, NULL)) == NULL) {
233 if ((k = load_identity(identity_file)) == NULL) {
234 fprintf(stderr, "load failed\n");
235 exit(1);
236 }
237 }
238 if (k->type == KEY_RSA1) {
239 fprintf(stderr, "version 1 keys are not supported\n");
240 exit(1);
241 }
242 if (key_to_blob(k, &blob, &len) <= 0) { 230 if (key_to_blob(k, &blob, &len) <= 0) {
243 fprintf(stderr, "key_to_blob failed\n"); 231 fprintf(stderr, "key_to_blob failed\n");
244 exit(1); 232 exit(1);
@@ -259,6 +247,81 @@ do_convert_to_ssh2(struct passwd *pw)
259} 247}
260 248
261static void 249static void
250do_convert_to_pkcs8(Key *k)
251{
252 switch (key_type_plain(k->type)) {
253 case KEY_RSA:
254 if (!PEM_write_RSA_PUBKEY(stdout, k->rsa))
255 fatal("PEM_write_RSA_PUBKEY failed");
256 break;
257 case KEY_DSA:
258 if (!PEM_write_DSA_PUBKEY(stdout, k->dsa))
259 fatal("PEM_write_DSA_PUBKEY failed");
260 break;
261 default:
262 fatal("%s: unsupported key type %s", __func__, key_type(k));
263 }
264 exit(0);
265}
266
267static void
268do_convert_to_pem(Key *k)
269{
270 switch (key_type_plain(k->type)) {
271 case KEY_RSA:
272 if (!PEM_write_RSAPublicKey(stdout, k->rsa))
273 fatal("PEM_write_RSAPublicKey failed");
274 break;
275#if notyet /* OpenSSH 0.9.8 lacks this function */
276 case KEY_DSA:
277 if (!PEM_write_DSAPublicKey(stdout, k->dsa))
278 fatal("PEM_write_DSAPublicKey failed");
279 break;
280#endif
281 default:
282 fatal("%s: unsupported key type %s", __func__, key_type(k));
283 }
284 exit(0);
285}
286
287static void
288do_convert_to(struct passwd *pw)
289{
290 Key *k;
291 struct stat st;
292
293 if (!have_identity)
294 ask_filename(pw, "Enter file in which the key is");
295 if (stat(identity_file, &st) < 0)
296 fatal("%s: %s: %s", __progname, identity_file, strerror(errno));
297 if ((k = key_load_public(identity_file, NULL)) == NULL) {
298 if ((k = load_identity(identity_file)) == NULL) {
299 fprintf(stderr, "load failed\n");
300 exit(1);
301 }
302 }
303 if (k->type == KEY_RSA1) {
304 fprintf(stderr, "version 1 keys are not supported\n");
305 exit(1);
306 }
307
308 switch (convert_format) {
309 case FMT_RFC4716:
310 do_convert_to_ssh2(pw, k);
311 break;
312 case FMT_PKCS8:
313 do_convert_to_pkcs8(k);
314 break;
315 case FMT_PEM:
316 do_convert_to_pem(k);
317 break;
318 default:
319 fatal("%s: unknown key format %d", __func__, convert_format);
320 }
321 exit(0);
322}
323
324static void
262buffer_get_bignum_bits(Buffer *b, BIGNUM *value) 325buffer_get_bignum_bits(Buffer *b, BIGNUM *value)
263{ 326{
264 u_int bignum_bits = buffer_get_int(b); 327 u_int bignum_bits = buffer_get_int(b);
@@ -396,24 +459,16 @@ get_line(FILE *fp, char *line, size_t len)
396} 459}
397 460
398static void 461static void
399do_convert_from_ssh2(struct passwd *pw) 462do_convert_from_ssh2(struct passwd *pw, Key **k, int *private)
400{ 463{
401 Key *k;
402 int blen; 464 int blen;
403 u_int len; 465 u_int len;
404 char line[1024]; 466 char line[1024];
405 u_char blob[8096]; 467 u_char blob[8096];
406 char encoded[8096]; 468 char encoded[8096];
407 struct stat st; 469 int escaped = 0;
408 int escaped = 0, private = 0, ok;
409 FILE *fp; 470 FILE *fp;
410 471
411 if (!have_identity)
412 ask_filename(pw, "Enter file in which the key is");
413 if (stat(identity_file, &st) < 0) {
414 perror(identity_file);
415 exit(1);
416 }
417 if ((fp = fopen(identity_file, "r")) == NULL) 472 if ((fp = fopen(identity_file, "r")) == NULL)
418 fatal("%s: %s: %s", __progname, identity_file, strerror(errno)); 473 fatal("%s: %s: %s", __progname, identity_file, strerror(errno));
419 encoded[0] = '\0'; 474 encoded[0] = '\0';
@@ -423,7 +478,7 @@ do_convert_from_ssh2(struct passwd *pw)
423 if (strncmp(line, "----", 4) == 0 || 478 if (strncmp(line, "----", 4) == 0 ||
424 strstr(line, ": ") != NULL) { 479 strstr(line, ": ") != NULL) {
425 if (strstr(line, SSH_COM_PRIVATE_BEGIN) != NULL) 480 if (strstr(line, SSH_COM_PRIVATE_BEGIN) != NULL)
426 private = 1; 481 *private = 1;
427 if (strstr(line, " END ") != NULL) { 482 if (strstr(line, " END ") != NULL) {
428 break; 483 break;
429 } 484 }
@@ -448,26 +503,130 @@ do_convert_from_ssh2(struct passwd *pw)
448 fprintf(stderr, "uudecode failed.\n"); 503 fprintf(stderr, "uudecode failed.\n");
449 exit(1); 504 exit(1);
450 } 505 }
451 k = private ? 506 *k = *private ?
452 do_convert_private_ssh2_from_blob(blob, blen) : 507 do_convert_private_ssh2_from_blob(blob, blen) :
453 key_from_blob(blob, blen); 508 key_from_blob(blob, blen);
454 if (k == NULL) { 509 if (*k == NULL) {
455 fprintf(stderr, "decode blob failed.\n"); 510 fprintf(stderr, "decode blob failed.\n");
456 exit(1); 511 exit(1);
457 } 512 }
458 ok = private ? 513 fclose(fp);
459 (k->type == KEY_DSA ? 514}
460 PEM_write_DSAPrivateKey(stdout, k->dsa, NULL, NULL, 0, NULL, NULL) : 515
461 PEM_write_RSAPrivateKey(stdout, k->rsa, NULL, NULL, 0, NULL, NULL)) : 516static void
462 key_write(k, stdout); 517do_convert_from_pkcs8(Key **k, int *private)
518{
519 EVP_PKEY *pubkey;
520 FILE *fp;
521
522 if ((fp = fopen(identity_file, "r")) == NULL)
523 fatal("%s: %s: %s", __progname, identity_file, strerror(errno));
524 if ((pubkey = PEM_read_PUBKEY(fp, NULL, NULL, NULL)) == NULL) {
525 fatal("%s: %s is not a recognised public key format", __func__,
526 identity_file);
527 }
528 fclose(fp);
529 switch (EVP_PKEY_type(pubkey->type)) {
530 case EVP_PKEY_RSA:
531 *k = key_new(KEY_UNSPEC);
532 (*k)->type = KEY_RSA;
533 (*k)->rsa = EVP_PKEY_get1_RSA(pubkey);
534 break;
535 case EVP_PKEY_DSA:
536 *k = key_new(KEY_UNSPEC);
537 (*k)->type = KEY_DSA;
538 (*k)->dsa = EVP_PKEY_get1_DSA(pubkey);
539 break;
540 default:
541 fatal("%s: unsupported pubkey type %d", __func__,
542 EVP_PKEY_type(pubkey->type));
543 }
544 EVP_PKEY_free(pubkey);
545 return;
546}
547
548static void
549do_convert_from_pem(Key **k, int *private)
550{
551 FILE *fp;
552 RSA *rsa;
553#ifdef notyet
554 DSA *dsa;
555#endif
556
557 if ((fp = fopen(identity_file, "r")) == NULL)
558 fatal("%s: %s: %s", __progname, identity_file, strerror(errno));
559 if ((rsa = PEM_read_RSAPublicKey(fp, NULL, NULL, NULL)) != NULL) {
560 *k = key_new(KEY_UNSPEC);
561 (*k)->type = KEY_RSA;
562 (*k)->rsa = rsa;
563 fclose(fp);
564 return;
565 }
566#if notyet /* OpenSSH 0.9.8 lacks this function */
567 rewind(fp);
568 if ((dsa = PEM_read_DSAPublicKey(fp, NULL, NULL, NULL)) != NULL) {
569 *k = key_new(KEY_UNSPEC);
570 (*k)->type = KEY_DSA;
571 (*k)->dsa = dsa;
572 fclose(fp);
573 return;
574 }
575#endif
576 fatal("%s: unrecognised raw private key format", __func__);
577}
578
579static void
580do_convert_from(struct passwd *pw)
581{
582 Key *k = NULL;
583 int private = 0, ok;
584 struct stat st;
585
586 if (!have_identity)
587 ask_filename(pw, "Enter file in which the key is");
588 if (stat(identity_file, &st) < 0)
589 fatal("%s: %s: %s", __progname, identity_file, strerror(errno));
590
591 switch (convert_format) {
592 case FMT_RFC4716:
593 do_convert_from_ssh2(pw, &k, &private);
594 break;
595 case FMT_PKCS8:
596 do_convert_from_pkcs8(&k, &private);
597 break;
598 case FMT_PEM:
599 do_convert_from_pem(&k, &private);
600 break;
601 default:
602 fatal("%s: unknown key format %d", __func__, convert_format);
603 }
604
605 if (!private)
606 ok = key_write(k, stdout);
607 if (ok)
608 fprintf(stdout, "\n");
609 else {
610 switch (k->type) {
611 case KEY_DSA:
612 ok = PEM_write_DSAPrivateKey(stdout, k->dsa, NULL,
613 NULL, 0, NULL, NULL);
614 break;
615 case KEY_RSA:
616 ok = PEM_write_RSAPrivateKey(stdout, k->rsa, NULL,
617 NULL, 0, NULL, NULL);
618 break;
619 default:
620 fatal("%s: unsupported key type %s", __func__,
621 key_type(k));
622 }
623 }
624
463 if (!ok) { 625 if (!ok) {
464 fprintf(stderr, "key write failed\n"); 626 fprintf(stderr, "key write failed\n");
465 exit(1); 627 exit(1);
466 } 628 }
467 key_free(k); 629 key_free(k);
468 if (!private)
469 fprintf(stdout, "\n");
470 fclose(fp);
471 exit(0); 630 exit(0);
472} 631}
473 632
@@ -1525,7 +1684,7 @@ usage(void)
1525#ifdef ENABLE_PKCS11 1684#ifdef ENABLE_PKCS11
1526 fprintf(stderr, " -D pkcs11 Download public key from pkcs11 token.\n"); 1685 fprintf(stderr, " -D pkcs11 Download public key from pkcs11 token.\n");
1527#endif 1686#endif
1528 fprintf(stderr, " -e Convert OpenSSH to RFC 4716 key file.\n"); 1687 fprintf(stderr, " -e Export OpenSSH to foreign format key file.\n");
1529 fprintf(stderr, " -F hostname Find hostname in known hosts file.\n"); 1688 fprintf(stderr, " -F hostname Find hostname in known hosts file.\n");
1530 fprintf(stderr, " -f filename Filename of the key file.\n"); 1689 fprintf(stderr, " -f filename Filename of the key file.\n");
1531 fprintf(stderr, " -G file Generate candidates for DH-GEX moduli.\n"); 1690 fprintf(stderr, " -G file Generate candidates for DH-GEX moduli.\n");
@@ -1533,9 +1692,10 @@ usage(void)
1533 fprintf(stderr, " -H Hash names in known_hosts file.\n"); 1692 fprintf(stderr, " -H Hash names in known_hosts file.\n");
1534 fprintf(stderr, " -h Generate host certificate instead of a user certificate.\n"); 1693 fprintf(stderr, " -h Generate host certificate instead of a user certificate.\n");
1535 fprintf(stderr, " -I key_id Key identifier to include in certificate.\n"); 1694 fprintf(stderr, " -I key_id Key identifier to include in certificate.\n");
1536 fprintf(stderr, " -i Convert RFC 4716 to OpenSSH key file.\n"); 1695 fprintf(stderr, " -i Import foreign format to OpenSSH key file.\n");
1537 fprintf(stderr, " -L Print the contents of a certificate.\n"); 1696 fprintf(stderr, " -L Print the contents of a certificate.\n");
1538 fprintf(stderr, " -l Show fingerprint of key file.\n"); 1697 fprintf(stderr, " -l Show fingerprint of key file.\n");
1698 fprintf(stderr, " -m key_fmt Conversion format for -e/-i (PEM|PKCS8|RFC4716).\n");
1539 fprintf(stderr, " -M memory Amount of memory (MB) to use for generating DH-GEX moduli.\n"); 1699 fprintf(stderr, " -M memory Amount of memory (MB) to use for generating DH-GEX moduli.\n");
1540 fprintf(stderr, " -n name,... User/host principal names to include in certificate\n"); 1700 fprintf(stderr, " -n name,... User/host principal names to include in certificate\n");
1541 fprintf(stderr, " -N phrase Provide new passphrase.\n"); 1701 fprintf(stderr, " -N phrase Provide new passphrase.\n");
@@ -1603,7 +1763,7 @@ main(int argc, char **argv)
1603 exit(1); 1763 exit(1);
1604 } 1764 }
1605 1765
1606 while ((opt = getopt(argc, argv, "degiqpclBHLhvxXyF:b:f:t:D:I:P:N:n:" 1766 while ((opt = getopt(argc, argv, "degiqpclBHLhvxXyF:b:f:t:D:I:P:m:N:n:"
1607 "O:C:r:g:R:T:G:M:S:s:a:V:W:z:")) != -1) { 1767 "O:C:r:g:R:T:G:M:S:s:a:V:W:z:")) != -1) {
1608 switch (opt) { 1768 switch (opt) {
1609 case 'b': 1769 case 'b':
@@ -1635,6 +1795,21 @@ main(int argc, char **argv)
1635 case 'B': 1795 case 'B':
1636 print_bubblebabble = 1; 1796 print_bubblebabble = 1;
1637 break; 1797 break;
1798 case 'm':
1799 if (strcasecmp(optarg, "RFC4716") == 0 ||
1800 strcasecmp(optarg, "ssh2") == 0) {
1801 convert_format = FMT_RFC4716;
1802 break;
1803 }
1804 if (strcasecmp(optarg, "PKCS8") == 0) {
1805 convert_format = FMT_PKCS8;
1806 break;
1807 }
1808 if (strcasecmp(optarg, "PEM") == 0) {
1809 convert_format = FMT_PEM;
1810 break;
1811 }
1812 fatal("Unsupported conversion format \"%s\"", optarg);
1638 case 'n': 1813 case 'n':
1639 cert_principals = optarg; 1814 cert_principals = optarg;
1640 break; 1815 break;
@@ -1671,7 +1846,7 @@ main(int argc, char **argv)
1671 case 'e': 1846 case 'e':
1672 case 'x': 1847 case 'x':
1673 /* export key */ 1848 /* export key */
1674 convert_to_ssh2 = 1; 1849 convert_to = 1;
1675 break; 1850 break;
1676 case 'h': 1851 case 'h':
1677 cert_key_type = SSH2_CERT_TYPE_HOST; 1852 cert_key_type = SSH2_CERT_TYPE_HOST;
@@ -1680,7 +1855,7 @@ main(int argc, char **argv)
1680 case 'i': 1855 case 'i':
1681 case 'X': 1856 case 'X':
1682 /* import key */ 1857 /* import key */
1683 convert_from_ssh2 = 1; 1858 convert_from = 1;
1684 break; 1859 break;
1685 case 'y': 1860 case 'y':
1686 print_public = 1; 1861 print_public = 1;
@@ -1796,10 +1971,10 @@ main(int argc, char **argv)
1796 do_change_passphrase(pw); 1971 do_change_passphrase(pw);
1797 if (change_comment) 1972 if (change_comment)
1798 do_change_comment(pw); 1973 do_change_comment(pw);
1799 if (convert_to_ssh2) 1974 if (convert_to)
1800 do_convert_to_ssh2(pw); 1975 do_convert_to(pw);
1801 if (convert_from_ssh2) 1976 if (convert_from)
1802 do_convert_from_ssh2(pw); 1977 do_convert_from(pw);
1803 if (print_public) 1978 if (print_public)
1804 do_print_public(pw); 1979 do_print_public(pw);
1805 if (rr_hostname != NULL) { 1980 if (rr_hostname != NULL) {