rijndael_api.c

Go to the documentation of this file.
00001 /*      rijndael-api.c - Rijndael encryption programming interface.
00002  *                                                      Author: Kees J. Bot
00003  *                                                              3 Nov 2000
00004  * Heavily based on the original API code by Antoon Bosselaers,
00005  * Vincent Rijmen, and Paulo Barreto, but with a different interface.
00006  *
00007  * Read this code top to bottom, not all comments are repeated.
00008  */
00009 
00010 #include <stdlib.h>
00011 #include <string.h>
00012 #include <sys/types.h>
00013 
00014 #include "rijndael-alg.h"
00015 #include "rijndael-api.h"
00016 
00017 /* Map a byte (?) address to a word address or vv. */
00018 #define W(a)    ((word32 *) (a))
00019 #define B(a)    ((word8 *) (a))
00020 
00021 #if STRICT_ALIGN
00022 /* This machine checks alignment religiously.  (The code is not proper with
00023  * respect to alignment.  We need a compiler that doesn't muck about with byte
00024  * arrays that follow words in structs, and that places automatic variables
00025  * at word boundaries if not odd-sized.  Most compilers are this nice.)
00026  */
00027 
00028 #define aligned(a)              (((unsigned) (a) & 3) == 0)
00029 #define aligned2(a1, a2)        aligned((unsigned) (a1) | (unsigned) (a2))
00030 
00031 static void blockcpy(void *dst, const void *src)
00032 {
00033     int i= 0;
00034 
00035     do {
00036         B(dst)[i+0] = B(src)[i+0];
00037         B(dst)[i+1] = B(src)[i+1];
00038         B(dst)[i+2] = B(src)[i+2];
00039         B(dst)[i+3] = B(src)[i+3];
00040     } while ((i += 4) < 16);
00041 }
00042 
00043 #else /* !STRICT_ALIGN */
00044 /* This machine doesn't mind misaligned accesses much. */
00045 
00046 #define aligned(a)              ((void) (a), 1)
00047 #define aligned2(a1, a2)        ((void) (a1), (void) (a2), 1)
00048 
00049 #if __GNUC__
00050 __inline
00051 #endif
00052 static void blockcpy(void *dst, const void *src)
00053 {
00054     W(dst)[0] = W(src)[0];
00055     W(dst)[1] = W(src)[1];
00056     W(dst)[2] = W(src)[2];
00057     W(dst)[3] = W(src)[3];
00058 }
00059 
00060 #endif /* !STRICT_ALIGN */
00061 
00062 #define between(a, c, z)        ((unsigned) (c) - (a) <= (unsigned) (z) - (a))
00063 
00064 int rijndael_makekey(rd_keyinstance *key,
00065         size_t keylen, const void *keymaterial)
00066 {
00067     word8 k[MAXKC][4];
00068 
00069     /* Initialize key schedule: */
00070     if (keylen == RD_KEY_HEX) {
00071         const word8 *kp;
00072         int c, b;
00073 
00074         kp= keymaterial;
00075         keylen= 0;
00076 
00077         for (;;) {
00078             c= *kp++;
00079             if (between('0', c, '9')) b= (c - '0' + 0x0) << 4;
00080             else
00081             if (between('a', c, 'f')) b= (c - 'a' + 0xa) << 4;
00082             else
00083             if (between('A', c, 'F')) b= (c - 'A' + 0xA) << 4;
00084             else break;
00085 
00086             c= *kp++;
00087             if (between('0', c, '9')) b |= (c - '0' + 0x0);
00088             else
00089             if (between('a', c, 'f')) b |= (c - 'a' + 0xa);
00090             else
00091             if (between('A', c, 'F')) b |= (c - 'A' + 0xA);
00092             else break;
00093 
00094             if (keylen >= 256/8) return RD_BAD_KEY_MAT;
00095             B(k)[keylen++] = b;
00096         }
00097         if (c != 0) return RD_BAD_KEY_MAT;
00098 
00099         if (keylen != 128/8 && keylen != 192/8 && keylen != 256/8) {
00100             return RD_BAD_KEY_MAT;
00101         }
00102     } else {
00103         if (keylen != 128/8 && keylen != 192/8 && keylen != 256/8) {
00104             return RD_BAD_KEY_MAT;
00105         }
00106         memcpy(k, keymaterial, keylen);
00107     }
00108 
00109     key->rounds= keylen * 8 / 32 + 6;
00110 
00111     rijndael_KeySched(k, key->encsched, key->rounds);
00112     memcpy(key->decsched, key->encsched, sizeof(key->decsched));
00113     rijndael_KeyEncToDec(key->decsched, key->rounds);
00114 
00115     return 0;
00116 }
00117 
00118 ssize_t rijndael_ecb_encrypt(rd_keyinstance *key,
00119         const void *input, void *output, size_t length, void *dummyIV)
00120 {
00121     /* Encrypt blocks of data in Electronic Codebook mode. */
00122     const word8 *inp= input;
00123     word8 *outp= output;
00124     size_t i, nr_blocks, extra;
00125     word32 in[4], out[4];
00126     word8 t;
00127 
00128     /* Compute the number of whole blocks, and the extra bytes beyond the
00129      * last block.  Those extra bytes, if any, are encrypted by stealing
00130      * enough bytes from the previous encrypted block to make a whole block.
00131      * This is done by encrypting the last block, exchanging the first few
00132      * encrypted bytes with the extra bytes, and encrypting the last whole
00133      * block again.
00134      */
00135     nr_blocks= length / 16;
00136     if ((extra= (length % 16)) > 0) {
00137         if (nr_blocks == 0) return RD_BAD_BLOCK_LENGTH;
00138         nr_blocks--;
00139     }
00140 
00141     /* Encrypt a number of blocks. */
00142     if (aligned2(inp, outp)) {
00143         for (i= 0; i < nr_blocks; i++) {
00144             rijndael_Encrypt(inp, outp, key->encsched, key->rounds);
00145             inp += 16;
00146             outp += 16;
00147         }
00148     } else {
00149         for (i= 0; i < nr_blocks; i++) {
00150             blockcpy(in, inp);
00151             rijndael_Encrypt(in, out, key->encsched, key->rounds);
00152             blockcpy(outp, out);
00153             inp += 16;
00154             outp += 16;
00155         }
00156     }
00157 
00158     /* Encrypt extra bytes by stealing from the last full block. */
00159     if (extra > 0) {
00160         blockcpy(in, inp);
00161         rijndael_Encrypt(in, out, key->encsched, key->rounds);
00162         for (i= 0; i < extra; i++) {
00163             t= B(out)[i];
00164             B(out)[i] = inp[16 + i];
00165             outp[16 + i] = t;
00166         }
00167         rijndael_Encrypt(out, out, key->encsched, key->rounds);
00168         blockcpy(outp, out);
00169     }
00170     return length;
00171 }
00172 
00173 ssize_t rijndael_ecb_decrypt(rd_keyinstance *key,
00174         const void *input, void *output, size_t length, void *dummyIV)
00175 {
00176     /* Decrypt blocks of data in Electronic Codebook mode. */
00177     const word8 *inp= input;
00178     word8 *outp= output;
00179     size_t i, nr_blocks, extra;
00180     word32 in[4], out[4];
00181     word8 t;
00182 
00183     nr_blocks= length / 16;
00184     if ((extra= (length % 16)) > 0) {
00185         if (nr_blocks == 0) return RD_BAD_BLOCK_LENGTH;
00186         nr_blocks--;
00187     }
00188 
00189     /* Decrypt a number of blocks. */
00190     if (aligned2(inp, outp)) {
00191         for (i= 0; i < nr_blocks; i++) {
00192             rijndael_Decrypt(inp, outp, key->decsched, key->rounds);
00193             inp += 16;
00194             outp += 16;
00195         }
00196     } else {
00197         for (i= 0; i < nr_blocks; i++) {
00198             blockcpy(in, inp);
00199             rijndael_Decrypt(in, out, key->decsched, key->rounds);
00200             blockcpy(outp, out);
00201             inp += 16;
00202             outp += 16;
00203         }
00204     }
00205 
00206     /* Decrypt extra bytes that stole from the last full block. */
00207     if (extra > 0) {
00208         blockcpy(in, inp);
00209         rijndael_Decrypt(in, out, key->decsched, key->rounds);
00210         for (i= 0; i < extra; i++) {
00211             t= B(out)[i];
00212             B(out)[i] = inp[16 + i];
00213             outp[16 + i] = t;
00214         }
00215         rijndael_Decrypt(out, out, key->decsched, key->rounds);
00216         blockcpy(outp, out);
00217     }
00218     return length;
00219 }
00220 
00221 ssize_t rijndael_cbc_encrypt(rd_keyinstance *key,
00222         const void *input, void *output, size_t length, void *IV)
00223 {
00224     /* Encrypt blocks of data in Cypher Block Chaining mode. */
00225     const word8 *inp= input;
00226     word8 *outp= output;
00227     size_t i, nr_blocks, extra;
00228     word32 in[4], out[4], iv[4], *ivp;
00229     word8 t;
00230 
00231     nr_blocks= length / 16;
00232     if ((extra= (length % 16)) > 0) {
00233         if (nr_blocks == 0) return RD_BAD_BLOCK_LENGTH;
00234         nr_blocks--;
00235     }
00236 
00237     /* Each input block is first XORed with the previous encryption result.
00238      * The "Initialization Vector" is used to XOR the first block with.
00239      * When done the last crypted block is stored back as the new IV to be
00240      * used for another call to this function.
00241      */
00242     ivp= aligned(IV) ? IV : (blockcpy(iv, IV), iv);
00243 
00244     if (aligned2(inp, outp)) {
00245         for (i= 0; i < nr_blocks; i++) {
00246             in[0] = W(inp)[0] ^ ivp[0];
00247             in[1] = W(inp)[1] ^ ivp[1];
00248             in[2] = W(inp)[2] ^ ivp[2];
00249             in[3] = W(inp)[3] ^ ivp[3];
00250             rijndael_Encrypt(in, outp, key->encsched, key->rounds);
00251             ivp= W(outp);
00252             inp += 16;
00253             outp += 16;
00254         }
00255     } else {
00256         for (i= 0; i < nr_blocks; i++) {
00257             blockcpy(in, inp);
00258             in[0] ^= ivp[0];
00259             in[1] ^= ivp[1];
00260             in[2] ^= ivp[2];
00261             in[3] ^= ivp[3];
00262             rijndael_Encrypt(in, out, key->encsched, key->rounds);
00263             blockcpy(outp, out);
00264             ivp= out;
00265             inp += 16;
00266             outp += 16;
00267         }
00268     }
00269     if (extra > 0) {
00270         blockcpy(in, inp);
00271         in[0] ^= ivp[0];
00272         in[1] ^= ivp[1];
00273         in[2] ^= ivp[2];
00274         in[3] ^= ivp[3];
00275         rijndael_Encrypt(in, out, key->encsched, key->rounds);
00276         for (i= 0; i < extra; i++) {
00277             t= B(out)[i];
00278             B(out)[i] ^= inp[16 + i];
00279             outp[16 + i] = t;
00280         }
00281         rijndael_Encrypt(out, out, key->encsched, key->rounds);
00282         blockcpy(outp, out);
00283         ivp= out;
00284     }
00285     blockcpy(IV, ivp);          /* Store last IV back. */
00286     return length;
00287 }
00288 
00289 ssize_t rijndael_cbc_decrypt(rd_keyinstance *key,
00290         const void *input, void *output, size_t length, void *IV)
00291 {
00292     /* Decrypt blocks of data in Cypher Block Chaining mode. */
00293     const word8 *inp= input;
00294     word8 *outp= output;
00295     size_t i, nr_blocks, extra;
00296     word32 in[4], out[4], iv[4];
00297     word8 t;
00298 
00299     nr_blocks= length / 16;
00300     if ((extra= (length % 16)) > 0) {
00301         if (nr_blocks == 0) return RD_BAD_BLOCK_LENGTH;
00302         nr_blocks--;
00303     }
00304 
00305     blockcpy(iv, IV);
00306 
00307     if (aligned2(inp, outp)) {
00308         for (i= 0; i < nr_blocks; i++) {
00309             rijndael_Decrypt(inp, out, key->decsched, key->rounds);
00310             out[0] ^= iv[0];
00311             out[1] ^= iv[1];
00312             out[2] ^= iv[2];
00313             out[3] ^= iv[3];
00314             iv[0] = W(inp)[0];
00315             iv[1] = W(inp)[1];
00316             iv[2] = W(inp)[2];
00317             iv[3] = W(inp)[3];
00318             W(outp)[0] = out[0];
00319             W(outp)[1] = out[1];
00320             W(outp)[2] = out[2];
00321             W(outp)[3] = out[3];
00322             inp += 16;
00323             outp += 16;
00324         }
00325     } else {
00326         for (i= 0; i < nr_blocks; i++) {
00327             blockcpy(in, inp);
00328             rijndael_Decrypt(in, out, key->decsched, key->rounds);
00329             out[0] ^= iv[0];
00330             out[1] ^= iv[1];
00331             out[2] ^= iv[2];
00332             out[3] ^= iv[3];
00333             iv[0] = in[0];
00334             iv[1] = in[1];
00335             iv[2] = in[2];
00336             iv[3] = in[3];
00337             blockcpy(outp, out);
00338             inp += 16;
00339             outp += 16;
00340         }
00341     }
00342     if (extra > 0) {
00343         blockcpy(in, inp);
00344         blockcpy(IV, in);
00345         rijndael_Decrypt(in, out, key->decsched, key->rounds);
00346         for (i= 0; i < extra; i++) {
00347             t= B(out)[i] ^ inp[16 + i];
00348             B(out)[i] = inp[16 + i];
00349             outp[16 + i] = t;
00350         }
00351         rijndael_Decrypt(out, out, key->decsched, key->rounds);
00352         out[0] ^= iv[0];
00353         out[1] ^= iv[1];
00354         out[2] ^= iv[2];
00355         out[3] ^= iv[3];
00356         blockcpy(outp, out);
00357     } else {
00358         blockcpy(IV, iv);
00359     }
00360     return length;
00361 }
00362 
00363 ssize_t rijndael_cfb1_encrypt(rd_keyinstance *key,
00364         const void *input, void *output, size_t length, void *IV)
00365 {
00366     /* Encrypt blocks of data in Cypher Feedback mode, 1 bit at a time. */
00367     const word8 *inp= input;
00368     word8 *outp= output;
00369     word8 t;
00370     size_t i;
00371     int b;
00372     word32 iv[4], civ[4];
00373 
00374     blockcpy(iv, IV);
00375 
00376     for (i= 0; i < length; i++) {
00377         t= *inp++;
00378         for (b= 0; b < 8; b++) {
00379             rijndael_Encrypt(iv, civ, key->encsched, key->rounds);
00380             t ^= (B(civ)[0] & 0x80) >> b;
00381             B(iv)[ 0] = (B(iv)[ 0] << 1) | (B(iv)[ 1] >> 7);
00382             B(iv)[ 1] = (B(iv)[ 1] << 1) | (B(iv)[ 2] >> 7);
00383             B(iv)[ 2] = (B(iv)[ 2] << 1) | (B(iv)[ 3] >> 7);
00384             B(iv)[ 3] = (B(iv)[ 3] << 1) | (B(iv)[ 4] >> 7);
00385             B(iv)[ 4] = (B(iv)[ 4] << 1) | (B(iv)[ 5] >> 7);
00386             B(iv)[ 5] = (B(iv)[ 5] << 1) | (B(iv)[ 6] >> 7);
00387             B(iv)[ 6] = (B(iv)[ 6] << 1) | (B(iv)[ 7] >> 7);
00388             B(iv)[ 7] = (B(iv)[ 7] << 1) | (B(iv)[ 8] >> 7);
00389             B(iv)[ 8] = (B(iv)[ 8] << 1) | (B(iv)[ 9] >> 7);
00390             B(iv)[ 9] = (B(iv)[ 9] << 1) | (B(iv)[10] >> 7);
00391             B(iv)[10] = (B(iv)[10] << 1) | (B(iv)[11] >> 7);
00392             B(iv)[11] = (B(iv)[11] << 1) | (B(iv)[12] >> 7);
00393             B(iv)[12] = (B(iv)[12] << 1) | (B(iv)[13] >> 7);
00394             B(iv)[13] = (B(iv)[13] << 1) | (B(iv)[14] >> 7);
00395             B(iv)[14] = (B(iv)[14] << 1) | (B(iv)[15] >> 7);
00396             B(iv)[15] = (B(iv)[15] << 1) | ((t >> (7-b)) & 1);
00397         }
00398         *outp++ = t;
00399     }
00400     blockcpy(IV, iv);
00401     return length;
00402 }
00403 
00404 ssize_t rijndael_cfb1_decrypt(rd_keyinstance *key,
00405         const void *input, void *output, size_t length, void *IV)
00406 {
00407     /* Decrypt blocks of data in Cypher Feedback mode, 1 bit at a time. */
00408     const word8 *inp= input;
00409     word8 *outp= output;
00410     word8 t;
00411     size_t i;
00412     int b;
00413     word32 iv[4], civ[4];
00414 
00415     blockcpy(iv, IV);
00416 
00417     for (i= 0; i < length; i++) {
00418         t= *inp++;
00419         for (b= 0; b < 8; b++) {
00420             rijndael_Encrypt(iv, civ, key->encsched, key->rounds);
00421             B(iv)[ 0] = (B(iv)[ 0] << 1) | (B(iv)[ 1] >> 7);
00422             B(iv)[ 1] = (B(iv)[ 1] << 1) | (B(iv)[ 2] >> 7);
00423             B(iv)[ 2] = (B(iv)[ 2] << 1) | (B(iv)[ 3] >> 7);
00424             B(iv)[ 3] = (B(iv)[ 3] << 1) | (B(iv)[ 4] >> 7);
00425             B(iv)[ 4] = (B(iv)[ 4] << 1) | (B(iv)[ 5] >> 7);
00426             B(iv)[ 5] = (B(iv)[ 5] << 1) | (B(iv)[ 6] >> 7);
00427             B(iv)[ 6] = (B(iv)[ 6] << 1) | (B(iv)[ 7] >> 7);
00428             B(iv)[ 7] = (B(iv)[ 7] << 1) | (B(iv)[ 8] >> 7);
00429             B(iv)[ 8] = (B(iv)[ 8] << 1) | (B(iv)[ 9] >> 7);
00430             B(iv)[ 9] = (B(iv)[ 9] << 1) | (B(iv)[10] >> 7);
00431             B(iv)[10] = (B(iv)[10] << 1) | (B(iv)[11] >> 7);
00432             B(iv)[11] = (B(iv)[11] << 1) | (B(iv)[12] >> 7);
00433             B(iv)[12] = (B(iv)[12] << 1) | (B(iv)[13] >> 7);
00434             B(iv)[13] = (B(iv)[13] << 1) | (B(iv)[14] >> 7);
00435             B(iv)[14] = (B(iv)[14] << 1) | (B(iv)[15] >> 7);
00436             B(iv)[15] = (B(iv)[15] << 1) | ((t >> (7-b)) & 1);
00437             t ^= (B(civ)[0] & 0x80) >> b;
00438         }
00439         *outp++ = t;
00440     }
00441     blockcpy(IV, iv);
00442     return length;
00443 }
00444 
00445 ssize_t rijndael_cfb8_encrypt(rd_keyinstance *key,
00446         const void *input, void *output, size_t length, void *IV)
00447 {
00448     /* Encrypt blocks of data in Cypher Feedback mode, 8 bits at a time. */
00449     const word8 *inp= input;
00450     word8 *outp= output;
00451     word8 t;
00452     size_t i;
00453     word32 iv[4], civ[4];
00454 
00455     blockcpy(iv, IV);
00456 
00457     for (i= 0; i < length; i++) {
00458         t= *inp++;
00459         rijndael_Encrypt(iv, civ, key->encsched, key->rounds);
00460         t ^= B(civ)[0];
00461         B(iv)[ 0] = B(iv)[ 1];
00462         B(iv)[ 1] = B(iv)[ 2];
00463         B(iv)[ 2] = B(iv)[ 3];
00464         B(iv)[ 3] = B(iv)[ 4];
00465         B(iv)[ 4] = B(iv)[ 5];
00466         B(iv)[ 5] = B(iv)[ 6];
00467         B(iv)[ 6] = B(iv)[ 7];
00468         B(iv)[ 7] = B(iv)[ 8];
00469         B(iv)[ 8] = B(iv)[ 9];
00470         B(iv)[ 9] = B(iv)[10];
00471         B(iv)[10] = B(iv)[11];
00472         B(iv)[11] = B(iv)[12];
00473         B(iv)[12] = B(iv)[13];
00474         B(iv)[13] = B(iv)[14];
00475         B(iv)[14] = B(iv)[15];
00476         B(iv)[15] = t;
00477         *outp++ = t;
00478     }
00479     blockcpy(IV, iv);
00480     return length;
00481 }
00482 
00483 ssize_t rijndael_cfb8_decrypt(rd_keyinstance *key,
00484         const void *input, void *output, size_t length, void *IV)
00485 {
00486     /* Decrypt blocks of data in Cypher Feedback mode, 1 byte at a time. */
00487     const word8 *inp= input;
00488     word8 *outp= output;
00489     word8 t;
00490     size_t i;
00491     word32 iv[4], civ[4];
00492 
00493     blockcpy(iv, IV);
00494 
00495     for (i= 0; i < length; i++) {
00496         t= *inp++;
00497         rijndael_Encrypt(iv, civ, key->encsched, key->rounds);
00498         B(iv)[ 0] = B(iv)[ 1];
00499         B(iv)[ 1] = B(iv)[ 2];
00500         B(iv)[ 2] = B(iv)[ 3];
00501         B(iv)[ 3] = B(iv)[ 4];
00502         B(iv)[ 4] = B(iv)[ 5];
00503         B(iv)[ 5] = B(iv)[ 6];
00504         B(iv)[ 6] = B(iv)[ 7];
00505         B(iv)[ 7] = B(iv)[ 8];
00506         B(iv)[ 8] = B(iv)[ 9];
00507         B(iv)[ 9] = B(iv)[10];
00508         B(iv)[10] = B(iv)[11];
00509         B(iv)[11] = B(iv)[12];
00510         B(iv)[12] = B(iv)[13];
00511         B(iv)[13] = B(iv)[14];
00512         B(iv)[14] = B(iv)[15];
00513         B(iv)[15] = t;
00514         t ^= B(civ)[0];
00515         *outp++ = t;
00516     }
00517     blockcpy(IV, iv);
00518     return length;
00519 }
00520 
00521 ssize_t rijndael_pad(void *input, size_t length)
00522 {
00523     /* Adds at most one block of RFC-2040 style padding to the input to make
00524      * it a whole number of blocks for easier encryption.  To be used if the
00525      * input may be less then one block in size, otherwise let the encryption
00526      * routines use cypher stealing.  The input buffer should allow enough
00527      * space for the padding.  The new length of the input is returned.
00528      */
00529     word8 *inp= input;
00530     size_t padlen;
00531 
00532     /* Add padding up until the next block boundary. */
00533     padlen= 16 - (length % 16);
00534     memset(inp + length, padlen, padlen);
00535     return length + padlen;
00536 }
00537 
00538 ssize_t rijndael_unpad(const void *input, size_t length)
00539 {
00540     /* Remove RFC-2040 style padding after decryption.  The true length of
00541      * the input is returned, or the usual errors if the padding is incorrect.
00542      */
00543     const word8 *inp= input;
00544     size_t i, padlen;
00545 
00546     if (length == 0 || (length % 16) != 0) return RD_BAD_BLOCK_LENGTH;
00547     padlen = inp[length-1];
00548     if (padlen <= 0 || padlen > 16) return RD_BAD_DATA;
00549     for (i= 2; i <= padlen; i++) {
00550         if (inp[length-i] != padlen) return RD_BAD_DATA;
00551     }
00552     return length - padlen;
00553 }
00554 
00555 #ifdef INTERMEDIATE_VALUE_KAT
00556 
00557 void cipherEncryptUpdateRounds(rd_keyinstance *key,
00558         const void *input, void *output, int rounds)
00559 {
00560     /* Encrypt a block only a specified number of rounds. */
00561     word8 block[4][4];
00562 
00563     blockcpy(block, input);
00564 
00565     rijndaelEncryptRound(block, key->encsched, key->rounds, rounds);
00566 
00567     blockcpy(output, block);
00568 }
00569 
00570 void cipherDecryptUpdateRounds(rd_keyinstance *key,
00571         const void *input, void *output, int rounds)
00572 {
00573     /* Decrypt a block only a specified number of rounds. */
00574     word8 block[4][4];
00575 
00576     blockcpy(block, input);
00577 
00578     rijndaelDecryptRound(block, key->decsched, key->rounds, rounds);
00579 
00580     blockcpy(output, block);
00581 }
00582 #endif /* INTERMEDIATE_VALUE_KAT */
00583 
00584 /*
00585  * $PchId: rijndael_api.c,v 1.2 2001/01/10 22:01:20 philip Exp $
00586  */

Generated on Fri Apr 14 22:57:17 2006 for minix by  doxygen 1.4.6