854d3b0afd239c6bac5463a386013bee39b65cc7
[openafs.git] / src / des / pcbc_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  * The key schedule is passed as an arg, as well as the cleartext or
16  * ciphertext.   The cleartext and ciphertext should be in host order.
17  *
18  * These routines form the library interface to the des facilities.
19  *
20  * spm 8/85     MIT project athena
21  */
22
23 #include <mit-cpyright.h>
24 #ifndef KERNEL
25 #include <stdio.h>
26 #endif
27 #include <des.h>
28 #include <afsconfig.h>
29 #include <afs/param.h>
30 #include "des_prototypes.h"
31
32 RCSID
33     ("$Header$");
34
35 #include "des_internal.h"
36
37 #define XPRT_PCBC_ENCRYPT
38
39 /*
40  * pcbc_encrypt is an "error propagation chaining" encrypt operation
41  * for DES, similar to CBC, but that, on encryption, "xor"s the
42  * plaintext of block N with the ciphertext resulting from block N,
43  * then "xor"s that result with the plaintext of block N+1 prior to
44  * encrypting block N+1. (decryption the appropriate inverse.  This
45  * "pcbc" mode propagates a single bit error anywhere in either the
46  * cleartext or ciphertext chain all the way through to the end. In
47  * contrast, CBC mode limits a single bit error in the ciphertext to
48  * affect only the current (8byte) block and the subsequent block.
49  *
50  * performs pcbc error-propagation chaining operation by xor-ing block
51  * N+1 with both the plaintext (block N) and the ciphertext from block
52  * N.  Either encrypts from cleartext to ciphertext, if encrypt != 0
53  * or decrypts from ciphertext to cleartext, if encrypt == 0
54  *
55  * NOTE-- the output is ALWAYS an multiple of 8 bytes long.  If not
56  * enough space was provided, your program will get trashed.
57  *
58  * For encryption, the cleartext string is null padded, at the end, to
59  * an integral multiple of eight bytes.
60  *
61  * For decryption, the ciphertext will be used in integral multiples
62  * of 8 bytes, but only the first "length" bytes returned into the
63  * cleartext.
64  *
65  * This is NOT a standard mode of operation.
66  *
67  */
68 /*
69     des_cblock *in;             * >= length bytes of input text *
70     des_cblock *out;            * >= length bytes of output text *
71     register afs_int32 length;  * in bytes *
72     int encrypt;                * 0 ==> decrypt, else encrypt *
73     des_key_schedule key;       * precomputed key schedule *
74     des_cblock *iv;             * 8 bytes of ivec *
75 */
76 afs_int32
77 des_pcbc_encrypt(des_cblock * in, des_cblock * out, register afs_int32 length,
78                  des_key_schedule key, des_cblock * iv, int encrypt)
79 {
80     register afs_uint32 *input = (afs_uint32 *) in;
81     register afs_uint32 *output = (afs_uint32 *) out;
82     register afs_uint32 *ivec = (afs_uint32 *) iv;
83
84     afs_uint32 i, j;
85     afs_uint32 t_input[2];
86     afs_uint32 t_output[2];
87     unsigned char *t_in_p = (unsigned char *)t_input;
88     afs_uint32 xor_0, xor_1;
89
90     if (encrypt) {
91 #ifdef MUSTALIGN
92         if ((afs_int32) ivec & 3) {
93             memcpy((char *)&xor_0, (char *)ivec++, sizeof(xor_0));
94             memcpy((char *)&xor_1, (char *)ivec, sizeof(xor_1));
95         } else
96 #endif
97         {
98             xor_0 = *ivec++;
99             xor_1 = *ivec;
100         }
101
102         for (i = 0; length > 0; i++, length -= 8) {
103             /* get input */
104 #ifdef MUSTALIGN
105             if ((afs_int32) input & 3) {
106                 memcpy((char *)&t_input[0], (char *)input,
107                        sizeof(t_input[0]));
108                 memcpy((char *)&t_input[1], (char *)(input + 1),
109                        sizeof(t_input[1]));
110             } else
111 #endif
112             {
113                 t_input[0] = *input;
114                 t_input[1] = *(input + 1);
115             }
116
117             /* zero pad */
118             if (length < 8) {
119                 for (j = length; j <= 7; j++)
120                     *(t_in_p + j) = 0;
121             }
122 #ifdef DEBUG
123             if (des_debug)
124                 des_debug_print("clear", length, t_input[0], t_input[1]);
125 #endif
126             /* do the xor for cbc into the temp */
127             t_input[0] ^= xor_0;
128             t_input[1] ^= xor_1;
129             /* encrypt */
130             (void)des_ecb_encrypt(t_input, t_output, key, encrypt);
131
132             /*
133              * We want to XOR with both the plaintext and ciphertext
134              * of the previous block, before we write the output, in
135              * case both input and output are the same space.
136              */
137 #ifdef MUSTALIGN
138             if ((afs_int32) input & 3) {
139                 memcpy((char *)&xor_0, (char *)input++, sizeof(xor_0));
140                 xor_0 ^= t_output[0];
141                 memcpy((char *)&xor_1, (char *)input++, sizeof(xor_1));
142                 xor_1 ^= t_output[1];
143             } else
144 #endif
145             {
146                 xor_0 = *input++ ^ t_output[0];
147                 xor_1 = *input++ ^ t_output[1];
148             }
149
150
151             /* copy temp output and save it for cbc */
152 #ifdef MUSTALIGN
153             if ((afs_int32) output & 3) {
154                 memcpy((char *)output++, (char *)&t_output[0],
155                        sizeof(t_output[0]));
156                 memcpy((char *)output++, (char *)&t_output[1],
157                        sizeof(t_output[1]));
158             } else
159 #endif
160             {
161                 *output++ = t_output[0];
162                 *output++ = t_output[1];
163             }
164
165 #ifdef DEBUG
166             if (des_debug) {
167                 des_debug_print("xor'ed", i, t_input[0], t_input[1]);
168                 des_debug_print("cipher", i, t_output[0], t_output[1]);
169             }
170 #endif
171         }
172         t_output[0] = 0;
173         t_output[1] = 0;
174         xor_0 = 0;
175         xor_1 = 0;
176         return 0;
177     }
178
179     else {
180         /* decrypt */
181 #ifdef MUSTALIGN
182         if ((afs_int32) ivec & 3) {
183             memcpy((char *)&xor_0, (char *)ivec++, sizeof(xor_0));
184             memcpy((char *)&xor_1, (char *)ivec, sizeof(xor_1));
185         } else
186 #endif
187         {
188             xor_0 = *ivec++;
189             xor_1 = *ivec;
190         }
191
192         for (i = 0; length > 0; i++, length -= 8) {
193             /* get input */
194 #ifdef MUSTALIGN
195             if ((afs_int32) input & 3) {
196                 memcpy((char *)&t_input[0], (char *)input++,
197                        sizeof(t_input[0]));
198                 memcpy((char *)&t_input[1], (char *)input++,
199                        sizeof(t_input[1]));
200             } else
201 #endif
202             {
203                 t_input[0] = *input++;
204                 t_input[1] = *input++;
205             }
206
207             /* no padding for decrypt */
208 #ifdef DEBUG
209             if (des_debug)
210                 des_debug_print("cipher", i, t_input[0], t_input[1]);
211 #else
212 #ifdef lint
213             i = i;
214 #endif
215 #endif
216             /* encrypt */
217             (void)des_ecb_encrypt(t_input, t_output, key, encrypt);
218 #ifdef DEBUG
219             if (des_debug)
220                 des_debug_print("out pre xor", i, t_output[0], t_output[1]);
221 #endif
222             /* do the xor for cbc into the output */
223             t_output[0] ^= xor_0;
224             t_output[1] ^= xor_1;
225             /* copy temp output */
226 #ifdef MUSTALIGN
227             if ((afs_int32) output & 3) {
228                 memcpy((char *)output++, (char *)&t_output[0],
229                        sizeof(t_output[0]));
230                 memcpy((char *)output++, (char *)&t_output[1],
231                        sizeof(t_output[1]));
232             } else
233 #endif
234             {
235                 *output++ = t_output[0];
236                 *output++ = t_output[1];
237             }
238
239             /* save xor value for next round */
240             xor_0 = t_output[0] ^ t_input[0];
241             xor_1 = t_output[1] ^ t_input[1];
242
243 #ifdef DEBUG
244             if (des_debug)
245                 des_debug_print("clear", i, t_output[0], t_output[1]);
246 #endif
247         }
248         return 0;
249     }
250 }