summaryrefslogtreecommitdiff
path: root/sshkey.c
diff options
context:
space:
mode:
authorColin Watson <cjwatson@debian.org>2015-08-19 17:00:17 +0100
committerColin Watson <cjwatson@debian.org>2015-08-19 17:40:32 +0100
commit927d0032b865f05679d3cc052bc13cb0e6490283 (patch)
tree69f782deb79182f26069ff41e9539f17e6e44912 /sshkey.c
parentd35c65e77ab6a6a95fefa2c852827ba08e507f0b (diff)
parent810eecd6b2e03770f21e46b5cb8ce8c7fcd46da8 (diff)
New upstream release (6.9p1).
Diffstat (limited to 'sshkey.c')
-rw-r--r--sshkey.c201
1 files changed, 116 insertions, 85 deletions
diff --git a/sshkey.c b/sshkey.c
index cd5992ecb..2c87d8099 100644
--- a/sshkey.c
+++ b/sshkey.c
@@ -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
1412int 1418int
1413sshkey_write(const struct sshkey *key, FILE *f) 1419sshkey_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
1447static int
1448sshkey_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: 1485static int
1457 case KEY_ECDSA: 1486sshkey_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
1508int
1509sshkey_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
1507const char * 1531const 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) {