#include "des_int.h"
#include "f_tables.h"
#undef mit_des3_cbc_encrypt
int
mit_des3_cbc_encrypt(const mit_des_cblock *in, mit_des_cblock *out,
unsigned long length, const mit_des_key_schedule ks1,
const mit_des_key_schedule ks2,
const mit_des_key_schedule ks3,
const mit_des_cblock ivec, int enc)
{
if (enc)
krb5int_des3_cbc_encrypt(in, out, length, ks1, ks2, ks3, ivec);
else
krb5int_des3_cbc_decrypt(in, out, length, ks1, ks2, ks3, ivec);
return 0;
}
void
krb5int_des3_cbc_encrypt(const mit_des_cblock *in,
mit_des_cblock *out,
unsigned long length,
const mit_des_key_schedule ks1,
const mit_des_key_schedule ks2,
const mit_des_key_schedule ks3,
const mit_des_cblock ivec)
{
unsigned DES_INT32 left, right;
const unsigned DES_INT32 *kp1, *kp2, *kp3;
const unsigned char *ip;
unsigned char *op;
kp1 = (const unsigned DES_INT32 *)ks1;
kp2 = (const unsigned DES_INT32 *)ks2;
kp3 = (const unsigned DES_INT32 *)ks3;
ip = ivec;
GET_HALF_BLOCK(left, ip);
GET_HALF_BLOCK(right, ip);
ip = *in;
op = *out;
while (length > 0) {
if (length >= 8) {
left ^= ((*ip++) & FF_UINT32) << 24;
left ^= ((*ip++) & FF_UINT32) << 16;
left ^= ((*ip++) & FF_UINT32) << 8;
left ^= (*ip++) & FF_UINT32;
right ^= ((*ip++) & FF_UINT32) << 24;
right ^= ((*ip++) & FF_UINT32) << 16;
right ^= ((*ip++) & FF_UINT32) << 8;
right ^= (*ip++) & FF_UINT32;
length -= 8;
} else {
ip += (int) length;
switch(length) {
case 7: right ^= (*(--ip) & FF_UINT32) << 8;
case 6: right ^= (*(--ip) & FF_UINT32) << 16;
case 5: right ^= (*(--ip) & FF_UINT32) << 24;
case 4: left ^= *(--ip) & FF_UINT32;
case 3: left ^= (*(--ip) & FF_UINT32) << 8;
case 2: left ^= (*(--ip) & FF_UINT32) << 16;
case 1: left ^= (*(--ip) & FF_UINT32) << 24;
}
length = 0;
}
DES_DO_ENCRYPT(left, right, kp1);
DES_DO_DECRYPT(left, right, kp2);
DES_DO_ENCRYPT(left, right, kp3);
PUT_HALF_BLOCK(left, op);
PUT_HALF_BLOCK(right, op);
}
}
void
krb5int_des3_cbc_decrypt(const mit_des_cblock *in,
mit_des_cblock *out,
unsigned long length,
const mit_des_key_schedule ks1,
const mit_des_key_schedule ks2,
const mit_des_key_schedule ks3,
const mit_des_cblock ivec)
{
unsigned DES_INT32 left, right;
const unsigned DES_INT32 *kp1, *kp2, *kp3;
const unsigned char *ip;
unsigned char *op;
unsigned DES_INT32 ocipherl, ocipherr;
unsigned DES_INT32 cipherl, cipherr;
kp1 = (const unsigned DES_INT32 *)ks1;
kp2 = (const unsigned DES_INT32 *)ks2;
kp3 = (const unsigned DES_INT32 *)ks3;
if (length <= 0)
return;
ip = ivec;
GET_HALF_BLOCK(ocipherl, ip);
GET_HALF_BLOCK(ocipherr, ip);
ip = *in;
op = *out;
for (;;) {
GET_HALF_BLOCK(left, ip);
GET_HALF_BLOCK(right, ip);
cipherl = left;
cipherr = right;
DES_DO_DECRYPT(left, right, kp3);
DES_DO_ENCRYPT(left, right, kp2);
DES_DO_DECRYPT(left, right, kp1);
left ^= ocipherl;
right ^= ocipherr;
if (length > 8) {
length -= 8;
PUT_HALF_BLOCK(left, op);
PUT_HALF_BLOCK(right, op);
ocipherl = cipherl;
ocipherr = cipherr;
} else {
op += (int) length;
switch(length) {
case 8: *(--op) = (unsigned char) (right & 0xff);
case 7: *(--op) = (unsigned char) ((right >> 8) & 0xff);
case 6: *(--op) = (unsigned char) ((right >> 16) & 0xff);
case 5: *(--op) = (unsigned char) ((right >> 24) & 0xff);
case 4: *(--op) = (unsigned char) (left & 0xff);
case 3: *(--op) = (unsigned char) ((left >> 8) & 0xff);
case 2: *(--op) = (unsigned char) ((left >> 16) & 0xff);
case 1: *(--op) = (unsigned char) ((left >> 24) & 0xff);
}
break;
}
}
}