"Fossies" - the Fresh Open Source Software Archive

Member "libmcrypt-2.5.8/modules/algorithms/rijndael-256.c" (19 Jan 2003, 11788 Bytes) of package /linux/privat/old/libmcrypt-2.5.8.tar.gz:


As a special service "Fossies" has tried to format the requested source page into HTML format using (guessed) C and C++ source code syntax highlighting (style: standard) with prefixed line numbers and code folding option. Alternatively you can here view or download the uninterpreted source code file. For more information about "rijndael-256.c" see the Fossies "Dox" file reference documentation.

    1 /* Rijndael Cipher
    2 
    3    Written by Mike Scott 21st April 1999
    4    Copyright (c) 1999 Mike Scott
    5    See rijndael documentation
    6 
    7    Permission for free direct or derivative use is granted subject 
    8    to compliance with any conditions that the originators of the 
    9    algorithm place on its exploitation.  
   10 
   11    Inspiration from Brian Gladman's implementation is acknowledged.
   12 
   13    Written for clarity, rather than speed.
   14    Full implementation. 
   15    Endian indifferent.
   16 */
   17 
   18 /* modified in order to use the libmcrypt API by Nikos Mavroyanopoulos 
   19  * All modifications are placed under the license of libmcrypt.
   20  */
   21 
   22 /* $Id: rijndael-256.c,v 1.15 2003/01/19 17:48:27 nmav Exp $ */
   23 
   24 #include <libdefs.h>
   25 
   26 #include <mcrypt_modules.h>
   27 #include "rijndael.h"
   28 
   29 #define _mcrypt_set_key rijndael_256_LTX__mcrypt_set_key
   30 #define _mcrypt_encrypt rijndael_256_LTX__mcrypt_encrypt
   31 #define _mcrypt_decrypt rijndael_256_LTX__mcrypt_decrypt
   32 #define _mcrypt_get_size rijndael_256_LTX__mcrypt_get_size
   33 #define _mcrypt_get_block_size rijndael_256_LTX__mcrypt_get_block_size
   34 #define _is_block_algorithm rijndael_256_LTX__is_block_algorithm
   35 #define _mcrypt_get_key_size rijndael_256_LTX__mcrypt_get_key_size
   36 #define _mcrypt_get_supported_key_sizes rijndael_256_LTX__mcrypt_get_supported_key_sizes
   37 #define _mcrypt_get_algorithms_name rijndael_256_LTX__mcrypt_get_algorithms_name
   38 #define _mcrypt_self_test rijndael_256_LTX__mcrypt_self_test
   39 #define _mcrypt_algorithm_version rijndael_256_LTX__mcrypt_algorithm_version
   40 
   41 /* rotates x one bit to the left */
   42 
   43 #define ROTL(x) (((x)>>7)|((x)<<1))
   44 
   45 /* Rotates 32-bit word left by 1, 2 or 3 byte  */
   46 
   47 #define ROTL8(x) (((x)<<8)|((x)>>24))
   48 #define ROTL16(x) (((x)<<16)|((x)>>16))
   49 #define ROTL24(x) (((x)<<24)|((x)>>8))
   50 
   51 /* Fixed Data */
   52 
   53 static byte InCo[4] = { 0xB, 0xD, 0x9, 0xE };   /* Inverse Coefficients */
   54 
   55 static byte fbsub[256];
   56 static byte rbsub[256];
   57 static byte ptab[256], ltab[256];
   58 static word32 ftable[256];
   59 static word32 rtable[256];
   60 static word32 rco[30];
   61 static int tables_ok = 0;
   62 
   63 /* Parameter-dependent data */
   64 
   65 /* in "rijndael.h" */
   66 
   67 static word32 pack(byte * b)
   68 {               /* pack bytes into a 32-bit Word */
   69     return ((word32) b[3] << 24) | ((word32) b[2] << 16) | ((word32)
   70                                 b[1] << 8)
   71         | (word32) b[0];
   72 }
   73 
   74 static void unpack(word32 a, byte * b)
   75 {               /* unpack bytes from a word */
   76     b[0] = (byte) a;
   77     b[1] = (byte) (a >> 8);
   78     b[2] = (byte) (a >> 16);
   79     b[3] = (byte) (a >> 24);
   80 }
   81 
   82 static byte xtime(byte a)
   83 {
   84     byte b;
   85     if (a & 0x80)
   86         b = 0x1B;
   87     else
   88         b = 0;
   89     a <<= 1;
   90     a ^= b;
   91     return a;
   92 }
   93 
   94 static byte bmul(byte x, byte y)
   95 {               /* x.y= AntiLog(Log(x) + Log(y)) */
   96     if (x && y)
   97         return ptab[(ltab[x] + ltab[y]) % 255];
   98     else
   99         return 0;
  100 }
  101 
  102 static word32 SubByte(word32 a)
  103 {
  104     byte b[4];
  105     unpack(a, b);
  106     b[0] = fbsub[b[0]];
  107     b[1] = fbsub[b[1]];
  108     b[2] = fbsub[b[2]];
  109     b[3] = fbsub[b[3]];
  110     return pack(b);
  111 }
  112 
  113 static byte product(word32 x, word32 y)
  114 {               /* dot product of two 4-byte arrays */
  115     byte xb[4], yb[4];
  116     unpack(x, xb);
  117     unpack(y, yb);
  118     return bmul(xb[0], yb[0]) ^ bmul(xb[1], yb[1]) ^ bmul(xb[2],
  119                                   yb[2]) ^
  120         bmul(xb[3], yb[3]);
  121 }
  122 
  123 static word32 InvMixCol(word32 x)
  124 {               /* matrix Multiplication */
  125     word32 y, m;
  126     byte b[4];
  127 
  128     m = pack(InCo);
  129     b[3] = product(m, x);
  130     m = ROTL24(m);
  131     b[2] = product(m, x);
  132     m = ROTL24(m);
  133     b[1] = product(m, x);
  134     m = ROTL24(m);
  135     b[0] = product(m, x);
  136     y = pack(b);
  137     return y;
  138 }
  139 
  140 static byte ByteSub(byte x)
  141 {
  142     byte y = ptab[255 - ltab[x]];   /* multiplicative inverse */
  143     x = y;
  144     x = ROTL(x);
  145     y ^= x;
  146     x = ROTL(x);
  147     y ^= x;
  148     x = ROTL(x);
  149     y ^= x;
  150     x = ROTL(x);
  151     y ^= x;
  152     y ^= 0x63;
  153     return y;
  154 }
  155 
  156 static void _mcrypt_rijndael_gentables(void)
  157 {               /* generate tables */
  158     int i;
  159     byte y, b[4];
  160 
  161     /* use 3 as primitive root to generate power and log tables */
  162 
  163     ltab[0] = 0;
  164     ptab[0] = 1;
  165     ltab[1] = 0;
  166     ptab[1] = 3;
  167     ltab[3] = 1;
  168     for (i = 2; i < 256; i++) {
  169         ptab[i] = ptab[i - 1] ^ xtime(ptab[i - 1]);
  170         ltab[ptab[i]] = i;
  171     }
  172 
  173     /* affine transformation:- each bit is xored with itself shifted one bit */
  174 
  175     fbsub[0] = 0x63;
  176     rbsub[0x63] = 0;
  177     for (i = 1; i < 256; i++) {
  178         y = ByteSub((byte) i);
  179         fbsub[i] = y;
  180         rbsub[y] = i;
  181     }
  182 
  183     for (i = 0, y = 1; i < 30; i++) {
  184         rco[i] = y;
  185         y = xtime(y);
  186     }
  187 
  188     /* calculate forward and reverse tables */
  189     for (i = 0; i < 256; i++) {
  190         y = fbsub[i];
  191         b[3] = y ^ xtime(y);
  192         b[2] = y;
  193         b[1] = y;
  194         b[0] = xtime(y);
  195         ftable[i] = pack(b);
  196 
  197         y = rbsub[i];
  198         b[3] = bmul(InCo[0], y);
  199         b[2] = bmul(InCo[1], y);
  200         b[1] = bmul(InCo[2], y);
  201         b[0] = bmul(InCo[3], y);
  202         rtable[i] = pack(b);
  203     }
  204 }
  205 
  206 WIN32DLL_DEFINE int _mcrypt_set_key(RI * rinst, byte * key, int nk)
  207 {               /* blocksize=32*nb bits. Key=32*nk bits */
  208     /* currently nb,bk = 4, 6 or 8          */
  209     /* key comes as 4*rinst->Nk bytes              */
  210     /* Key Scheduler. Create expanded encryption key */
  211     int nb = 8;     /* 256 block size */
  212     int i, j, k, m, N;
  213     int C1, C2, C3;
  214     word32 CipherKey[8];
  215 
  216     nk /= 4;
  217 
  218     if (tables_ok == 0) {
  219         _mcrypt_rijndael_gentables();
  220         tables_ok = 1;
  221     }
  222 
  223     rinst->Nb = nb;
  224     rinst->Nk = nk;
  225 
  226     /* rinst->Nr is number of rounds */
  227     if (rinst->Nb >= rinst->Nk)
  228         rinst->Nr = 6 + rinst->Nb;
  229     else
  230         rinst->Nr = 6 + rinst->Nk;
  231 
  232     C1 = 1;
  233     if (rinst->Nb < 8) {
  234         C2 = 2;
  235         C3 = 3;
  236     } else {
  237         C2 = 3;
  238         C3 = 4;
  239     }
  240 
  241     /* pre-calculate forward and reverse increments */
  242     for (m = j = 0; j < nb; j++, m += 3) {
  243         rinst->fi[m] = (j + C1) % nb;
  244         rinst->fi[m + 1] = (j + C2) % nb;
  245         rinst->fi[m + 2] = (j + C3) % nb;
  246         rinst->ri[m] = (nb + j - C1) % nb;
  247         rinst->ri[m + 1] = (nb + j - C2) % nb;
  248         rinst->ri[m + 2] = (nb + j - C3) % nb;
  249     }
  250 
  251     N = rinst->Nb * (rinst->Nr + 1);
  252 
  253     for (i = j = 0; i < rinst->Nk; i++, j += 4) {
  254         CipherKey[i] = pack(&key[j]);
  255     }
  256     for (i = 0; i < rinst->Nk; i++)
  257         rinst->fkey[i] = CipherKey[i];
  258     for (j = rinst->Nk, k = 0; j < N; j += rinst->Nk, k++) {
  259         rinst->fkey[j] =
  260             rinst->fkey[j -
  261                 rinst->Nk] ^ SubByte(ROTL24(rinst->
  262                                 fkey[j -
  263                                  1])) ^
  264             rco[k];
  265         if (rinst->Nk <= 6) {
  266             for (i = 1; i < rinst->Nk && (i + j) < N; i++)
  267                 rinst->fkey[i + j] =
  268                     rinst->fkey[i + j -
  269                         rinst->Nk] ^ rinst->
  270                     fkey[i + j - 1];
  271         } else {
  272             for (i = 1; i < 4 && (i + j) < N; i++)
  273                 rinst->fkey[i + j] =
  274                     rinst->fkey[i + j -
  275                         rinst->Nk] ^ rinst->
  276                     fkey[i + j - 1];
  277             if ((j + 4) < N)
  278                 rinst->fkey[j + 4] =
  279                     rinst->fkey[j + 4 -
  280                         rinst->
  281                         Nk] ^ SubByte(rinst->
  282                                   fkey[j + 3]);
  283             for (i = 5; i < rinst->Nk && (i + j) < N; i++)
  284                 rinst->fkey[i + j] =
  285                     rinst->fkey[i + j -
  286                         rinst->Nk] ^ rinst->
  287                     fkey[i + j - 1];
  288         }
  289 
  290     }
  291 
  292     /* now for the expanded decrypt key in reverse order */
  293 
  294     for (j = 0; j < rinst->Nb; j++)
  295         rinst->rkey[j + N - rinst->Nb] = rinst->fkey[j];
  296     for (i = rinst->Nb; i < N - rinst->Nb; i += rinst->Nb) {
  297         k = N - rinst->Nb - i;
  298         for (j = 0; j < rinst->Nb; j++)
  299             rinst->rkey[k + j] = InvMixCol(rinst->fkey[i + j]);
  300     }
  301     for (j = N - rinst->Nb; j < N; j++)
  302         rinst->rkey[j - N + rinst->Nb] = rinst->fkey[j];
  303     return 0;
  304 }
  305 
  306 
  307 /* There is an obvious time/space trade-off possible here.     *
  308  * Instead of just one ftable[], I could have 4, the other     *
  309  * 3 pre-rotated to save the ROTL8, ROTL16 and ROTL24 overhead */
  310 
  311 WIN32DLL_DEFINE void _mcrypt_encrypt(RI * rinst, byte * buff)
  312 {
  313     int i, j, k, m;
  314     word32 a[8], b[8], *x, *y, *t;
  315 
  316     for (i = j = 0; i < rinst->Nb; i++, j += 4) {
  317         a[i] = pack(&buff[j]);
  318         a[i] ^= rinst->fkey[i];
  319     }
  320     k = rinst->Nb;
  321     x = a;
  322     y = b;
  323 
  324 /* State alternates between a and b */
  325     for (i = 1; i < rinst->Nr; i++) {   /* rinst->Nr is number of rounds. May be odd. */
  326 
  327 /* if rinst->Nb is fixed - unroll this next 
  328    loop and hard-code in the values of fi[]  */
  329 
  330         for (m = j = 0; j < rinst->Nb; j++, m += 3) {   /* deal with each 32-bit element of the State */
  331             /* This is the time-critical bit */
  332             y[j] = rinst->fkey[k++] ^ ftable[(byte) x[j]] ^
  333                 ROTL8(ftable[(byte) (x[rinst->fi[m]] >> 8)]) ^
  334                 ROTL16(ftable
  335                    [(byte) (x[rinst->fi[m + 1]] >> 16)]) ^
  336                 ROTL24(ftable[x[rinst->fi[m + 2]] >> 24]);
  337         }
  338         t = x;
  339         x = y;
  340         y = t;      /* swap pointers */
  341     }
  342 
  343 /* Last Round - unroll if possible */
  344     for (m = j = 0; j < rinst->Nb; j++, m += 3) {
  345         y[j] = rinst->fkey[k++] ^ (word32) fbsub[(byte) x[j]] ^
  346             ROTL8((word32) fbsub[(byte) (x[rinst->fi[m]] >> 8)]) ^
  347             ROTL16((word32)
  348                fbsub[(byte) (x[rinst->fi[m + 1]] >> 16)]) ^
  349             ROTL24((word32) fbsub[x[rinst->fi[m + 2]] >> 24]);
  350     }
  351     for (i = j = 0; i < rinst->Nb; i++, j += 4) {
  352         unpack(y[i], &buff[j]);
  353         x[i] = y[i] = 0;    /* clean up stack */
  354     }
  355     return;
  356 }
  357 
  358 WIN32DLL_DEFINE void _mcrypt_decrypt(RI * rinst, byte * buff)
  359 {
  360     int i, j, k, m;
  361     word32 a[8], b[8], *x, *y, *t;
  362 
  363     for (i = j = 0; i < rinst->Nb; i++, j += 4) {
  364         a[i] = pack(&buff[j]);
  365         a[i] ^= rinst->rkey[i];
  366     }
  367     k = rinst->Nb;
  368     x = a;
  369     y = b;
  370 
  371 /* State alternates between a and b */
  372     for (i = 1; i < rinst->Nr; i++) {   /* rinst->Nr is number of rounds. May be odd. */
  373 
  374 /* if rinst->Nb is fixed - unroll this next 
  375    loop and hard-code in the values of ri[]  */
  376 
  377         for (m = j = 0; j < rinst->Nb; j++, m += 3) {   /* This is the time-critical bit */
  378             y[j] = rinst->rkey[k++] ^ rtable[(byte) x[j]] ^
  379                 ROTL8(rtable[(byte) (x[rinst->ri[m]] >> 8)]) ^
  380                 ROTL16(rtable
  381                    [(byte) (x[rinst->ri[m + 1]] >> 16)]) ^
  382                 ROTL24(rtable[x[rinst->ri[m + 2]] >> 24]);
  383         }
  384         t = x;
  385         x = y;
  386         y = t;      /* swap pointers */
  387     }
  388 
  389 /* Last Round - unroll if possible */
  390     for (m = j = 0; j < rinst->Nb; j++, m += 3) {
  391         y[j] = rinst->rkey[k++] ^ (word32) rbsub[(byte) x[j]] ^
  392             ROTL8((word32) rbsub[(byte) (x[rinst->ri[m]] >> 8)]) ^
  393             ROTL16((word32)
  394                rbsub[(byte) (x[rinst->ri[m + 1]] >> 16)]) ^
  395             ROTL24((word32) rbsub[x[rinst->ri[m + 2]] >> 24]);
  396     }
  397     for (i = j = 0; i < rinst->Nb; i++, j += 4) {
  398         unpack(y[i], &buff[j]);
  399         x[i] = y[i] = 0;    /* clean up stack */
  400     }
  401     return;
  402 }
  403 
  404 
  405 WIN32DLL_DEFINE int _mcrypt_get_size()
  406 {
  407     return sizeof(RI);
  408 }
  409 
  410 WIN32DLL_DEFINE int _mcrypt_get_block_size()
  411 {
  412     return 32;
  413 }
  414 
  415 WIN32DLL_DEFINE int _is_block_algorithm()
  416 {
  417     return 1;
  418 }
  419 
  420 WIN32DLL_DEFINE int _mcrypt_get_key_size()
  421 {
  422     return 32;
  423 }
  424 
  425 static const int key_sizes[] = { 16, 24, 32 };
  426 WIN32DLL_DEFINE const int *_mcrypt_get_supported_key_sizes(int *len)
  427 {
  428     *len = sizeof(key_sizes)/sizeof(int);
  429     return key_sizes;
  430 
  431 }
  432 WIN32DLL_DEFINE char *_mcrypt_get_algorithms_name()
  433 {
  434 return "Rijndael-256";
  435 }
  436 
  437 #define CIPHER "45af6c269326fd935edd24733cff74fc1aa358841a6cd80b79f242d983f8ff2e"
  438 
  439 WIN32DLL_DEFINE int _mcrypt_self_test()
  440 {
  441     char *keyword;
  442     unsigned char plaintext[32];
  443     unsigned char ciphertext[32];
  444     int blocksize = _mcrypt_get_block_size(), j;
  445     void *key;
  446     unsigned char cipher_tmp[200];
  447 
  448     keyword = calloc(1, _mcrypt_get_key_size());
  449     if (keyword == NULL)
  450         return -1;
  451 
  452     for (j = 0; j < _mcrypt_get_key_size(); j++) {
  453         keyword[j] = ((j * 2 + 10) % 256);
  454     }
  455 
  456     for (j = 0; j < blocksize; j++) {
  457         plaintext[j] = j % 256;
  458     }
  459     key = malloc(_mcrypt_get_size());
  460     if (key == NULL) {
  461         free(keyword);
  462         return -1;
  463     }
  464     memcpy(ciphertext, plaintext, blocksize);
  465 
  466     _mcrypt_set_key(key, (void *) keyword, _mcrypt_get_key_size());
  467     free(keyword);
  468 
  469     _mcrypt_encrypt(key, (void *) ciphertext);
  470 
  471     for (j = 0; j < blocksize; j++) {
  472         sprintf(&((char *) cipher_tmp)[2 * j], "%.2x",
  473             ciphertext[j]);
  474     }
  475 
  476     if (strcmp((char *) cipher_tmp, CIPHER) != 0) {
  477         printf("failed compatibility\n");
  478         printf("Expected: %s\nGot: %s\n", CIPHER,
  479                (char *) cipher_tmp);
  480         free(key);
  481         return -1;
  482     }
  483     _mcrypt_decrypt(key, (void *) ciphertext);
  484     free(key);
  485 
  486     if (strcmp(ciphertext, plaintext) != 0) {
  487         printf("failed internally\n");
  488         return -1;
  489     }
  490 
  491     return 0;
  492 }
  493 
  494 WIN32DLL_DEFINE word32 _mcrypt_algorithm_version()
  495 {
  496     return 20010801;
  497 }
  498 
  499 #ifdef WIN32
  500 # ifdef USE_LTDL
  501 WIN32DLL_DEFINE int main (void)
  502 {
  503        /* empty main function to avoid linker error (see cygwin FAQ) */
  504 }
  505 # endif
  506 #endif