convert-from-bsd-to-posix-string-and-memory-functions-20010807
[openafs.git] / src / des / cbc_encrypt.c
1 /*
2  * Copyright 1985, 1986, 1987, 1988 by the Massachusetts Institute
3  * of Technology.
4  *
5  * For copying and distribution information, please see the file
6  * <mit-cpyright.h>.
7  *
8  * These routines perform encryption and decryption using the DES
9  * private key algorithm, or else a subset of it -- fewer inner loops.
10  * (AUTH_DES_ITER defaults to 16, may be less.)
11  *
12  * Under U.S. law, this software may not be exported outside the US
13  * without license from the U.S. Commerce department.
14  *
15  * These routines form the library interface to the DES facilities.
16  *
17  * Originally written 8/85 by Steve Miller, MIT Project Athena.
18  */
19
20 #include <mit-cpyright.h>
21 #include <stdio.h>
22 #include <des.h>
23 #include <afsconfig.h>
24 #include <afs/param.h>
25
26 RCSID("$Header$");
27
28
29 #define XPRT_CBC_ENCRYPT
30
31 extern int des_debug;
32 extern int des_debug_print();
33 extern int des_ecb_encrypt();
34
35 /*
36  * This routine performs DES cipher-block-chaining operation, either
37  * encrypting from cleartext to ciphertext, if encrypt != 0 or
38  * decrypting from ciphertext to cleartext, if encrypt == 0.
39  *
40  * The key schedule is passed as an arg, as well as the cleartext or
41  * ciphertext.  The cleartext and ciphertext should be in host order.
42  *
43  * NOTE-- the output is ALWAYS an multiple of 8 bytes long.  If not
44  * enough space was provided, your program will get trashed.
45  *
46  * For encryption, the cleartext string is null padded, at the end, to
47  * an integral multiple of eight bytes.
48  *
49  * For decryption, the ciphertext will be used in integral multiples
50  * of 8 bytes, but only the first "length" bytes returned into the
51  * cleartext.
52  */
53
54 afs_int32
55 des_cbc_encrypt(in,out,length,key,iv,encrypt)
56     des_cblock *in;             /* >= length bytes of input text */
57     des_cblock *out;            /* >= length bytes of output text */
58     register afs_int32 length;  /* in bytes */
59     int encrypt;                /* 0 ==> decrypt, else encrypt */
60     des_key_schedule key;               /* precomputed key schedule */
61     des_cblock *iv;             /* 8 bytes of ivec */
62 {
63     register afs_uint32 *input = (afs_uint32 *) in;
64     register afs_uint32 *output = (afs_uint32 *) out;
65     register afs_uint32 *ivec = (afs_uint32 *) iv;
66
67     afs_uint32 i,j;
68     afs_uint32 t_input[2];
69     afs_uint32 t_output[2];
70     unsigned char *t_in_p = (unsigned char *) t_input;
71     afs_uint32 xor_0, xor_1;
72
73     if (encrypt) {
74 #ifdef MUSTALIGN
75         if ((afs_int32) ivec & 3) {
76             memcpy((char *)&t_output[0], (char *)ivec++, sizeof(t_output[0]));
77             memcpy((char *)&t_output[1], (char *)ivec, sizeof(t_output[1]));
78         }
79         else
80 #endif
81         {
82             t_output[0] = *ivec++;
83             t_output[1] = *ivec;
84         }
85
86         for (i = 0; length > 0; i++, length -= 8) {
87             /* get input */
88 #ifdef MUSTALIGN
89             if ((afs_int32) input & 3) {
90                 memcpy((char *)&t_input[0], (char *)input++, sizeof(t_input[0]));
91                 memcpy((char *)&t_input[1], (char *)input++, sizeof(t_input[1]));
92             }
93             else
94 #endif
95             {
96                 t_input[0] = *input++;
97                 t_input[1] = *input++;
98             }
99
100             /* zero pad */
101             if (length < 8)
102                 for (j = length; j <= 7; j++)
103                     *(t_in_p+j)= 0;
104
105 #ifdef DEBUG
106             if (des_debug)
107                 des_debug_print("clear",length,t_input[0],t_input[1]);
108 #endif
109             /* do the xor for cbc into the temp */
110             t_input[0] ^= t_output[0];
111             t_input[1] ^= t_output[1];
112             /* encrypt */
113             (void) des_ecb_encrypt(t_input,t_output,key,encrypt);
114             /* copy temp output and save it for cbc */
115 #ifdef MUSTALIGN
116             if ((afs_int32) output & 3) {
117                 memcpy((char *)output++, (char *)&t_output[0], sizeof(t_output[0]));
118                 memcpy((char *)output++, (char *)&t_output[1], sizeof(t_output[1]));
119             }
120             else
121 #endif
122             {
123                 *output++ = t_output[0];
124                 *output++ = t_output[1];
125             }
126
127 #ifdef DEBUG
128             if (des_debug) {
129                 des_debug_print("xor'ed",i,t_input[0],t_input[1]);
130                 des_debug_print("cipher",i,t_output[0],t_output[1]);
131             }
132 #endif
133         }
134         return 0;
135     }
136
137     else {
138         /* decrypt */
139 #ifdef MUSTALIGN
140         if ((afs_int32) ivec & 3) {
141             memcpy((char *)&xor_0, (char *)ivec++, sizeof(xor_0));
142             memcpy((char *)&xor_1, (char *)ivec, sizeof(xor_1));
143         }
144         else
145 #endif
146         {
147             xor_0 = *ivec++;
148             xor_1 = *ivec;
149         }
150
151         for (i = 0; length > 0; i++, length -= 8) {
152             /* get input */
153 #ifdef MUSTALIGN
154             if ((afs_int32) input & 3) {
155                 memcpy((char *)&t_input[0], (char *)input++, sizeof(t_input[0]));
156                 memcpy((char *)&t_input[1], (char *)input++, sizeof(t_input[0]));
157             }
158             else
159 #endif
160             {
161                 t_input[0] = *input++;
162                 t_input[1] = *input++;
163             }
164
165             /* no padding for decrypt */
166 #ifdef DEBUG
167             if (des_debug)
168                 des_debug_print("cipher",i,t_input[0],t_input[1]);
169 #else
170 #ifdef lint
171             i = i;
172 #endif
173 #endif
174             /* encrypt */
175             (void) des_ecb_encrypt(t_input,t_output,key,encrypt);
176 #ifdef DEBUG
177             if (des_debug)
178                 des_debug_print("out pre xor",i,t_output[0],t_output[1]);
179 #endif
180             /* do the xor for cbc into the output */
181             t_output[0] ^= xor_0;
182             t_output[1] ^= xor_1;
183             /* copy temp output */
184 #ifdef MUSTALIGN
185             if ((afs_int32) output & 3) {
186                 memcpy((char *)output++, (char *)&t_output[0], sizeof(t_output[0]));
187                 memcpy((char *)output++, (char *)&t_output[1], sizeof(t_output[1]));
188             }
189             else
190 #endif
191             {
192                 *output++ = t_output[0];
193                 *output++ = t_output[1];
194             }
195
196             /* save xor value for next round */
197             xor_0 = t_input[0];
198             xor_1 = t_input[1];
199 #ifdef DEBUG
200             if (des_debug)
201                 des_debug_print("clear",i,t_output[0],t_output[1]);
202 #endif
203         }
204         return 0;
205     }
206 }