Annotation of pgp/src/basslib.c, revision 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.