"Fossies" - the Fresh Open Source Software Archive

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