Skip Menu |
 

To: krb5-bugs@MIT.EDU
Subject: r22778 breaks zephyr; probable incompatible
From: Sam Hartman <hartmans@debian.org>, change@MIT.EDU, in@MIT.EDU, DES@MIT.EDU, checksums@MIT.EDU
Date: Sun, 22 Nov 2009 16:26:21 -0500 (EST)
CC: kcr@1ts.org

Found with git bisect, so I haven't looked into why this is the case.
However, Author: tsitkova <tsitkova@dc483132-0cff-0310-8789-dd5450dbe970>
Date: Fri Sep 18 19:10:48 2009 +0000

Use enc_provider for des hash routines. Also needed by Crypto modularity pro
j.


Breaks zephyr.
After this commit, subscribing gets a srvnak.
To: rt@krbdev.MIT.EDU
Subject: Re: [krbdev.mit.edu #6584] r22778 breaks zephyr; probable incompatible
From: Tom Yu <tlyu@MIT.EDU>
Date: Sun, 22 Nov 2009 16:52:38 -0500
RT-Send-Cc:
Sam Hartman via RT <rt-comment@krbdev.mit.edu> writes:

Show quoted text
> Found with git bisect, so I haven't looked into why this is the case.
> However, Author: tsitkova <tsitkova@dc483132-0cff-0310-8789-dd5450dbe970>
> Date: Fri Sep 18 19:10:48 2009 +0000
>
> Use enc_provider for des hash routines. Also needed by Crypto modularity pro
> j.
>
>
> Breaks zephyr.
> After this commit, subscribing gets a srvnak.

It looks like the raw input key is used, not the "xorkey" as before
this change.
To: rt@krbdev.MIT.EDU
Subject: Re: [krbdev.mit.edu #6584] r22778 breaks zephyr; probable incompatible
From: Tom Yu <tlyu@MIT.EDU>
Date: Tue, 24 Nov 2009 19:08:07 -0500
RT-Send-Cc:
Sam Hartman via RT <rt-comment@krbdev.mit.edu> writes:

Show quoted text
> Found with git bisect, so I haven't looked into why this is the case.
> However, Author: tsitkova <tsitkova@dc483132-0cff-0310-8789-dd5450dbe970>
> Date: Fri Sep 18 19:10:48 2009 +0000
>
> Use enc_provider for des hash routines. Also needed by Crypto modularity pro
> j.
>
>
> Breaks zephyr.
> After this commit, subscribing gets a srvnak.
>
> _______________________________________________
> krb5-bugs mailing list
> krb5-bugs@mit.edu
> https://mailman.mit.edu/mailman/listinfo/krb5-bugs

Please try to verify the attached patch against zephyr. It needs a
bit of cleaning up but I wanted to make sure that the "xorkey" is the
issue as I believe it to be. (The OpenSSL back end needs related
changes.)
Download diff
text/x-patch 9KiB
diff --git a/src/lib/crypto/crypto_tests/t_cksum.c b/src/lib/crypto/crypto_tests/t_cksum.c
index a544d9e..50e8e7c 100644
--- a/src/lib/crypto/crypto_tests/t_cksum.c
+++ b/src/lib/crypto/crypto_tests/t_cksum.c
@@ -37,11 +37,21 @@
#if MD == 4
extern struct krb5_keyhash_provider krb5int_keyhash_md4des;
#define khp krb5int_keyhash_md4des
+static unsigned char knowncksum[] = {
+ 0xe3, 0xf7, 0x6a, 0x07, 0xf3, 0x40, 0x1e, 0x35,
+ 0x36, 0xb4, 0x3a, 0x3f, 0x54, 0x22, 0x6c, 0x39,
+ 0x42, 0x2c, 0x35, 0x68, 0x2c, 0x35, 0x48, 0x35
+};
#endif

#if MD == 5
extern struct krb5_keyhash_provider krb5int_keyhash_md5des;
#define khp krb5int_keyhash_md5des
+static unsigned char knowncksum[] = {
+ 0xe3, 0xf7, 0x6a, 0x07, 0xf3, 0x40, 0x1e, 0x35,
+ 0x11, 0x43, 0xee, 0x6f, 0x4c, 0x09, 0xbe, 0x1e,
+ 0xdb, 0x42, 0x64, 0xd5, 0x50, 0x15, 0xdb, 0x53
+};
#endif

static void
@@ -77,7 +87,11 @@ main(argc, argv)
krb5_keyblock keyblock;
krb5_key key;
krb5_error_code kret=0;
- krb5_data plaintext, newstyle_checksum;
+ krb5_data plaintext, newstyle_checksum, knowncksum_dat;
+ char *known_plaintext = "this is a test";
+
+ knowncksum_dat.data = (char *)knowncksum;
+ knowncksum_dat.length = sizeof(knowncksum);

/* this is a terrible seed, but that's ok for the test. */

@@ -118,6 +132,7 @@ main(argc, argv)
}
if (!valid) {
printf("verify on new checksum failed\n");
+ kret = 1;
break;
}
printf("Verify succeeded for \"%s\"\n", argv[msgindex]);
@@ -130,9 +145,26 @@ main(argc, argv)
}
if (valid) {
printf("verify on new checksum succeeded, but shouldn't have\n");
+ kret = 1;
break;
}
printf("Verify of bad checksum OK for \"%s\"\n", argv[msgindex]);
+ if (strcmp(argv[msgindex], known_plaintext) == 0) {
+ if ((kret = (*(khp.verify))(key, 0, 0, &plaintext, &knowncksum_dat,
+ &valid))) {
+ printf("verify on known checksum choked with %d\n", kret);
+ break;
+ }
+ if (!valid) {
+ printf("verify on known checksum failed\n");
+ kret = 1;
+ break;
+ }
+ } else {
+ printf("WARNING: input plaintext doesn't match plaintext "
+ "of known hash.\n"
+ "NOT verifying known checksum.\n");
+ }
kret = 0;
}
free(newstyle_checksum.data);
diff --git a/src/lib/crypto/krb/keyhash_provider/k5_md4des.c b/src/lib/crypto/krb/keyhash_provider/k5_md4des.c
index ef10a68..89d97f7 100644
--- a/src/lib/crypto/krb/keyhash_provider/k5_md4des.c
+++ b/src/lib/crypto/krb/keyhash_provider/k5_md4des.c
@@ -38,6 +38,30 @@

