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:
Assar Westerlund
2000-07-06 00:06:58 +00:00
parent fbd08fd057
commit 6c81500e59

View File

@@ -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;