"Fossies" - the Fresh Open Source Software Archive

Member "libmcrypt-2.5.8/modules/algorithms/panama.c" (19 Jan 2003, 19854 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 "panama.c" see the Fossies "Dox" file reference documentation.

    1 /* panama_x.c */
    2 
    3 /* $Id: panama.c,v 1.21 2003/01/19 17:48:27 nmav Exp $ */
    4 
    5 /* daemen.j@protonworld.com */
    6 /**************************************************************************+
    7 *
    8 *  PANAMA high-performance reference C-code, based on the description in 
    9 *  the paper 'Fast Hashing and Stream Encryption with PANAMA', presented 
   10 *  at the Fast Software Encryption Workshop, Paris, 1998, see "Fast 
   11 *  Software Encryption - 5th International Workshop, FSE'98", edited by 
   12 *  Serge Vaudenay, LNCS-1372, Springer-Verlag, 1998, pp 60-74, also 
   13 *  available on-line at http://standard.pictel.com/ftp/research/security
   14 *
   15 *  Algorithm design by Joan Daemen and Craig Clapp
   16 *
   17 *  panama_x.c  -  Core routines for the Panama stream/hash module, this 
   18 *                 exportable version excludes an encryption routine.
   19 *
   20 *
   21 *  History:
   22 *
   23 *  29-Oct-98  Craig Clapp  Implemention for Dr. Dobbs, Dec. 1998 issue, 
   24 *                          based on earlier performance-benchmark code.
   25 *
   26 *
   27 *  Notes:  This code is supplied for the purposes of evaluating the 
   28 *          performance of the Panama stream/hash module and as a 
   29 *          reference implementation for generating test vectors for 
   30 *          compatibility / interoperability verification.
   31 *
   32 *
   33 +**************************************************************************/
   34 
   35 /* modified in order to use the libmcrypt API by Nikos Mavroyanopoulos 
   36  * All modifications are placed under the license of libmcrypt.
   37  */
   38 
   39 #include <libdefs.h>
   40 
   41 #include <mcrypt_modules.h>
   42 #include "panama.h"
   43 
   44 
   45 #define _mcrypt_set_key panama_LTX__mcrypt_set_key
   46 #define _mcrypt_encrypt panama_LTX__mcrypt_encrypt
   47 #define _mcrypt_decrypt panama_LTX__mcrypt_decrypt
   48 #define _mcrypt_get_size panama_LTX__mcrypt_get_size
   49 #define _mcrypt_get_block_size panama_LTX__mcrypt_get_block_size
   50 #define _is_block_algorithm panama_LTX__is_block_algorithm
   51 #define _mcrypt_get_key_size panama_LTX__mcrypt_get_key_size
   52 #define _mcrypt_get_algo_iv_size panama_LTX__mcrypt_get_algo_iv_size
   53 #define _mcrypt_get_supported_key_sizes panama_LTX__mcrypt_get_supported_key_sizes
   54 #define _mcrypt_get_algorithms_name panama_LTX__mcrypt_get_algorithms_name
   55 #define _mcrypt_self_test panama_LTX__mcrypt_self_test
   56 #define _mcrypt_algorithm_version panama_LTX__mcrypt_algorithm_version
   57 
   58 /**************************************************************************+
   59 *                         Panama internal routines                         *
   60 +**************************************************************************/
   61 
   62 /* tau, rotate  word 'a' to the left by rol_bits bit positions */
   63 
   64 #define tau(a, rol_bits)  ROTL32(a, rol_bits)
   65 
   66 /**************************************************************************/
   67 
   68 /* move state between memory and local registers */
   69 
   70 #define READ_STATE_i(i)   state_##i = state->word[i]
   71 #define WRITE_STATE_i(i)  state->word[i] = state_##i
   72 
   73 
   74 #define READ_STATE    \
   75                       \
   76     READ_STATE_i(0);  \
   77     READ_STATE_i(1);  \
   78     READ_STATE_i(2);  \
   79     READ_STATE_i(3);  \
   80     READ_STATE_i(4);  \
   81     READ_STATE_i(5);  \
   82     READ_STATE_i(6);  \
   83     READ_STATE_i(7);  \
   84     READ_STATE_i(8);  \
   85     READ_STATE_i(9);  \
   86     READ_STATE_i(10); \
   87     READ_STATE_i(11); \
   88     READ_STATE_i(12); \
   89     READ_STATE_i(13); \
   90     READ_STATE_i(14); \
   91     READ_STATE_i(15); \
   92     READ_STATE_i(16)
   93 
   94 
   95 #define WRITE_STATE    \
   96                        \
   97     WRITE_STATE_i(0);  \
   98     WRITE_STATE_i(1);  \
   99     WRITE_STATE_i(2);  \
  100     WRITE_STATE_i(3);  \
  101     WRITE_STATE_i(4);  \
  102     WRITE_STATE_i(5);  \
  103     WRITE_STATE_i(6);  \
  104     WRITE_STATE_i(7);  \
  105     WRITE_STATE_i(8);  \
  106     WRITE_STATE_i(9);  \
  107     WRITE_STATE_i(10); \
  108     WRITE_STATE_i(11); \
  109     WRITE_STATE_i(12); \
  110     WRITE_STATE_i(13); \
  111     WRITE_STATE_i(14); \
  112     WRITE_STATE_i(15); \
  113     WRITE_STATE_i(16)
  114 
  115 /**************************************************************************/
  116 
  117 /* gamma, shift-invariant transformation a[i] XOR (a[i+1] OR NOT a[i+2]) */
  118 
  119 #define gamma_in_(i)   state_##i
  120 #define gamma_out_(i)  gamma_##i
  121 
  122 #define GAMMA_i(i, i_plus_1, i_plus_2)  \
  123                                         \
  124     gamma_out_(i) = gamma_in_(i) ^ (gamma_in_(i_plus_1) | ~gamma_in_(i_plus_2))
  125 
  126 
  127 #define GAMMA            \
  128                          \
  129     GAMMA_i( 0,  1,  2); \
  130     GAMMA_i( 1,  2,  3); \
  131     GAMMA_i( 2,  3,  4); \
  132     GAMMA_i( 3,  4,  5); \
  133     GAMMA_i( 4,  5,  6); \
  134     GAMMA_i( 5,  6,  7); \
  135     GAMMA_i( 6,  7,  8); \
  136     GAMMA_i( 7,  8,  9); \
  137     GAMMA_i( 8,  9, 10); \
  138     GAMMA_i( 9, 10, 11); \
  139     GAMMA_i(10, 11, 12); \
  140     GAMMA_i(11, 12, 13); \
  141     GAMMA_i(12, 13, 14); \
  142     GAMMA_i(13, 14, 15); \
  143     GAMMA_i(14, 15, 16); \
  144     GAMMA_i(15, 16,  0); \
  145     GAMMA_i(16,  0,  1)
  146 
  147 /**************************************************************************/
  148 
  149 /* pi, permute and cyclicly rotate the state words */
  150 
  151 #define pi_in_(i)   gamma_##i
  152 #define pi_out_(i)  pi_##i
  153 
  154 #define PI_i(i, j, k)  pi_out_(i) = tau(pi_in_(j), k)
  155 
  156 
  157 #define PI                  \
  158                             \
  159     pi_out_(0) = pi_in_(0); \
  160     PI_i( 1,  7,  1);       \
  161     PI_i( 2, 14,  3);       \
  162     PI_i( 3,  4,  6);       \
  163     PI_i( 4, 11, 10);       \
  164     PI_i( 5,  1, 15);       \
  165     PI_i( 6,  8, 21);       \
  166     PI_i( 7, 15, 28);       \
  167     PI_i( 8,  5,  4);       \
  168     PI_i( 9, 12, 13);       \
  169     PI_i(10,  2, 23);       \
  170     PI_i(11,  9,  2);       \
  171     PI_i(12, 16, 14);       \
  172     PI_i(13,  6, 27);       \
  173     PI_i(14, 13,  9);       \
  174     PI_i(15,  3, 24);       \
  175     PI_i(16, 10,  8)
  176 
  177 /**************************************************************************/
  178 
  179 /* theta, shift-invariant transformation a[i] XOR a[i+1] XOR a[i+4] */
  180 
  181 #define theta_in_(i)   pi_##i
  182 #define theta_out_(i)  theta_##i
  183 
  184 #define THETA_i(i, i_plus_1, i_plus_4)  \
  185                                         \
  186     theta_out_(i) = theta_in_(i) ^ theta_in_(i_plus_1) ^ theta_in_(i_plus_4)
  187 
  188 
  189 #define THETA            \
  190                          \
  191     THETA_i( 0,  1,  4); \
  192     THETA_i( 1,  2,  5); \
  193     THETA_i( 2,  3,  6); \
  194     THETA_i( 3,  4,  7); \
  195     THETA_i( 4,  5,  8); \
  196     THETA_i( 5,  6,  9); \
  197     THETA_i( 6,  7, 10); \
  198     THETA_i( 7,  8, 11); \
  199     THETA_i( 8,  9, 12); \
  200     THETA_i( 9, 10, 13); \
  201     THETA_i(10, 11, 14); \
  202     THETA_i(11, 12, 15); \
  203     THETA_i(12, 13, 16); \
  204     THETA_i(13, 14,  0); \
  205     THETA_i(14, 15,  1); \
  206     THETA_i(15, 16,  2); \
  207     THETA_i(16,  0,  3)
  208 
  209 /**************************************************************************/
  210 
  211 /* sigma, merge two buffer stages with current state */
  212 
  213 #define sigma_in_(i)   theta_##i
  214 #define sigma_out_(i)  state_##i
  215 
  216 #define SIGMA_L_i(i)  sigma_out_(i) = sigma_in_(i) ^ L->word[i-1]
  217 #define SIGMA_B_i(i)  sigma_out_(i) = sigma_in_(i) ^ b->word[i-9]
  218 
  219 
  220 #define SIGMA      \
  221                    \
  222     sigma_out_(0) = sigma_in_(0) ^ 0x00000001L; \
  223                    \
  224     SIGMA_L_i(1);  \
  225     SIGMA_L_i(2);  \
  226     SIGMA_L_i(3);  \
  227     SIGMA_L_i(4);  \
  228     SIGMA_L_i(5);  \
  229     SIGMA_L_i(6);  \
  230     SIGMA_L_i(7);  \
  231     SIGMA_L_i(8);  \
  232                    \
  233     SIGMA_B_i(9);  \
  234     SIGMA_B_i(10); \
  235     SIGMA_B_i(11); \
  236     SIGMA_B_i(12); \
  237     SIGMA_B_i(13); \
  238     SIGMA_B_i(14); \
  239     SIGMA_B_i(15); \
  240     SIGMA_B_i(16)
  241 
  242 /**************************************************************************/
  243 
  244 /* lambda, update the 256-bit wide by 32-stage LFSR buffer */
  245 
  246 #define LAMBDA_25_i(i)  \
  247   ptap_25->word[i] = ptap_25->word[i] ^ ptap_0->word[(i+2) & (PAN_STAGE_SIZE-1)]
  248 
  249 #define LAMBDA_0_i(i, source)  ptap_0->word[i] = source ^ ptap_0->word[i]
  250 
  251 
  252 #define LAMBDA_25_UPDATE \
  253                          \
  254     LAMBDA_25_i(0);      \
  255     LAMBDA_25_i(1);      \
  256     LAMBDA_25_i(2);      \
  257     LAMBDA_25_i(3);      \
  258     LAMBDA_25_i(4);      \
  259     LAMBDA_25_i(5);      \
  260     LAMBDA_25_i(6);      \
  261     LAMBDA_25_i(7)
  262 
  263 #define LAMBDA_0_PULL       \
  264                             \
  265     LAMBDA_0_i(0, state_1); \
  266     LAMBDA_0_i(1, state_2); \
  267     LAMBDA_0_i(2, state_3); \
  268     LAMBDA_0_i(3, state_4); \
  269     LAMBDA_0_i(4, state_5); \
  270     LAMBDA_0_i(5, state_6); \
  271     LAMBDA_0_i(6, state_7); \
  272     LAMBDA_0_i(7, state_8)
  273 
  274 #define LAMBDA_0_PUSH          \
  275                                \
  276     LAMBDA_0_i(0, L->word[0]); \
  277     LAMBDA_0_i(1, L->word[1]); \
  278     LAMBDA_0_i(2, L->word[2]); \
  279     LAMBDA_0_i(3, L->word[3]); \
  280     LAMBDA_0_i(4, L->word[4]); \
  281     LAMBDA_0_i(5, L->word[5]); \
  282     LAMBDA_0_i(6, L->word[6]); \
  283     LAMBDA_0_i(7, L->word[7])
  284 
  285 /* avoid temporary register for tap 31 by finishing updating tap 25 before updating tap 0 */
  286 #define LAMBDA_PULL   \
  287     LAMBDA_25_UPDATE; \
  288     LAMBDA_0_PULL
  289 
  290 #define LAMBDA_PUSH   \
  291     LAMBDA_25_UPDATE; \
  292     LAMBDA_0_PUSH
  293 
  294 /**************************************************************************/
  295 
  296 #define regs(i)  state_##i, gamma_##i, pi_##i, theta_##i
  297 
  298 /**************************************************************************/
  299 
  300 
  301 
  302 
  303 /**************************************************************************+
  304 *                         Panama external routines                         *
  305 +**************************************************************************/
  306 
  307 
  308 /**************************************************************************+
  309 *
  310 *  pan_pull() - Performs multiple iterations of the Panama 'Pull' operation.
  311 *               The input and output arrays are treated as integer multiples 
  312 *               of Panama's natural 256-bit block size.
  313 *
  314 *               Input and output arrays may be disjoint or coincident but 
  315 *               may not be overlapped if offset from one another.
  316 *
  317 *               If 'In' is a NULL pointer then output is taken direct from 
  318 *               the state machine (used for hash output). If 'Out' is a NULL 
  319 *               pointer then a dummy 'Pull' is performed. Otherwise 'In' is 
  320 *               XOR combined with the state machine to produce 'Out' 
  321 *               (used for stream encryption / decryption).
  322 *
  323 +**************************************************************************/
  324 
  325 static void pan_pull(word32 * restrict In,  /* input array                   */
  326           word32 * restrict Out,    /* output array                  */
  327           word32 pan_blocks,    /* number of blocks to be Pulled */
  328           PAN_BUFFER * restrict buffer, /* LFSR buffer                   */
  329           PAN_STATE * restrict state)
  330 {               /* 17-word finite-state machine  */
  331     int i;
  332 
  333     word32 regs(0), regs(1), regs(2), regs(3), regs(4);
  334     word32 regs(5), regs(6), regs(7), regs(8), regs(9);
  335     word32 regs(10), regs(11), regs(12), regs(13), regs(14);
  336     word32 regs(15), regs(16);
  337 
  338     word32 tap_0;
  339     PAN_STAGE *restrict ptap_0, *restrict ptap_25;
  340     PAN_STAGE *restrict L, *restrict b;
  341 
  342     /* configure routine according to which PULL mode is intended */
  343     static word32 null_in[PAN_STAGE_SIZE] = { 0, 0, 0, 0, 0, 0, 0, 0 };
  344     word32 dummy_out[PAN_STAGE_SIZE];
  345     word32 in_step, out_step;
  346 
  347     in_step = out_step = PAN_STAGE_SIZE;
  348 
  349     if (In == NULL || Out == NULL) {
  350         In = null_in;
  351         in_step = 0;
  352     }
  353 
  354     if (Out == NULL) {
  355         Out = dummy_out;
  356         out_step = 0;
  357     }
  358 
  359     /* copy buffer pointers and state to registers */
  360     tap_0 = buffer->tap_0;
  361     READ_STATE;
  362 
  363     /* rho, cascade of state update operations */
  364 
  365     for (i = 0; i < pan_blocks; i++) {
  366         /* apply state output to crypto buffer */
  367         Out[0] = In[0] ^ gamma_in_(9);
  368         Out[1] = In[1] ^ gamma_in_(10);
  369         Out[2] = In[2] ^ gamma_in_(11);
  370         Out[3] = In[3] ^ gamma_in_(12);
  371         Out[4] = In[4] ^ gamma_in_(13);
  372         Out[5] = In[5] ^ gamma_in_(14);
  373         Out[6] = In[6] ^ gamma_in_(15);
  374         Out[7] = In[7] ^ gamma_in_(16);
  375 
  376         Out += out_step;
  377         In += in_step;
  378 
  379         GAMMA;      /* perform non-linearity stage */
  380 
  381         PI;     /* perform bit-dispersion stage */
  382 
  383         THETA;      /* perform diffusion stage */
  384 
  385         /* calculate pointers to taps 4 and 16 for sigma based on current position of tap 0 */
  386         L = &buffer->stage[(tap_0 + 4) & (PAN_STAGES - 1)];
  387         b = &buffer->stage[(tap_0 + 16) & (PAN_STAGES - 1)];
  388 
  389         /* move tap_0 left by one stage, equivalent to shifting LFSR one stage right */
  390         tap_0 = (tap_0 - 1) & (PAN_STAGES - 1);
  391 
  392         /* set tap pointers for use by lambda */
  393         ptap_0 = &buffer->stage[tap_0];
  394         ptap_25 = &buffer->stage[(tap_0 + 25) & (PAN_STAGES - 1)];
  395 
  396         LAMBDA_PULL;    /* update the LFSR buffer */
  397 
  398         /* postpone sigma until after lambda in order to avoid extra temporaries for feedback path */
  399         /* note that sigma gets to use the old positions of taps 4 and 16 */
  400 
  401         SIGMA;      /* perform buffer injection stage */
  402     }
  403 
  404     /* write buffer pointer and state back to memory */
  405     buffer->tap_0 = tap_0;
  406     WRITE_STATE;
  407 }
  408 
  409 
  410 /**************************************************************************+
  411 *
  412 *  pan_push() - Performs multiple iterations of the Panama 'Push' operation.
  413 *               The input array is treated as an integer multiple of the 
  414 *               256-bit blocks which are Panama's natural input size.
  415 *
  416 +**************************************************************************/
  417 
  418 static void pan_push(word32 * restrict In,  /* input array                   */
  419           word32 pan_blocks,    /* number of blocks to be Pushed */
  420           PAN_BUFFER * restrict buffer, /* LFSR buffer                   */
  421           PAN_STATE * restrict state)
  422 {               /* 17-word finite-state machine  */
  423     int i;
  424 
  425     word32 regs(0), regs(1), regs(2), regs(3), regs(4);
  426     word32 regs(5), regs(6), regs(7), regs(8), regs(9);
  427     word32 regs(10), regs(11), regs(12), regs(13), regs(14);
  428     word32 regs(15), regs(16);
  429 
  430     word32 tap_0;
  431     PAN_STAGE *restrict ptap_0, *restrict ptap_25;
  432     PAN_STAGE *restrict L, *restrict b;
  433 
  434     /* copy buffer pointers and state to registers */
  435     tap_0 = buffer->tap_0;
  436     READ_STATE;
  437 
  438 /*  assert((word32 *) ((PAN_STAGE *) In) == In); */
  439     L = (PAN_STAGE *) In;   /* we assume pointer to input buffer is compatible with pointer to PAN_STAGE */
  440 
  441 #ifdef WORDS_BIGENDIAN
  442     if (L != NULL)
  443         for (i = 0; i < PAN_STAGE_SIZE; i++) {
  444             L->word[i] = byteswap32(L->word[i]);
  445         }
  446 #endif
  447 
  448     /* rho, cascade of state update operations */
  449 
  450     for (i = 0; i < pan_blocks; i++) {
  451         GAMMA;      /* perform non-linearity stage */
  452 
  453         PI;     /* perform bit-dispersion stage */
  454 
  455         THETA;      /* perform diffusion stage */
  456 
  457 
  458         /* calculate pointer to tap 16 for sigma based on current position of tap 0 */
  459         b = &buffer->stage[(tap_0 + 16) & (PAN_STAGES - 1)];
  460 
  461         /* move tap_0 left by one stage, equivalent to shifting LFSR one stage right */
  462         tap_0 = (tap_0 - 1) & (PAN_STAGES - 1);
  463 
  464         /* set tap pointers for use by lambda */
  465         ptap_0 = &buffer->stage[tap_0];
  466         ptap_25 = &buffer->stage[(tap_0 + 25) & (PAN_STAGES - 1)];
  467 
  468         LAMBDA_PUSH;    /* update the LFSR buffer */
  469 
  470         /* postpone sigma until after lambda in order to avoid extra temporaries for feedback path */
  471         /* note that sigma gets to use the old positions of taps 4 and 16 */
  472 
  473         SIGMA;      /* perform buffer injection stage */
  474 
  475         L++;        /* In += PAN_STAGE_SIZE; */
  476     }
  477 
  478     /* write buffer pointer and state back to memory */
  479     buffer->tap_0 = tap_0;
  480     WRITE_STATE;
  481 
  482 }
  483 
  484 
  485 /**************************************************************************+
  486 *
  487 *  pan_reset() - Initializes an LFSR buffer and Panama state machine to 
  488 *                all zeros, ready for a new hash to be accumulated or to 
  489 *                re-synchronize or start up an encryption key-stream.
  490 *
  491 +**************************************************************************/
  492 
  493 static void pan_reset(PAN_BUFFER * buffer, PAN_STATE * state)
  494 {
  495     int i, j;
  496 
  497     buffer->tap_0 = 0;
  498 
  499     for (j = 0; j < PAN_STAGES; j++) {
  500         for (i = 0; i < PAN_STAGE_SIZE; i++) {
  501             buffer->stage[j].word[i] = 0L;
  502         }
  503     }
  504 
  505     for (i = 0; i < PAN_STATE_SIZE; i++) {
  506         state->word[i] = 0L;
  507     }
  508 }
  509 
  510 
  511 /**************************************************************************+
  512 *
  513 *  pan_crypt() - Performs stream encryption or decryption.
  514 *
  515 +**************************************************************************/
  516 
  517 WIN32DLL_DEFINE
  518     int _mcrypt_set_key(PANAMA_KEY * pan_key, char *in_key, int keysize,
  519             char *init_vec, int vecsize)
  520 {
  521     byte key[32];
  522     int keyblocks = (8 * keysize) / (PAN_STAGE_SIZE * WORDLENGTH);
  523     int vecblocks = (8 * vecsize) / (PAN_STAGE_SIZE * WORDLENGTH);
  524     int i;
  525 
  526     pan_key->keymat = (void*) pan_key->wkeymat;
  527 
  528 /* initialize the Panama state machine for a fresh crypting operation */
  529     pan_reset(&pan_key->buffer, &pan_key->state);
  530     pan_push((void *) in_key, keyblocks, &pan_key->buffer,
  531          &pan_key->state);
  532     if (init_vec != NULL)
  533         pan_push((void *) init_vec, vecblocks, &pan_key->buffer,
  534              &pan_key->state);
  535 
  536     pan_pull(NULL, NULL, 32, &pan_key->buffer, &pan_key->state);
  537 
  538     pan_pull(NULL, pan_key->wkeymat, 1, &pan_key->buffer,
  539          &pan_key->state);
  540     pan_key->keymat_pointer = 0;
  541 
  542 #ifdef WORDS_BIGENDIAN
  543     for (i = 0; i < 8; i++) {
  544 
  545         pan_key->wkeymat[i] =
  546             byteswap32( pan_key->wkeymat[i]);
  547     }
  548 #endif
  549 
  550     return 0;
  551 }
  552 
  553 WIN32DLL_DEFINE void _mcrypt_encrypt(PANAMA_KEY * pan_key,  /* the key from pan_init */
  554                      byte * buf,    /* input array                         */
  555                      int length)
  556 {               /* length to be encrypted, in bits     */
  557     int i;
  558 #ifdef WORDS_BIGENDIAN
  559     int j;
  560 #endif
  561 
  562 /* initialize the Panama state machine for a fresh crypting operation */
  563     for (i = 0; i < length; i++) {
  564 
  565         if (pan_key->keymat_pointer == 32) {
  566             pan_pull(NULL, (void *) pan_key->wkeymat, 1,
  567                  &pan_key->buffer, &pan_key->state);
  568             pan_key->keymat_pointer = 0;
  569 #ifdef WORDS_BIGENDIAN
  570             for (j = 0; j < 8; j++) {
  571                 pan_key->wkeymat[j] =
  572                     byteswap32( pan_key->wkeymat[j]);
  573             }
  574 #endif
  575         }
  576         buf[i] ^= pan_key->keymat[pan_key->keymat_pointer];
  577         pan_key->keymat_pointer++;
  578     }
  579 }
  580 
  581 WIN32DLL_DEFINE void _mcrypt_decrypt(PANAMA_KEY * pan_key,  /* the key from pan_init */
  582                      byte * buf,    /* input array                         */
  583                      int length)
  584 {               /* length to be encrypted, in bits     */
  585     _mcrypt_encrypt(pan_key, buf, length);
  586 }
  587 
  588 /**************************************************************************/
  589 
  590 
  591 WIN32DLL_DEFINE int _mcrypt_get_size()
  592 {
  593     return sizeof(PANAMA_KEY);
  594 }
  595 WIN32DLL_DEFINE int _mcrypt_get_block_size()
  596 {
  597     return 1;
  598 }
  599 WIN32DLL_DEFINE int _mcrypt_get_algo_iv_size()
  600 {
  601     return 32;
  602 }
  603 WIN32DLL_DEFINE int _is_block_algorithm()
  604 {
  605     return 0;
  606 }
  607 WIN32DLL_DEFINE int _mcrypt_get_key_size()
  608 {
  609     return 32;
  610 }
  611 
  612 static const int key_sizes[] = { 32 };
  613 WIN32DLL_DEFINE const int *_mcrypt_get_supported_key_sizes(int *len)
  614 {
  615     *len = sizeof(key_sizes)/sizeof(int);
  616     return key_sizes;
  617 
  618 }
  619 
  620 WIN32DLL_DEFINE char *_mcrypt_get_algorithms_name()
  621 {
  622 return "PANAMA";
  623 }
  624 
  625 #define CIPHER "d76e3c2243feadd2c99edfcb95c64c852ba6c59f"
  626 
  627 WIN32DLL_DEFINE int _mcrypt_self_test()
  628 {
  629     char *keyword;
  630     unsigned char plaintext[20];
  631     unsigned char ciphertext[20];
  632     int blocksize = 20, j;
  633     void *key;
  634     unsigned char cipher_tmp[200];
  635 
  636     keyword = calloc(1, _mcrypt_get_key_size());
  637     if (keyword == NULL)
  638         return -1;
  639 
  640     for (j = 0; j < _mcrypt_get_key_size(); j++) {
  641         keyword[j] = ((j * 2 + 10) % 256);
  642     }
  643 
  644     for (j = 0; j < blocksize; j++) {
  645         plaintext[j] = j % 256;
  646     }
  647     key = malloc(_mcrypt_get_size());
  648     if (key == NULL) {
  649         free(keyword);
  650         return -1;
  651     }
  652 
  653     memcpy(ciphertext, plaintext, blocksize);
  654 
  655     _mcrypt_set_key(key, (void *) keyword, _mcrypt_get_key_size(),
  656             NULL, 0);
  657     _mcrypt_encrypt(key, (void *) ciphertext, blocksize);
  658 
  659     for (j = 0; j < blocksize; j++) {
  660         sprintf(&((char *) cipher_tmp)[2 * j], "%.2x",
  661             ciphertext[j]);
  662     }
  663 
  664     if (strcmp((char *) cipher_tmp, CIPHER) != 0) {
  665         printf("failed compatibility\n");
  666         printf("Expected: %s\nGot: %s\n", CIPHER,
  667                (char *) cipher_tmp);
  668         free(keyword);
  669         free(key);
  670         return -1;
  671     }
  672 
  673     _mcrypt_set_key(key, (void *) keyword, _mcrypt_get_key_size(),
  674             NULL, 0);
  675     free(keyword);
  676 
  677     _mcrypt_decrypt(key, (void *) ciphertext, blocksize);
  678     free(key);
  679 
  680     if (strcmp(ciphertext, plaintext) != 0) {
  681         printf("failed internally\n");
  682         return -1;
  683     }
  684 
  685     return 0;
  686 }
  687 
  688 WIN32DLL_DEFINE word32 _mcrypt_algorithm_version(void)
  689 {
  690     return 20010801;
  691 }
  692 
  693 #ifdef WIN32
  694 # ifdef USE_LTDL
  695 WIN32DLL_DEFINE int main (void)
  696 {
  697        /* empty main function to avoid linker error (see cygwin FAQ) */
  698 }
  699 # endif
  700 #endif