diff options
author | Colin Watson <cjwatson@debian.org> | 2015-08-19 17:00:17 +0100 |
---|---|---|
committer | Colin Watson <cjwatson@debian.org> | 2015-08-19 17:40:32 +0100 |
commit | 927d0032b865f05679d3cc052bc13cb0e6490283 (patch) | |
tree | 69f782deb79182f26069ff41e9539f17e6e44912 /sshkey.c | |
parent | d35c65e77ab6a6a95fefa2c852827ba08e507f0b (diff) | |
parent | 810eecd6b2e03770f21e46b5cb8ce8c7fcd46da8 (diff) |
New upstream release (6.9p1).
Diffstat (limited to 'sshkey.c')
-rw-r--r-- | sshkey.c | 201 |
1 files changed, 116 insertions, 85 deletions
@@ -1,4 +1,4 @@ | |||
1 | /* $OpenBSD: sshkey.c,v 1.15 2015/03/06 01:40:56 djm Exp $ */ | 1 | /* $OpenBSD: sshkey.c,v 1.19 2015/05/21 04:55:51 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. |
@@ -252,7 +252,7 @@ sshkey_names_valid2(const char *names, int allow_wildcard) | |||
252 | if (kt->type == KEY_RSA1) | 252 | if (kt->type == KEY_RSA1) |
253 | continue; | 253 | continue; |
254 | if (match_pattern_list(kt->name, | 254 | if (match_pattern_list(kt->name, |
255 | p, strlen(p), 0) != 0) | 255 | p, 0) != 0) |
256 | break; | 256 | break; |
257 | } | 257 | } |
258 | if (kt->type != -1) | 258 | if (kt->type != -1) |
@@ -762,6 +762,12 @@ to_blob_buf(const struct sshkey *key, struct sshbuf *b, int force_plain) | |||
762 | if (key == NULL) | 762 | if (key == NULL) |
763 | return SSH_ERR_INVALID_ARGUMENT; | 763 | return SSH_ERR_INVALID_ARGUMENT; |
764 | 764 | ||
765 | if (sshkey_is_cert(key)) { | ||
766 | if (key->cert == NULL) | ||
767 | return SSH_ERR_EXPECTED_CERT; | ||
768 | if (sshbuf_len(key->cert->certblob) == 0) | ||
769 | return SSH_ERR_KEY_LACKS_CERTBLOB; | ||
770 | } | ||
765 | type = force_plain ? sshkey_type_plain(key->type) : key->type; | 771 | type = force_plain ? sshkey_type_plain(key->type) : key->type; |
766 | typename = sshkey_ssh_name_from_type_nid(type, key->ecdsa_nid); | 772 | typename = sshkey_ssh_name_from_type_nid(type, key->ecdsa_nid); |
767 | 773 | ||
@@ -1410,98 +1416,116 @@ sshkey_read(struct sshkey *ret, char **cpp) | |||
1410 | } | 1416 | } |
1411 | 1417 | ||
1412 | int | 1418 | int |
1413 | sshkey_write(const struct sshkey *key, FILE *f) | 1419 | sshkey_to_base64(const struct sshkey *key, char **b64p) |
1414 | { | 1420 | { |
1415 | int ret = SSH_ERR_INTERNAL_ERROR; | 1421 | int r = SSH_ERR_INTERNAL_ERROR; |
1416 | struct sshbuf *b = NULL, *bb = NULL; | 1422 | struct sshbuf *b = NULL; |
1417 | char *uu = NULL; | 1423 | char *uu = NULL; |
1424 | |||
1425 | if (b64p != NULL) | ||
1426 | *b64p = NULL; | ||
1427 | if ((b = sshbuf_new()) == NULL) | ||
1428 | return SSH_ERR_ALLOC_FAIL; | ||
1429 | if ((r = sshkey_putb(key, b)) != 0) | ||
1430 | goto out; | ||
1431 | if ((uu = sshbuf_dtob64(b)) == NULL) { | ||
1432 | r = SSH_ERR_ALLOC_FAIL; | ||
1433 | goto out; | ||
1434 | } | ||
1435 | /* Success */ | ||
1436 | if (b64p != NULL) { | ||
1437 | *b64p = uu; | ||
1438 | uu = NULL; | ||
1439 | } | ||
1440 | r = 0; | ||
1441 | out: | ||
1442 | sshbuf_free(b); | ||
1443 | free(uu); | ||
1444 | return r; | ||
1445 | } | ||
1446 | |||
1447 | static int | ||
1448 | sshkey_format_rsa1(const struct sshkey *key, struct sshbuf *b) | ||
1449 | { | ||
1450 | int r = SSH_ERR_INTERNAL_ERROR; | ||
1418 | #ifdef WITH_SSH1 | 1451 | #ifdef WITH_SSH1 |
1419 | u_int bits = 0; | 1452 | u_int bits = 0; |
1420 | char *dec_e = NULL, *dec_n = NULL; | 1453 | char *dec_e = NULL, *dec_n = NULL; |
1421 | #endif /* WITH_SSH1 */ | ||
1422 | 1454 | ||
1423 | if (sshkey_is_cert(key)) { | 1455 | if (key->rsa == NULL || key->rsa->e == NULL || |
1424 | if (key->cert == NULL) | 1456 | key->rsa->n == NULL) { |
1425 | return SSH_ERR_EXPECTED_CERT; | 1457 | r = SSH_ERR_INVALID_ARGUMENT; |
1426 | if (sshbuf_len(key->cert->certblob) == 0) | 1458 | goto out; |
1427 | return SSH_ERR_KEY_LACKS_CERTBLOB; | ||
1428 | } | 1459 | } |
1429 | if ((b = sshbuf_new()) == NULL) | 1460 | if ((dec_e = BN_bn2dec(key->rsa->e)) == NULL || |
1430 | return SSH_ERR_ALLOC_FAIL; | 1461 | (dec_n = BN_bn2dec(key->rsa->n)) == NULL) { |
1431 | switch (key->type) { | 1462 | r = SSH_ERR_ALLOC_FAIL; |
1432 | #ifdef WITH_SSH1 | 1463 | goto out; |
1433 | case KEY_RSA1: | 1464 | } |
1434 | if (key->rsa == NULL || key->rsa->e == NULL || | 1465 | /* size of modulus 'n' */ |
1435 | key->rsa->n == NULL) { | 1466 | if ((bits = BN_num_bits(key->rsa->n)) <= 0) { |
1436 | ret = SSH_ERR_INVALID_ARGUMENT; | 1467 | r = SSH_ERR_INVALID_ARGUMENT; |
1437 | goto out; | 1468 | goto out; |
1438 | } | 1469 | } |
1439 | if ((dec_e = BN_bn2dec(key->rsa->e)) == NULL || | 1470 | if ((r = sshbuf_putf(b, "%u %s %s", bits, dec_e, dec_n)) != 0) |
1440 | (dec_n = BN_bn2dec(key->rsa->n)) == NULL) { | 1471 | goto out; |
1441 | ret = SSH_ERR_ALLOC_FAIL; | 1472 | |
1442 | goto out; | 1473 | /* Success */ |
1443 | } | 1474 | r = 0; |
1444 | /* size of modulus 'n' */ | 1475 | out: |
1445 | if ((bits = BN_num_bits(key->rsa->n)) <= 0) { | 1476 | if (dec_e != NULL) |
1446 | ret = SSH_ERR_INVALID_ARGUMENT; | 1477 | OPENSSL_free(dec_e); |
1447 | goto out; | 1478 | if (dec_n != NULL) |
1448 | } | 1479 | OPENSSL_free(dec_n); |
1449 | if ((ret = sshbuf_putf(b, "%u %s %s", bits, dec_e, dec_n)) != 0) | ||
1450 | goto out; | ||
1451 | #endif /* WITH_SSH1 */ | 1480 | #endif /* WITH_SSH1 */ |
1452 | break; | 1481 | |
1453 | #ifdef WITH_OPENSSL | 1482 | return r; |
1454 | case KEY_DSA: | 1483 | } |
1455 | case KEY_DSA_CERT_V00: | 1484 | |
1456 | case KEY_DSA_CERT: | 1485 | static int |
1457 | case KEY_ECDSA: | 1486 | sshkey_format_text(const struct sshkey *key, struct sshbuf *b) |
1458 | case KEY_ECDSA_CERT: | 1487 | { |
1459 | case KEY_RSA: | 1488 | int r = SSH_ERR_INTERNAL_ERROR; |
1460 | case KEY_RSA_CERT_V00: | 1489 | char *uu = NULL; |
1461 | case KEY_RSA_CERT: | 1490 | |
1462 | #endif /* WITH_OPENSSL */ | 1491 | if (key->type == KEY_RSA1) { |
1463 | case KEY_ED25519: | 1492 | if ((r = sshkey_format_rsa1(key, b)) != 0) |
1464 | case KEY_ED25519_CERT: | ||
1465 | if ((bb = sshbuf_new()) == NULL) { | ||
1466 | ret = SSH_ERR_ALLOC_FAIL; | ||
1467 | goto out; | ||
1468 | } | ||
1469 | if ((ret = sshkey_putb(key, bb)) != 0) | ||
1470 | goto out; | ||
1471 | if ((uu = sshbuf_dtob64(bb)) == NULL) { | ||
1472 | ret = SSH_ERR_ALLOC_FAIL; | ||
1473 | goto out; | 1493 | goto out; |
1474 | } | 1494 | } else { |
1475 | if ((ret = sshbuf_putf(b, "%s ", sshkey_ssh_name(key))) != 0) | 1495 | /* Unsupported key types handled in sshkey_to_base64() */ |
1496 | if ((r = sshkey_to_base64(key, &uu)) != 0) | ||
1476 | goto out; | 1497 | goto out; |
1477 | if ((ret = sshbuf_put(b, uu, strlen(uu))) != 0) | 1498 | if ((r = sshbuf_putf(b, "%s %s", |
1499 | sshkey_ssh_name(key), uu)) != 0) | ||
1478 | goto out; | 1500 | goto out; |
1479 | break; | ||
1480 | default: | ||
1481 | ret = SSH_ERR_KEY_TYPE_UNKNOWN; | ||
1482 | goto out; | ||
1483 | } | 1501 | } |
1502 | r = 0; | ||
1503 | out: | ||
1504 | free(uu); | ||
1505 | return r; | ||
1506 | } | ||
1507 | |||
1508 | int | ||
1509 | sshkey_write(const struct sshkey *key, FILE *f) | ||
1510 | { | ||
1511 | struct sshbuf *b = NULL; | ||
1512 | int r = SSH_ERR_INTERNAL_ERROR; | ||
1513 | |||
1514 | if ((b = sshbuf_new()) == NULL) | ||
1515 | return SSH_ERR_ALLOC_FAIL; | ||
1516 | if ((r = sshkey_format_text(key, b)) != 0) | ||
1517 | goto out; | ||
1484 | if (fwrite(sshbuf_ptr(b), sshbuf_len(b), 1, f) != 1) { | 1518 | if (fwrite(sshbuf_ptr(b), sshbuf_len(b), 1, f) != 1) { |
1485 | if (feof(f)) | 1519 | if (feof(f)) |
1486 | errno = EPIPE; | 1520 | errno = EPIPE; |
1487 | ret = SSH_ERR_SYSTEM_ERROR; | 1521 | r = SSH_ERR_SYSTEM_ERROR; |
1488 | goto out; | 1522 | goto out; |
1489 | } | 1523 | } |
1490 | ret = 0; | 1524 | /* Success */ |
1525 | r = 0; | ||
1491 | out: | 1526 | out: |
1492 | if (b != NULL) | 1527 | sshbuf_free(b); |
1493 | sshbuf_free(b); | 1528 | return r; |
1494 | if (bb != NULL) | ||
1495 | sshbuf_free(bb); | ||
1496 | if (uu != NULL) | ||
1497 | free(uu); | ||
1498 | #ifdef WITH_SSH1 | ||
1499 | if (dec_e != NULL) | ||
1500 | OPENSSL_free(dec_e); | ||
1501 | if (dec_n != NULL) | ||
1502 | OPENSSL_free(dec_n); | ||
1503 | #endif /* WITH_SSH1 */ | ||
1504 | return ret; | ||
1505 | } | 1529 | } |
1506 | 1530 | ||
1507 | const char * | 1531 | const char * |
@@ -2014,8 +2038,8 @@ sshkey_from_blob_internal(struct sshbuf *b, struct sshkey **keyp, | |||
2014 | ret = SSH_ERR_ALLOC_FAIL; | 2038 | ret = SSH_ERR_ALLOC_FAIL; |
2015 | goto out; | 2039 | goto out; |
2016 | } | 2040 | } |
2017 | if (sshbuf_get_bignum2(b, key->rsa->e) == -1 || | 2041 | if (sshbuf_get_bignum2(b, key->rsa->e) != 0 || |
2018 | sshbuf_get_bignum2(b, key->rsa->n) == -1) { | 2042 | sshbuf_get_bignum2(b, key->rsa->n) != 0) { |
2019 | ret = SSH_ERR_INVALID_FORMAT; | 2043 | ret = SSH_ERR_INVALID_FORMAT; |
2020 | goto out; | 2044 | goto out; |
2021 | } | 2045 | } |
@@ -2036,10 +2060,10 @@ sshkey_from_blob_internal(struct sshbuf *b, struct sshkey **keyp, | |||
2036 | ret = SSH_ERR_ALLOC_FAIL; | 2060 | ret = SSH_ERR_ALLOC_FAIL; |
2037 | goto out; | 2061 | goto out; |
2038 | } | 2062 | } |
2039 | if (sshbuf_get_bignum2(b, key->dsa->p) == -1 || | 2063 | if (sshbuf_get_bignum2(b, key->dsa->p) != 0 || |
2040 | sshbuf_get_bignum2(b, key->dsa->q) == -1 || | 2064 | sshbuf_get_bignum2(b, key->dsa->q) != 0 || |
2041 | sshbuf_get_bignum2(b, key->dsa->g) == -1 || | 2065 | sshbuf_get_bignum2(b, key->dsa->g) != 0 || |
2042 | sshbuf_get_bignum2(b, key->dsa->pub_key) == -1) { | 2066 | sshbuf_get_bignum2(b, key->dsa->pub_key) != 0) { |
2043 | ret = SSH_ERR_INVALID_FORMAT; | 2067 | ret = SSH_ERR_INVALID_FORMAT; |
2044 | goto out; | 2068 | goto out; |
2045 | } | 2069 | } |
@@ -3202,7 +3226,7 @@ sshkey_parse_private2(struct sshbuf *blob, int type, const char *passphrase, | |||
3202 | const u_char *cp; | 3226 | const u_char *cp; |
3203 | int r = SSH_ERR_INTERNAL_ERROR; | 3227 | int r = SSH_ERR_INTERNAL_ERROR; |
3204 | size_t encoded_len; | 3228 | size_t encoded_len; |
3205 | size_t i, keylen = 0, ivlen = 0, slen = 0; | 3229 | size_t i, keylen = 0, ivlen = 0, authlen = 0, slen = 0; |
3206 | struct sshbuf *encoded = NULL, *decoded = NULL; | 3230 | struct sshbuf *encoded = NULL, *decoded = NULL; |
3207 | struct sshbuf *kdf = NULL, *decrypted = NULL; | 3231 | struct sshbuf *kdf = NULL, *decrypted = NULL; |
3208 | struct sshcipher_ctx ciphercontext; | 3232 | struct sshcipher_ctx ciphercontext; |
@@ -3312,6 +3336,7 @@ sshkey_parse_private2(struct sshbuf *blob, int type, const char *passphrase, | |||
3312 | /* setup key */ | 3336 | /* setup key */ |
3313 | keylen = cipher_keylen(cipher); | 3337 | keylen = cipher_keylen(cipher); |
3314 | ivlen = cipher_ivlen(cipher); | 3338 | ivlen = cipher_ivlen(cipher); |
3339 | authlen = cipher_authlen(cipher); | ||
3315 | if ((key = calloc(1, keylen + ivlen)) == NULL) { | 3340 | if ((key = calloc(1, keylen + ivlen)) == NULL) { |
3316 | r = SSH_ERR_ALLOC_FAIL; | 3341 | r = SSH_ERR_ALLOC_FAIL; |
3317 | goto out; | 3342 | goto out; |
@@ -3327,19 +3352,25 @@ sshkey_parse_private2(struct sshbuf *blob, int type, const char *passphrase, | |||
3327 | } | 3352 | } |
3328 | } | 3353 | } |
3329 | 3354 | ||
3355 | /* check that an appropriate amount of auth data is present */ | ||
3356 | if (sshbuf_len(decoded) < encrypted_len + authlen) { | ||
3357 | r = SSH_ERR_INVALID_FORMAT; | ||
3358 | goto out; | ||
3359 | } | ||
3360 | |||
3330 | /* decrypt private portion of key */ | 3361 | /* decrypt private portion of key */ |
3331 | if ((r = sshbuf_reserve(decrypted, encrypted_len, &dp)) != 0 || | 3362 | if ((r = sshbuf_reserve(decrypted, encrypted_len, &dp)) != 0 || |
3332 | (r = cipher_init(&ciphercontext, cipher, key, keylen, | 3363 | (r = cipher_init(&ciphercontext, cipher, key, keylen, |
3333 | key + keylen, ivlen, 0)) != 0) | 3364 | key + keylen, ivlen, 0)) != 0) |
3334 | goto out; | 3365 | goto out; |
3335 | if ((r = cipher_crypt(&ciphercontext, 0, dp, sshbuf_ptr(decoded), | 3366 | if ((r = cipher_crypt(&ciphercontext, 0, dp, sshbuf_ptr(decoded), |
3336 | sshbuf_len(decoded), 0, cipher_authlen(cipher))) != 0) { | 3367 | encrypted_len, 0, authlen)) != 0) { |
3337 | /* an integrity error here indicates an incorrect passphrase */ | 3368 | /* an integrity error here indicates an incorrect passphrase */ |
3338 | if (r == SSH_ERR_MAC_INVALID) | 3369 | if (r == SSH_ERR_MAC_INVALID) |
3339 | r = SSH_ERR_KEY_WRONG_PASSPHRASE; | 3370 | r = SSH_ERR_KEY_WRONG_PASSPHRASE; |
3340 | goto out; | 3371 | goto out; |
3341 | } | 3372 | } |
3342 | if ((r = sshbuf_consume(decoded, encrypted_len)) != 0) | 3373 | if ((r = sshbuf_consume(decoded, encrypted_len + authlen)) != 0) |
3343 | goto out; | 3374 | goto out; |
3344 | /* there should be no trailing data */ | 3375 | /* there should be no trailing data */ |
3345 | if (sshbuf_len(decoded) != 0) { | 3376 | if (sshbuf_len(decoded) != 0) { |