#include "k5-int.h"
#include "des_int.h"
krb5_error_code
mit_des_string_to_key_int (krb5_keyblock *key,
const krb5_data *pw, const krb5_data *salt)
{
union {
unsigned char uc[16];
krb5_ui_4 ui[4];
mit_des_cblock cb;
} temp;
int i;
krb5_ui_4 x, y, z;
unsigned char *p;
des_key_schedule sched;
char *copy;
size_t copylen;
if (sizeof(temp.uc) != sizeof(temp.ui)
|| (unsigned char)~0 != 0xFF
|| (krb5_ui_4)~(krb5_ui_4)0 != 0xFFFFFFFF
|| (temp.uc[0] = 1, temp.uc[1] = 2, temp.uc[2] = 3, temp.uc[3] = 4,
!(temp.ui[0] == 0x01020304
|| temp.ui[0] == 0x04030201)))
abort();
#define FETCH4(VAR, IDX) VAR = temp.ui[IDX/4]
#define PUT4(VAR, IDX) temp.ui[IDX/4] = VAR
if (salt
&& (salt->length == SALT_TYPE_AFS_LENGTH
|| salt->length == (unsigned) -1)) {
krb5_data afssalt;
char *at;
afssalt.data = salt->data;
at = strchr(afssalt.data, '@');
if (at) {
*at = 0;
afssalt.length = at - afssalt.data;
} else
afssalt.length = strlen(afssalt.data);
return mit_afs_string_to_key(key, pw, &afssalt);
}
copylen = pw->length + (salt ? salt->length : 0);
copy = malloc(copylen);
if (copy == NULL)
return errno;
memcpy(copy, pw->data, pw->length);
if (salt)
memcpy(copy + pw->length, salt->data, salt->length);
memset(&temp, 0, sizeof(temp));
p = temp.uc;
for (i = 0; i < copylen; i++) {
*p++ ^= copy[i];
if (p == temp.uc+16) {
p = temp.uc;
#ifdef PRINT_TEST_VECTORS
{
int j;
printf("after %d input bytes:\nforward block:\t", i+1);
for (j = 0; j < 8; j++)
printf(" %02x", temp.uc[j] & 0xff);
printf("\nreverse block:\t");
for (j = 8; j < 16; j++)
printf(" %02x", temp.uc[j] & 0xff);
printf("\n");
}
#endif
}
}
#ifdef PRINT_TEST_VECTORS
if (p != temp.uc) {
int j;
printf("at end, after %d input bytes:\nforward block:\t", i);
for (j = 0; j < 8; j++)
printf(" %02x", temp.uc[j] & 0xff);
printf("\nreverse block:\t");
for (j = 8; j < 16; j++)
printf(" %02x", temp.uc[j] & 0xff);
printf("\n");
}
#endif
#if 0
#define REVERSE_STEP(VAR, SHIFT, MASK) \
VAR = ((VAR >> SHIFT) & MASK) | ((VAR << SHIFT) & (0xFFFFFFFFUL & ~MASK))
#define REVERSE(VAR) \
REVERSE_STEP (VAR, 1, 0x55555555UL); \
REVERSE_STEP (VAR, 2, 0x33333333UL); \
REVERSE_STEP (VAR, 4, 0x0F0F0F0FUL); \
REVERSE_STEP (VAR, 8, 0x00FF00FFUL); \
REVERSE_STEP (VAR, 16, 0x0000FFFFUL);
#else
#define REVERSE(VAR) \
{ \
krb5_ui_4 old = VAR, temp1 = 0; \
int j; \
for (j = 0; j < 32; j++) { \
temp1 = (temp1 << 1) | (old & 1); \
old >>= 1; \
} \
VAR = temp1; \
}
#endif
FETCH4 (x, 8);
FETCH4 (y, 12);
x &= 0x7F7F7F7F;
y &= 0x7F7F7F7F;
REVERSE (x);
REVERSE (y);
#ifdef PRINT_TEST_VECTORS
{
int j;
union { unsigned char uc[4]; krb5_ui_4 ui; } t2;
printf("after reversal, reversed block:\n\t\t");
t2.ui = y;
for (j = 0; j < 4; j++)
printf(" %02x", t2.uc[j] & 0xff);
t2.ui = x;
for (j = 0; j < 4; j++)
printf(" %02x", t2.uc[j] & 0xff);
printf("\n");
}
#endif
FETCH4 (z, 0);
z &= 0x7F7F7F7F;
z <<= 1;
z ^= y;
PUT4 (z, 0);
FETCH4 (z, 4);
z &= 0x7F7F7F7F;
z <<= 1;
z ^= x;
PUT4 (z, 4);
#ifdef PRINT_TEST_VECTORS
{
int j;
printf("after reversal, combined block:\n\t\t");
for (j = 0; j < 8; j++)
printf(" %02x", temp.uc[j] & 0xff);
printf("\n");
}
#endif
#define FIXUP(K) \
(mit_des_fixup_key_parity(K), \
mit_des_is_weak_key(K) ? (K[7] ^= 0xF0) : 0)
FIXUP(temp.cb);
#ifdef PRINT_TEST_VECTORS
{
int j;
printf("after fixing parity and weak keys:\n\t\t");
for (j = 0; j < 8; j++)
printf(" %02x", temp.uc[j] & 0xff);
printf("\n");
}
#endif
mit_des_key_sched(temp.cb, sched);
mit_des_cbc_cksum(copy, temp.cb, copylen, sched, temp.cb);
memset(copy, 0, copylen);
free(copy);
#ifdef PRINT_TEST_VECTORS
{
int j;
printf("cbc checksum:\n\t\t");
for (j = 0; j < 8; j++)
printf(" %02x", temp.uc[j] & 0xff);
printf("\n");
}
#endif
memset(sched, 0, sizeof(sched));
FIXUP (temp.cb);
#ifdef PRINT_TEST_VECTORS
{
int j;
printf("after fixing parity and weak keys:\n\t\t");
for (j = 0; j < 8; j++)
printf(" %02x", temp.uc[j] & 0xff);
printf("\n");
}
#endif
memcpy(key->contents, temp.cb, 8);
memset(&temp, 0, sizeof(temp));
return 0;
}