summaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorTom Yu <tlyu@mit.edu>2009-11-26 03:54:59 +0000
committerTom Yu <tlyu@mit.edu>2009-11-26 03:54:59 +0000
commitad2adb977e00181627be7c9a4980b4015fd58fa6 (patch)
tree0d2a5e733401d0d905fea8bb398f1b97f67e081e /src
parentdc3ba26a2c9acde7ca4ed9260fdc01997511e478 (diff)
downloadkrb5-ad2adb977e00181627be7c9a4980b4015fd58fa6.tar.gz
krb5-ad2adb977e00181627be7c9a4980b4015fd58fa6.tar.xz
krb5-ad2adb977e00181627be7c9a4980b4015fd58fa6.zip
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). ticket: 6584 target_version: 1.7.1 tags: pullup git-svn-id: svn://anonsvn.mit.edu/krb5/trunk@23361 dc483132-0cff-0310-8789-dd5450dbe970
Diffstat (limited to 'src')
-rw-r--r--src/lib/crypto/crypto_tests/Makefile.in7
-rw-r--r--src/lib/crypto/crypto_tests/t_cksum.c46
-rw-r--r--src/lib/crypto/krb/keyhash_provider/k5_md4des.c52
-rw-r--r--src/lib/crypto/krb/keyhash_provider/k5_md5des.c52
4 files changed, 138 insertions, 19 deletions
diff --git a/src/lib/crypto/crypto_tests/Makefile.in b/src/lib/crypto/crypto_tests/Makefile.in
index 6e38506b5..ae0a5223b 100644
--- a/src/lib/crypto/crypto_tests/Makefile.in
+++ b/src/lib/crypto/crypto_tests/Makefile.in
@@ -37,6 +37,9 @@ EXTRADEPSRCS=\
##DOS##LIBOBJS = $(OBJS)
+# NOTE: The t_cksum known checksum values are primarily for regression
+# testing. They are not derived a priori, but are known to produce
+# checksums that interoperate.
check-unix:: t_nfold t_encrypt t_prf t_prng t_hmac \
t_cksum4 t_cksum5 \
aes-test \
@@ -49,8 +52,8 @@ check-unix:: t_nfold t_encrypt t_prf t_prng t_hmac \
$(RUN_SETUP) $(VALGRIND) ./t_hmac
$(RUN_SETUP) $(VALGRIND) ./t_prf <$(srcdir)/t_prf.in >t_prf.output
diff t_prf.output $(srcdir)/t_prf.expected
- $(RUN_SETUP) $(VALGRIND) ./t_cksum4 "this is a test"
- $(RUN_SETUP) $(VALGRIND) ./t_cksum5 "this is a test"
+ $(RUN_SETUP) $(VALGRIND) ./t_cksum4 "this is a test" e3f76a07f3401e3536b43a3f54226c39422c35682c354835
+ $(RUN_SETUP) $(VALGRIND) ./t_cksum5 "this is a test" e3f76a07f3401e351143ee6f4c09be1edb4264d55015db53
$(RUN_SETUP) $(VALGRIND) ./t_crc
$(RUN_SETUP) $(VALGRIND) ./t_cts
$(RUN_SETUP) $(VALGRIND) ./aes-test -k > vk.txt
diff --git a/src/lib/crypto/crypto_tests/t_cksum.c b/src/lib/crypto/crypto_tests/t_cksum.c
index a544d9ee8..5fab8695b 100644
--- a/src/lib/crypto/crypto_tests/t_cksum.c
+++ b/src/lib/crypto/crypto_tests/t_cksum.c
@@ -59,6 +59,27 @@ print_checksum(text, number, message, checksum)
printf("\n");
}
+static void
+parse_hexstring(const char *s, krb5_data *dat)
+{
+ size_t i, len;
+ unsigned int byte;
+ unsigned char *cp;
+
+ len = strlen(s);
+ cp = malloc(len / 2);
+ dat->data = (char *)cp;
+ if (cp == NULL) {
+ dat->length = 0;
+ return;
+ }
+ dat->length = len / 2;
+ for (i = 0; i + 1 < len; i += 2) {
+ sscanf(&s[i], "%2x", &byte);
+ *cp++ = byte;
+ }
+}
+
/*
* Test the checksum verification of Old Style (tm) and correct RSA-MD[4,5]-DES
* checksums.
@@ -77,7 +98,7 @@ 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;
/* this is a terrible seed, but that's ok for the test. */
@@ -101,7 +122,7 @@ main(argc, argv)
printf("cannot get memory for new style checksum\n");
return(ENOMEM);
}
- for (msgindex = 1; msgindex < argc; msgindex++) {
+ for (msgindex = 1; msgindex + 1 < argc; msgindex += 2) {
plaintext.length = strlen(argv[msgindex]);
plaintext.data = argv[msgindex];
@@ -118,6 +139,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,14 +152,32 @@ 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]);
+ parse_hexstring(argv[msgindex+1], &knowncksum_dat);
+ if (knowncksum_dat.data == NULL) {
+ printf("parse_hexstring failed\n");
+ kret = 1;
+ break;
+ }
+ 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;
+ }
+ printf("Verify on known checksum succeeded\n");
kret = 0;
}
free(newstyle_checksum.data);
if (!kret)
- printf("%d tests passed successfully for MD%d checksum\n", argc-1, MD);
+ printf("%d tests passed successfully for MD%d checksum\n", (argc-1)/2, MD);
krb5_k_free_key(NULL, key);
diff --git a/src/lib/crypto/krb/keyhash_provider/k5_md4des.c b/src/lib/crypto/krb/keyhash_provider/k5_md4des.c
index ef10a6898..89d97f7bf 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 eb189c26a..4a3d623ac 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);