2 * Copyright (c) 1990 Dennis Ferguson. All rights reserved.
4 * Commercial use is permitted only if products which are derived from
5 * or include this software are made available for purchase and/or use
6 * in Canada. Otherwise, redistribution and use in source and binary
11 * des_pcbc_encrypt.c - encrypt a string of characters in error propagation mode
17 * des_pcbc_encrypt - {en,de}crypt a stream in PCBC mode
20 mit_des_pcbc_encrypt(in, out, length, schedule, ivec, encrypt)
24 des_key_schedule schedule;
28 register unsigned KRB_INT32 left, right;
29 register unsigned KRB_INT32 temp;
30 register unsigned KRB_INT32 *kp;
31 register unsigned char *ip, *op;
34 * Copy the key pointer, just once
36 kp = (unsigned KRB_INT32 *)schedule;
39 * Deal with encryption and decryption separately.
42 register unsigned KRB_INT32 plainl;
43 register unsigned KRB_INT32 plainr;
46 * Initialize left and right with the contents of the initial
49 ip = (unsigned char *)ivec;
50 GET_HALF_BLOCK(left, ip);
51 GET_HALF_BLOCK(right, ip);
54 * Suitably initialized, now work the length down 8 bytes
57 ip = (unsigned char *)in;
58 op = (unsigned char *)out;
61 * Get block of input. If the length is
62 * greater than 8 this is straight
63 * forward. Otherwise we have to fart around.
66 GET_HALF_BLOCK(plainl, ip);
67 GET_HALF_BLOCK(plainr, ip);
73 * Oh, shoot. We need to pad the
74 * end with zeroes. Work backwards
75 * to do this. We know this is the
76 * last block, though, so we don't have
77 * to save the plain text.
82 right ^= *(--ip) & FF_UINT32;
84 right ^= (*(--ip) & FF_UINT32) << 8;
86 right ^= (*(--ip) & FF_UINT32) << 16;
88 right ^= (*(--ip) & FF_UINT32) << 24;
90 left ^= *(--ip) & FF_UINT32;
92 left ^= (*(--ip) & FF_UINT32) << 8;
94 left ^= (*(--ip) & FF_UINT32) << 16;
96 left ^= (*(--ip) & FF_UINT32) << 24;
103 * Encrypt what we have
105 DES_DO_ENCRYPT(left, right, temp, kp);
108 * Copy the results out
110 PUT_HALF_BLOCK(left, op);
111 PUT_HALF_BLOCK(right, op);
114 * Xor with the old plain text
121 * Decrypting is harder than encrypting because of
122 * the necessity of remembering a lot more things.
123 * Should think about this a little more...
125 unsigned KRB_INT32 ocipherl, ocipherr;
126 unsigned KRB_INT32 cipherl, cipherr;
132 * Prime the old cipher with ivec.
134 ip = (unsigned char *)ivec;
135 GET_HALF_BLOCK(ocipherl, ip);
136 GET_HALF_BLOCK(ocipherr, ip);
139 * Now do this in earnest until we run out of length.
141 ip = (unsigned char *)in;
142 op = (unsigned char *)out;
143 for (;;) { /* check done inside loop */
145 * Read a block from the input into left and
146 * right. Save this cipher block for later.
148 GET_HALF_BLOCK(left, ip);
149 GET_HALF_BLOCK(right, ip);
156 DES_DO_DECRYPT(left, right, temp, kp);
159 * Xor with the old cipher to get plain
160 * text. Output 8 or less bytes of this.
166 PUT_HALF_BLOCK(left, op);
167 PUT_HALF_BLOCK(right, op);
169 * Save current cipher block here
171 ocipherl = cipherl ^ left;
172 ocipherr = cipherr ^ right;
175 * Trouble here. Start at end of output,
181 *(--op) = (unsigned char) (right & 0xff);
183 *(--op) = (unsigned char) ((right >> 8) & 0xff);
185 *(--op) = (unsigned char) ((right >> 16) & 0xff);
187 *(--op) = (unsigned char) ((right >> 24) & 0xff);
189 *(--op) = (unsigned char) (left & 0xff);
191 *(--op) = (unsigned char) ((left >> 8) & 0xff);
193 *(--op) = (unsigned char) ((left >> 16) & 0xff);
195 *(--op) = (unsigned char) ((left >> 24) & 0xff);
198 break; /* we're done */
204 * Done, return nothing.