introduce the `special' encryption methods that are not like all other
encryption methods and implement arcfour-hmac-md5 git-svn-id: svn://svn.h5l.se/heimdal/trunk/heimdal@8560 ec53bebd-3082-4978-b11e-865c3cabbd6b
This commit is contained in:
@@ -65,6 +65,7 @@ struct krb5_crypto_data {
|
||||
#define F_DERIVED 4 /* uses derived keys */
|
||||
#define F_VARIANT 8 /* uses `variant' keys (6.4.3) */
|
||||
#define F_PSEUDO 16 /* not a real protocol type */
|
||||
#define F_SPECIAL 32 /* backwards */
|
||||
|
||||
struct salt_type {
|
||||
krb5_salttype type;
|
||||
@@ -93,9 +94,16 @@ struct checksum_type {
|
||||
size_t blocksize;
|
||||
size_t checksumsize;
|
||||
unsigned flags;
|
||||
void (*checksum)(krb5_context, struct key_data*, void*, size_t, Checksum*);
|
||||
krb5_error_code (*verify)(krb5_context, struct key_data*,
|
||||
void*, size_t, Checksum*);
|
||||
void (*checksum)(krb5_context context,
|
||||
struct key_data *key,
|
||||
const void *buf, size_t len,
|
||||
unsigned usage,
|
||||
Checksum *csum);
|
||||
krb5_error_code (*verify)(krb5_context context,
|
||||
struct key_data *key,
|
||||
const void *buf, size_t len,
|
||||
unsigned usage,
|
||||
Checksum *csum);
|
||||
};
|
||||
|
||||
struct encryption_type {
|
||||
@@ -107,7 +115,10 @@ struct encryption_type {
|
||||
struct checksum_type *cksumtype;
|
||||
struct checksum_type *keyed_checksum;
|
||||
unsigned flags;
|
||||
void (*encrypt)(struct key_data *, void *, size_t, int);
|
||||
krb5_error_code (*encrypt)(struct key_data *key,
|
||||
void *data, size_t len,
|
||||
krb5_boolean encrypt,
|
||||
int usage);
|
||||
};
|
||||
|
||||
#define ENCRYPTION_USAGE(U) (((U) << 8) | 0xAA)
|
||||
@@ -228,14 +239,12 @@ DES_AFS3_Transarc_string_to_key (krb5_data pw,
|
||||
memcpy(&temp_key, "kerberos", 8);
|
||||
des_set_odd_parity (&temp_key);
|
||||
des_set_key (&temp_key, schedule);
|
||||
des_cbc_cksum ((const void *)password, &ivec, passlen,
|
||||
schedule, &ivec);
|
||||
des_cbc_cksum ((des_cblock *)password, &ivec, passlen, schedule, &ivec);
|
||||
|
||||
memcpy(&temp_key, &ivec, 8);
|
||||
des_set_odd_parity (&temp_key);
|
||||
des_set_key (&temp_key, schedule);
|
||||
des_cbc_cksum ((const void *)password, key, passlen,
|
||||
schedule, &ivec);
|
||||
des_cbc_cksum ((des_cblock *)password, key, passlen, schedule, &ivec);
|
||||
memset(&schedule, 0, sizeof(schedule));
|
||||
memset(&temp_key, 0, sizeof(temp_key));
|
||||
memset(&ivec, 0, sizeof(ivec));
|
||||
@@ -339,8 +348,8 @@ DES3_string_to_key(krb5_context context,
|
||||
des_set_key(keys + i, s[i]);
|
||||
}
|
||||
memset(&ivec, 0, sizeof(ivec));
|
||||
des_ede3_cbc_encrypt((const void *)tmp,
|
||||
(void *)tmp, sizeof(tmp),
|
||||
des_ede3_cbc_encrypt((des_cblock *)tmp,
|
||||
(des_cblock *)tmp, sizeof(tmp),
|
||||
s[0], s[1], s[2], &ivec, DES_ENCRYPT);
|
||||
memset(s, 0, sizeof(s));
|
||||
memset(&ivec, 0, sizeof(ivec));
|
||||
@@ -416,7 +425,7 @@ ARCFOUR_string_to_key(krb5_context context,
|
||||
int i;
|
||||
MD4_CTX m;
|
||||
|
||||
len = 2 * (password.length + salt.saltvalue.length);
|
||||
len = 2 * password.length;
|
||||
s = malloc (len);
|
||||
if (len != 0 && s == NULL)
|
||||
return ENOMEM;
|
||||
@@ -424,10 +433,6 @@ ARCFOUR_string_to_key(krb5_context context,
|
||||
*p++ = ((char *)password.data)[i];
|
||||
*p++ = 0;
|
||||
}
|
||||
for (i = 0; i < salt.saltvalue.length; ++i) {
|
||||
*p++ = ((char *)salt.saltvalue.data)[i];
|
||||
*p++ = 0;
|
||||
}
|
||||
MD4Init (&m);
|
||||
MD4Update (&m, s, len);
|
||||
key->keytype = enctype;
|
||||
@@ -670,6 +675,11 @@ krb5_string_to_key (krb5_context context,
|
||||
return krb5_string_to_key_data(context, enctype, pw, principal, key);
|
||||
}
|
||||
|
||||
/*
|
||||
* Do a string -> key for encryption type `enctype' operation on
|
||||
* `password' (with salt `salt'), returning the resulting key in `key'
|
||||
*/
|
||||
|
||||
krb5_error_code
|
||||
krb5_string_to_key_data_salt (krb5_context context,
|
||||
krb5_enctype enctype,
|
||||
@@ -687,6 +697,12 @@ krb5_string_to_key_data_salt (krb5_context context,
|
||||
return HEIM_ERR_SALTTYPE_NOSUPP;
|
||||
}
|
||||
|
||||
/*
|
||||
* Do a string -> key for encryption type `enctype' operation on the
|
||||
* string `password' (with salt `salt'), returning the resulting key
|
||||
* in `key'
|
||||
*/
|
||||
|
||||
krb5_error_code
|
||||
krb5_string_to_key_salt (krb5_context context,
|
||||
krb5_enctype enctype,
|
||||
@@ -779,8 +795,9 @@ _key_schedule(krb5_context context,
|
||||
static void
|
||||
NONE_checksum(krb5_context context,
|
||||
struct key_data *key,
|
||||
void *data,
|
||||
const void *data,
|
||||
size_t len,
|
||||
unsigned usage,
|
||||
Checksum *C)
|
||||
{
|
||||
}
|
||||
@@ -788,8 +805,9 @@ NONE_checksum(krb5_context context,
|
||||
static void
|
||||
CRC32_checksum(krb5_context context,
|
||||
struct key_data *key,
|
||||
void *data,
|
||||
const void *data,
|
||||
size_t len,
|
||||
unsigned usage,
|
||||
Checksum *C)
|
||||
{
|
||||
u_int32_t crc;
|
||||
@@ -805,8 +823,9 @@ CRC32_checksum(krb5_context context,
|
||||
static void
|
||||
RSA_MD4_checksum(krb5_context context,
|
||||
struct key_data *key,
|
||||
void *data,
|
||||
const void *data,
|
||||
size_t len,
|
||||
unsigned usage,
|
||||
Checksum *C)
|
||||
{
|
||||
MD4_CTX m;
|
||||
@@ -819,8 +838,9 @@ RSA_MD4_checksum(krb5_context context,
|
||||
static void
|
||||
RSA_MD4_DES_checksum(krb5_context context,
|
||||
struct key_data *key,
|
||||
void *data,
|
||||
const void *data,
|
||||
size_t len,
|
||||
unsigned usage,
|
||||
Checksum *cksum)
|
||||
{
|
||||
MD4_CTX md4;
|
||||
@@ -833,8 +853,8 @@ RSA_MD4_DES_checksum(krb5_context context,
|
||||
MD4Update (&md4, data, len);
|
||||
MD4Final (p + 8, &md4);
|
||||
memset (&ivec, 0, sizeof(ivec));
|
||||
des_cbc_encrypt((const void *)p,
|
||||
(void *)p,
|
||||
des_cbc_encrypt((des_cblock*)p,
|
||||
(des_cblock*)p,
|
||||
24,
|
||||
key->schedule->data,
|
||||
&ivec,
|
||||
@@ -844,8 +864,9 @@ RSA_MD4_DES_checksum(krb5_context context,
|
||||
static krb5_error_code
|
||||
RSA_MD4_DES_verify(krb5_context context,
|
||||
struct key_data *key,
|
||||
void *data,
|
||||
const void *data,
|
||||
size_t len,
|
||||
unsigned usage,
|
||||
Checksum *C)
|
||||
{
|
||||
MD4_CTX md4;
|
||||
@@ -875,8 +896,9 @@ RSA_MD4_DES_verify(krb5_context context,
|
||||
static void
|
||||
RSA_MD5_checksum(krb5_context context,
|
||||
struct key_data *key,
|
||||
void *data,
|
||||
const void *data,
|
||||
size_t len,
|
||||
unsigned usage,
|
||||
Checksum *C)
|
||||
{
|
||||
MD5_CTX m;
|
||||
@@ -889,8 +911,9 @@ RSA_MD5_checksum(krb5_context context,
|
||||
static void
|
||||
RSA_MD5_DES_checksum(krb5_context context,
|
||||
struct key_data *key,
|
||||
void *data,
|
||||
const void *data,
|
||||
size_t len,
|
||||
unsigned usage,
|
||||
Checksum *C)
|
||||
{
|
||||
MD5_CTX md5;
|
||||
@@ -903,8 +926,8 @@ RSA_MD5_DES_checksum(krb5_context context,
|
||||
MD5Update (&md5, data, len);
|
||||
MD5Final (p + 8, &md5);
|
||||
memset (&ivec, 0, sizeof(ivec));
|
||||
des_cbc_encrypt((const void *)p,
|
||||
(void *)p,
|
||||
des_cbc_encrypt((des_cblock*)p,
|
||||
(des_cblock*)p,
|
||||
24,
|
||||
key->schedule->data,
|
||||
&ivec,
|
||||
@@ -914,8 +937,9 @@ RSA_MD5_DES_checksum(krb5_context context,
|
||||
static krb5_error_code
|
||||
RSA_MD5_DES_verify(krb5_context context,
|
||||
struct key_data *key,
|
||||
void *data,
|
||||
const void *data,
|
||||
size_t len,
|
||||
unsigned usage,
|
||||
Checksum *C)
|
||||
{
|
||||
MD5_CTX md5;
|
||||
@@ -946,8 +970,9 @@ RSA_MD5_DES_verify(krb5_context context,
|
||||
static void
|
||||
RSA_MD5_DES3_checksum(krb5_context context,
|
||||
struct key_data *key,
|
||||
void *data,
|
||||
const void *data,
|
||||
size_t len,
|
||||
unsigned usage,
|
||||
Checksum *C)
|
||||
{
|
||||
MD5_CTX md5;
|
||||
@@ -961,8 +986,8 @@ RSA_MD5_DES3_checksum(krb5_context context,
|
||||
MD5Update (&md5, data, len);
|
||||
MD5Final (p + 8, &md5);
|
||||
memset (&ivec, 0, sizeof(ivec));
|
||||
des_ede3_cbc_encrypt((const void *)p,
|
||||
(void *)p,
|
||||
des_ede3_cbc_encrypt((des_cblock*)p,
|
||||
(des_cblock*)p,
|
||||
24,
|
||||
sched[0], sched[1], sched[2],
|
||||
&ivec,
|
||||
@@ -972,8 +997,9 @@ RSA_MD5_DES3_checksum(krb5_context context,
|
||||
static krb5_error_code
|
||||
RSA_MD5_DES3_verify(krb5_context context,
|
||||
struct key_data *key,
|
||||
void *data,
|
||||
const void *data,
|
||||
size_t len,
|
||||
unsigned usage,
|
||||
Checksum *C)
|
||||
{
|
||||
MD5_CTX md5;
|
||||
@@ -1004,8 +1030,9 @@ RSA_MD5_DES3_verify(krb5_context context,
|
||||
static void
|
||||
SHA1_checksum(krb5_context context,
|
||||
struct key_data *key,
|
||||
void *data,
|
||||
const void *data,
|
||||
size_t len,
|
||||
unsigned usage,
|
||||
Checksum *C)
|
||||
{
|
||||
SHA1_CTX m;
|
||||
@@ -1019,8 +1046,9 @@ SHA1_checksum(krb5_context context,
|
||||
static void
|
||||
hmac(krb5_context context,
|
||||
struct checksum_type *cm,
|
||||
void *data,
|
||||
const void *data,
|
||||
size_t len,
|
||||
unsigned usage,
|
||||
struct key_data *keyblock,
|
||||
Checksum *result)
|
||||
{
|
||||
@@ -1034,6 +1062,7 @@ hmac(krb5_context context,
|
||||
keyblock,
|
||||
keyblock->key->keyvalue.data,
|
||||
keyblock->key->keyvalue.length,
|
||||
usage,
|
||||
result);
|
||||
key = result->checksum.data;
|
||||
key_len = result->checksum.length;
|
||||
@@ -1050,11 +1079,12 @@ hmac(krb5_context context,
|
||||
opad[i] ^= key[i];
|
||||
}
|
||||
memcpy(ipad + cm->blocksize, data, len);
|
||||
(*cm->checksum)(context, keyblock, ipad, cm->blocksize + len, result);
|
||||
(*cm->checksum)(context, keyblock, ipad, cm->blocksize + len,
|
||||
usage, result);
|
||||
memcpy(opad + cm->blocksize, result->checksum.data,
|
||||
result->checksum.length);
|
||||
(*cm->checksum)(context, keyblock, opad,
|
||||
cm->blocksize + cm->checksumsize, result);
|
||||
cm->blocksize + cm->checksumsize, usage, result);
|
||||
memset(ipad, 0, cm->blocksize + len);
|
||||
free(ipad);
|
||||
memset(opad, 0, cm->blocksize + cm->checksumsize);
|
||||
@@ -1064,13 +1094,84 @@ hmac(krb5_context context,
|
||||
static void
|
||||
HMAC_SHA1_DES3_checksum(krb5_context context,
|
||||
struct key_data *key,
|
||||
void *data,
|
||||
const void *data,
|
||||
size_t len,
|
||||
unsigned usage,
|
||||
Checksum *result)
|
||||
{
|
||||
struct checksum_type *c = _find_checksum(CKSUMTYPE_SHA1);
|
||||
|
||||
hmac(context, c, data, len, key, result);
|
||||
hmac(context, c, data, len, usage, key, result);
|
||||
}
|
||||
|
||||
/*
|
||||
* checksum according to section 5. of draft-brezak-win2k-krb-rc4-hmac-03.txt
|
||||
*/
|
||||
|
||||
static void
|
||||
HMAC_MD5_checksum(krb5_context context,
|
||||
struct key_data *key,
|
||||
const void *data,
|
||||
size_t len,
|
||||
unsigned usage,
|
||||
Checksum *result)
|
||||
{
|
||||
MD5_CTX md5;
|
||||
struct checksum_type *c = _find_checksum (CKSUMTYPE_RSA_MD5);
|
||||
const char signature[] = "signaturekey";
|
||||
Checksum ksign_c;
|
||||
struct key_data ksign;
|
||||
krb5_keyblock kb;
|
||||
unsigned char t[4];
|
||||
unsigned char tmp[16];
|
||||
unsigned char ksign_c_data[16];
|
||||
|
||||
ksign_c.checksum.length = sizeof(ksign_c_data);
|
||||
ksign_c.checksum.data = ksign_c_data;
|
||||
hmac(context, c, signature, sizeof(signature), 0, key, &ksign_c);
|
||||
ksign.key = &kb;
|
||||
kb.keyvalue = ksign_c.checksum;
|
||||
MD5Init (&md5);
|
||||
t[0] = (usage >> 0) & 0xFF;
|
||||
t[1] = (usage >> 8) & 0xFF;
|
||||
t[2] = (usage >> 16) & 0xFF;
|
||||
t[3] = (usage >> 24) & 0xFF;
|
||||
MD5Update (&md5, t, 4);
|
||||
MD5Update (&md5, data, len);
|
||||
MD5Final (tmp, &md5);
|
||||
hmac(context, c, tmp, sizeof(tmp), 0, &ksign, result);
|
||||
}
|
||||
|
||||
/*
|
||||
* same as previous but being used while encrypting.
|
||||
*/
|
||||
|
||||
static void
|
||||
HMAC_MD5_checksum_enc(krb5_context context,
|
||||
struct key_data *key,
|
||||
const void *data,
|
||||
size_t len,
|
||||
unsigned usage,
|
||||
Checksum *result)
|
||||
{
|
||||
struct checksum_type *c = _find_checksum (CKSUMTYPE_RSA_MD5);
|
||||
Checksum ksign_c;
|
||||
struct key_data ksign;
|
||||
krb5_keyblock kb;
|
||||
unsigned char t[4];
|
||||
unsigned char ksign_c_data[16];
|
||||
|
||||
t[0] = (usage >> 0) & 0xFF;
|
||||
t[1] = (usage >> 8) & 0xFF;
|
||||
t[2] = (usage >> 16) & 0xFF;
|
||||
t[3] = (usage >> 24) & 0xFF;
|
||||
|
||||
ksign_c.checksum.length = sizeof(ksign_c_data);
|
||||
ksign_c.checksum.data = ksign_c_data;
|
||||
hmac(context, c, t, sizeof(t), 0, key, &ksign_c);
|
||||
ksign.key = &kb;
|
||||
kb.keyvalue = ksign_c.checksum;
|
||||
hmac(context, c, data, len, 0, &ksign, result);
|
||||
}
|
||||
|
||||
struct checksum_type checksum_none = {
|
||||
@@ -1182,6 +1283,26 @@ struct checksum_type checksum_hmac_sha1_des3 = {
|
||||
NULL
|
||||
};
|
||||
|
||||
struct checksum_type checksum_hmac_md5 = {
|
||||
CKSUMTYPE_HMAC_MD5,
|
||||
"hmac-md5",
|
||||
64,
|
||||
16,
|
||||
F_KEYED | F_CPROOF,
|
||||
HMAC_MD5_checksum,
|
||||
NULL
|
||||
};
|
||||
|
||||
struct checksum_type checksum_hmac_md5_enc = {
|
||||
CKSUMTYPE_HMAC_MD5_ENC,
|
||||
"hmac-md5-enc",
|
||||
64,
|
||||
16,
|
||||
F_KEYED | F_CPROOF | F_PSEUDO,
|
||||
HMAC_MD5_checksum_enc,
|
||||
NULL
|
||||
};
|
||||
|
||||
struct checksum_type *checksum_types[] = {
|
||||
&checksum_none,
|
||||
&checksum_crc32,
|
||||
@@ -1196,7 +1317,9 @@ struct checksum_type *checksum_types[] = {
|
||||
&checksum_rsa_md5_des,
|
||||
&checksum_rsa_md5_des3,
|
||||
&checksum_sha1,
|
||||
&checksum_hmac_sha1_des3
|
||||
&checksum_hmac_sha1_des3,
|
||||
&checksum_hmac_md5,
|
||||
&checksum_hmac_md5_enc
|
||||
};
|
||||
|
||||
static int num_checksums = sizeof(checksum_types) / sizeof(checksum_types[0]);
|
||||
@@ -1263,7 +1386,7 @@ do_checksum (krb5_context context,
|
||||
dkey = NULL;
|
||||
result->cksumtype = ct->type;
|
||||
krb5_data_alloc(&result->checksum, ct->checksumsize);
|
||||
(*ct->checksum)(context, dkey, data, len, result);
|
||||
(*ct->checksum)(context, dkey, data, len, usage, result);
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -1329,13 +1452,13 @@ verify_checksum(krb5_context context,
|
||||
else
|
||||
dkey = NULL;
|
||||
if(ct->verify)
|
||||
return (*ct->verify)(context, dkey, data, len, cksum);
|
||||
return (*ct->verify)(context, dkey, data, len, usage, cksum);
|
||||
|
||||
ret = krb5_data_alloc (&c.checksum, ct->checksumsize);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
(*ct->checksum)(context, dkey, data, len, &c);
|
||||
(*ct->checksum)(context, dkey, data, len, usage, &c);
|
||||
|
||||
if(c.checksum.length != cksum->checksum.length ||
|
||||
memcmp(c.checksum.data, cksum->checksum.data, c.checksum.length))
|
||||
@@ -1394,55 +1517,64 @@ krb5_checksum_is_collision_proof(krb5_context context,
|
||||
* *
|
||||
************************************************************/
|
||||
|
||||
static void
|
||||
static krb5_error_code
|
||||
NULL_encrypt(struct key_data *key,
|
||||
void *data,
|
||||
size_t len,
|
||||
krb5_boolean encrypt)
|
||||
krb5_boolean encrypt,
|
||||
int usage)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void
|
||||
static krb5_error_code
|
||||
DES_CBC_encrypt_null_ivec(struct key_data *key,
|
||||
void *data,
|
||||
size_t len,
|
||||
krb5_boolean encrypt)
|
||||
krb5_boolean encrypt,
|
||||
int usage)
|
||||
{
|
||||
des_cblock ivec;
|
||||
des_key_schedule *s = key->schedule->data;
|
||||
memset(&ivec, 0, sizeof(ivec));
|
||||
des_cbc_encrypt(data, data, len, *s, &ivec, encrypt);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void
|
||||
static krb5_error_code
|
||||
DES_CBC_encrypt_key_ivec(struct key_data *key,
|
||||
void *data,
|
||||
size_t len,
|
||||
krb5_boolean encrypt)
|
||||
krb5_boolean encrypt,
|
||||
int usage)
|
||||
{
|
||||
des_cblock ivec;
|
||||
des_key_schedule *s = key->schedule->data;
|
||||
memcpy(&ivec, key->key->keyvalue.data, sizeof(ivec));
|
||||
des_cbc_encrypt(data, data, len, *s, &ivec, encrypt);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void
|
||||
static krb5_error_code
|
||||
DES3_CBC_encrypt(struct key_data *key,
|
||||
void *data,
|
||||
size_t len,
|
||||
krb5_boolean encrypt)
|
||||
krb5_boolean encrypt,
|
||||
int usage)
|
||||
{
|
||||
des_cblock ivec;
|
||||
des_key_schedule *s = key->schedule->data;
|
||||
memset(&ivec, 0, sizeof(ivec));
|
||||
des_ede3_cbc_encrypt(data, data, len, s[0], s[1], s[2], &ivec, encrypt);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void
|
||||
static krb5_error_code
|
||||
DES_CFB64_encrypt_null_ivec(struct key_data *key,
|
||||
void *data,
|
||||
size_t len,
|
||||
krb5_boolean encrypt)
|
||||
krb5_boolean encrypt,
|
||||
int usage)
|
||||
{
|
||||
des_cblock ivec;
|
||||
int num = 0;
|
||||
@@ -1450,34 +1582,209 @@ DES_CFB64_encrypt_null_ivec(struct key_data *key,
|
||||
memset(&ivec, 0, sizeof(ivec));
|
||||
|
||||
des_cfb64_encrypt(data, data, len, *s, &ivec, &num, encrypt);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void
|
||||
static krb5_error_code
|
||||
DES_PCBC_encrypt_key_ivec(struct key_data *key,
|
||||
void *data,
|
||||
size_t len,
|
||||
krb5_boolean encrypt)
|
||||
krb5_boolean encrypt,
|
||||
int usage)
|
||||
{
|
||||
des_cblock ivec;
|
||||
des_key_schedule *s = key->schedule->data;
|
||||
memcpy(&ivec, key->key->keyvalue.data, sizeof(ivec));
|
||||
|
||||
des_pcbc_encrypt(data, data, len, *s, &ivec, encrypt);
|
||||
}
|
||||
|
||||
static void
|
||||
ARCFOUR_encrypt(struct key_data *key,
|
||||
void *data,
|
||||
size_t len,
|
||||
krb5_boolean encrypt)
|
||||
{
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* these should currently be in reverse preference order.
|
||||
* section 6 of draft-brezak-win2k-krb-rc4-hmac-03
|
||||
*
|
||||
* warning: not for small children
|
||||
*/
|
||||
|
||||
static krb5_error_code
|
||||
ARCFOUR_subencrypt(struct key_data *key,
|
||||
void *data,
|
||||
size_t len,
|
||||
int usage)
|
||||
{
|
||||
struct checksum_type *c = _find_checksum (CKSUMTYPE_RSA_MD5);
|
||||
Checksum k1_c, k2_c, k3_c, cksum;
|
||||
struct key_data ke;
|
||||
krb5_keyblock kb;
|
||||
unsigned char t[4];
|
||||
RC4_KEY rc4_key;
|
||||
char *cdata = (char *)data;
|
||||
unsigned char k1_c_data[16], k2_c_data[16], k3_c_data[16];
|
||||
|
||||
t[0] = (usage >> 0) & 0xFF;
|
||||
t[1] = (usage >> 8) & 0xFF;
|
||||
t[2] = (usage >> 16) & 0xFF;
|
||||
t[3] = (usage >> 24) & 0xFF;
|
||||
|
||||
k1_c.checksum.length = sizeof(k1_c_data);
|
||||
k1_c.checksum.data = k1_c_data;
|
||||
|
||||
hmac(NULL, c, t, sizeof(t), 0, key, &k1_c);
|
||||
|
||||
memcpy (k2_c_data, k1_c_data, sizeof(k1_c_data));
|
||||
|
||||
k2_c.checksum.length = sizeof(k2_c_data);
|
||||
k2_c.checksum.data = k2_c_data;
|
||||
|
||||
ke.key = &kb;
|
||||
kb.keyvalue = k2_c.checksum;
|
||||
|
||||
cksum.checksum.length = 16;
|
||||
cksum.checksum.data = data;
|
||||
|
||||
hmac(NULL, c, cdata + 16, len - 16, 0, &ke, &cksum);
|
||||
|
||||
ke.key = &kb;
|
||||
kb.keyvalue = k1_c.checksum;
|
||||
|
||||
k3_c.checksum.length = sizeof(k3_c_data);
|
||||
k3_c.checksum.data = k3_c_data;
|
||||
|
||||
hmac(NULL, c, data, 16, 0, &ke, &k3_c);
|
||||
|
||||
RC4_set_key (&rc4_key, k3_c.checksum.length, k3_c.checksum.data);
|
||||
RC4 (&rc4_key, len - 16, cdata + 16, cdata + 16);
|
||||
memset (k1_c_data, 0, sizeof(k1_c_data));
|
||||
memset (k2_c_data, 0, sizeof(k2_c_data));
|
||||
memset (k3_c_data, 0, sizeof(k3_c_data));
|
||||
return 0;
|
||||
}
|
||||
|
||||
static krb5_error_code
|
||||
ARCFOUR_subdecrypt(struct key_data *key,
|
||||
void *data,
|
||||
size_t len,
|
||||
int usage)
|
||||
{
|
||||
struct checksum_type *c = _find_checksum (CKSUMTYPE_RSA_MD5);
|
||||
Checksum k1_c, k2_c, k3_c, cksum;
|
||||
struct key_data ke;
|
||||
krb5_keyblock kb;
|
||||
unsigned char t[4];
|
||||
RC4_KEY rc4_key;
|
||||
char *cdata = (char *)data;
|
||||
unsigned char k1_c_data[16], k2_c_data[16], k3_c_data[16];
|
||||
unsigned char cksum_data[16];
|
||||
|
||||
t[0] = (usage >> 0) & 0xFF;
|
||||
t[1] = (usage >> 8) & 0xFF;
|
||||
t[2] = (usage >> 16) & 0xFF;
|
||||
t[3] = (usage >> 24) & 0xFF;
|
||||
|
||||
k1_c.checksum.length = sizeof(k1_c_data);
|
||||
k1_c.checksum.data = k1_c_data;
|
||||
|
||||
hmac(NULL, c, t, sizeof(t), 0, key, &k1_c);
|
||||
|
||||
memcpy (k2_c_data, k1_c_data, sizeof(k1_c_data));
|
||||
|
||||
k2_c.checksum.length = sizeof(k2_c_data);
|
||||
k2_c.checksum.data = k2_c_data;
|
||||
|
||||
ke.key = &kb;
|
||||
kb.keyvalue = k1_c.checksum;
|
||||
|
||||
k3_c.checksum.length = sizeof(k3_c_data);
|
||||
k3_c.checksum.data = k3_c_data;
|
||||
|
||||
hmac(NULL, c, cdata, 16, 0, &ke, &k3_c);
|
||||
|
||||
RC4_set_key (&rc4_key, k3_c.checksum.length, k3_c.checksum.data);
|
||||
RC4 (&rc4_key, len - 16, cdata + 16, cdata + 16);
|
||||
|
||||
ke.key = &kb;
|
||||
kb.keyvalue = k2_c.checksum;
|
||||
|
||||
cksum.checksum.length = 16;
|
||||
cksum.checksum.data = cksum_data;
|
||||
|
||||
hmac(NULL, c, cdata + 16, len - 16, 0, &ke, &cksum);
|
||||
|
||||
memset (k1_c_data, 0, sizeof(k1_c_data));
|
||||
memset (k2_c_data, 0, sizeof(k2_c_data));
|
||||
memset (k3_c_data, 0, sizeof(k3_c_data));
|
||||
|
||||
if (memcmp (cksum.checksum.data, data, 16) != 0)
|
||||
return KRB5KRB_AP_ERR_BAD_INTEGRITY;
|
||||
else
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* convert the usage numbers used in
|
||||
* draft-ietf-cat-kerb-key-derivation-00.txt to the ones in
|
||||
* draft-brezak-win2k-krb-rc4-hmac-03.txt
|
||||
*/
|
||||
|
||||
static int
|
||||
usage2arcfour (int usage)
|
||||
{
|
||||
switch (usage) {
|
||||
case KRB5_KU_PA_ENC_TIMESTAMP :
|
||||
return 1;
|
||||
case KRB5_KU_TICKET :
|
||||
return 8;
|
||||
case KRB5_KU_AS_REP_ENC_PART :
|
||||
return 8;
|
||||
case KRB5_KU_TGS_REQ_AUTH_DAT_SESSION :
|
||||
case KRB5_KU_TGS_REQ_AUTH_DAT_SUBKEY :
|
||||
case KRB5_KU_TGS_REQ_AUTH_CKSUM :
|
||||
case KRB5_KU_TGS_REQ_AUTH :
|
||||
return 7;
|
||||
case KRB5_KU_TGS_REP_ENC_PART_SESSION :
|
||||
case KRB5_KU_TGS_REP_ENC_PART_SUB_KEY :
|
||||
return 8;
|
||||
case KRB5_KU_AP_REQ_AUTH_CKSUM :
|
||||
case KRB5_KU_AP_REQ_AUTH :
|
||||
case KRB5_KU_AP_REQ_ENC_PART :
|
||||
return 11;
|
||||
case KRB5_KU_KRB_PRIV :
|
||||
case KRB5_KU_KRB_CRED :
|
||||
case KRB5_KU_KRB_SAFE_CKSUM :
|
||||
case KRB5_KU_OTHER_ENCRYPTED :
|
||||
case KRB5_KU_OTHER_CKSUM :
|
||||
case KRB5_KU_KRB_ERROR :
|
||||
case KRB5_KU_AD_KDC_ISSUED :
|
||||
case KRB5_KU_MANDATORY_TICKET_EXTENSION :
|
||||
case KRB5_KU_AUTH_DATA_TICKET_EXTENSION :
|
||||
case KRB5_KU_USAGE_SEAL :
|
||||
case KRB5_KU_USAGE_SIGN :
|
||||
case KRB5_KU_USAGE_MIC :
|
||||
default :
|
||||
abort ();
|
||||
}
|
||||
}
|
||||
|
||||
static krb5_error_code
|
||||
ARCFOUR_encrypt(struct key_data *key,
|
||||
void *data,
|
||||
size_t len,
|
||||
krb5_boolean encrypt,
|
||||
int usage)
|
||||
{
|
||||
usage = usage2arcfour (usage);
|
||||
|
||||
if (encrypt)
|
||||
return ARCFOUR_subencrypt (key, data, len, usage);
|
||||
else
|
||||
return ARCFOUR_subdecrypt (key, data, len, usage);
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* these should currently be in reverse preference order.
|
||||
* (only relevant for !F_PSEUDO) */
|
||||
|
||||
static struct encryption_type etypes[] = {
|
||||
{
|
||||
ETYPE_NULL,
|
||||
@@ -1523,6 +1830,17 @@ static struct encryption_type etypes[] = {
|
||||
0,
|
||||
DES_CBC_encrypt_null_ivec,
|
||||
},
|
||||
{
|
||||
ETYPE_ARCFOUR_HMAC_MD5,
|
||||
"arcfour-hmac-md5",
|
||||
1,
|
||||
8,
|
||||
&keytype_arcfour,
|
||||
&checksum_hmac_md5_enc,
|
||||
&checksum_hmac_md5_enc,
|
||||
F_SPECIAL,
|
||||
ARCFOUR_encrypt
|
||||
},
|
||||
{
|
||||
ETYPE_DES3_CBC_MD5,
|
||||
"des3-cbc-md5",
|
||||
@@ -1755,6 +2073,12 @@ derived_crypto(krb5_context context,
|
||||
return (crypto->et->flags & F_DERIVED) != 0;
|
||||
}
|
||||
|
||||
static krb5_boolean
|
||||
special_crypto(krb5_context context,
|
||||
krb5_crypto crypto)
|
||||
{
|
||||
return (crypto->et->flags & F_SPECIAL) != 0;
|
||||
}
|
||||
|
||||
#define CHECKSUMSIZE(C) ((C)->checksumsize)
|
||||
#define CHECKSUMTYPE(C) ((C)->type)
|
||||
@@ -1817,7 +2141,7 @@ encrypt_internal_derived(krb5_context context,
|
||||
#ifdef CRYPTO_DEBUG
|
||||
krb5_crypto_debug(context, 1, block_sz, dkey->key);
|
||||
#endif
|
||||
(*et->encrypt)(dkey, p, block_sz, 1);
|
||||
(*et->encrypt)(dkey, p, block_sz, 1, usage);
|
||||
result->data = p;
|
||||
result->length = block_sz + checksum_sz;
|
||||
return 0;
|
||||
@@ -1879,12 +2203,40 @@ encrypt_internal(krb5_context context,
|
||||
#ifdef CRYPTO_DEBUG
|
||||
krb5_crypto_debug(context, 1, block_sz, crypto->key.key);
|
||||
#endif
|
||||
(*et->encrypt)(&crypto->key, p, block_sz, 1);
|
||||
(*et->encrypt)(&crypto->key, p, block_sz, 1, 0);
|
||||
result->data = p;
|
||||
result->length = block_sz;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static krb5_error_code
|
||||
encrypt_internal_special(krb5_context context,
|
||||
krb5_crypto crypto,
|
||||
int usage,
|
||||
void *data,
|
||||
size_t len,
|
||||
krb5_data *result)
|
||||
{
|
||||
struct encryption_type *et = crypto->et;
|
||||
size_t cksum_sz = CHECKSUMSIZE(et->cksumtype);
|
||||
size_t sz = len + cksum_sz + et->confoundersize;
|
||||
char *tmp, *p;
|
||||
|
||||
tmp = malloc (sz);
|
||||
if (tmp == NULL)
|
||||
return ENOMEM;
|
||||
p = tmp;
|
||||
memset (p, 0, cksum_sz);
|
||||
p += cksum_sz;
|
||||
krb5_generate_random_block(p, et->confoundersize);
|
||||
p += et->confoundersize;
|
||||
memcpy (p, data, len);
|
||||
(*et->encrypt)(&crypto->key, tmp, sz, TRUE, usage);
|
||||
result->data = tmp;
|
||||
result->length = sz;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static krb5_error_code
|
||||
decrypt_internal_derived(krb5_context context,
|
||||
krb5_crypto crypto,
|
||||
@@ -1922,7 +2274,7 @@ decrypt_internal_derived(krb5_context context,
|
||||
#ifdef CRYPTO_DEBUG
|
||||
krb5_crypto_debug(context, 0, len, dkey->key);
|
||||
#endif
|
||||
(*et->encrypt)(dkey, p, len, 0);
|
||||
(*et->encrypt)(dkey, p, len, 0, usage);
|
||||
|
||||
cksum.checksum.data = p + len;
|
||||
cksum.checksum.length = checksum_sz;
|
||||
@@ -1976,11 +2328,11 @@ decrypt_internal(krb5_context context,
|
||||
#ifdef CRYPTO_DEBUG
|
||||
krb5_crypto_debug(context, 0, len, crypto->key.key);
|
||||
#endif
|
||||
(*et->encrypt)(&crypto->key, p, len, 0);
|
||||
(*et->encrypt)(&crypto->key, p, len, 0, 0);
|
||||
ret = krb5_data_copy(&cksum.checksum, p + et->confoundersize, checksum_sz);
|
||||
if(ret) {
|
||||
free(p);
|
||||
return ret;
|
||||
free(p);
|
||||
return ret;
|
||||
}
|
||||
memset(p + et->confoundersize, 0, checksum_sz);
|
||||
cksum.cksumtype = CHECKSUMTYPE(et->cksumtype);
|
||||
@@ -2001,6 +2353,34 @@ decrypt_internal(krb5_context context,
|
||||
return 0;
|
||||
}
|
||||
|
||||
static krb5_error_code
|
||||
decrypt_internal_special(krb5_context context,
|
||||
krb5_crypto crypto,
|
||||
int usage,
|
||||
void *data,
|
||||
size_t len,
|
||||
krb5_data *result)
|
||||
{
|
||||
struct encryption_type *et = crypto->et;
|
||||
size_t cksum_sz = CHECKSUMSIZE(et->cksumtype);
|
||||
size_t sz = len - cksum_sz - et->confoundersize;
|
||||
char *cdata = (char *)data;
|
||||
char *tmp;
|
||||
|
||||
tmp = malloc (sz);
|
||||
if (tmp == NULL)
|
||||
return ENOMEM;
|
||||
|
||||
(*et->encrypt)(&crypto->key, data, len, FALSE, usage);
|
||||
|
||||
memcpy (tmp, cdata + cksum_sz + et->confoundersize, sz);
|
||||
|
||||
result->data = tmp;
|
||||
result->length = sz;
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
krb5_error_code
|
||||
krb5_encrypt(krb5_context context,
|
||||
krb5_crypto crypto,
|
||||
@@ -2012,6 +2392,9 @@ krb5_encrypt(krb5_context context,
|
||||
if(derived_crypto(context, crypto))
|
||||
return encrypt_internal_derived(context, crypto, usage,
|
||||
data, len, result);
|
||||
else if (special_crypto(context, crypto))
|
||||
return encrypt_internal_special (context, crypto, usage,
|
||||
data, len, result);
|
||||
else
|
||||
return encrypt_internal(context, crypto, data, len, result);
|
||||
}
|
||||
@@ -2045,6 +2428,9 @@ krb5_decrypt(krb5_context context,
|
||||
if(derived_crypto(context, crypto))
|
||||
return decrypt_internal_derived(context, crypto, usage,
|
||||
data, len, result);
|
||||
else if (special_crypto (context, crypto))
|
||||
return decrypt_internal_special(context, crypto, usage,
|
||||
data, len, result);
|
||||
else
|
||||
return decrypt_internal(context, crypto, data, len, result);
|
||||
}
|
||||
@@ -2152,7 +2538,7 @@ derive_key(krb5_context context,
|
||||
memcpy(k + i * et->blocksize,
|
||||
k + (i - 1) * et->blocksize,
|
||||
et->blocksize);
|
||||
(*et->encrypt)(key, k + i * et->blocksize, et->blocksize, 1);
|
||||
(*et->encrypt)(key, k + i * et->blocksize, et->blocksize, 1, 0);
|
||||
}
|
||||
} else {
|
||||
/* this case is probably broken, but won't be run anyway */
|
||||
@@ -2162,7 +2548,7 @@ derive_key(krb5_context context,
|
||||
if(len != 0 && c == NULL)
|
||||
return ENOMEM;
|
||||
memcpy(c, constant, len);
|
||||
(*et->encrypt)(key, c, len, 1);
|
||||
(*et->encrypt)(key, c, len, 1, 0);
|
||||
k = malloc(res_len);
|
||||
if(res_len != 0 && k == NULL)
|
||||
return ENOMEM;
|
||||
|
Reference in New Issue
Block a user