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:
@@ -97,7 +97,7 @@ q = (tbl[q & 0x0F] << 4) | (tbl[q >> 4])
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
static void
|
static void
|
||||||
xor (des_cblock *key, unsigned char *b)
|
xor (des_cblock *key, const unsigned char *b)
|
||||||
{
|
{
|
||||||
unsigned char *a = (unsigned char*)key;
|
unsigned char *a = (unsigned char*)key;
|
||||||
a[0] ^= b[0];
|
a[0] ^= b[0];
|
||||||
@@ -115,7 +115,7 @@ xor (des_cblock *key, unsigned char *b)
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
static void
|
static void
|
||||||
init (unsigned char *a, unsigned char *b)
|
init (unsigned char *a, const unsigned char *b)
|
||||||
{
|
{
|
||||||
a[0] = b[0] << 1;
|
a[0] = b[0] << 1;
|
||||||
a[1] = b[1] << 1;
|
a[1] = b[1] << 1;
|
||||||
@@ -128,25 +128,26 @@ init (unsigned char *a, unsigned char *b)
|
|||||||
}
|
}
|
||||||
|
|
||||||
static void
|
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;
|
des_key_schedule sched;
|
||||||
|
|
||||||
memset (key, 0, sizeof(des_cblock));
|
memset (key, 0, sizeof(des_cblock));
|
||||||
|
|
||||||
odd = 1;
|
even = 0;
|
||||||
for (i = 0; i < len; i += 8) {
|
for (i = 0; i < len; i += 8) {
|
||||||
unsigned char tmp[8];
|
unsigned char tmp[8];
|
||||||
|
|
||||||
init (tmp, (unsigned char*)&str[i]);
|
init (tmp, (const unsigned char*)(str + i));
|
||||||
|
|
||||||
if (odd == 0) {
|
if (even) {
|
||||||
odd = 1;
|
|
||||||
reverse (tmp);
|
reverse (tmp);
|
||||||
init (tmp, tmp);
|
init (tmp, tmp);
|
||||||
} else
|
}
|
||||||
odd = 0;
|
even = !even;
|
||||||
xor (key, tmp);
|
xor (key, tmp);
|
||||||
}
|
}
|
||||||
des_set_odd_parity (key);
|
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");
|
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
|
static void
|
||||||
rr13(unsigned char *buf, size_t len)
|
rr13(unsigned char *buf, size_t len)
|
||||||
{
|
{
|
||||||
unsigned char *tmp = malloc(len);
|
|
||||||
int i;
|
int i;
|
||||||
for(i = 0; i < len; i++){
|
/* assert(len >= 3); */
|
||||||
int x = (buf[i] << 8) | buf[(i + 1) % len];
|
unsigned a = buf[0], b = buf[len-1];
|
||||||
x >>= 5;
|
#define F(A, B) ((((A) << 3) | ((B) >> 5)) & 0xff)
|
||||||
tmp[(i + 2) % len] = x & 0xff;
|
buf[0] = F(buf[len-2], buf[len-1]);
|
||||||
}
|
for(i = len - 3; i >= 1; i--)
|
||||||
memcpy(buf, tmp, len);
|
buf[i + 2] = F(buf[i], buf[i+1]);
|
||||||
free(tmp);
|
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
|
static void
|
||||||
add1(unsigned char *a, unsigned char *b, size_t len)
|
add1(unsigned char *a, unsigned char *b, size_t len)
|
||||||
{
|
{
|
||||||
int i;
|
int i;
|
||||||
int carry = 0;
|
int carry = 0;
|
||||||
for(i = len - 1; i >= 0; i--){
|
for(i = len - 1; i >= 0; i--){
|
||||||
int x = a[i] + b[i];
|
int x = a[i] + b[i] + carry;
|
||||||
carry = x > 0xff;
|
carry = x > 0xff;
|
||||||
a[i] = 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
|
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;
|
const int size = 24;
|
||||||
unsigned char key[24];
|
/* if len < size we need at most N * len bytes, ie < 2 * size;
|
||||||
int num = 0;
|
if len > size we need at most 2 * len */
|
||||||
int i;
|
size_t maxlen = 2 * max(size, len);
|
||||||
int lcm = size * len / gcd(size, len);
|
size_t l = 0;
|
||||||
unsigned char *tmp = malloc(lcm);
|
unsigned char *tmp = malloc(maxlen);
|
||||||
unsigned char *buf = malloc(len);
|
unsigned char *buf = malloc(len);
|
||||||
|
|
||||||
memcpy(buf, str, len);
|
memcpy(buf, str, len);
|
||||||
for(; num < lcm; num += len){
|
memset(key, 0, size);
|
||||||
memcpy(tmp + num, buf, len);
|
do {
|
||||||
|
memcpy(tmp + l, buf, len);
|
||||||
|
l += len;
|
||||||
rr13(buf, 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);
|
free(buf);
|
||||||
memset(key, 0, sizeof(key));
|
memset(tmp, 0, maxlen);
|
||||||
for(i = 0; i < lcm; i += size)
|
|
||||||
add1(key, tmp + i, size);
|
|
||||||
free(tmp);
|
free(tmp);
|
||||||
memcpy(out, key, size);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
@@ -355,10 +354,9 @@ get_str(const void *pw, size_t pw_len, const void *salt, size_t salt_len,
|
|||||||
char *p;
|
char *p;
|
||||||
size_t len = pw_len + salt_len;
|
size_t len = pw_len + salt_len;
|
||||||
len = (len + 7) & ~7;
|
len = (len + 7) & ~7;
|
||||||
p = malloc(len);
|
p = calloc(len, 1);
|
||||||
if(p == NULL)
|
if(p == NULL)
|
||||||
return NULL;
|
return NULL;
|
||||||
memset (p, 0, len);
|
|
||||||
memcpy(p, pw, pw_len);
|
memcpy(p, pw, pw_len);
|
||||||
memcpy(p + pw_len, salt, salt_len);
|
memcpy(p + pw_len, salt, salt_len);
|
||||||
*ret_len = 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);
|
s = get_str(str, str_len, salt->data, salt->length, &len);
|
||||||
if(s == NULL)
|
if(s == NULL)
|
||||||
return ENOMEM;
|
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));
|
ret = krb5_data_copy(&key->keyvalue, keys, sizeof(keys));
|
||||||
memset(keys, 0, sizeof(keys));
|
memset(keys, 0, sizeof(keys));
|
||||||
break;
|
break;
|
||||||
|
Reference in New Issue
Block a user