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