diff --git a/lib/krb5/crypto.c b/lib/krb5/crypto.c index 09fc2f034..946cc8dd7 100644 --- a/lib/krb5/crypto.c +++ b/lib/krb5/crypto.c @@ -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;