From de2361e72ec68f4ea98f6db2965794b0770a753f Mon Sep 17 00:00:00 2001 From: dg <dg@51575b47-30f0-44d4-a5cc-537603b46e54> Date: Tue, 14 Dec 2010 16:25:39 +0000 Subject: [PATCH] plop git-svn-id: http://svn.net-core.org/repos/t-engine4@2143 51575b47-30f0-44d4-a5cc-537603b46e54 --- src/luamd5/des56.c | 548 ++++++++++++++++++++++++++++++++++++++++++++ src/luamd5/des56.h | 77 +++++++ src/luamd5/ldes56.c | 152 ++++++++++++ src/luamd5/ldes56.h | 1 + src/luamd5/md5.c | 214 +++++++++++++++++ src/luamd5/md5.h | 20 ++ src/luamd5/md5lib.c | 203 ++++++++++++++++ 7 files changed, 1215 insertions(+) create mode 100644 src/luamd5/des56.c create mode 100644 src/luamd5/des56.h create mode 100644 src/luamd5/ldes56.c create mode 100644 src/luamd5/ldes56.h create mode 100644 src/luamd5/md5.c create mode 100644 src/luamd5/md5.h create mode 100644 src/luamd5/md5lib.c diff --git a/src/luamd5/des56.c b/src/luamd5/des56.c new file mode 100644 index 0000000000..1fb377b906 --- /dev/null +++ b/src/luamd5/des56.c @@ -0,0 +1,548 @@ + +/* + * Fast implementation of the DES, as described in the Federal Register, + * Vol. 40, No. 52, p. 12134, March 17, 1975. + * + * Stuart Levy, Minnesota Supercomputer Center, April 1988. + * Currently (2007) slevy@ncsa.uiuc.edu + * NCSA, University of Illinois Urbana-Champaign + * + * Calling sequence: + * + * typedef unsigned long keysched[32]; + * + * fsetkey(key, keysched) / * Converts a DES key to a "key schedule" * / + * unsigned char key[8]; + * keysched *ks; + * + * fencrypt(block, decrypt, keysched) / * En/decrypts one 64-bit block * / + * unsigned char block[8]; / * data, en/decrypted in place * / + * int decrypt; / * 0=>encrypt, 1=>decrypt * / + * keysched *ks; / * key schedule, as set by fsetkey * / + * + * Key and data block representation: + * The 56-bit key (bits 1..64 including "parity" bits 8, 16, 24, ..., 64) + * and the 64-bit data block (bits 1..64) + * are each stored in arrays of 8 bytes. + * Following the NBS numbering, the MSB has the bit number 1, so + * key[0] = 128*bit1 + 64*bit2 + ... + 1*bit8, ... through + * key[7] = 128*bit57 + 64*bit58 + ... + 1*bit64. + * In the key, "parity" bits are not checked; their values are ignored. + * +*/ + +/* +=============================================================================== +License + +des56.c is licensed under the terms of the MIT license reproduced below. +This means that des56.c is free software and can be used for both academic +and commercial purposes at absolutely no cost. +=============================================================================== +Copyright (C) 1988 Stuart Levy + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +THE SOFTWARE. + */ + + +#include "des56.h" + + +/* + * Key schedule generation. + * We begin by pointlessly permuting the 56 useful key bits into + * two groups of 28 bits called C and D. + * bK_C and bK_D are indexed by C and D bit numbers, respectively, + * and give the key bit number (1..64) which should initialize that C/D bit. + * This is the "permuted choice 1" table. + */ + +static tiny bK_C[28] = { + 57, 49, 41, 33, 25, 17, 9, + 1, 58, 50, 42, 34, 26, 18, + 10, 2, 59, 51, 43, 35, 27, + 19, 11, 3, 60, 52, 44, 36, +}; +static tiny bK_D[28] = { + 63, 55, 47, 39, 31, 23, 15, + 7, 62, 54, 46, 38, 30, 22, + 14, 6, 61, 53, 45, 37, 29, + 21, 13, 5, 28, 20, 12, 4, +}; + +/* + * For speed, we invert these, building tables to map groups of + * key bits into the corresponding C and D bits. + * We represent C and D each as 28 contiguous bits right-justified in a + * word, padded on the left with zeros. + * If key byte `i' is said to contain bits Ki,0 (MSB) Ki,1 ... Ki,7 (LSB) + * then + * wC_K4[i][Ki,0 Ki,1 Ki,2 Ki,3] gives the C bits for Ki,0..3, + * wD_K4[i][Ki,0 Ki,1 Ki,2 Ki,3] the corresponding D bits, + * wC_K3[i][Ki,4 Ki,5 Ki,6] the C bits for Ki,4..6, + * and wD_K3[i][Ki,4 Ki,5 Ki,6] the D bits for Ki,4..6. + * Ki,7 is ignored since it is the nominal parity bit. + * We could just use a single table for [i][Ki,0 .. Ki,6] but that + * would take a lot of storage for such a rarely-used function. + */ + +static word32 wC_K4[8][16], wC_K3[8][8]; +static word32 wD_K4[8][16], wD_K3[8][8]; + +/* + * Successive Ci and Di for the sixteen steps in the key schedule are + * created by independent 28-bit left circular shifts on C and D. + * The shift count varies with the step number. + */ +static tiny preshift[16] = { + 1, 1, 2, 2, 2, 2, 2, 2, 1, 2, 2, 2, 2, 2, 2, 1, +}; + +/* + * Each step in the key schedule is generated by selecting 48 bits + * (8 groups of 6 bits) from the appropriately shifted Ci and Di. + * bCD_KS, indexed by the key schedule bit number, gives the bit number + * in CD (CD1 = MSB of C, CD28 = LSB of C, CD29 = MSB of D, CD56 = LSB of D) + * which determines that bit of the key schedule. + * Note that only C bits (1..28) appear in the first (upper) 24 bits of + * the key schedule, and D bits (29..56) in the second (lower) 24 bits. + * This is the "permuted-choice-2" table. + */ + +static tiny bCD_KS[48] = { + 14, 17, 11, 24, 1, 5, + 3, 28, 15, 6, 21, 10, + 23, 19, 12, 4, 26, 8, + 16, 7, 27, 20, 13, 2, + 41, 52, 31, 37, 47, 55, + 30, 40, 51, 45, 33, 48, + 44, 49, 39, 56, 34, 53, + 46, 42, 50, 36, 29, 32, +}; + +/* + * We invert bCD_KS into a pair of tables which map groups of 4 + * C or D bits into corresponding key schedule bits. + * We represent each step of the key schedule as 8 groups of 8 bits, + * with the 6 real bits right-justified in each 8-bit group. + * hKS_C4[i][C4i+1 .. C4i+4] gives the bits in the high order (first four) + * key schedule "bytes" which correspond to C bits 4i+1 .. 4i+4. + * lKS_D4[i][D4i+1 .. D4i+4] gives the appropriate bits in the latter (last 4) + * key schedule bytes, from the corresponding D bits. + */ + +static word32 hKS_C4[7][16]; +static word32 lKS_D4[7][16]; + +/* + * Encryption/decryption. + * Before beginning, and after ending, we perform another useless permutation + * on the bits in the data block. + * + * The initial permutation and its inverse, final permutation + * are too simple to need a table for. If we break the input I1 .. I64 into + * 8-bit chunks I0,0 I0,1 ... I0,7 I1,0 I1,1 ... I7,7 + * then the initial permutation sets LR as follows: + * L = I7,1 I6,1 I5,1 ... I0,1 I7,3 I6,3 ... I0,3 I7,5 ... I0,5 I7,7 ... I0,7 + * and + * R = I7,0 I6,0 I5,0 ... I0,0 I7,2 I6,2 ... I0,2 I7,4 ... I0,4 I7,6 ... I0,6 + * + * If we number the bits in the final LR similarly, + * L = L0,0 L0,1 ... L3,7 R = R0,0 R0,1 ... R3,7 + * then the output is + * O = R0,7 L0,7 R1,7 L1,7 ... R3,7 L3,7 R0,6 L0,6 ... L3,6 R0,5 ... R3,0 L3,0 + * + * To speed I => LR shuffling we use an array of 32-bit values indexed by + * 8-bit input bytes. + * wL_I8[ 0 I0,1 0 I0,3 0 I0,5 0 I0,7 ] = the corresponding L bits. + * Other R and L bits are derived from wL_I8 by shifting. + * + * To speed LR => O shuffling, an array of 32-bit values indexed by 4-bit lumps: + * wO_L4[ L0,4 L0,5 L0,6 L0,7 ] = the corresponding high-order 32 O bits. + */ + +static word32 wL_I8[0x55 + 1]; +static word32 wO_L4[16]; + +/* + * Core of encryption/decryption. + * In each key schedule stage, we: + * take 8 overlapping groups of 6 bits each from R + * (the NBS tabulates the bit selections in the E table, + * but it's so simple we just use shifting to get the right bits) + * XOR each group with the corresponding bits from the key schedule + * Use the resulting 6 bits as an index into the appropriate S table + * (there are 8 such tables, one per group of 6 bits) + * Each S entry yields 4 bits. + * The 8 groups of 4 bits are catenated into a 32-bit value. + * Those 32 bits are permuted according to the P table. + * Finally the permuted 32-bit value is XORed with L and becomes + * the R value for the next stage, while the previous R becomes the new L. + * + * Here, we merge the P permutation with the S tables by making the + * S entries be 32-bit masks, already suitably permuted. + * Also, the bits in each six-bit group must be permuted before use as + * an index into the NBS-tabulated S tables. + * We rearrange entries in wPS so that natural bit order can be used. + */ + +static word32 wPS[8][64]; + +static tiny P[32] = { + 16, 7, 20, 21, + 29, 12, 28, 17, + 1, 15, 23, 26, + 5, 18, 31, 10, + 2, 8, 24, 14, + 32, 27, 3, 9, + 19, 13, 30, 6, + 22, 11, 4, 25, +}; + +static tiny S[8][64] = { + { + 14, 4,13, 1, 2,15,11, 8, 3,10, 6,12, 5, 9, 0, 7, + 0,15, 7, 4,14, 2,13, 1,10, 6,12,11, 9, 5, 3, 8, + 4, 1,14, 8,13, 6, 2,11,15,12, 9, 7, 3,10, 5, 0, + 15,12, 8, 2, 4, 9, 1, 7, 5,11, 3,14,10, 0, 6,13, + }, + + { + 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, + }, + + { + 10, 0, 9,14, 6, 3,15, 5, 1,13,12, 7,11, 4, 2, 8, + 13, 7, 0, 9, 3, 4, 6,10, 2, 8, 5,14,12,11,15, 1, + 13, 6, 4, 9, 8,15, 3, 0,11, 1, 2,12, 5,10,14, 7, + 1,10,13, 0, 6, 9, 8, 7, 4,15,14, 3,11, 5, 2,12, + }, + + { + 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, + }, + + { + 2,12, 4, 1, 7,10,11, 6, 8, 5, 3,15,13, 0,14, 9, + 14,11, 2,12, 4, 7,13, 1, 5, 0,15,10, 3, 9, 8, 6, + 4, 2, 1,11,10,13, 7, 8,15, 9,12, 5, 6, 3, 0,14, + 11, 8,12, 7, 1,14, 2,13, 6,15, 0, 9,10, 4, 5, 3, + }, + + { + 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, + }, + + { + 4,11, 2,14,15, 0, 8,13, 3,12, 9, 7, 5,10, 6, 1, + 13, 0,11, 7, 4, 9, 1,10,14, 3, 5,12, 2,15, 8, 6, + 1, 4,11,13,12, 3, 7,14,10,15, 6, 8, 0, 5, 9, 2, + 6,11,13, 8, 1, 4,10, 7, 9, 5, 0,15,14, 2, 3,12, + }, + + { + 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 void buildtables( void ) +{ + register int i, j; + register word32 v; + word32 wC_K[64], wD_K[64]; + word32 hKS_C[28], lKS_D[28]; + int Smap[64]; + word32 wP[32]; + +#if USG +# define ZERO(array) memset((char *)(array), '\0', sizeof(array)) +#else +# if BSD +# define ZERO(array) bzero((char *)(array), sizeof(array)) +# else +# define ZERO(array) { register word32 *p = (word32 *)(array); \ + i = sizeof(array) / sizeof(*p); \ + do { *p++ = 0; } while(--i > 0); \ + } +# endif +#endif + + + /* Invert permuted-choice-1 (key => C,D) */ + + ZERO(wC_K); + ZERO(wD_K); + v = 1; + for(j = 28; --j >= 0; ) { + wC_K[ bK_C[j] - 1 ] = wD_K[ bK_D[j] - 1 ] = v; + v += v; /* (i.e. v <<= 1) */ + } + + for(i = 0; i < 64; i++) { + int t = 8 >> (i & 3); + for(j = 0; j < 16; j++) { + if(j & t) { + wC_K4[i >> 3][j] |= wC_K[i]; + wD_K4[i >> 3][j] |= wD_K[i]; + if(j < 8) { + wC_K3[i >> 3][j] |= wC_K[i + 3]; + wD_K3[i >> 3][j] |= wD_K[i + 3]; + } + } + } + /* Generate the sequence 0,1,2,3, 8,9,10,11, ..., 56,57,58,59. */ + if(t == 1) i += 4; + } + + /* Invert permuted-choice-2 */ + + ZERO(hKS_C); + ZERO(lKS_D); + v = 1; + for(i = 24; (i -= 6) >= 0; ) { + j = i+5; + do { + hKS_C[ bCD_KS[j] - 1 ] = lKS_D[ bCD_KS[j+24] - 28 - 1 ] = v; + v += v; /* Like v <<= 1 but may be faster */ + } while(--j >= i); + v <<= 2; /* Keep byte aligned */ + } + + for(i = 0; i < 28; i++) { + v = 8 >> (i & 3); + for(j = 0; j < 16; j++) { + if(j & v) { + hKS_C4[i >> 2][j] |= hKS_C[i]; + lKS_D4[i >> 2][j] |= lKS_D[i]; + } + } + } + + /* Initial permutation */ + + for(i = 0; i <= 0x55; i++) { + v = 0; + if(i & 64) v = (word32) 1 << 24; + if(i & 16) v |= (word32) 1 << 16; + if(i & 4) v |= (word32) 1 << 8; + if(i & 1) v |= 1; + wL_I8[i] = v; + } + + /* Final permutation */ + + for(i = 0; i < 16; i++) { + v = 0; + if(i & 1) v = (word32) 1 << 24; + if(i & 2) v |= (word32) 1 << 16; + if(i & 4) v |= (word32) 1 << 8; + if(i & 8) v |= (word32) 1; + wO_L4[i] = v; + } + + /* Funny bit rearrangement on second index into S tables */ + + for(i = 0; i < 64; i++) { + Smap[i] = (i & 0x20) | (i & 1) << 4 | (i & 0x1e) >> 1; + } + + /* Invert permutation P into mask indexed by R bit number */ + + v = 1; + for(i = 32; --i >= 0; ) { + wP[ P[i] - 1 ] = v; + v += v; + } + + /* Build bit-mask versions of S tables, indexed in natural bit order */ + + for(i = 0; i < 8; i++) { + for(j = 0; j < 64; j++) { + int k, t; + + t = S[i][ Smap[j] ]; + for(k = 0; k < 4; k++) { + if(t & 8) + wPS[i][j] |= wP[4*i + k]; + t += t; + } + } + } +} + + +void fsetkey(char key[8], keysched *ks) +{ + register int i; + register word32 C, D; + static int built = 0; + + if(!built) { + buildtables(); + built = 1; + } + + C = D = 0; + for(i = 0; i < 8; i++) { + register int v; + + v = key[i] >> 1; /* Discard "parity" bit */ + C |= wC_K4[i][(v>>3) & 15] | wC_K3[i][v & 7]; + D |= wD_K4[i][(v>>3) & 15] | wD_K3[i][v & 7]; + } + + /* + * C and D now hold the suitably right-justified + * 28 permuted key bits each. + */ + for(i = 0; i < 16; i++) { +#ifdef CRAY +#define choice2(x, v) x[6][v&15] | x[5][(v>>4)&15] | x[4][(v>>8)&15] | \ + x[3][(v>>12)&15] | x[2][(v>>16)&15] | x[1][(v>>20)&15] | \ + x[0][(v>>24)&15] +#else + register word32 *ap; + +# define choice2(x, v) ( \ + ap = &(x)[0][0], \ + ap[16*6 + (v&15)] | \ + ap[16*5 + ((v>>4)&15)] | ap[16*4 + ((v>>8)&15)] | \ + ap[16*3 + ((v>>12)&15)] | ap[16*2 + ((v>>16)&15)] | \ + ap[16*1 + ((v>>20)&15)] | ap[16*0 + ((v>>24)&15)] ) +#endif + + + /* 28-bit left circular shift */ + C <<= preshift[i]; + C = ((C >> 28) & 3) | (C & (((word32)1<<28) - 1)); + ks->KS[i].h = choice2(hKS_C4, C); + + D <<= preshift[i]; + D = ((D >> 28) & 3) | (D & (((word32)1<<28) - 1)); + ks->KS[i].l = choice2(lKS_D4, D); + } +} + +void +fencrypt(char block[8], int decrypt, keysched *ks) +{ + int i; + register word32 L, R; + register struct keystage *ksp; + register word32 *ap; + + /* Initial permutation */ + + L = R = 0; + i = 7; + ap = wL_I8; + do { + register int v; + + v = block[i]; /* Could optimize according to ENDIAN */ + L = ap[v & 0x55] | (L << 1); + R = ap[(v >> 1) & 0x55] | (R << 1); + } while(--i >= 0); + + if(decrypt) { + ksp = &ks->KS[15]; + } else { + ksp = &ks->KS[0]; + } + +#ifdef CRAY +# define PS(i,j) wPS[i][j] +#else +# define PS(i,j) ap[64*(i) + (j)] + ap = &wPS[0][0]; +#endif + + i = 16; + do { + register word32 k, tR; + + tR = (R >> 15) | (R << 17); + + k = ksp->h; + L ^= PS(0, ((tR >> 12) ^ (k >> 24)) & 63) + | PS(1, ((tR >> 8) ^ (k >> 16)) & 63) + | PS(2, ((tR >> 4) ^ (k >> 8)) & 63) + | PS(3, (tR ^ k) & 63); + + k = ksp->l; + L ^= PS(4, ((R >> 11) ^ (k >> 24)) & 63) + | PS(5, ((R >> 7) ^ (k >> 16)) & 63) + | PS(6, ((R >> 3) ^ (k >> 8)) & 63) + | PS(7, ((tR >> 16) ^ k) & 63); + + tR = L; + L = R; + R = tR; + + + if(decrypt) + ksp--; + else + ksp++; + } while(--i > 0); + { + register word32 t; + +#ifdef CRAY +# define FP(k) (wO_L4[ (L >> (k)) & 15 ] << 1 | wO_L4[ (R >> (k)) & 15 ]) +#else +# define FP(k) (ap[ (L >> (k)) & 15 ] << 1 | ap[ (R >> (k)) & 15 ]) + + ap = wO_L4; +#endif + + t = FP(0) | (FP(8) | (FP(16) | (FP(24) << 2)) << 2) << 2; + R = FP(4) | (FP(12) | (FP(20) | (FP(28) << 2)) << 2) << 2; + L = t; + } + { + register word32 t; + register char *bp; + + bp = &block[7]; + t = R; + *bp = t & 255; + *--bp = (t >>= 8) & 255; + *--bp = (t >>= 8) & 255; + *--bp = (t >> 8) & 255; + t = L; + *--bp = t & 255; + *--bp = (t >>= 8) & 255; + *--bp = (t >>= 8) & 255; + *--bp = (t >> 8) & 255; + } +} + diff --git a/src/luamd5/des56.h b/src/luamd5/des56.h new file mode 100644 index 0000000000..88e5f137c1 --- /dev/null +++ b/src/luamd5/des56.h @@ -0,0 +1,77 @@ +#ifndef DES56_H +#define DES56_H 1 +/* + * Fast implementation of the DES, as described in the Federal Register, + * Vol. 40, No. 52, p. 12134, March 17, 1975. + * + * Stuart Levy, Minnesota Supercomputer Center, April 1988. + * Currently (2007) slevy@ncsa.uiuc.edu + * NCSA, University of Illinois Urbana-Champaign + * + * Calling sequence: + * + * typedef unsigned long keysched[32]; + * + * fsetkey(key, keysched) / * Converts a DES key to a "key schedule" * / + * unsigned char key[8]; + * keysched *ks; + * + * fencrypt(block, decrypt, keysched) / * En/decrypts one 64-bit block * / + * unsigned char block[8]; / * data, en/decrypted in place * / + * int decrypt; / * 0=>encrypt, 1=>decrypt * / + * keysched *ks; / * key schedule, as set by fsetkey * / + * + * Key and data block representation: + * The 56-bit key (bits 1..64 including "parity" bits 8, 16, 24, ..., 64) + * and the 64-bit data block (bits 1..64) + * are each stored in arrays of 8 bytes. + * Following the NBS numbering, the MSB has the bit number 1, so + * key[0] = 128*bit1 + 64*bit2 + ... + 1*bit8, ... through + * key[7] = 128*bit57 + 64*bit58 + ... + 1*bit64. + * In the key, "parity" bits are not checked; their values are ignored. + * +*/ + +/* +=============================================================================== +License + +des56.c is licensed under the terms of the MIT license reproduced below. +This means that des56.c is free software and can be used for both academic +and commercial purposes at absolutely no cost. +=============================================================================== +Copyright (C) 1988 Stuart Levy + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +THE SOFTWARE. + */ + +typedef unsigned long word32; +typedef unsigned char tiny; + +typedef struct keysched { + struct keystage { + word32 h, l; + } KS[16]; +} keysched; + +extern void fsetkey(char key[8], keysched *ks); + +extern void fencrypt(char block[8], int decrypt, keysched *ks); + +#endif /*DES56_H*/ diff --git a/src/luamd5/ldes56.c b/src/luamd5/ldes56.c new file mode 100644 index 0000000000..5b8d9e1efa --- /dev/null +++ b/src/luamd5/ldes56.c @@ -0,0 +1,152 @@ +#include <stdlib.h> +#include <string.h> + +#include "des56.h" + +#include "lua.h" +#include "lauxlib.h" + +#include "ldes56.h" + +static int des56_decrypt( lua_State *L ) +{ + char* decypheredText; + keysched KS; + int rel_index, abs_index; + size_t cypherlen; + const char *cypheredText = + luaL_checklstring( L, 1, &cypherlen ); + const char *key = luaL_optstring( L, 2, NULL ); + int padinfo; + + padinfo = cypheredText[cypherlen-1]; + cypherlen--; + + /* Aloca array */ + decypheredText = + (char *) malloc( (cypherlen+1) * sizeof(char)); + if(decypheredText == NULL) { + lua_pushstring(L, "Error decrypting file. Not enough memory."); + lua_error(L); + } + + /* Inicia decifragem */ + if (key && strlen(key) >= 8) + { + char k[8]; + int i; + + for (i=0; i<8; i++) + k[i] = (unsigned char)key[i]; + fsetkey(k, &KS); + } else { + lua_pushstring(L, "Error decrypting file. Invalid key."); + lua_error(L); + } + + rel_index = 0; + abs_index = 0; + + while (abs_index < (int) cypherlen) + { + decypheredText[abs_index] = cypheredText[abs_index]; + abs_index++; + rel_index++; + if( rel_index == 8 ) + { + rel_index = 0; + fencrypt(&(decypheredText[abs_index - 8]), 1, &KS); + } + } + decypheredText[abs_index] = 0; + + lua_pushlstring(L, decypheredText, (abs_index-padinfo)); + free( decypheredText ); + return 1; +} + +static int des56_crypt( lua_State *L ) +{ + char *cypheredText; + keysched KS; + int rel_index, pad, abs_index; + size_t plainlen; + const char *plainText = luaL_checklstring( L, 1, &plainlen ); + const char *key = luaL_optstring( L, 2, NULL ); + + cypheredText = (char *) malloc( (plainlen+8) * sizeof(char)); + if(cypheredText == NULL) { + lua_pushstring(L, "Error encrypting file. Not enough memory."); + lua_error(L); + } + + if (key && strlen(key) >= 8) + { + char k[8]; + int i; + + for (i=0; i<8; i++) + k[i] = (unsigned char)key[i]; + fsetkey(k, &KS); + } else { + lua_pushstring(L, "Error encrypting file. Invalid key."); + lua_error(L); + } + + rel_index = 0; + abs_index = 0; + while (abs_index < (int) plainlen) { + cypheredText[abs_index] = plainText[abs_index]; + abs_index++; + rel_index++; + if( rel_index == 8 ) { + rel_index = 0; + fencrypt(&(cypheredText[abs_index - 8]), 0, &KS); + } + } + + pad = 0; + if(rel_index != 0) { /* Pads remaining bytes with zeroes */ + while(rel_index < 8) + { + pad++; + cypheredText[abs_index++] = 0; + rel_index++; + } + fencrypt(&(cypheredText[abs_index - 8]), 0, &KS); + } + cypheredText[abs_index] = pad; + + lua_pushlstring( L, cypheredText, abs_index+1 ); + free( cypheredText ); + return 1; +} + +/* +** Assumes the table is on top of the stack. +*/ +static void set_info (lua_State *L) { + lua_pushliteral (L, "_COPYRIGHT"); + lua_pushliteral (L, "Copyright (C) 2007 PUC-Rio"); + lua_settable (L, -3); + lua_pushliteral (L, "_DESCRIPTION"); + lua_pushliteral (L, "DES 56 cryptographic facilities for Lua"); + lua_settable (L, -3); + lua_pushliteral (L, "_VERSION"); + lua_pushliteral (L, "DES56 1.1.2"); + lua_settable (L, -3); +} + +static const struct luaL_reg des56lib[] = { + {"crypt", des56_crypt}, + {"decrypt", des56_decrypt}, + {NULL, NULL}, +}; + +int luaopen_des56 (lua_State *L) { + luaL_openlib (L, "des56", des56lib, 0); + set_info (L); + return 1; +} + + diff --git a/src/luamd5/ldes56.h b/src/luamd5/ldes56.h new file mode 100644 index 0000000000..8c2e86a8ca --- /dev/null +++ b/src/luamd5/ldes56.h @@ -0,0 +1 @@ +int luaopen_des56 (lua_State *L); diff --git a/src/luamd5/md5.c b/src/luamd5/md5.c new file mode 100644 index 0000000000..8b15b43763 --- /dev/null +++ b/src/luamd5/md5.c @@ -0,0 +1,214 @@ +/** +* $Id: md5.c,v 1.2 2008/03/24 20:59:12 mascarenhas Exp $ +* Hash function MD5 +* @author Marcela Ozorio Suarez, Roberto I. +*/ + + +#include <string.h> + +#include "md5.h" + + +#define WORD 32 +#define MASK 0xFFFFFFFF +#if __STDC_VERSION__ >= 199901L +#include <stdint.h> +typedef uint32_t WORD32; +#else +typedef unsigned int WORD32; +#endif + + +/** +* md5 hash function. +* @param message: aribtary string. +* @param len: message length. +* @param output: buffer to receive the hash value. Its size must be +* (at least) HASHSIZE. +*/ +void md5 (const char *message, long len, char *output); + + + +/* +** Realiza a rotacao no sentido horario dos bits da variavel 'D' do tipo WORD32. +** Os bits sao deslocados de 'num' posicoes +*/ +#define rotate(D, num) (D<<num) | (D>>(WORD-num)) + +/*Macros que definem operacoes relizadas pelo algoritmo md5 */ +#define F(x, y, z) (((x) & (y)) | ((~(x)) & (z))) +#define G(x, y, z) (((x) & (z)) | ((y) & (~(z)))) +#define H(x, y, z) ((x) ^ (y) ^ (z)) +#define I(x, y, z) ((y) ^ ((x) | (~(z)))) + + +/*vetor de numeros utilizados pelo algoritmo md5 para embaralhar bits */ +static const WORD32 T[64]={ + 0xd76aa478, 0xe8c7b756, 0x242070db, 0xc1bdceee, + 0xf57c0faf, 0x4787c62a, 0xa8304613, 0xfd469501, + 0x698098d8, 0x8b44f7af, 0xffff5bb1, 0x895cd7be, + 0x6b901122, 0xfd987193, 0xa679438e, 0x49b40821, + 0xf61e2562, 0xc040b340, 0x265e5a51, 0xe9b6c7aa, + 0xd62f105d, 0x02441453, 0xd8a1e681, 0xe7d3fbc8, + 0x21e1cde6, 0xc33707d6, 0xf4d50d87, 0x455a14ed, + 0xa9e3e905, 0xfcefa3f8, 0x676f02d9, 0x8d2a4c8a, + 0xfffa3942, 0x8771f681, 0x6d9d6122, 0xfde5380c, + 0xa4beea44, 0x4bdecfa9, 0xf6bb4b60, 0xbebfbc70, + 0x289b7ec6, 0xeaa127fa, 0xd4ef3085, 0x04881d05, + 0xd9d4d039, 0xe6db99e5, 0x1fa27cf8, 0xc4ac5665, + 0xf4292244, 0x432aff97, 0xab9423a7, 0xfc93a039, + 0x655b59c3, 0x8f0ccc92, 0xffeff47d, 0x85845dd1, + 0x6fa87e4f, 0xfe2ce6e0, 0xa3014314, 0x4e0811a1, + 0xf7537e82, 0xbd3af235, 0x2ad7d2bb, 0xeb86d391 +}; + + +static void word32tobytes (const WORD32 *input, char *output) { + int j = 0; + while (j<4*4) { + WORD32 v = *input++; + output[j++] = (char)(v & 0xff); v >>= 8; + output[j++] = (char)(v & 0xff); v >>= 8; + output[j++] = (char)(v & 0xff); v >>= 8; + output[j++] = (char)(v & 0xff); + } +} + + +static void inic_digest(WORD32 *d) { + d[0] = 0x67452301; + d[1] = 0xEFCDAB89; + d[2] = 0x98BADCFE; + d[3] = 0x10325476; +} + + +/*funcao que implemeta os quatro passos principais do algoritmo MD5 */ +static void digest(const WORD32 *m, WORD32 *d) { + int j; + /*MD5 PASSO1 */ + for (j=0; j<4*4; j+=4) { + d[0] = d[0]+ F(d[1], d[2], d[3])+ m[j] + T[j]; d[0]=rotate(d[0], 7); + d[0]+=d[1]; + d[3] = d[3]+ F(d[0], d[1], d[2])+ m[(j)+1] + T[j+1]; d[3]=rotate(d[3], 12); + d[3]+=d[0]; + d[2] = d[2]+ F(d[3], d[0], d[1])+ m[(j)+2] + T[j+2]; d[2]=rotate(d[2], 17); + d[2]+=d[3]; + d[1] = d[1]+ F(d[2], d[3], d[0])+ m[(j)+3] + T[j+3]; d[1]=rotate(d[1], 22); + d[1]+=d[2]; + } + /*MD5 PASSO2 */ + for (j=0; j<4*4; j+=4) { + d[0] = d[0]+ G(d[1], d[2], d[3])+ m[(5*j+1)&0x0f] + T[(j-1)+17]; + d[0] = rotate(d[0],5); + d[0]+=d[1]; + d[3] = d[3]+ G(d[0], d[1], d[2])+ m[((5*(j+1)+1)&0x0f)] + T[(j+0)+17]; + d[3] = rotate(d[3], 9); + d[3]+=d[0]; + d[2] = d[2]+ G(d[3], d[0], d[1])+ m[((5*(j+2)+1)&0x0f)] + T[(j+1)+17]; + d[2] = rotate(d[2], 14); + d[2]+=d[3]; + d[1] = d[1]+ G(d[2], d[3], d[0])+ m[((5*(j+3)+1)&0x0f)] + T[(j+2)+17]; + d[1] = rotate(d[1], 20); + d[1]+=d[2]; + } + /*MD5 PASSO3 */ + for (j=0; j<4*4; j+=4) { + d[0] = d[0]+ H(d[1], d[2], d[3])+ m[(3*j+5)&0x0f] + T[(j-1)+33]; + d[0] = rotate(d[0], 4); + d[0]+=d[1]; + d[3] = d[3]+ H(d[0], d[1], d[2])+ m[(3*(j+1)+5)&0x0f] + T[(j+0)+33]; + d[3] = rotate(d[3], 11); + d[3]+=d[0]; + d[2] = d[2]+ H(d[3], d[0], d[1])+ m[(3*(j+2)+5)&0x0f] + T[(j+1)+33]; + d[2] = rotate(d[2], 16); + d[2]+=d[3]; + d[1] = d[1]+ H(d[2], d[3], d[0])+ m[(3*(j+3)+5)&0x0f] + T[(j+2)+33]; + d[1] = rotate(d[1], 23); + d[1]+=d[2]; + } + /*MD5 PASSO4 */ + for (j=0; j<4*4; j+=4) { + d[0] = d[0]+ I(d[1], d[2], d[3])+ m[(7*j)&0x0f] + T[(j-1)+49]; + d[0] = rotate(d[0], 6); + d[0]+=d[1]; + d[3] = d[3]+ I(d[0], d[1], d[2])+ m[(7*(j+1))&0x0f] + T[(j+0)+49]; + d[3] = rotate(d[3], 10); + d[3]+=d[0]; + d[2] = d[2]+ I(d[3], d[0], d[1])+ m[(7*(j+2))&0x0f] + T[(j+1)+49]; + d[2] = rotate(d[2], 15); + d[2]+=d[3]; + d[1] = d[1]+ I(d[2], d[3], d[0])+ m[(7*(j+3))&0x0f] + T[(j+2)+49]; + d[1] = rotate(d[1], 21); + d[1]+=d[2]; + } +} + + +static void bytestoword32 (WORD32 *x, const char *pt) { + int i; + for (i=0; i<16; i++) { + int j=i*4; + x[i] = (((WORD32)(unsigned char)pt[j+3] << 8 | + (WORD32)(unsigned char)pt[j+2]) << 8 | + (WORD32)(unsigned char)pt[j+1]) << 8 | + (WORD32)(unsigned char)pt[j]; + } + +} + + +static void put_length(WORD32 *x, long len) { + /* in bits! */ + x[14] = (WORD32)((len<<3) & MASK); + x[15] = (WORD32)(len>>(32-3) & 0x7); +} + + +/* +** returned status: +* 0 - normal message (full 64 bytes) +* 1 - enough room for 0x80, but not for message length (two 4-byte words) +* 2 - enough room for 0x80 plus message length (at least 9 bytes free) +*/ +static int converte (WORD32 *x, const char *pt, int num, int old_status) { + int new_status = 0; + char buff[64]; + if (num<64) { + memcpy(buff, pt, num); /* to avoid changing original string */ + memset(buff+num, 0, 64-num); + if (old_status == 0) + buff[num] = '\200'; + new_status = 1; + pt = buff; + } + bytestoword32(x, pt); + if (num <= (64 - 9)) + new_status = 2; + return new_status; +} + + + +void md5 (const char *message, long len, char *output) { + WORD32 d[4]; + int status = 0; + long i = 0; + inic_digest(d); + while (status != 2) { + WORD32 d_old[4]; + WORD32 wbuff[16]; + int numbytes = (len-i >= 64) ? 64 : len-i; + /*salva os valores do vetor digest*/ + d_old[0]=d[0]; d_old[1]=d[1]; d_old[2]=d[2]; d_old[3]=d[3]; + status = converte(wbuff, message+i, numbytes, status); + if (status == 2) put_length(wbuff, len); + digest(wbuff, d); + d[0]+=d_old[0]; d[1]+=d_old[1]; d[2]+=d_old[2]; d[3]+=d_old[3]; + i += numbytes; + } + word32tobytes(d, output); +} + diff --git a/src/luamd5/md5.h b/src/luamd5/md5.h new file mode 100644 index 0000000000..5548bddadc --- /dev/null +++ b/src/luamd5/md5.h @@ -0,0 +1,20 @@ +/** +* $Id: md5.h,v 1.2 2006/03/03 15:04:49 tomas Exp $ +* Cryptographic module for Lua. +* @author Roberto Ierusalimschy +*/ + + +#ifndef md5_h +#define md5_h + +#include <lua.h> + + +#define HASHSIZE 16 + +void md5 (const char *message, long len, char *output); +int luaopen_md5_core (lua_State *L); + + +#endif diff --git a/src/luamd5/md5lib.c b/src/luamd5/md5lib.c new file mode 100644 index 0000000000..202903506b --- /dev/null +++ b/src/luamd5/md5lib.c @@ -0,0 +1,203 @@ +/** +* $Id: md5lib.c,v 1.10 2008/05/12 20:51:27 carregal Exp $ +* Cryptographic and Hash functions for Lua +* @author Roberto Ierusalimschy +*/ + + +#include <stdlib.h> +#include <string.h> +#include <time.h> + +#include <lua.h> +#include <lauxlib.h> + +#if ! defined (LUA_VERSION_NUM) || LUA_VERSION_NUM < 501 +#include "compat-5.1.h" +#endif + +#include "md5.h" + + +/** +* Hash function. Returns a hash for a given string. +* @param message: arbitrary binary string. +* @return A 128-bit hash string. +*/ +static int lmd5 (lua_State *L) { + char buff[16]; + size_t l; + const char *message = luaL_checklstring(L, 1, &l); + md5(message, l, buff); + lua_pushlstring(L, buff, 16L); + return 1; +} + + +/** +* X-Or. Does a bit-a-bit exclusive-or of two strings. +* @param s1: arbitrary binary string. +* @param s2: arbitrary binary string with same length as s1. +* @return a binary string with same length as s1 and s2, +* where each bit is the exclusive-or of the corresponding bits in s1-s2. +*/ +static int ex_or (lua_State *L) { + size_t l1, l2; + const char *s1 = luaL_checklstring(L, 1, &l1); + const char *s2 = luaL_checklstring(L, 2, &l2); + luaL_Buffer b; + luaL_argcheck( L, l1 == l2, 2, "lengths must be equal" ); + luaL_buffinit(L, &b); + while (l1--) luaL_putchar(&b, (*s1++)^(*s2++)); + luaL_pushresult(&b); + return 1; +} + + +static void checkseed (lua_State *L) { + if (lua_isnone(L, 3)) { /* no seed? */ + time_t tm = time(NULL); /* for `random' seed */ + lua_pushlstring(L, (char *)&tm, sizeof(tm)); + } +} + + +#define MAXKEY 256 +#define BLOCKSIZE 16 + + + +static int initblock (lua_State *L, const char *seed, int lseed, char *block) { + size_t lkey; + const char *key = luaL_checklstring(L, 2, &lkey); + if (lkey > MAXKEY) + luaL_error(L, "key too long (> %d)", MAXKEY); + memset(block, 0, BLOCKSIZE); + memcpy(block, seed, lseed); + memcpy(block+BLOCKSIZE, key, lkey); + return (int)lkey+BLOCKSIZE; +} + + +static void codestream (lua_State *L, const char *msg, size_t lmsg, + char *block, int lblock) { + luaL_Buffer b; + luaL_buffinit(L, &b); + while (lmsg > 0) { + char code[BLOCKSIZE]; + int i; + md5(block, lblock, code); + for (i=0; i<BLOCKSIZE && lmsg > 0; i++, lmsg--) + code[i] ^= *msg++; + luaL_addlstring(&b, code, i); + memcpy(block, code, i); /* update seed */ + } + luaL_pushresult(&b); +} + + +static void decodestream (lua_State *L, const char *cypher, size_t lcypher, + char *block, int lblock) { + luaL_Buffer b; + luaL_buffinit(L, &b); + while (lcypher > 0) { + char code[BLOCKSIZE]; + int i; + md5(block, lblock, code); /* update seed */ + for (i=0; i<BLOCKSIZE && lcypher > 0; i++, lcypher--) + code[i] ^= *cypher++; + luaL_addlstring(&b, code, i); + memcpy(block, cypher-i, i); + } + luaL_pushresult(&b); +} + + +/** +* Encrypts a string. Uses the hash function md5 in CFB (Cipher-feedback +* mode). +* @param message: arbitrary binary string to be encrypted. +* @param key: arbitrary binary string to be used as a key. +* @param [seed]: optional arbitrary binary string to be used as a seed. +* if no seed is provided, the function uses the result of +* <code>time()</code> as a seed. +* @return The cyphertext (as a binary string). +*/ +static int crypt (lua_State *L) { + size_t lmsg; + const char *msg = luaL_checklstring(L, 1, &lmsg); + size_t lseed; + const char *seed; + int lblock; + char block[BLOCKSIZE+MAXKEY]; + checkseed(L); + seed = luaL_checklstring(L, 3, &lseed); + if (lseed > BLOCKSIZE) + luaL_error(L, "seed too long (> %d)", BLOCKSIZE); + /* put seed and seed length at the beginning of result */ + block[0] = (char)lseed; + memcpy(block+1, seed, lseed); + lua_pushlstring(L, block, lseed+1); /* to concat with result */ + lblock = initblock(L, seed, lseed, block); + codestream(L, msg, lmsg, block, lblock); + lua_concat(L, 2); + return 1; +} + + +/** +* Decrypts a string. For any message, key, and seed, we have that +* <code>decrypt(crypt(msg, key, seed), key) == msg</code>. +* @param cyphertext: message to be decrypted (this must be the result of + a previous call to <code>crypt</code>. +* @param key: arbitrary binary string to be used as a key. +* @return The plaintext. +*/ +static int decrypt (lua_State *L) { + size_t lcyphertext; + const char *cyphertext = luaL_checklstring(L, 1, &lcyphertext); + size_t lseed = cyphertext[0]; + const char *seed = cyphertext+1; + int lblock; + char block[BLOCKSIZE+MAXKEY]; + luaL_argcheck(L, lcyphertext >= lseed+1 && lseed <= BLOCKSIZE, 1, + "invalid cyphered string"); + cyphertext += lseed+1; + lcyphertext -= lseed+1; + lblock = initblock(L, seed, lseed, block); + decodestream(L, cyphertext, lcyphertext, block, lblock); + return 1; +} + + +/* +** Assumes the table is on top of the stack. +*/ +static void set_info (lua_State *L) { + lua_pushliteral (L, "_COPYRIGHT"); + lua_pushliteral (L, "Copyright (C) 2003 PUC-Rio"); + lua_settable (L, -3); + lua_pushliteral (L, "_DESCRIPTION"); + lua_pushliteral (L, "Basic cryptographic facilities"); + lua_settable (L, -3); + lua_pushliteral (L, "_VERSION"); + lua_pushliteral (L, "MD5 1.1.2"); + lua_settable (L, -3); +} + + +static struct luaL_reg md5lib[] = { + {"sum", lmd5}, + {"exor", ex_or}, + {"crypt", crypt}, + {"decrypt", decrypt}, + {NULL, NULL} +}; + + +int luaopen_md5_core (lua_State *L) { + luaL_openlib(L, "md5.core", md5lib, 0); + set_info (L); + return 1; +} + -- GitLab