cbc.c revision 1.3 1 /* cbc.c: This file contains the encryption routines for the ed line editor */
2 /*-
3 * Copyright (c) 1991 The Regents of the University of California.
4 * All rights reserved.
5 *
6 * This code is derived from software contributed to Berkeley by
7 * Matt Bishop of Dartmouth College.
8 *
9 * The United States Government has rights in this work pursuant
10 * to contract no. NAG 2-680 between the National Aeronautics and
11 * Space Administration and Dartmouth College.
12 *
13 * Redistribution and use in source and binary forms, with or without
14 * modification, are permitted provided that the following conditions
15 * are met:
16 * 1. Redistributions of source code must retain the above copyright
17 * notice, this list of conditions and the following disclaimer.
18 * 2. Redistributions in binary form must reproduce the above copyright
19 * notice, this list of conditions and the following disclaimer in the
20 * documentation and/or other materials provided with the distribution.
21 * 3. All advertising materials mentioning features or use of this software
22 * must display the following acknowledgement:
23 * This product includes software developed by the University of
24 * California, Berkeley and its contributors.
25 * 4. Neither the name of the University nor the names of its contributors
26 * may be used to endorse or promote products derived from this software
27 * without specific prior written permission.
28 *
29 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
30 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
31 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
32 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
33 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
34 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
35 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
36 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
37 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
38 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
39 * SUCH DAMAGE.
40 */
41
42 #ifndef lint
43 static char sccsid[] = "@(#)cbc.c 5.5 (Berkeley) 6/27/91";
44 #endif /* not lint */
45
46 /* Author: Matt Bishop
47 * Department of Mathematics and Computer Science
48 * Dartmouth College
49 * Hanover, NH 03755
50 * Email: Matt.Bishop (at) dartmouth.edu
51 * ...!decvax!dartvax!Matt.Bishop
52 *
53 * See Technical Report PCS-TR91-158, Department of Mathematics and Computer
54 * Science, Dartmouth College, for a detailed description of the implemen-
55 * tation and differences between it and Sun's. The DES is described in
56 * FIPS PUB 46, and the modes in FIPS PUB 81 (see either the manual page
57 * or the technical report for a complete reference).
58 */
59
60 #ifdef DES
61 #include <errno.h>
62 #include <pwd.h>
63 #include <unistd.h>
64 #include <stdio.h>
65 #include <ctype.h>
66 #include <stdlib.h>
67 #include <string.h>
68 #include <sys/types.h>
69
70 #include "ed.h"
71
72 /*
73 * Define a divisor for rand() that yields a uniform distribution in the
74 * range 0-255.
75 */
76 #define RAND_DIV (((unsigned) RAND_MAX + 1) >> 8)
77
78 /*
79 * BSD and System V systems offer special library calls that do
80 * block moves and fills, so if possible we take advantage of them
81 */
82 #define MEMCPY(dest,src,len) bcopy((src),(dest),(len))
83 #define MEMZERO(dest,len) bzero((dest),(len))
84
85 /* Hide the calls to the primitive encryption routines. */
86 #define DES_KEY(buf) \
87 if (des_setkey(buf)) \
88 err("des_setkey");
89 #define DES_XFORM(buf) \
90 if (des_cipher(buf, buf, 0L, (inverse ? -1 : 1))) \
91 err("des_cipher");
92
93 /*
94 * read/write - no error checking
95 */
96 #define READ(buf, n, fp) fread(buf, sizeof(char), n, fp)
97 #define WRITE(buf, n, fp) fwrite(buf, sizeof(char), n, fp)
98
99 /*
100 * some things to make references easier
101 */
102 typedef char Desbuf[8];
103 #define CHAR(x,i) (x[i])
104 #define UCHAR(x,i) (x[i])
105 #define BUFFER(x) (x)
106 #define UBUFFER(x) (x)
107
108 /*
109 * global variables and related macros
110 */
111
112 enum { /* encrypt, decrypt, authenticate */
113 MODE_ENCRYPT, MODE_DECRYPT, MODE_AUTHENTICATE
114 } mode = MODE_ENCRYPT;
115
116 Desbuf ivec; /* initialization vector */
117 Desbuf pvec; /* padding vector */
118 char bits[] = { /* used to extract bits from a char */
119 '\200', '\100', '\040', '\020', '\010', '\004', '\002', '\001'
120 };
121 int pflag; /* 1 to preserve parity bits */
122
123 /*
124 * initialize cbc
125 */
126 void
127 cbcinit()
128 {
129 int i;
130
131 /* initialize the initialization vctor */
132 MEMZERO(ivec, 8);
133
134 /* intialize the padding vector */
135 srand((unsigned) time((time_t *) 0));
136 for (i = 0; i < 8; i++)
137 CHAR(pvec, i) = (char) (rand()/RAND_DIV);
138 }
139
140 /*
141 * get keyword from tty or stdin
142 */
143 getkey()
144 {
145 register char *p; /* used to obtain the key */
146 Desbuf msgbuf; /* I/O buffer */
147
148 /*
149 * get the key
150 */
151 if (*(p = getpass("Enter key: "))) {
152
153 /*
154 * copy it, nul-padded, into the key area
155 */
156 cvtkey(BUFFER(msgbuf), p);
157 MEMZERO(p, _PASSWORD_LEN);
158 makekey(msgbuf);
159 MEMZERO(msgbuf, sizeof msgbuf);
160 return 1;
161 }
162 return 0;
163 }
164
165
166 extern char errmsg[];
167
168 /*
169 * print a warning message and, possibly, terminate
170 */
171 err(s)
172 char *s; /* the message */
173 {
174 (void)sprintf(errmsg, "%s", s ? s : strerror(errno));
175 }
176
177 /*
178 * map a hex character to an integer
179 */
180 tobinhex(c, radix)
181 int c; /* char to be converted */
182 int radix; /* base (2 to 16) */
183 {
184 switch(c) {
185 case '0': return(0x0);
186 case '1': return(0x1);
187 case '2': return(radix > 2 ? 0x2 : -1);
188 case '3': return(radix > 3 ? 0x3 : -1);
189 case '4': return(radix > 4 ? 0x4 : -1);
190 case '5': return(radix > 5 ? 0x5 : -1);
191 case '6': return(radix > 6 ? 0x6 : -1);
192 case '7': return(radix > 7 ? 0x7 : -1);
193 case '8': return(radix > 8 ? 0x8 : -1);
194 case '9': return(radix > 9 ? 0x9 : -1);
195 case 'A': case 'a': return(radix > 10 ? 0xa : -1);
196 case 'B': case 'b': return(radix > 11 ? 0xb : -1);
197 case 'C': case 'c': return(radix > 12 ? 0xc : -1);
198 case 'D': case 'd': return(radix > 13 ? 0xd : -1);
199 case 'E': case 'e': return(radix > 14 ? 0xe : -1);
200 case 'F': case 'f': return(radix > 15 ? 0xf : -1);
201 }
202 /*
203 * invalid character
204 */
205 return(-1);
206 }
207
208 /*
209 * convert the key to a bit pattern
210 */
211 cvtkey(obuf, ibuf)
212 char *obuf; /* bit pattern */
213 char *ibuf; /* the key itself */
214 {
215 register int i, j; /* counter in a for loop */
216 int nbuf[64]; /* used for hex/key translation */
217
218 /*
219 * leading '0x' or '0X' == hex key
220 */
221 if (ibuf[0] == '0' && (ibuf[1] == 'x' || ibuf[1] == 'X')) {
222 ibuf = &ibuf[2];
223 /*
224 * now translate it, bombing on any illegal hex digit
225 */
226 for (i = 0; ibuf[i] && i < 16; i++)
227 if ((nbuf[i] = tobinhex((int) ibuf[i], 16)) == -1)
228 err("bad hex digit in key");
229 while (i < 16)
230 nbuf[i++] = 0;
231 for (i = 0; i < 8; i++)
232 obuf[i] =
233 ((nbuf[2*i]&0xf)<<4) | (nbuf[2*i+1]&0xf);
234 /* preserve parity bits */
235 pflag = 1;
236 return;
237 }
238 /*
239 * leading '0b' or '0B' == binary key
240 */
241 if (ibuf[0] == '0' && (ibuf[1] == 'b' || ibuf[1] == 'B')) {
242 ibuf = &ibuf[2];
243 /*
244 * now translate it, bombing on any illegal binary digit
245 */
246 for (i = 0; ibuf[i] && i < 16; i++)
247 if ((nbuf[i] = tobinhex((int) ibuf[i], 2)) == -1)
248 err("bad binary digit in key");
249 while (i < 64)
250 nbuf[i++] = 0;
251 for (i = 0; i < 8; i++)
252 for (j = 0; j < 8; j++)
253 obuf[i] = (obuf[i]<<1)|nbuf[8*i+j];
254 /* preserve parity bits */
255 pflag = 1;
256 return;
257 }
258 /*
259 * no special leader -- ASCII
260 */
261 (void)strncpy(obuf, ibuf, 8);
262 }
263
264 /*****************
265 * DES FUNCTIONS *
266 *****************/
267 /*
268 * This sets the DES key and (if you're using the deszip version)
269 * the direction of the transformation. This uses the Sun
270 * to map the 64-bit key onto the 56 bits that the key schedule
271 * generation routines use: the old way, which just uses the user-
272 * supplied 64 bits as is, and the new way, which resets the parity
273 * bit to be the same as the low-order bit in each character. The
274 * new way generates a greater variety of key schedules, since many
275 * systems set the parity (high) bit of each character to 0, and the
276 * DES ignores the low order bit of each character.
277 */
278 makekey(buf)
279 Desbuf buf; /* key block */
280 {
281 register int i, j; /* counter in a for loop */
282 register int par; /* parity counter */
283
284 /*
285 * if the parity is not preserved, flip it
286 */
287 if (!pflag) {
288 for (i = 0; i < 8; i++) {
289 par = 0;
290 for (j = 1; j < 8; j++)
291 if ((bits[j]&UCHAR(buf, i)) != 0)
292 par++;
293 if ((par&01) == 01)
294 UCHAR(buf, i) = UCHAR(buf, i)&0177;
295 else
296 UCHAR(buf, i) = (UCHAR(buf, i)&0177)|0200;
297 }
298 }
299
300 DES_KEY(UBUFFER(buf));
301 }
302
303
304 /*
305 * This encrypts using the Cipher Block Chaining mode of DES
306 */
307 cbcenc(msgbuf, n, fp)
308 char *msgbuf;
309 int n;
310 FILE *fp;
311 {
312 int inverse = 0; /* 0 to encrypt, 1 to decrypt */
313
314 /*
315 * do the transformation
316 */
317 if (n == 8) {
318 for (n = 0; n < 8; n++)
319 CHAR(msgbuf, n) ^= CHAR(ivec, n);
320 DES_XFORM(UBUFFER(msgbuf));
321 MEMCPY(BUFFER(ivec), BUFFER(msgbuf), 8);
322 return WRITE(BUFFER(msgbuf), 8, fp);
323 }
324 /*
325 * at EOF or last block -- in either case, the last byte contains
326 * the character representation of the number of bytes in it
327 */
328 /*
329 MEMZERO(msgbuf + n, 8 - n);
330 */
331 /*
332 * Pad the last block randomly
333 */
334 (void)MEMCPY(BUFFER(msgbuf + n), BUFFER(pvec), 8 - n);
335 CHAR(msgbuf, 7) = n;
336 for (n = 0; n < 8; n++)
337 CHAR(msgbuf, n) ^= CHAR(ivec, n);
338 DES_XFORM(UBUFFER(msgbuf));
339 return WRITE(BUFFER(msgbuf), 8, fp);
340 }
341
342 /*
343 * This decrypts using the Cipher Block Chaining mode of DES
344 */
345 cbcdec(msgbuf, fp)
346 char *msgbuf; /* I/O buffer */
347 FILE *fp; /* input file descriptor */
348 {
349 Desbuf ibuf; /* temp buffer for initialization vector */
350 register int n; /* number of bytes actually read */
351 register int c; /* used to test for EOF */
352 int inverse = 1; /* 0 to encrypt, 1 to decrypt */
353
354 if ((n = READ(BUFFER(msgbuf), 8, fp)) == 8) {
355 /*
356 * do the transformation
357 */
358 MEMCPY(BUFFER(ibuf), BUFFER(msgbuf), 8);
359 DES_XFORM(UBUFFER(msgbuf));
360 for (c = 0; c < 8; c++)
361 UCHAR(msgbuf, c) ^= UCHAR(ivec, c);
362 MEMCPY(BUFFER(ivec), BUFFER(ibuf), 8);
363 /*
364 * if the last one, handle it specially
365 */
366 if ((c = fgetc(fp)) == EOF) {
367 n = CHAR(msgbuf, 7);
368 if (n < 0 || n > 7) {
369 err("decryption failed (block corrupted)");
370 return EOF;
371 }
372 } else
373 (void)ungetc(c, fp);
374 return n;
375 }
376 if (n > 0)
377 err("decryption failed (incomplete block)");
378 else if (n < 0)
379 err("cannot read file");
380 return EOF;
381 }
382 #endif /* DES */
383