Fix DES3 string-to-key.

git-svn-id: svn://svn.h5l.se/heimdal/trunk/heimdal@4705 ec53bebd-3082-4978-b11e-865c3cabbd6b
This commit is contained in:
Johan Danielsson
1998-04-03 04:03:39 +00:00
parent a7ec1574f7
commit 7a8eeccb69

View File

@@ -97,7 +97,7 @@ q = (tbl[q & 0x0F] << 4) | (tbl[q >> 4])
*/
static void
xor (des_cblock *key, unsigned char *b)
xor (des_cblock *key, const unsigned char *b)
{
unsigned char *a = (unsigned char*)key;
a[0] ^= b[0];
@@ -115,7 +115,7 @@ xor (des_cblock *key, unsigned char *b)
*/
static void
init (unsigned char *a, unsigned char *b)
init (unsigned char *a, const unsigned char *b)
{
a[0] = b[0] << 1;
a[1] = b[1] << 1;
@@ -128,25 +128,26 @@ init (unsigned char *a, unsigned char *b)
}
static void
DES_string_to_key(const unsigned char *str, size_t len, des_cblock *key)
DES_string_to_key(const char *str, size_t len, des_cblock *key)
{
int odd, i;
/* could use des_string_to_key here, but then `str' must be zero
terminated, and the final weak-key check has to be added */
int even, i;
des_key_schedule sched;
memset (key, 0, sizeof(des_cblock));
odd = 1;
even = 0;
for (i = 0; i < len; i += 8) {
unsigned char tmp[8];
init (tmp, (unsigned char*)&str[i]);
init (tmp, (const unsigned char*)(str + i));
if (odd == 0) {
odd = 1;
if (even) {
reverse (tmp);
init (tmp, tmp);
} else
odd = 0;
}
even = !even;
xor (key, tmp);
}
des_set_odd_parity (key);
@@ -157,40 +158,29 @@ DES_string_to_key(const unsigned char *str, size_t len, des_cblock *key)
xor (key, (unsigned char*)"\0\0\0\0\0\0\0\xf0");
}
static int
gcd(int a, int b)
{
do{
int r = a % b;
a = b;
b = r;
}while(b);
return a;
}
static void
rr13(unsigned char *buf, size_t len)
{
unsigned char *tmp = malloc(len);
int i;
for(i = 0; i < len; i++){
int x = (buf[i] << 8) | buf[(i + 1) % len];
x >>= 5;
tmp[(i + 2) % len] = x & 0xff;
}
memcpy(buf, tmp, len);
free(tmp);
/* assert(len >= 3); */
unsigned a = buf[0], b = buf[len-1];
#define F(A, B) ((((A) << 3) | ((B) >> 5)) & 0xff)
buf[0] = F(buf[len-2], buf[len-1]);
for(i = len - 3; i >= 1; i--)
buf[i + 2] = F(buf[i], buf[i+1]);
buf[2] = F(a, buf[1]);
buf[1] = F(b, a);
#undef F
}
/* XXX what's this function supposed to do anyway? */
/* Add `b' to `a', both beeing one's complement numbers. */
static void
add1(unsigned char *a, unsigned char *b, size_t len)
{
int i;
int carry = 0;
for(i = len - 1; i >= 0; i--){
int x = a[i] + b[i];
int x = a[i] + b[i] + carry;
carry = x > 0xff;
a[i] = x & 0xff;
}
@@ -201,27 +191,36 @@ add1(unsigned char *a, unsigned char *b, size_t len)
}
}
/* key should point to a buffer of at least size (24) bytes */
static void
fold(const unsigned char *str, size_t len, unsigned char *out)
fold(const unsigned char *str, size_t len, unsigned char *key)
{
const int size = 24;
unsigned char key[24];
int num = 0;
int i;
int lcm = size * len / gcd(size, len);
unsigned char *tmp = malloc(lcm);
/* if len < size we need at most N * len bytes, ie < 2 * size;
if len > size we need at most 2 * len */
size_t maxlen = 2 * max(size, len);
size_t l = 0;
unsigned char *tmp = malloc(maxlen);
unsigned char *buf = malloc(len);
memcpy(buf, str, len);
for(; num < lcm; num += len){
memcpy(tmp + num, buf, len);
memset(key, 0, size);
do {
memcpy(tmp + l, buf, len);
l += len;
rr13(buf, len);
}
while(l >= size) {
add1(key, tmp, size);
l -= size;
if(l == 0)
break;
memmove(tmp, tmp + size, l);
}
} while(l != 0);
memset(buf, 0, len);
free(buf);
memset(key, 0, sizeof(key));
for(i = 0; i < lcm; i += size)
add1(key, tmp + i, size);
memset(tmp, 0, maxlen);
free(tmp);
memcpy(out, key, size);
}
static void
@@ -355,10 +354,9 @@ get_str(const void *pw, size_t pw_len, const void *salt, size_t salt_len,
char *p;
size_t len = pw_len + salt_len;
len = (len + 7) & ~7;
p = malloc(len);
p = calloc(len, 1);
if(p == NULL)
return NULL;
memset (p, 0, len);
memcpy(p, pw, pw_len);
memcpy(p + pw_len, salt, salt_len);
*ret_len = len;
@@ -396,7 +394,8 @@ string_to_key_internal (const unsigned char *str,
s = get_str(str, str_len, salt->data, salt->length, &len);
if(s == NULL)
return ENOMEM;
DES3_string_to_key(s, len, keys);
/* only des should pad to 8 */
DES3_string_to_key(s, str_len + salt->length, keys);
ret = krb5_data_copy(&key->keyvalue, keys, sizeof(keys));
memset(keys, 0, sizeof(keys));
break;