… | |
… | |
5 | Bruce Schneier, Counterpane Systems |
5 | Bruce Schneier, Counterpane Systems |
6 | Doug Whiting, Hi/fn |
6 | Doug Whiting, Hi/fn |
7 | John Kelsey, Counterpane Systems |
7 | John Kelsey, Counterpane Systems |
8 | Chris Hall, Counterpane Systems |
8 | Chris Hall, Counterpane Systems |
9 | David Wagner, UC Berkeley |
9 | David Wagner, UC Berkeley |
10 | |
10 | |
11 | Code Author: Doug Whiting, Hi/fn |
11 | Code Author: Doug Whiting, Hi/fn |
12 | |
12 | |
13 | Version 1.00 April 1998 |
13 | Version 1.00 April 1998 |
14 | |
14 | |
15 | Copyright 1998, Hi/fn and Counterpane Systems. All rights reserved. |
15 | Copyright 1998, Hi/fn and Counterpane Systems. All rights reserved. |
16 | |
16 | |
17 | Notes: |
17 | Notes: |
18 | * Optimized version |
18 | * Optimized version |
19 | * Tab size is set to 4 characters in this file |
19 | * Tab size is set to 4 characters in this file |
20 | |
20 | |
21 | ***************************************************************************/ |
21 | ***************************************************************************/ |
… | |
… | |
103 | MDStab[2][p8(21)[_sBox8_(2)[_b(x,R+2)]] ^ b2(SKEY0)] ^ \ |
103 | MDStab[2][p8(21)[_sBox8_(2)[_b(x,R+2)]] ^ b2(SKEY0)] ^ \ |
104 | MDStab[3][p8(31)[_sBox8_(3)[_b(x,R+3)]] ^ b3(SKEY0)]) |
104 | MDStab[3][p8(31)[_sBox8_(3)[_b(x,R+3)]] ^ b3(SKEY0)]) |
105 | #define sbSet(N,i,J,v) { _sBox8_(N)[i+J] = v; } |
105 | #define sbSet(N,i,J,v) { _sBox8_(N)[i+J] = v; } |
106 | #define GetSboxKey DWORD SKEY0 = key->sboxKeys[0] /* local copy */ |
106 | #define GetSboxKey DWORD SKEY0 = key->sboxKeys[0] /* local copy */ |
107 | /*----------------------------------------------------------------*/ |
107 | /*----------------------------------------------------------------*/ |
108 | #elif defined(PART_KEY) |
108 | #elif defined(PART_KEY) |
109 | #define MOD_STRING "(Partial keying)" |
109 | #define MOD_STRING "(Partial keying)" |
110 | #define Fe32_(x,R)(MDStab[0][_sBox8_(0)[_b(x,R )]] ^ \ |
110 | #define Fe32_(x,R)(MDStab[0][_sBox8_(0)[_b(x,R )]] ^ \ |
111 | MDStab[1][_sBox8_(1)[_b(x,R+1)]] ^ \ |
111 | MDStab[1][_sBox8_(1)[_b(x,R+1)]] ^ \ |
112 | MDStab[2][_sBox8_(2)[_b(x,R+2)]] ^ \ |
112 | MDStab[2][_sBox8_(2)[_b(x,R+2)]] ^ \ |
113 | MDStab[3][_sBox8_(3)[_b(x,R+3)]]) |
113 | MDStab[3][_sBox8_(3)[_b(x,R+3)]]) |
114 | #define sbSet(N,i,J,v) { _sBox8_(N)[i+J] = v; } |
114 | #define sbSet(N,i,J,v) { _sBox8_(N)[i+J] = v; } |
115 | #define GetSboxKey |
115 | #define GetSboxKey |
116 | /*----------------------------------------------------------------*/ |
116 | /*----------------------------------------------------------------*/ |
117 | #else /* default is FULL_KEY */ |
117 | #else /* default is FULL_KEY */ |
118 | #ifndef FULL_KEY |
118 | #ifndef FULL_KEY |
119 | #define FULL_KEY 1 |
119 | #define FULL_KEY 1 |
120 | #endif |
120 | #endif |
… | |
… | |
134 | */ |
134 | */ |
135 | #define Fe32_(x,R) (_sBox_[0][2*_b(x,R )] ^ _sBox_[0][2*_b(x,R+1)+1] ^ \ |
135 | #define Fe32_(x,R) (_sBox_[0][2*_b(x,R )] ^ _sBox_[0][2*_b(x,R+1)+1] ^ \ |
136 | _sBox_[2][2*_b(x,R+2)] ^ _sBox_[2][2*_b(x,R+3)+1]) |
136 | _sBox_[2][2*_b(x,R+2)] ^ _sBox_[2][2*_b(x,R+3)+1]) |
137 | /* set a single S-box value, given the input byte */ |
137 | /* set a single S-box value, given the input byte */ |
138 | #define sbSet(N,i,J,v) { _sBox_[N&2][2*i+(N&1)+2*J]=MDStab[N][v]; } |
138 | #define sbSet(N,i,J,v) { _sBox_[N&2][2*i+(N&1)+2*J]=MDStab[N][v]; } |
139 | #define GetSboxKey |
139 | #define GetSboxKey |
140 | #endif |
140 | #endif |
141 | |
141 | |
142 | /* macro(s) for debugging help */ |
142 | /* macro(s) for debugging help */ |
143 | #define CHECK_TABLE 0 /* nonzero --> compare against "slow" table */ |
143 | #define CHECK_TABLE 0 /* nonzero --> compare against "slow" table */ |
144 | #define VALIDATE_PARMS 0 /* disable for full speed */ |
144 | #define VALIDATE_PARMS 0 /* disable for full speed */ |
… | |
… | |
157 | * |
157 | * |
158 | * Function: Handle table use checking |
158 | * Function: Handle table use checking |
159 | * |
159 | * |
160 | * Arguments: op = what to do (see TAB_* defns in AES.H) |
160 | * Arguments: op = what to do (see TAB_* defns in AES.H) |
161 | * |
161 | * |
162 | * Return: TRUE --> done (for TAB_QUERY) |
162 | * Return: TRUE --> done (for TAB_QUERY) |
163 | * |
163 | * |
164 | * Notes: This routine is for use in generating the tables KAT file. |
164 | * Notes: This routine is for use in generating the tables KAT file. |
165 | * For this optimized version, we don't actually track table usage, |
165 | * For this optimized version, we don't actually track table usage, |
166 | * since it would make the macros incredibly ugly. Instead we just |
166 | * since it would make the macros incredibly ugly. Instead we just |
167 | * run for a fixed number of queries and then say we're done. |
167 | * run for a fixed number of queries and then say we're done. |
… | |
… | |
203 | * |
203 | * |
204 | * Return: The output of the keyed permutation applied to x. |
204 | * Return: The output of the keyed permutation applied to x. |
205 | * |
205 | * |
206 | * Notes: |
206 | * Notes: |
207 | * This function is a keyed 32-bit permutation. It is the major building |
207 | * This function is a keyed 32-bit permutation. It is the major building |
208 | * block for the Twofish round function, including the four keyed 8x8 |
208 | * block for the Twofish round function, including the four keyed 8x8 |
209 | * permutations and the 4x4 MDS matrix multiply. This function is used |
209 | * permutations and the 4x4 MDS matrix multiply. This function is used |
210 | * both for generating round subkeys and within the round function on the |
210 | * both for generating round subkeys and within the round function on the |
211 | * block being encrypted. |
211 | * block being encrypted. |
212 | * |
212 | * |
213 | * This version is fairly slow and pedagogical, although a smartcard would |
213 | * This version is fairly slow and pedagogical, although a smartcard would |
214 | * probably perform the operation exactly this way in firmware. For |
214 | * probably perform the operation exactly this way in firmware. For |
215 | * ultimate performance, the entire operation can be completed with four |
215 | * ultimate performance, the entire operation can be completed with four |
216 | * lookups into four 256x32-bit tables, with three dword xors. |
216 | * lookups into four 256x32-bit tables, with three dword xors. |
… | |
… | |
220 | * |
220 | * |
221 | -****************************************************************************/ |
221 | -****************************************************************************/ |
222 | static DWORD f32(DWORD x,CONST DWORD *k32,int keyLen) |
222 | static DWORD f32(DWORD x,CONST DWORD *k32,int keyLen) |
223 | { |
223 | { |
224 | BYTE b[4]; |
224 | BYTE b[4]; |
225 | |
225 | |
226 | /* Run each byte thru 8x8 S-boxes, xoring with key byte at each stage. */ |
226 | /* Run each byte thru 8x8 S-boxes, xoring with key byte at each stage. */ |
227 | /* Note that each byte goes through a different combination of S-boxes.*/ |
227 | /* Note that each byte goes through a different combination of S-boxes.*/ |
228 | |
228 | |
229 | *((DWORD *)b) = Bswap(x); /* make b[0] = LSB, b[3] = MSB */ |
229 | *((DWORD *)b) = Bswap(x); /* make b[0] = LSB, b[3] = MSB */ |
230 | switch (((keyLen + 63)/64) & 3) |
230 | switch (((keyLen + 63)/64) & 3) |
… | |
… | |
284 | |
284 | |
285 | for (i=r=0;i<2;i++) |
285 | for (i=r=0;i<2;i++) |
286 | { |
286 | { |
287 | r ^= (i) ? k0 : k1; /* merge in 32 more key bits */ |
287 | r ^= (i) ? k0 : k1; /* merge in 32 more key bits */ |
288 | for (j=0;j<4;j++) /* shift one byte at a time */ |
288 | for (j=0;j<4;j++) /* shift one byte at a time */ |
289 | RS_rem(r); |
289 | RS_rem(r); |
290 | } |
290 | } |
291 | return r; |
291 | return r; |
292 | } |
292 | } |
293 | |
293 | |
294 | |
294 | |
… | |
… | |
326 | |
326 | |
327 | #undef Mul_1 /* change what the pre-processor does with Mij */ |
327 | #undef Mul_1 /* change what the pre-processor does with Mij */ |
328 | #undef Mul_X |
328 | #undef Mul_X |
329 | #undef Mul_Y |
329 | #undef Mul_Y |
330 | #define Mul_1 m1 /* It will now access m01[], m5B[], and mEF[] */ |
330 | #define Mul_1 m1 /* It will now access m01[], m5B[], and mEF[] */ |
331 | #define Mul_X mX |
331 | #define Mul_X mX |
332 | #define Mul_Y mY |
332 | #define Mul_Y mY |
333 | |
333 | |
334 | #define SetMDS(N) \ |
334 | #define SetMDS(N) \ |
335 | b0(d) = M0##N[P_##N##0]; \ |
335 | b0(d) = M0##N[P_##N##0]; \ |
336 | b1(d) = M1##N[P_##N##0]; \ |
336 | b1(d) = M1##N[P_##N##0]; \ |
… | |
… | |
347 | #undef Mul_X |
347 | #undef Mul_X |
348 | #undef Mul_Y |
348 | #undef Mul_Y |
349 | #define Mul_1 Mx_1 /* re-enable true multiply */ |
349 | #define Mul_1 Mx_1 /* re-enable true multiply */ |
350 | #define Mul_X Mx_X |
350 | #define Mul_X Mx_X |
351 | #define Mul_Y Mx_Y |
351 | #define Mul_Y Mx_Y |
352 | |
352 | |
353 | #if BIG_TAB |
353 | #if BIG_TAB |
354 | { |
354 | { |
355 | int j,k; |
355 | int j,k; |
356 | BYTE *q0,*q1; |
356 | BYTE *q0,*q1; |
357 | |
357 | |
… | |
… | |
431 | * The penalty is nearly 50%! So we take the code size hit for inlining for |
431 | * The penalty is nearly 50%! So we take the code size hit for inlining for |
432 | * Borland, while Microsoft happily works with a call. |
432 | * Borland, while Microsoft happily works with a call. |
433 | * |
433 | * |
434 | -****************************************************************************/ |
434 | -****************************************************************************/ |
435 | #if defined(__BORLANDC__) /* do it inline */ |
435 | #if defined(__BORLANDC__) /* do it inline */ |
436 | #define Xor32(dst,src,i) { ((DWORD *)dst)[i] = ((DWORD *)src)[i] ^ tmpX; } |
436 | #define Xor32(dst,src,i) { ((DWORD *)dst)[i] = ((DWORD *)src)[i] ^ tmpX; } |
437 | #define Xor256(dst,src,b) \ |
437 | #define Xor256(dst,src,b) \ |
438 | { \ |
438 | { \ |
439 | register DWORD tmpX=0x01010101u * b;\ |
439 | register DWORD tmpX=0x01010101u * b;\ |
440 | for (i=0;i<64;i+=4) \ |
440 | for (i=0;i<64;i+=4) \ |
441 | { Xor32(dst,src,i ); Xor32(dst,src,i+1); Xor32(dst,src,i+2); Xor32(dst,src,i+3); } \ |
441 | { Xor32(dst,src,i ); Xor32(dst,src,i+1); Xor32(dst,src,i+2); Xor32(dst,src,i+3); } \ |
… | |
… | |
466 | * |
466 | * |
467 | * Return: TRUE on success |
467 | * Return: TRUE on success |
468 | * |
468 | * |
469 | * Notes: |
469 | * Notes: |
470 | * Here we precompute all the round subkeys, although that is not actually |
470 | * Here we precompute all the round subkeys, although that is not actually |
471 | * required. For example, on a smartcard, the round subkeys can |
471 | * required. For example, on a smartcard, the round subkeys can |
472 | * be generated on-the-fly using f32() |
472 | * be generated on-the-fly using f32() |
473 | * |
473 | * |
474 | -****************************************************************************/ |
474 | -****************************************************************************/ |
475 | static int reKey(keyInstance *key) |
475 | static int reKey(keyInstance *key) |
476 | { |
476 | { |
… | |
… | |
545 | reKey_86(key); |
545 | reKey_86(key); |
546 | } |
546 | } |
547 | else |
547 | else |
548 | #endif |
548 | #endif |
549 | { |
549 | { |
550 | for (i=q=0;i<subkeyCnt/2;i++,q+=SK_STEP) |
550 | for (i=q=0;i<subkeyCnt/2;i++,q+=SK_STEP) |
551 | { /* compute round subkeys for PHT */ |
551 | { /* compute round subkeys for PHT */ |
552 | F32(A,q ,k32e); /* A uses even key dwords */ |
552 | F32(A,q ,k32e); /* A uses even key dwords */ |
553 | F32(B,q+SK_BUMP,k32o); /* B uses odd key dwords */ |
553 | F32(B,q+SK_BUMP,k32o); /* B uses odd key dwords */ |
554 | B = ROL(B,8); |
554 | B = ROL(B,8); |
555 | key->subKeys[2*i ] = A+B; /* combine with a PHT */ |
555 | key->subKeys[2*i ] = A+B; /* combine with a PHT */ |
… | |
… | |
639 | assert(f32(q,key->sboxKeys,keyLen) == Fe32_(q,0)); |
639 | assert(f32(q,key->sboxKeys,keyLen) == Fe32_(q,0)); |
640 | #endif |
640 | #endif |
641 | } |
641 | } |
642 | #endif /* CHECK_TABLE */ |
642 | #endif /* CHECK_TABLE */ |
643 | |
643 | |
644 | if (key->direction == DIR_ENCRYPT) |
644 | if (key->direction == DIR_ENCRYPT) |
645 | ReverseRoundSubkeys(key,DIR_ENCRYPT); /* reverse the round subkey order */ |
645 | ReverseRoundSubkeys(key,DIR_ENCRYPT); /* reverse the round subkey order */ |
646 | |
646 | |
647 | return TRUE; |
647 | return TRUE; |
648 | } |
648 | } |
649 | /* |
649 | /* |
… | |
… | |
667 | static int makeKey(keyInstance *key, BYTE direction, int keyLen,CONST char *keyMaterial) |
667 | static int makeKey(keyInstance *key, BYTE direction, int keyLen,CONST char *keyMaterial) |
668 | { |
668 | { |
669 | int i; |
669 | int i; |
670 | |
670 | |
671 | #if VALIDATE_PARMS /* first, sanity check on parameters */ |
671 | #if VALIDATE_PARMS /* first, sanity check on parameters */ |
672 | if (key == NULL) |
672 | if (key == NULL) |
673 | return BAD_KEY_INSTANCE;/* must have a keyInstance to initialize */ |
673 | return BAD_KEY_INSTANCE;/* must have a keyInstance to initialize */ |
674 | if ((direction != DIR_ENCRYPT) && (direction != DIR_DECRYPT)) |
674 | if ((direction != DIR_ENCRYPT) && (direction != DIR_DECRYPT)) |
675 | return BAD_KEY_DIR; /* must have valid direction */ |
675 | return BAD_KEY_DIR; /* must have valid direction */ |
676 | if ((keyLen > MAX_KEY_BITS) || (keyLen < 8) || (keyLen & 0x3F)) |
676 | if ((keyLen > MAX_KEY_BITS) || (keyLen < 8) || (keyLen & 0x3F)) |
677 | return BAD_KEY_MAT; /* length must be valid */ |
677 | return BAD_KEY_MAT; /* length must be valid */ |
… | |
… | |
687 | key->numRounds = numRounds[(keyLen-1)/64]; |
687 | key->numRounds = numRounds[(keyLen-1)/64]; |
688 | memset(key->key32,0,sizeof(key->key32)); /* zero unused bits */ |
688 | memset(key->key32,0,sizeof(key->key32)); /* zero unused bits */ |
689 | |
689 | |
690 | if (keyMaterial == NULL) |
690 | if (keyMaterial == NULL) |
691 | return TRUE; /* allow a "dummy" call */ |
691 | return TRUE; /* allow a "dummy" call */ |
692 | |
692 | |
693 | for (i=0;i<keyLen/32;i++) /* make byte-oriented copy for CFB1 */ |
693 | for (i=0;i<keyLen/32;i++) /* make byte-oriented copy for CFB1 */ |
694 | key->key32[i] = (((unsigned char *)keyMaterial)[i*4+0] << 0) |
694 | key->key32[i] = (((unsigned char *)keyMaterial)[i*4+0] << 0) |
695 | | (((unsigned char *)keyMaterial)[i*4+1] << 8) |
695 | | (((unsigned char *)keyMaterial)[i*4+1] << 8) |
696 | | (((unsigned char *)keyMaterial)[i*4+2] << 16) |
696 | | (((unsigned char *)keyMaterial)[i*4+2] << 16) |
697 | | (((unsigned char *)keyMaterial)[i*4+3] << 24); |
697 | | (((unsigned char *)keyMaterial)[i*4+3] << 24); |
… | |
… | |
717 | -****************************************************************************/ |
717 | -****************************************************************************/ |
718 | static int cipherInit(cipherInstance *cipher, BYTE mode,CONST char *IV) |
718 | static int cipherInit(cipherInstance *cipher, BYTE mode,CONST char *IV) |
719 | { |
719 | { |
720 | int i; |
720 | int i; |
721 | #if VALIDATE_PARMS /* first, sanity check on parameters */ |
721 | #if VALIDATE_PARMS /* first, sanity check on parameters */ |
722 | if (cipher == NULL) |
722 | if (cipher == NULL) |
723 | return BAD_PARAMS; /* must have a cipherInstance to initialize */ |
723 | return BAD_PARAMS; /* must have a cipherInstance to initialize */ |
724 | if ((mode != MODE_ECB) && (mode != MODE_CBC) && (mode != MODE_CFB1)) |
724 | if ((mode != MODE_ECB) && (mode != MODE_CBC) && (mode != MODE_CFB1)) |
725 | return BAD_CIPHER_MODE; /* must have valid cipher mode */ |
725 | return BAD_CIPHER_MODE; /* must have valid cipher mode */ |
726 | cipher->cipherSig = VALID_SIG; |
726 | cipher->cipherSig = VALID_SIG; |
727 | #if ALIGN32 |
727 | #if ALIGN32 |
… | |
… | |
758 | * Return: # bits ciphered (>= 0) |
758 | * Return: # bits ciphered (>= 0) |
759 | * else error code (e.g., BAD_CIPHER_STATE, BAD_KEY_MATERIAL) |
759 | * else error code (e.g., BAD_CIPHER_STATE, BAD_KEY_MATERIAL) |
760 | * |
760 | * |
761 | * Notes: The only supported block size for ECB/CBC modes is BLOCK_SIZE bits. |
761 | * Notes: The only supported block size for ECB/CBC modes is BLOCK_SIZE bits. |
762 | * If inputLen is not a multiple of BLOCK_SIZE bits in those modes, |
762 | * If inputLen is not a multiple of BLOCK_SIZE bits in those modes, |
763 | * an error BAD_INPUT_LEN is returned. In CFB1 mode, all block |
763 | * an error BAD_INPUT_LEN is returned. In CFB1 mode, all block |
764 | * sizes can be supported. |
764 | * sizes can be supported. |
765 | * |
765 | * |
766 | -****************************************************************************/ |
766 | -****************************************************************************/ |
767 | static int blockEncrypt(cipherInstance *cipher, keyInstance *key,CONST BYTE *input, |
767 | static int blockEncrypt(cipherInstance *cipher, keyInstance *key,CONST BYTE *input, |
768 | int inputLen, BYTE *outBuffer) |
768 | int inputLen, BYTE *outBuffer) |
… | |
… | |
824 | #ifdef USE_ASM |
824 | #ifdef USE_ASM |
825 | if ((useAsm & 1) && (inputLen)) |
825 | if ((useAsm & 1) && (inputLen)) |
826 | #ifdef COMPILE_KEY |
826 | #ifdef COMPILE_KEY |
827 | if (key->keySig == VALID_SIG) |
827 | if (key->keySig == VALID_SIG) |
828 | return ((CipherProc *)(key->encryptFuncPtr))(cipher,key,input,inputLen,outBuffer); |
828 | return ((CipherProc *)(key->encryptFuncPtr))(cipher,key,input,inputLen,outBuffer); |
829 | #else |
829 | #else |
830 | return (*blockEncrypt_86)(cipher,key,input,inputLen,outBuffer); |
830 | return (*blockEncrypt_86)(cipher,key,input,inputLen,outBuffer); |
831 | #endif |
831 | #endif |
832 | #endif |
832 | #endif |
833 | /* make local copy of subkeys for speed */ |
833 | /* make local copy of subkeys for speed */ |
834 | memcpy(sk,key->subKeys,sizeof(DWORD)*(ROUND_SUBKEYS+2*rounds)); |
834 | memcpy(sk,key->subKeys,sizeof(DWORD)*(ROUND_SUBKEYS+2*rounds)); |
… | |
… | |
915 | * Return: # bits ciphered (>= 0) |
915 | * Return: # bits ciphered (>= 0) |
916 | * else error code (e.g., BAD_CIPHER_STATE, BAD_KEY_MATERIAL) |
916 | * else error code (e.g., BAD_CIPHER_STATE, BAD_KEY_MATERIAL) |
917 | * |
917 | * |
918 | * Notes: The only supported block size for ECB/CBC modes is BLOCK_SIZE bits. |
918 | * Notes: The only supported block size for ECB/CBC modes is BLOCK_SIZE bits. |
919 | * If inputLen is not a multiple of BLOCK_SIZE bits in those modes, |
919 | * If inputLen is not a multiple of BLOCK_SIZE bits in those modes, |
920 | * an error BAD_INPUT_LEN is returned. In CFB1 mode, all block |
920 | * an error BAD_INPUT_LEN is returned. In CFB1 mode, all block |
921 | * sizes can be supported. |
921 | * sizes can be supported. |
922 | * |
922 | * |
923 | -****************************************************************************/ |
923 | -****************************************************************************/ |
924 | static int blockDecrypt(cipherInstance *cipher, keyInstance *key,CONST BYTE *input, |
924 | static int blockDecrypt(cipherInstance *cipher, keyInstance *key,CONST BYTE *input, |
925 | int inputLen, BYTE *outBuffer) |
925 | int inputLen, BYTE *outBuffer) |
… | |
… | |
981 | #ifdef USE_ASM |
981 | #ifdef USE_ASM |
982 | if ((useAsm & 2) && (inputLen)) |
982 | if ((useAsm & 2) && (inputLen)) |
983 | #ifdef COMPILE_KEY |
983 | #ifdef COMPILE_KEY |
984 | if (key->keySig == VALID_SIG) |
984 | if (key->keySig == VALID_SIG) |
985 | return ((CipherProc *)(key->decryptFuncPtr))(cipher,key,input,inputLen,outBuffer); |
985 | return ((CipherProc *)(key->decryptFuncPtr))(cipher,key,input,inputLen,outBuffer); |
986 | #else |
986 | #else |
987 | return (*blockDecrypt_86)(cipher,key,input,inputLen,outBuffer); |
987 | return (*blockDecrypt_86)(cipher,key,input,inputLen,outBuffer); |
988 | #endif |
988 | #endif |
989 | #endif |
989 | #endif |
990 | /* make local copy of subkeys for speed */ |
990 | /* make local copy of subkeys for speed */ |
991 | memcpy(sk,key->subKeys,sizeof(DWORD)*(ROUND_SUBKEYS+2*rounds)); |
991 | memcpy(sk,key->subKeys,sizeof(DWORD)*(ROUND_SUBKEYS+2*rounds)); |