#include "k5-int.h"
#include "des_int.h"
#include "rsa-md5.h"
#include "keyhash_provider.h"
#define CONFLENGTH 8
#define KRB5_MD5DES_BETA5_COMPAT
static krb5_error_code
k5_md5des_hash(const krb5_keyblock *key, krb5_keyusage usage, const krb5_data *ivec,
const krb5_data *input, krb5_data *output)
{
krb5_error_code ret;
krb5_data data;
krb5_MD5_CTX ctx;
unsigned char conf[CONFLENGTH];
unsigned char xorkey[8];
int i;
mit_des_key_schedule schedule;
if (key->length != 8)
return(KRB5_BAD_KEYSIZE);
if (ivec)
return(KRB5_CRYPTO_INTERNAL);
if (output->length != (CONFLENGTH+RSA_MD5_CKSUM_LENGTH))
return(KRB5_CRYPTO_INTERNAL);
data.length = CONFLENGTH;
data.data = (char *) conf;
if ((ret = krb5_c_random_make_octets( 0, &data)))
return(ret);
memcpy(xorkey, key->contents, sizeof(xorkey));
for (i=0; i<sizeof(xorkey); i++)
xorkey[i] ^= 0xf0;
switch (ret = mit_des_key_sched(xorkey, schedule)) {
case -1:
return(KRB5DES_BAD_KEYPAR);
case -2:
return(KRB5DES_WEAK_KEY);
}
krb5_MD5Init(&ctx);
krb5_MD5Update(&ctx, conf, CONFLENGTH);
krb5_MD5Update(&ctx, (unsigned char *) input->data,
(unsigned int) input->length);
krb5_MD5Final(&ctx);
memcpy(output->data, conf, CONFLENGTH);
memcpy(output->data+CONFLENGTH, ctx.digest, RSA_MD5_CKSUM_LENGTH);
mit_des_cbc_encrypt((krb5_pointer) output->data,
(krb5_pointer) output->data, output->length,
schedule, (unsigned char *) mit_des_zeroblock, 1);
return(0);
}
static krb5_error_code
k5_md5des_verify(const krb5_keyblock *key, krb5_keyusage usage, const krb5_data *ivec,
const krb5_data *input, const krb5_data *hash,
krb5_boolean *valid)
{
krb5_MD5_CTX ctx;
unsigned char plaintext[CONFLENGTH+RSA_MD5_CKSUM_LENGTH];
unsigned char xorkey[8];
int i;
mit_des_key_schedule schedule;
int compathash = 0;
if (key->length != 8)
return(KRB5_BAD_KEYSIZE);
if (ivec)
return(KRB5_CRYPTO_INTERNAL);
if (hash->length != (CONFLENGTH+RSA_MD5_CKSUM_LENGTH)) {
#ifdef KRB5_MD5DES_BETA5_COMPAT
if (hash->length != RSA_MD5_CKSUM_LENGTH)
return(KRB5_CRYPTO_INTERNAL);
else
compathash = 1;
#else
return(KRB5_CRYPTO_INTERNAL);
#endif
}
memcpy(xorkey, key->contents, sizeof(xorkey));
if (!compathash) {
for (i=0; i<sizeof(xorkey); i++)
xorkey[i] ^= 0xf0;
}
switch (mit_des_key_sched(xorkey, schedule)) {
case -1:
return(KRB5DES_BAD_KEYPAR);
case -2:
return(KRB5DES_WEAK_KEY);
}
if (!compathash) {
mit_des_cbc_encrypt((krb5_pointer) hash->data,
(krb5_pointer) plaintext, hash->length,
schedule, (unsigned char *) mit_des_zeroblock, 0);
} else {
mit_des_cbc_encrypt((krb5_pointer) hash->data,
(krb5_pointer) plaintext, hash->length,
schedule, xorkey, 0);
}
krb5_MD5Init(&ctx);
if (!compathash) {
krb5_MD5Update(&ctx, plaintext, CONFLENGTH);
}
krb5_MD5Update(&ctx, (unsigned char *) input->data,
(unsigned) input->length);
krb5_MD5Final(&ctx);
if (!compathash) {
*valid =
(memcmp(plaintext+CONFLENGTH, ctx.digest, RSA_MD5_CKSUM_LENGTH)
== 0);
} else {
*valid =
(memcmp(plaintext, ctx.digest, RSA_MD5_CKSUM_LENGTH) == 0);
}
memset(plaintext, 0, sizeof(plaintext));
return(0);
}
const struct krb5_keyhash_provider krb5int_keyhash_md5des = {
CONFLENGTH+RSA_MD5_CKSUM_LENGTH,
k5_md5des_hash,
k5_md5des_verify
};