Fossil SCM
Optimizations to the SHA3 algorithm.
Commit
493321d44f314d33d44cd779ce430e4d80c5b582
Parent
b015ad715d8a14d…
1 file changed
+58
-9
+58
-9
| --- src/sha3.c | ||
| +++ src/sha3.c | ||
| @@ -1,10 +1,33 @@ | ||
| 1 | 1 | /* |
| 2 | 2 | ** This file contains an implementation of SHA3 (Keccak) hashing. |
| 3 | 3 | */ |
| 4 | 4 | #include "config.h" |
| 5 | 5 | #include "sha3.h" |
| 6 | + | |
| 7 | +/* | |
| 8 | +** Macros to determine whether the machine is big or little endian, | |
| 9 | +** and whether or not that determination is run-time or compile-time. | |
| 10 | +** | |
| 11 | +** For best performance, an attempt is made to guess at the byte-order | |
| 12 | +** using C-preprocessor macros. If that is unsuccessful, or if | |
| 13 | +** -DSHA3_BYTEORDER=0 is set, then byte-order is determined | |
| 14 | +** at run-time. | |
| 15 | +*/ | |
| 16 | +#ifndef SHA3_BYTEORDER | |
| 17 | +# if defined(i386) || defined(__i386__) || defined(_M_IX86) || \ | |
| 18 | + defined(__x86_64) || defined(__x86_64__) || defined(_M_X64) || \ | |
| 19 | + defined(_M_AMD64) || defined(_M_ARM) || defined(__x86) || \ | |
| 20 | + defined(__arm__) | |
| 21 | +# define SHA3_BYTEORDER 1234 | |
| 22 | +# elif defined(sparc) || defined(__ppc__) | |
| 23 | +# define SHA3_BYTEORDER 4321 | |
| 24 | +# else | |
| 25 | +# define SHA3_BYTEORDER 0 | |
| 26 | +# endif | |
| 27 | +#endif | |
| 28 | + | |
| 6 | 29 | |
| 7 | 30 | /* |
| 8 | 31 | ** State structure for a SHA3 hash in progress |
| 9 | 32 | */ |
| 10 | 33 | typedef struct SHA3Context SHA3Context; |
| @@ -342,24 +365,32 @@ | ||
| 342 | 365 | ** Initialize a new hash. iSize determines the size of the hash |
| 343 | 366 | ** in bits and should be one of 224, 256, 384, or 512. Or iSize |
| 344 | 367 | ** can be zero to use the default hash size of 224 bits. |
| 345 | 368 | */ |
| 346 | 369 | static void SHA3Init(SHA3Context *p, int iSize){ |
| 347 | - static unsigned int one = 1; | |
| 348 | 370 | memset(p, 0, sizeof(*p)); |
| 349 | 371 | if( iSize>=256 && iSize<=512 ){ |
| 350 | 372 | p->nRate = (1600 - ((iSize + 31)&~31)*2)/8; |
| 351 | 373 | }else{ |
| 352 | 374 | p->nRate = 144; |
| 353 | 375 | } |
| 354 | - if( 1==*(unsigned char*)&one ){ | |
| 355 | - /* Little endian. No byte swapping. */ | |
| 356 | - p->ixMask = 0; | |
| 357 | - }else{ | |
| 358 | - /* Big endian. Byte swap. */ | |
| 359 | - p->ixMask = 7; | |
| 376 | +#if SHA3_BYTEORDER==1234 | |
| 377 | + /* Known to be little-endian at compile-time. No-op */ | |
| 378 | +#elif SHA3_BYTEORDER==4321 | |
| 379 | + p->ixMask = 7; /* Big-endian */ | |
| 380 | +#else | |
| 381 | + { | |
| 382 | + static unsigned int one = 1; | |
| 383 | + if( 1==*(unsigned char*)&one ){ | |
| 384 | + /* Little endian. No byte swapping. */ | |
| 385 | + p->ixMask = 0; | |
| 386 | + }else{ | |
| 387 | + /* Big endian. Byte swap. */ | |
| 388 | + p->ixMask = 7; | |
| 389 | + } | |
| 360 | 390 | } |
| 391 | +#endif | |
| 361 | 392 | } |
| 362 | 393 | |
| 363 | 394 | /* |
| 364 | 395 | ** Make consecutive calls to the SHA3Update function to add new content |
| 365 | 396 | ** to the hash |
| @@ -367,13 +398,31 @@ | ||
| 367 | 398 | static void SHA3Update( |
| 368 | 399 | SHA3Context *p, |
| 369 | 400 | const unsigned char *aData, |
| 370 | 401 | unsigned int nData |
| 371 | 402 | ){ |
| 372 | - unsigned int i; | |
| 373 | - for(i=0; i<nData; i++){ | |
| 403 | + unsigned int i = 0; | |
| 404 | +#if SHA3_BYTEORDER==1234 | |
| 405 | + if( (p->nLoaded % 8)==0 && ((aData - (const unsigned char*)0)&7)==0 ){ | |
| 406 | + for(; i<nData-7; i+=8){ | |
| 407 | + p->u.s[p->nLoaded/8] ^= *(u64*)&aData[i]; | |
| 408 | + p->nLoaded += 8; | |
| 409 | + if( p->nLoaded>=p->nRate ){ | |
| 410 | + KeccakF1600Step(p); | |
| 411 | + p->nLoaded = 0; | |
| 412 | + } | |
| 413 | + } | |
| 414 | + } | |
| 415 | +#endif | |
| 416 | + for(; i<nData; i++){ | |
| 417 | +#if SHA1_BYTEORDER==1234 | |
| 418 | + p->u.x[p->nLoaded] ^= aData[i]; | |
| 419 | +#elif SHA3_BYTEORDER==4321 | |
| 420 | + p->u.x[p->nLoaded^0x07] ^= aData[i]; | |
| 421 | +#else | |
| 374 | 422 | p->u.x[p->nLoaded^p->ixMask] ^= aData[i]; |
| 423 | +#endif | |
| 375 | 424 | p->nLoaded++; |
| 376 | 425 | if( p->nLoaded==p->nRate ){ |
| 377 | 426 | KeccakF1600Step(p); |
| 378 | 427 | p->nLoaded = 0; |
| 379 | 428 | } |
| 380 | 429 |
| --- src/sha3.c | |
| +++ src/sha3.c | |
| @@ -1,10 +1,33 @@ | |
| 1 | /* |
| 2 | ** This file contains an implementation of SHA3 (Keccak) hashing. |
| 3 | */ |
| 4 | #include "config.h" |
| 5 | #include "sha3.h" |
| 6 | |
| 7 | /* |
| 8 | ** State structure for a SHA3 hash in progress |
| 9 | */ |
| 10 | typedef struct SHA3Context SHA3Context; |
| @@ -342,24 +365,32 @@ | |
| 342 | ** Initialize a new hash. iSize determines the size of the hash |
| 343 | ** in bits and should be one of 224, 256, 384, or 512. Or iSize |
| 344 | ** can be zero to use the default hash size of 224 bits. |
| 345 | */ |
| 346 | static void SHA3Init(SHA3Context *p, int iSize){ |
| 347 | static unsigned int one = 1; |
| 348 | memset(p, 0, sizeof(*p)); |
| 349 | if( iSize>=256 && iSize<=512 ){ |
| 350 | p->nRate = (1600 - ((iSize + 31)&~31)*2)/8; |
| 351 | }else{ |
| 352 | p->nRate = 144; |
| 353 | } |
| 354 | if( 1==*(unsigned char*)&one ){ |
| 355 | /* Little endian. No byte swapping. */ |
| 356 | p->ixMask = 0; |
| 357 | }else{ |
| 358 | /* Big endian. Byte swap. */ |
| 359 | p->ixMask = 7; |
| 360 | } |
| 361 | } |
| 362 | |
| 363 | /* |
| 364 | ** Make consecutive calls to the SHA3Update function to add new content |
| 365 | ** to the hash |
| @@ -367,13 +398,31 @@ | |
| 367 | static void SHA3Update( |
| 368 | SHA3Context *p, |
| 369 | const unsigned char *aData, |
| 370 | unsigned int nData |
| 371 | ){ |
| 372 | unsigned int i; |
| 373 | for(i=0; i<nData; i++){ |
| 374 | p->u.x[p->nLoaded^p->ixMask] ^= aData[i]; |
| 375 | p->nLoaded++; |
| 376 | if( p->nLoaded==p->nRate ){ |
| 377 | KeccakF1600Step(p); |
| 378 | p->nLoaded = 0; |
| 379 | } |
| 380 |
| --- src/sha3.c | |
| +++ src/sha3.c | |
| @@ -1,10 +1,33 @@ | |
| 1 | /* |
| 2 | ** This file contains an implementation of SHA3 (Keccak) hashing. |
| 3 | */ |
| 4 | #include "config.h" |
| 5 | #include "sha3.h" |
| 6 | |
| 7 | /* |
| 8 | ** Macros to determine whether the machine is big or little endian, |
| 9 | ** and whether or not that determination is run-time or compile-time. |
| 10 | ** |
| 11 | ** For best performance, an attempt is made to guess at the byte-order |
| 12 | ** using C-preprocessor macros. If that is unsuccessful, or if |
| 13 | ** -DSHA3_BYTEORDER=0 is set, then byte-order is determined |
| 14 | ** at run-time. |
| 15 | */ |
| 16 | #ifndef SHA3_BYTEORDER |
| 17 | # if defined(i386) || defined(__i386__) || defined(_M_IX86) || \ |
| 18 | defined(__x86_64) || defined(__x86_64__) || defined(_M_X64) || \ |
| 19 | defined(_M_AMD64) || defined(_M_ARM) || defined(__x86) || \ |
| 20 | defined(__arm__) |
| 21 | # define SHA3_BYTEORDER 1234 |
| 22 | # elif defined(sparc) || defined(__ppc__) |
| 23 | # define SHA3_BYTEORDER 4321 |
| 24 | # else |
| 25 | # define SHA3_BYTEORDER 0 |
| 26 | # endif |
| 27 | #endif |
| 28 | |
| 29 | |
| 30 | /* |
| 31 | ** State structure for a SHA3 hash in progress |
| 32 | */ |
| 33 | typedef struct SHA3Context SHA3Context; |
| @@ -342,24 +365,32 @@ | |
| 365 | ** Initialize a new hash. iSize determines the size of the hash |
| 366 | ** in bits and should be one of 224, 256, 384, or 512. Or iSize |
| 367 | ** can be zero to use the default hash size of 224 bits. |
| 368 | */ |
| 369 | static void SHA3Init(SHA3Context *p, int iSize){ |
| 370 | memset(p, 0, sizeof(*p)); |
| 371 | if( iSize>=256 && iSize<=512 ){ |
| 372 | p->nRate = (1600 - ((iSize + 31)&~31)*2)/8; |
| 373 | }else{ |
| 374 | p->nRate = 144; |
| 375 | } |
| 376 | #if SHA3_BYTEORDER==1234 |
| 377 | /* Known to be little-endian at compile-time. No-op */ |
| 378 | #elif SHA3_BYTEORDER==4321 |
| 379 | p->ixMask = 7; /* Big-endian */ |
| 380 | #else |
| 381 | { |
| 382 | static unsigned int one = 1; |
| 383 | if( 1==*(unsigned char*)&one ){ |
| 384 | /* Little endian. No byte swapping. */ |
| 385 | p->ixMask = 0; |
| 386 | }else{ |
| 387 | /* Big endian. Byte swap. */ |
| 388 | p->ixMask = 7; |
| 389 | } |
| 390 | } |
| 391 | #endif |
| 392 | } |
| 393 | |
| 394 | /* |
| 395 | ** Make consecutive calls to the SHA3Update function to add new content |
| 396 | ** to the hash |
| @@ -367,13 +398,31 @@ | |
| 398 | static void SHA3Update( |
| 399 | SHA3Context *p, |
| 400 | const unsigned char *aData, |
| 401 | unsigned int nData |
| 402 | ){ |
| 403 | unsigned int i = 0; |
| 404 | #if SHA3_BYTEORDER==1234 |
| 405 | if( (p->nLoaded % 8)==0 && ((aData - (const unsigned char*)0)&7)==0 ){ |
| 406 | for(; i<nData-7; i+=8){ |
| 407 | p->u.s[p->nLoaded/8] ^= *(u64*)&aData[i]; |
| 408 | p->nLoaded += 8; |
| 409 | if( p->nLoaded>=p->nRate ){ |
| 410 | KeccakF1600Step(p); |
| 411 | p->nLoaded = 0; |
| 412 | } |
| 413 | } |
| 414 | } |
| 415 | #endif |
| 416 | for(; i<nData; i++){ |
| 417 | #if SHA1_BYTEORDER==1234 |
| 418 | p->u.x[p->nLoaded] ^= aData[i]; |
| 419 | #elif SHA3_BYTEORDER==4321 |
| 420 | p->u.x[p->nLoaded^0x07] ^= aData[i]; |
| 421 | #else |
| 422 | p->u.x[p->nLoaded^p->ixMask] ^= aData[i]; |
| 423 | #endif |
| 424 | p->nLoaded++; |
| 425 | if( p->nLoaded==p->nRate ){ |
| 426 | KeccakF1600Step(p); |
| 427 | p->nLoaded = 0; |
| 428 | } |
| 429 |