Skip to content

Commit

Permalink
pull up r24538 from trunk
Browse files Browse the repository at this point in the history
 ------------------------------------------------------------------------
 r24538 | ghudson | 2010-11-30 16:20:49 -0500 (Tue, 30 Nov 2010) | 27 lines

 ticket: 6827
 subject: 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
version_fixed: 1.9
status: resolved

git-svn-id: svn://anonsvn.mit.edu/krb5/branches/krb5-1-9@24540 dc483132-0cff-0310-8789-dd5450dbe970
  • Loading branch information
tlyu committed Dec 1, 2010
1 parent cf4d170 commit dfe3625
Show file tree
Hide file tree
Showing 12 changed files with 82 additions and 81 deletions.
9 changes: 2 additions & 7 deletions src/lib/crypto/crypto_tests/t_kperf.c
Expand Up @@ -49,9 +49,8 @@ main(int argc, char **argv)
krb5_keyblock kblock;
krb5_key key;
krb5_enctype enctype;
krb5_cksumtype cktype, *cktypelist;
krb5_cksumtype cktype;
int blocksize, num_blocks, intf, op, i;
unsigned int count;
size_t outlen, cklen;
krb5_data block;
krb5_enc_data outblock;
Expand All @@ -69,11 +68,6 @@ main(int argc, char **argv)
blocksize = atoi(argv[3]);
num_blocks = atoi(argv[4]);

/* Pick the first available keyed checksum type. */
krb5_c_keyed_checksum_types(NULL, enctype, &count, &cktypelist);
assert(count > 0);
cktype = cktypelist[0];

block.data = "notrandom";
block.length = 9;
krb5_c_random_seed(NULL, &block);
Expand All @@ -89,6 +83,7 @@ main(int argc, char **argv)
outblock.ciphertext.length = outlen;
outblock.ciphertext.data = calloc(1, outlen);

