From bac36d1fd252ac8b3cb8bfa3855f20762635cd50 Mon Sep 17 00:00:00 2001 From: Tom Yu Date: Sat, 4 Dec 2010 05:11:04 +0000 Subject: [PATCH] SA-2010-007 Checksum vulnerabilities (CVE-2010-1324 and others) Apply patch for MITKRB5-SA-2010-007. 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: 6833 target_version: 1.8.4 version_fixed: 1.8.4 status: resolved git-svn-id: svn://anonsvn.mit.edu/krb5/branches/krb5-1-8@24560 dc483132-0cff-0310-8789-dd5450dbe970 --- src/lib/crypto/krb/cksumtypes.c | 2 +- src/lib/crypto/krb/dk/derive.c | 2 ++ src/lib/crypto/krb/keyed_checksum_types.c | 7 ++++++ src/lib/gssapi/krb5/util_crypt.c | 20 ++++++++++++---- src/lib/krb5/krb/mk_safe.c | 24 ++++++++++++++++--- src/lib/krb5/krb/pac.c | 2 ++ src/lib/krb5/krb/preauth2.c | 5 ++-- src/plugins/preauth/pkinit/pkinit_srv.c | 29 +++++++++++++++-------- 8 files changed, 71 insertions(+), 20 deletions(-) diff --git a/src/lib/crypto/krb/cksumtypes.c b/src/lib/crypto/krb/cksumtypes.c index 6e16b4ea8..29800b7d7 100644 --- a/src/lib/crypto/krb/cksumtypes.c +++ b/src/lib/crypto/krb/cksumtypes.c @@ -101,7 +101,7 @@ const struct krb5_cksumtypes krb5int_cksumtypes_list[] = { { CKSUMTYPE_MD5_HMAC_ARCFOUR, "md5-hmac-rc4", { 0 }, "Microsoft MD5 HMAC", - NULL, &krb5int_hash_md5, + &krb5int_enc_arcfour, &krb5int_hash_md5, krb5int_hmacmd5_checksum, NULL, 16, 16, 0 }, }; diff --git a/src/lib/crypto/krb/dk/derive.c b/src/lib/crypto/krb/dk/derive.c index 5fd887647..221df5d7b 100644 --- a/src/lib/crypto/krb/dk/derive.c +++ b/src/lib/crypto/krb/dk/derive.c @@ -91,6 +91,8 @@ krb5int_derive_random(const struct krb5_enc_provider *enc, blocksize = enc->block_size; keybytes = enc->keybytes; + if (blocksize == 1) + return KRB5_BAD_ENCTYPE; if (inkey->keyblock.length != enc->keylength || outrnd->length != keybytes) return KRB5_CRYPTO_INTERNAL; diff --git a/src/lib/crypto/krb/keyed_checksum_types.c b/src/lib/crypto/krb/keyed_checksum_types.c index 3cd1ebcae..8adef1d16 100644 --- a/src/lib/crypto/krb/keyed_checksum_types.c +++ b/src/lib/crypto/krb/keyed_checksum_types.c @@ -35,6 +35,13 @@ is_keyed_for(const struct krb5_cksumtypes *ctp, { if (ctp->flags & CKSUM_UNKEYED) return FALSE; + /* Stream ciphers do not play well with RFC 3961 key derivation, so be + * conservative with RC4. */ + if ((ktp->etype == ENCTYPE_ARCFOUR_HMAC || + ktp->etype == ENCTYPE_ARCFOUR_HMAC_EXP) && + ctp->ctype != CKSUMTYPE_HMAC_MD5_ARCFOUR && + ctp->ctype != CKSUMTYPE_MD5_HMAC_ARCFOUR) + return FALSE; return (!ctp->enc || ktp->enc == ctp->enc); } diff --git a/src/lib/gssapi/krb5/util_crypt.c b/src/lib/gssapi/krb5/util_crypt.c index 9699c2656..2cdffc874 100644 --- a/src/lib/gssapi/krb5/util_crypt.c +++ b/src/lib/gssapi/krb5/util_crypt.c @@ -119,10 +119,22 @@ kg_setup_keys(krb5_context context, krb5_gss_ctx_id_rec *ctx, krb5_key subkey, if (code != 0) return code; - code = (*kaccess.mandatory_cksumtype)(context, subkey->keyblock.enctype, - cksumtype); - if (code != 0) - return code; + switch (subkey->keyblock.enctype) { + case ENCTYPE_DES_CBC_MD4: + *cksumtype = CKSUMTYPE_RSA_MD4_DES; + break; + case ENCTYPE_DES_CBC_MD5: + case ENCTYPE_DES_CBC_CRC: + *cksumtype = CKSUMTYPE_RSA_MD5_DES; + break; + default: + code = (*kaccess.mandatory_cksumtype)(context, + subkey->keyblock.enctype, + cksumtype); + if (code != 0) + return code; + break; + } switch (subkey->keyblock.enctype) { case ENCTYPE_DES_CBC_MD5: diff --git a/src/lib/krb5/krb/mk_safe.c b/src/lib/krb5/krb/mk_safe.c index eaa3add82..2c790b7cf 100644 --- a/src/lib/krb5/krb/mk_safe.c +++ b/src/lib/krb5/krb/mk_safe.c @@ -215,10 +215,28 @@ krb5_mk_safe(krb5_context context, krb5_auth_context auth_context, 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); + if (i < nsumtypes) + sumtype = auth_context->safe_cksumtype; + else { + switch (enctype) { + case ENCTYPE_DES_CBC_MD4: + sumtype = CKSUMTYPE_RSA_MD4_DES; + break; + case ENCTYPE_DES_CBC_MD5: + case ENCTYPE_DES_CBC_CRC: + sumtype = CKSUMTYPE_RSA_MD5_DES; + break; + default: + retval = krb5int_c_mandatory_cksumtype(context, enctype, + &sumtype); + if (retval) { + CLEANUP_DONE(); + goto error; + } + break; + } + } } if ((retval = krb5_mk_safe_basic(context, userdata, key, &replaydata, plocal_fulladdr, premote_fulladdr, diff --git a/src/lib/krb5/krb/pac.c b/src/lib/krb5/krb/pac.c index cda09b255..abec59b02 100644 --- a/src/lib/krb5/krb/pac.c +++ b/src/lib/krb5/krb/pac.c @@ -582,6 +582,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); diff --git a/src/lib/krb5/krb/preauth2.c b/src/lib/krb5/krb/preauth2.c index cf99a29b1..2776b19e9 100644 --- a/src/lib/krb5/krb/preauth2.c +++ b/src/lib/krb5/krb/preauth2.c @@ -1578,7 +1578,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, @@ -1592,7 +1594,6 @@ pa_sam_2(krb5_context context, krb5_kdc_req *request, krb5_pa_data *in_padata, } if (valid_cksum) break; - cksum++; } if (!valid_cksum) { diff --git a/src/plugins/preauth/pkinit/pkinit_srv.c b/src/plugins/preauth/pkinit/pkinit_srv.c index 719b01c80..db38bcc54 100644 --- a/src/plugins/preauth/pkinit/pkinit_srv.c +++ b/src/plugins/preauth/pkinit/pkinit_srv.c @@ -691,8 +691,7 @@ pkinit_server_return_padata(krb5_context context, krb5_reply_key_pack *key_pack = NULL; krb5_reply_key_pack_draft9 *key_pack9 = NULL; krb5_data *encoded_key_pack = NULL; - unsigned int num_types; - krb5_cksumtype *cksum_types = NULL; + krb5_cksumtype cksum_type; pkinit_kdc_context plgctx; pkinit_kdc_req_context reqctx; @@ -882,14 +881,25 @@ pkinit_server_return_padata(krb5_context context, retval = ENOMEM; goto cleanup; } - /* retrieve checksums for a given enctype of the reply key */ - retval = krb5_c_keyed_checksum_types(context, - encrypting_key->enctype, &num_types, &cksum_types); - if (retval) - goto cleanup; - /* pick the first of acceptable enctypes for the checksum */ - retval = krb5_c_make_checksum(context, cksum_types[0], + switch (encrypting_key->enctype) { + case ENCTYPE_DES_CBC_MD4: + cksum_type = CKSUMTYPE_RSA_MD4_DES; + break; + case ENCTYPE_DES_CBC_MD5: + case ENCTYPE_DES_CBC_CRC: + cksum_type = CKSUMTYPE_RSA_MD5_DES; + break; + default: + retval = krb5int_c_mandatory_cksumtype(context, + encrypting_key->enctype, + &cksum_type); + if (retval) + goto cleanup; + break; + } + + retval = krb5_c_make_checksum(context, cksum_type, encrypting_key, KRB5_KEYUSAGE_TGS_REQ_AUTH_CKSUM, req_pkt, &key_pack->asChecksum); if (retval) { @@ -1033,7 +1043,6 @@ cleanup: krb5_free_data(context, encoded_key_pack); free(dh_pubkey); free(server_key); - free(cksum_types); switch ((int)padata->pa_type) { case KRB5_PADATA_PK_AS_REQ: -- 2.26.2