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