diff options
Diffstat (limited to 'sshkey.c')
-rw-r--r-- | sshkey.c | 609 |
1 files changed, 113 insertions, 496 deletions
@@ -1,4 +1,4 @@ | |||
1 | /* $OpenBSD: sshkey.c,v 1.45 2017/03/10 04:07:20 djm Exp $ */ | 1 | /* $OpenBSD: sshkey.c,v 1.56 2017/08/12 06:42:52 djm Exp $ */ |
2 | /* | 2 | /* |
3 | * Copyright (c) 2000, 2001 Markus Friedl. All rights reserved. | 3 | * Copyright (c) 2000, 2001 Markus Friedl. All rights reserved. |
4 | * Copyright (c) 2008 Alexander von Gernler. All rights reserved. | 4 | * Copyright (c) 2008 Alexander von Gernler. All rights reserved. |
@@ -51,7 +51,6 @@ | |||
51 | #include "ssherr.h" | 51 | #include "ssherr.h" |
52 | #include "misc.h" | 52 | #include "misc.h" |
53 | #include "sshbuf.h" | 53 | #include "sshbuf.h" |
54 | #include "rsa.h" | ||
55 | #include "cipher.h" | 54 | #include "cipher.h" |
56 | #include "digest.h" | 55 | #include "digest.h" |
57 | #define SSHKEY_INTERNAL | 56 | #define SSHKEY_INTERNAL |
@@ -66,7 +65,7 @@ | |||
66 | #define KDFNAME "bcrypt" | 65 | #define KDFNAME "bcrypt" |
67 | #define AUTH_MAGIC "openssh-key-v1" | 66 | #define AUTH_MAGIC "openssh-key-v1" |
68 | #define SALT_LEN 16 | 67 | #define SALT_LEN 16 |
69 | #define DEFAULT_CIPHERNAME "aes256-cbc" | 68 | #define DEFAULT_CIPHERNAME "aes256-ctr" |
70 | #define DEFAULT_ROUNDS 16 | 69 | #define DEFAULT_ROUNDS 16 |
71 | 70 | ||
72 | /* Version identification string for SSH v1 identity files. */ | 71 | /* Version identification string for SSH v1 identity files. */ |
@@ -89,9 +88,6 @@ static const struct keytype keytypes[] = { | |||
89 | { "ssh-ed25519-cert-v01@openssh.com", "ED25519-CERT", | 88 | { "ssh-ed25519-cert-v01@openssh.com", "ED25519-CERT", |
90 | KEY_ED25519_CERT, 0, 1, 0 }, | 89 | KEY_ED25519_CERT, 0, 1, 0 }, |
91 | #ifdef WITH_OPENSSL | 90 | #ifdef WITH_OPENSSL |
92 | # ifdef WITH_SSH1 | ||
93 | { NULL, "RSA1", KEY_RSA1, 0, 0, 0 }, | ||
94 | # endif | ||
95 | { "ssh-rsa", "RSA", KEY_RSA, 0, 0, 0 }, | 91 | { "ssh-rsa", "RSA", KEY_RSA, 0, 0, 0 }, |
96 | { "rsa-sha2-256", "RSA", KEY_RSA, 0, 0, 1 }, | 92 | { "rsa-sha2-256", "RSA", KEY_RSA, 0, 0, 1 }, |
97 | { "rsa-sha2-512", "RSA", KEY_RSA, 0, 0, 1 }, | 93 | { "rsa-sha2-512", "RSA", KEY_RSA, 0, 0, 1 }, |
@@ -238,10 +234,6 @@ sshkey_names_valid2(const char *names, int allow_wildcard) | |||
238 | for ((p = strsep(&cp, ",")); p && *p != '\0'; | 234 | for ((p = strsep(&cp, ",")); p && *p != '\0'; |
239 | (p = strsep(&cp, ","))) { | 235 | (p = strsep(&cp, ","))) { |
240 | type = sshkey_type_from_name(p); | 236 | type = sshkey_type_from_name(p); |
241 | if (type == KEY_RSA1) { | ||
242 | free(s); | ||
243 | return 0; | ||
244 | } | ||
245 | if (type == KEY_UNSPEC) { | 237 | if (type == KEY_UNSPEC) { |
246 | if (allow_wildcard) { | 238 | if (allow_wildcard) { |
247 | /* | 239 | /* |
@@ -250,8 +242,6 @@ sshkey_names_valid2(const char *names, int allow_wildcard) | |||
250 | * the component is accepted. | 242 | * the component is accepted. |
251 | */ | 243 | */ |
252 | for (kt = keytypes; kt->type != -1; kt++) { | 244 | for (kt = keytypes; kt->type != -1; kt++) { |
253 | if (kt->type == KEY_RSA1) | ||
254 | continue; | ||
255 | if (match_pattern_list(kt->name, | 245 | if (match_pattern_list(kt->name, |
256 | p, 0) != 0) | 246 | p, 0) != 0) |
257 | break; | 247 | break; |
@@ -272,7 +262,6 @@ sshkey_size(const struct sshkey *k) | |||
272 | { | 262 | { |
273 | switch (k->type) { | 263 | switch (k->type) { |
274 | #ifdef WITH_OPENSSL | 264 | #ifdef WITH_OPENSSL |
275 | case KEY_RSA1: | ||
276 | case KEY_RSA: | 265 | case KEY_RSA: |
277 | case KEY_RSA_CERT: | 266 | case KEY_RSA_CERT: |
278 | return BN_num_bits(k->rsa->n); | 267 | return BN_num_bits(k->rsa->n); |
@@ -475,7 +464,6 @@ sshkey_new(int type) | |||
475 | k->ed25519_pk = NULL; | 464 | k->ed25519_pk = NULL; |
476 | switch (k->type) { | 465 | switch (k->type) { |
477 | #ifdef WITH_OPENSSL | 466 | #ifdef WITH_OPENSSL |
478 | case KEY_RSA1: | ||
479 | case KEY_RSA: | 467 | case KEY_RSA: |
480 | case KEY_RSA_CERT: | 468 | case KEY_RSA_CERT: |
481 | if ((rsa = RSA_new()) == NULL || | 469 | if ((rsa = RSA_new()) == NULL || |
@@ -533,7 +521,6 @@ sshkey_add_private(struct sshkey *k) | |||
533 | { | 521 | { |
534 | switch (k->type) { | 522 | switch (k->type) { |
535 | #ifdef WITH_OPENSSL | 523 | #ifdef WITH_OPENSSL |
536 | case KEY_RSA1: | ||
537 | case KEY_RSA: | 524 | case KEY_RSA: |
538 | case KEY_RSA_CERT: | 525 | case KEY_RSA_CERT: |
539 | #define bn_maybe_alloc_failed(p) (p == NULL && (p = BN_new()) == NULL) | 526 | #define bn_maybe_alloc_failed(p) (p == NULL && (p = BN_new()) == NULL) |
@@ -589,7 +576,6 @@ sshkey_free(struct sshkey *k) | |||
589 | return; | 576 | return; |
590 | switch (k->type) { | 577 | switch (k->type) { |
591 | #ifdef WITH_OPENSSL | 578 | #ifdef WITH_OPENSSL |
592 | case KEY_RSA1: | ||
593 | case KEY_RSA: | 579 | case KEY_RSA: |
594 | case KEY_RSA_CERT: | 580 | case KEY_RSA_CERT: |
595 | if (k->rsa != NULL) | 581 | if (k->rsa != NULL) |
@@ -667,7 +653,6 @@ sshkey_equal_public(const struct sshkey *a, const struct sshkey *b) | |||
667 | 653 | ||
668 | switch (a->type) { | 654 | switch (a->type) { |
669 | #ifdef WITH_OPENSSL | 655 | #ifdef WITH_OPENSSL |
670 | case KEY_RSA1: | ||
671 | case KEY_RSA_CERT: | 656 | case KEY_RSA_CERT: |
672 | case KEY_RSA: | 657 | case KEY_RSA: |
673 | return a->rsa != NULL && b->rsa != NULL && | 658 | return a->rsa != NULL && b->rsa != NULL && |
@@ -884,25 +869,7 @@ sshkey_fingerprint_raw(const struct sshkey *k, int dgst_alg, | |||
884 | r = SSH_ERR_INVALID_ARGUMENT; | 869 | r = SSH_ERR_INVALID_ARGUMENT; |
885 | goto out; | 870 | goto out; |
886 | } | 871 | } |
887 | 872 | if ((r = to_blob(k, &blob, &blob_len, 1)) != 0) | |
888 | if (k->type == KEY_RSA1) { | ||
889 | #ifdef WITH_OPENSSL | ||
890 | int nlen = BN_num_bytes(k->rsa->n); | ||
891 | int elen = BN_num_bytes(k->rsa->e); | ||
892 | |||
893 | if (nlen < 0 || elen < 0 || nlen >= INT_MAX - elen) { | ||
894 | r = SSH_ERR_INVALID_FORMAT; | ||
895 | goto out; | ||
896 | } | ||
897 | blob_len = nlen + elen; | ||
898 | if ((blob = malloc(blob_len)) == NULL) { | ||
899 | r = SSH_ERR_ALLOC_FAIL; | ||
900 | goto out; | ||
901 | } | ||
902 | BN_bn2bin(k->rsa->n, blob); | ||
903 | BN_bn2bin(k->rsa->e, blob + nlen); | ||
904 | #endif /* WITH_OPENSSL */ | ||
905 | } else if ((r = to_blob(k, &blob, &blob_len, 1)) != 0) | ||
906 | goto out; | 873 | goto out; |
907 | if ((ret = calloc(1, SSH_DIGEST_MAX_LENGTH)) == NULL) { | 874 | if ((ret = calloc(1, SSH_DIGEST_MAX_LENGTH)) == NULL) { |
908 | r = SSH_ERR_ALLOC_FAIL; | 875 | r = SSH_ERR_ALLOC_FAIL; |
@@ -1194,39 +1161,6 @@ sshkey_fingerprint(const struct sshkey *k, int dgst_alg, | |||
1194 | return retval; | 1161 | return retval; |
1195 | } | 1162 | } |
1196 | 1163 | ||
1197 | #ifdef WITH_SSH1 | ||
1198 | /* | ||
1199 | * Reads a multiple-precision integer in decimal from the buffer, and advances | ||
1200 | * the pointer. The integer must already be initialized. This function is | ||
1201 | * permitted to modify the buffer. This leaves *cpp to point just beyond the | ||
1202 | * last processed character. | ||
1203 | */ | ||
1204 | static int | ||
1205 | read_decimal_bignum(char **cpp, BIGNUM *v) | ||
1206 | { | ||
1207 | char *cp; | ||
1208 | size_t e; | ||
1209 | int skip = 1; /* skip white space */ | ||
1210 | |||
1211 | cp = *cpp; | ||
1212 | while (*cp == ' ' || *cp == '\t') | ||
1213 | cp++; | ||
1214 | e = strspn(cp, "0123456789"); | ||
1215 | if (e == 0) | ||
1216 | return SSH_ERR_INVALID_FORMAT; | ||
1217 | if (e > SSHBUF_MAX_BIGNUM * 3) | ||
1218 | return SSH_ERR_BIGNUM_TOO_LARGE; | ||
1219 | if (cp[e] == '\0') | ||
1220 | skip = 0; | ||
1221 | else if (strchr(" \t\r\n", cp[e]) == NULL) | ||
1222 | return SSH_ERR_INVALID_FORMAT; | ||
1223 | cp[e] = '\0'; | ||
1224 | if (BN_dec2bn(&v, cp) <= 0) | ||
1225 | return SSH_ERR_INVALID_FORMAT; | ||
1226 | *cpp = cp + e + skip; | ||
1227 | return 0; | ||
1228 | } | ||
1229 | #endif /* WITH_SSH1 */ | ||
1230 | 1164 | ||
1231 | /* returns 0 ok, and < 0 error */ | 1165 | /* returns 0 ok, and < 0 error */ |
1232 | int | 1166 | int |
@@ -1237,9 +1171,6 @@ sshkey_read(struct sshkey *ret, char **cpp) | |||
1237 | char *ep, *cp, *space; | 1171 | char *ep, *cp, *space; |
1238 | int r, type, curve_nid = -1; | 1172 | int r, type, curve_nid = -1; |
1239 | struct sshbuf *blob; | 1173 | struct sshbuf *blob; |
1240 | #ifdef WITH_SSH1 | ||
1241 | u_long bits; | ||
1242 | #endif /* WITH_SSH1 */ | ||
1243 | 1174 | ||
1244 | if (ret == NULL) | 1175 | if (ret == NULL) |
1245 | return SSH_ERR_INVALID_ARGUMENT; | 1176 | return SSH_ERR_INVALID_ARGUMENT; |
@@ -1247,25 +1178,6 @@ sshkey_read(struct sshkey *ret, char **cpp) | |||
1247 | cp = *cpp; | 1178 | cp = *cpp; |
1248 | 1179 | ||
1249 | switch (ret->type) { | 1180 | switch (ret->type) { |
1250 | case KEY_RSA1: | ||
1251 | #ifdef WITH_SSH1 | ||
1252 | /* Get number of bits. */ | ||
1253 | bits = strtoul(cp, &ep, 10); | ||
1254 | if (*cp == '\0' || strchr(" \t\r\n", *ep) == NULL || | ||
1255 | bits == 0 || bits > SSHBUF_MAX_BIGNUM * 8) | ||
1256 | return SSH_ERR_INVALID_FORMAT; /* Bad bit count... */ | ||
1257 | /* Get public exponent, public modulus. */ | ||
1258 | if ((r = read_decimal_bignum(&ep, ret->rsa->e)) < 0) | ||
1259 | return r; | ||
1260 | if ((r = read_decimal_bignum(&ep, ret->rsa->n)) < 0) | ||
1261 | return r; | ||
1262 | /* validate the claimed number of bits */ | ||
1263 | if (BN_num_bits(ret->rsa->n) != (int)bits) | ||
1264 | return SSH_ERR_KEY_BITS_MISMATCH; | ||
1265 | *cpp = ep; | ||
1266 | retval = 0; | ||
1267 | #endif /* WITH_SSH1 */ | ||
1268 | break; | ||
1269 | case KEY_UNSPEC: | 1181 | case KEY_UNSPEC: |
1270 | case KEY_RSA: | 1182 | case KEY_RSA: |
1271 | case KEY_DSA: | 1183 | case KEY_DSA: |
@@ -1418,61 +1330,17 @@ sshkey_to_base64(const struct sshkey *key, char **b64p) | |||
1418 | return r; | 1330 | return r; |
1419 | } | 1331 | } |
1420 | 1332 | ||
1421 | static int | 1333 | int |
1422 | sshkey_format_rsa1(const struct sshkey *key, struct sshbuf *b) | ||
1423 | { | ||
1424 | int r = SSH_ERR_INTERNAL_ERROR; | ||
1425 | #ifdef WITH_SSH1 | ||
1426 | u_int bits = 0; | ||
1427 | char *dec_e = NULL, *dec_n = NULL; | ||
1428 | |||
1429 | if (key->rsa == NULL || key->rsa->e == NULL || | ||
1430 | key->rsa->n == NULL) { | ||
1431 | r = SSH_ERR_INVALID_ARGUMENT; | ||
1432 | goto out; | ||
1433 | } | ||
1434 | if ((dec_e = BN_bn2dec(key->rsa->e)) == NULL || | ||
1435 | (dec_n = BN_bn2dec(key->rsa->n)) == NULL) { | ||
1436 | r = SSH_ERR_ALLOC_FAIL; | ||
1437 | goto out; | ||
1438 | } | ||
1439 | /* size of modulus 'n' */ | ||
1440 | if ((bits = BN_num_bits(key->rsa->n)) <= 0) { | ||
1441 | r = SSH_ERR_INVALID_ARGUMENT; | ||
1442 | goto out; | ||
1443 | } | ||
1444 | if ((r = sshbuf_putf(b, "%u %s %s", bits, dec_e, dec_n)) != 0) | ||
1445 | goto out; | ||
1446 | |||
1447 | /* Success */ | ||
1448 | r = 0; | ||
1449 | out: | ||
1450 | if (dec_e != NULL) | ||
1451 | OPENSSL_free(dec_e); | ||
1452 | if (dec_n != NULL) | ||
1453 | OPENSSL_free(dec_n); | ||
1454 | #endif /* WITH_SSH1 */ | ||
1455 | |||
1456 | return r; | ||
1457 | } | ||
1458 | |||
1459 | static int | ||
1460 | sshkey_format_text(const struct sshkey *key, struct sshbuf *b) | 1334 | sshkey_format_text(const struct sshkey *key, struct sshbuf *b) |
1461 | { | 1335 | { |
1462 | int r = SSH_ERR_INTERNAL_ERROR; | 1336 | int r = SSH_ERR_INTERNAL_ERROR; |
1463 | char *uu = NULL; | 1337 | char *uu = NULL; |
1464 | 1338 | ||
1465 | if (key->type == KEY_RSA1) { | 1339 | if ((r = sshkey_to_base64(key, &uu)) != 0) |
1466 | if ((r = sshkey_format_rsa1(key, b)) != 0) | 1340 | goto out; |
1467 | goto out; | 1341 | if ((r = sshbuf_putf(b, "%s %s", |
1468 | } else { | 1342 | sshkey_ssh_name(key), uu)) != 0) |
1469 | /* Unsupported key types handled in sshkey_to_base64() */ | 1343 | goto out; |
1470 | if ((r = sshkey_to_base64(key, &uu)) != 0) | ||
1471 | goto out; | ||
1472 | if ((r = sshbuf_putf(b, "%s %s", | ||
1473 | sshkey_ssh_name(key), uu)) != 0) | ||
1474 | goto out; | ||
1475 | } | ||
1476 | r = 0; | 1344 | r = 0; |
1477 | out: | 1345 | out: |
1478 | free(uu); | 1346 | free(uu); |
@@ -1523,10 +1391,11 @@ rsa_generate_private_key(u_int bits, RSA **rsap) | |||
1523 | BIGNUM *f4 = NULL; | 1391 | BIGNUM *f4 = NULL; |
1524 | int ret = SSH_ERR_INTERNAL_ERROR; | 1392 | int ret = SSH_ERR_INTERNAL_ERROR; |
1525 | 1393 | ||
1526 | if (rsap == NULL || | 1394 | if (rsap == NULL) |
1527 | bits < SSH_RSA_MINIMUM_MODULUS_SIZE || | ||
1528 | bits > SSHBUF_MAX_BIGNUM * 8) | ||
1529 | return SSH_ERR_INVALID_ARGUMENT; | 1395 | return SSH_ERR_INVALID_ARGUMENT; |
1396 | if (bits < SSH_RSA_MINIMUM_MODULUS_SIZE || | ||
1397 | bits > SSHBUF_MAX_BIGNUM * 8) | ||
1398 | return SSH_ERR_KEY_LENGTH; | ||
1530 | *rsap = NULL; | 1399 | *rsap = NULL; |
1531 | if ((private = RSA_new()) == NULL || (f4 = BN_new()) == NULL) { | 1400 | if ((private = RSA_new()) == NULL || (f4 = BN_new()) == NULL) { |
1532 | ret = SSH_ERR_ALLOC_FAIL; | 1401 | ret = SSH_ERR_ALLOC_FAIL; |
@@ -1554,8 +1423,10 @@ dsa_generate_private_key(u_int bits, DSA **dsap) | |||
1554 | DSA *private; | 1423 | DSA *private; |
1555 | int ret = SSH_ERR_INTERNAL_ERROR; | 1424 | int ret = SSH_ERR_INTERNAL_ERROR; |
1556 | 1425 | ||
1557 | if (dsap == NULL || bits != 1024) | 1426 | if (dsap == NULL) |
1558 | return SSH_ERR_INVALID_ARGUMENT; | 1427 | return SSH_ERR_INVALID_ARGUMENT; |
1428 | if (bits != 1024) | ||
1429 | return SSH_ERR_KEY_LENGTH; | ||
1559 | if ((private = DSA_new()) == NULL) { | 1430 | if ((private = DSA_new()) == NULL) { |
1560 | ret = SSH_ERR_ALLOC_FAIL; | 1431 | ret = SSH_ERR_ALLOC_FAIL; |
1561 | goto out; | 1432 | goto out; |
@@ -1632,9 +1503,10 @@ ecdsa_generate_private_key(u_int bits, int *nid, EC_KEY **ecdsap) | |||
1632 | EC_KEY *private; | 1503 | EC_KEY *private; |
1633 | int ret = SSH_ERR_INTERNAL_ERROR; | 1504 | int ret = SSH_ERR_INTERNAL_ERROR; |
1634 | 1505 | ||
1635 | if (nid == NULL || ecdsap == NULL || | 1506 | if (nid == NULL || ecdsap == NULL) |
1636 | (*nid = sshkey_ecdsa_bits_to_nid(bits)) == -1) | ||
1637 | return SSH_ERR_INVALID_ARGUMENT; | 1507 | return SSH_ERR_INVALID_ARGUMENT; |
1508 | if ((*nid = sshkey_ecdsa_bits_to_nid(bits)) == -1) | ||
1509 | return SSH_ERR_KEY_LENGTH; | ||
1638 | *ecdsap = NULL; | 1510 | *ecdsap = NULL; |
1639 | if ((private = EC_KEY_new_by_curve_name(*nid)) == NULL) { | 1511 | if ((private = EC_KEY_new_by_curve_name(*nid)) == NULL) { |
1640 | ret = SSH_ERR_ALLOC_FAIL; | 1512 | ret = SSH_ERR_ALLOC_FAIL; |
@@ -1688,7 +1560,6 @@ sshkey_generate(int type, u_int bits, struct sshkey **keyp) | |||
1688 | break; | 1560 | break; |
1689 | # endif /* OPENSSL_HAS_ECC */ | 1561 | # endif /* OPENSSL_HAS_ECC */ |
1690 | case KEY_RSA: | 1562 | case KEY_RSA: |
1691 | case KEY_RSA1: | ||
1692 | ret = rsa_generate_private_key(bits, &k->rsa); | 1563 | ret = rsa_generate_private_key(bits, &k->rsa); |
1693 | break; | 1564 | break; |
1694 | #endif /* WITH_OPENSSL */ | 1565 | #endif /* WITH_OPENSSL */ |
@@ -1799,7 +1670,6 @@ sshkey_from_private(const struct sshkey *k, struct sshkey **pkp) | |||
1799 | break; | 1670 | break; |
1800 | # endif /* OPENSSL_HAS_ECC */ | 1671 | # endif /* OPENSSL_HAS_ECC */ |
1801 | case KEY_RSA: | 1672 | case KEY_RSA: |
1802 | case KEY_RSA1: | ||
1803 | case KEY_RSA_CERT: | 1673 | case KEY_RSA_CERT: |
1804 | if ((n = sshkey_new(k->type)) == NULL) | 1674 | if ((n = sshkey_new(k->type)) == NULL) |
1805 | return SSH_ERR_ALLOC_FAIL; | 1675 | return SSH_ERR_ALLOC_FAIL; |
@@ -1893,8 +1763,9 @@ cert_parse(struct sshbuf *b, struct sshkey *key, struct sshbuf *certbuf) | |||
1893 | goto out; | 1763 | goto out; |
1894 | } | 1764 | } |
1895 | oprincipals = key->cert->principals; | 1765 | oprincipals = key->cert->principals; |
1896 | key->cert->principals = reallocarray(key->cert->principals, | 1766 | key->cert->principals = recallocarray(key->cert->principals, |
1897 | key->cert->nprincipals + 1, sizeof(*key->cert->principals)); | 1767 | key->cert->nprincipals, key->cert->nprincipals + 1, |
1768 | sizeof(*key->cert->principals)); | ||
1898 | if (key->cert->principals == NULL) { | 1769 | if (key->cert->principals == NULL) { |
1899 | free(principal); | 1770 | free(principal); |
1900 | key->cert->principals = oprincipals; | 1771 | key->cert->principals = oprincipals; |
@@ -2009,6 +1880,10 @@ sshkey_from_blob_internal(struct sshbuf *b, struct sshkey **keyp, | |||
2009 | ret = SSH_ERR_INVALID_FORMAT; | 1880 | ret = SSH_ERR_INVALID_FORMAT; |
2010 | goto out; | 1881 | goto out; |
2011 | } | 1882 | } |
1883 | if (BN_num_bits(key->rsa->n) < SSH_RSA_MINIMUM_MODULUS_SIZE) { | ||
1884 | ret = SSH_ERR_KEY_LENGTH; | ||
1885 | goto out; | ||
1886 | } | ||
2012 | #ifdef DEBUG_PK | 1887 | #ifdef DEBUG_PK |
2013 | RSA_print_fp(stderr, key->rsa, 8); | 1888 | RSA_print_fp(stderr, key->rsa, 8); |
2014 | #endif | 1889 | #endif |
@@ -2111,11 +1986,6 @@ sshkey_from_blob_internal(struct sshbuf *b, struct sshkey **keyp, | |||
2111 | pk = NULL; | 1986 | pk = NULL; |
2112 | break; | 1987 | break; |
2113 | case KEY_UNSPEC: | 1988 | case KEY_UNSPEC: |
2114 | if ((key = sshkey_new(type)) == NULL) { | ||
2115 | ret = SSH_ERR_ALLOC_FAIL; | ||
2116 | goto out; | ||
2117 | } | ||
2118 | break; | ||
2119 | default: | 1989 | default: |
2120 | ret = SSH_ERR_KEY_TYPE_UNKNOWN; | 1990 | ret = SSH_ERR_KEY_TYPE_UNKNOWN; |
2121 | goto out; | 1991 | goto out; |
@@ -2269,7 +2139,6 @@ sshkey_demote(const struct sshkey *k, struct sshkey **dkp) | |||
2269 | if ((ret = sshkey_cert_copy(k, pk)) != 0) | 2139 | if ((ret = sshkey_cert_copy(k, pk)) != 0) |
2270 | goto fail; | 2140 | goto fail; |
2271 | /* FALLTHROUGH */ | 2141 | /* FALLTHROUGH */ |
2272 | case KEY_RSA1: | ||
2273 | case KEY_RSA: | 2142 | case KEY_RSA: |
2274 | if ((pk->rsa = RSA_new()) == NULL || | 2143 | if ((pk->rsa = RSA_new()) == NULL || |
2275 | (pk->rsa->e = BN_dup(k->rsa->e)) == NULL || | 2144 | (pk->rsa->e = BN_dup(k->rsa->e)) == NULL || |
@@ -2378,7 +2247,8 @@ sshkey_drop_cert(struct sshkey *k) | |||
2378 | 2247 | ||
2379 | /* Sign a certified key, (re-)generating the signed certblob. */ | 2248 | /* Sign a certified key, (re-)generating the signed certblob. */ |
2380 | int | 2249 | int |
2381 | sshkey_certify(struct sshkey *k, struct sshkey *ca, const char *alg) | 2250 | sshkey_certify_custom(struct sshkey *k, struct sshkey *ca, const char *alg, |
2251 | sshkey_certify_signer *signer, void *signer_ctx) | ||
2382 | { | 2252 | { |
2383 | struct sshbuf *principals = NULL; | 2253 | struct sshbuf *principals = NULL; |
2384 | u_char *ca_blob = NULL, *sig_blob = NULL, nonce[32]; | 2254 | u_char *ca_blob = NULL, *sig_blob = NULL, nonce[32]; |
@@ -2467,8 +2337,8 @@ sshkey_certify(struct sshkey *k, struct sshkey *ca, const char *alg) | |||
2467 | goto out; | 2337 | goto out; |
2468 | 2338 | ||
2469 | /* Sign the whole mess */ | 2339 | /* Sign the whole mess */ |
2470 | if ((ret = sshkey_sign(ca, &sig_blob, &sig_len, sshbuf_ptr(cert), | 2340 | if ((ret = signer(ca, &sig_blob, &sig_len, sshbuf_ptr(cert), |
2471 | sshbuf_len(cert), alg, 0)) != 0) | 2341 | sshbuf_len(cert), alg, 0, signer_ctx)) != 0) |
2472 | goto out; | 2342 | goto out; |
2473 | 2343 | ||
2474 | /* Append signature and we are done */ | 2344 | /* Append signature and we are done */ |
@@ -2484,6 +2354,22 @@ sshkey_certify(struct sshkey *k, struct sshkey *ca, const char *alg) | |||
2484 | return ret; | 2354 | return ret; |
2485 | } | 2355 | } |
2486 | 2356 | ||
2357 | static int | ||
2358 | default_key_sign(const struct sshkey *key, u_char **sigp, size_t *lenp, | ||
2359 | const u_char *data, size_t datalen, | ||
2360 | const char *alg, u_int compat, void *ctx) | ||
2361 | { | ||
2362 | if (ctx != NULL) | ||
2363 | return SSH_ERR_INVALID_ARGUMENT; | ||
2364 | return sshkey_sign(key, sigp, lenp, data, datalen, alg, compat); | ||
2365 | } | ||
2366 | |||
2367 | int | ||
2368 | sshkey_certify(struct sshkey *k, struct sshkey *ca, const char *alg) | ||
2369 | { | ||
2370 | return sshkey_certify_custom(k, ca, alg, default_key_sign, NULL); | ||
2371 | } | ||
2372 | |||
2487 | int | 2373 | int |
2488 | sshkey_cert_check_authority(const struct sshkey *k, | 2374 | sshkey_cert_check_authority(const struct sshkey *k, |
2489 | int want_host, int require_principal, | 2375 | int want_host, int require_principal, |
@@ -2775,8 +2661,12 @@ sshkey_private_deserialize(struct sshbuf *buf, struct sshkey **kp) | |||
2775 | (r = sshbuf_get_bignum2(buf, k->rsa->iqmp)) != 0 || | 2661 | (r = sshbuf_get_bignum2(buf, k->rsa->iqmp)) != 0 || |
2776 | (r = sshbuf_get_bignum2(buf, k->rsa->p)) != 0 || | 2662 | (r = sshbuf_get_bignum2(buf, k->rsa->p)) != 0 || |
2777 | (r = sshbuf_get_bignum2(buf, k->rsa->q)) != 0 || | 2663 | (r = sshbuf_get_bignum2(buf, k->rsa->q)) != 0 || |
2778 | (r = rsa_generate_additional_parameters(k->rsa)) != 0) | 2664 | (r = ssh_rsa_generate_additional_parameters(k)) != 0) |
2779 | goto out; | 2665 | goto out; |
2666 | if (BN_num_bits(k->rsa->n) < SSH_RSA_MINIMUM_MODULUS_SIZE) { | ||
2667 | r = SSH_ERR_KEY_LENGTH; | ||
2668 | goto out; | ||
2669 | } | ||
2780 | break; | 2670 | break; |
2781 | case KEY_RSA_CERT: | 2671 | case KEY_RSA_CERT: |
2782 | if ((r = sshkey_froms(buf, &k)) != 0 || | 2672 | if ((r = sshkey_froms(buf, &k)) != 0 || |
@@ -2785,8 +2675,12 @@ sshkey_private_deserialize(struct sshbuf *buf, struct sshkey **kp) | |||
2785 | (r = sshbuf_get_bignum2(buf, k->rsa->iqmp)) != 0 || | 2675 | (r = sshbuf_get_bignum2(buf, k->rsa->iqmp)) != 0 || |
2786 | (r = sshbuf_get_bignum2(buf, k->rsa->p)) != 0 || | 2676 | (r = sshbuf_get_bignum2(buf, k->rsa->p)) != 0 || |
2787 | (r = sshbuf_get_bignum2(buf, k->rsa->q)) != 0 || | 2677 | (r = sshbuf_get_bignum2(buf, k->rsa->q)) != 0 || |
2788 | (r = rsa_generate_additional_parameters(k->rsa)) != 0) | 2678 | (r = ssh_rsa_generate_additional_parameters(k)) != 0) |
2789 | goto out; | 2679 | goto out; |
2680 | if (BN_num_bits(k->rsa->n) < SSH_RSA_MINIMUM_MODULUS_SIZE) { | ||
2681 | r = SSH_ERR_KEY_LENGTH; | ||
2682 | goto out; | ||
2683 | } | ||
2790 | break; | 2684 | break; |
2791 | #endif /* WITH_OPENSSL */ | 2685 | #endif /* WITH_OPENSSL */ |
2792 | case KEY_ED25519: | 2686 | case KEY_ED25519: |
@@ -2828,7 +2722,6 @@ sshkey_private_deserialize(struct sshbuf *buf, struct sshkey **kp) | |||
2828 | switch (k->type) { | 2722 | switch (k->type) { |
2829 | case KEY_RSA: | 2723 | case KEY_RSA: |
2830 | case KEY_RSA_CERT: | 2724 | case KEY_RSA_CERT: |
2831 | case KEY_RSA1: | ||
2832 | if (RSA_blinding_on(k->rsa, NULL) != 1) { | 2725 | if (RSA_blinding_on(k->rsa, NULL) != 1) { |
2833 | r = SSH_ERR_LIBCRYPTO_ERROR; | 2726 | r = SSH_ERR_LIBCRYPTO_ERROR; |
2834 | goto out; | 2727 | goto out; |
@@ -3057,12 +2950,8 @@ sshkey_private_to_blob2(const struct sshkey *prv, struct sshbuf *blob, | |||
3057 | kdfname = "none"; | 2950 | kdfname = "none"; |
3058 | } else if (ciphername == NULL) | 2951 | } else if (ciphername == NULL) |
3059 | ciphername = DEFAULT_CIPHERNAME; | 2952 | ciphername = DEFAULT_CIPHERNAME; |
3060 | else if (cipher_number(ciphername) != SSH_CIPHER_SSH2) { | ||
3061 | r = SSH_ERR_INVALID_ARGUMENT; | ||
3062 | goto out; | ||
3063 | } | ||
3064 | if ((cipher = cipher_by_name(ciphername)) == NULL) { | 2953 | if ((cipher = cipher_by_name(ciphername)) == NULL) { |
3065 | r = SSH_ERR_INTERNAL_ERROR; | 2954 | r = SSH_ERR_INVALID_ARGUMENT; |
3066 | goto out; | 2955 | goto out; |
3067 | } | 2956 | } |
3068 | 2957 | ||
@@ -3404,105 +3293,6 @@ sshkey_parse_private2(struct sshbuf *blob, int type, const char *passphrase, | |||
3404 | return r; | 3293 | return r; |
3405 | } | 3294 | } |
3406 | 3295 | ||
3407 | #if WITH_SSH1 | ||
3408 | /* | ||
3409 | * Serialises the authentication (private) key to a blob, encrypting it with | ||
3410 | * passphrase. The identification of the blob (lowest 64 bits of n) will | ||
3411 | * precede the key to provide identification of the key without needing a | ||
3412 | * passphrase. | ||
3413 | */ | ||
3414 | static int | ||
3415 | sshkey_private_rsa1_to_blob(struct sshkey *key, struct sshbuf *blob, | ||
3416 | const char *passphrase, const char *comment) | ||
3417 | { | ||
3418 | struct sshbuf *buffer = NULL, *encrypted = NULL; | ||
3419 | u_char buf[8]; | ||
3420 | int r, cipher_num; | ||
3421 | struct sshcipher_ctx *ciphercontext = NULL; | ||
3422 | const struct sshcipher *cipher; | ||
3423 | u_char *cp; | ||
3424 | |||
3425 | /* | ||
3426 | * If the passphrase is empty, use SSH_CIPHER_NONE to ease converting | ||
3427 | * to another cipher; otherwise use SSH_AUTHFILE_CIPHER. | ||
3428 | */ | ||
3429 | cipher_num = (strcmp(passphrase, "") == 0) ? | ||
3430 | SSH_CIPHER_NONE : SSH_CIPHER_3DES; | ||
3431 | if ((cipher = cipher_by_number(cipher_num)) == NULL) | ||
3432 | return SSH_ERR_INTERNAL_ERROR; | ||
3433 | |||
3434 | /* This buffer is used to build the secret part of the private key. */ | ||
3435 | if ((buffer = sshbuf_new()) == NULL) | ||
3436 | return SSH_ERR_ALLOC_FAIL; | ||
3437 | |||
3438 | /* Put checkbytes for checking passphrase validity. */ | ||
3439 | if ((r = sshbuf_reserve(buffer, 4, &cp)) != 0) | ||
3440 | goto out; | ||
3441 | arc4random_buf(cp, 2); | ||
3442 | memcpy(cp + 2, cp, 2); | ||
3443 | |||
3444 | /* | ||
3445 | * Store the private key (n and e will not be stored because they | ||
3446 | * will be stored in plain text, and storing them also in encrypted | ||
3447 | * format would just give known plaintext). | ||
3448 | * Note: q and p are stored in reverse order to SSL. | ||
3449 | */ | ||
3450 | if ((r = sshbuf_put_bignum1(buffer, key->rsa->d)) != 0 || | ||
3451 | (r = sshbuf_put_bignum1(buffer, key->rsa->iqmp)) != 0 || | ||
3452 | (r = sshbuf_put_bignum1(buffer, key->rsa->q)) != 0 || | ||
3453 | (r = sshbuf_put_bignum1(buffer, key->rsa->p)) != 0) | ||
3454 | goto out; | ||
3455 | |||
3456 | /* Pad the part to be encrypted to a size that is a multiple of 8. */ | ||
3457 | explicit_bzero(buf, 8); | ||
3458 | if ((r = sshbuf_put(buffer, buf, 8 - (sshbuf_len(buffer) % 8))) != 0) | ||
3459 | goto out; | ||
3460 | |||
3461 | /* This buffer will be used to contain the data in the file. */ | ||
3462 | if ((encrypted = sshbuf_new()) == NULL) { | ||
3463 | r = SSH_ERR_ALLOC_FAIL; | ||
3464 | goto out; | ||
3465 | } | ||
3466 | |||
3467 | /* First store keyfile id string. */ | ||
3468 | if ((r = sshbuf_put(encrypted, LEGACY_BEGIN, | ||
3469 | sizeof(LEGACY_BEGIN))) != 0) | ||
3470 | goto out; | ||
3471 | |||
3472 | /* Store cipher type and "reserved" field. */ | ||
3473 | if ((r = sshbuf_put_u8(encrypted, cipher_num)) != 0 || | ||
3474 | (r = sshbuf_put_u32(encrypted, 0)) != 0) | ||
3475 | goto out; | ||
3476 | |||
3477 | /* Store public key. This will be in plain text. */ | ||
3478 | if ((r = sshbuf_put_u32(encrypted, BN_num_bits(key->rsa->n))) != 0 || | ||
3479 | (r = sshbuf_put_bignum1(encrypted, key->rsa->n)) != 0 || | ||
3480 | (r = sshbuf_put_bignum1(encrypted, key->rsa->e)) != 0 || | ||
3481 | (r = sshbuf_put_cstring(encrypted, comment)) != 0) | ||
3482 | goto out; | ||
3483 | |||
3484 | /* Allocate space for the private part of the key in the buffer. */ | ||
3485 | if ((r = sshbuf_reserve(encrypted, sshbuf_len(buffer), &cp)) != 0) | ||
3486 | goto out; | ||
3487 | |||
3488 | if ((r = cipher_set_key_string(&ciphercontext, cipher, passphrase, | ||
3489 | CIPHER_ENCRYPT)) != 0) | ||
3490 | goto out; | ||
3491 | if ((r = cipher_crypt(ciphercontext, 0, cp, | ||
3492 | sshbuf_ptr(buffer), sshbuf_len(buffer), 0, 0)) != 0) | ||
3493 | goto out; | ||
3494 | |||
3495 | r = sshbuf_putb(blob, encrypted); | ||
3496 | |||
3497 | out: | ||
3498 | cipher_free(ciphercontext); | ||
3499 | explicit_bzero(buf, sizeof(buf)); | ||
3500 | sshbuf_free(buffer); | ||
3501 | sshbuf_free(encrypted); | ||
3502 | |||
3503 | return r; | ||
3504 | } | ||
3505 | #endif /* WITH_SSH1 */ | ||
3506 | 3296 | ||
3507 | #ifdef WITH_OPENSSL | 3297 | #ifdef WITH_OPENSSL |
3508 | /* convert SSH v2 key in OpenSSL PEM format */ | 3298 | /* convert SSH v2 key in OpenSSL PEM format */ |
@@ -3513,11 +3303,7 @@ sshkey_private_pem_to_blob(struct sshkey *key, struct sshbuf *blob, | |||
3513 | int success, r; | 3303 | int success, r; |
3514 | int blen, len = strlen(_passphrase); | 3304 | int blen, len = strlen(_passphrase); |
3515 | u_char *passphrase = (len > 0) ? (u_char *)_passphrase : NULL; | 3305 | u_char *passphrase = (len > 0) ? (u_char *)_passphrase : NULL; |
3516 | #if (OPENSSL_VERSION_NUMBER < 0x00907000L) | 3306 | const EVP_CIPHER *cipher = (len > 0) ? EVP_aes_128_cbc() : NULL; |
3517 | const EVP_CIPHER *cipher = (len > 0) ? EVP_des_ede3_cbc() : NULL; | ||
3518 | #else | ||
3519 | const EVP_CIPHER *cipher = (len > 0) ? EVP_aes_128_cbc() : NULL; | ||
3520 | #endif | ||
3521 | const u_char *bptr; | 3307 | const u_char *bptr; |
3522 | BIO *bio = NULL; | 3308 | BIO *bio = NULL; |
3523 | 3309 | ||
@@ -3569,11 +3355,6 @@ sshkey_private_to_fileblob(struct sshkey *key, struct sshbuf *blob, | |||
3569 | int force_new_format, const char *new_format_cipher, int new_format_rounds) | 3355 | int force_new_format, const char *new_format_cipher, int new_format_rounds) |
3570 | { | 3356 | { |
3571 | switch (key->type) { | 3357 | switch (key->type) { |
3572 | #ifdef WITH_SSH1 | ||
3573 | case KEY_RSA1: | ||
3574 | return sshkey_private_rsa1_to_blob(key, blob, | ||
3575 | passphrase, comment); | ||
3576 | #endif /* WITH_SSH1 */ | ||
3577 | #ifdef WITH_OPENSSL | 3358 | #ifdef WITH_OPENSSL |
3578 | case KEY_DSA: | 3359 | case KEY_DSA: |
3579 | case KEY_ECDSA: | 3360 | case KEY_ECDSA: |
@@ -3593,184 +3374,66 @@ sshkey_private_to_fileblob(struct sshkey *key, struct sshbuf *blob, | |||
3593 | } | 3374 | } |
3594 | } | 3375 | } |
3595 | 3376 | ||
3596 | #ifdef WITH_SSH1 | ||
3597 | /* | ||
3598 | * Parse the public, unencrypted portion of a RSA1 key. | ||
3599 | */ | ||
3600 | int | ||
3601 | sshkey_parse_public_rsa1_fileblob(struct sshbuf *blob, | ||
3602 | struct sshkey **keyp, char **commentp) | ||
3603 | { | ||
3604 | int r; | ||
3605 | struct sshkey *pub = NULL; | ||
3606 | struct sshbuf *copy = NULL; | ||
3607 | |||
3608 | if (keyp != NULL) | ||
3609 | *keyp = NULL; | ||
3610 | if (commentp != NULL) | ||
3611 | *commentp = NULL; | ||
3612 | |||
3613 | /* Check that it is at least big enough to contain the ID string. */ | ||
3614 | if (sshbuf_len(blob) < sizeof(LEGACY_BEGIN)) | ||
3615 | return SSH_ERR_INVALID_FORMAT; | ||
3616 | 3377 | ||
3617 | /* | 3378 | #ifdef WITH_OPENSSL |
3618 | * Make sure it begins with the id string. Consume the id string | 3379 | static int |
3619 | * from the buffer. | 3380 | translate_libcrypto_error(unsigned long pem_err) |
3620 | */ | 3381 | { |
3621 | if (memcmp(sshbuf_ptr(blob), LEGACY_BEGIN, sizeof(LEGACY_BEGIN)) != 0) | 3382 | int pem_reason = ERR_GET_REASON(pem_err); |
3383 | |||
3384 | switch (ERR_GET_LIB(pem_err)) { | ||
3385 | case ERR_LIB_PEM: | ||
3386 | switch (pem_reason) { | ||
3387 | case PEM_R_BAD_PASSWORD_READ: | ||
3388 | case PEM_R_PROBLEMS_GETTING_PASSWORD: | ||
3389 | case PEM_R_BAD_DECRYPT: | ||
3390 | return SSH_ERR_KEY_WRONG_PASSPHRASE; | ||
3391 | default: | ||
3392 | return SSH_ERR_INVALID_FORMAT; | ||
3393 | } | ||
3394 | case ERR_LIB_EVP: | ||
3395 | switch (pem_reason) { | ||
3396 | case EVP_R_BAD_DECRYPT: | ||
3397 | return SSH_ERR_KEY_WRONG_PASSPHRASE; | ||
3398 | case EVP_R_BN_DECODE_ERROR: | ||
3399 | case EVP_R_DECODE_ERROR: | ||
3400 | #ifdef EVP_R_PRIVATE_KEY_DECODE_ERROR | ||
3401 | case EVP_R_PRIVATE_KEY_DECODE_ERROR: | ||
3402 | #endif | ||
3403 | return SSH_ERR_INVALID_FORMAT; | ||
3404 | default: | ||
3405 | return SSH_ERR_LIBCRYPTO_ERROR; | ||
3406 | } | ||
3407 | case ERR_LIB_ASN1: | ||
3622 | return SSH_ERR_INVALID_FORMAT; | 3408 | return SSH_ERR_INVALID_FORMAT; |
3623 | /* Make a working copy of the keyblob and skip past the magic */ | ||
3624 | if ((copy = sshbuf_fromb(blob)) == NULL) | ||
3625 | return SSH_ERR_ALLOC_FAIL; | ||
3626 | if ((r = sshbuf_consume(copy, sizeof(LEGACY_BEGIN))) != 0) | ||
3627 | goto out; | ||
3628 | |||
3629 | /* Skip cipher type, reserved data and key bits. */ | ||
3630 | if ((r = sshbuf_get_u8(copy, NULL)) != 0 || /* cipher type */ | ||
3631 | (r = sshbuf_get_u32(copy, NULL)) != 0 || /* reserved */ | ||
3632 | (r = sshbuf_get_u32(copy, NULL)) != 0) /* key bits */ | ||
3633 | goto out; | ||
3634 | |||
3635 | /* Read the public key from the buffer. */ | ||
3636 | if ((pub = sshkey_new(KEY_RSA1)) == NULL || | ||
3637 | (r = sshbuf_get_bignum1(copy, pub->rsa->n)) != 0 || | ||
3638 | (r = sshbuf_get_bignum1(copy, pub->rsa->e)) != 0) | ||
3639 | goto out; | ||
3640 | |||
3641 | /* Finally, the comment */ | ||
3642 | if ((r = sshbuf_get_string(copy, (u_char**)commentp, NULL)) != 0) | ||
3643 | goto out; | ||
3644 | |||
3645 | /* The encrypted private part is not parsed by this function. */ | ||
3646 | |||
3647 | r = 0; | ||
3648 | if (keyp != NULL) { | ||
3649 | *keyp = pub; | ||
3650 | pub = NULL; | ||
3651 | } | 3409 | } |
3652 | out: | 3410 | return SSH_ERR_LIBCRYPTO_ERROR; |
3653 | sshbuf_free(copy); | ||
3654 | sshkey_free(pub); | ||
3655 | return r; | ||
3656 | } | 3411 | } |
3657 | 3412 | ||
3658 | static int | 3413 | static void |
3659 | sshkey_parse_private_rsa1(struct sshbuf *blob, const char *passphrase, | 3414 | clear_libcrypto_errors(void) |
3660 | struct sshkey **keyp, char **commentp) | ||
3661 | { | 3415 | { |
3662 | int r; | 3416 | while (ERR_get_error() != 0) |
3663 | u_int16_t check1, check2; | 3417 | ; |
3664 | u_int8_t cipher_type; | 3418 | } |
3665 | struct sshbuf *decrypted = NULL, *copy = NULL; | ||
3666 | u_char *cp; | ||
3667 | char *comment = NULL; | ||
3668 | struct sshcipher_ctx *ciphercontext = NULL; | ||
3669 | const struct sshcipher *cipher; | ||
3670 | struct sshkey *prv = NULL; | ||
3671 | |||
3672 | if (keyp != NULL) | ||
3673 | *keyp = NULL; | ||
3674 | if (commentp != NULL) | ||
3675 | *commentp = NULL; | ||
3676 | |||
3677 | /* Check that it is at least big enough to contain the ID string. */ | ||
3678 | if (sshbuf_len(blob) < sizeof(LEGACY_BEGIN)) | ||
3679 | return SSH_ERR_INVALID_FORMAT; | ||
3680 | 3419 | ||
3420 | /* | ||
3421 | * Translate OpenSSL error codes to determine whether | ||
3422 | * passphrase is required/incorrect. | ||
3423 | */ | ||
3424 | static int | ||
3425 | convert_libcrypto_error(void) | ||
3426 | { | ||
3681 | /* | 3427 | /* |
3682 | * Make sure it begins with the id string. Consume the id string | 3428 | * Some password errors are reported at the beginning |
3683 | * from the buffer. | 3429 | * of the error queue. |
3684 | */ | 3430 | */ |
3685 | if (memcmp(sshbuf_ptr(blob), LEGACY_BEGIN, sizeof(LEGACY_BEGIN)) != 0) | 3431 | if (translate_libcrypto_error(ERR_peek_error()) == |
3686 | return SSH_ERR_INVALID_FORMAT; | 3432 | SSH_ERR_KEY_WRONG_PASSPHRASE) |
3687 | 3433 | return SSH_ERR_KEY_WRONG_PASSPHRASE; | |
3688 | if ((prv = sshkey_new_private(KEY_RSA1)) == NULL) { | 3434 | return translate_libcrypto_error(ERR_peek_last_error()); |
3689 | r = SSH_ERR_ALLOC_FAIL; | ||
3690 | goto out; | ||
3691 | } | ||
3692 | if ((copy = sshbuf_fromb(blob)) == NULL || | ||
3693 | (decrypted = sshbuf_new()) == NULL) { | ||
3694 | r = SSH_ERR_ALLOC_FAIL; | ||
3695 | goto out; | ||
3696 | } | ||
3697 | if ((r = sshbuf_consume(copy, sizeof(LEGACY_BEGIN))) != 0) | ||
3698 | goto out; | ||
3699 | |||
3700 | /* Read cipher type. */ | ||
3701 | if ((r = sshbuf_get_u8(copy, &cipher_type)) != 0 || | ||
3702 | (r = sshbuf_get_u32(copy, NULL)) != 0) /* reserved */ | ||
3703 | goto out; | ||
3704 | |||
3705 | /* Read the public key and comment from the buffer. */ | ||
3706 | if ((r = sshbuf_get_u32(copy, NULL)) != 0 || /* key bits */ | ||
3707 | (r = sshbuf_get_bignum1(copy, prv->rsa->n)) != 0 || | ||
3708 | (r = sshbuf_get_bignum1(copy, prv->rsa->e)) != 0 || | ||
3709 | (r = sshbuf_get_cstring(copy, &comment, NULL)) != 0) | ||
3710 | goto out; | ||
3711 | |||
3712 | /* Check that it is a supported cipher. */ | ||
3713 | cipher = cipher_by_number(cipher_type); | ||
3714 | if (cipher == NULL) { | ||
3715 | r = SSH_ERR_KEY_UNKNOWN_CIPHER; | ||
3716 | goto out; | ||
3717 | } | ||
3718 | /* Initialize space for decrypted data. */ | ||
3719 | if ((r = sshbuf_reserve(decrypted, sshbuf_len(copy), &cp)) != 0) | ||
3720 | goto out; | ||
3721 | |||
3722 | /* Rest of the buffer is encrypted. Decrypt it using the passphrase. */ | ||
3723 | if ((r = cipher_set_key_string(&ciphercontext, cipher, passphrase, | ||
3724 | CIPHER_DECRYPT)) != 0) | ||
3725 | goto out; | ||
3726 | if ((r = cipher_crypt(ciphercontext, 0, cp, | ||
3727 | sshbuf_ptr(copy), sshbuf_len(copy), 0, 0)) != 0) | ||
3728 | goto out; | ||
3729 | |||
3730 | if ((r = sshbuf_get_u16(decrypted, &check1)) != 0 || | ||
3731 | (r = sshbuf_get_u16(decrypted, &check2)) != 0) | ||
3732 | goto out; | ||
3733 | if (check1 != check2) { | ||
3734 | r = SSH_ERR_KEY_WRONG_PASSPHRASE; | ||
3735 | goto out; | ||
3736 | } | ||
3737 | |||
3738 | /* Read the rest of the private key. */ | ||
3739 | if ((r = sshbuf_get_bignum1(decrypted, prv->rsa->d)) != 0 || | ||
3740 | (r = sshbuf_get_bignum1(decrypted, prv->rsa->iqmp)) != 0 || | ||
3741 | (r = sshbuf_get_bignum1(decrypted, prv->rsa->q)) != 0 || | ||
3742 | (r = sshbuf_get_bignum1(decrypted, prv->rsa->p)) != 0) | ||
3743 | goto out; | ||
3744 | |||
3745 | /* calculate p-1 and q-1 */ | ||
3746 | if ((r = rsa_generate_additional_parameters(prv->rsa)) != 0) | ||
3747 | goto out; | ||
3748 | |||
3749 | /* enable blinding */ | ||
3750 | if (RSA_blinding_on(prv->rsa, NULL) != 1) { | ||
3751 | r = SSH_ERR_LIBCRYPTO_ERROR; | ||
3752 | goto out; | ||
3753 | } | ||
3754 | r = 0; | ||
3755 | if (keyp != NULL) { | ||
3756 | *keyp = prv; | ||
3757 | prv = NULL; | ||
3758 | } | ||
3759 | if (commentp != NULL) { | ||
3760 | *commentp = comment; | ||
3761 | comment = NULL; | ||
3762 | } | ||
3763 | out: | ||
3764 | cipher_free(ciphercontext); | ||
3765 | free(comment); | ||
3766 | sshkey_free(prv); | ||
3767 | sshbuf_free(copy); | ||
3768 | sshbuf_free(decrypted); | ||
3769 | return r; | ||
3770 | } | 3435 | } |
3771 | #endif /* WITH_SSH1 */ | ||
3772 | 3436 | ||
3773 | #ifdef WITH_OPENSSL | ||
3774 | static int | 3437 | static int |
3775 | sshkey_parse_private_pem_fileblob(struct sshbuf *blob, int type, | 3438 | sshkey_parse_private_pem_fileblob(struct sshbuf *blob, int type, |
3776 | const char *passphrase, struct sshkey **keyp) | 3439 | const char *passphrase, struct sshkey **keyp) |
@@ -3791,48 +3454,10 @@ sshkey_parse_private_pem_fileblob(struct sshbuf *blob, int type, | |||
3791 | goto out; | 3454 | goto out; |
3792 | } | 3455 | } |
3793 | 3456 | ||
3457 | clear_libcrypto_errors(); | ||
3794 | if ((pk = PEM_read_bio_PrivateKey(bio, NULL, NULL, | 3458 | if ((pk = PEM_read_bio_PrivateKey(bio, NULL, NULL, |
3795 | (char *)passphrase)) == NULL) { | 3459 | (char *)passphrase)) == NULL) { |
3796 | unsigned long pem_err = ERR_peek_last_error(); | 3460 | r = convert_libcrypto_error(); |
3797 | int pem_reason = ERR_GET_REASON(pem_err); | ||
3798 | |||
3799 | /* | ||
3800 | * Translate OpenSSL error codes to determine whether | ||
3801 | * passphrase is required/incorrect. | ||
3802 | */ | ||
3803 | switch (ERR_GET_LIB(pem_err)) { | ||
3804 | case ERR_LIB_PEM: | ||
3805 | switch (pem_reason) { | ||
3806 | case PEM_R_BAD_PASSWORD_READ: | ||
3807 | case PEM_R_PROBLEMS_GETTING_PASSWORD: | ||
3808 | case PEM_R_BAD_DECRYPT: | ||
3809 | r = SSH_ERR_KEY_WRONG_PASSPHRASE; | ||
3810 | goto out; | ||
3811 | default: | ||
3812 | r = SSH_ERR_INVALID_FORMAT; | ||
3813 | goto out; | ||
3814 | } | ||
3815 | case ERR_LIB_EVP: | ||
3816 | switch (pem_reason) { | ||
3817 | case EVP_R_BAD_DECRYPT: | ||
3818 | r = SSH_ERR_KEY_WRONG_PASSPHRASE; | ||
3819 | goto out; | ||
3820 | case EVP_R_BN_DECODE_ERROR: | ||
3821 | case EVP_R_DECODE_ERROR: | ||
3822 | #ifdef EVP_R_PRIVATE_KEY_DECODE_ERROR | ||
3823 | case EVP_R_PRIVATE_KEY_DECODE_ERROR: | ||
3824 | #endif | ||
3825 | r = SSH_ERR_INVALID_FORMAT; | ||
3826 | goto out; | ||
3827 | default: | ||
3828 | r = SSH_ERR_LIBCRYPTO_ERROR; | ||
3829 | goto out; | ||
3830 | } | ||
3831 | case ERR_LIB_ASN1: | ||
3832 | r = SSH_ERR_INVALID_FORMAT; | ||
3833 | goto out; | ||
3834 | } | ||
3835 | r = SSH_ERR_LIBCRYPTO_ERROR; | ||
3836 | goto out; | 3461 | goto out; |
3837 | } | 3462 | } |
3838 | if (pk->type == EVP_PKEY_RSA && | 3463 | if (pk->type == EVP_PKEY_RSA && |
@@ -3850,6 +3475,10 @@ sshkey_parse_private_pem_fileblob(struct sshbuf *blob, int type, | |||
3850 | r = SSH_ERR_LIBCRYPTO_ERROR; | 3475 | r = SSH_ERR_LIBCRYPTO_ERROR; |
3851 | goto out; | 3476 | goto out; |
3852 | } | 3477 | } |
3478 | if (BN_num_bits(prv->rsa->n) < SSH_RSA_MINIMUM_MODULUS_SIZE) { | ||
3479 | r = SSH_ERR_KEY_LENGTH; | ||
3480 | goto out; | ||
3481 | } | ||
3853 | } else if (pk->type == EVP_PKEY_DSA && | 3482 | } else if (pk->type == EVP_PKEY_DSA && |
3854 | (type == KEY_UNSPEC || type == KEY_DSA)) { | 3483 | (type == KEY_UNSPEC || type == KEY_DSA)) { |
3855 | if ((prv = sshkey_new(KEY_UNSPEC)) == NULL) { | 3484 | if ((prv = sshkey_new(KEY_UNSPEC)) == NULL) { |
@@ -3914,11 +3543,6 @@ sshkey_parse_private_fileblob_type(struct sshbuf *blob, int type, | |||
3914 | *commentp = NULL; | 3543 | *commentp = NULL; |
3915 | 3544 | ||
3916 | switch (type) { | 3545 | switch (type) { |
3917 | #ifdef WITH_SSH1 | ||
3918 | case KEY_RSA1: | ||
3919 | return sshkey_parse_private_rsa1(blob, passphrase, | ||
3920 | keyp, commentp); | ||
3921 | #endif /* WITH_SSH1 */ | ||
3922 | #ifdef WITH_OPENSSL | 3546 | #ifdef WITH_OPENSSL |
3923 | case KEY_DSA: | 3547 | case KEY_DSA: |
3924 | case KEY_ECDSA: | 3548 | case KEY_ECDSA: |
@@ -3955,13 +3579,6 @@ sshkey_parse_private_fileblob(struct sshbuf *buffer, const char *passphrase, | |||
3955 | if (commentp != NULL) | 3579 | if (commentp != NULL) |
3956 | *commentp = NULL; | 3580 | *commentp = NULL; |
3957 | 3581 | ||
3958 | #ifdef WITH_SSH1 | ||
3959 | /* it's a SSH v1 key if the public key part is readable */ | ||
3960 | if (sshkey_parse_public_rsa1_fileblob(buffer, NULL, NULL) == 0) { | ||
3961 | return sshkey_parse_private_fileblob_type(buffer, KEY_RSA1, | ||
3962 | passphrase, keyp, commentp); | ||
3963 | } | ||
3964 | #endif /* WITH_SSH1 */ | ||
3965 | return sshkey_parse_private_fileblob_type(buffer, KEY_UNSPEC, | 3582 | return sshkey_parse_private_fileblob_type(buffer, KEY_UNSPEC, |
3966 | passphrase, keyp, commentp); | 3583 | passphrase, keyp, commentp); |
3967 | } | 3584 | } |