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