summaryrefslogtreecommitdiff
path: root/sshkey.c
diff options
context:
space:
mode:
authordjm@openbsd.org <djm@openbsd.org>2017-04-30 23:10:43 +0000
committerDamien Miller <djm@mindrot.org>2017-05-01 09:37:40 +1000
commit56912dea6ef63dae4eb1194e5d88973a7c6c5740 (patch)
treec0425585449d257a90a42efce5f602f7ce16779f /sshkey.c
parentd4084cd230f7319056559b00db8b99296dad49d5 (diff)
upstream commit
unifdef WITH_SSH1 ok markus@ Upstream-ID: 9716e62a883ef8826c57f4d33b4a81a9cc7755c7
Diffstat (limited to 'sshkey.c')
-rw-r--r--sshkey.c380
1 files changed, 1 insertions, 379 deletions
diff --git a/sshkey.c b/sshkey.c
index 3c487849e..045f1284f 100644
--- a/sshkey.c
+++ b/sshkey.c
@@ -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.46 2017/04/30 23:10:43 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.
@@ -89,9 +89,6 @@ static const struct keytype keytypes[] = {
89 { "ssh-ed25519-cert-v01@openssh.com", "ED25519-CERT", 89 { "ssh-ed25519-cert-v01@openssh.com", "ED25519-CERT",
90 KEY_ED25519_CERT, 0, 1, 0 }, 90 KEY_ED25519_CERT, 0, 1, 0 },
91#ifdef WITH_OPENSSL 91#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 }, 92 { "ssh-rsa", "RSA", KEY_RSA, 0, 0, 0 },
96 { "rsa-sha2-256", "RSA", KEY_RSA, 0, 0, 1 }, 93 { "rsa-sha2-256", "RSA", KEY_RSA, 0, 0, 1 },
97 { "rsa-sha2-512", "RSA", KEY_RSA, 0, 0, 1 }, 94 { "rsa-sha2-512", "RSA", KEY_RSA, 0, 0, 1 },
@@ -1194,39 +1191,6 @@ sshkey_fingerprint(const struct sshkey *k, int dgst_alg,
1194 return retval; 1191 return retval;
1195} 1192}
1196 1193
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 */
1204static int
1205read_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 1194
1231/* returns 0 ok, and < 0 error */ 1195/* returns 0 ok, and < 0 error */
1232int 1196int
@@ -1237,9 +1201,6 @@ sshkey_read(struct sshkey *ret, char **cpp)
1237 char *ep, *cp, *space; 1201 char *ep, *cp, *space;
1238 int r, type, curve_nid = -1; 1202 int r, type, curve_nid = -1;
1239 struct sshbuf *blob; 1203 struct sshbuf *blob;
1240#ifdef WITH_SSH1
1241 u_long bits;
1242#endif /* WITH_SSH1 */
1243 1204
1244 if (ret == NULL) 1205 if (ret == NULL)
1245 return SSH_ERR_INVALID_ARGUMENT; 1206 return SSH_ERR_INVALID_ARGUMENT;
@@ -1248,23 +1209,6 @@ sshkey_read(struct sshkey *ret, char **cpp)
1248 1209
1249 switch (ret->type) { 1210 switch (ret->type) {
1250 case KEY_RSA1: 1211 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; 1212 break;
1269 case KEY_UNSPEC: 1213 case KEY_UNSPEC:
1270 case KEY_RSA: 1214 case KEY_RSA:
@@ -1422,36 +1366,6 @@ static int
1422sshkey_format_rsa1(const struct sshkey *key, struct sshbuf *b) 1366sshkey_format_rsa1(const struct sshkey *key, struct sshbuf *b)
1423{ 1367{
1424 int r = SSH_ERR_INTERNAL_ERROR; 1368 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 1369
1456 return r; 1370 return r;
1457} 1371}
@@ -3404,105 +3318,6 @@ sshkey_parse_private2(struct sshbuf *blob, int type, const char *passphrase,
3404 return r; 3318 return r;
3405} 3319}
3406 3320
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 */
3414static int
3415sshkey_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 3321
3507#ifdef WITH_OPENSSL 3322#ifdef WITH_OPENSSL
3508/* convert SSH v2 key in OpenSSL PEM format */ 3323/* convert SSH v2 key in OpenSSL PEM format */
@@ -3565,11 +3380,6 @@ sshkey_private_to_fileblob(struct sshkey *key, struct sshbuf *blob,
3565 int force_new_format, const char *new_format_cipher, int new_format_rounds) 3380 int force_new_format, const char *new_format_cipher, int new_format_rounds)
3566{ 3381{
3567 switch (key->type) { 3382 switch (key->type) {
3568#ifdef WITH_SSH1
3569 case KEY_RSA1:
3570 return sshkey_private_rsa1_to_blob(key, blob,
3571 passphrase, comment);
3572#endif /* WITH_SSH1 */
3573#ifdef WITH_OPENSSL 3383#ifdef WITH_OPENSSL
3574 case KEY_DSA: 3384 case KEY_DSA:
3575 case KEY_ECDSA: 3385 case KEY_ECDSA:
@@ -3589,182 +3399,6 @@ sshkey_private_to_fileblob(struct sshkey *key, struct sshbuf *blob,
3589 } 3399 }
3590} 3400}
3591 3401
3592#ifdef WITH_SSH1
3593/*
3594 * Parse the public, unencrypted portion of a RSA1 key.
3595 */
3596int
3597sshkey_parse_public_rsa1_fileblob(struct sshbuf *blob,
3598 struct sshkey **keyp, char **commentp)
3599{
3600 int r;
3601 struct sshkey *pub = NULL;
3602 struct sshbuf *copy = NULL;
3603
3604 if (keyp != NULL)
3605 *keyp = NULL;
3606 if (commentp != NULL)
3607 *commentp = NULL;
3608
3609 /* Check that it is at least big enough to contain the ID string. */
3610 if (sshbuf_len(blob) < sizeof(LEGACY_BEGIN))
3611 return SSH_ERR_INVALID_FORMAT;
3612
3613 /*
3614 * Make sure it begins with the id string. Consume the id string
3615 * from the buffer.
3616 */
3617 if (memcmp(sshbuf_ptr(blob), LEGACY_BEGIN, sizeof(LEGACY_BEGIN)) != 0)
3618 return SSH_ERR_INVALID_FORMAT;
3619 /* Make a working copy of the keyblob and skip past the magic */
3620 if ((copy = sshbuf_fromb(blob)) == NULL)
3621 return SSH_ERR_ALLOC_FAIL;
3622 if ((r = sshbuf_consume(copy, sizeof(LEGACY_BEGIN))) != 0)
3623 goto out;
3624
3625 /* Skip cipher type, reserved data and key bits. */
3626 if ((r = sshbuf_get_u8(copy, NULL)) != 0 || /* cipher type */
3627 (r = sshbuf_get_u32(copy, NULL)) != 0 || /* reserved */
3628 (r = sshbuf_get_u32(copy, NULL)) != 0) /* key bits */
3629 goto out;
3630
3631 /* Read the public key from the buffer. */
3632 if ((pub = sshkey_new(KEY_RSA1)) == NULL ||
3633 (r = sshbuf_get_bignum1(copy, pub->rsa->n)) != 0 ||
3634 (r = sshbuf_get_bignum1(copy, pub->rsa->e)) != 0)
3635 goto out;
3636
3637 /* Finally, the comment */
3638 if ((r = sshbuf_get_string(copy, (u_char**)commentp, NULL)) != 0)
3639 goto out;
3640
3641 /* The encrypted private part is not parsed by this function. */
3642
3643 r = 0;
3644 if (keyp != NULL) {
3645 *keyp = pub;
3646 pub = NULL;
3647 }
3648 out:
3649 sshbuf_free(copy);
3650 sshkey_free(pub);
3651 return r;
3652}
3653
3654static int
3655sshkey_parse_private_rsa1(struct sshbuf *blob, const char *passphrase,
3656 struct sshkey **keyp, char **commentp)
3657{
3658 int r;
3659 u_int16_t check1, check2;
3660 u_int8_t cipher_type;
3661 struct sshbuf *decrypted = NULL, *copy = NULL;
3662 u_char *cp;
3663 char *comment = NULL;
3664 struct sshcipher_ctx *ciphercontext = NULL;
3665 const struct sshcipher *cipher;
3666 struct sshkey *prv = NULL;
3667
3668 if (keyp != NULL)
3669 *keyp = NULL;
3670 if (commentp != NULL)
3671 *commentp = NULL;
3672
3673 /* Check that it is at least big enough to contain the ID string. */
3674 if (sshbuf_len(blob) < sizeof(LEGACY_BEGIN))
3675 return SSH_ERR_INVALID_FORMAT;
3676
3677 /*
3678 * Make sure it begins with the id string. Consume the id string
3679 * from the buffer.
3680 */
3681 if (memcmp(sshbuf_ptr(blob), LEGACY_BEGIN, sizeof(LEGACY_BEGIN)) != 0)
3682 return SSH_ERR_INVALID_FORMAT;
3683
3684 if ((prv = sshkey_new_private(KEY_RSA1)) == NULL) {
3685 r = SSH_ERR_ALLOC_FAIL;
3686 goto out;
3687 }
3688 if ((copy = sshbuf_fromb(blob)) == NULL ||
3689 (decrypted = sshbuf_new()) == NULL) {
3690 r = SSH_ERR_ALLOC_FAIL;
3691 goto out;
3692 }
3693 if ((r = sshbuf_consume(copy, sizeof(LEGACY_BEGIN))) != 0)
3694 goto out;
3695
3696 /* Read cipher type. */
3697 if ((r = sshbuf_get_u8(copy, &cipher_type)) != 0 ||
3698 (r = sshbuf_get_u32(copy, NULL)) != 0) /* reserved */
3699 goto out;
3700
3701 /* Read the public key and comment from the buffer. */
3702 if ((r = sshbuf_get_u32(copy, NULL)) != 0 || /* key bits */
3703 (r = sshbuf_get_bignum1(copy, prv->rsa->n)) != 0 ||
3704 (r = sshbuf_get_bignum1(copy, prv->rsa->e)) != 0 ||
3705 (r = sshbuf_get_cstring(copy, &comment, NULL)) != 0)
3706 goto out;
3707
3708 /* Check that it is a supported cipher. */
3709 cipher = cipher_by_number(cipher_type);
3710 if (cipher == NULL) {
3711 r = SSH_ERR_KEY_UNKNOWN_CIPHER;
3712 goto out;
3713 }
3714 /* Initialize space for decrypted data. */
3715 if ((r = sshbuf_reserve(decrypted, sshbuf_len(copy), &cp)) != 0)
3716 goto out;
3717
3718 /* Rest of the buffer is encrypted. Decrypt it using the passphrase. */
3719 if ((r = cipher_set_key_string(&ciphercontext, cipher, passphrase,
3720 CIPHER_DECRYPT)) != 0)
3721 goto out;
3722 if ((r = cipher_crypt(ciphercontext, 0, cp,
3723 sshbuf_ptr(copy), sshbuf_len(copy), 0, 0)) != 0)
3724 goto out;
3725
3726 if ((r = sshbuf_get_u16(decrypted, &check1)) != 0 ||
3727 (r = sshbuf_get_u16(decrypted, &check2)) != 0)
3728 goto out;
3729 if (check1 != check2) {
3730 r = SSH_ERR_KEY_WRONG_PASSPHRASE;
3731 goto out;
3732 }
3733
3734 /* Read the rest of the private key. */
3735 if ((r = sshbuf_get_bignum1(decrypted, prv->rsa->d)) != 0 ||
3736 (r = sshbuf_get_bignum1(decrypted, prv->rsa->iqmp)) != 0 ||
3737 (r = sshbuf_get_bignum1(decrypted, prv->rsa->q)) != 0 ||
3738 (r = sshbuf_get_bignum1(decrypted, prv->rsa->p)) != 0)
3739 goto out;
3740
3741 /* calculate p-1 and q-1 */
3742 if ((r = rsa_generate_additional_parameters(prv->rsa)) != 0)
3743 goto out;
3744
3745 /* enable blinding */
3746 if (RSA_blinding_on(prv->rsa, NULL) != 1) {
3747 r = SSH_ERR_LIBCRYPTO_ERROR;
3748 goto out;
3749 }
3750 r = 0;
3751 if (keyp != NULL) {
3752 *keyp = prv;
3753 prv = NULL;
3754 }
3755 if (commentp != NULL) {
3756 *commentp = comment;
3757 comment = NULL;
3758 }
3759 out:
3760 cipher_free(ciphercontext);
3761 free(comment);
3762 sshkey_free(prv);
3763 sshbuf_free(copy);
3764 sshbuf_free(decrypted);
3765 return r;
3766}
3767#endif /* WITH_SSH1 */
3768 3402
3769#ifdef WITH_OPENSSL 3403#ifdef WITH_OPENSSL
3770static int 3404static int
@@ -3910,11 +3544,6 @@ sshkey_parse_private_fileblob_type(struct sshbuf *blob, int type,
3910 *commentp = NULL; 3544 *commentp = NULL;
3911 3545
3912 switch (type) { 3546 switch (type) {
3913#ifdef WITH_SSH1
3914 case KEY_RSA1:
3915 return sshkey_parse_private_rsa1(blob, passphrase,
3916 keyp, commentp);
3917#endif /* WITH_SSH1 */
3918#ifdef WITH_OPENSSL 3547#ifdef WITH_OPENSSL
3919 case KEY_DSA: 3548 case KEY_DSA:
3920 case KEY_ECDSA: 3549 case KEY_ECDSA:
@@ -3951,13 +3580,6 @@ sshkey_parse_private_fileblob(struct sshbuf *buffer, const char *passphrase,
3951 if (commentp != NULL) 3580 if (commentp != NULL)
3952 *commentp = NULL; 3581 *commentp = NULL;
3953 3582
3954#ifdef WITH_SSH1
3955 /* it's a SSH v1 key if the public key part is readable */
3956 if (sshkey_parse_public_rsa1_fileblob(buffer, NULL, NULL) == 0) {
3957 return sshkey_parse_private_fileblob_type(buffer, KEY_RSA1,
3958 passphrase, keyp, commentp);
3959 }
3960#endif /* WITH_SSH1 */
3961 return sshkey_parse_private_fileblob_type(buffer, KEY_UNSPEC, 3583 return sshkey_parse_private_fileblob_type(buffer, KEY_UNSPEC,
3962 passphrase, keyp, commentp); 3584 passphrase, keyp, commentp);
3963} 3585}