Windows global stuff:
[krb5.git] / src / lib / crypto / des / f_cksum.c
1 /*
2  * Copyright (c) 1990 Dennis Ferguson.  All rights reserved.
3  *
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
7  * forms are permitted.
8  */
9
10 /*
11  * des_cbc_cksum.c - compute an 8 byte checksum using DES in CBC mode
12  */
13 #include "des.h"
14 #include "f_tables.h"
15
16 /*
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.
20  *
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.
23  *
24  * NOTE-- the output is ALWAYS 8 bytes long.  If not enough space was
25  * provided, your program will get trashed.
26  *
27  * The input is null padded, at the end (highest addr), to an integral
28  * multiple of eight bytes.
29  */
30
31 unsigned long
32 mit_des_cbc_cksum(in, out, length, schedule, ivec)
33         des_cblock *in;
34         des_cblock *out;
35         long length;
36         des_key_schedule schedule;
37         des_cblock ivec;
38 {
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;
44
45         /*
46          * Initialize left and right with the contents of the initial
47          * vector.
48          */
49         ip = (unsigned char *)ivec;
50         GET_HALF_BLOCK(left, ip);
51         GET_HALF_BLOCK(right, ip);
52
53         /*
54          * Suitably initialized, now work the length down 8 bytes
55          * at a time.
56          */
57         ip = (unsigned char *)in;
58         len = length;
59         while (len > 0) {
60                 /*
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.
64                  */
65                 if (len >= 8) {
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;
74                         len -= 8;
75                 } else {
76                         /*
77                          * Oh, shoot.  We need to pad the
78                          * end with zeroes.  Work backwards
79                          * to do this.
80                          */
81                         ip += (int) len;
82                         switch(len) {
83                         case 7:
84                                 right ^= (*(--ip) & FF_UINT32) <<  8;
85                         case 6:
86                                 right ^= (*(--ip) & FF_UINT32) << 16;
87                         case 5:
88                                 right ^= (*(--ip) & FF_UINT32) << 24;
89                         case 4:
90                                 left  ^=  *(--ip) & FF_UINT32;
91                         case 3:
92                                 left  ^= (*(--ip) & FF_UINT32) <<  8;
93                         case 2:
94                                 left  ^= (*(--ip) & FF_UINT32) << 16;
95                         case 1:
96                                 left  ^= (*(--ip) & FF_UINT32) << 24;
97                                 break;
98                         }
99                         len = 0;
100                 }
101
102                 /*
103                  * Encrypt what we have
104                  */
105                 kp = (unsigned KRB_INT32 *)schedule;
106                 DES_DO_ENCRYPT(left, right, temp, kp);
107         }
108
109         /*
110          * Done.  Left and right have the checksum.  Put it into
111          * the output.
112          */
113         ip = (unsigned char *)out;
114         PUT_HALF_BLOCK(left, ip);
115         PUT_HALF_BLOCK(right, ip);
116
117         /*
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.
121          */
122         return right;
123 }