1 /* $OpenBSD: ssh-keygen.c,v 1.477 2024/12/04 14:24:20 djm Exp $ */
3 * Author: Tatu Ylonen <ylo@cs.hut.fi>
4 * Copyright (c) 1994 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
6 * Identity and host key generation and maintenance.
8 * As far as I am concerned, the code I have written for this software
9 * can be used freely for any purpose. Any derived versions of this
10 * software must be clearly marked as such, and if the derived work is
11 * incompatible with the protocol description in the RFC file, it must be
12 * called by a name other than "ssh" or "Secure Shell".
17 #include <sys/types.h>
18 #include <sys/socket.h>
22 #include <openssl/evp.h>
23 #include <openssl/pem.h>
24 #include "openbsd-compat/openssl-compat.h"
50 #include "pathnames.h"
59 #include "ssh-pkcs11.h"
67 #include "sk-api.h" /* XXX for SSH_SK_USER_PRESENCE_REQD; remove */
70 #define DEFAULT_KEY_TYPE_NAME "ed25519"
73 * Default number of bits in the RSA, DSA and ECDSA keys. These value can be
74 * overridden on the command line.
76 * These values, with the exception of DSA, provide security equivalent to at
77 * least 128 bits of security according to NIST Special Publication 800-57:
78 * Recommendation for Key Management Part 1 rev 4 section 5.6.1.
79 * For DSA it (and FIPS-186-4 section 4.2) specifies that the only size for
80 * which a 160bit hash is acceptable is 1kbit, and since ssh-dss specifies only
81 * SHA1 we limit the DSA key size 1k bits.
83 #define DEFAULT_BITS 3072
84 #define DEFAULT_BITS_DSA 1024
85 #define DEFAULT_BITS_ECDSA 256
89 /* Flag indicating that we just want to see the key fingerprint */
90 static int print_fingerprint
= 0;
91 static int print_bubblebabble
= 0;
93 /* Hash algorithm to use for fingerprints. */
94 static int fingerprint_hash
= SSH_FP_HASH_DEFAULT
;
96 /* The identity file name, given on the command line or entered by the user. */
97 static char identity_file
[PATH_MAX
];
98 static int have_identity
= 0;
100 /* This is set to the passphrase if given on the command line. */
101 static char *identity_passphrase
= NULL
;
103 /* This is set to the new passphrase if given on the command line. */
104 static char *identity_new_passphrase
= NULL
;
106 /* Key type when certifying */
107 static u_int cert_key_type
= SSH2_CERT_TYPE_USER
;
109 /* "key ID" of signed key */
110 static char *cert_key_id
= NULL
;
112 /* Comma-separated list of principal names for certifying keys */
113 static char *cert_principals
= NULL
;
115 /* Validity period for certificates */
116 static u_int64_t cert_valid_from
= 0;
117 static u_int64_t cert_valid_to
= ~0ULL;
119 /* Certificate options */
120 #define CERTOPT_X_FWD (1)
121 #define CERTOPT_AGENT_FWD (1<<1)
122 #define CERTOPT_PORT_FWD (1<<2)
123 #define CERTOPT_PTY (1<<3)
124 #define CERTOPT_USER_RC (1<<4)
125 #define CERTOPT_NO_REQUIRE_USER_PRESENCE (1<<5)
126 #define CERTOPT_REQUIRE_VERIFY (1<<6)
127 #define CERTOPT_DEFAULT (CERTOPT_X_FWD|CERTOPT_AGENT_FWD| \
128 CERTOPT_PORT_FWD|CERTOPT_PTY|CERTOPT_USER_RC)
129 static u_int32_t certflags_flags
= CERTOPT_DEFAULT
;
130 static char *certflags_command
= NULL
;
131 static char *certflags_src_addr
= NULL
;
133 /* Arbitrary extensions specified by user */
139 static struct cert_ext
*cert_ext
;
140 static size_t ncert_ext
;
142 /* Conversion to/from various formats */
147 } convert_format
= FMT_RFC4716
;
149 static char *key_type_name
= NULL
;
151 /* Load key from this PKCS#11 provider */
152 static char *pkcs11provider
= NULL
;
154 /* FIDO/U2F provider to use */
155 static char *sk_provider
= NULL
;
157 /* Format for writing private keys */
158 static int private_key_format
= SSHKEY_PRIVATE_OPENSSH
;
160 /* Cipher for new-format private keys */
161 static char *openssh_format_cipher
= NULL
;
163 /* Number of KDF rounds to derive new format keys. */
164 static int rounds
= 0;
167 extern char *__progname
;
169 static char hostname
[NI_MAXHOST
];
173 int gen_candidates(FILE *, u_int32_t
, u_int32_t
, BIGNUM
*);
174 int prime_test(FILE *, FILE *, u_int32_t
, u_int32_t
, char *, unsigned long,
179 type_bits_valid(int type
, const char *name
, u_int32_t
*bitsp
)
181 if (type
== KEY_UNSPEC
)
182 fatal("unknown key type %s", key_type_name
);
189 *bitsp
= DEFAULT_BITS_DSA
;
193 (nid
= sshkey_ecdsa_nid_from_name(name
)) > 0)
194 *bitsp
= sshkey_curve_nid_to_bits(nid
);
196 *bitsp
= DEFAULT_BITS_ECDSA
;
199 *bitsp
= DEFAULT_BITS
;
208 fatal("Invalid DSA key length: must be 1024 bits");
211 if (*bitsp
< SSH_RSA_MINIMUM_MODULUS_SIZE
)
212 fatal("Invalid RSA key length: minimum is %d bits",
213 SSH_RSA_MINIMUM_MODULUS_SIZE
);
214 else if (*bitsp
> OPENSSL_RSA_MAX_MODULUS_BITS
)
215 fatal("Invalid RSA key length: maximum is %d bits",
216 OPENSSL_RSA_MAX_MODULUS_BITS
);
219 if (sshkey_ecdsa_bits_to_nid(*bitsp
) == -1)
220 #ifdef OPENSSL_HAS_NISTP521
221 fatal("Invalid ECDSA key length: valid lengths are "
222 "256, 384 or 521 bits");
224 fatal("Invalid ECDSA key length: valid lengths are "
232 * Checks whether a file exists and, if so, asks the user whether they wish
234 * Returns nonzero if the file does not already exist or if the user agrees to
235 * overwrite, or zero otherwise.
238 confirm_overwrite(const char *filename
)
243 if (stat(filename
, &st
) != 0)
245 printf("%s already exists.\n", filename
);
246 printf("Overwrite (y/n)? ");
248 if (fgets(yesno
, sizeof(yesno
), stdin
) == NULL
)
250 if (yesno
[0] != 'y' && yesno
[0] != 'Y')
256 ask_filename(struct passwd
*pw
, const char *prompt
)
261 if (key_type_name
== NULL
)
262 name
= _PATH_SSH_CLIENT_ID_ED25519
;
264 switch (sshkey_type_from_shortname(key_type_name
)) {
268 name
= _PATH_SSH_CLIENT_ID_DSA
;
271 #ifdef OPENSSL_HAS_ECC
274 name
= _PATH_SSH_CLIENT_ID_ECDSA
;
276 case KEY_ECDSA_SK_CERT
:
278 name
= _PATH_SSH_CLIENT_ID_ECDSA_SK
;
283 name
= _PATH_SSH_CLIENT_ID_RSA
;
286 case KEY_ED25519_CERT
:
287 name
= _PATH_SSH_CLIENT_ID_ED25519
;
290 case KEY_ED25519_SK_CERT
:
291 name
= _PATH_SSH_CLIENT_ID_ED25519_SK
;
295 name
= _PATH_SSH_CLIENT_ID_XMSS
;
298 fatal("bad key type");
301 snprintf(identity_file
, sizeof(identity_file
),
302 "%s/%s", pw
->pw_dir
, name
);
303 printf("%s (%s): ", prompt
, identity_file
);
305 if (fgets(buf
, sizeof(buf
), stdin
) == NULL
)
307 buf
[strcspn(buf
, "\n")] = '\0';
308 if (strcmp(buf
, "") != 0)
309 strlcpy(identity_file
, buf
, sizeof(identity_file
));
313 static struct sshkey
*
314 load_identity(const char *filename
, char **commentp
)
320 if (commentp
!= NULL
)
322 if ((r
= sshkey_load_private(filename
, "", &prv
, commentp
)) == 0)
324 if (r
!= SSH_ERR_KEY_WRONG_PASSPHRASE
)
325 fatal_r(r
, "Load key \"%s\"", filename
);
326 if (identity_passphrase
)
327 pass
= xstrdup(identity_passphrase
);
329 xasprintf(&prompt
, "Enter passphrase for \"%s\": ", filename
);
330 pass
= read_passphrase(prompt
, RP_ALLOW_STDIN
);
333 r
= sshkey_load_private(filename
, pass
, &prv
, commentp
);
334 freezero(pass
, strlen(pass
));
336 fatal_r(r
, "Load key \"%s\"", filename
);
340 #define SSH_COM_PUBLIC_BEGIN "---- BEGIN SSH2 PUBLIC KEY ----"
341 #define SSH_COM_PUBLIC_END "---- END SSH2 PUBLIC KEY ----"
342 #define SSH_COM_PRIVATE_BEGIN "---- BEGIN SSH2 ENCRYPTED PRIVATE KEY ----"
343 #define SSH_COM_PRIVATE_KEY_MAGIC 0x3f6ff9eb
347 do_convert_to_ssh2(struct passwd
*pw
, struct sshkey
*k
)
350 char comment
[61], *b64
;
353 if ((b
= sshbuf_new()) == NULL
)
354 fatal_f("sshbuf_new failed");
355 if ((r
= sshkey_putb(k
, b
)) != 0)
356 fatal_fr(r
, "put key");
357 if ((b64
= sshbuf_dtob64_string(b
, 1)) == NULL
)
358 fatal_f("sshbuf_dtob64_string failed");
360 /* Comment + surrounds must fit into 72 chars (RFC 4716 sec 3.3) */
361 snprintf(comment
, sizeof(comment
),
362 "%u-bit %s, converted by %s@%s from OpenSSH",
363 sshkey_size(k
), sshkey_type(k
),
364 pw
->pw_name
, hostname
);
369 fprintf(stdout
, "%s\n", SSH_COM_PUBLIC_BEGIN
);
370 fprintf(stdout
, "Comment: \"%s\"\n%s", comment
, b64
);
371 fprintf(stdout
, "%s\n", SSH_COM_PUBLIC_END
);
377 do_convert_to_pkcs8(struct sshkey
*k
)
379 switch (sshkey_type_plain(k
->type
)) {
381 if (!PEM_write_RSA_PUBKEY(stdout
,
382 EVP_PKEY_get0_RSA(k
->pkey
)))
383 fatal("PEM_write_RSA_PUBKEY failed");
387 if (!PEM_write_DSA_PUBKEY(stdout
, k
->dsa
))
388 fatal("PEM_write_DSA_PUBKEY failed");
391 #ifdef OPENSSL_HAS_ECC
393 if (!PEM_write_EC_PUBKEY(stdout
,
394 EVP_PKEY_get0_EC_KEY(k
->pkey
)))
395 fatal("PEM_write_EC_PUBKEY failed");
399 fatal_f("unsupported key type %s", sshkey_type(k
));
405 do_convert_to_pem(struct sshkey
*k
)
407 switch (sshkey_type_plain(k
->type
)) {
409 if (!PEM_write_RSAPublicKey(stdout
,
410 EVP_PKEY_get0_RSA(k
->pkey
)))
411 fatal("PEM_write_RSAPublicKey failed");
415 if (!PEM_write_DSA_PUBKEY(stdout
, k
->dsa
))
416 fatal("PEM_write_DSA_PUBKEY failed");
419 #ifdef OPENSSL_HAS_ECC
421 if (!PEM_write_EC_PUBKEY(stdout
,
422 EVP_PKEY_get0_EC_KEY(k
->pkey
)))
423 fatal("PEM_write_EC_PUBKEY failed");
427 fatal_f("unsupported key type %s", sshkey_type(k
));
433 do_convert_to(struct passwd
*pw
)
440 ask_filename(pw
, "Enter file in which the key is");
441 if (stat(identity_file
, &st
) == -1)
442 fatal("%s: %s: %s", __progname
, identity_file
, strerror(errno
));
443 if ((r
= sshkey_load_public(identity_file
, &k
, NULL
)) != 0)
444 k
= load_identity(identity_file
, NULL
);
445 switch (convert_format
) {
447 do_convert_to_ssh2(pw
, k
);
450 do_convert_to_pkcs8(k
);
453 do_convert_to_pem(k
);
456 fatal_f("unknown key format %d", convert_format
);
462 * This is almost exactly the bignum1 encoding, but with 32 bit for length
466 buffer_get_bignum_bits(struct sshbuf
*b
, BIGNUM
*value
)
468 u_int bytes
, bignum_bits
;
471 if ((r
= sshbuf_get_u32(b
, &bignum_bits
)) != 0)
472 fatal_fr(r
, "parse");
473 bytes
= (bignum_bits
+ 7) / 8;
474 if (sshbuf_len(b
) < bytes
)
475 fatal_f("input buffer too small: need %d have %zu",
476 bytes
, sshbuf_len(b
));
477 if (BN_bin2bn(sshbuf_ptr(b
), bytes
, value
) == NULL
)
478 fatal_f("BN_bin2bn failed");
479 if ((r
= sshbuf_consume(b
, bytes
)) != 0)
480 fatal_fr(r
, "consume");
483 static struct sshkey
*
484 do_convert_private_ssh2(struct sshbuf
*b
)
486 struct sshkey
*key
= NULL
;
488 const char *alg
= NULL
;
489 u_char e1
, e2
, e3
, *sig
= NULL
, data
[] = "abcde12345";
491 u_int magic
, i1
, i2
, i3
, i4
;
495 BIGNUM
*dsa_p
= NULL
, *dsa_q
= NULL
, *dsa_g
= NULL
;
496 BIGNUM
*dsa_pub_key
= NULL
, *dsa_priv_key
= NULL
;
498 BIGNUM
*rsa_n
= NULL
, *rsa_e
= NULL
, *rsa_d
= NULL
;
499 BIGNUM
*rsa_p
= NULL
, *rsa_q
= NULL
, *rsa_iqmp
= NULL
;
500 BIGNUM
*rsa_dmp1
= NULL
, *rsa_dmq1
= NULL
;
503 if ((r
= sshbuf_get_u32(b
, &magic
)) != 0)
504 fatal_fr(r
, "parse magic");
506 if (magic
!= SSH_COM_PRIVATE_KEY_MAGIC
) {
507 error("bad magic 0x%x != 0x%x", magic
,
508 SSH_COM_PRIVATE_KEY_MAGIC
);
511 if ((r
= sshbuf_get_u32(b
, &i1
)) != 0 ||
512 (r
= sshbuf_get_cstring(b
, &type
, NULL
)) != 0 ||
513 (r
= sshbuf_get_cstring(b
, &cipher
, NULL
)) != 0 ||
514 (r
= sshbuf_get_u32(b
, &i2
)) != 0 ||
515 (r
= sshbuf_get_u32(b
, &i3
)) != 0 ||
516 (r
= sshbuf_get_u32(b
, &i4
)) != 0)
517 fatal_fr(r
, "parse");
518 debug("ignore (%d %d %d %d)", i1
, i2
, i3
, i4
);
519 if (strcmp(cipher
, "none") != 0) {
520 error("unsupported cipher %s", cipher
);
527 if (strstr(type
, "rsa")) {
530 } else if (strstr(type
, "dsa")) {
537 if ((key
= sshkey_new(ktype
)) == NULL
)
538 fatal("sshkey_new failed");
544 if ((dsa_p
= BN_new()) == NULL
||
545 (dsa_q
= BN_new()) == NULL
||
546 (dsa_g
= BN_new()) == NULL
||
547 (dsa_pub_key
= BN_new()) == NULL
||
548 (dsa_priv_key
= BN_new()) == NULL
)
550 buffer_get_bignum_bits(b
, dsa_p
);
551 buffer_get_bignum_bits(b
, dsa_g
);
552 buffer_get_bignum_bits(b
, dsa_q
);
553 buffer_get_bignum_bits(b
, dsa_pub_key
);
554 buffer_get_bignum_bits(b
, dsa_priv_key
);
555 if (!DSA_set0_pqg(key
->dsa
, dsa_p
, dsa_q
, dsa_g
))
556 fatal_f("DSA_set0_pqg failed");
557 dsa_p
= dsa_q
= dsa_g
= NULL
; /* transferred */
558 if (!DSA_set0_key(key
->dsa
, dsa_pub_key
, dsa_priv_key
))
559 fatal_f("DSA_set0_key failed");
560 dsa_pub_key
= dsa_priv_key
= NULL
; /* transferred */
564 if ((r
= sshbuf_get_u8(b
, &e1
)) != 0 ||
565 (e1
< 30 && (r
= sshbuf_get_u8(b
, &e2
)) != 0) ||
566 (e1
< 30 && (r
= sshbuf_get_u8(b
, &e3
)) != 0))
567 fatal_fr(r
, "parse RSA");
578 if ((rsa_e
= BN_new()) == NULL
)
580 if (!BN_set_word(rsa_e
, e
)) {
581 BN_clear_free(rsa_e
);
585 if ((rsa_n
= BN_new()) == NULL
||
586 (rsa_d
= BN_new()) == NULL
||
587 (rsa_p
= BN_new()) == NULL
||
588 (rsa_q
= BN_new()) == NULL
||
589 (rsa_iqmp
= BN_new()) == NULL
)
591 buffer_get_bignum_bits(b
, rsa_d
);
592 buffer_get_bignum_bits(b
, rsa_n
);
593 buffer_get_bignum_bits(b
, rsa_iqmp
);
594 buffer_get_bignum_bits(b
, rsa_q
);
595 buffer_get_bignum_bits(b
, rsa_p
);
596 if ((r
= ssh_rsa_complete_crt_parameters(rsa_d
, rsa_p
, rsa_q
,
597 rsa_iqmp
, &rsa_dmp1
, &rsa_dmq1
)) != 0)
598 fatal_fr(r
, "generate RSA CRT parameters");
599 if ((key
->pkey
= EVP_PKEY_new()) == NULL
)
600 fatal_f("EVP_PKEY_new failed");
601 if ((rsa
= RSA_new()) == NULL
)
602 fatal_f("RSA_new failed");
603 if (!RSA_set0_key(rsa
, rsa_n
, rsa_e
, rsa_d
))
604 fatal_f("RSA_set0_key failed");
605 rsa_n
= rsa_e
= rsa_d
= NULL
; /* transferred */
606 if (!RSA_set0_factors(rsa
, rsa_p
, rsa_q
))
607 fatal_f("RSA_set0_factors failed");
608 rsa_p
= rsa_q
= NULL
; /* transferred */
609 if (RSA_set0_crt_params(rsa
, rsa_dmp1
, rsa_dmq1
, rsa_iqmp
) != 1)
610 fatal_f("RSA_set0_crt_params failed");
611 rsa_dmp1
= rsa_dmq1
= rsa_iqmp
= NULL
;
612 if (EVP_PKEY_set1_RSA(key
->pkey
, rsa
) != 1)
613 fatal_f("EVP_PKEY_set1_RSA failed");
615 alg
= "rsa-sha2-256";
618 rlen
= sshbuf_len(b
);
620 error_f("remaining bytes in key blob %d", rlen
);
623 if ((r
= sshkey_sign(key
, &sig
, &slen
, data
, sizeof(data
),
624 alg
, NULL
, NULL
, 0)) != 0)
625 error_fr(r
, "signing with converted key failed");
626 else if ((r
= sshkey_verify(key
, sig
, slen
, data
, sizeof(data
),
628 error_fr(r
, "verification with converted key failed");
639 get_line(FILE *fp
, char *line
, size_t len
)
645 while ((c
= fgetc(fp
)) != EOF
) {
647 fatal("input line too long.");
651 if (c
!= EOF
&& c
!= '\n' && ungetc(c
, fp
) == EOF
)
652 fatal("unget: %s", strerror(errno
));
665 do_convert_from_ssh2(struct passwd
*pw
, struct sshkey
**k
, int *private)
667 int r
, blen
, escaped
= 0;
674 if ((buf
= sshbuf_new()) == NULL
)
675 fatal("sshbuf_new failed");
676 if ((fp
= fopen(identity_file
, "r")) == NULL
)
677 fatal("%s: %s: %s", __progname
, identity_file
, strerror(errno
));
679 while ((blen
= get_line(fp
, line
, sizeof(line
))) != -1) {
680 if (blen
> 0 && line
[blen
- 1] == '\\')
682 if (strncmp(line
, "----", 4) == 0 ||
683 strstr(line
, ": ") != NULL
) {
684 if (strstr(line
, SSH_COM_PRIVATE_BEGIN
) != NULL
)
686 if (strstr(line
, " END ") != NULL
) {
689 /* fprintf(stderr, "ignore: %s", line); */
694 /* fprintf(stderr, "escaped: %s", line); */
697 strlcat(encoded
, line
, sizeof(encoded
));
699 len
= strlen(encoded
);
700 if (((len
% 4) == 3) &&
701 (encoded
[len
-1] == '=') &&
702 (encoded
[len
-2] == '=') &&
703 (encoded
[len
-3] == '='))
704 encoded
[len
-3] = '\0';
705 if ((r
= sshbuf_b64tod(buf
, encoded
)) != 0)
706 fatal_fr(r
, "base64 decode");
708 if ((*k
= do_convert_private_ssh2(buf
)) == NULL
)
709 fatal_f("private key conversion failed");
710 } else if ((r
= sshkey_fromb(buf
, k
)) != 0)
711 fatal_fr(r
, "parse key");
717 do_convert_from_pkcs8(struct sshkey
**k
, int *private)
722 if ((fp
= fopen(identity_file
, "r")) == NULL
)
723 fatal("%s: %s: %s", __progname
, identity_file
, strerror(errno
));
724 if ((pubkey
= PEM_read_PUBKEY(fp
, NULL
, NULL
, NULL
)) == NULL
) {
725 fatal_f("%s is not a recognised public key format",
729 switch (EVP_PKEY_base_id(pubkey
)) {
731 if ((*k
= sshkey_new(KEY_UNSPEC
)) == NULL
)
732 fatal("sshkey_new failed");
733 (*k
)->type
= KEY_RSA
;
739 if ((*k
= sshkey_new(KEY_UNSPEC
)) == NULL
)
740 fatal("sshkey_new failed");
741 (*k
)->type
= KEY_DSA
;
742 (*k
)->dsa
= EVP_PKEY_get1_DSA(pubkey
);
745 #ifdef OPENSSL_HAS_ECC
747 if ((*k
= sshkey_new(KEY_UNSPEC
)) == NULL
)
748 fatal("sshkey_new failed");
749 if (((*k
)->ecdsa_nid
= sshkey_ecdsa_fixup_group(pubkey
)) == -1)
750 fatal("sshkey_ecdsa_fixup_group failed");
751 (*k
)->type
= KEY_ECDSA
;
757 fatal_f("unsupported pubkey type %d",
758 EVP_PKEY_base_id(pubkey
));
760 EVP_PKEY_free(pubkey
);
765 do_convert_from_pem(struct sshkey
**k
, int *private)
770 if ((fp
= fopen(identity_file
, "r")) == NULL
)
771 fatal("%s: %s: %s", __progname
, identity_file
, strerror(errno
));
772 if ((rsa
= PEM_read_RSAPublicKey(fp
, NULL
, NULL
, NULL
)) != NULL
) {
773 if ((*k
= sshkey_new(KEY_UNSPEC
)) == NULL
)
774 fatal("sshkey_new failed");
775 if (((*k
)->pkey
= EVP_PKEY_new()) == NULL
)
776 fatal("EVP_PKEY_new failed");
777 (*k
)->type
= KEY_RSA
;
778 if (EVP_PKEY_set1_RSA((*k
)->pkey
, rsa
) != 1)
779 fatal("EVP_PKEY_set1_RSA failed");
784 fatal_f("unrecognised raw private key format");
788 do_convert_from(struct passwd
*pw
)
790 struct sshkey
*k
= NULL
;
791 int r
, private = 0, ok
= 0;
795 ask_filename(pw
, "Enter file in which the key is");
796 if (stat(identity_file
, &st
) == -1)
797 fatal("%s: %s: %s", __progname
, identity_file
, strerror(errno
));
799 switch (convert_format
) {
801 do_convert_from_ssh2(pw
, &k
, &private);
804 do_convert_from_pkcs8(&k
, &private);
807 do_convert_from_pem(&k
, &private);
810 fatal_f("unknown key format %d", convert_format
);
814 if ((r
= sshkey_write(k
, stdout
)) == 0)
817 fprintf(stdout
, "\n");
822 ok
= PEM_write_DSAPrivateKey(stdout
, k
->dsa
, NULL
,
823 NULL
, 0, NULL
, NULL
);
826 #ifdef OPENSSL_HAS_ECC
828 ok
= PEM_write_ECPrivateKey(stdout
,
829 EVP_PKEY_get0_EC_KEY(k
->pkey
), NULL
, NULL
, 0,
834 ok
= PEM_write_RSAPrivateKey(stdout
,
835 EVP_PKEY_get0_RSA(k
->pkey
), NULL
, NULL
, 0,
839 fatal_f("unsupported key type %s", sshkey_type(k
));
844 fatal("key write failed");
851 do_print_public(struct passwd
*pw
)
856 char *comment
= NULL
;
859 ask_filename(pw
, "Enter file in which the key is");
860 if (stat(identity_file
, &st
) == -1)
861 fatal("%s: %s", identity_file
, strerror(errno
));
862 prv
= load_identity(identity_file
, &comment
);
863 if ((r
= sshkey_write(prv
, stdout
)) != 0)
864 fatal_fr(r
, "write key");
865 if (comment
!= NULL
&& *comment
!= '\0')
866 fprintf(stdout
, " %s", comment
);
867 fprintf(stdout
, "\n");
868 if (sshkey_is_sk(prv
)) {
869 debug("sk_application: \"%s\", sk_flags 0x%02x",
870 prv
->sk_application
, prv
->sk_flags
);
878 do_download(struct passwd
*pw
)
881 struct sshkey
**keys
= NULL
;
883 enum sshkey_fp_rep rep
;
885 char *fp
, *ra
, **comments
= NULL
;
887 fptype
= print_bubblebabble
? SSH_DIGEST_SHA1
: fingerprint_hash
;
888 rep
= print_bubblebabble
? SSH_FP_BUBBLEBABBLE
: SSH_FP_DEFAULT
;
891 nkeys
= pkcs11_add_provider(pkcs11provider
, NULL
, &keys
, &comments
);
893 fatal("cannot read public key from pkcs11");
894 for (i
= 0; i
< nkeys
; i
++) {
895 if (print_fingerprint
) {
896 fp
= sshkey_fingerprint(keys
[i
], fptype
, rep
);
897 ra
= sshkey_fingerprint(keys
[i
], fingerprint_hash
,
899 if (fp
== NULL
|| ra
== NULL
)
900 fatal_f("sshkey_fingerprint fail");
901 printf("%u %s %s (PKCS11 key)\n", sshkey_size(keys
[i
]),
902 fp
, sshkey_type(keys
[i
]));
903 if (log_level_get() >= SYSLOG_LEVEL_VERBOSE
)
908 (void) sshkey_write(keys
[i
], stdout
); /* XXX check */
909 fprintf(stdout
, "%s%s\n",
910 *(comments
[i
]) == '\0' ? "" : " ", comments
[i
]);
913 sshkey_free(keys
[i
]);
920 fatal("no pkcs11 support");
921 #endif /* ENABLE_PKCS11 */
924 static struct sshkey
*
925 try_read_key(char **cpp
)
930 if ((ret
= sshkey_new(KEY_UNSPEC
)) == NULL
)
931 fatal("sshkey_new failed");
932 if ((r
= sshkey_read(ret
, cpp
)) == 0)
940 fingerprint_one_key(const struct sshkey
*public, const char *comment
)
942 char *fp
= NULL
, *ra
= NULL
;
943 enum sshkey_fp_rep rep
;
946 fptype
= print_bubblebabble
? SSH_DIGEST_SHA1
: fingerprint_hash
;
947 rep
= print_bubblebabble
? SSH_FP_BUBBLEBABBLE
: SSH_FP_DEFAULT
;
948 fp
= sshkey_fingerprint(public, fptype
, rep
);
949 ra
= sshkey_fingerprint(public, fingerprint_hash
, SSH_FP_RANDOMART
);
950 if (fp
== NULL
|| ra
== NULL
)
951 fatal_f("sshkey_fingerprint failed");
952 mprintf("%u %s %s (%s)\n", sshkey_size(public), fp
,
953 comment
? comment
: "no comment", sshkey_type(public));
954 if (log_level_get() >= SYSLOG_LEVEL_VERBOSE
)
961 fingerprint_private(const char *path
)
964 char *comment
= NULL
;
965 struct sshkey
*privkey
= NULL
, *pubkey
= NULL
;
968 if (stat(identity_file
, &st
) == -1)
969 fatal("%s: %s", path
, strerror(errno
));
970 if ((r
= sshkey_load_public(path
, &pubkey
, &comment
)) != 0)
971 debug_r(r
, "load public \"%s\"", path
);
972 if (pubkey
== NULL
|| comment
== NULL
|| *comment
== '\0') {
974 if ((r
= sshkey_load_private(path
, NULL
,
975 &privkey
, &comment
)) != 0)
976 debug_r(r
, "load private \"%s\"", path
);
978 if (pubkey
== NULL
&& privkey
== NULL
)
979 fatal("%s is not a key file.", path
);
981 fingerprint_one_key(pubkey
== NULL
? privkey
: pubkey
, comment
);
983 sshkey_free(privkey
);
988 do_fingerprint(struct passwd
*pw
)
991 struct sshkey
*public = NULL
;
992 char *comment
= NULL
, *cp
, *ep
, *line
= NULL
;
999 ask_filename(pw
, "Enter file in which the key is");
1000 path
= identity_file
;
1002 if (strcmp(identity_file
, "-") == 0) {
1005 } else if ((f
= fopen(path
, "r")) == NULL
)
1006 fatal("%s: %s: %s", __progname
, path
, strerror(errno
));
1008 while (getline(&line
, &linesize
, f
) != -1) {
1011 cp
[strcspn(cp
, "\r\n")] = '\0';
1012 /* Trim leading space and comments */
1013 cp
= line
+ strspn(line
, " \t");
1014 if (*cp
== '#' || *cp
== '\0')
1018 * Input may be plain keys, private keys, authorized_keys
1023 * Try private keys first. Assume a key is private if
1024 * "SSH PRIVATE KEY" appears on the first line and we're
1025 * not reading from stdin (XXX support private keys on stdin).
1027 if (lnum
== 1 && strcmp(identity_file
, "-") != 0 &&
1028 strstr(cp
, "PRIVATE KEY") != NULL
) {
1031 fingerprint_private(path
);
1036 * If it's not a private key, then this must be prepared to
1037 * accept a public key prefixed with a hostname or options.
1038 * Try a bare key first, otherwise skip the leading stuff.
1041 if ((public = try_read_key(&cp
)) == NULL
) {
1042 i
= strtol(cp
, &ep
, 10);
1043 if (i
== 0 || ep
== NULL
||
1044 (*ep
!= ' ' && *ep
!= '\t')) {
1048 for (; *cp
&& (quoted
|| (*cp
!= ' ' &&
1049 *cp
!= '\t')); cp
++) {
1050 if (*cp
== '\\' && cp
[1] == '"')
1051 cp
++; /* Skip both */
1052 else if (*cp
== '"')
1060 /* Retry after parsing leading hostname/key options */
1061 if (public == NULL
&& (public = try_read_key(&cp
)) == NULL
) {
1062 debug("%s:%lu: not a public key", path
, lnum
);
1066 /* Find trailing comment, if any */
1067 for (; *cp
== ' ' || *cp
== '\t'; cp
++)
1069 if (*cp
!= '\0' && *cp
!= '#')
1072 fingerprint_one_key(public, comment
);
1073 sshkey_free(public);
1074 invalid
= 0; /* One good key in the file is sufficient */
1080 fatal("%s is not a public key file.", path
);
1085 do_gen_all_hostkeys(struct passwd
*pw
)
1089 char *key_type_display
;
1093 { "rsa", "RSA" ,_PATH_HOST_RSA_KEY_FILE
},
1094 #ifdef OPENSSL_HAS_ECC
1095 { "ecdsa", "ECDSA",_PATH_HOST_ECDSA_KEY_FILE
},
1096 #endif /* OPENSSL_HAS_ECC */
1097 #endif /* WITH_OPENSSL */
1098 { "ed25519", "ED25519",_PATH_HOST_ED25519_KEY_FILE
},
1100 { "xmss", "XMSS",_PATH_HOST_XMSS_KEY_FILE
},
1101 #endif /* WITH_XMSS */
1102 { NULL
, NULL
, NULL
}
1108 struct sshkey
*private, *public;
1109 char comment
[1024], *prv_tmp
, *pub_tmp
, *prv_file
, *pub_file
;
1112 for (i
= 0; key_types
[i
].key_type
; i
++) {
1113 public = private = NULL
;
1114 prv_tmp
= pub_tmp
= prv_file
= pub_file
= NULL
;
1116 xasprintf(&prv_file
, "%s%s",
1117 identity_file
, key_types
[i
].path
);
1119 /* Check whether private key exists and is not zero-length */
1120 if (stat(prv_file
, &st
) == 0) {
1121 if (st
.st_size
!= 0)
1123 } else if (errno
!= ENOENT
) {
1124 error("Could not stat %s: %s", key_types
[i
].path
,
1130 * Private key doesn't exist or is invalid; proceed with
1133 xasprintf(&prv_tmp
, "%s%s.XXXXXXXXXX",
1134 identity_file
, key_types
[i
].path
);
1135 xasprintf(&pub_tmp
, "%s%s.pub.XXXXXXXXXX",
1136 identity_file
, key_types
[i
].path
);
1137 xasprintf(&pub_file
, "%s%s.pub",
1138 identity_file
, key_types
[i
].path
);
1142 printf("%s: generating new host keys: ", __progname
);
1144 printf("%s ", key_types
[i
].key_type_display
);
1146 type
= sshkey_type_from_shortname(key_types
[i
].key_type
);
1147 if ((fd
= mkstemp(prv_tmp
)) == -1) {
1148 error("Could not save your private key in %s: %s",
1149 prv_tmp
, strerror(errno
));
1152 (void)close(fd
); /* just using mkstemp() to reserve a name */
1154 type_bits_valid(type
, NULL
, &bits
);
1155 if ((r
= sshkey_generate(type
, bits
, &private)) != 0) {
1156 error_r(r
, "sshkey_generate failed");
1159 if ((r
= sshkey_from_private(private, &public)) != 0)
1160 fatal_fr(r
, "sshkey_from_private");
1161 snprintf(comment
, sizeof comment
, "%s@%s", pw
->pw_name
,
1163 if ((r
= sshkey_save_private(private, prv_tmp
, "",
1164 comment
, private_key_format
, openssh_format_cipher
,
1166 error_r(r
, "Saving key \"%s\" failed", prv_tmp
);
1169 if ((fd
= mkstemp(pub_tmp
)) == -1) {
1170 error("Could not save your public key in %s: %s",
1171 pub_tmp
, strerror(errno
));
1174 (void)fchmod(fd
, 0644);
1176 if ((r
= sshkey_save_public(public, pub_tmp
, comment
)) != 0) {
1177 error_r(r
, "Unable to save public key to %s",
1182 /* Rename temporary files to their permanent locations. */
1183 if (rename(pub_tmp
, pub_file
) != 0) {
1184 error("Unable to move %s into position: %s",
1185 pub_file
, strerror(errno
));
1188 if (rename(prv_tmp
, prv_file
) != 0) {
1189 error("Unable to move %s into position: %s",
1190 key_types
[i
].path
, strerror(errno
));
1196 sshkey_free(private);
1197 sshkey_free(public);
1207 struct known_hosts_ctx
{
1208 const char *host
; /* Hostname searched for in find/delete case */
1209 FILE *out
; /* Output file, stdout for find_hosts case */
1210 int has_unhashed
; /* When hashing, original had unhashed hosts */
1211 int found_key
; /* For find/delete, host was found */
1212 int invalid
; /* File contained invalid items; don't delete */
1213 int hash_hosts
; /* Hash hostnames as we go */
1214 int find_host
; /* Search for specific hostname */
1215 int delete_host
; /* Delete host from known_hosts */
1219 known_hosts_hash(struct hostkey_foreach_line
*l
, void *_ctx
)
1221 struct known_hosts_ctx
*ctx
= (struct known_hosts_ctx
*)_ctx
;
1222 char *hashed
, *cp
, *hosts
, *ohosts
;
1223 int has_wild
= l
->hosts
&& strcspn(l
->hosts
, "*?!") != strlen(l
->hosts
);
1224 int was_hashed
= l
->hosts
&& l
->hosts
[0] == HASH_DELIM
;
1226 switch (l
->status
) {
1228 case HKF_STATUS_MATCHED
:
1230 * Don't hash hosts already hashed, with wildcard
1231 * characters or a CA/revocation marker.
1233 if (was_hashed
|| has_wild
|| l
->marker
!= MRK_NONE
) {
1234 fprintf(ctx
->out
, "%s\n", l
->line
);
1235 if (has_wild
&& !ctx
->find_host
) {
1236 logit("%s:%lu: ignoring host name "
1237 "with wildcard: %.64s", l
->path
,
1238 l
->linenum
, l
->hosts
);
1243 * Split any comma-separated hostnames from the host list,
1244 * hash and store separately.
1246 ohosts
= hosts
= xstrdup(l
->hosts
);
1247 while ((cp
= strsep(&hosts
, ",")) != NULL
&& *cp
!= '\0') {
1249 if ((hashed
= host_hash(cp
, NULL
, 0)) == NULL
)
1250 fatal("hash_host failed");
1251 fprintf(ctx
->out
, "%s %s\n", hashed
, l
->rawkey
);
1253 ctx
->has_unhashed
= 1;
1257 case HKF_STATUS_INVALID
:
1258 /* Retain invalid lines, but mark file as invalid. */
1260 logit("%s:%lu: invalid line", l
->path
, l
->linenum
);
1263 fprintf(ctx
->out
, "%s\n", l
->line
);
1271 known_hosts_find_delete(struct hostkey_foreach_line
*l
, void *_ctx
)
1273 struct known_hosts_ctx
*ctx
= (struct known_hosts_ctx
*)_ctx
;
1274 enum sshkey_fp_rep rep
;
1276 char *fp
= NULL
, *ra
= NULL
;
1278 fptype
= print_bubblebabble
? SSH_DIGEST_SHA1
: fingerprint_hash
;
1279 rep
= print_bubblebabble
? SSH_FP_BUBBLEBABBLE
: SSH_FP_DEFAULT
;
1281 if (l
->status
== HKF_STATUS_MATCHED
) {
1282 if (ctx
->delete_host
) {
1283 if (l
->marker
!= MRK_NONE
) {
1284 /* Don't remove CA and revocation lines */
1285 fprintf(ctx
->out
, "%s\n", l
->line
);
1288 * Hostname matches and has no CA/revoke
1289 * marker, delete it by *not* writing the
1294 printf("# Host %s found: line %lu\n",
1295 ctx
->host
, l
->linenum
);
1298 } else if (ctx
->find_host
) {
1301 printf("# Host %s found: line %lu %s\n",
1303 l
->linenum
, l
->marker
== MRK_CA
? "CA" :
1304 (l
->marker
== MRK_REVOKE
? "REVOKED" : ""));
1306 if (ctx
->hash_hosts
)
1307 known_hosts_hash(l
, ctx
);
1308 else if (print_fingerprint
) {
1309 fp
= sshkey_fingerprint(l
->key
, fptype
, rep
);
1310 ra
= sshkey_fingerprint(l
->key
,
1311 fingerprint_hash
, SSH_FP_RANDOMART
);
1312 if (fp
== NULL
|| ra
== NULL
)
1313 fatal_f("sshkey_fingerprint failed");
1314 mprintf("%s %s %s%s%s\n", ctx
->host
,
1315 sshkey_type(l
->key
), fp
,
1316 l
->comment
[0] ? " " : "",
1318 if (log_level_get() >= SYSLOG_LEVEL_VERBOSE
)
1323 fprintf(ctx
->out
, "%s\n", l
->line
);
1326 } else if (ctx
->delete_host
) {
1327 /* Retain non-matching hosts when deleting */
1328 if (l
->status
== HKF_STATUS_INVALID
) {
1330 logit("%s:%lu: invalid line", l
->path
, l
->linenum
);
1332 fprintf(ctx
->out
, "%s\n", l
->line
);
1338 do_known_hosts(struct passwd
*pw
, const char *name
, int find_host
,
1339 int delete_host
, int hash_hosts
)
1341 char *cp
, tmp
[PATH_MAX
], old
[PATH_MAX
];
1342 int r
, fd
, oerrno
, inplace
= 0;
1343 struct known_hosts_ctx ctx
;
1344 u_int foreach_options
;
1347 if (!have_identity
) {
1348 cp
= tilde_expand_filename(_PATH_SSH_USER_HOSTFILE
, pw
->pw_uid
);
1349 if (strlcpy(identity_file
, cp
, sizeof(identity_file
)) >=
1350 sizeof(identity_file
))
1351 fatal("Specified known hosts path too long");
1355 if (stat(identity_file
, &sb
) != 0)
1356 fatal("Cannot stat %s: %s", identity_file
, strerror(errno
));
1358 memset(&ctx
, 0, sizeof(ctx
));
1361 ctx
.hash_hosts
= hash_hosts
;
1362 ctx
.find_host
= find_host
;
1363 ctx
.delete_host
= delete_host
;
1366 * Find hosts goes to stdout, hash and deletions happen in-place
1367 * A corner case is ssh-keygen -HF foo, which should go to stdout
1369 if (!find_host
&& (hash_hosts
|| delete_host
)) {
1370 if (strlcpy(tmp
, identity_file
, sizeof(tmp
)) >= sizeof(tmp
) ||
1371 strlcat(tmp
, ".XXXXXXXXXX", sizeof(tmp
)) >= sizeof(tmp
) ||
1372 strlcpy(old
, identity_file
, sizeof(old
)) >= sizeof(old
) ||
1373 strlcat(old
, ".old", sizeof(old
)) >= sizeof(old
))
1374 fatal("known_hosts path too long");
1376 if ((fd
= mkstemp(tmp
)) == -1)
1377 fatal("mkstemp: %s", strerror(errno
));
1378 if ((ctx
.out
= fdopen(fd
, "w")) == NULL
) {
1381 fatal("fdopen: %s", strerror(oerrno
));
1383 (void)fchmod(fd
, sb
.st_mode
& 0644);
1386 /* XXX support identity_file == "-" for stdin */
1387 foreach_options
= find_host
? HKF_WANT_MATCH
: 0;
1388 foreach_options
|= print_fingerprint
? HKF_WANT_PARSE_KEY
: 0;
1389 if ((r
= hostkeys_foreach(identity_file
, (find_host
|| !hash_hosts
) ?
1390 known_hosts_find_delete
: known_hosts_hash
, &ctx
, name
, NULL
,
1391 foreach_options
, 0)) != 0) {
1394 fatal_fr(r
, "hostkeys_foreach");
1401 error("%s is not a valid known_hosts file.", identity_file
);
1403 error("Not replacing existing known_hosts "
1404 "file because of errors");
1408 } else if (delete_host
&& !ctx
.found_key
) {
1409 logit("Host %s not found in %s", name
, identity_file
);
1412 } else if (inplace
) {
1413 /* Backup existing file */
1414 if (unlink(old
) == -1 && errno
!= ENOENT
)
1415 fatal("unlink %.100s: %s", old
, strerror(errno
));
1416 if (link(identity_file
, old
) == -1)
1417 fatal("link %.100s to %.100s: %s", identity_file
, old
,
1419 /* Move new one into place */
1420 if (rename(tmp
, identity_file
) == -1) {
1421 error("rename\"%s\" to \"%s\": %s", tmp
, identity_file
,
1428 printf("%s updated.\n", identity_file
);
1429 printf("Original contents retained as %s\n", old
);
1430 if (ctx
.has_unhashed
) {
1431 logit("WARNING: %s contains unhashed entries", old
);
1432 logit("Delete this file to ensure privacy "
1437 exit (find_host
&& !ctx
.found_key
);
1441 * Perform changing a passphrase. The argument is the passwd structure
1442 * for the current user.
1445 do_change_passphrase(struct passwd
*pw
)
1448 char *old_passphrase
, *passphrase1
, *passphrase2
;
1450 struct sshkey
*private;
1454 ask_filename(pw
, "Enter file in which the key is");
1455 if (stat(identity_file
, &st
) == -1)
1456 fatal("%s: %s", identity_file
, strerror(errno
));
1457 /* Try to load the file with empty passphrase. */
1458 r
= sshkey_load_private(identity_file
, "", &private, &comment
);
1459 if (r
== SSH_ERR_KEY_WRONG_PASSPHRASE
) {
1460 if (identity_passphrase
)
1461 old_passphrase
= xstrdup(identity_passphrase
);
1464 read_passphrase("Enter old passphrase: ",
1466 r
= sshkey_load_private(identity_file
, old_passphrase
,
1467 &private, &comment
);
1468 freezero(old_passphrase
, strlen(old_passphrase
));
1471 } else if (r
!= 0) {
1473 fatal_r(r
, "Failed to load key %s", identity_file
);
1476 mprintf("Key has comment '%s'\n", comment
);
1478 /* Ask the new passphrase (twice). */
1479 if (identity_new_passphrase
) {
1480 passphrase1
= xstrdup(identity_new_passphrase
);
1484 read_passphrase("Enter new passphrase (empty for no "
1485 "passphrase): ", RP_ALLOW_STDIN
);
1486 passphrase2
= read_passphrase("Enter same passphrase again: ",
1489 /* Verify that they are the same. */
1490 if (strcmp(passphrase1
, passphrase2
) != 0) {
1491 explicit_bzero(passphrase1
, strlen(passphrase1
));
1492 explicit_bzero(passphrase2
, strlen(passphrase2
));
1495 printf("Pass phrases do not match. Try again.\n");
1498 /* Destroy the other copy. */
1499 freezero(passphrase2
, strlen(passphrase2
));
1502 /* Save the file using the new passphrase. */
1503 if ((r
= sshkey_save_private(private, identity_file
, passphrase1
,
1504 comment
, private_key_format
, openssh_format_cipher
, rounds
)) != 0) {
1505 error_r(r
, "Saving key \"%s\" failed", identity_file
);
1506 freezero(passphrase1
, strlen(passphrase1
));
1507 sshkey_free(private);
1511 /* Destroy the passphrase and the copy of the key in memory. */
1512 freezero(passphrase1
, strlen(passphrase1
));
1513 sshkey_free(private); /* Destroys contents */
1516 printf("Your identification has been saved with the new passphrase.\n");
1521 * Print the SSHFP RR.
1524 do_print_resource_record(struct passwd
*pw
, char *fname
, char *hname
,
1525 int print_generic
, char * const *opts
, size_t nopts
)
1527 struct sshkey
*public;
1528 char *comment
= NULL
;
1533 for (i
= 0; i
< nopts
; i
++) {
1534 if (strncasecmp(opts
[i
], "hashalg=", 8) == 0) {
1535 if ((hash
= ssh_digest_alg_by_name(opts
[i
] + 8)) == -1)
1536 fatal("Unsupported hash algorithm");
1538 error("Invalid option \"%s\"", opts
[i
]);
1539 return SSH_ERR_INVALID_ARGUMENT
;
1543 fatal_f("no filename");
1544 if (stat(fname
, &st
) == -1) {
1545 if (errno
== ENOENT
)
1547 fatal("%s: %s", fname
, strerror(errno
));
1549 if ((r
= sshkey_load_public(fname
, &public, &comment
)) != 0)
1550 fatal_r(r
, "Failed to read v2 public key from \"%s\"", fname
);
1551 export_dns_rr(hname
, public, stdout
, print_generic
, hash
);
1552 sshkey_free(public);
1558 * Change the comment of a private key file.
1561 do_change_comment(struct passwd
*pw
, const char *identity_comment
)
1563 char new_comment
[1024], *comment
, *passphrase
;
1564 struct sshkey
*private;
1565 struct sshkey
*public;
1570 ask_filename(pw
, "Enter file in which the key is");
1571 if (stat(identity_file
, &st
) == -1)
1572 fatal("%s: %s", identity_file
, strerror(errno
));
1573 if ((r
= sshkey_load_private(identity_file
, "",
1574 &private, &comment
)) == 0)
1575 passphrase
= xstrdup("");
1576 else if (r
!= SSH_ERR_KEY_WRONG_PASSPHRASE
)
1577 fatal_r(r
, "Cannot load private key \"%s\"", identity_file
);
1579 if (identity_passphrase
)
1580 passphrase
= xstrdup(identity_passphrase
);
1581 else if (identity_new_passphrase
)
1582 passphrase
= xstrdup(identity_new_passphrase
);
1584 passphrase
= read_passphrase("Enter passphrase: ",
1586 /* Try to load using the passphrase. */
1587 if ((r
= sshkey_load_private(identity_file
, passphrase
,
1588 &private, &comment
)) != 0) {
1589 freezero(passphrase
, strlen(passphrase
));
1590 fatal_r(r
, "Cannot load private key \"%s\"",
1595 if (private->type
!= KEY_ED25519
&& private->type
!= KEY_XMSS
&&
1596 private_key_format
!= SSHKEY_PRIVATE_OPENSSH
) {
1597 error("Comments are only supported for keys stored in "
1598 "the new format (-o).");
1599 explicit_bzero(passphrase
, strlen(passphrase
));
1600 sshkey_free(private);
1604 printf("Old comment: %s\n", comment
);
1606 printf("No existing comment\n");
1608 if (identity_comment
) {
1609 strlcpy(new_comment
, identity_comment
, sizeof(new_comment
));
1611 printf("New comment: ");
1613 if (!fgets(new_comment
, sizeof(new_comment
), stdin
)) {
1614 explicit_bzero(passphrase
, strlen(passphrase
));
1615 sshkey_free(private);
1618 new_comment
[strcspn(new_comment
, "\n")] = '\0';
1620 if (comment
!= NULL
&& strcmp(comment
, new_comment
) == 0) {
1621 printf("No change to comment\n");
1623 sshkey_free(private);
1628 /* Save the file using the new passphrase. */
1629 if ((r
= sshkey_save_private(private, identity_file
, passphrase
,
1630 new_comment
, private_key_format
, openssh_format_cipher
,
1632 error_r(r
, "Saving key \"%s\" failed", identity_file
);
1633 freezero(passphrase
, strlen(passphrase
));
1634 sshkey_free(private);
1638 freezero(passphrase
, strlen(passphrase
));
1639 if ((r
= sshkey_from_private(private, &public)) != 0)
1640 fatal_fr(r
, "sshkey_from_private");
1641 sshkey_free(private);
1643 strlcat(identity_file
, ".pub", sizeof(identity_file
));
1644 if ((r
= sshkey_save_public(public, identity_file
, new_comment
)) != 0)
1645 fatal_r(r
, "Unable to save public key to %s", identity_file
);
1646 sshkey_free(public);
1649 if (strlen(new_comment
) > 0)
1650 printf("Comment '%s' applied\n", new_comment
);
1652 printf("Comment removed\n");
1658 cert_ext_add(const char *key
, const char *value
, int iscrit
)
1660 cert_ext
= xreallocarray(cert_ext
, ncert_ext
+ 1, sizeof(*cert_ext
));
1661 cert_ext
[ncert_ext
].key
= xstrdup(key
);
1662 cert_ext
[ncert_ext
].val
= value
== NULL
? NULL
: xstrdup(value
);
1663 cert_ext
[ncert_ext
].crit
= iscrit
;
1667 /* qsort(3) comparison function for certificate extensions */
1669 cert_ext_cmp(const void *_a
, const void *_b
)
1671 const struct cert_ext
*a
= (const struct cert_ext
*)_a
;
1672 const struct cert_ext
*b
= (const struct cert_ext
*)_b
;
1675 if (a
->crit
!= b
->crit
)
1676 return (a
->crit
< b
->crit
) ? -1 : 1;
1677 if ((r
= strcmp(a
->key
, b
->key
)) != 0)
1679 if ((a
->val
== NULL
) != (b
->val
== NULL
))
1680 return (a
->val
== NULL
) ? -1 : 1;
1681 if (a
->val
!= NULL
&& (r
= strcmp(a
->val
, b
->val
)) != 0)
1686 #define OPTIONS_CRITICAL 1
1687 #define OPTIONS_EXTENSIONS 2
1689 prepare_options_buf(struct sshbuf
*c
, int which
)
1694 const struct cert_ext
*ext
;
1696 if ((b
= sshbuf_new()) == NULL
)
1697 fatal_f("sshbuf_new failed");
1699 for (i
= 0; i
< ncert_ext
; i
++) {
1701 if ((ext
->crit
&& (which
& OPTIONS_EXTENSIONS
)) ||
1702 (!ext
->crit
&& (which
& OPTIONS_CRITICAL
)))
1704 if (ext
->val
== NULL
) {
1706 debug3_f("%s", ext
->key
);
1707 if ((r
= sshbuf_put_cstring(c
, ext
->key
)) != 0 ||
1708 (r
= sshbuf_put_string(c
, NULL
, 0)) != 0)
1709 fatal_fr(r
, "prepare flag");
1711 /* key/value option */
1712 debug3_f("%s=%s", ext
->key
, ext
->val
);
1714 if ((r
= sshbuf_put_cstring(c
, ext
->key
)) != 0 ||
1715 (r
= sshbuf_put_cstring(b
, ext
->val
)) != 0 ||
1716 (r
= sshbuf_put_stringb(c
, b
)) != 0)
1717 fatal_fr(r
, "prepare k/v");
1724 finalise_cert_exts(void)
1726 /* critical options */
1727 if (certflags_command
!= NULL
)
1728 cert_ext_add("force-command", certflags_command
, 1);
1729 if (certflags_src_addr
!= NULL
)
1730 cert_ext_add("source-address", certflags_src_addr
, 1);
1731 if ((certflags_flags
& CERTOPT_REQUIRE_VERIFY
) != 0)
1732 cert_ext_add("verify-required", NULL
, 1);
1734 if ((certflags_flags
& CERTOPT_X_FWD
) != 0)
1735 cert_ext_add("permit-X11-forwarding", NULL
, 0);
1736 if ((certflags_flags
& CERTOPT_AGENT_FWD
) != 0)
1737 cert_ext_add("permit-agent-forwarding", NULL
, 0);
1738 if ((certflags_flags
& CERTOPT_PORT_FWD
) != 0)
1739 cert_ext_add("permit-port-forwarding", NULL
, 0);
1740 if ((certflags_flags
& CERTOPT_PTY
) != 0)
1741 cert_ext_add("permit-pty", NULL
, 0);
1742 if ((certflags_flags
& CERTOPT_USER_RC
) != 0)
1743 cert_ext_add("permit-user-rc", NULL
, 0);
1744 if ((certflags_flags
& CERTOPT_NO_REQUIRE_USER_PRESENCE
) != 0)
1745 cert_ext_add("no-touch-required", NULL
, 0);
1746 /* order lexically by key */
1748 qsort(cert_ext
, ncert_ext
, sizeof(*cert_ext
), cert_ext_cmp
);
1751 static struct sshkey
*
1752 load_pkcs11_key(char *path
)
1754 #ifdef ENABLE_PKCS11
1755 struct sshkey
**keys
= NULL
, *public, *private = NULL
;
1758 if ((r
= sshkey_load_public(path
, &public, NULL
)) != 0)
1759 fatal_r(r
, "Couldn't load CA public key \"%s\"", path
);
1761 nkeys
= pkcs11_add_provider(pkcs11provider
, identity_passphrase
,
1763 debug3_f("%d keys", nkeys
);
1765 fatal("cannot read public key from pkcs11");
1766 for (i
= 0; i
< nkeys
; i
++) {
1767 if (sshkey_equal_public(public, keys
[i
])) {
1771 sshkey_free(keys
[i
]);
1774 sshkey_free(public);
1777 fatal("no pkcs11 support");
1778 #endif /* ENABLE_PKCS11 */
1781 /* Signer for sshkey_certify_custom that uses the agent */
1783 agent_signer(struct sshkey
*key
, u_char
**sigp
, size_t *lenp
,
1784 const u_char
*data
, size_t datalen
,
1785 const char *alg
, const char *provider
, const char *pin
,
1786 u_int compat
, void *ctx
)
1788 int *agent_fdp
= (int *)ctx
;
1790 return ssh_agent_sign(*agent_fdp
, key
, sigp
, lenp
,
1791 data
, datalen
, alg
, compat
);
1795 do_ca_sign(struct passwd
*pw
, const char *ca_key_path
, int prefer_agent
,
1796 unsigned long long cert_serial
, int cert_serial_autoinc
,
1797 int argc
, char **argv
)
1799 int r
, i
, found
, agent_fd
= -1;
1801 struct sshkey
*ca
, *public;
1802 char valid
[64], *otmp
, *tmp
, *cp
, *out
, *comment
;
1803 char *ca_fp
= NULL
, **plist
= NULL
, *pin
= NULL
;
1804 struct ssh_identitylist
*agent_ids
;
1806 struct notifier_ctx
*notifier
= NULL
;
1808 #ifdef ENABLE_PKCS11
1811 tmp
= tilde_expand_filename(ca_key_path
, pw
->pw_uid
);
1812 if (pkcs11provider
!= NULL
) {
1813 /* If a PKCS#11 token was specified then try to use it */
1814 if ((ca
= load_pkcs11_key(tmp
)) == NULL
)
1815 fatal("No PKCS#11 key matching %s found", ca_key_path
);
1816 } else if (prefer_agent
) {
1818 * Agent signature requested. Try to use agent after making
1819 * sure the public key specified is actually present in the
1822 if ((r
= sshkey_load_public(tmp
, &ca
, NULL
)) != 0)
1823 fatal_r(r
, "Cannot load CA public key %s", tmp
);
1824 if ((r
= ssh_get_authentication_socket(&agent_fd
)) != 0)
1825 fatal_r(r
, "Cannot use public key for CA signature");
1826 if ((r
= ssh_fetch_identitylist(agent_fd
, &agent_ids
)) != 0)
1827 fatal_r(r
, "Retrieve agent key list");
1829 for (j
= 0; j
< agent_ids
->nkeys
; j
++) {
1830 if (sshkey_equal(ca
, agent_ids
->keys
[j
])) {
1836 fatal("CA key %s not found in agent", tmp
);
1837 ssh_free_identitylist(agent_ids
);
1838 ca
->flags
|= SSHKEY_FLAG_EXT
;
1840 /* CA key is assumed to be a private key on the filesystem */
1841 ca
= load_identity(tmp
, NULL
);
1842 if (sshkey_is_sk(ca
) &&
1843 (ca
->sk_flags
& SSH_SK_USER_VERIFICATION_REQD
)) {
1844 if ((pin
= read_passphrase("Enter PIN for CA key: ",
1845 RP_ALLOW_STDIN
)) == NULL
)
1846 fatal_f("couldn't read PIN");
1851 if (key_type_name
!= NULL
) {
1852 if (sshkey_type_from_shortname(key_type_name
) != ca
->type
) {
1853 fatal("CA key type %s doesn't match specified %s",
1854 sshkey_ssh_name(ca
), key_type_name
);
1856 } else if (ca
->type
== KEY_RSA
) {
1857 /* Default to a good signature algorithm */
1858 key_type_name
= "rsa-sha2-512";
1860 ca_fp
= sshkey_fingerprint(ca
, fingerprint_hash
, SSH_FP_DEFAULT
);
1862 finalise_cert_exts();
1863 for (i
= 0; i
< argc
; i
++) {
1864 /* Split list of principals */
1866 if (cert_principals
!= NULL
) {
1867 otmp
= tmp
= xstrdup(cert_principals
);
1869 for (; (cp
= strsep(&tmp
, ",")) != NULL
; n
++) {
1870 plist
= xreallocarray(plist
, n
+ 1, sizeof(*plist
));
1871 if (*(plist
[n
] = xstrdup(cp
)) == '\0')
1872 fatal("Empty principal name");
1876 if (n
> SSHKEY_CERT_MAX_PRINCIPALS
)
1877 fatal("Too many certificate principals specified");
1879 tmp
= tilde_expand_filename(argv
[i
], pw
->pw_uid
);
1880 if ((r
= sshkey_load_public(tmp
, &public, &comment
)) != 0)
1881 fatal_r(r
, "load pubkey \"%s\"", tmp
);
1882 if (sshkey_is_cert(public))
1883 fatal_f("key \"%s\" type %s cannot be certified",
1884 tmp
, sshkey_type(public));
1886 /* Prepare certificate to sign */
1887 if ((r
= sshkey_to_certified(public)) != 0)
1888 fatal_r(r
, "Could not upgrade key %s to certificate", tmp
);
1889 public->cert
->type
= cert_key_type
;
1890 public->cert
->serial
= (u_int64_t
)cert_serial
;
1891 public->cert
->key_id
= xstrdup(cert_key_id
);
1892 public->cert
->nprincipals
= n
;
1893 public->cert
->principals
= plist
;
1894 public->cert
->valid_after
= cert_valid_from
;
1895 public->cert
->valid_before
= cert_valid_to
;
1896 prepare_options_buf(public->cert
->critical
, OPTIONS_CRITICAL
);
1897 prepare_options_buf(public->cert
->extensions
,
1898 OPTIONS_EXTENSIONS
);
1899 if ((r
= sshkey_from_private(ca
,
1900 &public->cert
->signature_key
)) != 0)
1901 fatal_r(r
, "sshkey_from_private (ca key)");
1903 if (agent_fd
!= -1 && (ca
->flags
& SSHKEY_FLAG_EXT
) != 0) {
1904 if ((r
= sshkey_certify_custom(public, ca
,
1905 key_type_name
, sk_provider
, NULL
, agent_signer
,
1907 fatal_r(r
, "Couldn't certify %s via agent", tmp
);
1909 if (sshkey_is_sk(ca
) &&
1910 (ca
->sk_flags
& SSH_SK_USER_PRESENCE_REQD
)) {
1911 notifier
= notify_start(0,
1912 "Confirm user presence for key %s %s",
1913 sshkey_type(ca
), ca_fp
);
1915 r
= sshkey_certify(public, ca
, key_type_name
,
1917 notify_complete(notifier
, "User presence confirmed");
1919 fatal_r(r
, "Couldn't certify key %s", tmp
);
1922 if ((cp
= strrchr(tmp
, '.')) != NULL
&& strcmp(cp
, ".pub") == 0)
1924 xasprintf(&out
, "%s-cert.pub", tmp
);
1927 if ((r
= sshkey_save_public(public, out
, comment
)) != 0) {
1928 fatal_r(r
, "Unable to save public key to %s",
1933 sshkey_format_cert_validity(public->cert
,
1934 valid
, sizeof(valid
));
1935 logit("Signed %s key %s: id \"%s\" serial %llu%s%s "
1936 "valid %s", sshkey_cert_type(public),
1937 out
, public->cert
->key_id
,
1938 (unsigned long long)public->cert
->serial
,
1939 cert_principals
!= NULL
? " for " : "",
1940 cert_principals
!= NULL
? cert_principals
: "",
1944 sshkey_free(public);
1946 if (cert_serial_autoinc
)
1950 freezero(pin
, strlen(pin
));
1952 #ifdef ENABLE_PKCS11
1959 parse_relative_time(const char *s
, time_t now
)
1963 mul
= *s
== '-' ? -1 : 1;
1965 if ((secs
= convtime(s
+ 1)) == -1)
1966 fatal("Invalid relative certificate time %s", s
);
1967 if (mul
== -1 && secs
> now
)
1968 fatal("Certificate time %s cannot be represented", s
);
1969 return now
+ (u_int64_t
)(secs
* mul
);
1973 parse_hex_u64(const char *s
, uint64_t *up
)
1976 unsigned long long ull
;
1979 ull
= strtoull(s
, &ep
, 16);
1980 if (*s
== '\0' || *ep
!= '\0')
1981 fatal("Invalid certificate time: not a number");
1982 if (errno
== ERANGE
&& ull
== ULONG_MAX
)
1983 fatal_fr(SSH_ERR_SYSTEM_ERROR
, "Invalid certificate time");
1984 *up
= (uint64_t)ull
;
1988 parse_cert_times(char *timespec
)
1991 time_t now
= time(NULL
);
1994 /* +timespec relative to now */
1995 if (*timespec
== '+' && strchr(timespec
, ':') == NULL
) {
1996 if ((secs
= convtime(timespec
+ 1)) == -1)
1997 fatal("Invalid relative certificate life %s", timespec
);
1998 cert_valid_to
= now
+ secs
;
2000 * Backdate certificate one minute to avoid problems on hosts
2001 * with poorly-synchronised clocks.
2003 cert_valid_from
= ((now
- 59)/ 60) * 60;
2009 * from := [+-]timespec | YYYYMMDD | YYYYMMDDHHMMSS | 0x... | "always"
2010 * to := [+-]timespec | YYYYMMDD | YYYYMMDDHHMMSS | 0x... | "forever"
2012 from
= xstrdup(timespec
);
2013 to
= strchr(from
, ':');
2014 if (to
== NULL
|| from
== to
|| *(to
+ 1) == '\0')
2015 fatal("Invalid certificate life specification %s", timespec
);
2018 if (*from
== '-' || *from
== '+')
2019 cert_valid_from
= parse_relative_time(from
, now
);
2020 else if (strcmp(from
, "always") == 0)
2021 cert_valid_from
= 0;
2022 else if (strncmp(from
, "0x", 2) == 0)
2023 parse_hex_u64(from
, &cert_valid_from
);
2024 else if (parse_absolute_time(from
, &cert_valid_from
) != 0)
2025 fatal("Invalid from time \"%s\"", from
);
2027 if (*to
== '-' || *to
== '+')
2028 cert_valid_to
= parse_relative_time(to
, now
);
2029 else if (strcmp(to
, "forever") == 0)
2030 cert_valid_to
= ~(u_int64_t
)0;
2031 else if (strncmp(to
, "0x", 2) == 0)
2032 parse_hex_u64(to
, &cert_valid_to
);
2033 else if (parse_absolute_time(to
, &cert_valid_to
) != 0)
2034 fatal("Invalid to time \"%s\"", to
);
2036 if (cert_valid_to
<= cert_valid_from
)
2037 fatal("Empty certificate validity interval");
2042 add_cert_option(char *opt
)
2047 if (strcasecmp(opt
, "clear") == 0)
2048 certflags_flags
= 0;
2049 else if (strcasecmp(opt
, "no-x11-forwarding") == 0)
2050 certflags_flags
&= ~CERTOPT_X_FWD
;
2051 else if (strcasecmp(opt
, "permit-x11-forwarding") == 0)
2052 certflags_flags
|= CERTOPT_X_FWD
;
2053 else if (strcasecmp(opt
, "no-agent-forwarding") == 0)
2054 certflags_flags
&= ~CERTOPT_AGENT_FWD
;
2055 else if (strcasecmp(opt
, "permit-agent-forwarding") == 0)
2056 certflags_flags
|= CERTOPT_AGENT_FWD
;
2057 else if (strcasecmp(opt
, "no-port-forwarding") == 0)
2058 certflags_flags
&= ~CERTOPT_PORT_FWD
;
2059 else if (strcasecmp(opt
, "permit-port-forwarding") == 0)
2060 certflags_flags
|= CERTOPT_PORT_FWD
;
2061 else if (strcasecmp(opt
, "no-pty") == 0)
2062 certflags_flags
&= ~CERTOPT_PTY
;
2063 else if (strcasecmp(opt
, "permit-pty") == 0)
2064 certflags_flags
|= CERTOPT_PTY
;
2065 else if (strcasecmp(opt
, "no-user-rc") == 0)
2066 certflags_flags
&= ~CERTOPT_USER_RC
;
2067 else if (strcasecmp(opt
, "permit-user-rc") == 0)
2068 certflags_flags
|= CERTOPT_USER_RC
;
2069 else if (strcasecmp(opt
, "touch-required") == 0)
2070 certflags_flags
&= ~CERTOPT_NO_REQUIRE_USER_PRESENCE
;
2071 else if (strcasecmp(opt
, "no-touch-required") == 0)
2072 certflags_flags
|= CERTOPT_NO_REQUIRE_USER_PRESENCE
;
2073 else if (strcasecmp(opt
, "no-verify-required") == 0)
2074 certflags_flags
&= ~CERTOPT_REQUIRE_VERIFY
;
2075 else if (strcasecmp(opt
, "verify-required") == 0)
2076 certflags_flags
|= CERTOPT_REQUIRE_VERIFY
;
2077 else if (strncasecmp(opt
, "force-command=", 14) == 0) {
2080 fatal("Empty force-command option");
2081 if (certflags_command
!= NULL
)
2082 fatal("force-command already specified");
2083 certflags_command
= xstrdup(val
);
2084 } else if (strncasecmp(opt
, "source-address=", 15) == 0) {
2087 fatal("Empty source-address option");
2088 if (certflags_src_addr
!= NULL
)
2089 fatal("source-address already specified");
2090 if (addr_match_cidr_list(NULL
, val
) != 0)
2091 fatal("Invalid source-address list");
2092 certflags_src_addr
= xstrdup(val
);
2093 } else if (strncasecmp(opt
, "extension:", 10) == 0 ||
2094 (iscrit
= (strncasecmp(opt
, "critical:", 9) == 0))) {
2095 val
= xstrdup(strchr(opt
, ':') + 1);
2096 if ((cp
= strchr(val
, '=')) != NULL
)
2098 cert_ext_add(val
, cp
, iscrit
);
2101 fatal("Unsupported certificate option \"%s\"", opt
);
2105 show_options(struct sshbuf
*optbuf
, int in_critical
)
2107 char *name
, *arg
, *hex
;
2108 struct sshbuf
*options
, *option
= NULL
;
2111 if ((options
= sshbuf_fromb(optbuf
)) == NULL
)
2112 fatal_f("sshbuf_fromb failed");
2113 while (sshbuf_len(options
) != 0) {
2114 sshbuf_free(option
);
2116 if ((r
= sshbuf_get_cstring(options
, &name
, NULL
)) != 0 ||
2117 (r
= sshbuf_froms(options
, &option
)) != 0)
2118 fatal_fr(r
, "parse option");
2119 printf(" %s", name
);
2121 (strcmp(name
, "permit-X11-forwarding") == 0 ||
2122 strcmp(name
, "permit-agent-forwarding") == 0 ||
2123 strcmp(name
, "permit-port-forwarding") == 0 ||
2124 strcmp(name
, "permit-pty") == 0 ||
2125 strcmp(name
, "permit-user-rc") == 0 ||
2126 strcmp(name
, "no-touch-required") == 0)) {
2128 } else if (in_critical
&&
2129 (strcmp(name
, "force-command") == 0 ||
2130 strcmp(name
, "source-address") == 0)) {
2131 if ((r
= sshbuf_get_cstring(option
, &arg
, NULL
)) != 0)
2132 fatal_fr(r
, "parse critical");
2133 printf(" %s\n", arg
);
2135 } else if (in_critical
&&
2136 strcmp(name
, "verify-required") == 0) {
2138 } else if (sshbuf_len(option
) > 0) {
2139 hex
= sshbuf_dtob16(option
);
2140 printf(" UNKNOWN OPTION: %s (len %zu)\n",
2141 hex
, sshbuf_len(option
));
2142 sshbuf_reset(option
);
2145 printf(" UNKNOWN FLAG OPTION\n");
2147 if (sshbuf_len(option
) != 0)
2148 fatal("Option corrupt: extra data at end");
2150 sshbuf_free(option
);
2151 sshbuf_free(options
);
2155 print_cert(struct sshkey
*key
)
2157 char valid
[64], *key_fp
, *ca_fp
;
2160 key_fp
= sshkey_fingerprint(key
, fingerprint_hash
, SSH_FP_DEFAULT
);
2161 ca_fp
= sshkey_fingerprint(key
->cert
->signature_key
,
2162 fingerprint_hash
, SSH_FP_DEFAULT
);
2163 if (key_fp
== NULL
|| ca_fp
== NULL
)
2164 fatal_f("sshkey_fingerprint fail");
2165 sshkey_format_cert_validity(key
->cert
, valid
, sizeof(valid
));
2167 printf(" Type: %s %s certificate\n", sshkey_ssh_name(key
),
2168 sshkey_cert_type(key
));
2169 printf(" Public key: %s %s\n", sshkey_type(key
), key_fp
);
2170 printf(" Signing CA: %s %s (using %s)\n",
2171 sshkey_type(key
->cert
->signature_key
), ca_fp
,
2172 key
->cert
->signature_type
);
2173 printf(" Key ID: \"%s\"\n", key
->cert
->key_id
);
2174 printf(" Serial: %llu\n", (unsigned long long)key
->cert
->serial
);
2175 printf(" Valid: %s\n", valid
);
2176 printf(" Principals: ");
2177 if (key
->cert
->nprincipals
== 0)
2180 for (i
= 0; i
< key
->cert
->nprincipals
; i
++)
2182 key
->cert
->principals
[i
]);
2185 printf(" Critical Options: ");
2186 if (sshbuf_len(key
->cert
->critical
) == 0)
2190 show_options(key
->cert
->critical
, 1);
2192 printf(" Extensions: ");
2193 if (sshbuf_len(key
->cert
->extensions
) == 0)
2197 show_options(key
->cert
->extensions
, 0);
2202 do_show_cert(struct passwd
*pw
)
2204 struct sshkey
*key
= NULL
;
2206 int r
, is_stdin
= 0, ok
= 0;
2208 char *cp
, *line
= NULL
;
2210 size_t linesize
= 0;
2214 ask_filename(pw
, "Enter file in which the key is");
2215 if (strcmp(identity_file
, "-") != 0 && stat(identity_file
, &st
) == -1)
2216 fatal("%s: %s: %s", __progname
, identity_file
, strerror(errno
));
2218 path
= identity_file
;
2219 if (strcmp(path
, "-") == 0) {
2223 } else if ((f
= fopen(identity_file
, "r")) == NULL
)
2224 fatal("fopen %s: %s", identity_file
, strerror(errno
));
2226 while (getline(&line
, &linesize
, f
) != -1) {
2230 /* Trim leading space and comments */
2231 cp
= line
+ strspn(line
, " \t");
2232 if (*cp
== '#' || *cp
== '\0')
2234 if ((key
= sshkey_new(KEY_UNSPEC
)) == NULL
)
2235 fatal("sshkey_new");
2236 if ((r
= sshkey_read(key
, &cp
)) != 0) {
2237 error_r(r
, "%s:%lu: invalid key", path
, lnum
);
2240 if (!sshkey_is_cert(key
)) {
2241 error("%s:%lu is not a certificate", path
, lnum
);
2245 if (!is_stdin
&& lnum
== 1)
2246 printf("%s:\n", path
);
2248 printf("%s:%lu:\n", path
, lnum
);
2258 load_krl(const char *path
, struct ssh_krl
**krlp
)
2260 struct sshbuf
*krlbuf
;
2263 if ((r
= sshbuf_load_file(path
, &krlbuf
)) != 0)
2264 fatal_r(r
, "Unable to load KRL %s", path
);
2265 /* XXX check sigs */
2266 if ((r
= ssh_krl_from_blob(krlbuf
, krlp
)) != 0 ||
2268 fatal_r(r
, "Invalid KRL file %s", path
);
2269 sshbuf_free(krlbuf
);
2273 hash_to_blob(const char *cp
, u_char
**blobp
, size_t *lenp
,
2274 const char *file
, u_long lnum
)
2281 if (strncmp(cp
, "SHA256:", 7) != 0)
2282 fatal("%s:%lu: unsupported hash algorithm", file
, lnum
);
2286 * OpenSSH base64 hashes omit trailing '='
2287 * characters; put them back for decode.
2289 if ((tlen
= strlen(cp
)) >= SIZE_MAX
- 5)
2290 fatal_f("hash too long: %zu bytes", tlen
);
2291 tmp
= xmalloc(tlen
+ 4 + 1);
2292 strlcpy(tmp
, cp
, tlen
+ 1);
2293 while ((tlen
% 4) != 0) {
2297 if ((b
= sshbuf_new()) == NULL
)
2298 fatal_f("sshbuf_new failed");
2299 if ((r
= sshbuf_b64tod(b
, tmp
)) != 0)
2300 fatal_r(r
, "%s:%lu: decode hash failed", file
, lnum
);
2302 *lenp
= sshbuf_len(b
);
2303 *blobp
= xmalloc(*lenp
);
2304 memcpy(*blobp
, sshbuf_ptr(b
), *lenp
);
2309 update_krl_from_file(struct passwd
*pw
, const char *file
, int wild_ca
,
2310 const struct sshkey
*ca
, struct ssh_krl
*krl
)
2312 struct sshkey
*key
= NULL
;
2314 char *path
, *cp
, *ep
, *line
= NULL
;
2315 u_char
*blob
= NULL
;
2316 size_t blen
= 0, linesize
= 0;
2317 unsigned long long serial
, serial2
;
2318 int i
, was_explicit_key
, was_sha1
, was_sha256
, was_hash
, r
;
2321 path
= tilde_expand_filename(file
, pw
->pw_uid
);
2322 if (strcmp(path
, "-") == 0) {
2325 path
= xstrdup("(standard input)");
2326 } else if ((krl_spec
= fopen(path
, "r")) == NULL
)
2327 fatal("fopen %s: %s", path
, strerror(errno
));
2330 printf("Revoking from %s\n", path
);
2331 while (getline(&line
, &linesize
, krl_spec
) != -1) {
2332 if (linesize
>= INT_MAX
) {
2333 fatal_f("%s contains unparsable line, len=%zu",
2337 was_explicit_key
= was_sha1
= was_sha256
= was_hash
= 0;
2338 cp
= line
+ strspn(line
, " \t");
2339 /* Trim trailing space, comments and strip \n */
2340 for (i
= 0, r
= -1; cp
[i
] != '\0'; i
++) {
2341 if (cp
[i
] == '#' || cp
[i
] == '\n') {
2345 if (cp
[i
] == ' ' || cp
[i
] == '\t') {
2346 /* Remember the start of a span of whitespace */
2356 if (strncasecmp(cp
, "serial:", 7) == 0) {
2357 if (ca
== NULL
&& !wild_ca
) {
2358 fatal("revoking certificates by serial number "
2359 "requires specification of a CA key");
2362 cp
= cp
+ strspn(cp
, " \t");
2364 serial
= strtoull(cp
, &ep
, 0);
2365 if (*cp
== '\0' || (*ep
!= '\0' && *ep
!= '-'))
2366 fatal("%s:%lu: invalid serial \"%s\"",
2368 if (errno
== ERANGE
&& serial
== ULLONG_MAX
)
2369 fatal("%s:%lu: serial out of range",
2375 serial2
= strtoull(cp
, &ep
, 0);
2376 if (*cp
== '\0' || *ep
!= '\0')
2377 fatal("%s:%lu: invalid serial \"%s\"",
2379 if (errno
== ERANGE
&& serial2
== ULLONG_MAX
)
2380 fatal("%s:%lu: serial out of range",
2382 if (serial2
<= serial
)
2383 fatal("%s:%lu: invalid serial range "
2384 "%llu:%llu", path
, lnum
,
2385 (unsigned long long)serial
,
2386 (unsigned long long)serial2
);
2388 if (ssh_krl_revoke_cert_by_serial_range(krl
,
2389 ca
, serial
, serial2
) != 0) {
2390 fatal_f("revoke serial failed");
2392 } else if (strncasecmp(cp
, "id:", 3) == 0) {
2393 if (ca
== NULL
&& !wild_ca
) {
2394 fatal("revoking certificates by key ID "
2395 "requires specification of a CA key");
2398 cp
= cp
+ strspn(cp
, " \t");
2399 if (ssh_krl_revoke_cert_by_key_id(krl
, ca
, cp
) != 0)
2400 fatal_f("revoke key ID failed");
2401 } else if (strncasecmp(cp
, "hash:", 5) == 0) {
2403 cp
= cp
+ strspn(cp
, " \t");
2404 hash_to_blob(cp
, &blob
, &blen
, file
, lnum
);
2405 r
= ssh_krl_revoke_key_sha256(krl
, blob
, blen
);
2407 fatal_fr(r
, "revoke key failed");
2409 if (strncasecmp(cp
, "key:", 4) == 0) {
2411 cp
= cp
+ strspn(cp
, " \t");
2412 was_explicit_key
= 1;
2413 } else if (strncasecmp(cp
, "sha1:", 5) == 0) {
2415 cp
= cp
+ strspn(cp
, " \t");
2417 } else if (strncasecmp(cp
, "sha256:", 7) == 0) {
2419 cp
= cp
+ strspn(cp
, " \t");
2422 * Just try to process the line as a key.
2423 * Parsing will fail if it isn't.
2426 if ((key
= sshkey_new(KEY_UNSPEC
)) == NULL
)
2427 fatal("sshkey_new");
2428 if ((r
= sshkey_read(key
, &cp
)) != 0)
2429 fatal_r(r
, "%s:%lu: invalid key", path
, lnum
);
2430 if (was_explicit_key
)
2431 r
= ssh_krl_revoke_key_explicit(krl
, key
);
2432 else if (was_sha1
) {
2433 if (sshkey_fingerprint_raw(key
,
2434 SSH_DIGEST_SHA1
, &blob
, &blen
) != 0) {
2435 fatal("%s:%lu: fingerprint failed",
2438 r
= ssh_krl_revoke_key_sha1(krl
, blob
, blen
);
2439 } else if (was_sha256
) {
2440 if (sshkey_fingerprint_raw(key
,
2441 SSH_DIGEST_SHA256
, &blob
, &blen
) != 0) {
2442 fatal("%s:%lu: fingerprint failed",
2445 r
= ssh_krl_revoke_key_sha256(krl
, blob
, blen
);
2447 r
= ssh_krl_revoke_key(krl
, key
);
2449 fatal_fr(r
, "revoke key failed");
2450 freezero(blob
, blen
);
2456 if (strcmp(path
, "-") != 0)
2463 do_gen_krl(struct passwd
*pw
, int updating
, const char *ca_key_path
,
2464 unsigned long long krl_version
, const char *krl_comment
,
2465 int argc
, char **argv
)
2467 struct ssh_krl
*krl
;
2469 struct sshkey
*ca
= NULL
;
2470 int i
, r
, wild_ca
= 0;
2472 struct sshbuf
*kbuf
;
2474 if (*identity_file
== '\0')
2475 fatal("KRL generation requires an output file");
2476 if (stat(identity_file
, &sb
) == -1) {
2477 if (errno
!= ENOENT
)
2478 fatal("Cannot access KRL \"%s\": %s",
2479 identity_file
, strerror(errno
));
2481 fatal("KRL \"%s\" does not exist", identity_file
);
2483 if (ca_key_path
!= NULL
) {
2484 if (strcasecmp(ca_key_path
, "none") == 0)
2487 tmp
= tilde_expand_filename(ca_key_path
, pw
->pw_uid
);
2488 if ((r
= sshkey_load_public(tmp
, &ca
, NULL
)) != 0)
2489 fatal_r(r
, "Cannot load CA public key %s", tmp
);
2495 load_krl(identity_file
, &krl
);
2496 else if ((krl
= ssh_krl_init()) == NULL
)
2497 fatal("couldn't create KRL");
2499 if (krl_version
!= 0)
2500 ssh_krl_set_version(krl
, krl_version
);
2501 if (krl_comment
!= NULL
)
2502 ssh_krl_set_comment(krl
, krl_comment
);
2504 for (i
= 0; i
< argc
; i
++)
2505 update_krl_from_file(pw
, argv
[i
], wild_ca
, ca
, krl
);
2507 if ((kbuf
= sshbuf_new()) == NULL
)
2508 fatal("sshbuf_new failed");
2509 if (ssh_krl_to_blob(krl
, kbuf
) != 0)
2510 fatal("Couldn't generate KRL");
2511 if ((r
= sshbuf_write_file(identity_file
, kbuf
)) != 0)
2512 fatal("write %s: %s", identity_file
, strerror(errno
));
2519 do_check_krl(struct passwd
*pw
, int print_krl
, int argc
, char **argv
)
2523 struct ssh_krl
*krl
;
2526 if (*identity_file
== '\0')
2527 fatal("KRL checking requires an input file");
2528 load_krl(identity_file
, &krl
);
2530 krl_dump(krl
, stdout
);
2531 for (i
= 0; i
< argc
; i
++) {
2532 if ((r
= sshkey_load_public(argv
[i
], &k
, &comment
)) != 0)
2533 fatal_r(r
, "Cannot load public key %s", argv
[i
]);
2534 r
= ssh_krl_check_key(krl
, k
);
2535 printf("%s%s%s%s: %s\n", argv
[i
],
2536 *comment
? " (" : "", comment
, *comment
? ")" : "",
2537 r
== 0 ? "ok" : "REVOKED");
2547 static struct sshkey
*
2548 load_sign_key(const char *keypath
, const struct sshkey
*pubkey
)
2550 size_t i
, slen
, plen
= strlen(keypath
);
2551 char *privpath
= xstrdup(keypath
);
2552 static const char * const suffixes
[] = { "-cert.pub", ".pub", NULL
};
2553 struct sshkey
*ret
= NULL
, *privkey
= NULL
;
2558 * If passed a public key filename, then try to locate the corresponding
2559 * private key. This lets us specify certificates on the command-line
2560 * and have ssh-keygen find the appropriate private key.
2562 for (i
= 0; suffixes
[i
]; i
++) {
2563 slen
= strlen(suffixes
[i
]);
2565 strcmp(privpath
+ plen
- slen
, suffixes
[i
]) != 0)
2567 privpath
[plen
- slen
] = '\0';
2568 debug_f("%s looks like a public key, using private key "
2569 "path %s instead", keypath
, privpath
);
2572 if (waspub
&& stat(privpath
, &st
) != 0 && errno
== ENOENT
)
2573 fatal("No private key found for public key \"%s\"", keypath
);
2574 if ((r
= sshkey_load_private(privpath
, "", &privkey
, NULL
)) != 0 &&
2575 (r
!= SSH_ERR_KEY_WRONG_PASSPHRASE
)) {
2576 debug_fr(r
, "load private key \"%s\"", privpath
);
2577 fatal("No private key found for \"%s\"", privpath
);
2578 } else if (privkey
== NULL
)
2579 privkey
= load_identity(privpath
, NULL
);
2581 if (!sshkey_equal_public(pubkey
, privkey
)) {
2582 error("Public key %s doesn't match private %s",
2586 if (sshkey_is_cert(pubkey
) && !sshkey_is_cert(privkey
)) {
2588 * Graft the certificate onto the private key to make
2589 * it capable of signing.
2591 if ((r
= sshkey_to_certified(privkey
)) != 0) {
2592 error_fr(r
, "sshkey_to_certified");
2595 if ((r
= sshkey_cert_copy(pubkey
, privkey
)) != 0) {
2596 error_fr(r
, "sshkey_cert_copy");
2604 sshkey_free(privkey
);
2610 sign_one(struct sshkey
*signkey
, const char *filename
, int fd
,
2611 const char *sig_namespace
, const char *hashalg
, sshsig_signer
*signer
,
2614 struct sshbuf
*sigbuf
= NULL
, *abuf
= NULL
;
2615 int r
= SSH_ERR_INTERNAL_ERROR
, wfd
= -1, oerrno
;
2616 char *wfile
= NULL
, *asig
= NULL
, *fp
= NULL
;
2617 char *pin
= NULL
, *prompt
= NULL
;
2620 if (fd
== STDIN_FILENO
)
2621 fprintf(stderr
, "Signing data on standard input\n");
2623 fprintf(stderr
, "Signing file %s\n", filename
);
2625 if (signer
== NULL
&& sshkey_is_sk(signkey
)) {
2626 if ((signkey
->sk_flags
& SSH_SK_USER_VERIFICATION_REQD
)) {
2627 xasprintf(&prompt
, "Enter PIN for %s key: ",
2628 sshkey_type(signkey
));
2629 if ((pin
= read_passphrase(prompt
,
2630 RP_ALLOW_STDIN
)) == NULL
)
2631 fatal_f("couldn't read PIN");
2633 if ((signkey
->sk_flags
& SSH_SK_USER_PRESENCE_REQD
)) {
2634 if ((fp
= sshkey_fingerprint(signkey
, fingerprint_hash
,
2635 SSH_FP_DEFAULT
)) == NULL
)
2636 fatal_f("fingerprint failed");
2637 fprintf(stderr
, "Confirm user presence for key %s %s\n",
2638 sshkey_type(signkey
), fp
);
2642 if ((r
= sshsig_sign_fd(signkey
, hashalg
, sk_provider
, pin
,
2643 fd
, sig_namespace
, &sigbuf
, signer
, signer_ctx
)) != 0) {
2644 error_r(r
, "Signing %s failed", filename
);
2647 if ((r
= sshsig_armor(sigbuf
, &abuf
)) != 0) {
2648 error_fr(r
, "sshsig_armor");
2651 if ((asig
= sshbuf_dup_string(abuf
)) == NULL
) {
2652 error_f("buffer error");
2653 r
= SSH_ERR_ALLOC_FAIL
;
2657 if (fd
== STDIN_FILENO
) {
2658 fputs(asig
, stdout
);
2661 xasprintf(&wfile
, "%s.sig", filename
);
2662 if (confirm_overwrite(wfile
)) {
2663 if ((wfd
= open(wfile
, O_WRONLY
|O_CREAT
|O_TRUNC
,
2666 error("Cannot open %s: %s",
2667 wfile
, strerror(errno
));
2669 r
= SSH_ERR_SYSTEM_ERROR
;
2672 if (atomicio(vwrite
, wfd
, asig
,
2673 strlen(asig
)) != strlen(asig
)) {
2675 error("Cannot write to %s: %s",
2676 wfile
, strerror(errno
));
2678 r
= SSH_ERR_SYSTEM_ERROR
;
2682 fprintf(stderr
, "Write signature to %s\n",
2694 freezero(pin
, strlen(pin
));
2696 sshbuf_free(sigbuf
);
2703 sig_process_opts(char * const *opts
, size_t nopts
, char **hashalgp
,
2704 uint64_t *verify_timep
, int *print_pubkey
)
2709 if (verify_timep
!= NULL
)
2711 if (print_pubkey
!= NULL
)
2713 if (hashalgp
!= NULL
)
2715 for (i
= 0; i
< nopts
; i
++) {
2716 if (hashalgp
!= NULL
&&
2717 strncasecmp(opts
[i
], "hashalg=", 8) == 0) {
2718 *hashalgp
= xstrdup(opts
[i
] + 8);
2719 } else if (verify_timep
&&
2720 strncasecmp(opts
[i
], "verify-time=", 12) == 0) {
2721 if (parse_absolute_time(opts
[i
] + 12,
2722 verify_timep
) != 0 || *verify_timep
== 0) {
2723 error("Invalid \"verify-time\" option");
2724 return SSH_ERR_INVALID_ARGUMENT
;
2726 } else if (print_pubkey
&&
2727 strcasecmp(opts
[i
], "print-pubkey") == 0) {
2730 error("Invalid option \"%s\"", opts
[i
]);
2731 return SSH_ERR_INVALID_ARGUMENT
;
2734 if (verify_timep
&& *verify_timep
== 0) {
2735 if ((now
= time(NULL
)) < 0) {
2736 error("Time is before epoch");
2737 return SSH_ERR_INVALID_ARGUMENT
;
2739 *verify_timep
= (uint64_t)now
;
2746 sig_sign(const char *keypath
, const char *sig_namespace
, int require_agent
,
2747 int argc
, char **argv
, char * const *opts
, size_t nopts
)
2749 int i
, fd
= -1, r
, ret
= -1;
2751 struct sshkey
*pubkey
= NULL
, *privkey
= NULL
, *signkey
= NULL
;
2752 sshsig_signer
*signer
= NULL
;
2753 char *hashalg
= NULL
;
2755 /* Check file arguments. */
2756 for (i
= 0; i
< argc
; i
++) {
2757 if (strcmp(argv
[i
], "-") != 0)
2759 if (i
> 0 || argc
> 1)
2760 fatal("Cannot sign mix of paths and standard input");
2763 if (sig_process_opts(opts
, nopts
, &hashalg
, NULL
, NULL
) != 0)
2764 goto done
; /* error already logged */
2766 if ((r
= sshkey_load_public(keypath
, &pubkey
, NULL
)) != 0) {
2767 error_r(r
, "Couldn't load public key %s", keypath
);
2771 if ((r
= ssh_get_authentication_socket(&agent_fd
)) != 0) {
2773 fatal("Couldn't get agent socket");
2774 debug_r(r
, "Couldn't get agent socket");
2776 if ((r
= ssh_agent_has_key(agent_fd
, pubkey
)) == 0)
2777 signer
= agent_signer
;
2780 fatal("Couldn't find key in agent");
2781 debug_r(r
, "Couldn't find key in agent");
2785 if (signer
== NULL
) {
2786 /* Not using agent - try to load private key */
2787 if ((privkey
= load_sign_key(keypath
, pubkey
)) == NULL
)
2791 /* Will use key in agent */
2796 if ((r
= sign_one(signkey
, "(stdin)", STDIN_FILENO
,
2797 sig_namespace
, hashalg
, signer
, &agent_fd
)) != 0)
2800 for (i
= 0; i
< argc
; i
++) {
2801 if (strcmp(argv
[i
], "-") == 0)
2803 else if ((fd
= open(argv
[i
], O_RDONLY
)) == -1) {
2804 error("Cannot open %s for signing: %s",
2805 argv
[i
], strerror(errno
));
2808 if ((r
= sign_one(signkey
, argv
[i
], fd
, sig_namespace
,
2809 hashalg
, signer
, &agent_fd
)) != 0)
2811 if (fd
!= STDIN_FILENO
)
2819 if (fd
!= -1 && fd
!= STDIN_FILENO
)
2821 sshkey_free(pubkey
);
2822 sshkey_free(privkey
);
2828 sig_verify(const char *signature
, const char *sig_namespace
,
2829 const char *principal
, const char *allowed_keys
, const char *revoked_keys
,
2830 char * const *opts
, size_t nopts
)
2833 int print_pubkey
= 0;
2834 struct sshbuf
*sigbuf
= NULL
, *abuf
= NULL
;
2835 struct sshkey
*sign_key
= NULL
;
2837 struct sshkey_sig_details
*sig_details
= NULL
;
2838 uint64_t verify_time
= 0;
2840 if (sig_process_opts(opts
, nopts
, NULL
, &verify_time
,
2841 &print_pubkey
) != 0)
2842 goto done
; /* error already logged */
2844 memset(&sig_details
, 0, sizeof(sig_details
));
2845 if ((r
= sshbuf_load_file(signature
, &abuf
)) != 0) {
2846 error_r(r
, "Couldn't read signature file");
2850 if ((r
= sshsig_dearmor(abuf
, &sigbuf
)) != 0) {
2851 error_fr(r
, "sshsig_armor");
2854 if ((r
= sshsig_verify_fd(sigbuf
, STDIN_FILENO
, sig_namespace
,
2855 &sign_key
, &sig_details
)) != 0)
2856 goto done
; /* sshsig_verify() prints error */
2858 if ((fp
= sshkey_fingerprint(sign_key
, fingerprint_hash
,
2859 SSH_FP_DEFAULT
)) == NULL
)
2860 fatal_f("sshkey_fingerprint failed");
2861 debug("Valid (unverified) signature from key %s", fp
);
2862 if (sig_details
!= NULL
) {
2863 debug2_f("signature details: counter = %u, flags = 0x%02x",
2864 sig_details
->sk_counter
, sig_details
->sk_flags
);
2869 if (revoked_keys
!= NULL
) {
2870 if ((r
= sshkey_check_revoked(sign_key
, revoked_keys
)) != 0) {
2871 debug3_fr(r
, "sshkey_check_revoked");
2876 if (allowed_keys
!= NULL
&& (r
= sshsig_check_allowed_keys(allowed_keys
,
2877 sign_key
, principal
, sig_namespace
, verify_time
)) != 0) {
2878 debug3_fr(r
, "sshsig_check_allowed_keys");
2886 if ((fp
= sshkey_fingerprint(sign_key
, fingerprint_hash
,
2887 SSH_FP_DEFAULT
)) == NULL
)
2888 fatal_f("sshkey_fingerprint failed");
2889 if (principal
== NULL
) {
2890 printf("Good \"%s\" signature with %s key %s\n",
2891 sig_namespace
, sshkey_type(sign_key
), fp
);
2894 printf("Good \"%s\" signature for %s with %s key %s\n",
2895 sig_namespace
, principal
,
2896 sshkey_type(sign_key
), fp
);
2899 printf("Could not verify signature.\n");
2902 /* Print the signature key if requested */
2903 if (ret
== 0 && print_pubkey
&& sign_key
!= NULL
) {
2904 if ((r
= sshkey_write(sign_key
, stdout
)) == 0)
2905 fputc('\n', stdout
);
2907 error_r(r
, "Could not print public key.\n");
2911 sshbuf_free(sigbuf
);
2913 sshkey_free(sign_key
);
2914 sshkey_sig_details_free(sig_details
);
2920 sig_find_principals(const char *signature
, const char *allowed_keys
,
2921 char * const *opts
, size_t nopts
)
2924 struct sshbuf
*sigbuf
= NULL
, *abuf
= NULL
;
2925 struct sshkey
*sign_key
= NULL
;
2926 char *principals
= NULL
, *cp
, *tmp
;
2927 uint64_t verify_time
= 0;
2929 if (sig_process_opts(opts
, nopts
, NULL
, &verify_time
, NULL
) != 0)
2930 goto done
; /* error already logged */
2932 if ((r
= sshbuf_load_file(signature
, &abuf
)) != 0) {
2933 error_r(r
, "Couldn't read signature file");
2936 if ((r
= sshsig_dearmor(abuf
, &sigbuf
)) != 0) {
2937 error_fr(r
, "sshsig_armor");
2940 if ((r
= sshsig_get_pubkey(sigbuf
, &sign_key
)) != 0) {
2941 error_fr(r
, "sshsig_get_pubkey");
2944 if ((r
= sshsig_find_principals(allowed_keys
, sign_key
,
2945 verify_time
, &principals
)) != 0) {
2946 if (r
!= SSH_ERR_KEY_NOT_FOUND
)
2947 error_fr(r
, "sshsig_find_principal");
2953 /* Emit matching principals one per line */
2955 while ((cp
= strsep(&tmp
, ",")) != NULL
&& *cp
!= '\0')
2958 fprintf(stderr
, "No principal matched.\n");
2960 sshbuf_free(sigbuf
);
2962 sshkey_free(sign_key
);
2968 sig_match_principals(const char *allowed_keys
, char *principal
,
2969 char * const *opts
, size_t nopts
)
2972 char **principals
= NULL
;
2973 size_t i
, nprincipals
= 0;
2975 if ((r
= sig_process_opts(opts
, nopts
, NULL
, NULL
, NULL
)) != 0)
2976 return r
; /* error already logged */
2978 if ((r
= sshsig_match_principals(allowed_keys
, principal
,
2979 &principals
, &nprincipals
)) != 0) {
2980 debug_f("match: %s", ssh_err(r
));
2981 fprintf(stderr
, "No principal matched.\n");
2984 for (i
= 0; i
< nprincipals
; i
++) {
2985 printf("%s\n", principals
[i
]);
2986 free(principals
[i
]);
2994 do_moduli_gen(const char *out_file
, char **opts
, size_t nopts
)
2997 /* Moduli generation/screening */
2998 u_int32_t memory
= 0;
2999 BIGNUM
*start
= NULL
;
3000 int moduli_bits
= 0;
3006 for (i
= 0; i
< nopts
; i
++) {
3007 if (strncmp(opts
[i
], "memory=", 7) == 0) {
3008 memory
= (u_int32_t
)strtonum(opts
[i
]+7, 1,
3011 fatal("Memory limit is %s: %s",
3014 } else if (strncmp(opts
[i
], "start=", 6) == 0) {
3015 /* XXX - also compare length against bits */
3016 if (BN_hex2bn(&start
, opts
[i
]+6) == 0)
3017 fatal("Invalid start point.");
3018 } else if (strncmp(opts
[i
], "bits=", 5) == 0) {
3019 moduli_bits
= (int)strtonum(opts
[i
]+5, 1,
3022 fatal("Invalid number: %s (%s)",
3023 opts
[i
]+12, errstr
);
3026 fatal("Option \"%s\" is unsupported for moduli "
3027 "generation", opts
[i
]);
3031 if (strcmp(out_file
, "-") == 0)
3033 else if ((out
= fopen(out_file
, "w")) == NULL
) {
3034 fatal("Couldn't open modulus candidate file \"%s\": %s",
3035 out_file
, strerror(errno
));
3037 setvbuf(out
, NULL
, _IOLBF
, 0);
3039 if (moduli_bits
== 0)
3040 moduli_bits
= DEFAULT_BITS
;
3041 if (gen_candidates(out
, memory
, moduli_bits
, start
) != 0)
3042 fatal("modulus candidate generation failed");
3043 #else /* WITH_OPENSSL */
3044 fatal("Moduli generation is not supported");
3045 #endif /* WITH_OPENSSL */
3049 do_moduli_screen(const char *out_file
, char **opts
, size_t nopts
)
3052 /* Moduli generation/screening */
3053 char *checkpoint
= NULL
;
3054 u_int32_t generator_wanted
= 0;
3055 unsigned long start_lineno
= 0, lines_to_process
= 0;
3056 int prime_tests
= 0;
3057 FILE *out
, *in
= stdin
;
3062 for (i
= 0; i
< nopts
; i
++) {
3063 if (strncmp(opts
[i
], "lines=", 6) == 0) {
3064 lines_to_process
= strtoul(opts
[i
]+6, NULL
, 10);
3065 } else if (strncmp(opts
[i
], "start-line=", 11) == 0) {
3066 start_lineno
= strtoul(opts
[i
]+11, NULL
, 10);
3067 } else if (strncmp(opts
[i
], "checkpoint=", 11) == 0) {
3069 checkpoint
= xstrdup(opts
[i
]+11);
3070 } else if (strncmp(opts
[i
], "generator=", 10) == 0) {
3071 generator_wanted
= (u_int32_t
)strtonum(
3072 opts
[i
]+10, 1, UINT_MAX
, &errstr
);
3073 if (errstr
!= NULL
) {
3074 fatal("Generator invalid: %s (%s)",
3075 opts
[i
]+10, errstr
);
3077 } else if (strncmp(opts
[i
], "prime-tests=", 12) == 0) {
3078 prime_tests
= (int)strtonum(opts
[i
]+12, 1,
3081 fatal("Invalid number: %s (%s)",
3082 opts
[i
]+12, errstr
);
3085 fatal("Option \"%s\" is unsupported for moduli "
3086 "screening", opts
[i
]);
3090 if (have_identity
&& strcmp(identity_file
, "-") != 0) {
3091 if ((in
= fopen(identity_file
, "r")) == NULL
) {
3092 fatal("Couldn't open modulus candidate "
3093 "file \"%s\": %s", identity_file
,
3098 if (strcmp(out_file
, "-") == 0)
3100 else if ((out
= fopen(out_file
, "a")) == NULL
) {
3101 fatal("Couldn't open moduli file \"%s\": %s",
3102 out_file
, strerror(errno
));
3104 setvbuf(out
, NULL
, _IOLBF
, 0);
3105 if (prime_test(in
, out
, prime_tests
== 0 ? 100 : prime_tests
,
3106 generator_wanted
, checkpoint
,
3107 start_lineno
, lines_to_process
) != 0)
3108 fatal("modulus screening failed");
3112 #else /* WITH_OPENSSL */
3113 fatal("Moduli screening is not supported");
3114 #endif /* WITH_OPENSSL */
3117 /* Read and confirm a passphrase */
3119 read_check_passphrase(const char *prompt1
, const char *prompt2
,
3120 const char *retry_prompt
)
3122 char *passphrase1
, *passphrase2
;
3125 passphrase1
= read_passphrase(prompt1
, RP_ALLOW_STDIN
);
3126 passphrase2
= read_passphrase(prompt2
, RP_ALLOW_STDIN
);
3127 if (strcmp(passphrase1
, passphrase2
) == 0) {
3128 freezero(passphrase2
, strlen(passphrase2
));
3131 /* The passphrases do not match. Clear them and retry. */
3132 freezero(passphrase1
, strlen(passphrase1
));
3133 freezero(passphrase2
, strlen(passphrase2
));
3134 fputs(retry_prompt
, stdout
);
3135 fputc('\n', stdout
);
3143 private_key_passphrase(const char *path
)
3147 if (identity_passphrase
)
3148 return xstrdup(identity_passphrase
);
3149 if (identity_new_passphrase
)
3150 return xstrdup(identity_new_passphrase
);
3152 xasprintf(&prompt
, "Enter passphrase for \"%s\" "
3153 "(empty for no passphrase): ", path
);
3154 ret
= read_check_passphrase(prompt
,
3155 "Enter same passphrase again: ",
3156 "Passphrases do not match. Try again.");
3162 sk_suffix(const char *application
, const uint8_t *user
, size_t userlen
)
3167 /* Trim off URL-like preamble */
3168 if (strncmp(application
, "ssh://", 6) == 0)
3169 ret
= xstrdup(application
+ 6);
3170 else if (strncmp(application
, "ssh:", 4) == 0)
3171 ret
= xstrdup(application
+ 4);
3173 ret
= xstrdup(application
);
3175 /* Count trailing zeros in user */
3176 for (i
= 0; i
< userlen
; i
++) {
3177 if (user
[userlen
- i
- 1] != 0)
3181 return ret
; /* user-id was default all-zeros */
3183 /* Append user-id, escaping non-UTF-8 characters */
3185 if (asmprintf(&cp
, INT_MAX
, NULL
, "%.*s", (int)slen
, user
) == -1)
3186 fatal_f("asmprintf failed");
3187 /* Don't emit a user-id that contains path or control characters */
3188 if (strchr(cp
, '/') != NULL
|| strstr(cp
, "..") != NULL
||
3189 strchr(cp
, '\\') != NULL
) {
3191 cp
= tohex(user
, slen
);
3193 xextendf(&ret
, "_", "%s", cp
);
3199 do_download_sk(const char *skprovider
, const char *device
)
3201 struct sshsk_resident_key
**srks
;
3204 char *fp
, *pin
= NULL
, *pass
= NULL
, *path
, *pubpath
;
3208 if (skprovider
== NULL
)
3209 fatal("Cannot download keys without provider");
3211 pin
= read_passphrase("Enter PIN for authenticator: ", RP_ALLOW_STDIN
);
3213 printf("You may need to touch your authenticator "
3214 "to authorize key download.\n");
3216 if ((r
= sshsk_load_resident(skprovider
, device
, pin
, 0,
3217 &srks
, &nsrks
)) != 0) {
3219 freezero(pin
, strlen(pin
));
3220 error_r(r
, "Unable to load resident keys");
3224 logit("No keys to download");
3226 freezero(pin
, strlen(pin
));
3228 for (i
= 0; i
< nsrks
; i
++) {
3230 if (key
->type
!= KEY_ECDSA_SK
&& key
->type
!= KEY_ED25519_SK
) {
3231 error("Unsupported key type %s (%d)",
3232 sshkey_type(key
), key
->type
);
3235 if ((fp
= sshkey_fingerprint(key
, fingerprint_hash
,
3236 SSH_FP_DEFAULT
)) == NULL
)
3237 fatal_f("sshkey_fingerprint failed");
3238 debug_f("key %zu: %s %s %s (flags 0x%02x)", i
,
3239 sshkey_type(key
), fp
, key
->sk_application
, key
->sk_flags
);
3240 ext
= sk_suffix(key
->sk_application
,
3241 srks
[i
]->user_id
, srks
[i
]->user_id_len
);
3242 xasprintf(&path
, "id_%s_rk%s%s",
3243 key
->type
== KEY_ECDSA_SK
? "ecdsa_sk" : "ed25519_sk",
3244 *ext
== '\0' ? "" : "_", ext
);
3246 /* If the file already exists, ask the user to confirm. */
3247 if (!confirm_overwrite(path
)) {
3252 /* Save the key with the application string as the comment */
3254 pass
= private_key_passphrase(path
);
3255 if ((r
= sshkey_save_private(key
, path
, pass
,
3256 key
->sk_application
, private_key_format
,
3257 openssh_format_cipher
, rounds
)) != 0) {
3258 error_r(r
, "Saving key \"%s\" failed", path
);
3263 printf("Saved %s key%s%s to %s\n", sshkey_type(key
),
3264 *ext
!= '\0' ? " " : "",
3265 *ext
!= '\0' ? key
->sk_application
: "",
3269 /* Save public key too */
3270 xasprintf(&pubpath
, "%s.pub", path
);
3272 if ((r
= sshkey_save_public(key
, pubpath
,
3273 key
->sk_application
)) != 0) {
3274 error_r(r
, "Saving public key \"%s\" failed", pubpath
);
3282 ret
= 0; /* success */
3284 freezero(pass
, strlen(pass
));
3285 sshsk_free_resident_keys(srks
, nsrks
);
3290 save_attestation(struct sshbuf
*attest
, const char *path
)
3296 return; /* nothing to do */
3297 if (attest
== NULL
|| sshbuf_len(attest
) == 0)
3298 fatal("Enrollment did not return attestation data");
3300 r
= sshbuf_write_file(path
, attest
);
3303 fatal_r(r
, "Unable to write attestation data \"%s\"", path
);
3305 printf("Your FIDO attestation certificate has been saved in "
3310 confirm_sk_overwrite(const char *application
, const char *user
)
3314 printf("A resident key scoped to '%s' with user id '%s' already "
3315 "exists.\n", application
== NULL
? "ssh:" : application
,
3316 user
== NULL
? "null" : user
);
3317 printf("Overwrite key in token (y/n)? ");
3319 if (fgets(yesno
, sizeof(yesno
), stdin
) == NULL
)
3321 if (yesno
[0] != 'y' && yesno
[0] != 'Y')
3330 "usage: ssh-keygen [-q] [-a rounds] [-b bits] [-C comment] [-f output_keyfile]\n"
3331 " [-m format] [-N new_passphrase] [-O option]\n"
3332 " [-t dsa | ecdsa | ecdsa-sk | ed25519 | ed25519-sk | rsa]\n"
3333 " [-w provider] [-Z cipher]\n"
3334 " ssh-keygen -p [-a rounds] [-f keyfile] [-m format] [-N new_passphrase]\n"
3335 " [-P old_passphrase] [-Z cipher]\n"
3337 " ssh-keygen -i [-f input_keyfile] [-m key_format]\n"
3338 " ssh-keygen -e [-f input_keyfile] [-m key_format]\n"
3340 " ssh-keygen -y [-f input_keyfile]\n"
3341 " ssh-keygen -c [-a rounds] [-C comment] [-f keyfile] [-P passphrase]\n"
3342 " ssh-keygen -l [-v] [-E fingerprint_hash] [-f input_keyfile]\n"
3343 " ssh-keygen -B [-f input_keyfile]\n");
3344 #ifdef ENABLE_PKCS11
3346 " ssh-keygen -D pkcs11\n");
3349 " ssh-keygen -F hostname [-lv] [-f known_hosts_file]\n"
3350 " ssh-keygen -H [-f known_hosts_file]\n"
3351 " ssh-keygen -K [-a rounds] [-w provider]\n"
3352 " ssh-keygen -R hostname [-f known_hosts_file]\n"
3353 " ssh-keygen -r hostname [-g] [-f input_keyfile]\n"
3355 " ssh-keygen -M generate [-O option] output_file\n"
3356 " ssh-keygen -M screen [-f input_file] [-O option] output_file\n"
3358 " ssh-keygen -I certificate_identity -s ca_key [-hU] [-D pkcs11_provider]\n"
3359 " [-n principals] [-O option] [-V validity_interval]\n"
3360 " [-z serial_number] file ...\n"
3361 " ssh-keygen -L [-f input_keyfile]\n"
3362 " ssh-keygen -A [-a rounds] [-f prefix_path]\n"
3363 " ssh-keygen -k -f krl_file [-u] [-s ca_public] [-z version_number]\n"
3365 " ssh-keygen -Q [-l] -f krl_file [file ...]\n"
3366 " ssh-keygen -Y find-principals -s signature_file -f allowed_signers_file\n"
3367 " ssh-keygen -Y match-principals -I signer_identity -f allowed_signers_file\n"
3368 " ssh-keygen -Y check-novalidate -n namespace -s signature_file\n"
3369 " ssh-keygen -Y sign -f key_file -n namespace file [-O option] ...\n"
3370 " ssh-keygen -Y verify -f allowed_signers_file -I signer_identity\n"
3371 " -n namespace -s signature_file [-r krl_file] [-O option]\n");
3376 * Main program for key management.
3379 main(int argc
, char **argv
)
3381 char comment
[1024], *passphrase
= NULL
;
3382 char *rr_hostname
= NULL
, *ep
, *fp
, *ra
;
3383 struct sshkey
*private, *public;
3386 int change_passphrase
= 0, change_comment
= 0, show_cert
= 0;
3387 int find_host
= 0, delete_host
= 0, hash_hosts
= 0;
3388 int gen_all_hostkeys
= 0, gen_krl
= 0, update_krl
= 0, check_krl
= 0;
3389 int prefer_agent
= 0, convert_to
= 0, convert_from
= 0;
3390 int print_public
= 0, print_generic
= 0, cert_serial_autoinc
= 0;
3391 int do_gen_candidates
= 0, do_screen_candidates
= 0, download_sk
= 0;
3392 unsigned long long cert_serial
= 0;
3393 char *identity_comment
= NULL
, *ca_key_path
= NULL
, **opts
= NULL
;
3394 char *sk_application
= NULL
, *sk_device
= NULL
, *sk_user
= NULL
;
3395 char *sk_attestation_path
= NULL
;
3396 struct sshbuf
*challenge
= NULL
, *attest
= NULL
;
3397 size_t i
, nopts
= 0;
3399 uint8_t sk_flags
= SSH_SK_USER_PRESENCE_REQD
;
3401 int log_level
= SYSLOG_LEVEL_INFO
;
3402 char *sign_op
= NULL
;
3405 extern char *optarg
;
3407 /* Ensure that fds 0, 1 and 2 are open or directed to /dev/null */
3410 __progname
= ssh_get_progname(argv
[0]);
3414 log_init(argv
[0], SYSLOG_LEVEL_INFO
, SYSLOG_FACILITY_USER
, 1);
3418 /* we need this for the home * directory. */
3419 pw
= getpwuid(getuid());
3421 fatal("No user exists for uid %lu", (u_long
)getuid());
3423 if (gethostname(hostname
, sizeof(hostname
)) == -1)
3424 fatal("gethostname: %s", strerror(errno
));
3426 sk_provider
= getenv("SSH_SK_PROVIDER");
3428 /* Remaining characters: dGjJSTWx */
3429 while ((opt
= getopt(argc
, argv
, "ABHKLQUXceghiklopquvy"
3430 "C:D:E:F:I:M:N:O:P:R:V:Y:Z:"
3431 "a:b:f:g:m:n:r:s:t:w:z:")) != -1) {
3434 gen_all_hostkeys
= 1;
3437 bits
= (u_int32_t
)strtonum(optarg
, 1, UINT32_MAX
,
3440 fatal("Bits has bad value %s (%s)",
3444 fingerprint_hash
= ssh_digest_alg_by_name(optarg
);
3445 if (fingerprint_hash
== -1)
3446 fatal("Invalid hash algorithm \"%s\"", optarg
);
3450 rr_hostname
= optarg
;
3456 cert_key_id
= optarg
;
3460 rr_hostname
= optarg
;
3466 print_fingerprint
= 1;
3469 print_bubblebabble
= 1;
3472 if (strcasecmp(optarg
, "RFC4716") == 0 ||
3473 strcasecmp(optarg
, "ssh2") == 0) {
3474 convert_format
= FMT_RFC4716
;
3477 if (strcasecmp(optarg
, "PKCS8") == 0) {
3478 convert_format
= FMT_PKCS8
;
3479 private_key_format
= SSHKEY_PRIVATE_PKCS8
;
3482 if (strcasecmp(optarg
, "PEM") == 0) {
3483 convert_format
= FMT_PEM
;
3484 private_key_format
= SSHKEY_PRIVATE_PEM
;
3487 fatal("Unsupported conversion format \"%s\"", optarg
);
3489 cert_principals
= optarg
;
3492 /* no-op; new format is already the default */
3495 change_passphrase
= 1;
3501 if (strlcpy(identity_file
, optarg
,
3502 sizeof(identity_file
)) >= sizeof(identity_file
))
3503 fatal("Identity filename too long");
3513 identity_passphrase
= optarg
;
3516 identity_new_passphrase
= optarg
;
3522 opts
= xrecallocarray(opts
, nopts
, nopts
+ 1,
3524 opts
[nopts
++] = xstrdup(optarg
);
3527 openssh_format_cipher
= optarg
;
3528 if (cipher_by_name(openssh_format_cipher
) == NULL
)
3529 fatal("Invalid OpenSSH-format cipher '%s'",
3530 openssh_format_cipher
);
3533 identity_comment
= optarg
;
3543 cert_key_type
= SSH2_CERT_TYPE_HOST
;
3544 certflags_flags
= 0;
3558 ca_key_path
= optarg
;
3561 key_type_name
= optarg
;
3564 pkcs11provider
= optarg
;
3573 if (log_level
== SYSLOG_LEVEL_INFO
)
3574 log_level
= SYSLOG_LEVEL_DEBUG1
;
3576 if (log_level
>= SYSLOG_LEVEL_DEBUG1
&&
3577 log_level
< SYSLOG_LEVEL_DEBUG3
)
3582 rr_hostname
= optarg
;
3585 rounds
= (int)strtonum(optarg
, 1, INT_MAX
, &errstr
);
3587 fatal("Invalid number: %s (%s)",
3591 parse_cert_times(optarg
);
3597 sk_provider
= optarg
;
3601 if (*optarg
== '+') {
3602 cert_serial_autoinc
= 1;
3605 cert_serial
= strtoull(optarg
, &ep
, 10);
3606 if (*optarg
< '0' || *optarg
> '9' || *ep
!= '\0' ||
3607 (errno
== ERANGE
&& cert_serial
== ULLONG_MAX
))
3608 fatal("Invalid serial number \"%s\"", optarg
);
3611 if (strcmp(optarg
, "generate") == 0)
3612 do_gen_candidates
= 1;
3613 else if (strcmp(optarg
, "screen") == 0)
3614 do_screen_candidates
= 1;
3616 fatal("Unsupported moduli option %s", optarg
);
3623 #ifdef ENABLE_SK_INTERNAL
3624 if (sk_provider
== NULL
)
3625 sk_provider
= "internal";
3629 log_init(argv
[0], log_level
, SYSLOG_FACILITY_USER
, 1);
3634 if (sign_op
!= NULL
) {
3635 if (strncmp(sign_op
, "find-principals", 15) == 0) {
3636 if (ca_key_path
== NULL
) {
3637 error("Too few arguments for find-principals:"
3638 "missing signature file");
3641 if (!have_identity
) {
3642 error("Too few arguments for find-principals:"
3643 "missing allowed keys file");
3646 return sig_find_principals(ca_key_path
, identity_file
,
3648 } else if (strncmp(sign_op
, "match-principals", 16) == 0) {
3649 if (!have_identity
) {
3650 error("Too few arguments for match-principals:"
3651 "missing allowed keys file");
3654 if (cert_key_id
== NULL
) {
3655 error("Too few arguments for match-principals: "
3656 "missing principal ID");
3659 return sig_match_principals(identity_file
, cert_key_id
,
3661 } else if (strncmp(sign_op
, "sign", 4) == 0) {
3662 /* NB. cert_principals is actually namespace, via -n */
3663 if (cert_principals
== NULL
||
3664 *cert_principals
== '\0') {
3665 error("Too few arguments for sign: "
3666 "missing namespace");
3669 if (!have_identity
) {
3670 error("Too few arguments for sign: "
3674 return sig_sign(identity_file
, cert_principals
,
3675 prefer_agent
, argc
, argv
, opts
, nopts
);
3676 } else if (strncmp(sign_op
, "check-novalidate", 16) == 0) {
3677 /* NB. cert_principals is actually namespace, via -n */
3678 if (cert_principals
== NULL
||
3679 *cert_principals
== '\0') {
3680 error("Too few arguments for check-novalidate: "
3681 "missing namespace");
3684 if (ca_key_path
== NULL
) {
3685 error("Too few arguments for check-novalidate: "
3686 "missing signature file");
3689 return sig_verify(ca_key_path
, cert_principals
,
3690 NULL
, NULL
, NULL
, opts
, nopts
);
3691 } else if (strncmp(sign_op
, "verify", 6) == 0) {
3692 /* NB. cert_principals is actually namespace, via -n */
3693 if (cert_principals
== NULL
||
3694 *cert_principals
== '\0') {
3695 error("Too few arguments for verify: "
3696 "missing namespace");
3699 if (ca_key_path
== NULL
) {
3700 error("Too few arguments for verify: "
3701 "missing signature file");
3704 if (!have_identity
) {
3705 error("Too few arguments for sign: "
3706 "missing allowed keys file");
3709 if (cert_key_id
== NULL
) {
3710 error("Too few arguments for verify: "
3711 "missing principal identity");
3714 return sig_verify(ca_key_path
, cert_principals
,
3715 cert_key_id
, identity_file
, rr_hostname
,
3718 error("Unsupported operation for -Y: \"%s\"", sign_op
);
3723 if (ca_key_path
!= NULL
) {
3724 if (argc
< 1 && !gen_krl
) {
3725 error("Too few arguments.");
3728 } else if (argc
> 0 && !gen_krl
&& !check_krl
&&
3729 !do_gen_candidates
&& !do_screen_candidates
) {
3730 error("Too many arguments.");
3733 if (change_passphrase
&& change_comment
) {
3734 error("Can only have one of -p and -c.");
3737 if (print_fingerprint
&& (delete_host
|| hash_hosts
)) {
3738 error("Cannot use -l with -H or -R.");
3742 do_gen_krl(pw
, update_krl
, ca_key_path
,
3743 cert_serial
, identity_comment
, argc
, argv
);
3747 do_check_krl(pw
, print_fingerprint
, argc
, argv
);
3750 if (ca_key_path
!= NULL
) {
3751 if (cert_key_id
== NULL
)
3752 fatal("Must specify key id (-I) when certifying");
3753 for (i
= 0; i
< nopts
; i
++)
3754 add_cert_option(opts
[i
]);
3755 do_ca_sign(pw
, ca_key_path
, prefer_agent
,
3756 cert_serial
, cert_serial_autoinc
, argc
, argv
);
3760 if (delete_host
|| hash_hosts
|| find_host
) {
3761 do_known_hosts(pw
, rr_hostname
, find_host
,
3762 delete_host
, hash_hosts
);
3764 if (pkcs11provider
!= NULL
)
3767 for (i
= 0; i
< nopts
; i
++) {
3768 if (strncasecmp(opts
[i
], "device=", 7) == 0) {
3769 sk_device
= xstrdup(opts
[i
] + 7);
3771 fatal("Option \"%s\" is unsupported for "
3772 "FIDO authenticator download", opts
[i
]);
3775 return do_download_sk(sk_provider
, sk_device
);
3777 if (print_fingerprint
|| print_bubblebabble
)
3779 if (change_passphrase
)
3780 do_change_passphrase(pw
);
3782 do_change_comment(pw
, identity_comment
);
3787 do_convert_from(pw
);
3788 #else /* WITH_OPENSSL */
3789 if (convert_to
|| convert_from
)
3790 fatal("key conversion disabled at compile time");
3791 #endif /* WITH_OPENSSL */
3793 do_print_public(pw
);
3794 if (rr_hostname
!= NULL
) {
3797 if (have_identity
) {
3798 n
= do_print_resource_record(pw
, identity_file
,
3799 rr_hostname
, print_generic
, opts
, nopts
);
3801 fatal("%s: %s", identity_file
, strerror(errno
));
3805 n
+= do_print_resource_record(pw
,
3806 _PATH_HOST_RSA_KEY_FILE
, rr_hostname
,
3807 print_generic
, opts
, nopts
);
3809 n
+= do_print_resource_record(pw
,
3810 _PATH_HOST_DSA_KEY_FILE
, rr_hostname
,
3811 print_generic
, opts
, nopts
);
3813 n
+= do_print_resource_record(pw
,
3814 _PATH_HOST_ECDSA_KEY_FILE
, rr_hostname
,
3815 print_generic
, opts
, nopts
);
3816 n
+= do_print_resource_record(pw
,
3817 _PATH_HOST_ED25519_KEY_FILE
, rr_hostname
,
3818 print_generic
, opts
, nopts
);
3819 n
+= do_print_resource_record(pw
,
3820 _PATH_HOST_XMSS_KEY_FILE
, rr_hostname
,
3821 print_generic
, opts
, nopts
);
3823 fatal("no keys found.");
3828 if (do_gen_candidates
|| do_screen_candidates
) {
3830 fatal("No output file specified");
3832 fatal("Too many output files specified");
3834 if (do_gen_candidates
) {
3835 do_moduli_gen(argv
[0], opts
, nopts
);
3838 if (do_screen_candidates
) {
3839 do_moduli_screen(argv
[0], opts
, nopts
);
3843 if (gen_all_hostkeys
) {
3844 do_gen_all_hostkeys(pw
);
3848 if (key_type_name
== NULL
)
3849 key_type_name
= DEFAULT_KEY_TYPE_NAME
;
3851 type
= sshkey_type_from_shortname(key_type_name
);
3852 type_bits_valid(type
, key_type_name
, &bits
);
3855 printf("Generating public/private %s key pair.\n",
3859 case KEY_ED25519_SK
:
3860 for (i
= 0; i
< nopts
; i
++) {
3861 if (strcasecmp(opts
[i
], "no-touch-required") == 0) {
3862 sk_flags
&= ~SSH_SK_USER_PRESENCE_REQD
;
3863 } else if (strcasecmp(opts
[i
], "verify-required") == 0) {
3864 sk_flags
|= SSH_SK_USER_VERIFICATION_REQD
;
3865 } else if (strcasecmp(opts
[i
], "resident") == 0) {
3866 sk_flags
|= SSH_SK_RESIDENT_KEY
;
3867 } else if (strncasecmp(opts
[i
], "device=", 7) == 0) {
3868 sk_device
= xstrdup(opts
[i
] + 7);
3869 } else if (strncasecmp(opts
[i
], "user=", 5) == 0) {
3870 sk_user
= xstrdup(opts
[i
] + 5);
3871 } else if (strncasecmp(opts
[i
], "challenge=", 10) == 0) {
3872 if ((r
= sshbuf_load_file(opts
[i
] + 10,
3873 &challenge
)) != 0) {
3874 fatal_r(r
, "Unable to load FIDO "
3875 "enrollment challenge \"%s\"",
3878 } else if (strncasecmp(opts
[i
],
3879 "write-attestation=", 18) == 0) {
3880 sk_attestation_path
= opts
[i
] + 18;
3881 } else if (strncasecmp(opts
[i
],
3882 "application=", 12) == 0) {
3883 sk_application
= xstrdup(opts
[i
] + 12);
3884 if (strncmp(sk_application
, "ssh:", 4) != 0) {
3885 fatal("FIDO application string must "
3886 "begin with \"ssh:\"");
3889 fatal("Option \"%s\" is unsupported for "
3890 "FIDO authenticator enrollment", opts
[i
]);
3893 if ((attest
= sshbuf_new()) == NULL
)
3894 fatal("sshbuf_new failed");
3898 printf("You may need to touch your "
3899 "authenticator%s to authorize key "
3901 r
== 0 ? "" : " again");
3904 r
= sshsk_enroll(type
, sk_provider
, sk_device
,
3905 sk_application
== NULL
? "ssh:" : sk_application
,
3906 sk_user
, sk_flags
, passphrase
, challenge
,
3910 if (r
== SSH_ERR_KEY_BAD_PERMISSIONS
&&
3911 (sk_flags
& SSH_SK_RESIDENT_KEY
) != 0 &&
3912 (sk_flags
& SSH_SK_FORCE_OPERATION
) == 0 &&
3913 confirm_sk_overwrite(sk_application
, sk_user
)) {
3914 sk_flags
|= SSH_SK_FORCE_OPERATION
;
3917 if (r
!= SSH_ERR_KEY_WRONG_PASSPHRASE
)
3918 fatal_r(r
, "Key enrollment failed");
3919 else if (passphrase
!= NULL
) {
3920 error("PIN incorrect");
3921 freezero(passphrase
, strlen(passphrase
));
3925 fatal("Too many incorrect PINs");
3926 passphrase
= read_passphrase("Enter PIN for "
3927 "authenticator: ", RP_ALLOW_STDIN
);
3929 if (passphrase
!= NULL
) {
3930 freezero(passphrase
, strlen(passphrase
));
3935 if ((r
= sshkey_generate(type
, bits
, &private)) != 0)
3936 fatal("sshkey_generate failed");
3939 if ((r
= sshkey_from_private(private, &public)) != 0)
3940 fatal_r(r
, "sshkey_from_private");
3943 ask_filename(pw
, "Enter file in which to save the key");
3945 /* Create ~/.ssh directory if it doesn't already exist. */
3946 hostfile_create_user_ssh_dir(identity_file
, !quiet
);
3948 /* If the file already exists, ask the user to confirm. */
3949 if (!confirm_overwrite(identity_file
))
3952 /* Determine the passphrase for the private key */
3953 passphrase
= private_key_passphrase(identity_file
);
3954 if (identity_comment
) {
3955 strlcpy(comment
, identity_comment
, sizeof(comment
));
3957 /* Create default comment field for the passphrase. */
3958 snprintf(comment
, sizeof comment
, "%s@%s", pw
->pw_name
, hostname
);
3961 /* Save the key with the given passphrase and comment. */
3962 if ((r
= sshkey_save_private(private, identity_file
, passphrase
,
3963 comment
, private_key_format
, openssh_format_cipher
, rounds
)) != 0) {
3964 error_r(r
, "Saving key \"%s\" failed", identity_file
);
3965 freezero(passphrase
, strlen(passphrase
));
3968 freezero(passphrase
, strlen(passphrase
));
3969 sshkey_free(private);
3972 printf("Your identification has been saved in %s\n",
3976 strlcat(identity_file
, ".pub", sizeof(identity_file
));
3977 if ((r
= sshkey_save_public(public, identity_file
, comment
)) != 0)
3978 fatal_r(r
, "Unable to save public key to %s", identity_file
);
3981 fp
= sshkey_fingerprint(public, fingerprint_hash
,
3983 ra
= sshkey_fingerprint(public, fingerprint_hash
,
3985 if (fp
== NULL
|| ra
== NULL
)
3986 fatal("sshkey_fingerprint failed");
3987 printf("Your public key has been saved in %s\n",
3989 printf("The key fingerprint is:\n");
3990 printf("%s %s\n", fp
, comment
);
3991 printf("The key's randomart image is:\n");
3997 if (sk_attestation_path
!= NULL
)
3998 save_attestation(attest
, sk_attestation_path
);
4000 sshbuf_free(attest
);
4001 sshkey_free(public);