convert-from-bsd-to-posix-string-and-memory-functions-20010807
[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 <afsconfig.h>
27 #include <afs/param.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             memcpy((char *)&xor_0, (char *)ivec++, sizeof(xor_0));
92             memcpy((char *)&xor_1, (char *)ivec, 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                 memcpy((char *)&t_input[0], (char *)input, sizeof(t_input[0]));
106                 memcpy((char *)&t_input[1], (char *)(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                 memcpy((char *)&xor_0, (char *)input++, sizeof(xor_0));
139                 xor_0 ^= t_output[0];
140                 memcpy((char *)&xor_1, (char *)input++, 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                 memcpy((char *)output++, (char *)&t_output[0], sizeof(t_output[0]));
155                 memcpy((char *)output++, (char *)&t_output[1], sizeof(t_output[1]));
156             }
157             else
158 #endif
159             {
160                 *output++ = t_output[0];
161                 *output++ = t_output[1];
162             }
163
164 #ifdef DEBUG
165             if (des_debug) {
166                 des_debug_print("xor'ed",i,t_input[0],t_input[1]);
167                 des_debug_print("cipher",i,t_output[0],t_output[1]);
168             }
169 #endif
170         }
171         t_output[0] = 0;
172         t_output[1] = 0;
173         xor_0 = 0;
174         xor_1 = 0;
175         return 0;
176     }
177
178     else {
179         /* decrypt */
180 #ifdef MUSTALIGN
181         if ((afs_int32) ivec & 3) {
182             memcpy((char *)&xor_0, (char *)ivec++, sizeof(xor_0));
183             memcpy((char *)&xor_1, (char *)ivec, sizeof(xor_1));
184         }
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++, sizeof(t_input[0]));
197                 memcpy((char *)&t_input[1], (char *)input++, sizeof(t_input[1]));
198             }
199             else
200 #endif
201             {
202                 t_input[0] = *input++;
203                 t_input[1] = *input++;
204             }
205
206             /* no padding for decrypt */
207 #ifdef DEBUG
208             if (des_debug)
209                 des_debug_print("cipher",i,t_input[0],t_input[1]);
210 #else
211 #ifdef lint
212             i = i;
213 #endif
214 #endif
215             /* encrypt */
216             (void) des_ecb_encrypt(t_input,t_output,key,encrypt);
217 #ifdef DEBUG
218             if (des_debug)
219                 des_debug_print("out pre xor",i,t_output[0],t_output[1]);
220 #endif
221             /* do the xor for cbc into the output */
222             t_output[0] ^= xor_0 ;
223             t_output[1] ^= xor_1 ;
224             /* copy temp output */
225 #ifdef MUSTALIGN
226             if ((afs_int32) output & 3) {
227                 memcpy((char *)output++, (char *)&t_output[0], sizeof(t_output[0]));
228                 memcpy((char *)output++, (char *)&t_output[1], sizeof(t_output[1]));
229             }
230             else
231 #endif
232             {
233                 *output++ = t_output[0];
234                 *output++ = t_output[1];
235             }
236
237             /* save xor value for next round */
238             xor_0 = t_output[0] ^ t_input[0];
239             xor_1 = t_output[1] ^ t_input[1];
240
241 #ifdef DEBUG
242             if (des_debug)
243                 des_debug_print("clear",i,t_output[0],t_output[1]);
244 #endif
245         }
246         return 0;
247     }
248 }