2 * Copyright (c) 1990 Dennis Ferguson. All rights reserved.
4 * Commercial use is permitted only if products which are derived from
5 * or include this software are made available for purchase and/or use
6 * in Canada. Otherwise, redistribution and use in source and binary
11 * des_cbc_cksum.c - compute an 8 byte checksum using DES in CBC mode
17 * This routine performs DES cipher-block-chaining checksum operation,
18 * a.k.a. Message Authentication Code. It ALWAYS encrypts from input
19 * to a single 64 bit output MAC checksum.
21 * The key schedule is passed as an arg, as well as the cleartext or
22 * ciphertext. The cleartext and ciphertext should be in host order.
24 * NOTE-- the output is ALWAYS 8 bytes long. If not enough space was
25 * provided, your program will get trashed.
27 * The input is null padded, at the end (highest addr), to an integral
28 * multiple of eight bytes.
32 mit_des_cbc_cksum(in, out, length, schedule, ivec)
36 des_key_schedule schedule;
39 register unsigned KRB_INT32 left, right;
40 register unsigned KRB_INT32 temp;
41 register unsigned KRB_INT32 *kp;
42 register unsigned char *ip;
43 register KRB_INT32 len;
46 * Initialize left and right with the contents of the initial
49 ip = (unsigned char *)ivec;
50 GET_HALF_BLOCK(left, ip);
51 GET_HALF_BLOCK(right, ip);
54 * Suitably initialized, now work the length down 8 bytes
57 ip = (unsigned char *)in;
61 * Get more input, xor it in. If the length is
62 * greater than or equal to 8 this is straight
63 * forward. Otherwise we have to fart around.
66 left ^= ((*ip++) & FF_UINT32) << 24;
67 left ^= ((*ip++) & FF_UINT32) << 16;
68 left ^= ((*ip++) & FF_UINT32) << 8;
69 left ^= (*ip++) & FF_UINT32;
70 right ^= ((*ip++) & FF_UINT32) << 24;
71 right ^= ((*ip++) & FF_UINT32) << 16;
72 right ^= ((*ip++) & FF_UINT32) << 8;
73 right ^= (*ip++) & FF_UINT32;
77 * Oh, shoot. We need to pad the
78 * end with zeroes. Work backwards
84 right ^= (*(--ip) & FF_UINT32) << 8;
86 right ^= (*(--ip) & FF_UINT32) << 16;
88 right ^= (*(--ip) & FF_UINT32) << 24;
90 left ^= *(--ip) & FF_UINT32;
92 left ^= (*(--ip) & FF_UINT32) << 8;
94 left ^= (*(--ip) & FF_UINT32) << 16;
96 left ^= (*(--ip) & FF_UINT32) << 24;
103 * Encrypt what we have
105 kp = (unsigned KRB_INT32 *)schedule;
106 DES_DO_ENCRYPT(left, right, temp, kp);
110 * Done. Left and right have the checksum. Put it into
113 ip = (unsigned char *)out;
114 PUT_HALF_BLOCK(left, ip);
115 PUT_HALF_BLOCK(right, ip);
118 * Return right. I'll bet the MIT code returns this
119 * inconsistantly (with the low order byte of the checksum
120 * not always in the low order byte of the KRB_INT32). We won't.