extern struct krb5_enc_provider krb5int_enc_des;

+/* Derive a key by XOR with 0xF0 bytes. */
+static krb5_error_code
+mk_xorkey(krb5_key origkey, krb5_key *xorkey)
+{
+ krb5_error_code retval = 0;
+ unsigned char xorbytes[8];
+ krb5_keyblock xorkeyblock;
+ size_t i = 0;
+
+ if (origkey->keyblock.length != sizeof(xorbytes))
+ return KRB5_CRYPTO_INTERNAL;
+ memcpy(xorbytes, origkey->keyblock.contents, sizeof(xorbytes));
+ for (i = 0; i < sizeof(xorbytes); i++)
+ xorbytes[i] ^= 0xf0;
+
+ /* Do a shallow copy here. */
+ xorkeyblock = origkey->keyblock;
+ xorkeyblock.contents = xorbytes;
+
+ retval = krb5_k_create_key(0, &xorkeyblock, xorkey);
+ zap(xorbytes, sizeof(xorbytes));
+ return retval;
+}
+
static krb5_error_code
k5_md4des_hash(krb5_key key, krb5_keyusage usage, const krb5_data *ivec,
const krb5_data *input, krb5_data *output)
@@ -46,6 +70,7 @@ k5_md4des_hash(krb5_key key, krb5_keyusage usage, const krb5_data *ivec,
krb5_data data;
krb5_MD4_CTX ctx;
unsigned char conf[CONFLENGTH];
+ krb5_key xorkey = NULL;
struct krb5_enc_provider *enc = &krb5int_enc_des;

if (output->length != (CONFLENGTH+RSA_MD4_CKSUM_LENGTH))
@@ -58,6 +83,10 @@ k5_md4des_hash(krb5_key key, krb5_keyusage usage, const krb5_data *ivec,
if ((ret = krb5_c_random_make_octets(/* XXX */ 0, &data)))
return(ret);

+ ret = mk_xorkey(key, &xorkey);
+ if (ret)
+ return ret;
+
/* hash the confounder, then the input data */

krb5int_MD4Init(&ctx);
@@ -71,7 +100,9 @@ k5_md4des_hash(krb5_key key, krb5_keyusage usage, const krb5_data *ivec,
memcpy(output->data, conf, CONFLENGTH);
memcpy(output->data+CONFLENGTH, ctx.digest, RSA_MD4_CKSUM_LENGTH);

- ret = enc->encrypt(key, NULL, output, output);
+ ret = enc->encrypt(xorkey, NULL, output, output);
+
+ krb5_k_free_key(NULL, xorkey);

return (ret);
}
@@ -85,10 +116,14 @@ k5_md4des_verify(krb5_key key, krb5_keyusage usage,
krb5_error_code ret;
krb5_MD4_CTX ctx;
unsigned char plaintext[CONFLENGTH+RSA_MD4_CKSUM_LENGTH];
+ krb5_key xorkey = NULL;
int compathash = 0;
struct krb5_enc_provider *enc = &krb5int_enc_des;
krb5_data output, iv;

+ iv.data = NULL;
+ iv.length = 0;
+
if (key->keyblock.length != 8)
return(KRB5_BAD_KEYSIZE);
if (hash->length != (CONFLENGTH+RSA_MD4_CKSUM_LENGTH)) {
@@ -109,20 +144,23 @@ k5_md4des_verify(krb5_key key, krb5_keyusage usage,
iv.length = key->keyblock.length;
if (key->keyblock.contents)
memcpy(iv.data, key->keyblock.contents, key->keyblock.length);
+ } else {
+ ret = mk_xorkey(key, &xorkey);
+ if (ret)
+ return ret;
}

/* decrypt it */
- output.data = plaintext;
+ output.data = (char *)plaintext;
output.length = hash->length;

if (!compathash) {
- ret = enc->decrypt(key, NULL, hash, &output);
+ ret = enc->decrypt(xorkey, NULL, hash, &output);
+ krb5_k_free_key(NULL, xorkey);
} else {
ret = enc->decrypt(key, &iv, hash, &output);
- }
-
- if (compathash && iv.data) {
- free (iv.data);
+ zap(iv.data, iv.length);
+ free(iv.data);
}

if (ret) return(ret);
diff --git a/src/lib/crypto/krb/keyhash_provider/k5_md5des.c b/src/lib/crypto/krb/keyhash_provider/k5_md5des.c
index eb189c2..4a3d623 100644
--- a/src/lib/crypto/krb/keyhash_provider/k5_md5des.c
+++ b/src/lib/crypto/krb/keyhash_provider/k5_md5des.c
@@ -38,6 +38,30 @@

extern struct krb5_enc_provider krb5int_enc_des;

+/* Derive a key by XOR with 0xF0 bytes. */
+static krb5_error_code
+mk_xorkey(krb5_key origkey, krb5_key *xorkey)
+{
+ krb5_error_code retval = 0;
+ unsigned char xorbytes[8];
+ krb5_keyblock xorkeyblock;
+ size_t i = 0;
+
+ if (origkey->keyblock.length != sizeof(xorbytes))
+ return KRB5_CRYPTO_INTERNAL;
+ memcpy(xorbytes, origkey->keyblock.contents, sizeof(xorbytes));
+ for (i = 0; i < sizeof(xorbytes); i++)
+ xorbytes[i] ^= 0xf0;
+
+ /* Do a shallow copy here. */
+ xorkeyblock = origkey->keyblock;
+ xorkeyblock.contents = xorbytes;
+
+ retval = krb5_k_create_key(0, &xorkeyblock, xorkey);
+ zap(xorbytes, sizeof(xorbytes));
+ return retval;
+}
+
static krb5_error_code
k5_md5des_hash(krb5_key key, krb5_keyusage usage, const krb5_data *ivec,
const krb5_data *input, krb5_data *output)
@@ -46,6 +70,7 @@ k5_md5des_hash(krb5_key key, krb5_keyusage usage, const krb5_data *ivec,
krb5_data data;
krb5_MD5_CTX ctx;
unsigned char conf[CONFLENGTH];
+ krb5_key xorkey = NULL;
struct krb5_enc_provider *enc = &krb5int_enc_des;

if (output->length != (CONFLENGTH+RSA_MD5_CKSUM_LENGTH))
@@ -58,6 +83,10 @@ k5_md5des_hash(krb5_key key, krb5_keyusage usage, const krb5_data *ivec,
if ((ret = krb5_c_random_make_octets(/* XXX */ 0, &data)))
return(ret);

+ ret = mk_xorkey(key, &xorkey);
+ if (ret)
+ return ret;
+
/* hash the confounder, then the input data */

krb5int_MD5Init(&ctx);
@@ -71,7 +100,9 @@ k5_md5des_hash(krb5_key key, krb5_keyusage usage, const krb5_data *ivec,
memcpy(output->data, conf, CONFLENGTH);
memcpy(output->data+CONFLENGTH, ctx.digest, RSA_MD5_CKSUM_LENGTH);

- ret = enc->encrypt(key, NULL, output, output);
+ ret = enc->encrypt(xorkey, NULL, output, output);
+
+ krb5_k_free_key(NULL, xorkey);

return ret;

@@ -85,10 +116,14 @@ k5_md5des_verify(krb5_key key, krb5_keyusage usage, const krb5_data *ivec,
krb5_error_code ret;
krb5_MD5_CTX ctx;
unsigned char plaintext[CONFLENGTH+RSA_MD5_CKSUM_LENGTH];
+ krb5_key xorkey = NULL;
int compathash = 0;
struct krb5_enc_provider *enc = &krb5int_enc_des;
krb5_data output, iv;

+ iv.data = NULL;
+ iv.length = 0;
+
if (key->keyblock.length != 8)
return(KRB5_BAD_KEYSIZE);

@@ -109,20 +144,23 @@ k5_md5des_verify(krb5_key key, krb5_keyusage usage, const krb5_data *ivec,
iv.length = key->keyblock.length;
if (key->keyblock.contents)
memcpy(iv.data, key->keyblock.contents, key->keyblock.length);
+ } else {
+ ret = mk_xorkey(key, &xorkey);
+ if (ret)
+ return ret;
}

/* decrypt it */
- output.data = plaintext;
+ output.data = (char *)plaintext;
output.length = hash->length;

if (!compathash) {
- ret = enc->decrypt(key, NULL, hash, &output);
+ ret = enc->decrypt(xorkey, NULL, hash, &output);
+ krb5_k_free_key(NULL, xorkey);
} else {
ret = enc->decrypt(key, &iv, hash, &output);
- }
-
- if (compathash && iv.data) {
- free (iv.data);
+ zap(iv.data, iv.length);
+ free(iv.data);
}

if (ret) return(ret);
To: rt@krbdev.mit.edu
Subject: Re: [krbdev.mit.edu #6584] r22778 breaks zephyr; probable incompatible
From: Sam Hartman <hartmans@debian.org>
Date: Wed, 25 Nov 2009 22:23:40 -0500
RT-Send-Cc:
I can confirm the patch works.
From: tlyu@mit.edu
Subject: SVN Commit

Pullup to 1.7-branch is only for the test case, as krb5-1.7 behaved
correctly for these checksums.

Fix regression in MD4-DES and MD5-DES keyed checksums. The original
key was being used for the DES encryption, not the "xorkey". (key
with each byte XORed with 0xf0)

Add a test case that will catch future regressions of this sort, by
including a verification of a "known-good" checksum (derived from a
known-to-be-interoperable version of the implementation).

https://github.com/krb5/krb5/commit/ad2adb977e00181627be7c9a4980b4015fd58fa6
Commit By: tlyu
Revision: 23361
Changed Files:
U trunk/src/lib/crypto/crypto_tests/Makefile.in
U trunk/src/lib/crypto/crypto_tests/t_cksum.c
U trunk/src/lib/crypto/krb/keyhash_provider/k5_md4des.c
U trunk/src/lib/crypto/krb/keyhash_provider/k5_md5des.c
From: tlyu@mit.edu
Subject: SVN Commit

Backport test suite portion of r23361 from trunk

------------------------------------------------------------------------
r23361 | tlyu | 2009-11-25 22:54:59 -0500 (Wed, 25 Nov 2009) | 15 lines

ticket: 6584
target_version: 1.7.1
tags: pullup

Pullup to 1.7-branch is only for the test case, as krb5-1.7 behaved
correctly for these checksums.

Fix regression in MD4-DES and MD5-DES keyed checksums. The original
key was being used for the DES encryption, not the "xorkey". (key
with each byte XORed with 0xf0)

Add a test case that will catch future regressions of this sort, by
including a verification of a "known-good" checksum (derived from a
known-to-be-interoperable version of the implementation).

https://github.com/krb5/krb5/commit/a9d409c735676299c91cfcb23963f3e8ce2242ad
Commit By: tlyu
Revision: 23642
Changed Files:
U branches/krb5-1-7/src/lib/crypto/keyhash_provider/Makefile.in
U branches/krb5-1-7/src/lib/crypto/keyhash_provider/t_cksum.c