Crypt-Twofish2

 view release on metacpan or  search on metacpan

README  view on Meta::CPAN

NAME
    Crypt::Twofish2 - Crypt::CBC compliant Twofish encryption module

SYNOPSIS
     use Crypt::Twofish2;

     # keysize() is 32, but 24 and 16 are also possible
     # blocksize() is 16

     $cipher = new Crypt::Twofish2 "a" x 32, Crypt::Twofish2::MODE_CBC;

     $crypted = $cipher->encrypt($plaintext);
     # - OR -
     $plaintext = $cipher->decrypt($crypted);

DESCRIPTION
    This module implements the twofish cipher in a less braindamaged (read:
    slow and ugly) way than the existing "Crypt::Twofish" module.

    Although it is "Crypt::CBC" compliant you usually gain nothing by using
    that module (except generality, which is often a good thing), since
    "Crypt::Twofish2" can work in either ECB or CBC mode itself.

    keysize
        Returns the keysize, which is 32 (bytes). The Twofish2 cipher
        actually supports keylengths of 16, 24 or 32 bytes, but there is no
        way to communicate this to "Crypt::CBC".

    blocksize
        The blocksize for Twofish2 is 16 bytes (128 bits), which is somewhat
        unique. It is also the reason I need this module myself ;)

    $cipher = new $key [, $mode]
        Create a new "Crypt::Twofish2" cipher object with the given key
        (which must be 128, 192 or 256 bits long). The additional $mode
        argument is the encryption mode, either "MODE_ECB" (electronic
        cookbook mode, the default), "MODE_CBC" (cipher block chaining, the
        same that "Crypt::CBC" does) or "MODE_CFB1" (1-bit cipher feedback
        mode).

        ECB mode is very insecure (read a book on cryptography if you don't
        know why!), so you should probably use CBC mode. CFB1 mode is not
        tested and is most probably broken, so do not try to use it.

        In ECB mode you can use the same cipher object to encrypt and
        decrypt data. However, every change of "direction" causes an
        internal reordering of key data, which is quite slow, so if you want
        ECB mode and encryption/decryption at the same time you should
        create two seperate "Crypt::Twofish2" objects with the same key.

        In CBC mode you have to use seperate objects for
        encryption/decryption in any case.

        The "MODE_*"-constants are not exported by this module, so you must
        specify them as "Crypt::Twofish2::MODE_CBC" etc. (sorry for that).

    $cipher->encrypt($data)
        Encrypt data. The size of $data must be a multiple of "blocksize"
        (16 bytes), otherwise this function will croak. Apart from that, it
        can be of (almost) any length.

    $cipher->decrypt($data)
        The pendant to "encrypt" in that it *de*crypts data again.

SEE ALSO
    Crypt::CBC, Crypt::Twofish.

BUGS
    Should EXPORT or EXPORT_OK the MODE constants.

    There should be a way to access initial IV contents :(

    Although I tried to make the original twofish code portable, I can't say
    how much I did succeed. The code tries to be portable itself, and I hope
    I got the endianness issues right. The code is also copyright
    Counterpane Systems, no license accompanied it, so using it might

Twofish2.pm  view on Meta::CPAN

=head1 NAME

Crypt::Twofish2 - Crypt::CBC compliant Twofish encryption module

=head1 SYNOPSIS

 use Crypt::Twofish2;

 # keysize() is 32, but 24 and 16 are also possible
 # blocksize() is 16

 $cipher = new Crypt::Twofish2 "a" x 32, Crypt::Twofish2::MODE_CBC;

 $crypted = $cipher->encrypt($plaintext);
 # - OR -
 $plaintext = $cipher->decrypt($crypted);

=head1 DESCRIPTION

This module implements the twofish cipher in a less braindamaged (read:
slow and ugly) way than the existing C<Crypt::Twofish> module.

Although it is C<Crypt::CBC> compliant you usually gain nothing by using
that module (except generality, which is often a good thing), since
C<Crypt::Twofish2> can work in either ECB or CBC mode itself.

=over 4

=cut

package Crypt::Twofish2;

use XSLoader;

$VERSION = '1.03';

XSLoader::load __PACKAGE__, $VERSION;

=item keysize

Returns the keysize, which is 32 (bytes). The Twofish2 cipher actually
supports keylengths of 16, 24 or 32 bytes, but there is no way to
communicate this to C<Crypt::CBC>.

=item blocksize

The blocksize for Twofish2 is 16 bytes (128 bits), which is somewhat
unique. It is also the reason I need this module myself ;)

=item $cipher = new $key [, $mode]

Create a new C<Crypt::Twofish2> cipher object with the given key (which
must be 128, 192 or 256 bits long). The additional C<$mode> argument is
the encryption mode, either C<MODE_ECB> (electronic cookbook mode, the
default), C<MODE_CBC> (cipher block chaining, the same that C<Crypt::CBC>
does) or C<MODE_CFB1> (1-bit cipher feedback mode).

ECB mode is very insecure (read a book on cryptography if you don't know
why!), so you should probably use CBC mode. CFB1 mode is not tested and is
most probably broken, so do not try to use it.

In ECB mode you can use the same cipher object to encrypt and decrypt
data. However, every change of "direction" causes an internal reordering
of key data, which is quite slow, so if you want ECB mode and
encryption/decryption at the same time you should create two seperate
C<Crypt::Twofish2> objects with the same key.

In CBC mode you have to use seperate objects for encryption/decryption in
any case.

The C<MODE_*>-constants are not exported by this module, so you must
specify them as C<Crypt::Twofish2::MODE_CBC> etc. (sorry for that).

=item $cipher->encrypt($data)

Encrypt data. The size of C<$data> must be a multiple of C<blocksize> (16
bytes), otherwise this function will croak. Apart from that, it can be of
(almost) any length.

=item $cipher->decrypt($data)

The pendant to C<encrypt> in that it I<de>crypts data again.

=back

=head1 SEE ALSO

L<Crypt::CBC>, L<Crypt::Twofish>.

=head1 BUGS

Should EXPORT or EXPORT_OK the MODE constants.

There should be a way to access initial IV contents :(

Although I tried to make the original twofish code portable, I can't say
how much I did succeed. The code tries to be portable itself, and I hope
I got the endianness issues right. The code is also copyright Counterpane

Twofish2.xs  view on Meta::CPAN


PROTOTYPES: ENABLE

BOOT:
{
	HV *stash = gv_stashpv ("Crypt::Twofish2", 0);

	newCONSTSUB (stash, "keysize",   newSViv (32));
	newCONSTSUB (stash, "blocksize", newSViv (16));
	newCONSTSUB (stash, "MODE_ECB",  newSViv (MODE_ECB));
	newCONSTSUB (stash, "MODE_CBC",  newSViv (MODE_CBC));
	newCONSTSUB (stash, "MODE_CFB1", newSViv (MODE_CFB1));
}

Crypt::Twofish2
new(class, key, mode=MODE_ECB)
	SV *	class
	SV *	key
        int	mode
        CODE:
        {
          STRLEN keysize;
          
          if (!SvPOK (key))
            croak ("key must be a string scalar");

          keysize = SvCUR(key);

          if (keysize != 16 && keysize != 24 && keysize != 32)
            croak ("wrong key length: key must be 128, 192 or 256 bits long");
          if (mode != MODE_ECB && mode != MODE_CBC && mode != MODE_CFB1)
            croak ("illegal mode: mode must be MODE_ECB, MODE_2 or MODE_CFB1");

          Newz (0, RETVAL, 1, struct cryptstate); /* Newz required for defined IV */
          
          if (makeKey (&RETVAL->ki, DIR_ENCRYPT, keysize*8, SvPV_nolen(key)) != TRUE)
            croak ("Crypt::Twofish2: makeKey failed, please report!");
          if (cipherInit (&RETVAL->ci, mode, 0) != TRUE) /* no IV supported (yet) */
            croak ("Crypt::Twofish2: makeKey failed, please report!");
        }         
	OUTPUT:

aes.h  view on Meta::CPAN

#include    <stdio.h>
#include    "platform.h"            /* platform-specific defines */

/*  Defines:
        Add any additional defines you need
*/

#define     DIR_ENCRYPT     0       /* Are we encrpyting? */
#define     DIR_DECRYPT     1       /* Are we decrpyting? */
#define     MODE_ECB        1       /* Are we ciphering in ECB mode? */
#define     MODE_CBC        2       /* Are we ciphering in CBC mode? */
#define     MODE_CFB1       3       /* Are we ciphering in 1-bit CFB mode? */

#define     BAD_KEY_DIR         -5  /* Key direction is invalid (unknown value) */
#define     BAD_KEY_MAT         -6  /* Key material not of correct length */
#define     BAD_KEY_INSTANCE    -7  /* Key passed is not valid */
#define     BAD_CIPHER_MODE     -8  /* Params struct passed to cipherInit invalid */
#define     BAD_CIPHER_STATE    -9  /* Cipher in wrong state (e.g., not initialized) */

/* CHANGE POSSIBLE: inclusion of algorithm specific defines */
/* TWOFISH specific definitions */

aes.h  view on Meta::CPAN

    DWORD codeSize;                 /* size of compiledCode */
    DWORD cSig2;                    /* set after first "compile" */
    BYTE  compiledCode[5000];       /* make room for the code itself */
  #endif
#endif
    } keyInstance;

/* The structure for cipher information */
typedef struct
    {
    BYTE  mode;                     /* MODE_ECB, MODE_CBC, or MODE_CFB1 */
#if ALIGN32
    BYTE dummyAlign[3];             /* keep 32-bit alignment */
#endif
    BYTE  IV[MAX_IV_SIZE];          /* CFB1 iv bytes  (CBC uses iv32) */

    /* Twofish-specific parameters: */
    DWORD cipherSig;                /* set to VALID_SIG by cipherInit() */
    DWORD iv32[BLOCK_SIZE/32];      /* CBC IV bytes arranged as dwords */
    } cipherInstance;

/* Function protoypes */
static int makeKey(keyInstance *key, BYTE direction, int keyLen, char *keyMaterial);

static int cipherInit(cipherInstance *cipher, BYTE mode, char *IV);

static int blockEncrypt(cipherInstance *cipher, keyInstance *key, BYTE *input,
                int inputLen, BYTE *outBuffer);

aes.h  view on Meta::CPAN


#include <stdio.h>
#include <stdlib.h>
#include <time.h>
#include <string.h>

#define MAX_BLK_CNT     4       /* max # blocks per call in TestTwofish */
static int TestTwofish(int mode,int keySize) /* keySize must be 128, 192, or 256 */
    {                           /* return 0 iff test passes */
    keyInstance    ki;          /* key information, including tables */
    cipherInstance ci;          /* keeps mode (ECB, CBC) and IV */
    BYTE  plainText[MAX_BLK_CNT*(BLOCK_SIZE/8)];
    BYTE cipherText[MAX_BLK_CNT*(BLOCK_SIZE/8)];
    BYTE decryptOut[MAX_BLK_CNT*(BLOCK_SIZE/8)];
    BYTE iv[BLOCK_SIZE/8];
    int  i,byteCnt;

    if (makeKey(&ki,DIR_ENCRYPT,keySize,NULL) != TRUE)
        return 1;               /* 'dummy' setup for a 128-bit key */
    if (cipherInit(&ci,mode,NULL) != TRUE)
        return 1;               /* 'dummy' setup for cipher */

aes.h  view on Meta::CPAN

    {
    int testCnt,keySize;

    srand((unsigned) time(NULL));   /* randomize */

    for (keySize=128;keySize<=256;keySize+=64)
        for (testCnt=0;testCnt<10;testCnt++)
            {
            if (TestTwofish(MODE_ECB,keySize))
                { printf("ECB Failure at keySize=%d",keySize); return; }
            if (TestTwofish(MODE_CBC,keySize))
                { printf("CBC Failure at keySize=%d",keySize); return; }
            }
    printf("Tests passed");
    }
#endif /* TEST_2FISH */

#endif

t/00_load.t  view on Meta::CPAN

END {print "not ok 1\n" unless $loaded;}
use Crypt::Twofish2;
$loaded = 1;
print "ok 1\n";

$i = 2;

$plaintext = ("p" x 30)."xi";
$key = "po".("k"  x 30);

$cbc = new Crypt::Twofish2 $key, Crypt::Twofish2::MODE_CBC;
$crypted = $cbc->encrypt($plaintext);
print unpack("H*", $crypted) eq "57a627f0aca655dc495e15e30354a6334825f10ba9d2d20441b84ffc504d2942" ? "" : "not ", "ok ".$i++."\n";
$crypted2 = $cbc->encrypt($plaintext);
print unpack("H*", $crypted2) eq "440996719ae702988b631db5820ad94e76603972835342bbbc99311654a4d6ba" ? "" : "not ", "ok ".$i++."\n";

$cbc = new Crypt::Twofish2 $key, Crypt::Twofish2::MODE_CBC;
print $cbc->decrypt($crypted)  eq $plaintext ? "" : "not ", "ok ".$i++."\n";
print $cbc->decrypt($crypted2) eq $plaintext ? "" : "not ", "ok ".$i++."\n";

# now try the test vectors provided

while (<DATA>) {
   if (/KEY=(\S+)\s+PT=(\S+)\s+CT=(\S+)\s+/) {
      my $key = pack "H*", $1;
      my $pt  = pack "H*", $2;
      my $ct  = pack "H*", $3;

t/00_load.t  view on Meta::CPAN


KEY=00000000000000000000000000000000 PT=00000000000000000000000000000000 CT=9F589F5CF6122C32B6BFEC2F2AE8C35A
KEY=0123456789ABCDEFFEDCBA98765432100011223344556677 PT=00000000000000000000000000000000 CT=CFD1D2E5A9BE9CDF501F13B892BD2248
KEY=0123456789ABCDEFFEDCBA987654321000112233445566778899AABBCCDDEEFF PT=00000000000000000000000000000000 CT=37527BE0052334B89F0CFCCAE87CFA20
KEY=00000000000000000000000000000000 PT=00000000000000000000000000000000 CT=9F589F5CF6122C32B6BFEC2F2AE8C35A
KEY=00000000000000000000000000000000 PT=9F589F5CF6122C32B6BFEC2F2AE8C35A CT=D491DB16E7B1C39E86CB086B789F5419
KEY=9F589F5CF6122C32B6BFEC2F2AE8C35A PT=D491DB16E7B1C39E86CB086B789F5419 CT=019F9809DE1711858FAAC3A3BA20FBC3
KEY=D491DB16E7B1C39E86CB086B789F5419 PT=019F9809DE1711858FAAC3A3BA20FBC3 CT=6363977DE839486297E661C6C9D668EB
KEY=019F9809DE1711858FAAC3A3BA20FBC3 PT=6363977DE839486297E661C6C9D668EB CT=816D5BD0FAE35342BF2A7412C246F752
KEY=6363977DE839486297E661C6C9D668EB PT=816D5BD0FAE35342BF2A7412C246F752 CT=5449ECA008FF5921155F598AF4CED4D0
KEY=816D5BD0FAE35342BF2A7412C246F752 PT=5449ECA008FF5921155F598AF4CED4D0 CT=6600522E97AEB3094ED5F92AFCBCDD10
KEY=5449ECA008FF5921155F598AF4CED4D0 PT=6600522E97AEB3094ED5F92AFCBCDD10 CT=34C8A5FB2D3D08A170D120AC6D26DBFA
KEY=6600522E97AEB3094ED5F92AFCBCDD10 PT=34C8A5FB2D3D08A170D120AC6D26DBFA CT=28530B358C1B42EF277DE6D4407FC591
KEY=34C8A5FB2D3D08A170D120AC6D26DBFA PT=28530B358C1B42EF277DE6D4407FC591 CT=8A8AB983310ED78C8C0ECDE030B8DCA4
KEY=137A24CA47CD12BE818DF4D2F4355960 PT=BCA724A54533C6987E14AA827952F921 CT=6B459286F3FFD28D49F15B1581B08E42
KEY=BCA724A54533C6987E14AA827952F921 PT=6B459286F3FFD28D49F15B1581B08E42 CT=5D9D4EEFFA9151575524F115815A12E0
KEY=000000000000000000000000000000000000000000000000 PT=00000000000000000000000000000000 CT=EFA71F788965BD4453F860178FC19101
KEY=000000000000000000000000000000000000000000000000 PT=EFA71F788965BD4453F860178FC19101 CT=88B2B2706B105E36B446BB6D731A1E88
KEY=EFA71F788965BD4453F860178FC191010000000000000000 PT=88B2B2706B105E36B446BB6D731A1E88 CT=39DA69D6BA4997D585B6DC073CA341B2
KEY=88B2B2706B105E36B446BB6D731A1E88EFA71F788965BD44 PT=39DA69D6BA4997D585B6DC073CA341B2 CT=182B02D81497EA45F9DAACDC29193A65
KEY=39DA69D6BA4997D585B6DC073CA341B288B2B2706B105E36 PT=182B02D81497EA45F9DAACDC29193A65 CT=7AFF7A70CA2FF28AC31DD8AE5DAAAB63
KEY=182B02D81497EA45F9DAACDC29193A6539DA69D6BA4997D5 PT=7AFF7A70CA2FF28AC31DD8AE5DAAAB63 CT=D1079B789F666649B6BD7D1629F1F77E
KEY=7AFF7A70CA2FF28AC31DD8AE5DAAAB63182B02D81497EA45 PT=D1079B789F666649B6BD7D1629F1F77E CT=3AF6F7CE5BD35EF18BEC6FA787AB506B

twofish.c  view on Meta::CPAN



/*
+*****************************************************************************
*
* Function Name:    cipherInit
*
* Function:         Initialize the Twofish cipher in a given mode
*
* Arguments:        cipher      =   ptr to cipherInstance to be initialized
*                   mode        =   MODE_ECB, MODE_CBC, or MODE_CFB1
*                   IV          =   ptr to hex ASCII test representing IV bytes
*
* Return:           TRUE on success
*                   else error code (e.g., BAD_CIPHER_MODE)
*
-****************************************************************************/
static int cipherInit(cipherInstance *cipher, BYTE mode,CONST char *IV)
    {
    int i;
#if VALIDATE_PARMS              /* first, sanity check on parameters */
    if (cipher == NULL)
        return BAD_PARAMS;      /* must have a cipherInstance to initialize */
    if ((mode != MODE_ECB) && (mode != MODE_CBC) && (mode != MODE_CFB1))
        return BAD_CIPHER_MODE; /* must have valid cipher mode */
    cipher->cipherSig   =   VALID_SIG;
  #if ALIGN32
    if ((((int)cipher) & 3) || (((int)cipher->IV) & 3) || (((int)cipher->iv32) & 3))
        return BAD_ALIGN32;
  #endif
#endif

    if ((mode != MODE_ECB) && (IV)) /* parse the IV */
        {

twofish.c  view on Meta::CPAN

*
* Arguments:        cipher      =   ptr to already initialized cipherInstance
*                   key         =   ptr to already initialized keyInstance
*                   input       =   ptr to data blocks to be encrypted
*                   inputLen    =   # bits to encrypt (multiple of blockSize)
*                   outBuffer   =   ptr to where to put encrypted blocks
*
* Return:           # bits ciphered (>= 0)
*                   else error code (e.g., BAD_CIPHER_STATE, BAD_KEY_MATERIAL)
*
* Notes: The only supported block size for ECB/CBC modes is BLOCK_SIZE bits.
*        If inputLen is not a multiple of BLOCK_SIZE bits in those modes,
*        an error BAD_INPUT_LEN is returned.  In CFB1 mode, all block
*        sizes can be supported.
*
-****************************************************************************/
static int blockEncrypt(cipherInstance *cipher, keyInstance *key,CONST BYTE *input,
                int inputLen, BYTE *outBuffer)
    {
    int   i,n;                      /* loop counters */
    DWORD x[BLOCK_SIZE/32];         /* block being encrypted */

twofish.c  view on Meta::CPAN

                {
                bit = cipher->IV[i] >> 7;   /* save next "carry" from shift */
                cipher->IV[i] = (cipher->IV[i] << 1) ^ carry;
                carry = bit;
                }
            }
        cipher->mode = MODE_CFB1;   /* restore mode for next time */
        return inputLen;
        }

    /* here for ECB, CBC modes */
    if (key->direction != DIR_ENCRYPT)
        ReverseRoundSubkeys(key,DIR_ENCRYPT);   /* reverse the round subkey order */

#ifdef USE_ASM
    if ((useAsm & 1) && (inputLen))
  #ifdef COMPILE_KEY
        if (key->keySig == VALID_SIG)
            return ((CipherProc *)(key->encryptFuncPtr))(cipher,key,input,inputLen,outBuffer);
  #else
        return (*blockEncrypt_86)(cipher,key,input,inputLen,outBuffer);
  #endif
#endif
    /* make local copy of subkeys for speed */
    memcpy(sk,key->subKeys,sizeof(DWORD)*(ROUND_SUBKEYS+2*rounds));
    if (mode == MODE_CBC)
        BlockCopy(IV,cipher->iv32)
    else
        IV[0]=IV[1]=IV[2]=IV[3]=0;

    for (n=0;n<inputLen;n+=BLOCK_SIZE,input+=BLOCK_SIZE/8,outBuffer+=BLOCK_SIZE/8)
        {
#define LoadBlockE(N)  x[N]=Bswap(((DWORD *)input)[N]) ^ sk[INPUT_WHITEN+N] ^ IV[N]
        LoadBlockE(0);  LoadBlockE(1);  LoadBlockE(2);  LoadBlockE(3);
#define EncryptRound(K,R,id)    \
            t0     = Fe32##id(x[K  ],0);                    \

twofish.c  view on Meta::CPAN

        Encrypt2( 0,_);
#endif

        /* need to do (or undo, depending on your point of view) final swap */
#if LittleEndian
#define StoreBlockE(N)  ((DWORD *)outBuffer)[N]=x[N^2] ^ sk[OUTPUT_WHITEN+N]
#else
#define StoreBlockE(N)  { t0=x[N^2] ^ sk[OUTPUT_WHITEN+N]; ((DWORD *)outBuffer)[N]=Bswap(t0); }
#endif
        StoreBlockE(0); StoreBlockE(1); StoreBlockE(2); StoreBlockE(3);
        if (mode == MODE_CBC)
            {
            IV[0]=Bswap(((DWORD *)outBuffer)[0]);
            IV[1]=Bswap(((DWORD *)outBuffer)[1]);
            IV[2]=Bswap(((DWORD *)outBuffer)[2]);
            IV[3]=Bswap(((DWORD *)outBuffer)[3]);
            }
        }

    if (mode == MODE_CBC)
        BlockCopy(cipher->iv32,IV);

    return inputLen;
    }

/*
+*****************************************************************************
*
* Function Name:    blockDecrypt
*

twofish.c  view on Meta::CPAN

*
* Arguments:        cipher      =   ptr to already initialized cipherInstance
*                   key         =   ptr to already initialized keyInstance
*                   input       =   ptr to data blocks to be decrypted
*                   inputLen    =   # bits to encrypt (multiple of blockSize)
*                   outBuffer   =   ptr to where to put decrypted blocks
*
* Return:           # bits ciphered (>= 0)
*                   else error code (e.g., BAD_CIPHER_STATE, BAD_KEY_MATERIAL)
*
* Notes: The only supported block size for ECB/CBC modes is BLOCK_SIZE bits.
*        If inputLen is not a multiple of BLOCK_SIZE bits in those modes,
*        an error BAD_INPUT_LEN is returned.  In CFB1 mode, all block
*        sizes can be supported.
*
-****************************************************************************/
static int blockDecrypt(cipherInstance *cipher, keyInstance *key,CONST BYTE *input,
                int inputLen, BYTE *outBuffer)
    {
    int   i,n;                      /* loop counters */
    DWORD x[BLOCK_SIZE/32];         /* block being encrypted */

twofish.c  view on Meta::CPAN

                {
                bit = cipher->IV[i] >> 7;   /* save next "carry" from shift */
                cipher->IV[i] = (cipher->IV[i] << 1) ^ carry;
                carry = bit;
                }
            }
        cipher->mode = MODE_CFB1;   /* restore mode for next time */
        return inputLen;
        }

    /* here for ECB, CBC modes */
    if (key->direction != DIR_DECRYPT)
        ReverseRoundSubkeys(key,DIR_DECRYPT);   /* reverse the round subkey order */
#ifdef USE_ASM
    if ((useAsm & 2) && (inputLen))
  #ifdef COMPILE_KEY
        if (key->keySig == VALID_SIG)
            return ((CipherProc *)(key->decryptFuncPtr))(cipher,key,input,inputLen,outBuffer);
  #else
        return (*blockDecrypt_86)(cipher,key,input,inputLen,outBuffer);
  #endif
#endif
    /* make local copy of subkeys for speed */
    memcpy(sk,key->subKeys,sizeof(DWORD)*(ROUND_SUBKEYS+2*rounds));
    if (mode == MODE_CBC)
        BlockCopy(IV,cipher->iv32)
    else
        IV[0]=IV[1]=IV[2]=IV[3]=0;

    for (n=0;n<inputLen;n+=BLOCK_SIZE,input+=BLOCK_SIZE/8,outBuffer+=BLOCK_SIZE/8)
        {
#define LoadBlockD(N) x[N^2]=Bswap(((DWORD *)input)[N]) ^ sk[OUTPUT_WHITEN+N]
        LoadBlockD(0);  LoadBlockD(1);  LoadBlockD(2);  LoadBlockD(3);

#define DecryptRound(K,R,id)                                \

twofish.c  view on Meta::CPAN

            }
        else
            {
#define StoreBlockD(N)  x[N]   ^= sk[INPUT_WHITEN+N] ^ IV[N];   \
                        IV[N]   = Bswap(((DWORD *)input)[N]);   \
                        ((DWORD *)outBuffer)[N] = Bswap(x[N]);
            StoreBlockD(0); StoreBlockD(1); StoreBlockD(2); StoreBlockD(3);
#undef  StoreBlockD
            }
        }
    if (mode == MODE_CBC)   /* restore iv32 to cipher */
        BlockCopy(cipher->iv32,IV)

    return inputLen;
    }

#ifdef GetCodeSize
static DWORD TwofishCodeSize(void)
    {
    DWORD x= Here(0);
#ifdef USE_ASM



( run in 0.783 second using v1.01-cache-2.11-cpan-e1769b4cff6 )