Annotation of pgp/src/basslib.c, revision 1.1.1.1

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: 

unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.