diff options
author | Greg Hudson <ghudson@mit.edu> | 2010-11-30 21:20:49 +0000 |
---|---|---|
committer | Greg Hudson <ghudson@mit.edu> | 2010-11-30 21:20:49 +0000 |
commit | 1c411f836063e4e6d67390d205e043149302fdd9 (patch) | |
tree | a8909e74c2c23b7b1c5b1282cf8dd4119c92c989 /src/lib/krb5 | |
parent | a87789f75f1a7563982953e088927135bb5d6e85 (diff) | |
download | krb5-1c411f836063e4e6d67390d205e043149302fdd9.tar.gz krb5-1c411f836063e4e6d67390d205e043149302fdd9.tar.xz krb5-1c411f836063e4e6d67390d205e043149302fdd9.zip |
SA-2010-007 Checksum vulnerabilities (CVE-2010-1324 and others)
Fix multiple checksum handling bugs, as described in:
CVE-2010-1324
CVE-2010-1323
CVE-2010-4020
CVE-2010-4021
* Return the correct (keyed) checksums as the mandatory checksum type
for DES enctypes.
* Restrict simplified-profile checksums to their corresponding etypes.
* Add internal checks to reduce the risk of stream ciphers being used
with simplified-profile key derivation or other algorithms relying
on the block encryption primitive.
* Use the mandatory checksum type for the PKINIT KDC signature,
instead of the first-listed keyed checksum.
* Use the mandatory checksum type when sending KRB-SAFE messages by
default, instead of the first-listed keyed checksum.
* Use the mandatory checksum type for the t_kperf test program.
* Use the mandatory checksum type (without additional logic) for the
FAST request checksum.
* Preserve the existing checksum choices (unkeyed checksums for DES
enctypes) for the authenticator checksum, using explicit logic.
* Ensure that SAM checksums received from the KDC are keyed.
* Ensure that PAC checksums are keyed.
ticket: 6827
git-svn-id: svn://anonsvn.mit.edu/krb5/trunk@24538 dc483132-0cff-0310-8789-dd5450dbe970
Diffstat (limited to 'src/lib/krb5')
-rw-r--r-- | src/lib/krb5/krb/fast.c | 10 | ||||
-rw-r--r-- | src/lib/krb5/krb/mk_req_ext.c | 39 | ||||
-rw-r--r-- | src/lib/krb5/krb/mk_safe.c | 55 | ||||
-rw-r--r-- | src/lib/krb5/krb/pac.c | 4 | ||||
-rw-r--r-- | src/lib/krb5/krb/preauth2.c | 5 |
5 files changed, 67 insertions, 46 deletions
diff --git a/src/lib/krb5/krb/fast.c b/src/lib/krb5/krb/fast.c index cc9f899a7..3137195ae 100644 --- a/src/lib/krb5/krb/fast.c +++ b/src/lib/krb5/krb/fast.c @@ -211,7 +211,6 @@ krb5int_fast_prep_req(krb5_context context, krb5_data *encoded_fast_req = NULL; krb5_data *encoded_armored_req = NULL; krb5_data *local_encoded_result = NULL; - krb5_cksumtype cksumtype; krb5_data random_data; char random_buf[4]; @@ -247,15 +246,8 @@ krb5int_fast_prep_req(krb5_context context, } if (retval == 0) armored_req->armor = state->armor; - if (retval == 0) - retval = krb5int_c_mandatory_cksumtype(context, - state->armor_key->enctype, - &cksumtype); - /* DES enctypes have unkeyed mandatory checksums; need a keyed one. */ - if (retval == 0 && !krb5_c_is_keyed_cksum(cksumtype)) - cksumtype = CKSUMTYPE_RSA_MD5_DES; if (retval ==0) - retval = krb5_c_make_checksum(context, cksumtype, state->armor_key, + retval = krb5_c_make_checksum(context, 0, state->armor_key, KRB5_KEYUSAGE_FAST_REQ_CHKSUM, to_be_checksummed, &armored_req->req_checksum); diff --git a/src/lib/krb5/krb/mk_req_ext.c b/src/lib/krb5/krb/mk_req_ext.c index 3a4004dc0..1979b8d63 100644 --- a/src/lib/krb5/krb/mk_req_ext.c +++ b/src/lib/krb5/krb/mk_req_ext.c @@ -81,6 +81,36 @@ generate_authenticator(krb5_context, krb5_enctype *desired_etypes, krb5_enctype tkt_enctype); +/* Return the checksum type for the AP request, or 0 to use the enctype's + * mandatory checksum. */ +static krb5_cksumtype +ap_req_cksum(krb5_context context, krb5_auth_context auth_context, + krb5_enctype enctype) +{ + /* Use the configured checksum type if one was set. */ + if (auth_context->req_cksumtype) + return auth_context->req_cksumtype; + + /* + * Otherwise choose based on the enctype. For interoperability with very + * old implementations, use unkeyed MD4 or MD5 checkums for DES enctypes. + * (The authenticator checksum does not have to be keyed since it is + * contained within an encrypted blob.) + */ + switch (enctype) { + case ENCTYPE_DES_CBC_CRC: + case ENCTYPE_DES_CBC_MD5: + return CKSUMTYPE_RSA_MD5; + break; + case ENCTYPE_DES_CBC_MD4: + return CKSUMTYPE_RSA_MD4; + break; + default: + /* Use the mandatory checksum type for the enctype. */ + return 0; + } +} + krb5_error_code KRB5_CALLCONV krb5_mk_req_extended(krb5_context context, krb5_auth_context *auth_context, krb5_flags ap_req_options, krb5_data *in_data, @@ -169,13 +199,8 @@ krb5_mk_req_extended(krb5_context context, krb5_auth_context *auth_context, } else { krb5_enctype enctype = krb5_k_key_enctype(context, (*auth_context)->key); - krb5_cksumtype cksumtype; - retval = krb5int_c_mandatory_cksumtype(context, enctype, - &cksumtype); - if (retval) - goto cleanup_cksum; - if ((*auth_context)->req_cksumtype) - cksumtype = (*auth_context)->req_cksumtype; + krb5_cksumtype cksumtype = ap_req_cksum(context, *auth_context, + enctype); if ((retval = krb5_k_make_checksum(context, cksumtype, (*auth_context)->key, diff --git a/src/lib/krb5/krb/mk_safe.c b/src/lib/krb5/krb/mk_safe.c index eaa3add82..334701dd5 100644 --- a/src/lib/krb5/krb/mk_safe.c +++ b/src/lib/krb5/krb/mk_safe.c @@ -59,10 +59,9 @@ krb5_mk_safe_basic(krb5_context context, const krb5_data *userdata, krb5_checksum safe_checksum; krb5_data *scratch1, *scratch2; - if (!krb5_c_valid_cksumtype(sumtype)) + if (sumtype && !krb5_c_valid_cksumtype(sumtype)) return KRB5_PROG_SUMTYPE_NOSUPP; - if (!krb5_c_is_coll_proof_cksum(sumtype) - || !krb5_c_is_keyed_cksum(sumtype)) + if (sumtype && !krb5_c_is_keyed_cksum(sumtype)) return KRB5KRB_AP_ERR_INAPP_CKSUM; safemsg.user_data = *userdata; @@ -110,6 +109,30 @@ cleanup_checksum: return retval; } +/* Return the checksum type for the KRB-SAFE message, or 0 to use the enctype's + * mandatory checksum. */ +static krb5_cksumtype +safe_cksumtype(krb5_context context, krb5_auth_context auth_context, + krb5_enctype enctype) +{ + krb5_error_code retval; + unsigned int nsumtypes, i; + krb5_cksumtype *sumtypes; + + /* Use the auth context's safe_cksumtype if it is valid for the enctype. + * Otherwise return 0 for the mandatory checksum. */ + retval = krb5_c_keyed_checksum_types(context, enctype, &nsumtypes, + &sumtypes); + if (retval != 0 || nsumtypes == 0) + return 0; + for (i = 0; i < nsumtypes; i++) { + if (auth_context->safe_cksumtype == sumtypes[i]) + break; + } + krb5_free_cksumtypes(context, sumtypes); + return (i == nsumtypes) ? 0 : auth_context->safe_cksumtype; +} + krb5_error_code KRB5_CALLCONV krb5_mk_safe(krb5_context context, krb5_auth_context auth_context, const krb5_data *userdata, krb5_data *outbuf, @@ -195,31 +218,7 @@ krb5_mk_safe(krb5_context context, krb5_auth_context auth_context, } } - { - krb5_enctype enctype = krb5_k_key_enctype(context, key); - unsigned int nsumtypes; - unsigned int i; - krb5_cksumtype *sumtypes; - retval = krb5_c_keyed_checksum_types (context, enctype, - &nsumtypes, &sumtypes); - if (retval) { - CLEANUP_DONE (); - goto error; - } - if (nsumtypes == 0) { - retval = KRB5_BAD_ENCTYPE; - krb5_free_cksumtypes (context, sumtypes); - CLEANUP_DONE (); - goto error; - } - for (i = 0; i < nsumtypes; i++) - if (auth_context->safe_cksumtype == sumtypes[i]) - break; - if (i == nsumtypes) - i = 0; - sumtype = sumtypes[i]; - krb5_free_cksumtypes (context, sumtypes); - } + sumtype = safe_cksumtype(context, auth_context, key->keyblock.enctype); if ((retval = krb5_mk_safe_basic(context, userdata, key, &replaydata, plocal_fulladdr, premote_fulladdr, sumtype, outbuf))) { diff --git a/src/lib/krb5/krb/pac.c b/src/lib/krb5/krb/pac.c index 5b6e18288..983b4e8a5 100644 --- a/src/lib/krb5/krb/pac.c +++ b/src/lib/krb5/krb/pac.c @@ -533,6 +533,8 @@ k5_pac_verify_server_checksum(krb5_context context, checksum.checksum_type = load_32_le(p); checksum.length = checksum_data.length - PAC_SIGNATURE_DATA_LENGTH; checksum.contents = p + PAC_SIGNATURE_DATA_LENGTH; + if (!krb5_c_is_keyed_cksum(checksum.checksum_type)) + return KRB5KRB_AP_ERR_INAPP_CKSUM; pac_data.length = pac->data.length; pac_data.data = malloc(pac->data.length); @@ -603,6 +605,8 @@ k5_pac_verify_kdc_checksum(krb5_context context, checksum.checksum_type = load_32_le(p); checksum.length = privsvr_checksum.length - PAC_SIGNATURE_DATA_LENGTH; checksum.contents = p + PAC_SIGNATURE_DATA_LENGTH; + if (!krb5_c_is_keyed_cksum(checksum.checksum_type)) + return KRB5KRB_AP_ERR_INAPP_CKSUM; server_checksum.data += PAC_SIGNATURE_DATA_LENGTH; server_checksum.length -= PAC_SIGNATURE_DATA_LENGTH; diff --git a/src/lib/krb5/krb/preauth2.c b/src/lib/krb5/krb/preauth2.c index 5d7d2448c..f4896eb96 100644 --- a/src/lib/krb5/krb/preauth2.c +++ b/src/lib/krb5/krb/preauth2.c @@ -1283,7 +1283,9 @@ pa_sam_2(krb5_context context, krb5_kdc_req *request, krb5_pa_data *in_padata, cksum = sc2->sam_cksum; - while (*cksum) { + for (; *cksum; cksum++) { + if (!krb5_c_is_keyed_cksum((*cksum)->checksum_type)) + continue; /* Check this cksum */ retval = krb5_c_verify_checksum(context, as_key, KRB5_KEYUSAGE_PA_SAM_CHALLENGE_CKSUM, @@ -1297,7 +1299,6 @@ pa_sam_2(krb5_context context, krb5_kdc_req *request, krb5_pa_data *in_padata, } if (valid_cksum) break; - cksum++; } if (!valid_cksum) { |