From 689473cbbd1fc5a750e0edc8292ad8f6f51e0496 Mon Sep 17 00:00:00 2001 From: Greg Hudson Date: Wed, 20 May 2009 02:05:53 +0000 Subject: [PATCH] Restore compatibility with KDCs using key usage 8 to encrypt TGS replies in a subkey, by implementing a fallback in krb5_arcfour_decrypt. ticket: 6490 git-svn-id: svn://anonsvn.mit.edu/krb5/trunk@22357 dc483132-0cff-0310-8789-dd5450dbe970 --- src/lib/crypto/arcfour/arcfour.c | 79 +++++++++++++++++++------------- src/lib/crypto/t_encrypt.c | 34 ++++++++++---- 2 files changed, 74 insertions(+), 39 deletions(-) diff --git a/src/lib/crypto/arcfour/arcfour.c b/src/lib/crypto/arcfour/arcfour.c index 4999982c3..7e527cf89 100644 --- a/src/lib/crypto/arcfour/arcfour.c +++ b/src/lib/crypto/arcfour/arcfour.c @@ -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); -- 2.26.2