SA-2010-007 Checksum vulnerabilities (CVE-2010-1324 and others)
authorTom Yu <tlyu@mit.edu>
Mon, 6 Dec 2010 23:23:17 +0000 (23:23 +0000)
committerTom Yu <tlyu@mit.edu>
Mon, 6 Dec 2010 23:23:17 +0000 (23:23 +0000)
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: 6837
target_version: 1.7.2
version_fixed: 1.7.2
status: resolved

git-svn-id: svn://anonsvn.mit.edu/krb5/branches/krb5-1-7@24562 dc483132-0cff-0310-8789-dd5450dbe970

src/lib/crypto/dk/derive.c
src/lib/crypto/keyed_checksum_types.c
src/lib/gssapi/krb5/util_crypt.c
src/lib/krb5/krb/mk_safe.c
src/lib/krb5/krb/pac.c
src/lib/krb5/krb/preauth2.c
src/plugins/preauth/pkinit/pkinit_srv.c

index 77b05fa1abcdf3c5e550110dcaf2e982dbd7d7e6..7f5fd5a9618cdc8bb7624ecfb2a8dda24883fd58 100644 (file)
@@ -40,6 +40,8 @@ krb5_derive_key(const struct krb5_enc_provider *enc,
     keybytes = enc->keybytes;
     keylength = enc->keylength;
 
+    if (blocksize == 1)
+       return(KRB5_BAD_ENCTYPE);
     if ((inkey->length != keylength) ||
        (outkey->length != keylength))
        return(KRB5_CRYPTO_INTERNAL);
index 04aa44757c1c54d2eae88c5b1b8964696773a5ab..d4673569e946b37cc9ec1899d7fa843373f29cd9 100644 (file)
@@ -51,6 +51,16 @@ krb5_c_keyed_checksum_types(krb5_context context, krb5_enctype enctype,
 {
     unsigned int i, c;
 
+    if (enctype == ENCTYPE_ARCFOUR_HMAC ||
+       enctype == ENCTYPE_ARCFOUR_HMAC_EXP) {
+       *count = 2;
+       if ((*cksumtypes = malloc(2*sizeof(krb5_cksumtype))) == NULL)
+           return(ENOMEM);
+       (*cksumtypes)[0] = CKSUMTYPE_HMAC_MD5_ARCFOUR;
+       (*cksumtypes)[1] = CKSUMTYPE_MD5_HMAC_ARCFOUR;
+       return(0);
+    }
+
     c = 0;
     for (i=0; i<krb5_cksumtypes_length; i++) {
        if ((krb5_cksumtypes_list[i].keyhash &&
index a8558a594424d0f085b1eb714e08017aa9fed105..1935662a874f7b0851b0cd9c593cc255c74a52f3 100644 (file)
@@ -109,10 +109,22 @@ kg_setup_keys(krb5_context context,
     if (code != 0)
         return code;
 
-    code = (*kaccess.krb5int_c_mandatory_cksumtype)(context, subkey->enctype,
-                                                    cksumtype);
-    if (code != 0)
-        return code;
+    switch (subkey->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.krb5int_c_mandatory_cksumtype)(context,
+                                                        subkey->enctype,
+                                                        cksumtype);
+        if (code != 0)
+            return code;
+        break;
+    }
 
     switch (subkey->enctype) {
     case ENCTYPE_DES_CBC_MD5:
index 0afa61e856835dd4f36344fc0e092d9a3b58b8d7..f36587da353511842855165ae05735d8bc9b9428 100644 (file)
@@ -213,10 +213,29 @@ 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 (keyblock->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,
+                                                      keyblock->enctype,
+                                                      &sumtype);
+               if (retval) {
+                   CLEANUP_DONE();
+                   goto error;
+               }
+               break;
+           }
+       }
     }
     if ((retval = krb5_mk_safe_basic(context, userdata, keyblock, &replaydata, 
                                     plocal_fulladdr, premote_fulladdr,
index c5a7065624917601c0cae118d2e587bb7f3b96dd..21f2ca3a3ee061934608d710d4d6bb7019cd9a54 100644 (file)
@@ -524,6 +524,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);
index ed05babe37daec6b7330d20599515e5056e3322a..96abaa49282df967d58b9516e1646010ea68de89 100644 (file)
@@ -1579,7 +1579,9 @@ krb5_error_code pa_sam_2(krb5_context context,
 
    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,
@@ -1593,7 +1595,6 @@ krb5_error_code pa_sam_2(krb5_context context,
        }
        if (valid_cksum)
           break;
-       cksum++;
    }
 
    if (!valid_cksum) {
index b9a23d7cca023375a06b0b53818089805f235d9e..0c7c6a033ce4a7ccc0537779cc8f935d5222d599 100644 (file)
@@ -664,8 +664,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;
@@ -851,14 +850,24 @@ 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) {
@@ -1006,8 +1015,6 @@ pkinit_server_return_padata(krb5_context context,
        free(dh_pubkey);
     if (server_key != NULL)
        free(server_key);
-    if (cksum_types != NULL)
-       free(cksum_types);
 
     switch ((int)padata->pa_type) {
        case KRB5_PADATA_PK_AS_REQ: