diff options
Diffstat (limited to 'ssh-keygen.c')
-rw-r--r-- | ssh-keygen.c | 140 |
1 files changed, 115 insertions, 25 deletions
diff --git a/ssh-keygen.c b/ssh-keygen.c index 22860ad90..46b3af5a8 100644 --- a/ssh-keygen.c +++ b/ssh-keygen.c | |||
@@ -1,4 +1,4 @@ | |||
1 | /* $OpenBSD: ssh-keygen.c,v 1.319 2018/08/08 01:16:01 djm Exp $ */ | 1 | /* $OpenBSD: ssh-keygen.c,v 1.322 2018/09/14 04:17:44 djm Exp $ */ |
2 | /* | 2 | /* |
3 | * Author: Tatu Ylonen <ylo@cs.hut.fi> | 3 | * Author: Tatu Ylonen <ylo@cs.hut.fi> |
4 | * Copyright (c) 1994 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland | 4 | * Copyright (c) 1994 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland |
@@ -450,7 +450,10 @@ do_convert_private_ssh2_from_blob(u_char *blob, u_int blen) | |||
450 | u_int magic, i1, i2, i3, i4; | 450 | u_int magic, i1, i2, i3, i4; |
451 | size_t slen; | 451 | size_t slen; |
452 | u_long e; | 452 | u_long e; |
453 | 453 | BIGNUM *dsa_p = NULL, *dsa_q = NULL, *dsa_g = NULL; | |
454 | BIGNUM *dsa_pub_key = NULL, *dsa_priv_key = NULL; | ||
455 | BIGNUM *rsa_n = NULL, *rsa_e = NULL, *rsa_d = NULL; | ||
456 | BIGNUM *rsa_p = NULL, *rsa_q = NULL, *rsa_iqmp = NULL; | ||
454 | if ((b = sshbuf_from(blob, blen)) == NULL) | 457 | if ((b = sshbuf_from(blob, blen)) == NULL) |
455 | fatal("%s: sshbuf_from failed", __func__); | 458 | fatal("%s: sshbuf_from failed", __func__); |
456 | if ((r = sshbuf_get_u32(b, &magic)) != 0) | 459 | if ((r = sshbuf_get_u32(b, &magic)) != 0) |
@@ -488,17 +491,29 @@ do_convert_private_ssh2_from_blob(u_char *blob, u_int blen) | |||
488 | free(type); | 491 | free(type); |
489 | return NULL; | 492 | return NULL; |
490 | } | 493 | } |
491 | if ((key = sshkey_new_private(ktype)) == NULL) | 494 | if ((key = sshkey_new(ktype)) == NULL) |
492 | fatal("sshkey_new_private failed"); | 495 | fatal("sshkey_new failed"); |
493 | free(type); | 496 | free(type); |
494 | 497 | ||
495 | switch (key->type) { | 498 | switch (key->type) { |
496 | case KEY_DSA: | 499 | case KEY_DSA: |
497 | buffer_get_bignum_bits(b, key->dsa->p); | 500 | if ((dsa_p = BN_new()) == NULL || |
498 | buffer_get_bignum_bits(b, key->dsa->g); | 501 | (dsa_q = BN_new()) == NULL || |
499 | buffer_get_bignum_bits(b, key->dsa->q); | 502 | (dsa_g = BN_new()) == NULL || |
500 | buffer_get_bignum_bits(b, key->dsa->pub_key); | 503 | (dsa_pub_key = BN_new()) == NULL || |
501 | buffer_get_bignum_bits(b, key->dsa->priv_key); | 504 | (dsa_priv_key = BN_new()) == NULL) |
505 | fatal("%s: BN_new", __func__); | ||
506 | buffer_get_bignum_bits(b, dsa_p); | ||
507 | buffer_get_bignum_bits(b, dsa_g); | ||
508 | buffer_get_bignum_bits(b, dsa_q); | ||
509 | buffer_get_bignum_bits(b, dsa_pub_key); | ||
510 | buffer_get_bignum_bits(b, dsa_priv_key); | ||
511 | if (!DSA_set0_pqg(key->dsa, dsa_p, dsa_q, dsa_g)) | ||
512 | fatal("%s: DSA_set0_pqg failed", __func__); | ||
513 | dsa_p = dsa_q = dsa_g = NULL; /* transferred */ | ||
514 | if (!DSA_set0_key(key->dsa, dsa_pub_key, dsa_priv_key)) | ||
515 | fatal("%s: DSA_set0_key failed", __func__); | ||
516 | dsa_pub_key = dsa_priv_key = NULL; /* transferred */ | ||
502 | break; | 517 | break; |
503 | case KEY_RSA: | 518 | case KEY_RSA: |
504 | if ((r = sshbuf_get_u8(b, &e1)) != 0 || | 519 | if ((r = sshbuf_get_u8(b, &e1)) != 0 || |
@@ -515,18 +530,34 @@ do_convert_private_ssh2_from_blob(u_char *blob, u_int blen) | |||
515 | e += e3; | 530 | e += e3; |
516 | debug("e %lx", e); | 531 | debug("e %lx", e); |
517 | } | 532 | } |
518 | if (!BN_set_word(key->rsa->e, e)) { | 533 | if ((rsa_e = BN_new()) == NULL) |
534 | fatal("%s: BN_new", __func__); | ||
535 | if (!BN_set_word(rsa_e, e)) { | ||
536 | BN_clear_free(rsa_e); | ||
519 | sshbuf_free(b); | 537 | sshbuf_free(b); |
520 | sshkey_free(key); | 538 | sshkey_free(key); |
521 | return NULL; | 539 | return NULL; |
522 | } | 540 | } |
523 | buffer_get_bignum_bits(b, key->rsa->d); | 541 | if ((rsa_n = BN_new()) == NULL || |
524 | buffer_get_bignum_bits(b, key->rsa->n); | 542 | (rsa_d = BN_new()) == NULL || |
525 | buffer_get_bignum_bits(b, key->rsa->iqmp); | 543 | (rsa_p = BN_new()) == NULL || |
526 | buffer_get_bignum_bits(b, key->rsa->q); | 544 | (rsa_q = BN_new()) == NULL || |
527 | buffer_get_bignum_bits(b, key->rsa->p); | 545 | (rsa_iqmp = BN_new()) == NULL) |
528 | if ((r = ssh_rsa_generate_additional_parameters(key)) != 0) | 546 | fatal("%s: BN_new", __func__); |
547 | buffer_get_bignum_bits(b, rsa_d); | ||
548 | buffer_get_bignum_bits(b, rsa_n); | ||
549 | buffer_get_bignum_bits(b, rsa_iqmp); | ||
550 | buffer_get_bignum_bits(b, rsa_q); | ||
551 | buffer_get_bignum_bits(b, rsa_p); | ||
552 | if (!RSA_set0_key(key->rsa, rsa_n, rsa_e, rsa_d)) | ||
553 | fatal("%s: RSA_set0_key failed", __func__); | ||
554 | rsa_n = rsa_e = rsa_d = NULL; /* transferred */ | ||
555 | if (!RSA_set0_factors(key->rsa, rsa_p, rsa_q)) | ||
556 | fatal("%s: RSA_set0_factors failed", __func__); | ||
557 | rsa_p = rsa_q = NULL; /* transferred */ | ||
558 | if ((r = ssh_rsa_complete_crt_parameters(key, rsa_iqmp)) != 0) | ||
529 | fatal("generate RSA parameters failed: %s", ssh_err(r)); | 559 | fatal("generate RSA parameters failed: %s", ssh_err(r)); |
560 | BN_clear_free(rsa_iqmp); | ||
530 | break; | 561 | break; |
531 | } | 562 | } |
532 | rlen = sshbuf_len(b); | 563 | rlen = sshbuf_len(b); |
@@ -634,7 +665,7 @@ do_convert_from_pkcs8(struct sshkey **k, int *private) | |||
634 | identity_file); | 665 | identity_file); |
635 | } | 666 | } |
636 | fclose(fp); | 667 | fclose(fp); |
637 | switch (EVP_PKEY_type(pubkey->type)) { | 668 | switch (EVP_PKEY_base_id(pubkey)) { |
638 | case EVP_PKEY_RSA: | 669 | case EVP_PKEY_RSA: |
639 | if ((*k = sshkey_new(KEY_UNSPEC)) == NULL) | 670 | if ((*k = sshkey_new(KEY_UNSPEC)) == NULL) |
640 | fatal("sshkey_new failed"); | 671 | fatal("sshkey_new failed"); |
@@ -658,7 +689,7 @@ do_convert_from_pkcs8(struct sshkey **k, int *private) | |||
658 | #endif | 689 | #endif |
659 | default: | 690 | default: |
660 | fatal("%s: unsupported pubkey type %d", __func__, | 691 | fatal("%s: unsupported pubkey type %d", __func__, |
661 | EVP_PKEY_type(pubkey->type)); | 692 | EVP_PKEY_base_id(pubkey)); |
662 | } | 693 | } |
663 | EVP_PKEY_free(pubkey); | 694 | EVP_PKEY_free(pubkey); |
664 | return; | 695 | return; |
@@ -2080,15 +2111,51 @@ load_krl(const char *path, struct ssh_krl **krlp) | |||
2080 | } | 2111 | } |
2081 | 2112 | ||
2082 | static void | 2113 | static void |
2114 | hash_to_blob(const char *cp, u_char **blobp, size_t *lenp, | ||
2115 | const char *file, u_long lnum) | ||
2116 | { | ||
2117 | char *tmp; | ||
2118 | size_t tlen; | ||
2119 | struct sshbuf *b; | ||
2120 | int r; | ||
2121 | |||
2122 | if (strncmp(cp, "SHA256:", 7) != 0) | ||
2123 | fatal("%s:%lu: unsupported hash algorithm", file, lnum); | ||
2124 | cp += 7; | ||
2125 | |||
2126 | /* | ||
2127 | * OpenSSH base64 hashes omit trailing '=' | ||
2128 | * characters; put them back for decode. | ||
2129 | */ | ||
2130 | tlen = strlen(cp); | ||
2131 | tmp = xmalloc(tlen + 4 + 1); | ||
2132 | strlcpy(tmp, cp, tlen + 1); | ||
2133 | while ((tlen % 4) != 0) { | ||
2134 | tmp[tlen++] = '='; | ||
2135 | tmp[tlen] = '\0'; | ||
2136 | } | ||
2137 | if ((b = sshbuf_new()) == NULL) | ||
2138 | fatal("%s: sshbuf_new failed", __func__); | ||
2139 | if ((r = sshbuf_b64tod(b, tmp)) != 0) | ||
2140 | fatal("%s:%lu: decode hash failed: %s", file, lnum, ssh_err(r)); | ||
2141 | free(tmp); | ||
2142 | *lenp = sshbuf_len(b); | ||
2143 | *blobp = xmalloc(*lenp); | ||
2144 | memcpy(*blobp, sshbuf_ptr(b), *lenp); | ||
2145 | sshbuf_free(b); | ||
2146 | } | ||
2147 | |||
2148 | static void | ||
2083 | update_krl_from_file(struct passwd *pw, const char *file, int wild_ca, | 2149 | update_krl_from_file(struct passwd *pw, const char *file, int wild_ca, |
2084 | const struct sshkey *ca, struct ssh_krl *krl) | 2150 | const struct sshkey *ca, struct ssh_krl *krl) |
2085 | { | 2151 | { |
2086 | struct sshkey *key = NULL; | 2152 | struct sshkey *key = NULL; |
2087 | u_long lnum = 0; | 2153 | u_long lnum = 0; |
2088 | char *path, *cp, *ep, *line = NULL; | 2154 | char *path, *cp, *ep, *line = NULL; |
2089 | size_t linesize = 0; | 2155 | u_char *blob = NULL; |
2156 | size_t blen = 0, linesize = 0; | ||
2090 | unsigned long long serial, serial2; | 2157 | unsigned long long serial, serial2; |
2091 | int i, was_explicit_key, was_sha1, r; | 2158 | int i, was_explicit_key, was_sha1, was_sha256, was_hash, r; |
2092 | FILE *krl_spec; | 2159 | FILE *krl_spec; |
2093 | 2160 | ||
2094 | path = tilde_expand_filename(file, pw->pw_uid); | 2161 | path = tilde_expand_filename(file, pw->pw_uid); |
@@ -2103,7 +2170,7 @@ update_krl_from_file(struct passwd *pw, const char *file, int wild_ca, | |||
2103 | printf("Revoking from %s\n", path); | 2170 | printf("Revoking from %s\n", path); |
2104 | while (getline(&line, &linesize, krl_spec) != -1) { | 2171 | while (getline(&line, &linesize, krl_spec) != -1) { |
2105 | lnum++; | 2172 | lnum++; |
2106 | was_explicit_key = was_sha1 = 0; | 2173 | was_explicit_key = was_sha1 = was_sha256 = was_hash = 0; |
2107 | cp = line + strspn(line, " \t"); | 2174 | cp = line + strspn(line, " \t"); |
2108 | /* Trim trailing space, comments and strip \n */ | 2175 | /* Trim trailing space, comments and strip \n */ |
2109 | for (i = 0, r = -1; cp[i] != '\0'; i++) { | 2176 | for (i = 0, r = -1; cp[i] != '\0'; i++) { |
@@ -2168,6 +2235,11 @@ update_krl_from_file(struct passwd *pw, const char *file, int wild_ca, | |||
2168 | cp = cp + strspn(cp, " \t"); | 2235 | cp = cp + strspn(cp, " \t"); |
2169 | if (ssh_krl_revoke_cert_by_key_id(krl, ca, cp) != 0) | 2236 | if (ssh_krl_revoke_cert_by_key_id(krl, ca, cp) != 0) |
2170 | fatal("%s: revoke key ID failed", __func__); | 2237 | fatal("%s: revoke key ID failed", __func__); |
2238 | } else if (strncasecmp(cp, "hash:", 5) == 0) { | ||
2239 | cp += 5; | ||
2240 | cp = cp + strspn(cp, " \t"); | ||
2241 | hash_to_blob(cp, &blob, &blen, file, lnum); | ||
2242 | r = ssh_krl_revoke_key_sha256(krl, blob, blen); | ||
2171 | } else { | 2243 | } else { |
2172 | if (strncasecmp(cp, "key:", 4) == 0) { | 2244 | if (strncasecmp(cp, "key:", 4) == 0) { |
2173 | cp += 4; | 2245 | cp += 4; |
@@ -2177,7 +2249,10 @@ update_krl_from_file(struct passwd *pw, const char *file, int wild_ca, | |||
2177 | cp += 5; | 2249 | cp += 5; |
2178 | cp = cp + strspn(cp, " \t"); | 2250 | cp = cp + strspn(cp, " \t"); |
2179 | was_sha1 = 1; | 2251 | was_sha1 = 1; |
2180 | } else { | 2252 | } else if (strncasecmp(cp, "sha256:", 7) == 0) { |
2253 | cp += 7; | ||
2254 | cp = cp + strspn(cp, " \t"); | ||
2255 | was_sha256 = 1; | ||
2181 | /* | 2256 | /* |
2182 | * Just try to process the line as a key. | 2257 | * Just try to process the line as a key. |
2183 | * Parsing will fail if it isn't. | 2258 | * Parsing will fail if it isn't. |
@@ -2190,13 +2265,28 @@ update_krl_from_file(struct passwd *pw, const char *file, int wild_ca, | |||
2190 | path, lnum, ssh_err(r)); | 2265 | path, lnum, ssh_err(r)); |
2191 | if (was_explicit_key) | 2266 | if (was_explicit_key) |
2192 | r = ssh_krl_revoke_key_explicit(krl, key); | 2267 | r = ssh_krl_revoke_key_explicit(krl, key); |
2193 | else if (was_sha1) | 2268 | else if (was_sha1) { |
2194 | r = ssh_krl_revoke_key_sha1(krl, key); | 2269 | if (sshkey_fingerprint_raw(key, |
2195 | else | 2270 | SSH_DIGEST_SHA1, &blob, &blen) != 0) { |
2271 | fatal("%s:%lu: fingerprint failed", | ||
2272 | file, lnum); | ||
2273 | } | ||
2274 | r = ssh_krl_revoke_key_sha1(krl, blob, blen); | ||
2275 | } else if (was_sha256) { | ||
2276 | if (sshkey_fingerprint_raw(key, | ||
2277 | SSH_DIGEST_SHA256, &blob, &blen) != 0) { | ||
2278 | fatal("%s:%lu: fingerprint failed", | ||
2279 | file, lnum); | ||
2280 | } | ||
2281 | r = ssh_krl_revoke_key_sha256(krl, blob, blen); | ||
2282 | } else | ||
2196 | r = ssh_krl_revoke_key(krl, key); | 2283 | r = ssh_krl_revoke_key(krl, key); |
2197 | if (r != 0) | 2284 | if (r != 0) |
2198 | fatal("%s: revoke key failed: %s", | 2285 | fatal("%s: revoke key failed: %s", |
2199 | __func__, ssh_err(r)); | 2286 | __func__, ssh_err(r)); |
2287 | freezero(blob, blen); | ||
2288 | blob = NULL; | ||
2289 | blen = 0; | ||
2200 | sshkey_free(key); | 2290 | sshkey_free(key); |
2201 | } | 2291 | } |
2202 | } | 2292 | } |