krb5int_c_mandatory_cksumtype(NULL, enctype, &cktype);
krb5_c_checksum_length(NULL, cktype, &cklen);
sum.checksum_type = cktype;
sum.length = cklen;
Expand Down
8 changes: 4 additions & 4 deletions src/lib/crypto/krb/cksumtypes.c
Expand Up @@ -76,7 +76,7 @@ const struct krb5_cksumtypes krb5int_cksumtypes_list[] = {

{ CKSUMTYPE_HMAC_SHA1_DES3,
"hmac-sha1-des3", { "hmac-sha1-des3-kd" }, "HMAC-SHA1 DES3 key",
NULL, &krb5int_hash_sha1,
&krb5int_enc_des3, &krb5int_hash_sha1,
krb5int_dk_checksum, NULL,
20, 20, 0 },

Expand All @@ -89,19 +89,19 @@ const struct krb5_cksumtypes krb5int_cksumtypes_list[] = {

{ CKSUMTYPE_HMAC_SHA1_96_AES128,
"hmac-sha1-96-aes128", { 0 }, "HMAC-SHA1 AES128 key",
NULL, &krb5int_hash_sha1,
&krb5int_enc_aes128, &krb5int_hash_sha1,
krb5int_dk_checksum, NULL,
20, 12, 0 },

{ CKSUMTYPE_HMAC_SHA1_96_AES256,
"hmac-sha1-96-aes256", { 0 }, "HMAC-SHA1 AES256 key",
NULL, &krb5int_hash_sha1,
&krb5int_enc_aes256, &krb5int_hash_sha1,
krb5int_dk_checksum, NULL,
20, 12, 0 },

{ 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 },

Expand Down
10 changes: 1 addition & 9 deletions src/lib/crypto/krb/dk/checksum_hmac.c
Expand Up @@ -39,20 +39,12 @@ krb5int_dk_checksum(const struct krb5_cksumtypes *ctp,
krb5_data *output)
{
const struct krb5_keytypes *ktp;
const struct krb5_enc_provider *enc;
const struct krb5_enc_provider *enc = ctp->enc;
krb5_error_code ret;
unsigned char constantdata[K5CLENGTH];
krb5_data datain;
krb5_key kc;

/* Use the key's enctype (more flexible than setting an enctype in ctp). */
ktp = find_enctype(key->keyblock.enctype);
if (ktp == NULL)
return KRB5_BAD_ENCTYPE;
enc = ktp->enc;
if (key->keyblock.length != enc->keylength)
return KRB5_BAD_KEYSIZE;

/* Derive the key. */
datain = make_data(constantdata, K5CLENGTH);
store_32_be(usage, constantdata);
Expand Down
2 changes: 2 additions & 0 deletions src/lib/crypto/krb/dk/derive.c
Expand Up @@ -91,6 +91,8 @@ derive_random_rfc3961(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;

Expand Down
6 changes: 3 additions & 3 deletions src/lib/crypto/krb/etypes.c
Expand Up @@ -51,7 +51,7 @@ const struct krb5_keytypes krb5int_enctypes_list[] = {
krb5int_des_string_to_key,
krb5int_des_prf,
krb5int_init_state_enc, krb5int_free_state_enc,
CKSUMTYPE_RSA_MD5,
CKSUMTYPE_RSA_MD5_DES,
ETYPE_WEAK },
{ ENCTYPE_DES_CBC_MD4,
"des-cbc-md4", { 0 }, "DES cbc mode with RSA-MD4",
Expand All @@ -61,7 +61,7 @@ const struct krb5_keytypes krb5int_enctypes_list[] = {
krb5int_des_string_to_key,
krb5int_des_prf,
krb5int_init_state_enc, krb5int_free_state_enc,
CKSUMTYPE_RSA_MD4,
CKSUMTYPE_RSA_MD4_DES,
ETYPE_WEAK },
{ ENCTYPE_DES_CBC_MD5,
"des-cbc-md5", { "des" }, "DES cbc mode with RSA-MD5",
Expand All @@ -71,7 +71,7 @@ const struct krb5_keytypes krb5int_enctypes_list[] = {
krb5int_des_string_to_key,
krb5int_des_prf,
krb5int_init_state_enc, krb5int_free_state_enc,
CKSUMTYPE_RSA_MD5,
CKSUMTYPE_RSA_MD5_DES,
ETYPE_WEAK },
{ ENCTYPE_DES_CBC_RAW,
"des-cbc-raw", { 0 }, "DES cbc mode raw",
Expand Down
4 changes: 2 additions & 2 deletions src/lib/crypto/krb/etypes.h
Expand Up @@ -108,8 +108,8 @@ encrypt_block(const struct krb5_enc_provider *enc, krb5_key key,
{
krb5_crypto_iov iov;

/* Verify that block is the right length. */
if (block->length != enc->block_size)
/* Verify that this is a block cipher and block is the right length. */
if (block->length != enc->block_size || enc->block_size == 1)
return EINVAL;
iov.flags = KRB5_CRYPTO_TYPE_DATA;
iov.data = *block;
Expand Down
10 changes: 1 addition & 9 deletions src/lib/krb5/krb/fast.c
Expand Up @@ -213,7 +213,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];

Expand Down Expand Up @@ -249,15 +248,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);
Expand Down
39 changes: 32 additions & 7 deletions src/lib/krb5/krb/mk_req_ext.c
Expand Up @@ -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,
Expand Down Expand Up @@ -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,
Expand Down
55 changes: 27 additions & 28 deletions src/lib/krb5/krb/mk_safe.c
Expand Up @@ -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;
Expand Down Expand Up @@ -110,6 +109,30 @@ krb5_mk_safe_basic(krb5_context context, const krb5_data *userdata,
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,
Expand Down Expand Up @@ -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))) {
Expand Down
4 changes: 4 additions & 0 deletions src/lib/krb5/krb/pac.c
Expand Up @@ -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);
Expand Down Expand Up @@ -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;
Expand Down
5 changes: 3 additions & 2 deletions src/lib/krb5/krb/preauth2.c
Expand Up @@ -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,
Expand All @@ -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) {
Expand Down
11 changes: 1 addition & 10 deletions src/plugins/preauth/pkinit/pkinit_srv.c
Expand Up @@ -691,8 +691,6 @@ 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;

pkinit_kdc_context plgctx;
pkinit_kdc_req_context reqctx;
Expand Down Expand Up @@ -882,14 +880,8 @@ 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],
retval = krb5_c_make_checksum(context, 0,
encrypting_key, KRB5_KEYUSAGE_TGS_REQ_AUTH_CKSUM,
req_pkt, &key_pack->asChecksum);
if (retval) {
Expand Down Expand Up @@ -1033,7 +1025,6 @@ pkinit_server_return_padata(krb5_context context,
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:
Expand Down

0 comments on commit dfe3625

Please sign in to comment.