qemu/crypto/desrfb.c
<<
>>
Prefs
   1/*
   2 * This is D3DES (V5.09) by Richard Outerbridge with the double and
   3 * triple-length support removed for use in VNC.  Also the bytebit[] array
   4 * has been reversed so that the most significant bit in each byte of the
   5 * key is ignored, not the least significant.
   6 *
   7 * These changes are:
   8 *  Copyright (C) 1999 AT&T Laboratories Cambridge.  All Rights Reserved.
   9 *
  10 * This software is distributed in the hope that it will be useful,
  11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
  12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
  13 */
  14
  15/* D3DES (V5.09) -
  16 *
  17 * A portable, public domain, version of the Data Encryption Standard.
  18 *
  19 * Written with Symantec's THINK (Lightspeed) C by Richard Outerbridge.
  20 * Thanks to: Dan Hoey for his excellent Initial and Inverse permutation
  21 * code;  Jim Gillogly & Phil Karn for the DES key schedule code; Dennis
  22 * Ferguson, Eric Young and Dana How for comparing notes; and Ray Lau,
  23 * for humouring me on.
  24 *
  25 * Copyright (c) 1988,1989,1990,1991,1992 by Richard Outerbridge.
  26 * (GEnie : OUTER; CIS : [71755,204]) Graven Imagery, 1992.
  27 */
  28
  29#include "qemu/osdep.h"
  30#include "crypto/desrfb.h"
  31
  32static void scrunch(unsigned char *, unsigned long *);
  33static void unscrun(unsigned long *, unsigned char *);
  34static void desfunc(unsigned long *, unsigned long *);
  35static void cookey(unsigned long *);
  36
  37static unsigned long KnL[32] = { 0L };
  38
  39static const unsigned short bytebit[8]  = {
  40        01, 02, 04, 010, 020, 040, 0100, 0200 };
  41
  42static const unsigned long bigbyte[24] = {
  43        0x800000L,      0x400000L,      0x200000L,      0x100000L,
  44        0x80000L,       0x40000L,       0x20000L,       0x10000L,
  45        0x8000L,        0x4000L,        0x2000L,        0x1000L,
  46        0x800L,         0x400L,         0x200L,         0x100L,
  47        0x80L,          0x40L,          0x20L,          0x10L,
  48        0x8L,           0x4L,           0x2L,           0x1L    };
  49
  50/* Use the key schedule specified in the Standard (ANSI X3.92-1981). */
  51
  52static const unsigned char pc1[56] = {
  53        56, 48, 40, 32, 24, 16,  8,      0, 57, 49, 41, 33, 25, 17,
  54         9,  1, 58, 50, 42, 34, 26,     18, 10,  2, 59, 51, 43, 35,
  55        62, 54, 46, 38, 30, 22, 14,      6, 61, 53, 45, 37, 29, 21,
  56        13,  5, 60, 52, 44, 36, 28,     20, 12,  4, 27, 19, 11,  3 };
  57
  58static const unsigned char totrot[16] = {
  59        1,2,4,6,8,10,12,14,15,17,19,21,23,25,27,28 };
  60
  61static const unsigned char pc2[48] = {
  62        13, 16, 10, 23,  0,  4,  2, 27, 14,  5, 20,  9,
  63        22, 18, 11,  3, 25,  7, 15,  6, 26, 19, 12,  1,
  64        40, 51, 30, 36, 46, 54, 29, 39, 50, 44, 32, 47,
  65        43, 48, 38, 55, 33, 52, 45, 41, 49, 35, 28, 31 };
  66
  67/* Thanks to James Gillogly & Phil Karn! */
  68void deskey(unsigned char *key, int edf)
  69{
  70        register int i, j, l, m, n;
  71        unsigned char pc1m[56], pcr[56];
  72        unsigned long kn[32];
  73
  74        for ( j = 0; j < 56; j++ ) {
  75                l = pc1[j];
  76                m = l & 07;
  77                pc1m[j] = (key[l >> 3] & bytebit[m]) ? 1 : 0;
  78                }
  79        for( i = 0; i < 16; i++ ) {
  80                if( edf == DE1 ) m = (15 - i) << 1;
  81                else m = i << 1;
  82                n = m + 1;
  83                kn[m] = kn[n] = 0L;
  84                for( j = 0; j < 28; j++ ) {
  85                        l = j + totrot[i];
  86                        if( l < 28 ) pcr[j] = pc1m[l];
  87                        else pcr[j] = pc1m[l - 28];
  88                        }
  89                for( j = 28; j < 56; j++ ) {
  90                    l = j + totrot[i];
  91                    if( l < 56 ) pcr[j] = pc1m[l];
  92                    else pcr[j] = pc1m[l - 28];
  93                    }
  94                for( j = 0; j < 24; j++ ) {
  95                        if( pcr[pc2[j]] ) kn[m] |= bigbyte[j];
  96                        if( pcr[pc2[j+24]] ) kn[n] |= bigbyte[j];
  97                        }
  98                }
  99        cookey(kn);
 100        return;
 101        }
 102
 103static void cookey(register unsigned long *raw1)
 104{
 105        register unsigned long *cook, *raw0;
 106        unsigned long dough[32];
 107        register int i;
 108
 109        cook = dough;
 110        for( i = 0; i < 16; i++, raw1++ ) {
 111                raw0 = raw1++;
 112                *cook    = (*raw0 & 0x00fc0000L) << 6;
 113                *cook   |= (*raw0 & 0x00000fc0L) << 10;
 114                *cook   |= (*raw1 & 0x00fc0000L) >> 10;
 115                *cook++ |= (*raw1 & 0x00000fc0L) >> 6;
 116                *cook    = (*raw0 & 0x0003f000L) << 12;
 117                *cook   |= (*raw0 & 0x0000003fL) << 16;
 118                *cook   |= (*raw1 & 0x0003f000L) >> 4;
 119                *cook++ |= (*raw1 & 0x0000003fL);
 120                }
 121        usekey(dough);
 122        return;
 123        }
 124
 125void usekey(register unsigned long *from)
 126{
 127        register unsigned long *to, *endp;
 128
 129        to = KnL, endp = &KnL[32];
 130        while( to < endp ) *to++ = *from++;
 131        return;
 132        }
 133
 134void des(unsigned char *inblock, unsigned char *outblock)
 135{
 136        unsigned long work[2];
 137
 138        scrunch(inblock, work);
 139        desfunc(work, KnL);
 140        unscrun(work, outblock);
 141        return;
 142        }
 143
 144static void scrunch(register unsigned char *outof, register unsigned long *into)
 145{
 146        *into    = (*outof++ & 0xffL) << 24;
 147        *into   |= (*outof++ & 0xffL) << 16;
 148        *into   |= (*outof++ & 0xffL) << 8;
 149        *into++ |= (*outof++ & 0xffL);
 150        *into    = (*outof++ & 0xffL) << 24;
 151        *into   |= (*outof++ & 0xffL) << 16;
 152        *into   |= (*outof++ & 0xffL) << 8;
 153        *into   |= (*outof   & 0xffL);
 154        return;
 155        }
 156
 157static void unscrun(register unsigned long *outof, register unsigned char *into)
 158{
 159        *into++ = (unsigned char)((*outof >> 24) & 0xffL);
 160        *into++ = (unsigned char)((*outof >> 16) & 0xffL);
 161        *into++ = (unsigned char)((*outof >>  8) & 0xffL);
 162        *into++ = (unsigned char)(*outof++       & 0xffL);
 163        *into++ = (unsigned char)((*outof >> 24) & 0xffL);
 164        *into++ = (unsigned char)((*outof >> 16) & 0xffL);
 165        *into++ = (unsigned char)((*outof >>  8) & 0xffL);
 166        *into   =  (unsigned char)(*outof        & 0xffL);
 167        return;
 168        }
 169
 170static const unsigned long SP1[64] = {
 171        0x01010400L, 0x00000000L, 0x00010000L, 0x01010404L,
 172        0x01010004L, 0x00010404L, 0x00000004L, 0x00010000L,
 173        0x00000400L, 0x01010400L, 0x01010404L, 0x00000400L,
 174        0x01000404L, 0x01010004L, 0x01000000L, 0x00000004L,
 175        0x00000404L, 0x01000400L, 0x01000400L, 0x00010400L,
 176        0x00010400L, 0x01010000L, 0x01010000L, 0x01000404L,
 177        0x00010004L, 0x01000004L, 0x01000004L, 0x00010004L,
 178        0x00000000L, 0x00000404L, 0x00010404L, 0x01000000L,
 179        0x00010000L, 0x01010404L, 0x00000004L, 0x01010000L,
 180        0x01010400L, 0x01000000L, 0x01000000L, 0x00000400L,
 181        0x01010004L, 0x00010000L, 0x00010400L, 0x01000004L,
 182        0x00000400L, 0x00000004L, 0x01000404L, 0x00010404L,
 183        0x01010404L, 0x00010004L, 0x01010000L, 0x01000404L,
 184        0x01000004L, 0x00000404L, 0x00010404L, 0x01010400L,
 185        0x00000404L, 0x01000400L, 0x01000400L, 0x00000000L,
 186        0x00010004L, 0x00010400L, 0x00000000L, 0x01010004L };
 187
 188static const unsigned long SP2[64] = {
 189        0x80108020L, 0x80008000L, 0x00008000L, 0x00108020L,
 190        0x00100000L, 0x00000020L, 0x80100020L, 0x80008020L,
 191        0x80000020L, 0x80108020L, 0x80108000L, 0x80000000L,
 192        0x80008000L, 0x00100000L, 0x00000020L, 0x80100020L,
 193        0x00108000L, 0x00100020L, 0x80008020L, 0x00000000L,
 194        0x80000000L, 0x00008000L, 0x00108020L, 0x80100000L,
 195        0x00100020L, 0x80000020L, 0x00000000L, 0x00108000L,
 196        0x00008020L, 0x80108000L, 0x80100000L, 0x00008020L,
 197        0x00000000L, 0x00108020L, 0x80100020L, 0x00100000L,
 198        0x80008020L, 0x80100000L, 0x80108000L, 0x00008000L,
 199        0x80100000L, 0x80008000L, 0x00000020L, 0x80108020L,
 200        0x00108020L, 0x00000020L, 0x00008000L, 0x80000000L,
 201        0x00008020L, 0x80108000L, 0x00100000L, 0x80000020L,
 202        0x00100020L, 0x80008020L, 0x80000020L, 0x00100020L,
 203        0x00108000L, 0x00000000L, 0x80008000L, 0x00008020L,
 204        0x80000000L, 0x80100020L, 0x80108020L, 0x00108000L };
 205
 206static const unsigned long SP3[64] = {
 207        0x00000208L, 0x08020200L, 0x00000000L, 0x08020008L,
 208        0x08000200L, 0x00000000L, 0x00020208L, 0x08000200L,
 209        0x00020008L, 0x08000008L, 0x08000008L, 0x00020000L,
 210        0x08020208L, 0x00020008L, 0x08020000L, 0x00000208L,
 211        0x08000000L, 0x00000008L, 0x08020200L, 0x00000200L,
 212        0x00020200L, 0x08020000L, 0x08020008L, 0x00020208L,
 213        0x08000208L, 0x00020200L, 0x00020000L, 0x08000208L,
 214        0x00000008L, 0x08020208L, 0x00000200L, 0x08000000L,
 215        0x08020200L, 0x08000000L, 0x00020008L, 0x00000208L,
 216        0x00020000L, 0x08020200L, 0x08000200L, 0x00000000L,
 217        0x00000200L, 0x00020008L, 0x08020208L, 0x08000200L,
 218        0x08000008L, 0x00000200L, 0x00000000L, 0x08020008L,
 219        0x08000208L, 0x00020000L, 0x08000000L, 0x08020208L,
 220        0x00000008L, 0x00020208L, 0x00020200L, 0x08000008L,
 221        0x08020000L, 0x08000208L, 0x00000208L, 0x08020000L,
 222        0x00020208L, 0x00000008L, 0x08020008L, 0x00020200L };
 223
 224static const unsigned long SP4[64] = {
 225        0x00802001L, 0x00002081L, 0x00002081L, 0x00000080L,
 226        0x00802080L, 0x00800081L, 0x00800001L, 0x00002001L,
 227        0x00000000L, 0x00802000L, 0x00802000L, 0x00802081L,
 228        0x00000081L, 0x00000000L, 0x00800080L, 0x00800001L,
 229        0x00000001L, 0x00002000L, 0x00800000L, 0x00802001L,
 230        0x00000080L, 0x00800000L, 0x00002001L, 0x00002080L,
 231        0x00800081L, 0x00000001L, 0x00002080L, 0x00800080L,
 232        0x00002000L, 0x00802080L, 0x00802081L, 0x00000081L,
 233        0x00800080L, 0x00800001L, 0x00802000L, 0x00802081L,
 234        0x00000081L, 0x00000000L, 0x00000000L, 0x00802000L,
 235        0x00002080L, 0x00800080L, 0x00800081L, 0x00000001L,
 236        0x00802001L, 0x00002081L, 0x00002081L, 0x00000080L,
 237        0x00802081L, 0x00000081L, 0x00000001L, 0x00002000L,
 238        0x00800001L, 0x00002001L, 0x00802080L, 0x00800081L,
 239        0x00002001L, 0x00002080L, 0x00800000L, 0x00802001L,
 240        0x00000080L, 0x00800000L, 0x00002000L, 0x00802080L };
 241
 242static const unsigned long SP5[64] = {
 243        0x00000100L, 0x02080100L, 0x02080000L, 0x42000100L,
 244        0x00080000L, 0x00000100L, 0x40000000L, 0x02080000L,
 245        0x40080100L, 0x00080000L, 0x02000100L, 0x40080100L,
 246        0x42000100L, 0x42080000L, 0x00080100L, 0x40000000L,
 247        0x02000000L, 0x40080000L, 0x40080000L, 0x00000000L,
 248        0x40000100L, 0x42080100L, 0x42080100L, 0x02000100L,
 249        0x42080000L, 0x40000100L, 0x00000000L, 0x42000000L,
 250        0x02080100L, 0x02000000L, 0x42000000L, 0x00080100L,
 251        0x00080000L, 0x42000100L, 0x00000100L, 0x02000000L,
 252        0x40000000L, 0x02080000L, 0x42000100L, 0x40080100L,
 253        0x02000100L, 0x40000000L, 0x42080000L, 0x02080100L,
 254        0x40080100L, 0x00000100L, 0x02000000L, 0x42080000L,
 255        0x42080100L, 0x00080100L, 0x42000000L, 0x42080100L,
 256        0x02080000L, 0x00000000L, 0x40080000L, 0x42000000L,
 257        0x00080100L, 0x02000100L, 0x40000100L, 0x00080000L,
 258        0x00000000L, 0x40080000L, 0x02080100L, 0x40000100L };
 259
 260static const unsigned long SP6[64] = {
 261        0x20000010L, 0x20400000L, 0x00004000L, 0x20404010L,
 262        0x20400000L, 0x00000010L, 0x20404010L, 0x00400000L,
 263        0x20004000L, 0x00404010L, 0x00400000L, 0x20000010L,
 264        0x00400010L, 0x20004000L, 0x20000000L, 0x00004010L,
 265        0x00000000L, 0x00400010L, 0x20004010L, 0x00004000L,
 266        0x00404000L, 0x20004010L, 0x00000010L, 0x20400010L,
 267        0x20400010L, 0x00000000L, 0x00404010L, 0x20404000L,
 268        0x00004010L, 0x00404000L, 0x20404000L, 0x20000000L,
 269        0x20004000L, 0x00000010L, 0x20400010L, 0x00404000L,
 270        0x20404010L, 0x00400000L, 0x00004010L, 0x20000010L,
 271        0x00400000L, 0x20004000L, 0x20000000L, 0x00004010L,
 272        0x20000010L, 0x20404010L, 0x00404000L, 0x20400000L,
 273        0x00404010L, 0x20404000L, 0x00000000L, 0x20400010L,
 274        0x00000010L, 0x00004000L, 0x20400000L, 0x00404010L,
 275        0x00004000L, 0x00400010L, 0x20004010L, 0x00000000L,
 276        0x20404000L, 0x20000000L, 0x00400010L, 0x20004010L };
 277
 278static const unsigned long SP7[64] = {
 279        0x00200000L, 0x04200002L, 0x04000802L, 0x00000000L,
 280        0x00000800L, 0x04000802L, 0x00200802L, 0x04200800L,
 281        0x04200802L, 0x00200000L, 0x00000000L, 0x04000002L,
 282        0x00000002L, 0x04000000L, 0x04200002L, 0x00000802L,
 283        0x04000800L, 0x00200802L, 0x00200002L, 0x04000800L,
 284        0x04000002L, 0x04200000L, 0x04200800L, 0x00200002L,
 285        0x04200000L, 0x00000800L, 0x00000802L, 0x04200802L,
 286        0x00200800L, 0x00000002L, 0x04000000L, 0x00200800L,
 287        0x04000000L, 0x00200800L, 0x00200000L, 0x04000802L,
 288        0x04000802L, 0x04200002L, 0x04200002L, 0x00000002L,
 289        0x00200002L, 0x04000000L, 0x04000800L, 0x00200000L,
 290        0x04200800L, 0x00000802L, 0x00200802L, 0x04200800L,
 291        0x00000802L, 0x04000002L, 0x04200802L, 0x04200000L,
 292        0x00200800L, 0x00000000L, 0x00000002L, 0x04200802L,
 293        0x00000000L, 0x00200802L, 0x04200000L, 0x00000800L,
 294        0x04000002L, 0x04000800L, 0x00000800L, 0x00200002L };
 295
 296static const unsigned long SP8[64] = {
 297        0x10001040L, 0x00001000L, 0x00040000L, 0x10041040L,
 298        0x10000000L, 0x10001040L, 0x00000040L, 0x10000000L,
 299        0x00040040L, 0x10040000L, 0x10041040L, 0x00041000L,
 300        0x10041000L, 0x00041040L, 0x00001000L, 0x00000040L,
 301        0x10040000L, 0x10000040L, 0x10001000L, 0x00001040L,
 302        0x00041000L, 0x00040040L, 0x10040040L, 0x10041000L,
 303        0x00001040L, 0x00000000L, 0x00000000L, 0x10040040L,
 304        0x10000040L, 0x10001000L, 0x00041040L, 0x00040000L,
 305        0x00041040L, 0x00040000L, 0x10041000L, 0x00001000L,
 306        0x00000040L, 0x10040040L, 0x00001000L, 0x00041040L,
 307        0x10001000L, 0x00000040L, 0x10000040L, 0x10040000L,
 308        0x10040040L, 0x10000000L, 0x00040000L, 0x10001040L,
 309        0x00000000L, 0x10041040L, 0x00040040L, 0x10000040L,
 310        0x10040000L, 0x10001000L, 0x10001040L, 0x00000000L,
 311        0x10041040L, 0x00041000L, 0x00041000L, 0x00001040L,
 312        0x00001040L, 0x00040040L, 0x10000000L, 0x10041000L };
 313
 314static void desfunc(register unsigned long *block, register unsigned long *keys)
 315{
 316        register unsigned long fval, work, right, leftt;
 317        register int round;
 318
 319        leftt = block[0];
 320        right = block[1];
 321        work = ((leftt >> 4) ^ right) & 0x0f0f0f0fL;
 322        right ^= work;
 323        leftt ^= (work << 4);
 324        work = ((leftt >> 16) ^ right) & 0x0000ffffL;
 325        right ^= work;
 326        leftt ^= (work << 16);
 327        work = ((right >> 2) ^ leftt) & 0x33333333L;
 328        leftt ^= work;
 329        right ^= (work << 2);
 330        work = ((right >> 8) ^ leftt) & 0x00ff00ffL;
 331        leftt ^= work;
 332        right ^= (work << 8);
 333        right = ((right << 1) | ((right >> 31) & 1L)) & 0xffffffffL;
 334        work = (leftt ^ right) & 0xaaaaaaaaL;
 335        leftt ^= work;
 336        right ^= work;
 337        leftt = ((leftt << 1) | ((leftt >> 31) & 1L)) & 0xffffffffL;
 338
 339        for( round = 0; round < 8; round++ ) {
 340                work  = (right << 28) | (right >> 4);
 341                work ^= *keys++;
 342                fval  = SP7[ work                & 0x3fL];
 343                fval |= SP5[(work >>  8) & 0x3fL];
 344                fval |= SP3[(work >> 16) & 0x3fL];
 345                fval |= SP1[(work >> 24) & 0x3fL];
 346                work  = right ^ *keys++;
 347                fval |= SP8[ work                & 0x3fL];
 348                fval |= SP6[(work >>  8) & 0x3fL];
 349                fval |= SP4[(work >> 16) & 0x3fL];
 350                fval |= SP2[(work >> 24) & 0x3fL];
 351                leftt ^= fval;
 352                work  = (leftt << 28) | (leftt >> 4);
 353                work ^= *keys++;
 354                fval  = SP7[ work                & 0x3fL];
 355                fval |= SP5[(work >>  8) & 0x3fL];
 356                fval |= SP3[(work >> 16) & 0x3fL];
 357                fval |= SP1[(work >> 24) & 0x3fL];
 358                work  = leftt ^ *keys++;
 359                fval |= SP8[ work                & 0x3fL];
 360                fval |= SP6[(work >>  8) & 0x3fL];
 361                fval |= SP4[(work >> 16) & 0x3fL];
 362                fval |= SP2[(work >> 24) & 0x3fL];
 363                right ^= fval;
 364                }
 365
 366        right = (right << 31) | (right >> 1);
 367        work = (leftt ^ right) & 0xaaaaaaaaL;
 368        leftt ^= work;
 369        right ^= work;
 370        leftt = (leftt << 31) | (leftt >> 1);
 371        work = ((leftt >> 8) ^ right) & 0x00ff00ffL;
 372        right ^= work;
 373        leftt ^= (work << 8);
 374        work = ((leftt >> 2) ^ right) & 0x33333333L;
 375        right ^= work;
 376        leftt ^= (work << 2);
 377        work = ((right >> 16) ^ leftt) & 0x0000ffffL;
 378        leftt ^= work;
 379        right ^= (work << 16);
 380        work = ((right >> 4) ^ leftt) & 0x0f0f0f0fL;
 381        leftt ^= work;
 382        right ^= (work << 4);
 383        *block++ = right;
 384        *block = leftt;
 385        return;
 386        }
 387
 388/* Validation sets:
 389 *
 390 * Single-length key, single-length plaintext -
 391 * Key    : 0123 4567 89ab cdef
 392 * Plain  : 0123 4567 89ab cde7
 393 * Cipher : c957 4425 6a5e d31d
 394 *
 395 * Double-length key, single-length plaintext -
 396 * Key    : 0123 4567 89ab cdef fedc ba98 7654 3210
 397 * Plain  : 0123 4567 89ab cde7
 398 * Cipher : 7f1d 0a77 826b 8aff
 399 *
 400 * Double-length key, double-length plaintext -
 401 * Key    : 0123 4567 89ab cdef fedc ba98 7654 3210
 402 * Plain  : 0123 4567 89ab cdef 0123 4567 89ab cdff
 403 * Cipher : 27a0 8440 406a df60 278f 47cf 42d6 15d7
 404 *
 405 * Triple-length key, single-length plaintext -
 406 * Key    : 0123 4567 89ab cdef fedc ba98 7654 3210 89ab cdef 0123 4567
 407 * Plain  : 0123 4567 89ab cde7
 408 * Cipher : de0b 7c06 ae5e 0ed5
 409 *
 410 * Triple-length key, double-length plaintext -
 411 * Key    : 0123 4567 89ab cdef fedc ba98 7654 3210 89ab cdef 0123 4567
 412 * Plain  : 0123 4567 89ab cdef 0123 4567 89ab cdff
 413 * Cipher : ad0d 1b30 ac17 cf07 0ed1 1c63 81e4 4de5
 414 *
 415 * d3des V5.0a rwo 9208.07 18:44 Graven Imagery
 416 **********************************************************************/
 417