home *** CD-ROM | disk | FTP | other *** search
/ OS/2 Shareware BBS: 10 Tools / 10-Tools.zip / crypl200.zip / LIB_RC5.C < prev    next >
Text File  |  1996-09-29  |  17KB  |  584 lines

  1. /****************************************************************************
  2. *                                                                            *
  3. *                        cryptlib RC5 Encryption Routines                    *
  4. *                        Copyright Peter Gutmann 1992-1996                    *
  5. *                                                                            *
  6. ****************************************************************************/
  7.  
  8. #include <ctype.h>
  9. #include <stdio.h>
  10. #include <stdlib.h>
  11. #include <string.h>
  12. #include <time.h>
  13. #include "crypt.h"
  14. #ifdef INC_ALL
  15.   #include "rc5.h"
  16. #else
  17.   #include "rc/rc5.h"
  18. #endif /* Compiler-specific includes */
  19.  
  20. /****************************************************************************
  21. *                                                                            *
  22. *                                RC5 Self-test Routines                        *
  23. *                                                                            *
  24. ****************************************************************************/
  25.  
  26. /* RC5 test vectors from RC5 specification */
  27.  
  28. static struct RC5_TEST {
  29.     BYTE key[ 16 ];
  30.     BYTE plainText[ 8 ];
  31.     BYTE cipherText[ 8 ];
  32.     } testRC5[] = {
  33.     { { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  34.         0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 },
  35.       { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 },
  36.       { 0x21, 0xA5, 0xDB, 0xEE, 0x15, 0x4B, 0x8F, 0x6D } },
  37.     { { 0x91, 0x5F, 0x46, 0x19, 0xBE, 0x41, 0xB2, 0x51,
  38.         0x63, 0x55, 0xA5, 0x01, 0x10, 0xA9, 0xCE, 0x91 },
  39.       { 0x21, 0xA5, 0xDB, 0xEE, 0x15, 0x4B, 0x8F, 0x6D },
  40.       { 0xF7, 0xC0, 0x13, 0xAC, 0x5B, 0x2B, 0x89, 0x52 } },
  41.     { { 0x78, 0x33, 0x48, 0xE7, 0x5A, 0xEB, 0x0F, 0x2F,
  42.         0xD7, 0xB1, 0x69, 0xBB, 0x8D, 0xC1, 0x67, 0x87 },
  43.       { 0xF7, 0xC0, 0x13, 0xAC, 0x5B, 0x2B, 0x89, 0x52 },
  44.       { 0x2F, 0x42, 0xB3, 0xB7, 0x03, 0x69, 0xFC, 0x92 } },
  45.     { { 0xDC, 0x49, 0xDB, 0x13, 0x75, 0xA5, 0x58, 0x4F,
  46.         0x64, 0x85, 0xB4, 0x13, 0xB5, 0xF1, 0x2B, 0xAF },
  47.       { 0x2F, 0x42, 0xB3, 0xB7, 0x03, 0x69, 0xFC, 0x92 },
  48.       { 0x65, 0xC1, 0x78, 0xB2, 0x84, 0xD1, 0x97, 0xCC } },
  49.     { { 0x52, 0x69, 0xF1, 0x49, 0xD4, 0x1B, 0xA0, 0x15,
  50.         0x24, 0x97, 0x57, 0x4D, 0x7F, 0x15, 0x31, 0x25 },
  51.       { 0x65, 0xC1, 0x78, 0xB2, 0x84, 0xD1, 0x97, 0xCC },
  52.       { 0xEB, 0x44, 0xE4, 0x15, 0xDA, 0x31, 0x98, 0x24 } }
  53.     };
  54.  
  55. /* Test the RC5 code against the RC5 test vectors */
  56.  
  57. int rc5SelfTest( void )
  58.     {
  59.     BYTE temp[ RC5_BLOCKSIZE ];
  60.     RC5_KEY key;
  61.     int i;
  62.  
  63.     for( i = 0; i < sizeof( testRC5 ) / sizeof( struct RC5_TEST ); i++ )
  64.         {
  65.         key.noRounds = 12;
  66.         memcpy( temp, testRC5[ i ].plainText, RC5_BLOCKSIZE );
  67.             rc5keyInit( &key, testRC5[ i ].key, 16 );
  68.         rc5encrypt( &key, temp );
  69.         if( memcmp( testRC5[ i ].cipherText, temp, RC5_BLOCKSIZE ) )
  70.             return( CRYPT_ERROR );
  71.         }
  72.  
  73.     return( CRYPT_OK );
  74.     }
  75.  
  76. /****************************************************************************
  77. *                                                                            *
  78. *                            Init/Shutdown Routines                            *
  79. *                                                                            *
  80. ****************************************************************************/
  81.  
  82. /* Perform auxiliary init and shutdown actions on an encryption context */
  83.  
  84. int rc5InitEx( CRYPT_INFO *cryptInfo, void *cryptInfoEx )
  85.     {
  86.     CRYPT_INFO_RC5 *cryptInfoExPtr = ( CRYPT_INFO_RC5 * ) cryptInfoEx;
  87.     int status;
  88.  
  89.     /* Allocate memory for the key and the algorithm-specific data within
  90.        the crypt context and set up any pointers we need.  We don't process
  91.        cryptInfoExPtr->noRounds at this point since we set things up when we
  92.        perform the rc5InitKey() function, as the number of rounds is key-
  93.        dependant */
  94.     if( cryptInfo->key != NULL || cryptInfo->privateData != NULL )
  95.         return( CRYPT_INITED );
  96.     if( ( status = secureMalloc( &cryptInfo->key, sizeof( RC5_KEY ) ) ) != CRYPT_OK )
  97.         return( status );
  98.     if( cryptInfoExPtr->rounds == CRYPT_USE_DEFAULT )
  99.         cryptInfo->privateUseDefaults = TRUE;
  100.     if( ( status = secureMalloc( &cryptInfo->privateData, sizeof( CRYPT_INFO_RC5 ) ) ) != CRYPT_OK )
  101.         {
  102.         secureFree( cryptInfo->key );
  103.         return( status );
  104.         }
  105.     setRC5info( cryptInfo, cryptInfoExPtr->rounds );
  106.     cryptInfo->keyLength = sizeof( RC5_KEY );
  107.  
  108.     return( CRYPT_OK );
  109.     }
  110.  
  111. int rc5Init( CRYPT_INFO *cryptInfo )
  112.     {
  113.     CRYPT_INFO_RC5 cryptInfoEx;
  114.  
  115.     /* Use the default number of rounds */
  116.     memset( &cryptInfoEx, 0, sizeof( CRYPT_INFO_RC5 ) );
  117.     cryptInfoEx.rounds = CRYPT_USE_DEFAULT;
  118.  
  119.     /* Pass through to the extended setup routine */
  120.     return( rc5InitEx( cryptInfo, &cryptInfoEx ) );
  121.     }
  122.  
  123. int rc5End( CRYPT_INFO *cryptInfo )
  124.     {
  125.     /* Free any allocated memory */
  126.     secureFree( &cryptInfo->key );
  127.     secureFree( &cryptInfo->privateData );
  128.  
  129.     return( CRYPT_OK );
  130.     }
  131.  
  132. /****************************************************************************
  133. *                                                                            *
  134. *                            RC5 En/Decryption Routines                        *
  135. *                                                                            *
  136. ****************************************************************************/
  137.  
  138. /* Encrypt/decrypt data in ECB mode */
  139.  
  140. int rc5EncryptECB( CRYPT_INFO *cryptInfo, BYTE *buffer, int noBytes )
  141.     {
  142.     RC5_KEY *rc5Key = ( RC5_KEY * ) cryptInfo->key;
  143.     int blockCount = noBytes / RC5_BLOCKSIZE;
  144.  
  145.     /* Make sure the data length is a multiple of the block size */
  146.     if( noBytes % RC5_BLOCKSIZE )
  147.         return( CRYPT_BADPARM3 );
  148.  
  149.     while( blockCount-- )
  150.         {
  151.         /* Encrypt a block of data */
  152.         rc5encrypt( rc5Key, buffer );
  153.  
  154.         /* Move on to next block of data */
  155.         buffer += RC5_BLOCKSIZE;
  156.         }
  157.  
  158.     return( CRYPT_OK );
  159.     }
  160.  
  161. int rc5DecryptECB( CRYPT_INFO *cryptInfo, BYTE *buffer, int noBytes )
  162.     {
  163.     RC5_KEY *rc5Key = ( RC5_KEY * ) cryptInfo->key;
  164.     int blockCount = noBytes / RC5_BLOCKSIZE;
  165.  
  166.     /* Make sure the data length is a multiple of the block size */
  167.     if( noBytes % RC5_BLOCKSIZE )
  168.         return( CRYPT_BADPARM3 );
  169.  
  170.     while( blockCount-- )
  171.         {
  172.         /* Decrypt a block of data */
  173.         rc5decrypt( rc5Key, buffer );
  174.  
  175.         /* Move on to next block of data */
  176.         buffer += RC5_BLOCKSIZE;
  177.         }
  178.  
  179.     return( CRYPT_OK );
  180.     }
  181.  
  182. /* Encrypt/decrypt data in CBC mode */
  183.  
  184. int rc5EncryptCBC( CRYPT_INFO *cryptInfo, BYTE *buffer, int noBytes )
  185.     {
  186.     RC5_KEY *rc5Key = ( RC5_KEY * ) cryptInfo->key;
  187.     int blockCount = noBytes / RC5_BLOCKSIZE;
  188.  
  189.     /* Make sure the data length is a multiple of the block size */
  190.     if( noBytes % RC5_BLOCKSIZE )
  191.         return( CRYPT_BADPARM3 );
  192.  
  193.     while( blockCount-- )
  194.         {
  195.         int i;
  196.  
  197.         /* XOR the buffer contents with the IV */
  198.         for( i = 0; i < RC5_BLOCKSIZE; i++ )
  199.             buffer[ i ] ^= cryptInfo->currentIV[ i ];
  200.  
  201.         /* Encrypt a block of data */
  202.         rc5encrypt( rc5Key, buffer );
  203.  
  204.         /* Shift ciphertext into IV */
  205.         memcpy( cryptInfo->currentIV, buffer, RC5_BLOCKSIZE );
  206.  
  207.         /* Move on to next block of data */
  208.         buffer += RC5_BLOCKSIZE;
  209.         }
  210.  
  211.     return( CRYPT_OK );
  212.     }
  213.  
  214. int rc5DecryptCBC( CRYPT_INFO *cryptInfo, BYTE *buffer, int noBytes )
  215.     {
  216.     RC5_KEY *rc5Key = ( RC5_KEY * ) cryptInfo->key;
  217.     BYTE temp[ RC5_BLOCKSIZE ];
  218.     int blockCount = noBytes / RC5_BLOCKSIZE;
  219.  
  220.     /* Make sure the data length is a multiple of the block size */
  221.     if( noBytes % RC5_BLOCKSIZE )
  222.         return( CRYPT_BADPARM3 );
  223.  
  224.     while( blockCount-- )
  225.         {
  226.         int i;
  227.  
  228.         /* Save the ciphertext */
  229.         memcpy( temp, buffer, RC5_BLOCKSIZE );
  230.  
  231.         /* Decrypt a block of data */
  232.         rc5decrypt( rc5Key, buffer );
  233.  
  234.         /* XOR the buffer contents with the IV */
  235.         for( i = 0; i < RC5_BLOCKSIZE; i++ )
  236.             buffer[ i ] ^= cryptInfo->currentIV[ i ];
  237.  
  238.         /* Shift the ciphertext into the IV */
  239.         memcpy( cryptInfo->currentIV, temp, RC5_BLOCKSIZE );
  240.  
  241.         /* Move on to next block of data */
  242.         buffer += RC5_BLOCKSIZE;
  243.         }
  244.  
  245.     /* Clear the temporary buffer */
  246.     zeroise( temp, RC5_BLOCKSIZE );
  247.  
  248.     return( CRYPT_OK );
  249.     }
  250.  
  251. /* Encrypt/decrypt data in CFB mode */
  252.  
  253. int rc5EncryptCFB( CRYPT_INFO *cryptInfo, BYTE *buffer, int noBytes )
  254.     {
  255.     RC5_KEY *rc5Key = ( RC5_KEY * ) cryptInfo->key;
  256.     int i, ivCount = cryptInfo->ivCount;
  257.  
  258.     /* If there's any encrypted material left in the IV, use it now */
  259.     if( ivCount )
  260.         {
  261.         int bytesToUse;
  262.  
  263.         /* Find out how much material left in the encrypted IV we can use */
  264.         bytesToUse = RC5_BLOCKSIZE - ivCount;
  265.         if( noBytes < bytesToUse )
  266.             bytesToUse = noBytes;
  267.  
  268.         /* Encrypt the data */
  269.         for( i = 0; i < bytesToUse; i++ )
  270.             buffer[ i ] ^= cryptInfo->currentIV[ i + ivCount ];
  271.         memcpy( cryptInfo->currentIV + ivCount, buffer, bytesToUse );
  272.  
  273.         /* Adjust the byte count and buffer position */
  274.         noBytes -= bytesToUse;
  275.         buffer += bytesToUse;
  276.         ivCount += bytesToUse;
  277.         }
  278.  
  279.     while( noBytes )
  280.         {
  281.         ivCount = ( noBytes > RC5_BLOCKSIZE ) ? RC5_BLOCKSIZE : noBytes;
  282.  
  283.         /* Encrypt the IV */
  284.         rc5encrypt( rc5Key, cryptInfo->currentIV );
  285.  
  286.         /* XOR the buffer contents with the encrypted IV */
  287.         for( i = 0; i < ivCount; i++ )
  288.             buffer[ i ] ^= cryptInfo->currentIV[ i ];
  289.  
  290.         /* Shift the ciphertext into the IV */
  291.         memcpy( cryptInfo->currentIV, buffer, ivCount );
  292.  
  293.         /* Move on to next block of data */
  294.         noBytes -= ivCount;
  295.         buffer += ivCount;
  296.         }
  297.  
  298.     /* Remember how much of the IV is still available for use */
  299.     cryptInfo->ivCount = ( ivCount % RC5_BLOCKSIZE );
  300.  
  301.     return( CRYPT_OK );
  302.     }
  303.  
  304. /* Decrypt data in CFB mode.  Note that the transformation can be made
  305.    faster (but less clear) with temp = buffer, buffer ^= iv, iv = temp
  306.    all in one loop */
  307.  
  308. int rc5DecryptCFB( CRYPT_INFO *cryptInfo, BYTE *buffer, int noBytes )
  309.     {
  310.     RC5_KEY *rc5Key = ( RC5_KEY * ) cryptInfo->key;
  311.     BYTE temp[ RC5_BLOCKSIZE ];
  312.     int i, ivCount = cryptInfo->ivCount;
  313.  
  314.     /* If there's any encrypted material left in the IV, use it now */
  315.     if( ivCount )
  316.         {
  317.         int bytesToUse;
  318.  
  319.         /* Find out how much material left in the encrypted IV we can use */
  320.         bytesToUse = RC5_BLOCKSIZE - ivCount;
  321.         if( noBytes < bytesToUse )
  322.             bytesToUse = noBytes;
  323.  
  324.         /* Decrypt the data */
  325.         memcpy( temp, buffer, bytesToUse );
  326.         for( i = 0; i < bytesToUse; i++ )
  327.             buffer[ i ] ^= cryptInfo->currentIV[ i + ivCount ];
  328.         memcpy( cryptInfo->currentIV + ivCount, temp, bytesToUse );
  329.  
  330.         /* Adjust the byte count and buffer position */
  331.         noBytes -= bytesToUse;
  332.         buffer += bytesToUse;
  333.         ivCount += bytesToUse;
  334.         }
  335.  
  336.     while( noBytes )
  337.         {
  338.         ivCount = ( noBytes > RC5_BLOCKSIZE ) ? RC5_BLOCKSIZE : noBytes;
  339.  
  340.         /* Encrypt the IV */
  341.         rc5encrypt( rc5Key, cryptInfo->currentIV );
  342.  
  343.         /* Save the ciphertext */
  344.         memcpy( temp, buffer, ivCount );
  345.  
  346.         /* XOR the buffer contents with the encrypted IV */
  347.         for( i = 0; i < ivCount; i++ )
  348.             buffer[ i ] ^= cryptInfo->currentIV[ i ];
  349.  
  350.         /* Shift the ciphertext into the IV */
  351.         memcpy( cryptInfo->currentIV, temp, ivCount );
  352.  
  353.         /* Move on to next block of data */
  354.         noBytes -= ivCount;
  355.         buffer += ivCount;
  356.         }
  357.  
  358.     /* Remember how much of the IV is still available for use */
  359.     cryptInfo->ivCount = ( ivCount % RC5_BLOCKSIZE );
  360.  
  361.     /* Clear the temporary buffer */
  362.     zeroise( temp, RC5_BLOCKSIZE );
  363.  
  364.     return( CRYPT_OK );
  365.     }
  366.  
  367. /* Encrypt/decrypt data in OFB mode */
  368.  
  369. int rc5EncryptOFB( CRYPT_INFO *cryptInfo, BYTE *buffer, int noBytes )
  370.     {
  371.     RC5_KEY *rc5Key = ( RC5_KEY * ) cryptInfo->key;
  372.     int i, ivCount = cryptInfo->ivCount;
  373.  
  374.     /* If there's any encrypted material left in the IV, use it now */
  375.     if( ivCount )
  376.         {
  377.         int bytesToUse;
  378.  
  379.         /* Find out how much material left in the encrypted IV we can use */
  380.         bytesToUse = RC5_BLOCKSIZE - ivCount;
  381.         if( noBytes < bytesToUse )
  382.             bytesToUse = noBytes;
  383.  
  384.         /* Encrypt the data */
  385.         for( i = 0; i < bytesToUse; i++ )
  386.             buffer[ i ] ^= cryptInfo->currentIV[ i + ivCount ];
  387.  
  388.         /* Adjust the byte count and buffer position */
  389.         noBytes -= bytesToUse;
  390.         buffer += bytesToUse;
  391.         ivCount += bytesToUse;
  392.         }
  393.  
  394.     while( noBytes )
  395.         {
  396.         ivCount = ( noBytes > RC5_BLOCKSIZE ) ? RC5_BLOCKSIZE : noBytes;
  397.  
  398.         /* Encrypt the IV */
  399.         rc5encrypt( rc5Key, cryptInfo->currentIV );
  400.  
  401.         /* XOR the buffer contents with the encrypted IV */
  402.         for( i = 0; i < ivCount; i++ )
  403.             buffer[ i ] ^= cryptInfo->currentIV[ i ];
  404.  
  405.         /* Move on to next block of data */
  406.         noBytes -= ivCount;
  407.         buffer += ivCount;
  408.         }
  409.  
  410.     /* Remember how much of the IV is still available for use */
  411.     cryptInfo->ivCount = ( ivCount % RC5_BLOCKSIZE );
  412.  
  413.     return( CRYPT_OK );
  414.     }
  415.  
  416. /* Decrypt data in OFB mode */
  417.  
  418. int rc5DecryptOFB( CRYPT_INFO *cryptInfo, BYTE *buffer, int noBytes )
  419.     {
  420.     RC5_KEY *rc5Key = ( RC5_KEY * ) cryptInfo->key;
  421.     int i, ivCount = cryptInfo->ivCount;
  422.  
  423.     /* If there's any encrypted material left in the IV, use it now */
  424.     if( ivCount )
  425.         {
  426.         int bytesToUse;
  427.  
  428.         /* Find out how much material left in the encrypted IV we can use */
  429.         bytesToUse = RC5_BLOCKSIZE - ivCount;
  430.         if( noBytes < bytesToUse )
  431.             bytesToUse = noBytes;
  432.  
  433.         /* Decrypt the data */
  434.         for( i = 0; i < bytesToUse; i++ )
  435.             buffer[ i ] ^= cryptInfo->currentIV[ i + ivCount ];
  436.  
  437.         /* Adjust the byte count and buffer position */
  438.         noBytes -= bytesToUse;
  439.         buffer += bytesToUse;
  440.         ivCount += bytesToUse;
  441.         }
  442.  
  443.     while( noBytes )
  444.         {
  445.         ivCount = ( noBytes > RC5_BLOCKSIZE ) ? RC5_BLOCKSIZE : noBytes;
  446.  
  447.         /* Encrypt the IV */
  448.         rc5encrypt( rc5Key, cryptInfo->currentIV );
  449.  
  450.         /* XOR the buffer contents with the encrypted IV */
  451.         for( i = 0; i < ivCount; i++ )
  452.             buffer[ i ] ^= cryptInfo->currentIV[ i ];
  453.  
  454.         /* Move on to next block of data */
  455.         noBytes -= ivCount;
  456.         buffer += ivCount;
  457.         }
  458.  
  459.     /* Remember how much of the IV is still available for use */
  460.     cryptInfo->ivCount = ( ivCount % RC5_BLOCKSIZE );
  461.  
  462.     return( CRYPT_OK );
  463.     }
  464.  
  465. /* Encrypt/decrypt data in PCBC mode.  We have to carry along the previous
  466.    block's plaintext as well as the IV so we store it after the IV in the
  467.    buffer allocated for IV storage.  Initially the plaintextChain value will
  468.    be null as the IV buffer is zeroed on init, so we don't need to worry
  469.    about the special case of the first ciphertext block */
  470.  
  471. int rc5EncryptPCBC( CRYPT_INFO *cryptInfo, BYTE *buffer, int noBytes )
  472.     {
  473.     RC5_KEY *rc5Key = ( RC5_KEY * ) cryptInfo->key;
  474.     BYTE *plaintextChain = cryptInfo->currentIV + RC5_BLOCKSIZE;
  475.     BYTE temp[ RC5_BLOCKSIZE ];
  476.     int blockCount = noBytes / RC5_BLOCKSIZE;
  477.  
  478.     /* Make sure the data length is a multiple of the block size */
  479.     if( noBytes % RC5_BLOCKSIZE )
  480.         return( CRYPT_BADPARM3 );
  481.  
  482.     while( blockCount-- )
  483.         {
  484.         int i;
  485.  
  486.         /* Remember the previous block's plaintext and copy the current
  487.            plaintext for chaining in the next iteration */
  488.         memcpy( temp, plaintextChain, RC5_BLOCKSIZE );
  489.         memcpy( plaintextChain, buffer, RC5_BLOCKSIZE );
  490.  
  491.         /* XOR the buffer contents with the IV and previous plaintext */
  492.         for( i = 0; i < RC5_BLOCKSIZE; i++ )
  493.             buffer[ i ] ^= cryptInfo->currentIV[ i ] ^ temp[ i ];
  494.  
  495.         /* Encrypt a block of data */
  496.         rc5encrypt( rc5Key, buffer );
  497.  
  498.         /* Shift ciphertext into IV */
  499.         memcpy( cryptInfo->currentIV, buffer, RC5_BLOCKSIZE );
  500.  
  501.         /* Move on to next block of data */
  502.         buffer += RC5_BLOCKSIZE;
  503.         }
  504.  
  505.     /* Clear the temporary buffer */
  506.     zeroise( temp, RC5_BLOCKSIZE );
  507.  
  508.     return( CRYPT_OK );
  509.     }
  510.  
  511. int rc5DecryptPCBC( CRYPT_INFO *cryptInfo, BYTE *buffer, int noBytes )
  512.     {
  513.     RC5_KEY *rc5Key = ( RC5_KEY * ) cryptInfo->key;
  514.     BYTE *plaintextChain = cryptInfo->currentIV + RC5_BLOCKSIZE;
  515.     BYTE temp[ RC5_BLOCKSIZE ];
  516.     int blockCount = noBytes / RC5_BLOCKSIZE;
  517.  
  518.     /* Make sure the data length is a multiple of the block size */
  519.     if( noBytes % RC5_BLOCKSIZE )
  520.         return( CRYPT_BADPARM3 );
  521.  
  522.     while( blockCount-- )
  523.         {
  524.         int i;
  525.  
  526.         /* Save the ciphertext */
  527.         memcpy( temp, buffer, RC5_BLOCKSIZE );
  528.  
  529.         /* Decrypt a block of data */
  530.         rc5decrypt( rc5Key, buffer );
  531.  
  532.         /* XOR the buffer contents with the IV and previous plaintext */
  533.         for( i = 0; i < RC5_BLOCKSIZE; i++ )
  534.             buffer[ i ] ^= cryptInfo->currentIV[ i ] ^ plaintextChain[ i ];
  535.  
  536.         /* Shift the ciphertext into the IV and copy the current plaintext
  537.            for chaining in the next iteration */
  538.         memcpy( cryptInfo->currentIV, temp, RC5_BLOCKSIZE );
  539.         memcpy( plaintextChain, buffer, RC5_BLOCKSIZE );
  540.  
  541.         /* Move on to next block of data */
  542.         buffer += RC5_BLOCKSIZE;
  543.         }
  544.  
  545.     /* Clear the temporary buffer */
  546.     zeroise( temp, RC5_BLOCKSIZE );
  547.  
  548.     return( CRYPT_OK );
  549.     }
  550.  
  551.  
  552. /****************************************************************************
  553. *                                                                            *
  554. *                            RC5 Key Management Routines                        *
  555. *                                                                            *
  556. ****************************************************************************/
  557.  
  558. /* Get/set algorithm-specific parameters */
  559.  
  560. int getRC5info( const CRYPT_INFO *cryptInfo )
  561.     {
  562.     return( ( ( CRYPT_INFO_RC5 * ) cryptInfo->privateData )->rounds );
  563.     }
  564.  
  565. void setRC5info( CRYPT_INFO *cryptInfo, const int rounds )
  566.     {
  567.     ( ( CRYPT_INFO_RC5 * ) cryptInfo->privateData )->rounds = rounds;
  568.     }
  569.  
  570. /* Key schedule a RC5 key */
  571.  
  572. int rc5InitKey( CRYPT_INFO *cryptInfo )
  573.     {
  574.     CRYPT_INFO_RC5 *cryptInfoEx = ( CRYPT_INFO_RC5 * ) cryptInfo->privateData;
  575.     RC5_KEY *rc5Key = ( RC5_KEY * ) cryptInfo->key;
  576.  
  577.     /* If the number of rounds has been preset, use this value */
  578.     rc5Key->noRounds = ( cryptInfoEx->rounds != CRYPT_USE_DEFAULT ) ? \
  579.                        cryptInfoEx->rounds : RC5_DEFAULT_ROUNDS;
  580.  
  581.     rc5keyInit( rc5Key, cryptInfo->userKey, cryptInfo->userKeyLength );
  582.     return( CRYPT_OK );
  583.     }
  584.