|
|
1.1 root 1: /* basslib.c -- BassOmatic encipherment functions in C.
2: Version 1.0 25 Jun 89 - Last revised 22 May 91
3:
4: (c) Copyright 1988 by Philip Zimmermann. All rights reserved.
5: This software may not be copied without the written permission of
6: Philip Zimmermann. The author assumes no liability for damages
7: resulting from the use of this software, even if the damage results
8: from defects in this software. No warranty is expressed or implied.
9:
10: Boulder Software Engineering
11: 3021 Eleventh Street
12: Boulder, CO 80304 USA
13: Tel. (303) 444-4541
14: FAX (303) 444-4541 ext. 10
15:
16: BassOmatic is a conventional block cipher with a 256-byte
17: block size for the plaintext and the ciphertext. It also
18: uses a key size of up to 256 bytes. It runs fairly quickly
19: on a computer, faster than most simple DES implementations.
20: Like the DES, it can be used in cipher feedback and cipher block
21: chaining modes. It is based in part on Charles W. Merritt's
22: algorithms which have been used in secure military communications.
23: Merritt's original designs were refined by Zhahai Stewart and
24: Philip Zimmermann to improve security and to improve performance
25: in a portable C implementation. BassOmatic has not yet (in 1989)
26: been through a formal security review and has had only limited peer
27: review. The initial version was implemented in Microsoft C for the
28: IBM PC, and it has been ported to MPW C on the Apple Macintosh
29: and to Unix C without significant modification.
30:
31: BassOmatic gets its name from an old Dan Aykroyd Saturday Night Live
32: skit involving a blender and a whole fish. The BassOmatic algorithm
33: does to data what the original BassOmatic did to the fish.
34: */
35:
36: /* Define STATIC as blank to assist execution performance profiling. */
37: #define STATIC static /* define STATIC as static for normal use */
38:
39: #include <stdio.h> /* for printf */
40:
41: #include "memmgr.h" /* memory manager headers */
42: #include "lfsr.h" /* Linear Feedback Shift Register headers */
43: #include "basslib.h" /* BassOmatic headers */
44:
45: /* on many CPUs, using 16 bits for bytecounter is actually faster: */
46: #define bytecounter word16 /* byte, or word16 for speed */
47:
48: #ifdef DEBUG
49: #define DEBUGprintf1(x) fprintf(stderr,x)
50: #define DEBUGprintf2(x,y) fprintf(stderr,x,y)
51: #else
52: #define DEBUGprintf1(x) /* null macro */
53: #define DEBUGprintf2(x,y) /* null macro */
54: #endif
55:
56:
57: #define NCONTEXTS 3 /* number of key contexts allowed at once */
58: /* NUMBLOX is number of memory blocks in partition */
59: #define NUMBLOX (NCONTEXTS*(NTABLES+3)+8)
60: /* declare memory partition buffer space */
61: static byte part[partsize(256,NUMBLOX)]; /* memory partition */
62: /* We could just call calloc() for this space, instead of declaring it here. */
63:
64: /* The following variables comprise the keyed context information for the
65: ** BassOmatic machine. If the BassOmatic is rekeyed, these variables
66: ** will be affected. If more than one BassOmatic key context is needed
67: ** concurrently, these variables must be saved and restored for each
68: ** context change.
69: */
70:
71: static boolean initialized = FALSE; /* determines whether key context is defined */
72: static byteptr tlist[NTABLES] = {nil}; /* list of permutation table pointers */
73: static byte bitmasks[NTABLES]; /* bitshredder bitmasks with 50% bits set */
74:
75: static byteptr iv = nil; /* CFB Initialization Vector used by initcfb and basscfb */
76: static boolean cfbuncryp = FALSE; /* TRUE means decrypting (in CFB mode) */
77: static boolean uncryp = FALSE; /* TRUE means decrypting (in ECB mode) */
78: /* The following parameters are computed from the key control byte...*/
79: static char nrounds = 0; /* specifies number of rounds thru BassOmatic */
80: static boolean hardrand = FALSE; /* means regenerate tables with BassOmatic */
81: static boolean shred8ways = FALSE; /* means use 8-way bit shredding */
82: static boolean rerand = FALSE; /* means replenish tables with every block */
83:
84: static byteptr lfsr = nil; /* it would help to align LFSR on 256-byte boundary */
85: /* rtail is an index into LFSR buffer */
86: static byte rtail = 0; /* points to 256, which is same as 0 */
87:
88: /* End of BassOmatic keyed context variables */
89:
90:
91:
92: /*
93: ** fillbuf(dst,count,c) - fill byte buffer dst with byte c
94: ** dst is destination buffer pointer.
95: ** count is nonzero byte count.
96: ** c is fill byte.
97: */
98: void fillbuf(register byteptr dst, register short count, register byte c)
99: { do *dst++ = c; while (--count);
100: } /* fillbuf */
101:
102:
103: /*
104: ** CRC routines are purely for debugging purposes...
105: */
106: #define CRCDEBUG /* enables CRC debugging code */
107: #ifdef CRCDEBUG
108: /*
109: ** updcrc - updates CRC 16-bit accumulator with ch,
110: ** uses CCITT polynomial: X^16 + X^12 + X^5 + 1
111: */
112: static word16 updcrc(byte ch, word16 crcaccum)
113: { word16 shifter,flag,data;
114: data = ((word16) ch) & 0xff;
115: for (shifter = 0x80; shifter; shifter >>= 1)
116: { flag = (crcaccum & 0x8000);
117: crcaccum <<= 1;
118: crcaccum |= ((shifter & data) ? 1 : 0);
119: if (flag) crcaccum ^= 0x1021;
120: }
121: return (crcaccum & 0xffff);
122: } /* updcrc() */
123:
124:
125: /*
126: ** crc() - compute crc of buffer
127: ** Used for diagnostic purposes.
128: */
129: word16 crc(register byteptr buf, int count)
130: { word16 crcaccum; /* CRC accumulator */
131: crcaccum = 0; /* clear crc accumulator */
132: do crcaccum = updcrc(*buf++,crcaccum);
133: while (--count); /* loop 256 times */
134: crcaccum = updcrc(0,crcaccum); /* finish up crc */
135: crcaccum = updcrc(0,crcaccum); /* have to do it twice */
136: return(crcaccum); /* return 16-bit CRC */
137: } /* crc */
138:
139:
140: #define dumpcrc(msg,buf) printf("%s CRC=%04x ",msg,crc(buf,256))
141:
142: /*
143: ** dumpblock - dump 256-byte buffer in hex
144: */
145: static void dumpblock(byteptr buf)
146: { bytecounter i;
147: i = 256;
148: printf(" Memory block at %04X: ",buf);
149: do
150: { if ((i & 15)==0)
151: putchar('\n');
152: printf("%02X ",*buf++);
153: } while (--i); /* loop 256 times */
154: dumpcrc("",buf-256);
155: putchar('\n');
156: } /* dumpblock */
157:
158: #endif /* end of CRC debugging routines */
159:
160:
161: /*
162: ** randbuf and randbuf_counter are used by initbassrand, initbrand,
163: ** bassrand, and closebrand. They are not directly used by the BassOmatic
164: ** routines except by initkey(), and thus are not considered part of a
165: ** lasting key context.
166: */
167: static byteptr randbuf = nil; /* buffer for BassOmatic random # generator */
168: static byte randbuf_counter = 0; /* # of random bytes left in randbuf */
169:
170: /*
171: ** initbrand - initialize bassrand, BassOmatic random number generator
172: ** For internal use by initkey() only.
173: ** seed is pointer to random number seed buffer.
174: ** seedlen is length of seed buffer, must be <= 256.
175: */
176: static void initbrand(byteptr seed, short seedlen)
177: { short i;
178: if (randbuf==nil)
179: randbuf = (byteptr) gblock(part); /* allocate block */
180:
181: if (seedlen > 256) seedlen=256;
182: for (i=0; i<seedlen; i++) /* copy original seed material to randbuf */
183: randbuf[i] = seed[i];
184:
185: /* fill rest of randbuf with randomly modified key material */
186: for (; i<256; i++) /* pick up where we left off */
187: randbuf[i] = getlfsr(lfsr,rtail); /* macro gets LFSR byte */
188:
189: randbuf_counter = 0; /* # of random bytes left in randbuf */
190: } /* initbrand */
191:
192:
193: /*
194: ** initbassrand - initialize bassrand, BassOmatic random number generator
195: ** This can be used for generating cryptographically strong random
196: ** numbers by any external application code outside the BassOmatic.
197: ** key is pointer to BassOmatic key buffer.
198: ** keylen is length of key buffer, must be < 256.
199: ** seed is pointer to random number seed buffer.
200: ** seedlen is length of seed buffer, must be <= 256.
201: **
202: ** NOTE: Because this routine calls initkey(), this generator
203: ** must be closed by calling closebass(), NOT closebrand().
204: */
205: void initbassrand(byteptr key, short keylen, byteptr seed, short seedlen)
206: { short i;
207: if (randbuf==nil) /* prevents multiple initialization */
208: { initkey(key, keylen, FALSE); /* initialize BassOmatic */
209: randbuf = (byteptr) gblock(part); /* allocate block */
210: }
211: fillbuf(randbuf,256,0); /* get a clean start */
212: if (seedlen > 256) seedlen=256;
213: for (i=0; i<seedlen; i++) /* copy original seed material to randbuf */
214: randbuf[i] = seed[i];
215: randbuf_counter = 0; /* # of random bytes left in randbuf */
216: } /* initbassrand */
217:
218:
219: /*
220: ** bassrand - BassOmatic pseudo-random number generator
221: ** This can be used for generating cryptographically strong random
222: ** numbers by any external application code outside the BassOmatic.
223: */
224: byte bassrand(void)
225: { byteptr tmp;
226: if (randbuf_counter==0) /* if random buffer is spent...*/
227: { tmp = (byteptr) gblock(part); /* allocate new block */
228: bassomatic(randbuf,tmp); /* fill new block */
229: rblock(part,randbuf); /* release old spent block */
230: randbuf = tmp; /* start on new block */
231: }
232: return(randbuf[--randbuf_counter]); /* take a byte from randbuf */
233: } /* bassrand */
234:
235:
236: /*
237: ** closebrand - deallocate storage used by bassrand
238: ** For internal use by initkey() only.
239: */
240: static void closebrand(void)
241: { if (randbuf!=nil)
242: randbuf = rblock(part,randbuf); /* release block */
243: } /* closebrand */
244:
245:
246: /*
247: ** buildtbl - build a random byte permutation vector
248: **
249: ** References context variables lfsr, rtail, and part.
250: **
251: ** A permutation vector is a table of 256 bytes containing the
252: ** values 0-255 in random order. Each of the values 0-255 appears
253: ** exactly once in the table, with no duplicates and no omissions.
254: **
255: ** The appropriate way to build such a table for cryptographic
256: ** applications is to do the following:
257: ** 1) Start with an empty table, meaning its length is zero.
258: ** 2) Use a pseudo-random number generator to generate random bytes
259: ** that are appended to the table if and only if they are not
260: ** already in the table. If the random byte is already in the
261: ** table, it is discarded and another one is generated from the
262: ** pseudo-random number generator. As the table gets nearly full,
263: ** more and more random bytes are discarded as duplicate entries.
264: ** This is continued until 256 bytes have been inserted in the table.
265: **
266: ** While this approach seems computationally wasteful, it makes it harder
267: ** for a cryptanalyst to infer the properties of the pseudo-random number
268: ** generator, because so many of its output bytes are discarded.
269: **
270: ** Permutation vectors such as these are useful for byte substitution
271: ** tables and byte transposition tables. These are also referred to
272: ** herein as key schedule tables.
273: */
274: STATIC void buildtbl(register byteptr table, boolean rselect)
275: /* table is pointer to table to build.
276: rselect is to select which of 2 random number generators to use.
277: */
278: { register byteptr notdup; /* scratchpad bitmap */
279: register byte c;
280: register short tlen; /* current accumulated table length */
281: register short randtics; /* counts LFSR tics */
282: #define MAXTICS 16383 /* lose patience with LFSR after this long */
283: notdup = (byteptr) gblock(part); /* we could use local stack array instead. */
284: fillbuf(notdup,256,TRUE); /* initialize scratchpad bitmap */
285: tlen = 0; /* start new table with length 0 */
286: /* To fill one table, we can expect to have to tic the LFSR
287: typically about 1000-2500 times, on the average. */
288: randtics = MAXTICS; /* countdown maximum LFSR tics */
289: do
290: { /* get pseudo-random byte from either LFSR or BassOmatic... */
291: c = rselect ?
292: bassrand() : /* get a hard random byte */
293: getlfsr(lfsr,rtail); /* macro gets LFSR byte */
294: if (notdup[c]) /* not in table already? */
295: { table[tlen++] = c; /* append it */
296: notdup[c] = FALSE; /* indicate it's now in table */
297: }
298: if (--randtics == 0) /* detects bogus random generator */
299: { /* Must be an LFSR problem, because the bassrand
300: generator will probably always run OK, so we
301: won't even check rselect. */
302: DEBUGprintf1("\007Adjusting weak LFSR. ");
303: stomplfsr(lfsr); /* hit unruly LFSR upside the head */
304: randtics=MAXTICS; /* reset countdown counter */
305: } /* randtics alarm */
306: } while (tlen<256); /* do until table is full */
307: if (!rselect)
308: /* "discard" current contents of lfsr buffer. Causes
309: steplfsr256 to be called the next time getlfsr is called. */
310: rtail=0; /* dump some LFSR output, confuse attacker */
311: rblock(part,notdup); /* deallocate storage */
312: } /* buildtbl */
313:
314:
315: /*
316: ** Some notes--
317: **
318: ** With some sacrifice of performance due to bit packing and unpacking,
319: ** it would be possible to modify the whole BassOmatic algorithm to use
320: ** a smaller block size. This would require using smaller key schedule
321: ** tables with smaller entries. For example, you could use a table of
322: ** 16 4-bit entries instead of 256 8-bit entries. The number of bits in
323: ** each table entry exponentialy determines the number of entries in the
324: ** key schedule table, and those two dimensions together determine the
325: ** size of the plaintext or ciphertext block. The following chart
326: ** summarizes the relationship between table entry width and cipher
327: ** block size.
328: **
329: ** ENTRY TABLE BLOCK
330: ** WIDTH LENGTH SIZE
331: ** ----- ------ -----
332: ** 8 bits 256 entries 2048 bits, or 256 bytes
333: ** 7 bits 128 entries 896 bits, or 112 bytes
334: ** 6 bits 64 entries 384 bits, or 48 bytes
335: ** 5 bits 32 entries 160 bits, or 20 bytes
336: ** 4 bits 16 entries 64 bits, or 8 bytes
337: **
338: **
339: ** Other questions--
340: ** How many of the key bits are actually effective in producing the
341: ** key schedule tables? Are any key bits wasted?
342: **
343: ** There are 256! permutation tables possible. With 8 tables made
344: ** from a single key, there are (256!)**8 sets of tables possible.
345: ** If there are n bytes in a key (with n<=256), there are 256**n
346: ** keys possible.
347: **
348: ** In theory, more than one of these keys can produce the same table
349: ** or set of tables, since a different selection of random output
350: ** bytes from the pseudorandom number generator may be discarded to
351: ** produce the same table.
352: */
353:
354:
355: /*
356: ** invert - invert a random permutation table
357: ** Called from bldtbls.
358: */
359: STATIC void invert(register byteptr intable, register byteptr outtable)
360: { register byte i;
361: i = 0; /* byte loop index i = 0,255,254,...2,1 */
362: do outtable[intable[i]] = i; /* invert table */
363: while (--i); /* loop 256 times */
364: } /* invert */
365:
366:
367: /*
368: ** transpose - transpose input via table to output
369: ** Called from bldtbls.
370: */
371: STATIC void transpose(register byteptr in, register byteptr out, register byteptr table)
372: /* in and out are the input, output blocks, 256 bytes each.
373: table contains random permutation of 256 bytes.
374: */
375: { register byte i;
376: i = 256; /* byte loop counter */
377: do *out++ = in[*table++]; /* table transpose */
378: while (--i); /* loop 256 times */
379: } /* transpose */
380:
381:
382: /*
383: ** halfmask(c) - returns TRUE iff 50% of the bits in c are set.
384: ** Called only from getmask.
385: */
386: STATIC boolean halfmask(byte c)
387: { byte bitmask,nbits;
388: nbits=0; bitmask=0x80;
389: do
390: { if (c & bitmask)
391: nbits++; /* count the # of 1 bits */
392: bitmask >>= 1;
393: } while (bitmask);
394: return(nbits==4); /* are 4 out of 8 bits set? */
395: } /* halfmask */
396:
397:
398: /*
399: ** getmask - search table for a suitable random mask byte.
400: ** Finds a random mask byte with 50% of its bits set.
401: ** Called from bldtbls.
402: */
403: STATIC byte getmask(register byteptr table)
404: /* table contains random permutation of 256 bytes. */
405: { byte i;
406: i = 0; /* byte loop index i = 0,255,254,...2,1 */
407: do
408: { if (halfmask(table[i]))
409: return(table[i]); /* returns 1st 50% bitmask found */
410: } while (--i); /* loop 256 times */
411: return (0x0f); /* never gets here */
412: } /* getmask */
413:
414:
415: #define ptrswap(p1,p2) { register byteptr p3; p3=p1; p1=p2; p2=p3; }
416:
417:
418: /*
419: ** bldtbls - generate all the permutation tables for the BassOmatic
420: **
421: ** References context variables tlist, shred8ways, bitmasks, and part.
422: */
423: STATIC void bldtbls(boolean hardrand, boolean decryp)
424: /* hardrand specifies which random number generator to use.
425: decryp determines whether to invert the tables.
426: */
427: { byteptr tmp; /* scratchpad table pointers */
428: byteptr mixer; /* table transposer */
429: byte i;
430: tmp = (byteptr) gblock(part); /* allocate new block */
431:
432: mixer = (byteptr) gblock(part); /* allocate transposer table */
433: buildtbl(mixer,hardrand);
434:
435: for (i=0; i<NTABLES; i++) /* for each key schedule table */
436: { /* build a random byte permutation vector... */
437: buildtbl(tmp,hardrand);
438: if (!shred8ways) /* need bitmasks for 2-way bitshredding */
439: bitmasks[i] = getmask(tmp);
440: /* currently, tmp is the table we just built */
441: transpose(tmp,tlist[i],mixer); /* mix up the table */
442: /* now tlist[i] is the table we just built */
443: } /* for each table */
444:
445: rblock(part,mixer); /* deallocate transposer table */
446:
447: /* For decryption, it's not safe to invert any tables until they've
448: all been built, in case hardrand is set. Use separate loop... */
449: if (decryp) /* decryption uses inverted tables */
450: for (i=0; i<NTABLES; i++) /* for each table */
451: { invert(tlist[i],tmp);
452: ptrswap(tlist[i],tmp); /* swap/replace block ptrs */
453: } /* for each table */
454: rblock(part,tmp); /* deallocate block */
455: DEBUGprintf1("*");
456: } /* bldtbls */
457:
458:
459: /*
460: ** bass_save - saves BassOmatic key context in context structure
461: */
462: void bass_save(KEYCONTEXT *context)
463: { int i;
464: context->initialized = initialized;
465: for (i=0; i<NTABLES; i++)
466: context->tlist[i] = tlist[i];
467: for (i=0; i<NTABLES; i++)
468: context->bitmasks[i] = bitmasks[i];
469: context->iv = iv; /* note that iv was passed to initcfb by caller */
470: context->cfbuncryp = cfbuncryp;
471: context->uncryp = uncryp;
472: context->nrounds = nrounds;
473: context->hardrand = hardrand;
474: context->shred8ways = shred8ways;
475: context->rerand = rerand;
476: context->lfsr = lfsr;
477: context->rtail = rtail;
478: } /* bass_save */
479:
480:
481: /*
482: ** bass_restore - restore BassOmatic key context from context structure
483: */
484: void bass_restore(KEYCONTEXT *context)
485: { int i;
486: initialized = context->initialized;
487: for (i=0; i<NTABLES; i++)
488: tlist[i] = context->tlist[i];
489: for (i=0; i<NTABLES; i++)
490: bitmasks[i] = context->bitmasks[i];
491: iv = context->iv; /* note that iv was passed to initcfb by caller */
492: cfbuncryp = context->cfbuncryp;
493: uncryp = context->uncryp;
494: nrounds = context->nrounds;
495: hardrand = context->hardrand;
496: shred8ways = context->shred8ways;
497: rerand = context->rerand;
498: lfsr = context->lfsr;
499: rtail = context->rtail;
500: } /* bass_restore */
501:
502:
503: /*
504: ** closebass - end the current BassOmatic key context, freeing its buffers
505: */
506: void closebass(void)
507: { int i;
508: if (initialized)
509: {
510: /* Close BassOmatic random number generator, in case it's open: */
511: closebrand();
512:
513: for (i=0; i<NTABLES; i++)
514: if (tlist[i]!=nil)
515: tlist[i] = rblock(part,tlist[i]);
516: /* Note that iv is not allocated from memory manager,
517: and thus should not be deallocated */
518: if (lfsr!=nil)
519: lfsr = rblock(part,lfsr);
520: initialized = FALSE;
521: }
522: } /* closebass */
523:
524:
525: static char *copyright_notice(void)
526: /* force linker to include copyright notice in the executable object image. */
527: { return ("(c)1988 Philip Zimmermann"); } /* copyright_notice */
528:
529:
530: /*
531: ** initkey - Initializes the BassOmatic key schedule tables via key.
532: **
533: ** References context variables from key context structure, all of them.
534: **
535: ** Uses several bits from the first byte of the key to select
536: ** how exhaustivly to run the BassOmatic. The key control bits
537: ** specify what tradeoff to make between speed and security.
538: ** These bits in the first byte of the key have these meanings:
539: ** bits 0-2: Number of rounds thru BassOmatic (0-7 means 1-8
540: ** times through). The greater the number, the slower
541: ** it runs.
542: ** bit 3: Set to 1 if we should use slower 8-way bit shredding,
543: ** Set to 0 if we should use faster 50% bitmask shredding.
544: ** bit 4: Set to 1 means use BassOmatic to build its own tables.
545: ** bit 5: Set to 1 iff we should rebuild tables with every block.
546: ** This implicitly disables bit 4, above.
547: ** bits 6-7: Reserved.
548: **
549: ** Key control bit 4 enables a two-tiered key schedule table
550: ** generation. The first set of tables are generated in the usual
551: ** way with a linear feedback shift register (LFSR). Then, a new
552: ** set of tables is regenerated with a far better pseudo-random
553: ** number generator--namely, the BassOmatic running off the first
554: ** set of tables. The BassOmatic pseudo-random number generator
555: ** feeds its output back into itself to generate a stream of
556: ** random blocks. It is seeded with the same raw key that
557: ** seeded the LFSR. When the new set of tables are built, they
558: ** replace the first set as the working tables.
559: **
560: ** Key control bit 5 keeps running the pseudorandom number generator
561: ** to continuously rebuild the key schedule tables for each block of text.
562: ** It automatically turns off key control bit 4. Continuously replenishing
563: ** the tables greatly slows down everything, but it improves security
564: ** significantly. This mode unfortunately also makes using the BassOmatic
565: ** in the DES-like cipher block chaining (CBC) and cipher feedback (CFB)
566: ** modes non-self-synchronizing.
567: */
568: int initkey(byteptr key, short keylen, boolean decryp)
569: /* key is pointer to key buffer, up to 256 bytes long.
570: keylen is length of key buffer, including key control byte.
571: decryp is TRUE if decrypting, FALSE if encrypting.
572: */
573: { byte i;
574:
575: /* initialize BassOmatic data structures */
576: static boolean partition_initialized = FALSE;
577: if (!partition_initialized)
578: { /* if already initialized, skip these steps. */
579: partition_initialized = TRUE;
580: pcreat2(part,256,NUMBLOX); /* initialize memory partition */
581: #ifdef DEBUG2
582: dumpfree(part); /* dump memory free list */
583: #endif
584: }
585:
586: if (key == nil) /* initkey(nil,0,0) only initializes partition */
587: return(0);
588:
589: if (keylen < 2)
590: { /* key must have control byte and nonzero body length */
591: fprintf(stderr,"\nError: BassOmatic key too short.\n\007");
592: return(-1); /* error return */
593: }
594:
595: closebass(); /* deallocate any previously allocated buffers */
596:
597: initialized = TRUE; /* set already initialized flag */
598: for (i=0; i<NTABLES; i++) /* for each table */
599: { /* get memory block from partition */
600: tlist[i] = (byteptr) gblock(part);
601: } /* for each table */
602:
603: nrounds = (*key & 0x07) + 1; /* specifies number of rounds */
604: shred8ways = ((*key & 0x08) != 0); /* use 8-way bit shredding? */
605: rerand = ((*key & 0x20) != 0); /* replenish tables with every block */
606: /* hardrand means use BassOmatic table generator... */
607: hardrand = ((*key & 0x10) != 0) && !rerand;
608: uncryp = FALSE; /* initially assume encrypt, in case of hardrand */
609:
610: #ifdef DEBUG3
611: if (decryp) /* use inverted tables for decryption */
612: fprintf(stderr,"Decrypt, ");
613: else /* use non-inverted tables for encryption */
614: fprintf(stderr,"Encrypt, ");
615: fprintf(stderr,"%x rounds, ",nrounds);
616: if (hardrand) /* BassOmatic random number generator */
617: fprintf(stderr,"hard ");
618: else /* LFSR random number generator */
619: fprintf(stderr,"LFSR ");
620: if (rerand) /* rebuild tables for every block */
621: fprintf(stderr,"dynamic ");
622: else /* keep same tables throughout message */
623: fprintf(stderr,"static ");
624: fprintf(stderr,"tables, ");
625:
626: if (shred8ways)
627: fprintf(stderr,"8-way bitshred.\n");
628: else
629: fprintf(stderr,"2-way bitshred.\n");
630: #endif /* DEBUG3 */
631:
632: /* init LFSR random number generator with key seed */
633: if (lfsr==nil)
634: lfsr = (byteptr) gblock(part); /* allocate LFSR buffer */
635: if (keylen > 255) keylen=255;
636: /* Assume actual key starts after 1st byte, which is control byte */
637: initlfsr(key+1,keylen-1,lfsr,&rtail);
638: /* dumpblock(lfsr); */
639:
640: buildtbl(tlist[0],FALSE); /* build throwaway table to prime the LFSR */
641:
642: /* generate all the permutation tables for the key schedule */
643: if (!rerand) /* don't do it now if it's going to be redone anyway */
644: bldtbls(FALSE,decryp && !hardrand);
645:
646: /* if hardrand, rebuild tables again, this time with BassOmatic */
647: if (hardrand) /* rebuild tables with BassOmatic */
648: { /* form progressivly better bassrand function. */
649: /* init BassOmatic pseudo-random generator */
650: initbrand(key+1,keylen-1); /* skip 1st key byte */
651: bldtbls(hardrand,decryp);/* generate all the tables again */
652: closebrand(); /* deallocate scratch buffers for bassrand */
653: } /* if (hardrand) */
654: uncryp = decryp; /* specifies BassOmatic decrypt or encrypt */
655:
656: if (!rerand) /* if we don't need lfsr buffer anymore, then free it. */
657: lfsr=rblock(part,lfsr); /* sure hope we don't use lfsr again */
658:
659: /* Do an explicit reference to the copyright notice so that the linker
660: will be forced to include it in the executable object image... */
661: copyright_notice(); /* has no real effect at run time */
662: return(0); /* normal return */
663: } /* initkey */
664:
665:
666: /* Now for the primitives called directly from the BassOmatic algorithm...*/
667:
668:
669: /*
670: ** shred1bit - 8-way random bit shred
671: **
672: ** Tears each byte into 8 bits, and randomly distributes the bits.
673: ** Uses 8 different permutation vectors from tlist.
674: ** Unfortunately, it always uses the same 8 tables.
675: */
676: STATIC void shred1bit(register byteptr in, register byteptr out)
677: /* in and out are input, output blocks, 256 bytes each. */
678: { register byte bitmask; /* byte has 1 of its bits set */
679: register bytecounter i;
680: register byteptr table; /* permutation vector */
681: byteptr insave; /* for saving input buffer pointer */
682: byte j;
683: bitmask = 0x80; /* initialize bitmask at highest bit */
684: fillbuf(out,256,0); /* make sure output buffer is clean */
685: /* We could run faster by skipping the fillbuf step, and
686: using "=" instead of "|=" the first time thru the j loop below. */
687:
688: insave = in; /* save input buffer pointer */
689: for (j=0; j<=7; j++) /* for each of 8 bits per byte */
690: { i = 256; /* byte loop counter */
691: table = tlist[j]; /* select a permutation vector */
692: in = insave; /* recover input buffer pointer */
693: do /* permute a single bit from each byte */
694: out[*table++] |= (*in++ & bitmask);
695: while (--i); /* loop 256 times */
696: bitmask >>= 1; /* select next bit for isolation */
697: }
698: } /* shred1bit */
699:
700:
701: /*
702: ** shred4bit - 2-way random bit shred
703: **
704: ** Tears each byte in half, and randomly distributes the halves.
705: */
706: STATIC void shred4bit(register byteptr in, register byteptr out,
707: register byteptr t1, register byteptr t2, register byte bitmask)
708: /* in and out are input, output blocks, 256 bytes each.
709: t1 and t2 each contain random permutation of 256 bytes.
710: bitmask is byte which has 50% of its bits set.
711: */
712: { register bytecounter i;
713: byteptr insave; /* for saving input buffer pointer */
714: insave = in; /* save input buffer pointer */
715: i = 256; /* byte loop counter */
716: do /* isolate half the bits */
717: out[*t1++] = *in++ & bitmask;
718: while (--i); /* loop 256 times */
719: in = insave; /* recover input buffer pointer */
720: bitmask = ~bitmask; /* invert bitmask for other half */
721: i = 256; /* byte loop counter */
722: do /* isolate other half and combine the two halfs */
723: out[*t2++] |= *in++ & bitmask;
724: while (--i); /* loop 256 times */
725: } /* shred4bit */
726:
727:
728: /*
729: ** multilookup - change input via multiple substitution tables
730: */
731: STATIC void multilookup(register byteptr in, register byteptr out, byte ti)
732: /* in and out are input, output blocks, 256 bytes each.
733: ti contains index into starting point of tlist.
734: */
735: { register byteptr table;
736: register byte i;
737: byte j;
738: j=8;
739: do
740: { table = tlist[ti++ & 7]; /* assumes 8 tables */
741: i=32;
742: do *out++ = table[*in++]; /* multi-table substitute */
743: while (--i); /* loop 32 times */
744: }
745: while (--j); /* loop 8 times */
746: } /* multilookup */
747:
748:
749: /*
750: ** xortable - change block via xor with random table
751: **
752: ** This function would serve as its own inverse, if the table is the
753: ** same each time. For use with an inverted table, call ixortable.
754: ** This function inverts 50% of the bits.
755: */
756: STATIC void xortable(register byteptr block, register byteptr table)
757: /* block is a 256 byte block.
758: table contains random permutation of 256 bytes.
759: */
760: { register bytecounter i;
761: i = 256; /* byte loop counter */
762: do *block++ ^= *table++; /* table xor */
763: while (--i); /* loop 256 times */
764: } /* xortable */
765:
766:
767: /*
768: ** ixortable - change block via xor with inverted random table
769: **
770: ** This function inverts 50% of the bits. It is the inverse function
771: ** for xortable, if the table is inverted. Used for decryption.
772: */
773: STATIC void ixortable(register byteptr block, register byteptr table)
774: /* block is a 256 byte block.
775: table contains random permutation of 256 bytes.
776: */
777: { register byte i;
778: i = 0; /* byte loop index i = 0,255,254,...2,1 */
779: do block[table[i]] ^= i; /* inverted table xor */
780: while (--i); /* loop 256 times */
781: } /* ixortable */
782:
783:
784: /*
785: ** rake - rake forwards and backwards with xor and add
786: **
787: ** This is not a keyed operation. It is only useful for increasing
788: ** the intersymbol dependencies between the plaintext and the ciphertext,
789: ** not the key and the ciphertext. Its inverse is function unrake.
790: */
791: STATIC void rake(register byteptr block)
792: { register byte i;
793: register byteptr block1;
794: block1 = block++;
795: /* now block1 = 0, block = 1, relatively speaking */
796: i = 255; /* loop 255 times */
797: /* first do forward raking with cumulative xor */
798: do /* from *1++ ^= *0++; thru *255++ ^= *254++; */
799: *block++ ^= *block1++;
800: while (--i);
801: /* now block1 = 255, block = 256 */
802: i = 255; /* loop 255 times */
803: /* now do backward raking with cumulative add */
804: do /* from *(--255) += *(--256); thru *(--1) += *(--2); */
805: *(--block1) += *(--block);
806: while (--i);
807: /* now block1 = 0, block = 1 */
808: } /* rake */
809:
810:
811: /*
812: ** unrake - unrake forwards and backwards with subtract and xor
813: **
814: ** This is the inverse function of rake. Used for decryption.
815: */
816: STATIC void unrake(register byteptr block)
817: { register byte i;
818: register byteptr block1;
819: block1 = block++;
820: /* now block1 = 0, block = 1, relatively speaking */
821: i = 255; /* loop 255 times */
822: /* first do forward unraking with cumulative subtract */
823: do /* from *0++ -= *1++; thru *254++ -= *255++; */
824: *block1++ -= *block++;
825: while (--i);
826: /* now block1 = 255, block = 256 */
827: i = 255; /* loop 255 times */
828: /* now do backward unraking with cumulative xor */
829: do /* from *(--256) ^= *(--255); thru *(--2) ^= *(--1); */
830: *(--block) ^= *(--block1);
831: while (--i);
832: /* now block1 = 0, block = 1 */
833: } /* unrake */
834:
835:
836: /*
837: ** copy256(dst,src) - copy 256-byte buffer src to dst
838: */
839: void copy256(register byteptr dst, register byteptr src)
840: { register bytecounter size;
841: size = 256; /* loop 256 times */
842: do *dst++ = *src++; while (--size);
843: } /* copy256 */
844:
845:
846: #define f(i,j) (((i)+(j)) & 7) /* used for circular addressing mod 8 */
847: #define tl(i,j) tlist[f(i,j)] /* assumes 8 tables */
848:
849:
850: /*
851: ** bassomatic - encipher 1 block with BassOmatic enciphering algorithm
852: **
853: ** Assumes initkey has already been called.
854: ** References context variables tlist, nrounds, shred8ways,
855: ** bitmasks, uncryp, rerand, and part.
856: */
857: void bassomatic(byteptr in, byteptr out)
858: /* in and out are input, output blocks, 256 bytes each. */
859: { char i; /* signed char */
860: byteptr tmp;
861:
862: if (rerand) /* dynamic replenishment of tables? */
863: bldtbls(FALSE,uncryp);
864:
865: tmp = (byteptr) gblock(part); /* get memory block */
866: copy256(out,in); /* copy in to out */
867:
868: if (uncryp)
869: { /* do decryption */
870: for (i=nrounds-1; i>=0; i--) /* repeat a few rounds */
871: { multilookup(out,tmp,f(i,2));
872: unrake(tmp); /* not effective if last step */
873: if (shred8ways) /* use 8-way bit shredding */
874: shred1bit(tmp,out);
875: else /* use faster 2-way bit shredding */
876: shred4bit(tmp,out,tl(i,1),tl(i,5),
877: bitmasks[f(i,3)]);
878: ixortable(out,tl(i,0)); /* inverts 50% of bits */
879: } /* for loop */
880: } /* if decryption */
881: else /* do encryption */
882: { for (i=0; i<nrounds; i++) /* repeat a few rounds */
883: { xortable(out,tl(i,0)); /* inverts 50% of bits */
884: if (shred8ways) /* use 8-way bit shredding */
885: shred1bit(out,tmp);
886: else /* use faster 2-way bit shredding */
887: shred4bit(out,tmp,tl(i,1),tl(i,5),
888: bitmasks[f(i,3)]);
889: rake(tmp); /* not effective if last step */
890: multilookup(tmp,out,f(i,2));
891: } /* for loop */
892: } /* else encryption */
893: rblock(part,tmp); /* release block */
894: } /* bassomatic */
895:
896:
897: /*
898: ** xorbuf - change buffer via xor with random mask block
899: ** Used for Cipher Feedback (CFB) or Cipher Block Chaining
900: ** (CBC) modes of encryption.
901: ** Can be applied for any block encryption algorithm,
902: ** such as the DES or the BassOmatic.
903: */
904: STATIC void xorbuf(register byteptr buf, register byteptr mask, register int count)
905: /* count must be > 0 */
906: { do
907: *buf++ ^= *mask++;
908: while (--count);
909: } /* xorbuf */
910:
911:
912: /*
913: ** cfbshift - shift bytes into IV for CFB input
914: ** Used only for Cipher Feedback (CFB) mode of encryption.
915: ** Can be applied for any block encryption algorithm,
916: ** such as the DES or the BassOmatic.
917: */
918: STATIC void cfbshift(register byteptr iv, register byteptr buf,
919: register int count, int blocksize)
920: /* iv is the initialization vector.
921: buf is the buffer pointer.
922: count is the number of bytes to shift in...must be > 0.
923: blocksize is 8 for DES, 256 for BassOmatic.
924: */
925: { int retained;
926: retained = blocksize-count; /* number bytes in iv to retain */
927: /* left-shift retained bytes of IV over by count bytes to make room */
928: while (retained--)
929: { *iv = *(iv+count);
930: iv++;
931: }
932: /* now copy count bytes from buf to shifted tail of IV */
933: do *iv++ = *buf++;
934: while (--count);
935: } /* cfbshift */
936:
937:
938: #define BLOCKSIZE 256 /* encryption block size for CFB mode. */
939:
940: /*
941: ** initcfb - Initializes the BassOmatic key schedule tables via key,
942: ** and initializes the Cipher Feedback mode IV.
943: ** References context variables cfbuncryp and iv.
944: */
945: int initcfb(byteptr iv0, byteptr key, short keylen, boolean decryp)
946: /* iv0 is copied to global iv, buffer will be destroyed by basscfb.
947: key is pointer to key buffer, up to 256 bytes long.
948: keylen is length of key buffer.
949: decryp is TRUE if decrypting, FALSE if encrypting.
950: */
951: { iv = iv0; /* iv is not allocated from memory manager */
952: cfbuncryp = decryp;
953: return (initkey(key,keylen,FALSE));
954: } /* initcfb */
955:
956:
957: /*
958: ** basscfb - encipher 1 block with BassOmatic enciphering algorithm,
959: ** using Cipher Feedback (CFB) mode.
960: **
961: ** Assumes initcfb has already been called.
962: ** References context variables cfbuncryp and iv.
963: */
964: void basscfb(byteptr buf, int count)
965: /* buf is input, output buffer, may be more than 1 block.
966: count is byte count of buffer. May be > BLOCKSIZE.
967: */
968: { int chunksize; /* smaller of count, BLOCKSIZE */
969: byte temp[BLOCKSIZE];
970:
971: while ((chunksize = min(count,BLOCKSIZE)) > 0)
972: { bassomatic(iv,temp); /* encrypt iv. */
973:
974: if (cfbuncryp) /* buf is ciphertext */
975: /* shift in ciphertext to IV... */
976: cfbshift(iv,buf,chunksize,BLOCKSIZE);
977:
978: /* convert buf via xor */
979: xorbuf(buf,temp,chunksize); /* buf now has enciphered output */
980:
981: if (!cfbuncryp) /* buf was plaintext, is now ciphertext */
982: /* shift in ciphertext to IV... */
983: cfbshift(iv,buf,chunksize,BLOCKSIZE);
984:
985: count -= chunksize;
986: buf += chunksize;
987: }
988: } /* basscfb */
989:
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.