From: Tom Yu Date: Sun, 24 May 2009 22:50:58 +0000 (+0000) Subject: pull up 22355, 22356, 22357 from trunk X-Git-Tag: krb5-1.7-beta3~12 X-Git-Url: http://git.tremily.us/?a=commitdiff_plain;h=f64ca62bda058a468025b4ed868534d93fc5fbde;p=krb5.git pull up 22355, 22356, 22357 from trunk ------------------------------------------------------------------------ r22357 | ghudson | 2009-05-20 04:05:53 +0200 (Wed, 20 May 2009) | 6 lines ticket: 6490 Restore compatibility with KDCs using key usage 8 to encrypt TGS replies in a subkey, by implementing a fallback in krb5_arcfour_decrypt. ------------------------------------------------------------------------ r22356 | ghudson | 2009-05-20 01:17:49 +0200 (Wed, 20 May 2009) | 13 lines ticket: 6490 status: open tags: pullup When using keyed checksum types with TGS subkeys, Microsoft AD 2003 verifies the checksum using the subkey, whereas MIT and Heimdal verify it using the TGS session key. (RFC 4120 is actually silent on which is correct; RFC 4757 specifies the TGS session key.) To sidestep this interop issue, don't use keyed checksum types with RC4 keys without explicit configuration in krb5.conf. Using keyed checksum types with AES is fine since, experimentally, AD 2008 accepts checksums keyed with the TGS session key. ------------------------------------------------------------------------ r22355 | hartmans | 2009-05-19 01:28:53 +0200 (Tue, 19 May 2009) | 5 lines ticket: 6490 status: open In practice, key usage 9 requires no translation. ticket: 6490 version_fixed: 1.7 git-svn-id: svn://anonsvn.mit.edu/krb5/branches/krb5-1-7@22374 dc483132-0cff-0310-8789-dd5450dbe970 --- diff --git a/src/lib/crypto/arcfour/arcfour.c b/src/lib/crypto/arcfour/arcfour.c index db529bed0..da4471459 100644 --- a/src/lib/crypto/arcfour/arcfour.c +++ b/src/lib/crypto/arcfour/arcfour.c @@ -47,7 +47,7 @@ case 7: /* tgs-req authenticator */ case 8: return 8; case 9: /* tgs-rep encrypted with subkey */ - return 8; + return 9; case 10: /* ap-rep authentication cksum */ return 10; /* xxx Microsoft never uses this*/ case 11: /* app-req authenticator */ @@ -252,40 +252,57 @@ krb5_arcfour_decrypt(const struct krb5_enc_provider *enc, checksum.length=hashsize; checksum.data=input->data; - /* compute the salt */ ms_usage=krb5int_arcfour_translate_usage(usage); - if (key->enctype == ENCTYPE_ARCFOUR_HMAC_EXP) { - strncpy(salt.data, krb5int_arcfour_l40, salt.length); - store_32_le(ms_usage, salt.data+10); - } else { - salt.length=4; - store_32_le(ms_usage, salt.data); - } - ret=krb5_hmac(hash, key, 1, &salt, &d1); - if (ret) - goto cleanup; - - memcpy(k2.contents, k1.contents, k2.length); - if (key->enctype == ENCTYPE_ARCFOUR_HMAC_EXP) - memset(k1.contents+7, 0xab, 9); + /* We may have to try two ms_usage values; see below. */ + do { + /* compute the salt */ + if (key->enctype == ENCTYPE_ARCFOUR_HMAC_EXP) { + strncpy(salt.data, krb5int_arcfour_l40, salt.length); + store_32_le(ms_usage, salt.data + 10); + } else { + salt.length = 4; + store_32_le(ms_usage, salt.data); + } + ret = krb5_hmac(hash, key, 1, &salt, &d1); + if (ret) + goto cleanup; + + memcpy(k2.contents, k1.contents, k2.length); + + if (key->enctype == ENCTYPE_ARCFOUR_HMAC_EXP) + memset(k1.contents + 7, 0xab, 9); - ret = krb5_hmac(hash, &k1, 1, &checksum, &d3); - if (ret) - goto cleanup; - - ret=(*(enc->decrypt))(&k3, ivec, &ciphertext, &plaintext); - if (ret) - goto cleanup; - - ret=krb5_hmac(hash, &k2, 1, &plaintext, &d1); - if (ret) - goto cleanup; - - if (memcmp(checksum.data, d1.data, hashsize) != 0) { - ret=KRB5KRB_AP_ERR_BAD_INTEGRITY; - goto cleanup; - } + ret = krb5_hmac(hash, &k1, 1, &checksum, &d3); + if (ret) + goto cleanup; + + ret = (*(enc->decrypt))(&k3, ivec, &ciphertext, &plaintext); + if (ret) + goto cleanup; + + ret = krb5_hmac(hash, &k2, 1, &plaintext, &d1); + if (ret) + goto cleanup; + + if (memcmp(checksum.data, d1.data, hashsize) != 0) { + if (ms_usage == 9) { + /* + * RFC 4757 specifies usage 8 for TGS-REP encrypted + * parts encrypted in a subkey, but the value used by MS + * is actually 9. We now use 9 to start with, but fall + * back to 8 on failure in case we are communicating + * with a KDC using the value from the RFC. + */ + ms_usage = 8; + continue; + } + ret = KRB5KRB_AP_ERR_BAD_INTEGRITY; + goto cleanup; + } + + break; + } while (1); memcpy(output->data, plaintext.data+CONFOUNDERLENGTH, (plaintext.length-CONFOUNDERLENGTH)); diff --git a/src/lib/crypto/t_encrypt.c b/src/lib/crypto/t_encrypt.c index c4ecbdecf..974dc585b 100644 --- a/src/lib/crypto/t_encrypt.c +++ b/src/lib/crypto/t_encrypt.c @@ -47,14 +47,17 @@ krb5_enctype interesting_enctypes[] = { 0 }; -#define test(msg, exp) \ -printf ("%s: . . . ", msg); \ -retval = (exp);\ -if( retval) { \ - printf( "Failed: %s\n", error_message(retval)); \ - abort(); \ -} else printf ("OK\n"); - +static void +test(const char *msg, krb5_error_code retval) +{ + printf("%s: . . . ", msg); + if (retval) { + printf("Failed: %s\n", error_message(retval)); + abort(); + } else + printf("OK\n"); +} + static int compare_results(krb5_data *d1, krb5_data *d2) { if (d1->length != d2->length) { @@ -186,6 +189,21 @@ main () krb5_free_keyblock (context, key); } + /* Test the RC4 decrypt fallback from key usage 9 to 8. */ + test ("Initializing an RC4 keyblock", + krb5_init_keyblock (context, ENCTYPE_ARCFOUR_HMAC, 0, &key)); + test ("Generating random RC4 key", + krb5_c_make_random_key (context, ENCTYPE_ARCFOUR_HMAC, key)); + enc_out.ciphertext = out; + krb5_c_encrypt_length (context, key->enctype, in.length, &len); + enc_out.ciphertext.length = len; + check.length = 2048; + test ("Encrypting with RC4 key usage 8", + krb5_c_encrypt (context, key, 8, 0, &in, &enc_out)); + test ("Decrypting with RC4 key usage 9", + krb5_c_decrypt (context, key, 9, 0, &enc_out, &check)); + test ("Comparing", compare_results (&in, &check)); + free(out.data); free(out2.data); free(check.data); diff --git a/src/lib/krb5/krb/send_tgs.c b/src/lib/krb5/krb/send_tgs.c index 84c89d56b..c23a5a371 100644 --- a/src/lib/krb5/krb/send_tgs.c +++ b/src/lib/krb5/krb/send_tgs.c @@ -68,6 +68,8 @@ tgs_construct_tgsreq(krb5_context context, krb5_data *in_data, case ENCTYPE_DES_CBC_CRC: case ENCTYPE_DES_CBC_MD4: case ENCTYPE_DES_CBC_MD5: + case ENCTYPE_ARCFOUR_HMAC: + case ENCTYPE_ARCFOUR_HMAC_EXP: cksumtype = context->kdc_req_sumtype; break; default: