[comp.os.vms] Encryption, anyone?

haug%vax.runit.unit.uninett@TOR.NTA.NO (Steinar Haug) (05/27/87)

In connection with the implementation of secure MHS (X.400 based) systems,
I'm looking for any available programs to perform DES and/or RSA encryption.

Before you start telling me about it: Yes, I'm aware that there is a version
of DES used in Unix systems to encrypt passwords. Yes, I'm aware of the MP
multiple precision math package running under Unix. The trouble with both of
these is that they are simply too slow! The Unix DES because (among other
things) it was made slow on purpose; the mp package because it is a very
general package using a lot of malloc/free calls.

So I'm looking for something faster... Preferably written in C or Pascal,
running on VMS or Unix systems. Any help is appreciated!

Steinar Haug
Database Research Group,
Computing Center at the Univ. of Trondheim, Norway

E-mail:
haug%vax.runit.unit.uninett@nta-vax.arpa
steinar@nta-vax.arpa

ivanovic%vaxr.DECnet@LLL-ICDC.ARPA.UUCP (05/27/87)

Steinar Haug <haug%vax.runit.unit.uninett@NTA-VAX.ARPA> asks

    In connection with the implementation of secure MHS (X.400 based) systems,
    I'm looking for any available programs to perform DES and/or RSA
    encryption.

I have the following, untested, never-been-compiled C code (thanks to a
Macintosh user group) that may do the trick.  User be alert.

NOT National Security Agency approved.  NOT National Security Agency approved.
NOT National Security Agency approved.  NOT National Security Agency approved.
No software DES algorithm is.

-------------------------------  Cut here -------------------------------------
/***************************** desmods *************************
 * DESMODS: encrypt/decrypt bytes using the NBS DES algorithm.
 * Programmed by R.W.Outerbridge; uses Jim Gillogly's DES.
 *
 * Usage: des (+|-)([ecb]|<cbc|cks>) key1 <ivec>
 *              EN/DE   MODES           KEYS
 *
 *      + :     ENcrypt (default if MODE specified)
 *      - :     DEcrypt (presumes encrypted input)
 *
 *      Modes of Operation (choose ONE):
 *
 *      ecb : (default) Electronic Code Book.  Only uses one key.
 *              If simply "+" or "-" is specified, ecb is used.
 *      cbc : Cipher Block Chaining.  Uses two keys.
 *      cks : ChecKSum.  Generates a 64-bit checksum using two keys.
 *
 *      Both keys may be as long as you wish.  The practical limit
 *      on keylength is the size of your system's argument buffer.
 *      WARNING: on some machines all arguments become CAPITALS.
 *      WARNING: non-ascii machines MAY get different results.
 *
 *      Any character may be used in keys - depending on the O/S -
 *      except ASCII NULL (0x00).  The one letter key '#', when used
 *      for "key1", will cause desmods to use a preset default key
 *      (for verification and testing).  Failing to specify "ivec", if
 *      required, will result in "key1" being used for both keys.  It
 *      is an error to omit "key1".  There is no provision for giving
 *      arbitrary, absolute, bit-valued keys.
 *
 *      As painful as they are to use, long keys are MUCH safer;
 *      think up nonsense phrases you can safely remember.
 *
 * 8501.29 : Default key ['#'] not erased from command line.  rwo
 */

#include <stdio.h>
#define toascii(a)      ((a)&0177)
#define EN      0
#define DE      1
#define CKS     2
#define MODS    6       /* three modes times two cases  */
typedef char    BYTE;   /* BYTE = (vax) ? int : char    */

/* cryptographic declarations   */
/*void*/ copy8(), xor8(), getkey();
BYTE Block[8], Link[8], Temp[8], IV[8];
BYTE DFLTKY[8] = { 1,35,69,103,137,171,205,239 };
        /* DO NOT ALTER! => 0x0123456789abcdef <=       */

extern /*void*/ desinit(), kinit(), des();

/* I/O declarations     */
/*void*/ ruderr(), put8(), vraiput(), initio();
int IOedf, End, Once;
BYTE Last[8];

int Ecb(), Cbc(), Cks();
struct modes {
        char *name;
        int (*func)();
        };
struct modes ModsOp[MODS] = {   /* Must be CAPs for CP/M        */
        { "ecb", Ecb },
        { "ECB", Ecb },
        { "cbc", Cbc },
        { "CBC", Cbc },
        { "cks", Cks },
        { "CKS", Cks }  };

main(argc, argv)
int argc;
char **argv;
        {
        int (*xeqtr)();
        int step, ende, edio, ok, i;
        BYTE kv[8];

        argv++; argc--;
        if(argc > 3 || argc < 2) ruderr();
        else desinit();

        for(step=0; argc > 0; step++) {
                switch(step) {
                case 0:         /* set en/de and/or default mode        */
                        if(*argv[0] == '+' || *argv[0] == '-') {
                                ende = (*argv[0] == '+') ? EN : DE;
                                *argv[0]++ = NULL;
                                if(*argv[0] == NULL) {
                                        xeqtr = Ecb;    /* default mode */
                                        edio = ende;
                                        argv++; argc--;
                                        break;
                                        }
                                }
                        else ende = EN;

                        for(i=ok=0; i < MODS && !ok; i++) {
                                if(strcmp(argv[0], ModsOp[i].name) == 0) {
                                        xeqtr = ModsOp[i].func;
                                        ok = 1;
                                        }
                                }
                        if(!ok) {
                                fprintf(stderr,
                                        "Des: unknown mode >%s<.\n", argv[0]);
                                ruderr();
                                }
                        while(*argv[0]) *argv[0]++ = NULL;
                        argv++; argc--;

                        /* set appropriate IO modes     */
                        if(xeqtr == Cks) edio = CKS;
                        else edio = ende;

                /* falling through....  */
                case 1: /* get the key and IV, if needed and present    */
                        if(strcmp(argv[0], "#") == 0) {
                                copy8(DFLTKY, kv);
                                *argv[0] = NULL;
                                }
                        else getkey(argv[0], kv);
                        argv++; argc--;

                        /* if nothing left, but an IV needed, use the key */
                        if(argc == 0) {
                                if(xeqtr != Ecb) copy8(kv, IV);
                                break;
                                }
                        else if(xeqtr == Ecb) {
                                fprintf(stderr, "Des: ivec ignored.\n");
                                while(*argv[0]) *argv[0]++ = NULL;
                                argv++; argc--;
                                break;
                                }

                        else getkey(argv[0], IV);
                        argv++; argc--;
                        break;

                default:
                        fprintf(stderr, "Des: Programming error!\n");
                        exit(1);
                        break;
                        }       /* switch       */
                }       /* argument parsing     */

        kinit(kv, ende);
        initio(edio);
        (*xeqtr)(ende); /* ta-da!       Take it away xeqtr!  */
        exit(0);
        }       /* end of main  */

/*void*/ ruderr() {
        fprintf(stderr, "Usage: des (+|-)([ecb]|<cbc|cks>) key1 <ivec>\n");
        exit(1);
        }

Cbc(e_d)        /* Cipher Block Chaining                */
int e_d;        /* Ciphertext errors are self-healing.  */
        {
        copy8(IV, Link);
        while(get8(Block) != EOF) {
                if(e_d == DE) {
                        des(Block, Temp);
                        xor8(Temp, Link);
                        copy8(Block, Link);
                        put8(Temp);
                        }
                else {
                        xor8(Block, Link);
                        des(Block, Link);
                        put8(Link);
                        }
                }
        return;
        }

Cks(dummy)      /* CBC authentication checksum generator        */
int dummy;      /* The banks use this for verifications.        */
        {
        int i, j, k;
        long count = 0L;
        copy8(IV, Link);
        while(get8(Block) != EOF) {
                xor8(Block, Link);
                des(Block, Link);
                count++;
                }
        fprintf(stdout, ": %0ld bytes\t: ", count<<3);
        for(i=j=0; i < 2; i++) {
                for(k=0; k < 4; k++, j++)
                        fprintf(stdout, "%02x", Link[j]&0377);
                putc(' ', stdout);
                }
        fprintf(stdout, ":\n");
        return;
        }

Ecb(dummy)      /* Electronic Code Book : simple substitution   */
int dummy;      /* Yawn.        For static data and random access.      */
        {
        while(get8(Block) != EOF) {
                des(Block, Block);
                put8(Block);
                }
        return;
        }

/*void*/ copy8(from, to)
register BYTE *from, *to;
        {
        register BYTE *ep;
        ep = &to[8];
        while(to < ep) *to++ = *from++;
        return;
        }

/*void*/ xor8(to, with)
register BYTE *to, *with;
        {
        register BYTE *ep;
        ep = &to[8];
        while(to < ep) *to++ ^= *with++;
        return;
        }

/*void*/ put8(block)
register BYTE *block;
        {
        if(IOedf == DE) copy8(block, Last);
        else vraiput(block, &block[8]);
        return;
        }

get8(input)     /* KLUDGE: incomplete blocks handled sleazily   */
register BYTE *input;
        {
        register int i, j;
        if(End == 1) return(EOF);       /* no more input        */

        for(i=0; i < 8 && ((j = getc(stdin)) != EOF); i++) *input++ = j;

        if(IOedf == DE) {       /* DECRYPTION   */
                /* complete block?      pending output? */
                if(i == 8 && (Once > 0)) vraiput(Last, &Last[8]);
                else if(j == EOF) {
                        End = 1;
                        if(Once > 0) {
                                /* incomplete block means no nulls      */
                                if(i != 0) i = 0;
                                else {
                                        i = Last[7]&0377;
                                        if(i > 8) i = 0;        /* huh? */
                                        }
                                vraiput(Last, &Last[8-i]);
                                }
                        return(EOF);
                        }
                }
        else if(j == EOF) {     /* ENCRYPTION   */
                End = 1;
                if(i == 0 && (IOedf == EN || (Once > 0))) {
                        /* if no padding to do, print a kludge  */
                        if(IOedf == EN && (Once > 0)) putc('0', stdout);
                        return(EOF);
                        }
                for(j=i; j < 7; j++) *input++ = NULL;
                *input = 8-i;
                }
        Once = 1;
        return(0);
        }

/*void*/ vraiput(cp, ep)
register BYTE *cp, *ep;
        {
        while(cp < ep) putc((char)*cp++, stdout);
        return;
        }

/*void*/ initio(edf)        /* use this as a hook on systems without UNIX   */
int edf;
        {
        IOedf = edf;
        End = Once = 0;
        return;
        }

/*void*/ getkey(aptr, kptr)
register char *aptr;
register BYTE *kptr;
        {
        register BYTE *store;
        register int i, first;
        BYTE hold[8];
        store = kptr;
        first = 1;
        kinit(DFLTKY, EN);
        copy8(DFLTKY, hold);
        while(*aptr || first) {
                kptr = store;
                for(i=0; i<8 && (*aptr != NULL); i++) {
                        *kptr++ = toascii(*aptr);
                        *aptr++ = NULL;
                        }
                while(i++ < 8) *kptr++ = NULL;
                xor8(store, hold);
                des(store, hold);
                first = 0;
                }
        copy8(hold, store);
        return;
        }

/* des cks # < /dev/null
 *      : 8 bytes       : c9574425 6a5ed31d :
 *      : (-DKSX64)     : acdcebea eb77deaa :
 *                      (rwo/8502.16.18:30/V1.2)                */
/****************   End of desmods ******************************/
/* des: duplicate the NBS Data Encryption Standard in software.
 *
 * Jim Gillogly, May 1977
 * Modified 8/84 by Jim Gillogly and Lauren Weinstein to compile with
 *      post-1977 C compilers and systems
 * 8409.30 Static & void declarations added.  Interface & testing removed.
 * 8501.28 Rewritten to handle 48-bit blocks during computation.
 * 8502.15 Basic unit of operation changed to 24-bit longs.
 * 8502.19 Type-conversion bugs killed; table pre-computes minimized.
 * 8502.25 Array-size mismatch in p48init() squelched.  KSX64 added.
 *      Richard Outerbridge
 *
 * The copyright in this program remains the proprietary property of
 * the authors.  Permission is hereby given for non-commercial use
 * provided the copyright lines are retained.
 *
 *      Copyright (c) 1977, 1984 by Jim Gillogly
 *      Copyright (c) 1984 by Lauren Weinstein
 *      Copyright (c) 1984, 1985 by Richard Outerbridge
 *
 */

#define DE      1
typedef char     BYTE;   /* BYTE = (vax) ? int : char    */

/*void*/ desinit(), p48init(), permute();

static char s12[4096], s34[4096], s56[4096], s78[4096];
static long p48a[256][2], p48b[256][2], p48c[256][2], p48d[256][2];
static long kn[32];

static int pmv[8] = { 64, 16,  4,  1, 128, 32,  8,  2   };
static int pvs[8] = {  1,  2,  4,  8,  16, 32, 64, 128  };

/*void*/ des(inblock,outblock)
BYTE *inblock, *outblock;
        {
        register long *fmp, suba, subb, val, *h0L, *h1R, *keys;
        BYTE scratch[8], *small;
        long swap[4];
        int i;

        permute(inblock, pmv, pvs, scratch);
        h0L = swap, h1R = &swap[4], small = scratch;
        while(h0L < h1R) {
                val = ((*small++)&0377L)<<24, val |= ((*small++)&0377L)<<16;
                val |= ((*small++)&0377L)<<8, val |= (*small++)&0377L;
                *h0L++ = ((val&0x1L)<<23) | ((val>>9)&0x7C0000L) |
                        ((val&0x1F800000L)>>11) |
                        ((val&0x1F80000L)>>13) |
                        ((val&0x1F8000L)>>15);
                *h0L++ = ((val&0x1F800L)<<7) |
                        ((val&0x1F80L)<<5) |
                        ((val&0x1F8L)<<3) |
                        ((val&0x1FL)<<1) | ((val>>31)&0x1L);
                }
        keys = kn, h0L = swap, h1R = &swap[2];
        for(i=0; i<16; i++) {
                val = *keys++ ^ *h1R++;
                fmp = &p48a[ s12[(val>>12)]&0377 ][0];
                suba = *fmp++, subb = *fmp;
                fmp = &p48b[ s34[(val&07777L)]&0377 ][0];
                suba |= *fmp++, subb |= *fmp;
                val = *keys++ ^ *h1R++;
                fmp = &p48c[ s56[(val>>12)]&0377 ][0];
                suba |= *fmp++, subb |= *fmp;
                fmp = &p48d[ s78[(val&07777L)]&0377 ][0];
                suba |= *fmp++, subb |= *fmp;
                *h0L++ ^= suba, *h0L++ ^= subb;
                if(i&1) h0L = swap;
                else h1R = swap;
                }
        val = *h0L, *h0L++ = *h1R, *h1R++ = val;
        val = *h0L, *h0L = *h1R, *h1R = val;
        h0L = swap, h1R = &swap[4], small = scratch;
        while(h0L < h1R) {
                *small++ = ((*h0L&036000000L)>>15) | ((*h0L&0360000L)>>13);
                *small++ = ((*h0L&03600L)>>3) | ((*h0L&036L)>>1);
                h0L++;
                }
        permute(scratch, pvs, pmv, outblock);
        return;
        }

static char s1[64] = {                  /* S[1]<<4              */
       224, 64,208, 16, 32,240,176,128, 48,160, 96,192, 80,144,  0,112,
         0,240,112, 64,224, 32,208, 16,160, 96,192,176,144, 80, 48,128,
        64, 16,224,128,208, 96, 32,176,240,192,144,112, 48,160, 80,  0,
       240,192,128, 32, 64,144, 16,112, 80,176, 48,224,160,  0, 96,208  };
static char s3[64] = {                  /* S[3]<<4              */
       160,  0,144,224, 96, 48,240, 80, 16,208,192,112,176, 64, 32,128,
       208,112,  0,144, 48, 64, 96,160, 32,128, 80,224,192,176,240, 16,
       208, 96, 64,144,128,240, 48,  0,176, 16, 32,192, 80,160,224,112,
        16,160,208,  0, 96,144,128,112, 64,240,224, 48,176, 80, 32,192  };
static char s5[64] = {                  /* S[5]<<4              */
        32,192, 64, 16,112,160,176, 96,128, 80, 48,240,208,  0,224,144,
       224,176, 32,192, 64,112,208, 16, 80,  0,240,160, 48,144,128, 96,
        64, 32, 16,176,160,208,112,128,240,144,192, 80, 96, 48,  0,224,
       176,128,192,112, 16,224, 32,208, 96,240,  0,144,160, 64, 80, 48  };
static char s7[64] = {                  /* S[7]<<4              */
        64,176, 32,224,240,  0,128,208, 48,192,144,112, 80,160, 96, 16,
       208,  0,176,112, 64,144, 16,160,224, 48, 80,192, 32,240,128, 96,
        16, 64,176,208,192, 48,112,224,160,240, 96,128,  0, 80,144, 32,
        96,176,208,128, 16, 64,160,112,144, 80,  0,240,224, 32, 48,192  };

static char s2[64] = {                  /* S[2]                 */
        15,  1,  8, 14,  6, 11,  3,  4,  9,  7,  2, 13, 12,  0,  5, 10,
         3, 13,  4,  7, 15,  2,  8, 14, 12,  0,  1, 10,  6,  9, 11,  5,
         0, 14,  7, 11, 10,  4, 13,  1,  5,  8, 12,  6,  9,  3,  2, 15,
        13,  8, 10,  1,  3, 15,  4,  2, 11,  6,  7, 12,  0,  5, 14,  9  };
static char s4[64] = {                  /* S[4]                 */
         7, 13, 14,  3,  0,  6,  9, 10,  1,  2,  8,  5, 11, 12,  4, 15,
        13,  8, 11,  5,  6, 15,  0,  3,  4,  7,  2, 12,  1, 10, 14,  9,
        10,  6,  9,  0, 12, 11,  7, 13, 15,  1,  3, 14,  5,  2,  8,  4,
         3, 15,  0,  6, 10,  1, 13,  8,  9,  4,  5, 11, 12,  7,  2, 14  };
static char s6[64] = {                  /* S[6]                 */
        12,  1, 10, 15,  9,  2,  6,  8,  0, 13,  3,  4, 14,  7,  5, 11,
        10, 15,  4,  2,  7, 12,  9,  5,  6,  1, 13, 14,  0, 11,  3,  8,
         9, 14, 15,  5,  2,  8, 12,  3,  7,  0,  4, 10,  1, 13, 11,  6,
         4,  3,  2, 12,  9,  5, 15, 10, 11, 14,  1,  7,  6,  0,  8, 13  };
static char s8[64] = {                  /* S[8]                 */
        13,  2,  8,  4,  6, 15, 11,  1, 10,  9,  3, 14,  5,  0, 12,  7,
         1, 15, 13,  8, 10,  3,  7,  4, 12,  5,  6, 11,  0, 14,  9,  2,
         7, 11,  4,  1,  9, 12, 14,  2,  0,  6, 10, 13, 15,  3,  5,  8,
         2,  1, 14,  7,  4, 10,  8, 13, 15, 12,  9,  0,  3,  5,  6, 11  };

static char p48i[] = {
        24, 15,  6, 19, 20, 28, 20, 28, 11, 27, 16,  0,
        16,  0, 14, 22, 25,  4, 25,  4, 17, 30,  9,  1,
         9,  1,  7, 23, 13, 31, 13, 31, 26,  2,  8, 18,
         8, 18, 12, 29,  5, 21,  5, 21, 10,  3, 24, 15  };

static int bytebit[]                /* bit 0 is left-most in byte   */
        = {     0200,0100,040,020,010,04,02,01 };

static long bigbyte[] = {
        0x800000L, 0x400000L, 0x200000L, 0x100000L,
        0x80000L,  0x40000L,  0x20000L,  0x10000L,
        0x8000L,   0x4000L,   0x2000L,   0x1000L,
        0x800L,    0x400L,    0x200L,    0x100L,
        0x80L,     0x40L,     0x20L,     0x10L,
        0x8L,      0x4L,      0x2L,      0x1L       };

static int Ignited = 0;

/*void*/ desinit() {
        register int j, left, right;

        if(Ignited) return;
        for(j=0; j<4096; j++) {
                left = ((j>>6)&040) | ((j>>2)&020) | ((j>>7)&017);
                right = (j&040) | ((j<<4)&020) | ((j>>1)&017);
                s12[j] = s1[left] | s2[right];
                s34[j] = s3[left] | s4[right];
                s56[j] = s5[left] | s6[right];
                s78[j] = s7[left] | s8[right];
                }
        p48init();
        Ignited = 1;
        return;
        }

#ifdef KSX64
/* Implement an experimental, non-standard, simple-minded 64-bit key.   */

/*void*/ kinit(key, edf)
BYTE *key;
int edf;
        {
        register int i;
        register long *tofill;
        long master[16];

        if(!Ignited) desinit();
        for(i=0; i<16; i++) {
                master[i++] = (*key>>4)&017L;
                master[i] = (*key++)&017L;
                }
        for(i=0; i<16; i++) {
                if(edf == DE) tofill = &kn[(15-i)<<1];
                else tofill = &kn[i<<1];
                *tofill = (master[(i + 1)&017]<<20);
                *tofill |= (master[(i + 8)&017]<<16);
                *tofill |= (master[(i + 5)&017]<<12);
                *tofill |= (master[(i + 10)&017]<<8);
                *tofill |= (master[(i + 3)&017]<<4);
                *tofill++ |= master[(i + 14)&017];
                *tofill = (master[(i + 6)&017]<<20);
                *tofill |= (master[(i + 11)&017]<<16);
                *tofill |= (master[(i + 2)&017]<<12);
                *tofill |= (master[(i + 13)&017]<<8);
                *tofill |= (master[i]<<4);
                *tofill |= master[(i + 9)&017];
                }
        return;
        }

#else
/* Use the key schedule specified in the Standard (ANSI X3.92-1981).    */

static char pc1[] = {                   /* permuted choice table (key)  */
        56, 48, 40, 32, 24, 16,  8,
         0, 57, 49, 41, 33, 25, 17,
         9,  1, 58, 50, 42, 34, 26,
        18, 10,  2, 59, 51, 43, 35,
        62, 54, 46, 38, 30, 22, 14,
         6, 61, 53, 45, 37, 29, 21,
        13,  5, 60, 52, 44, 36, 28,
        20, 12,  4, 27, 19, 11,  3      };

static char totrot[]                    /* number left rotations of pc1 */
= {     1,2,4,6,8,10,12,14,15,17,19,21,23,25,27,28      };

static char pc2[] = {                   /* permuted choice key (table)  */
        13, 16, 10, 23,  0,  4,
         2, 27, 14,  5, 20,  9,
        22, 18, 11,  3, 25,  7,
        15,  6, 26, 19, 12,  1,
        40, 51, 30, 36, 46, 54,
        29, 39, 50, 44, 32, 47,
        43, 48, 38, 55, 33, 52,
        45, 41, 49, 35, 28, 31  };

/*void*/ kinit(key, edf)                    /* initialize key schedule array*/
BYTE *key;                              /* 64 bits; we'll only use 56   */
int edf;
{
        register int i, j, l, m, n;
        char pc1m[56], pcr[56];

        if(!Ignited) desinit();
        for (j=0; j<56; j++) {          /* convert pc1 to bits of key   */
                l = pc1[j];             /* integer bit location         */
                m = l & 07;             /* find bit                     */
                pc1m[j] = (key[l>>3] &  bytebit[m]) ? 1 : 0;
                }
        for (i=0; i<16; i++) {          /* key chunk for each iteration */
                if(edf == DE) m = (15 - i)<<1;
                else m = i<<1;
                n = m + 1;
                kn[m] = kn[n] = 0L;
                for (j=0; j<56; j++)    /* rotate pc1 the right amount  */
                pcr[j] = pc1m[(l=j+totrot[i])<(j<28? 28 : 56) ? l: l-28];
                        /* rotate left and right halves independently   */
                for(j=0; j<24; j++) {
                        if(pcr[pc2[j]]) kn[m] |= bigbyte[j];
                        if(pcr[pc2[j+24]]) kn[n] |= bigbyte[j];
                        }
                }
        return;
        }

#endif

static /*void*/ p48init() {                 /* initialize 32-bit permutation*/
        register int l, j, k, i;
        register long (*pfill)[2];

        for (i=0; i<4; i++) {           /* each input byte position     */
                switch(i) {
                        case 0: pfill = p48a;
                                break;
                        case 1: pfill = p48b;
                                break;
                        case 2: pfill = p48c;
                                break;
                        case 3: pfill = p48d;
                                break;
                        default: break;
                        }
                for (j=0; j<256; j++) {
                        for(k=0; k<2; k++) pfill[j][k] = 0L;
                        for(k=0; k<24; k++) {
                                l = p48i[k];
                                if((l>>3) != i) continue;
                                if( !(j&bytebit[l&07]) ) continue;
                                pfill[j][0] |= bigbyte[k];
                                }
                        for(k=24; k<48; k++) {
                                l = p48i[k];
                                if((l>>3) != i) continue;
                                if( !(j&bytebit[l&07]) ) continue;
                                pfill[j][1] |= bigbyte[k-24];
                                }
                        }
                }
        return;
        }

static /*void*/ permute(inblock, test, vals, outblock)
register BYTE *inblock;
int *test;
register int *vals;
BYTE *outblock;
        {
        register BYTE *cp;
        register int *dp;
        register BYTE *eop, *eip;

        eop = &outblock[8]; eip = &inblock[8];
        for(cp = outblock; cp < eop;) *cp++ = 0;
        while(inblock < eip) {
                cp = outblock;
                dp = test;
                while(cp < eop) {
                        if(*inblock&*dp++) *cp |= *vals;
                        cp++;
                        }
                inblock++;
                vals++;
                }
        return;
        }

/**************** End of DES algorithm PROP rel V2.4 8502.25 **************/
------