summaryrefslogtreecommitdiff
path: root/sshkey.c
diff options
context:
space:
mode:
Diffstat (limited to 'sshkey.c')
-rw-r--r--sshkey.c487
1 files changed, 255 insertions, 232 deletions
diff --git a/sshkey.c b/sshkey.c
index 57995ee68..1571e3d93 100644
--- a/sshkey.c
+++ b/sshkey.c
@@ -1,4 +1,4 @@
1/* $OpenBSD: sshkey.c,v 1.99 2020/01/21 05:56:56 djm Exp $ */ 1/* $OpenBSD: sshkey.c,v 1.108 2020/04/11 10:16:11 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.
@@ -1019,10 +1019,8 @@ sshkey_fingerprint_raw(const struct sshkey *k, int dgst_alg,
1019 r = 0; 1019 r = 0;
1020 out: 1020 out:
1021 free(ret); 1021 free(ret);
1022 if (blob != NULL) { 1022 if (blob != NULL)
1023 explicit_bzero(blob, blob_len); 1023 freezero(blob, blob_len);
1024 free(blob);
1025 }
1026 return r; 1024 return r;
1027} 1025}
1028 1026
@@ -1280,12 +1278,10 @@ sshkey_fingerprint(const struct sshkey *k, int dgst_alg,
1280 dgst_raw, dgst_raw_len, k); 1278 dgst_raw, dgst_raw_len, k);
1281 break; 1279 break;
1282 default: 1280 default:
1283 explicit_bzero(dgst_raw, dgst_raw_len); 1281 freezero(dgst_raw, dgst_raw_len);
1284 free(dgst_raw);
1285 return NULL; 1282 return NULL;
1286 } 1283 }
1287 explicit_bzero(dgst_raw, dgst_raw_len); 1284 freezero(dgst_raw, dgst_raw_len);
1288 free(dgst_raw);
1289 return retval; 1285 return retval;
1290} 1286}
1291 1287
@@ -3082,8 +3078,8 @@ sshkey_cert_check_authority(const struct sshkey *k,
3082 u_int i, principal_matches; 3078 u_int i, principal_matches;
3083 time_t now = time(NULL); 3079 time_t now = time(NULL);
3084 3080
3085 if (reason != NULL) 3081 if (reason == NULL)
3086 *reason = NULL; 3082 return SSH_ERR_INVALID_ARGUMENT;
3087 3083
3088 if (want_host) { 3084 if (want_host) {
3089 if (k->cert->type != SSH2_CERT_TYPE_HOST) { 3085 if (k->cert->type != SSH2_CERT_TYPE_HOST) {
@@ -3398,38 +3394,52 @@ sshkey_private_deserialize(struct sshbuf *buf, struct sshkey **kp)
3398 if ((r = sshbuf_get_cstring(buf, &tname, NULL)) != 0) 3394 if ((r = sshbuf_get_cstring(buf, &tname, NULL)) != 0)
3399 goto out; 3395 goto out;
3400 type = sshkey_type_from_name(tname); 3396 type = sshkey_type_from_name(tname);
3401 switch (type) { 3397 if (sshkey_type_is_cert(type)) {
3402#ifdef WITH_OPENSSL 3398 /*
3403 case KEY_DSA: 3399 * Certificate key private keys begin with the certificate
3400 * itself. Make sure this matches the type of the enclosing
3401 * private key.
3402 */
3403 if ((r = sshkey_froms(buf, &k)) != 0)
3404 goto out;
3405 if (k->type != type) {
3406 r = SSH_ERR_KEY_CERT_MISMATCH;
3407 goto out;
3408 }
3409 /* For ECDSA keys, the group must match too */
3410 if (k->type == KEY_ECDSA &&
3411 k->ecdsa_nid != sshkey_ecdsa_nid_from_name(tname)) {
3412 r = SSH_ERR_KEY_CERT_MISMATCH;
3413 goto out;
3414 }
3415 } else {
3404 if ((k = sshkey_new(type)) == NULL) { 3416 if ((k = sshkey_new(type)) == NULL) {
3405 r = SSH_ERR_ALLOC_FAIL; 3417 r = SSH_ERR_ALLOC_FAIL;
3406 goto out; 3418 goto out;
3407 } 3419 }
3420 }
3421 switch (type) {
3422#ifdef WITH_OPENSSL
3423 case KEY_DSA:
3408 if ((r = sshbuf_get_bignum2(buf, &dsa_p)) != 0 || 3424 if ((r = sshbuf_get_bignum2(buf, &dsa_p)) != 0 ||
3409 (r = sshbuf_get_bignum2(buf, &dsa_q)) != 0 || 3425 (r = sshbuf_get_bignum2(buf, &dsa_q)) != 0 ||
3410 (r = sshbuf_get_bignum2(buf, &dsa_g)) != 0 || 3426 (r = sshbuf_get_bignum2(buf, &dsa_g)) != 0 ||
3411 (r = sshbuf_get_bignum2(buf, &dsa_pub_key)) != 0 || 3427 (r = sshbuf_get_bignum2(buf, &dsa_pub_key)) != 0)
3412 (r = sshbuf_get_bignum2(buf, &dsa_priv_key)) != 0)
3413 goto out; 3428 goto out;
3414 if (!DSA_set0_pqg(k->dsa, dsa_p, dsa_q, dsa_g)) { 3429 if (!DSA_set0_pqg(k->dsa, dsa_p, dsa_q, dsa_g)) {
3415 r = SSH_ERR_LIBCRYPTO_ERROR; 3430 r = SSH_ERR_LIBCRYPTO_ERROR;
3416 goto out; 3431 goto out;
3417 } 3432 }
3418 dsa_p = dsa_q = dsa_g = NULL; /* transferred */ 3433 dsa_p = dsa_q = dsa_g = NULL; /* transferred */
3419 if (!DSA_set0_key(k->dsa, dsa_pub_key, dsa_priv_key)) { 3434 if (!DSA_set0_key(k->dsa, dsa_pub_key, NULL)) {
3420 r = SSH_ERR_LIBCRYPTO_ERROR; 3435 r = SSH_ERR_LIBCRYPTO_ERROR;
3421 goto out; 3436 goto out;
3422 } 3437 }
3423 dsa_pub_key = dsa_priv_key = NULL; /* transferred */ 3438 dsa_pub_key = NULL; /* transferred */
3424 break; 3439 /* FALLTHROUGH */
3425 case KEY_DSA_CERT: 3440 case KEY_DSA_CERT:
3426 if ((r = sshkey_froms(buf, &k)) != 0 || 3441 if ((r = sshbuf_get_bignum2(buf, &dsa_priv_key)) != 0)
3427 (r = sshbuf_get_bignum2(buf, &dsa_priv_key)) != 0)
3428 goto out; 3442 goto out;
3429 if (k->type != type) {
3430 r = SSH_ERR_INVALID_FORMAT;
3431 goto out;
3432 }
3433 if (!DSA_set0_key(k->dsa, NULL, dsa_priv_key)) { 3443 if (!DSA_set0_key(k->dsa, NULL, dsa_priv_key)) {
3434 r = SSH_ERR_LIBCRYPTO_ERROR; 3444 r = SSH_ERR_LIBCRYPTO_ERROR;
3435 goto out; 3445 goto out;
@@ -3438,10 +3448,6 @@ sshkey_private_deserialize(struct sshbuf *buf, struct sshkey **kp)
3438 break; 3448 break;
3439# ifdef OPENSSL_HAS_ECC 3449# ifdef OPENSSL_HAS_ECC
3440 case KEY_ECDSA: 3450 case KEY_ECDSA:
3441 if ((k = sshkey_new(type)) == NULL) {
3442 r = SSH_ERR_ALLOC_FAIL;
3443 goto out;
3444 }
3445 if ((k->ecdsa_nid = sshkey_ecdsa_nid_from_name(tname)) == -1) { 3451 if ((k->ecdsa_nid = sshkey_ecdsa_nid_from_name(tname)) == -1) {
3446 r = SSH_ERR_INVALID_ARGUMENT; 3452 r = SSH_ERR_INVALID_ARGUMENT;
3447 goto out; 3453 goto out;
@@ -3457,27 +3463,12 @@ sshkey_private_deserialize(struct sshbuf *buf, struct sshkey **kp)
3457 r = SSH_ERR_LIBCRYPTO_ERROR; 3463 r = SSH_ERR_LIBCRYPTO_ERROR;
3458 goto out; 3464 goto out;
3459 } 3465 }
3460 if ((r = sshbuf_get_eckey(buf, k->ecdsa)) != 0 || 3466 if ((r = sshbuf_get_eckey(buf, k->ecdsa)) != 0)
3461 (r = sshbuf_get_bignum2(buf, &exponent)))
3462 goto out;
3463 if (EC_KEY_set_private_key(k->ecdsa, exponent) != 1) {
3464 r = SSH_ERR_LIBCRYPTO_ERROR;
3465 goto out;
3466 }
3467 if ((r = sshkey_ec_validate_public(EC_KEY_get0_group(k->ecdsa),
3468 EC_KEY_get0_public_key(k->ecdsa))) != 0 ||
3469 (r = sshkey_ec_validate_private(k->ecdsa)) != 0)
3470 goto out; 3467 goto out;
3471 break; 3468 /* FALLTHROUGH */
3472 case KEY_ECDSA_CERT: 3469 case KEY_ECDSA_CERT:
3473 if ((r = sshkey_froms(buf, &k)) != 0 || 3470 if ((r = sshbuf_get_bignum2(buf, &exponent)) != 0)
3474 (r = sshbuf_get_bignum2(buf, &exponent)) != 0)
3475 goto out;
3476 if (k->type != type ||
3477 k->ecdsa_nid != sshkey_ecdsa_nid_from_name(tname)) {
3478 r = SSH_ERR_INVALID_FORMAT;
3479 goto out; 3471 goto out;
3480 }
3481 if (EC_KEY_set_private_key(k->ecdsa, exponent) != 1) { 3472 if (EC_KEY_set_private_key(k->ecdsa, exponent) != 1) {
3482 r = SSH_ERR_LIBCRYPTO_ERROR; 3473 r = SSH_ERR_LIBCRYPTO_ERROR;
3483 goto out; 3474 goto out;
@@ -3488,10 +3479,6 @@ sshkey_private_deserialize(struct sshbuf *buf, struct sshkey **kp)
3488 goto out; 3479 goto out;
3489 break; 3480 break;
3490 case KEY_ECDSA_SK: 3481 case KEY_ECDSA_SK:
3491 if ((k = sshkey_new(type)) == NULL) {
3492 r = SSH_ERR_ALLOC_FAIL;
3493 goto out;
3494 }
3495 if ((k->ecdsa_nid = sshkey_ecdsa_nid_from_name(tname)) == -1) { 3482 if ((k->ecdsa_nid = sshkey_ecdsa_nid_from_name(tname)) == -1) {
3496 r = SSH_ERR_INVALID_ARGUMENT; 3483 r = SSH_ERR_INVALID_ARGUMENT;
3497 goto out; 3484 goto out;
@@ -3524,8 +3511,6 @@ sshkey_private_deserialize(struct sshbuf *buf, struct sshkey **kp)
3524 goto out; 3511 goto out;
3525 break; 3512 break;
3526 case KEY_ECDSA_SK_CERT: 3513 case KEY_ECDSA_SK_CERT:
3527 if ((r = sshkey_froms(buf, &k)) != 0)
3528 goto out;
3529 if ((k->sk_key_handle = sshbuf_new()) == NULL || 3514 if ((k->sk_key_handle = sshbuf_new()) == NULL ||
3530 (k->sk_reserved = sshbuf_new()) == NULL) { 3515 (k->sk_reserved = sshbuf_new()) == NULL) {
3531 r = SSH_ERR_ALLOC_FAIL; 3516 r = SSH_ERR_ALLOC_FAIL;
@@ -3543,43 +3528,21 @@ sshkey_private_deserialize(struct sshbuf *buf, struct sshkey **kp)
3543 break; 3528 break;
3544# endif /* OPENSSL_HAS_ECC */ 3529# endif /* OPENSSL_HAS_ECC */
3545 case KEY_RSA: 3530 case KEY_RSA:
3546 if ((k = sshkey_new(type)) == NULL) {
3547 r = SSH_ERR_ALLOC_FAIL;
3548 goto out;
3549 }
3550 if ((r = sshbuf_get_bignum2(buf, &rsa_n)) != 0 || 3531 if ((r = sshbuf_get_bignum2(buf, &rsa_n)) != 0 ||
3551 (r = sshbuf_get_bignum2(buf, &rsa_e)) != 0 || 3532 (r = sshbuf_get_bignum2(buf, &rsa_e)) != 0)
3552 (r = sshbuf_get_bignum2(buf, &rsa_d)) != 0 ||
3553 (r = sshbuf_get_bignum2(buf, &rsa_iqmp)) != 0 ||
3554 (r = sshbuf_get_bignum2(buf, &rsa_p)) != 0 ||
3555 (r = sshbuf_get_bignum2(buf, &rsa_q)) != 0)
3556 goto out; 3533 goto out;
3557 if (!RSA_set0_key(k->rsa, rsa_n, rsa_e, rsa_d)) { 3534 if (!RSA_set0_key(k->rsa, rsa_n, rsa_e, NULL)) {
3558 r = SSH_ERR_LIBCRYPTO_ERROR; 3535 r = SSH_ERR_LIBCRYPTO_ERROR;
3559 goto out; 3536 goto out;
3560 } 3537 }
3561 rsa_n = rsa_e = rsa_d = NULL; /* transferred */ 3538 rsa_n = rsa_e = NULL; /* transferred */
3562 if (!RSA_set0_factors(k->rsa, rsa_p, rsa_q)) { 3539 /* FALLTHROUGH */
3563 r = SSH_ERR_LIBCRYPTO_ERROR;
3564 goto out;
3565 }
3566 rsa_p = rsa_q = NULL; /* transferred */
3567 if ((r = check_rsa_length(k->rsa)) != 0)
3568 goto out;
3569 if ((r = ssh_rsa_complete_crt_parameters(k, rsa_iqmp)) != 0)
3570 goto out;
3571 break;
3572 case KEY_RSA_CERT: 3540 case KEY_RSA_CERT:
3573 if ((r = sshkey_froms(buf, &k)) != 0 || 3541 if ((r = sshbuf_get_bignum2(buf, &rsa_d)) != 0 ||
3574 (r = sshbuf_get_bignum2(buf, &rsa_d)) != 0 ||
3575 (r = sshbuf_get_bignum2(buf, &rsa_iqmp)) != 0 || 3542 (r = sshbuf_get_bignum2(buf, &rsa_iqmp)) != 0 ||
3576 (r = sshbuf_get_bignum2(buf, &rsa_p)) != 0 || 3543 (r = sshbuf_get_bignum2(buf, &rsa_p)) != 0 ||
3577 (r = sshbuf_get_bignum2(buf, &rsa_q)) != 0) 3544 (r = sshbuf_get_bignum2(buf, &rsa_q)) != 0)
3578 goto out; 3545 goto out;
3579 if (k->type != type) {
3580 r = SSH_ERR_INVALID_FORMAT;
3581 goto out;
3582 }
3583 if (!RSA_set0_key(k->rsa, NULL, NULL, rsa_d)) { 3546 if (!RSA_set0_key(k->rsa, NULL, NULL, rsa_d)) {
3584 r = SSH_ERR_LIBCRYPTO_ERROR; 3547 r = SSH_ERR_LIBCRYPTO_ERROR;
3585 goto out; 3548 goto out;
@@ -3597,30 +3560,10 @@ sshkey_private_deserialize(struct sshbuf *buf, struct sshkey **kp)
3597 break; 3560 break;
3598#endif /* WITH_OPENSSL */ 3561#endif /* WITH_OPENSSL */
3599 case KEY_ED25519: 3562 case KEY_ED25519:
3600 if ((k = sshkey_new(type)) == NULL) {
3601 r = SSH_ERR_ALLOC_FAIL;
3602 goto out;
3603 }
3604 if ((r = sshbuf_get_string(buf, &ed25519_pk, &pklen)) != 0 ||
3605 (r = sshbuf_get_string(buf, &ed25519_sk, &sklen)) != 0)
3606 goto out;
3607 if (pklen != ED25519_PK_SZ || sklen != ED25519_SK_SZ) {
3608 r = SSH_ERR_INVALID_FORMAT;
3609 goto out;
3610 }
3611 k->ed25519_pk = ed25519_pk;
3612 k->ed25519_sk = ed25519_sk;
3613 ed25519_pk = ed25519_sk = NULL;
3614 break;
3615 case KEY_ED25519_CERT: 3563 case KEY_ED25519_CERT:
3616 if ((r = sshkey_froms(buf, &k)) != 0 || 3564 if ((r = sshbuf_get_string(buf, &ed25519_pk, &pklen)) != 0 ||
3617 (r = sshbuf_get_string(buf, &ed25519_pk, &pklen)) != 0 ||
3618 (r = sshbuf_get_string(buf, &ed25519_sk, &sklen)) != 0) 3565 (r = sshbuf_get_string(buf, &ed25519_sk, &sklen)) != 0)
3619 goto out; 3566 goto out;
3620 if (k->type != type) {
3621 r = SSH_ERR_INVALID_FORMAT;
3622 goto out;
3623 }
3624 if (pklen != ED25519_PK_SZ || sklen != ED25519_SK_SZ) { 3567 if (pklen != ED25519_PK_SZ || sklen != ED25519_SK_SZ) {
3625 r = SSH_ERR_INVALID_FORMAT; 3568 r = SSH_ERR_INVALID_FORMAT;
3626 goto out; 3569 goto out;
@@ -3630,38 +3573,9 @@ sshkey_private_deserialize(struct sshbuf *buf, struct sshkey **kp)
3630 ed25519_pk = ed25519_sk = NULL; /* transferred */ 3573 ed25519_pk = ed25519_sk = NULL; /* transferred */
3631 break; 3574 break;
3632 case KEY_ED25519_SK: 3575 case KEY_ED25519_SK:
3633 if ((k = sshkey_new(type)) == NULL) {
3634 r = SSH_ERR_ALLOC_FAIL;
3635 goto out;
3636 }
3637 if ((r = sshbuf_get_string(buf, &ed25519_pk, &pklen)) != 0)
3638 goto out;
3639 if (pklen != ED25519_PK_SZ) {
3640 r = SSH_ERR_INVALID_FORMAT;
3641 goto out;
3642 }
3643 if ((k->sk_key_handle = sshbuf_new()) == NULL ||
3644 (k->sk_reserved = sshbuf_new()) == NULL) {
3645 r = SSH_ERR_ALLOC_FAIL;
3646 goto out;
3647 }
3648 if ((r = sshbuf_get_cstring(buf, &k->sk_application,
3649 NULL)) != 0 ||
3650 (r = sshbuf_get_u8(buf, &k->sk_flags)) != 0 ||
3651 (r = sshbuf_get_stringb(buf, k->sk_key_handle)) != 0 ||
3652 (r = sshbuf_get_stringb(buf, k->sk_reserved)) != 0)
3653 goto out;
3654 k->ed25519_pk = ed25519_pk;
3655 ed25519_pk = NULL;
3656 break;
3657 case KEY_ED25519_SK_CERT: 3576 case KEY_ED25519_SK_CERT:
3658 if ((r = sshkey_froms(buf, &k)) != 0 || 3577 if ((r = sshbuf_get_string(buf, &ed25519_pk, &pklen)) != 0)
3659 (r = sshbuf_get_string(buf, &ed25519_pk, &pklen)) != 0)
3660 goto out;
3661 if (k->type != type) {
3662 r = SSH_ERR_INVALID_FORMAT;
3663 goto out; 3578 goto out;
3664 }
3665 if (pklen != ED25519_PK_SZ) { 3579 if (pklen != ED25519_PK_SZ) {
3666 r = SSH_ERR_INVALID_FORMAT; 3580 r = SSH_ERR_INVALID_FORMAT;
3667 goto out; 3581 goto out;
@@ -3682,10 +3596,7 @@ sshkey_private_deserialize(struct sshbuf *buf, struct sshkey **kp)
3682 break; 3596 break;
3683#ifdef WITH_XMSS 3597#ifdef WITH_XMSS
3684 case KEY_XMSS: 3598 case KEY_XMSS:
3685 if ((k = sshkey_new(type)) == NULL) { 3599 case KEY_XMSS_CERT:
3686 r = SSH_ERR_ALLOC_FAIL;
3687 goto out;
3688 }
3689 if ((r = sshbuf_get_cstring(buf, &xmss_name, NULL)) != 0 || 3600 if ((r = sshbuf_get_cstring(buf, &xmss_name, NULL)) != 0 ||
3690 (r = sshkey_xmss_init(k, xmss_name)) != 0 || 3601 (r = sshkey_xmss_init(k, xmss_name)) != 0 ||
3691 (r = sshbuf_get_string(buf, &xmss_pk, &pklen)) != 0 || 3602 (r = sshbuf_get_string(buf, &xmss_pk, &pklen)) != 0 ||
@@ -3703,28 +3614,6 @@ sshkey_private_deserialize(struct sshbuf *buf, struct sshkey **kp)
3703 if ((r = sshkey_xmss_deserialize_state_opt(k, buf)) != 0) 3614 if ((r = sshkey_xmss_deserialize_state_opt(k, buf)) != 0)
3704 goto out; 3615 goto out;
3705 break; 3616 break;
3706 case KEY_XMSS_CERT:
3707 if ((r = sshkey_froms(buf, &k)) != 0 ||
3708 (r = sshbuf_get_cstring(buf, &xmss_name, NULL)) != 0 ||
3709 (r = sshbuf_get_string(buf, &xmss_pk, &pklen)) != 0 ||
3710 (r = sshbuf_get_string(buf, &xmss_sk, &sklen)) != 0)
3711 goto out;
3712 if (k->type != type || strcmp(xmss_name, k->xmss_name) != 0) {
3713 r = SSH_ERR_INVALID_FORMAT;
3714 goto out;
3715 }
3716 if (pklen != sshkey_xmss_pklen(k) ||
3717 sklen != sshkey_xmss_sklen(k)) {
3718 r = SSH_ERR_INVALID_FORMAT;
3719 goto out;
3720 }
3721 k->xmss_pk = xmss_pk;
3722 k->xmss_sk = xmss_sk;
3723 xmss_pk = xmss_sk = NULL;
3724 /* optional internal state */
3725 if ((r = sshkey_xmss_deserialize_state_opt(k, buf)) != 0)
3726 goto out;
3727 break;
3728#endif /* WITH_XMSS */ 3617#endif /* WITH_XMSS */
3729 default: 3618 default:
3730 r = SSH_ERR_KEY_TYPE_UNKNOWN; 3619 r = SSH_ERR_KEY_TYPE_UNKNOWN;
@@ -4054,46 +3943,31 @@ sshkey_private_to_blob2(struct sshkey *prv, struct sshbuf *blob,
4054 sshbuf_free(encrypted); 3943 sshbuf_free(encrypted);
4055 cipher_free(ciphercontext); 3944 cipher_free(ciphercontext);
4056 explicit_bzero(salt, sizeof(salt)); 3945 explicit_bzero(salt, sizeof(salt));
4057 if (key != NULL) { 3946 if (key != NULL)
4058 explicit_bzero(key, keylen + ivlen); 3947 freezero(key, keylen + ivlen);
4059 free(key); 3948 if (pubkeyblob != NULL)
4060 } 3949 freezero(pubkeyblob, pubkeylen);
4061 if (pubkeyblob != NULL) { 3950 if (b64 != NULL)
4062 explicit_bzero(pubkeyblob, pubkeylen); 3951 freezero(b64, strlen(b64));
4063 free(pubkeyblob);
4064 }
4065 if (b64 != NULL) {
4066 explicit_bzero(b64, strlen(b64));
4067 free(b64);
4068 }
4069 return r; 3952 return r;
4070} 3953}
4071 3954
4072static int 3955static int
4073sshkey_parse_private2(struct sshbuf *blob, int type, const char *passphrase, 3956private2_uudecode(struct sshbuf *blob, struct sshbuf **decodedp)
4074 struct sshkey **keyp, char **commentp)
4075{ 3957{
4076 char *comment = NULL, *ciphername = NULL, *kdfname = NULL;
4077 const struct sshcipher *cipher = NULL;
4078 const u_char *cp; 3958 const u_char *cp;
4079 int r = SSH_ERR_INTERNAL_ERROR;
4080 size_t encoded_len; 3959 size_t encoded_len;
4081 size_t i, keylen = 0, ivlen = 0, authlen = 0, slen = 0; 3960 int r;
3961 u_char last;
4082 struct sshbuf *encoded = NULL, *decoded = NULL; 3962 struct sshbuf *encoded = NULL, *decoded = NULL;
4083 struct sshbuf *kdf = NULL, *decrypted = NULL;
4084 struct sshcipher_ctx *ciphercontext = NULL;
4085 struct sshkey *k = NULL;
4086 u_char *key = NULL, *salt = NULL, *dp, pad, last;
4087 u_int blocksize, rounds, nkeys, encrypted_len, check1, check2;
4088 3963
4089 if (keyp != NULL) 3964 if (blob == NULL || decodedp == NULL)
4090 *keyp = NULL; 3965 return SSH_ERR_INVALID_ARGUMENT;
4091 if (commentp != NULL) 3966
4092 *commentp = NULL; 3967 *decodedp = NULL;
4093 3968
4094 if ((encoded = sshbuf_new()) == NULL || 3969 if ((encoded = sshbuf_new()) == NULL ||
4095 (decoded = sshbuf_new()) == NULL || 3970 (decoded = sshbuf_new()) == NULL) {
4096 (decrypted = sshbuf_new()) == NULL) {
4097 r = SSH_ERR_ALLOC_FAIL; 3971 r = SSH_ERR_ALLOC_FAIL;
4098 goto out; 3972 goto out;
4099 } 3973 }
@@ -4143,13 +4017,56 @@ sshkey_parse_private2(struct sshbuf *blob, int type, const char *passphrase,
4143 r = SSH_ERR_INVALID_FORMAT; 4017 r = SSH_ERR_INVALID_FORMAT;
4144 goto out; 4018 goto out;
4145 } 4019 }
4020 /* success */
4021 *decodedp = decoded;
4022 decoded = NULL;
4023 r = 0;
4024 out:
4025 sshbuf_free(encoded);
4026 sshbuf_free(decoded);
4027 return r;
4028}
4029
4030static int
4031private2_decrypt(struct sshbuf *decoded, const char *passphrase,
4032 struct sshbuf **decryptedp, struct sshkey **pubkeyp)
4033{
4034 char *ciphername = NULL, *kdfname = NULL;
4035 const struct sshcipher *cipher = NULL;
4036 int r = SSH_ERR_INTERNAL_ERROR;
4037 size_t keylen = 0, ivlen = 0, authlen = 0, slen = 0;
4038 struct sshbuf *kdf = NULL, *decrypted = NULL;
4039 struct sshcipher_ctx *ciphercontext = NULL;
4040 struct sshkey *pubkey = NULL;
4041 u_char *key = NULL, *salt = NULL, *dp;
4042 u_int blocksize, rounds, nkeys, encrypted_len, check1, check2;
4043
4044 if (decoded == NULL || decryptedp == NULL || pubkeyp == NULL)
4045 return SSH_ERR_INVALID_ARGUMENT;
4046
4047 *decryptedp = NULL;
4048 *pubkeyp = NULL;
4049
4050 if ((decrypted = sshbuf_new()) == NULL) {
4051 r = SSH_ERR_ALLOC_FAIL;
4052 goto out;
4053 }
4054
4146 /* parse public portion of key */ 4055 /* parse public portion of key */
4147 if ((r = sshbuf_consume(decoded, sizeof(AUTH_MAGIC))) != 0 || 4056 if ((r = sshbuf_consume(decoded, sizeof(AUTH_MAGIC))) != 0 ||
4148 (r = sshbuf_get_cstring(decoded, &ciphername, NULL)) != 0 || 4057 (r = sshbuf_get_cstring(decoded, &ciphername, NULL)) != 0 ||
4149 (r = sshbuf_get_cstring(decoded, &kdfname, NULL)) != 0 || 4058 (r = sshbuf_get_cstring(decoded, &kdfname, NULL)) != 0 ||
4150 (r = sshbuf_froms(decoded, &kdf)) != 0 || 4059 (r = sshbuf_froms(decoded, &kdf)) != 0 ||
4151 (r = sshbuf_get_u32(decoded, &nkeys)) != 0 || 4060 (r = sshbuf_get_u32(decoded, &nkeys)) != 0)
4152 (r = sshbuf_skip_string(decoded)) != 0 || /* pubkey */ 4061 goto out;
4062
4063 if (nkeys != 1) {
4064 /* XXX only one key supported at present */
4065 r = SSH_ERR_INVALID_FORMAT;
4066 goto out;
4067 }
4068
4069 if ((r = sshkey_froms(decoded, &pubkey)) != 0 ||
4153 (r = sshbuf_get_u32(decoded, &encrypted_len)) != 0) 4070 (r = sshbuf_get_u32(decoded, &encrypted_len)) != 0)
4154 goto out; 4071 goto out;
4155 4072
@@ -4157,23 +4074,18 @@ sshkey_parse_private2(struct sshbuf *blob, int type, const char *passphrase,
4157 r = SSH_ERR_KEY_UNKNOWN_CIPHER; 4074 r = SSH_ERR_KEY_UNKNOWN_CIPHER;
4158 goto out; 4075 goto out;
4159 } 4076 }
4160 if ((passphrase == NULL || strlen(passphrase) == 0) &&
4161 strcmp(ciphername, "none") != 0) {
4162 /* passphrase required */
4163 r = SSH_ERR_KEY_WRONG_PASSPHRASE;
4164 goto out;
4165 }
4166 if (strcmp(kdfname, "none") != 0 && strcmp(kdfname, "bcrypt") != 0) { 4077 if (strcmp(kdfname, "none") != 0 && strcmp(kdfname, "bcrypt") != 0) {
4167 r = SSH_ERR_KEY_UNKNOWN_CIPHER; 4078 r = SSH_ERR_KEY_UNKNOWN_CIPHER;
4168 goto out; 4079 goto out;
4169 } 4080 }
4170 if (!strcmp(kdfname, "none") && strcmp(ciphername, "none") != 0) { 4081 if (strcmp(kdfname, "none") == 0 && strcmp(ciphername, "none") != 0) {
4171 r = SSH_ERR_INVALID_FORMAT; 4082 r = SSH_ERR_INVALID_FORMAT;
4172 goto out; 4083 goto out;
4173 } 4084 }
4174 if (nkeys != 1) { 4085 if ((passphrase == NULL || strlen(passphrase) == 0) &&
4175 /* XXX only one key supported */ 4086 strcmp(kdfname, "none") != 0) {
4176 r = SSH_ERR_INVALID_FORMAT; 4087 /* passphrase required */
4088 r = SSH_ERR_KEY_WRONG_PASSPHRASE;
4177 goto out; 4089 goto out;
4178 } 4090 }
4179 4091
@@ -4238,13 +4150,38 @@ sshkey_parse_private2(struct sshbuf *blob, int type, const char *passphrase,
4238 r = SSH_ERR_KEY_WRONG_PASSPHRASE; 4150 r = SSH_ERR_KEY_WRONG_PASSPHRASE;
4239 goto out; 4151 goto out;
4240 } 4152 }
4153 /* success */
4154 *decryptedp = decrypted;
4155 decrypted = NULL;
4156 *pubkeyp = pubkey;
4157 pubkey = NULL;
4158 r = 0;
4159 out:
4160 cipher_free(ciphercontext);
4161 free(ciphername);
4162 free(kdfname);
4163 sshkey_free(pubkey);
4164 if (salt != NULL) {
4165 explicit_bzero(salt, slen);
4166 free(salt);
4167 }
4168 if (key != NULL) {
4169 explicit_bzero(key, keylen + ivlen);
4170 free(key);
4171 }
4172 sshbuf_free(kdf);
4173 sshbuf_free(decrypted);
4174 return r;
4175}
4241 4176
4242 /* Load the private key and comment */ 4177/* Check deterministic padding after private key */
4243 if ((r = sshkey_private_deserialize(decrypted, &k)) != 0 || 4178static int
4244 (r = sshbuf_get_cstring(decrypted, &comment, NULL)) != 0) 4179private2_check_padding(struct sshbuf *decrypted)
4245 goto out; 4180{
4181 u_char pad;
4182 size_t i;
4183 int r = SSH_ERR_INTERNAL_ERROR;
4246 4184
4247 /* Check deterministic padding */
4248 i = 0; 4185 i = 0;
4249 while (sshbuf_len(decrypted)) { 4186 while (sshbuf_len(decrypted)) {
4250 if ((r = sshbuf_get_u8(decrypted, &pad)) != 0) 4187 if ((r = sshbuf_get_u8(decrypted, &pad)) != 0)
@@ -4254,8 +4191,54 @@ sshkey_parse_private2(struct sshbuf *blob, int type, const char *passphrase,
4254 goto out; 4191 goto out;
4255 } 4192 }
4256 } 4193 }
4194 /* success */
4195 r = 0;
4196 out:
4197 explicit_bzero(&pad, sizeof(pad));
4198 explicit_bzero(&i, sizeof(i));
4199 return r;
4200}
4257 4201
4258 /* XXX decode pubkey and check against private */ 4202static int
4203sshkey_parse_private2(struct sshbuf *blob, int type, const char *passphrase,
4204 struct sshkey **keyp, char **commentp)
4205{
4206 char *comment = NULL;
4207 int r = SSH_ERR_INTERNAL_ERROR;
4208 struct sshbuf *decoded = NULL, *decrypted = NULL;
4209 struct sshkey *k = NULL, *pubkey = NULL;
4210
4211 if (keyp != NULL)
4212 *keyp = NULL;
4213 if (commentp != NULL)
4214 *commentp = NULL;
4215
4216 /* Undo base64 encoding and decrypt the private section */
4217 if ((r = private2_uudecode(blob, &decoded)) != 0 ||
4218 (r = private2_decrypt(decoded, passphrase,
4219 &decrypted, &pubkey)) != 0)
4220 goto out;
4221
4222 if (type != KEY_UNSPEC &&
4223 sshkey_type_plain(type) != sshkey_type_plain(pubkey->type)) {
4224 r = SSH_ERR_KEY_TYPE_MISMATCH;
4225 goto out;
4226 }
4227
4228 /* Load the private key and comment */
4229 if ((r = sshkey_private_deserialize(decrypted, &k)) != 0 ||
4230 (r = sshbuf_get_cstring(decrypted, &comment, NULL)) != 0)
4231 goto out;
4232
4233 /* Check deterministic padding after private section */
4234 if ((r = private2_check_padding(decrypted)) != 0)
4235 goto out;
4236
4237 /* Check that the public key in the envelope matches the private key */
4238 if (!sshkey_equal(pubkey, k)) {
4239 r = SSH_ERR_INVALID_FORMAT;
4240 goto out;
4241 }
4259 4242
4260 /* success */ 4243 /* success */
4261 r = 0; 4244 r = 0;
@@ -4268,27 +4251,63 @@ sshkey_parse_private2(struct sshbuf *blob, int type, const char *passphrase,
4268 comment = NULL; 4251 comment = NULL;
4269 } 4252 }
4270 out: 4253 out:
4271 pad = 0;
4272 cipher_free(ciphercontext);
4273 free(ciphername);
4274 free(kdfname);
4275 free(comment); 4254 free(comment);
4276 if (salt != NULL) {
4277 explicit_bzero(salt, slen);
4278 free(salt);
4279 }
4280 if (key != NULL) {
4281 explicit_bzero(key, keylen + ivlen);
4282 free(key);
4283 }
4284 sshbuf_free(encoded);
4285 sshbuf_free(decoded); 4255 sshbuf_free(decoded);
4286 sshbuf_free(kdf);
4287 sshbuf_free(decrypted); 4256 sshbuf_free(decrypted);
4288 sshkey_free(k); 4257 sshkey_free(k);
4258 sshkey_free(pubkey);
4289 return r; 4259 return r;
4290} 4260}
4291 4261
4262static int
4263sshkey_parse_private2_pubkey(struct sshbuf *blob, int type,
4264 struct sshkey **keyp)
4265{
4266 int r = SSH_ERR_INTERNAL_ERROR;
4267 struct sshbuf *decoded = NULL;
4268 struct sshkey *pubkey = NULL;
4269 u_int nkeys = 0;
4270
4271 if (keyp != NULL)
4272 *keyp = NULL;
4273
4274 if ((r = private2_uudecode(blob, &decoded)) != 0)
4275 goto out;
4276 /* parse public key from unencrypted envelope */
4277 if ((r = sshbuf_consume(decoded, sizeof(AUTH_MAGIC))) != 0 ||
4278 (r = sshbuf_skip_string(decoded)) != 0 || /* cipher */
4279 (r = sshbuf_skip_string(decoded)) != 0 || /* KDF alg */
4280 (r = sshbuf_skip_string(decoded)) != 0 || /* KDF hint */
4281 (r = sshbuf_get_u32(decoded, &nkeys)) != 0)
4282 goto out;
4283
4284 if (nkeys != 1) {
4285 /* XXX only one key supported at present */
4286 r = SSH_ERR_INVALID_FORMAT;
4287 goto out;
4288 }
4289
4290 /* Parse the public key */
4291 if ((r = sshkey_froms(decoded, &pubkey)) != 0)
4292 goto out;
4293
4294 if (type != KEY_UNSPEC &&
4295 sshkey_type_plain(type) != sshkey_type_plain(pubkey->type)) {
4296 r = SSH_ERR_KEY_TYPE_MISMATCH;
4297 goto out;
4298 }
4299
4300 /* success */
4301 r = 0;
4302 if (keyp != NULL) {
4303 *keyp = pubkey;
4304 pubkey = NULL;
4305 }
4306 out:
4307 sshbuf_free(decoded);
4308 sshkey_free(pubkey);
4309 return r;
4310}
4292 4311
4293#ifdef WITH_OPENSSL 4312#ifdef WITH_OPENSSL
4294/* convert SSH v2 key to PEM or PKCS#8 format */ 4313/* convert SSH v2 key to PEM or PKCS#8 format */
@@ -4615,24 +4634,16 @@ sshkey_parse_private_fileblob_type(struct sshbuf *blob, int type,
4615 *commentp = NULL; 4634 *commentp = NULL;
4616 4635
4617 switch (type) { 4636 switch (type) {
4618#ifdef WITH_OPENSSL
4619 case KEY_DSA:
4620 case KEY_ECDSA:
4621 case KEY_RSA:
4622 return sshkey_parse_private_pem_fileblob(blob, type,
4623 passphrase, keyp);
4624#endif /* WITH_OPENSSL */
4625 case KEY_ED25519: 4637 case KEY_ED25519:
4626#ifdef WITH_XMSS
4627 case KEY_XMSS: 4638 case KEY_XMSS:
4628#endif /* WITH_XMSS */ 4639 /* No fallback for new-format-only keys */
4629 return sshkey_parse_private2(blob, type, passphrase, 4640 return sshkey_parse_private2(blob, type, passphrase,
4630 keyp, commentp); 4641 keyp, commentp);
4631 case KEY_UNSPEC: 4642 default:
4632 r = sshkey_parse_private2(blob, type, passphrase, keyp, 4643 r = sshkey_parse_private2(blob, type, passphrase, keyp,
4633 commentp); 4644 commentp);
4634 /* Do not fallback to PEM parser if only passphrase is wrong. */ 4645 /* Only fallback to PEM parser if a format error occurred. */
4635 if (r == 0 || r == SSH_ERR_KEY_WRONG_PASSPHRASE) 4646 if (r != SSH_ERR_INVALID_FORMAT)
4636 return r; 4647 return r;
4637#ifdef WITH_OPENSSL 4648#ifdef WITH_OPENSSL
4638 return sshkey_parse_private_pem_fileblob(blob, type, 4649 return sshkey_parse_private_pem_fileblob(blob, type,
@@ -4640,8 +4651,6 @@ sshkey_parse_private_fileblob_type(struct sshbuf *blob, int type,
4640#else 4651#else
4641 return SSH_ERR_INVALID_FORMAT; 4652 return SSH_ERR_INVALID_FORMAT;
4642#endif /* WITH_OPENSSL */ 4653#endif /* WITH_OPENSSL */
4643 default:
4644 return SSH_ERR_KEY_TYPE_UNKNOWN;
4645 } 4654 }
4646} 4655}
4647 4656
@@ -4664,6 +4673,20 @@ sshkey_sig_details_free(struct sshkey_sig_details *details)
4664 freezero(details, sizeof(*details)); 4673 freezero(details, sizeof(*details));
4665} 4674}
4666 4675
4676int
4677sshkey_parse_pubkey_from_private_fileblob_type(struct sshbuf *blob, int type,
4678 struct sshkey **pubkeyp)
4679{
4680 int r = SSH_ERR_INTERNAL_ERROR;
4681
4682 if (pubkeyp != NULL)
4683 *pubkeyp = NULL;
4684 /* only new-format private keys bundle a public key inside */
4685 if ((r = sshkey_parse_private2_pubkey(blob, type, pubkeyp)) != 0)
4686 return r;
4687 return 0;
4688}
4689
4667#ifdef WITH_XMSS 4690#ifdef WITH_XMSS
4668/* 4691/*
4669 * serialize the key with the current state and forward the state 4692 * serialize the key with the current state and forward the state