afsconfig-and-rcsid-all-around-20010705
[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 <afsconfig.h>
28
29 RCSID("$Header$");
30
31 #include "des_internal.h"
32
33 #define XPRT_PCBC_ENCRYPT
34
35 extern int des_debug;
36 extern int des_debug_print();
37 extern int des_ecb_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 afs_int32
70 des_pcbc_encrypt(in,out,length,key,iv,encrypt)
71     des_cblock *in;             /* >= length bytes of inputtext */
72     des_cblock *out;            /* >= length bytes of outputtext */
73     register afs_int32 length;  /* in bytes */
74     int encrypt;                /* 0 ==> decrypt, else encrypt */
75     des_key_schedule key;               /* precomputed key schedule */
76     des_cblock *iv;             /* 8 bytes of ivec */
77 {
78     register afs_uint32 *input = (afs_uint32 *) in;
79     register afs_uint32 *output = (afs_uint32 *) out;
80     register afs_uint32 *ivec = (afs_uint32 *) iv;
81
82     afs_uint32 i,j;
83     afs_uint32 t_input[2];
84     afs_uint32 t_output[2];
85     unsigned char *t_in_p = (unsigned char *) t_input;
86     afs_uint32 xor_0, xor_1;
87
88     if (encrypt) {
89 #ifdef MUSTALIGN
90         if ((afs_int32) ivec & 3) {
91             bcopy((char *)ivec++,(char *)&xor_0,sizeof(xor_0));
92             bcopy((char *)ivec,(char *)&xor_1,sizeof(xor_1));
93         }
94         else
95 #endif
96         {
97             xor_0 = *ivec++;
98             xor_1 = *ivec;
99         }
100
101         for (i = 0; length > 0; i++, length -= 8) {
102             /* get input */
103 #ifdef MUSTALIGN
104             if ((afs_int32) input & 3) {
105                 bcopy((char *)input,(char *)&t_input[0],sizeof(t_input[0]));
106                 bcopy((char *)(input+1),(char *)&t_input[1],sizeof(t_input[1]));
107             }
108             else
109 #endif
110             {
111                 t_input[0] = *input;
112                 t_input[1] = *(input+1);
113             }
114
115             /* zero pad */
116             if (length < 8) {
117                 for (j = length; j <= 7; j++)
118                     *(t_in_p+j)= 0;
119             }
120
121 #ifdef DEBUG
122             if (des_debug)
123                 des_debug_print("clear",length,t_input[0],t_input[1]);
124 #endif
125             /* do the xor for cbc into the temp */
126             t_input[0] ^= xor_0 ;
127             t_input[1] ^= xor_1 ;
128             /* encrypt */
129             (void) des_ecb_encrypt(t_input,t_output,key,encrypt);
130
131             /*
132              * We want to XOR with both the plaintext and ciphertext
133              * of the previous block, before we write the output, in
134              * case both input and output are the same space.
135              */
136 #ifdef MUSTALIGN
137             if ((afs_int32) input & 3) {
138                 bcopy((char *)input++,(char *)&xor_0,sizeof(xor_0));
139                 xor_0 ^= t_output[0];
140                 bcopy((char *)input++,(char *)&xor_1,sizeof(xor_1));
141                 xor_1 ^= t_output[1];
142             }
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                 bcopy((char *)&t_output[0],(char *)output++,
155                       sizeof(t_output[0]));
156                 bcopy((char *)&t_output[1],(char *)output++,
157                       sizeof(t_output[1]));
158             }
159             else
160 #endif
161             {
162                 *output++ = t_output[0];
163                 *output++ = t_output[1];
164             }
165
166 #ifdef DEBUG
167             if (des_debug) {
168                 des_debug_print("xor'ed",i,t_input[0],t_input[1]);
169                 des_debug_print("cipher",i,t_output[0],t_output[1]);
170             }
171 #endif
172         }
173         t_output[0] = 0;
174         t_output[1] = 0;
175         xor_0 = 0;
176         xor_1 = 0;
177         return 0;
178     }
179
180     else {
181         /* decrypt */
182 #ifdef MUSTALIGN
183         if ((afs_int32) ivec & 3) {
184             bcopy((char *)ivec++,(char *)&xor_0,sizeof(xor_0));
185             bcopy((char *)ivec,(char *)&xor_1,sizeof(xor_1));
186         }
187         else
188 #endif
189         {
190             xor_0 = *ivec++;
191             xor_1 = *ivec;
192         }
193
194         for (i = 0; length > 0; i++, length -= 8) {
195             /* get input */
196 #ifdef MUSTALIGN
197             if ((afs_int32) input & 3) {
198                 bcopy((char *)input++,(char *)&t_input[0],sizeof(t_input[0]));
199                 bcopy((char *)input++,(char *)&t_input[1],sizeof(t_input[1]));
200             }
201             else
202 #endif
203             {
204                 t_input[0] = *input++;
205                 t_input[1] = *input++;
206             }
207
208             /* no padding for decrypt */
209 #ifdef DEBUG
210             if (des_debug)
211                 des_debug_print("cipher",i,t_input[0],t_input[1]);
212 #else
213 #ifdef lint
214             i = i;
215 #endif
216 #endif
217             /* encrypt */
218             (void) des_ecb_encrypt(t_input,t_output,key,encrypt);
219 #ifdef DEBUG
220             if (des_debug)
221                 des_debug_print("out pre xor",i,t_output[0],t_output[1]);
222 #endif
223             /* do the xor for cbc into the output */
224             t_output[0] ^= xor_0 ;
225             t_output[1] ^= xor_1 ;
226             /* copy temp output */
227 #ifdef MUSTALIGN
228             if ((afs_int32) output & 3) {
229                 bcopy((char *)&t_output[0],(char *)output++,
230                       sizeof(t_output[0]));
231                 bcopy((char *)&t_output[1],(char *)output++,
232                       sizeof(t_output[1]));
233             }
234             else
235 #endif
236             {
237                 *output++ = t_output[0];
238                 *output++ = t_output[1];
239             }
240
241             /* save xor value for next round */
242             xor_0 = t_output[0] ^ t_input[0];
243             xor_1 = t_output[1] ^ t_input[1];
244
245 #ifdef DEBUG
246             if (des_debug)
247                 des_debug_print("clear",i,t_output[0],t_output[1]);
248 #endif
249         }
250         return 0;
251     }
252 }