diff --git a/.gitignore b/.gitignore index 9933e13..8b7c18d 100644 --- a/.gitignore +++ b/.gitignore @@ -5,8 +5,8 @@ __pycache__/ *$py.class # Custom Ignore -.aax -.m4b +*.aax +*.m4b # C extensions *.so diff --git a/tables/Makefile b/tables/Makefile new file mode 100644 index 0000000..ba5b1dd --- /dev/null +++ b/tables/Makefile @@ -0,0 +1,11 @@ +alglib1.so: + g++ -Wall -O3 -shared -fPIC alglib1.cpp sha1.c -o alglib1.so + +windows: + # yum install mingw32-openssl mingw32-openssl-static mingw32-gcc mingw32-gcc-c++ mingw32-winpthreads-static -y + i686-w64-mingw32-g++ -c alglib1.cpp + i686-w64-mingw32-g++ -static -shared -o alglib1.dll alglib1.o -lcrypto -lpthread + + # yum install mingw64-openssl mingw64-openssl-static mingw64-gcc mingw64-gcc-c++ mingw64-winpthreads-static mingw64-zlib-static mingw64-libgomp -y + x86_64-w64-mingw32-g++ -c alglib1.cpp -lcrypto + x86_64-w64-mingw32-g++ -static -shared -o alglib1.dll alglib1.o -lcrypto -lpthread diff --git a/tables/README.md b/tables/README.md new file mode 100644 index 0000000..3d84596 --- /dev/null +++ b/tables/README.md @@ -0,0 +1,84 @@ +## NOTE (Licensing) + +Commercial usage of this project requires a license from the author(s) of +this project. Contact us for details. + +Note: The licensing terms of this project were changed due to commercial abuse +from OpenAudible (http://openaudible.org/) and other projects. + +## About + +Plugin for [RainbowCrack](http://project-rainbowcrack.com/) to recover your own +Audible activation data (activation_bytes) in an offline manner. + +You need to recover or retrieve your "activation_bytes" only once. This single +"activation_bytes" value will work for all your .aax files. + +## Donations + +Donations are gladly accepted. Please send BTC to `1FDFp8kWjnUCGTLw1SVkim6kRnYDge2vYh` +to support the development, and maintenance of this project. Thank you! + +## Note + +Git clone this repository on your machine. This repository has the required +rainbow tables `(*.rtc files)` and RainbowCrack binaries. + +``` +git clone https://github.com/inAudible-NG/tables.git +``` + +## Usage on Linux + +FFmpeg 2.8.1+ is required. Use Wine with the included (in `run` folder) Windows +binaries in case these Linux executables do not run on your distribution. + +##### Extract SHA1 checksum from the .aax file + +``` +$ ffprobe test.aax # extract SHA1 checksum +... +[mov,mp4,m4a,3gp,3g2,mj2 @ 0x1dde580] [aax] file checksum == 999a6ab8... +[mov,mp4,m4a,3gp,3g2,mj2 @ 0x1dde580] [aax] activation_bytes option is missing! +``` + +##### Recover "activation_bytes" + +``` +$ ./rcrack . -h 999a6ab8... +``` + +## Usage on Windows + +Download FFmpeg from https://ffmpeg.zeranoe.com/builds/. + +##### Extract SHA1 checksum from .aax file + +``` +C:\>ffprobe.exe sample.aax +ffprobe version N-79460-g21acc4d Copyright (c) 2007-2016 the FFmpeg developers + built with gcc 5.3.0 (GCC) +... +[mov,mp4,m4a,3gp,3g2,mj2 @ 039aae60] [aax] file checksum == 999a6ab8... +[mov,mp4,m4a,3gp,3g2,mj2 @ 039aae60] [aax] activation_bytes option is missing! +``` + +##### Recover "activation_bytes" + +``` +C:\tables>run\rcrack.exe . -h 999a6ab8... +statistics +------------------------------------------------------- +plaintext found: 1 of 1 +total time: 13.98 s +... +result +------------------------------------------------------- +999a6ab8... xyz hex:CAFED00D +``` + +"activation_bytes" is CAFED00D here. + +## References + +See http://project-rainbowcrack.com/alglib.htm for details. diff --git a/tables/alglib1.cpp b/tables/alglib1.cpp new file mode 100644 index 0000000..c5f90b8 --- /dev/null +++ b/tables/alglib1.cpp @@ -0,0 +1,80 @@ +/* + * http://www.tobtu.com/rtcalc.php#params + * + * keyspace is 256^4 (length is always 4) + * 99.999999% (Total success rate) + * + * ./rtgen audible byte 4 4 0 10000 10008356 0 + * ./rtgen audible byte 4 4 1 10000 10008356 0 + * ./rtgen audible byte 4 4 2 10000 10008356 0 + * ./rtgen audible byte 4 4 3 10000 10008356 0 + * ./rtgen audible byte 4 4 4 10000 10008356 0 + * ./rtgen audible byte 4 4 5 10000 10008356 0 + * ./rtgen audible byte 4 4 6 10000 10008356 0 + * ./rtgen audible byte 4 4 7 10000 10008356 0 + * ./rtgen audible byte 4 4 8 10000 10008356 0 + * ./rtgen audible byte 4 4 9 10000 10008356 0 + * + * ./rtsort *.rt + * ./rt2rtc *.rt 21 24 -m 18 -p + * ./rt2rtc *.rt 25 25 -m 512 -p + */ + +// #include +#include +#include "sha1.h" +#ifdef _WIN32 +#pragma comment(lib, "libeay32.lib") +#endif + +#define MIN_HASH_LEN 8 +#define MAX_HASH_LEN 32 + +void +#ifdef _WIN32 +__stdcall +#endif +Audible( + unsigned char *pData, // [in] plaintext to be hashed + unsigned int uLen, // [in] length of the plaintext + unsigned char Hash[MAX_HASH_LEN]) // [out] the result hash, size of the buffer is MAX_HASH_LEN bytes +{ + unsigned char fixed_key[] = { 0x77, 0x21, 0x4d, 0x4b, 0x19, 0x6a, 0x87, + 0xcd, 0x52, 0x00, 0x45, 0xfd, 0x20, 0xa5, 0x1d, 0x67 }; + + unsigned char intermediate_key[20] = {0}; + unsigned char intermediate_iv[20] = {0}; + SHA_CTX ctx; + + SHA1_Init(&ctx); + SHA1_Update(&ctx, fixed_key, 16); + SHA1_Update(&ctx, pData, uLen); + SHA1_Final(intermediate_key, &ctx); + + SHA1_Init(&ctx); + SHA1_Update(&ctx, fixed_key, 16); + SHA1_Update(&ctx, intermediate_key, 20); + SHA1_Update(&ctx, pData, uLen); + SHA1_Final(intermediate_iv, &ctx); + + SHA1_Init(&ctx); + SHA1_Update(&ctx, intermediate_key, 16); + SHA1_Update(&ctx, intermediate_iv, 16); + SHA1_Final(Hash, &ctx); +} + +struct HashAlgorithmEntry +{ + const char *szName; // name of the hash algorithm + void *pHashAlgorithm; // function pointer to the hash algorithm's implementation + unsigned int uHashLen; // output length of the hash algorithm, MIN_HASH_LEN <= uHashLen <= MAX_HASH_LEN + + // input plaintext length range supported by the hash algorithm's implementation + unsigned int uPlaintextLenMin; + unsigned int uPlaintextLenMax; +}; + +struct HashAlgorithmEntry HashAlgorithms[] = { // this symbol will be exported + {"audible", (void *)Audible, 20, 4, 4}, // always 4 bytes + {0, 0, 0, 0, 0}, // terminated by an entry of all zeroes +}; diff --git a/tables/audible_byte#4-4_0_10000x789935_0.rtc b/tables/audible_byte#4-4_0_10000x789935_0.rtc new file mode 100644 index 0000000..6359b7a Binary files /dev/null and b/tables/audible_byte#4-4_0_10000x789935_0.rtc differ diff --git a/tables/audible_byte#4-4_1_10000x791425_0.rtc b/tables/audible_byte#4-4_1_10000x791425_0.rtc new file mode 100644 index 0000000..57aa2b1 Binary files /dev/null and b/tables/audible_byte#4-4_1_10000x791425_0.rtc differ diff --git a/tables/audible_byte#4-4_2_10000x790991_0.rtc b/tables/audible_byte#4-4_2_10000x790991_0.rtc new file mode 100644 index 0000000..0ab3c43 Binary files /dev/null and b/tables/audible_byte#4-4_2_10000x790991_0.rtc differ diff --git a/tables/audible_byte#4-4_3_10000x792120_0.rtc b/tables/audible_byte#4-4_3_10000x792120_0.rtc new file mode 100644 index 0000000..8e0438c Binary files /dev/null and b/tables/audible_byte#4-4_3_10000x792120_0.rtc differ diff --git a/tables/audible_byte#4-4_4_10000x790743_0.rtc b/tables/audible_byte#4-4_4_10000x790743_0.rtc new file mode 100644 index 0000000..1e169c3 Binary files /dev/null and b/tables/audible_byte#4-4_4_10000x790743_0.rtc differ diff --git a/tables/audible_byte#4-4_5_10000x790568_0.rtc b/tables/audible_byte#4-4_5_10000x790568_0.rtc new file mode 100644 index 0000000..77c2a19 Binary files /dev/null and b/tables/audible_byte#4-4_5_10000x790568_0.rtc differ diff --git a/tables/audible_byte#4-4_6_10000x791458_0.rtc b/tables/audible_byte#4-4_6_10000x791458_0.rtc new file mode 100644 index 0000000..4f7b21c Binary files /dev/null and b/tables/audible_byte#4-4_6_10000x791458_0.rtc differ diff --git a/tables/audible_byte#4-4_7_10000x791707_0.rtc b/tables/audible_byte#4-4_7_10000x791707_0.rtc new file mode 100644 index 0000000..f4b7b06 Binary files /dev/null and b/tables/audible_byte#4-4_7_10000x791707_0.rtc differ diff --git a/tables/audible_byte#4-4_8_10000x790202_0.rtc b/tables/audible_byte#4-4_8_10000x790202_0.rtc new file mode 100644 index 0000000..e279ee0 Binary files /dev/null and b/tables/audible_byte#4-4_8_10000x790202_0.rtc differ diff --git a/tables/audible_byte#4-4_9_10000x791022_0.rtc b/tables/audible_byte#4-4_9_10000x791022_0.rtc new file mode 100644 index 0000000..18e558f Binary files /dev/null and b/tables/audible_byte#4-4_9_10000x791022_0.rtc differ diff --git a/tables/bswap.h b/tables/bswap.h new file mode 100644 index 0000000..d47c003 --- /dev/null +++ b/tables/bswap.h @@ -0,0 +1,180 @@ +/* + * Let's make sure we always have a sane definition for ntohl()/htonl(). + * Some libraries define those as a function call, just to perform byte + * shifting, bringing significant overhead to what should be a simple + * operation. + */ + +/* + * Default version that the compiler ought to optimize properly with + * constant values. + */ +static inline uint32_t default_swab32(uint32_t val) +{ + return (((val & 0xff000000) >> 24) | + ((val & 0x00ff0000) >> 8) | + ((val & 0x0000ff00) << 8) | + ((val & 0x000000ff) << 24)); +} + +static inline uint64_t default_bswap64(uint64_t val) +{ + return (((val & (uint64_t)0x00000000000000ffULL) << 56) | + ((val & (uint64_t)0x000000000000ff00ULL) << 40) | + ((val & (uint64_t)0x0000000000ff0000ULL) << 24) | + ((val & (uint64_t)0x00000000ff000000ULL) << 8) | + ((val & (uint64_t)0x000000ff00000000ULL) >> 8) | + ((val & (uint64_t)0x0000ff0000000000ULL) >> 24) | + ((val & (uint64_t)0x00ff000000000000ULL) >> 40) | + ((val & (uint64_t)0xff00000000000000ULL) >> 56)); +} + +#undef bswap32 +#undef bswap64 + +#if defined(__GNUC__) && (defined(__i386__) || defined(__x86_64__)) + +#define bswap32 git_bswap32 +static inline uint32_t git_bswap32(uint32_t x) +{ + uint32_t result; + if (__builtin_constant_p(x)) + result = default_swab32(x); + else + __asm__("bswap %0" : "=r" (result) : "0" (x)); + return result; +} + +#define bswap64 git_bswap64 +#if defined(__x86_64__) +static inline uint64_t git_bswap64(uint64_t x) +{ + uint64_t result; + if (__builtin_constant_p(x)) + result = default_bswap64(x); + else + __asm__("bswap %q0" : "=r" (result) : "0" (x)); + return result; +} +#else +static inline uint64_t git_bswap64(uint64_t x) +{ + union { uint64_t i64; uint32_t i32[2]; } tmp, result; + if (__builtin_constant_p(x)) + result.i64 = default_bswap64(x); + else { + tmp.i64 = x; + result.i32[0] = git_bswap32(tmp.i32[1]); + result.i32[1] = git_bswap32(tmp.i32[0]); + } + return result.i64; +} +#endif + +#elif defined(_MSC_VER) && (defined(_M_IX86) || defined(_M_X64)) + +#include + +#define bswap32(x) _byteswap_ulong(x) +#define bswap64(x) _byteswap_uint64(x) + +#endif + +#if defined(bswap32) + +#undef ntohl +#undef htonl +#define ntohl(x) bswap32(x) +#define htonl(x) bswap32(x) + +#endif + +#if defined(bswap64) + +#undef ntohll +#undef htonll +#define ntohll(x) bswap64(x) +#define htonll(x) bswap64(x) + +#else + +#undef ntohll +#undef htonll + +#if defined(__BYTE_ORDER) && defined(__LITTLE_ENDIAN) && defined(__BIG_ENDIAN) + +# define GIT_BYTE_ORDER __BYTE_ORDER +# define GIT_LITTLE_ENDIAN __LITTLE_ENDIAN +# define GIT_BIG_ENDIAN __BIG_ENDIAN + +#elif defined(BYTE_ORDER) && defined(LITTLE_ENDIAN) && defined(BIG_ENDIAN) + +# define GIT_BYTE_ORDER BYTE_ORDER +# define GIT_LITTLE_ENDIAN LITTLE_ENDIAN +# define GIT_BIG_ENDIAN BIG_ENDIAN + +#else + +# define GIT_BIG_ENDIAN 4321 +# define GIT_LITTLE_ENDIAN 1234 + +# if defined(_BIG_ENDIAN) && !defined(_LITTLE_ENDIAN) +# define GIT_BYTE_ORDER GIT_BIG_ENDIAN +# elif defined(_LITTLE_ENDIAN) && !defined(_BIG_ENDIAN) +# define GIT_BYTE_ORDER GIT_LITTLE_ENDIAN +# elif defined(__THW_BIG_ENDIAN__) && !defined(__THW_LITTLE_ENDIAN__) +# define GIT_BYTE_ORDER GIT_BIG_ENDIAN +# elif defined(__THW_LITTLE_ENDIAN__) && !defined(__THW_BIG_ENDIAN__) +# define GIT_BYTE_ORDER GIT_LITTLE_ENDIAN +# else +# error "Cannot determine endianness" +# endif + +#endif + +#if GIT_BYTE_ORDER == GIT_BIG_ENDIAN +# define ntohll(n) (n) +# define htonll(n) (n) +#else +# define ntohll(n) default_bswap64(n) +# define htonll(n) default_bswap64(n) +#endif + +#endif + +/* + * Performance might be improved if the CPU architecture is OK with + * unaligned 32-bit loads and a fast ntohl() is available. + * Otherwise fall back to byte loads and shifts which is portable, + * and is faster on architectures with memory alignment issues. + */ + +#if !defined(NO_UNALIGNED_LOADS) && ( \ + defined(__i386__) || defined(__x86_64__) || \ + defined(_M_IX86) || defined(_M_X64) || \ + defined(__ppc__) || defined(__ppc64__) || \ + defined(__powerpc__) || defined(__powerpc64__) || \ + defined(__s390__) || defined(__s390x__)) + +#define get_be16(p) ntohs(*(unsigned short *)(p)) +#define get_be32(p) ntohl(*(unsigned int *)(p)) +#define put_be32(p, v) do { *(unsigned int *)(p) = htonl(v); } while (0) + +#else + +#define get_be16(p) ( \ + (*((unsigned char *)(p) + 0) << 8) | \ + (*((unsigned char *)(p) + 1) << 0) ) +#define get_be32(p) ( \ + (*((unsigned char *)(p) + 0) << 24) | \ + (*((unsigned char *)(p) + 1) << 16) | \ + (*((unsigned char *)(p) + 2) << 8) | \ + (*((unsigned char *)(p) + 3) << 0) ) +#define put_be32(p, v) do { \ + unsigned int __v = (v); \ + *((unsigned char *)(p) + 0) = __v >> 24; \ + *((unsigned char *)(p) + 1) = __v >> 16; \ + *((unsigned char *)(p) + 2) = __v >> 8; \ + *((unsigned char *)(p) + 3) = __v >> 0; } while (0) + +#endif diff --git a/tables/charset.txt b/tables/charset.txt new file mode 100644 index 0000000..558fc0a --- /dev/null +++ b/tables/charset.txt @@ -0,0 +1,15 @@ + +numeric = [0123456789] + +alpha = [ABCDEFGHIJKLMNOPQRSTUVWXYZ] +alpha-numeric = [ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789] + +loweralpha = [abcdefghijklmnopqrstuvwxyz] +loweralpha-numeric = [abcdefghijklmnopqrstuvwxyz0123456789] + +mixalpha = [abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ] +mixalpha-numeric = [abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789] + +ascii-32-95 = [ !"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcdefghijklmnopqrstuvwxyz{|}~] +ascii-32-65-123-4 = [ !"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`{|}~] +alpha-numeric-symbol32-space = [ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789!@#$%^&*()-_+=~`[]{}|\:;"'<>,.?/ ] diff --git a/tables/demo.sh b/tables/demo.sh new file mode 100644 index 0000000..6907e00 --- /dev/null +++ b/tables/demo.sh @@ -0,0 +1,10 @@ +#!/bin/bash + +# ./demo.sh +# 00112233 + +pattern='hex:' + +cd `dirname $0` + +./rcrack . -h $1 | grep $pattern | awk -F $pattern '{print $2}' diff --git a/tables/generate-tables.sh b/tables/generate-tables.sh new file mode 100644 index 0000000..50e8ae2 --- /dev/null +++ b/tables/generate-tables.sh @@ -0,0 +1,20 @@ +#!/bin/bash + +# http://www.tobtu.com/rtcalc.php#params +# keyspace is 256^4 (length is always 4) +# 99.999999% (Total success rate) + +./rtgen audible byte 4 4 0 10000 10008356 0 +./rtgen audible byte 4 4 1 10000 10008356 0 +./rtgen audible byte 4 4 2 10000 10008356 0 +./rtgen audible byte 4 4 3 10000 10008356 0 +./rtgen audible byte 4 4 4 10000 10008356 0 +./rtgen audible byte 4 4 5 10000 10008356 0 +./rtgen audible byte 4 4 6 10000 10008356 0 +./rtgen audible byte 4 4 7 10000 10008356 0 +./rtgen audible byte 4 4 8 10000 10008356 0 +./rtgen audible byte 4 4 9 10000 10008356 0 + +# ./rtsort *.rt +# ./rt2rtc *.rt 21 24 -m 18 -p +# ./rt2rtc *.rt 25 25 -m 512 -p diff --git a/tables/rcrack b/tables/rcrack new file mode 100644 index 0000000..2eb1210 Binary files /dev/null and b/tables/rcrack differ diff --git a/tables/run/alglib1.dll b/tables/run/alglib1.dll new file mode 100644 index 0000000..6da4ca5 Binary files /dev/null and b/tables/run/alglib1.dll differ diff --git a/tables/run/alglib1.dll.md5 b/tables/run/alglib1.dll.md5 new file mode 100644 index 0000000..6ea26f4 --- /dev/null +++ b/tables/run/alglib1.dll.md5 @@ -0,0 +1 @@ +f0bb92cc20224fa806cd68d1bbd4fca4 alglib1.dll diff --git a/tables/run/charset.txt b/tables/run/charset.txt new file mode 100644 index 0000000..558fc0a --- /dev/null +++ b/tables/run/charset.txt @@ -0,0 +1,15 @@ + +numeric = [0123456789] + +alpha = [ABCDEFGHIJKLMNOPQRSTUVWXYZ] +alpha-numeric = [ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789] + +loweralpha = [abcdefghijklmnopqrstuvwxyz] +loweralpha-numeric = [abcdefghijklmnopqrstuvwxyz0123456789] + +mixalpha = [abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ] +mixalpha-numeric = [abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789] + +ascii-32-95 = [ !"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcdefghijklmnopqrstuvwxyz{|}~] +ascii-32-65-123-4 = [ !"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`{|}~] +alpha-numeric-symbol32-space = [ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789!@#$%^&*()-_+=~`[]{}|\:;"'<>,.?/ ] diff --git a/tables/run/rcrack.exe b/tables/run/rcrack.exe new file mode 100644 index 0000000..a67724e Binary files /dev/null and b/tables/run/rcrack.exe differ diff --git a/tables/run/rcrack.exe.md5 b/tables/run/rcrack.exe.md5 new file mode 100644 index 0000000..ca85bd3 --- /dev/null +++ b/tables/run/rcrack.exe.md5 @@ -0,0 +1 @@ +7a58ea0c818653a323345800d394dfc9 rcrack.exe diff --git a/tables/run/readme.txt b/tables/run/readme.txt new file mode 100644 index 0000000..58450e7 --- /dev/null +++ b/tables/run/readme.txt @@ -0,0 +1,4 @@ +This folder contains a stripped down version of rainbowcrack-1.7-win64.zip +file. + +Tested on CentOS 7 (with Wine from EPEL). diff --git a/tables/sha1.c b/tables/sha1.c new file mode 100644 index 0000000..146f3f0 --- /dev/null +++ b/tables/sha1.c @@ -0,0 +1,249 @@ +/* + * SHA1 routine optimized to do word accesses rather than byte accesses, + * and to avoid unnecessary copies into the context array. + * + * This was initially based on the Mozilla SHA1 implementation, although + * none of the original Mozilla code remains. + */ + +/* this is only to get definitions for memcpy(), ntohl() and htonl() */ +#include "sha1.h" + +#if defined(__GNUC__) && (defined(__i386__) || defined(__x86_64__)) + +/* + * Force usage of rol or ror by selecting the one with the smaller constant. + * It _can_ generate slightly smaller code (a constant of 1 is special), but + * perhaps more importantly it's possibly faster on any uarch that does a + * rotate with a loop. + */ + +#define SHA_ASM(op, x, n) ({ unsigned int __res; __asm__(op " %1,%0":"=r" (__res):"i" (n), "0" (x)); __res; }) +#define SHA_ROL(x,n) SHA_ASM("rol", x, n) +#define SHA_ROR(x,n) SHA_ASM("ror", x, n) + +#else + +#define SHA_ROT(X,l,r) (((X) << (l)) | ((X) >> (r))) +#define SHA_ROL(X,n) SHA_ROT(X,n,32-(n)) +#define SHA_ROR(X,n) SHA_ROT(X,32-(n),n) + +#endif + +/* + * If you have 32 registers or more, the compiler can (and should) + * try to change the array[] accesses into registers. However, on + * machines with less than ~25 registers, that won't really work, + * and at least gcc will make an unholy mess of it. + * + * So to avoid that mess which just slows things down, we force + * the stores to memory to actually happen (we might be better off + * with a 'W(t)=(val);asm("":"+m" (W(t))' there instead, as + * suggested by Artur Skawina - that will also make gcc unable to + * try to do the silly "optimize away loads" part because it won't + * see what the value will be). + * + * Ben Herrenschmidt reports that on PPC, the C version comes close + * to the optimized asm with this (ie on PPC you don't want that + * 'volatile', since there are lots of registers). + * + * On ARM we get the best code generation by forcing a full memory barrier + * between each SHA_ROUND, otherwise gcc happily get wild with spilling and + * the stack frame size simply explode and performance goes down the drain. + */ + +#if defined(__i386__) || defined(__x86_64__) + #define setW(x, val) (*(volatile unsigned int *)&W(x) = (val)) +#elif defined(__GNUC__) && defined(__arm__) + #define setW(x, val) do { W(x) = (val); __asm__("":::"memory"); } while (0) +#else + #define setW(x, val) (W(x) = (val)) +#endif + +/* This "rolls" over the 512-bit array */ +#define W(x) (array[(x)&15]) + +/* + * Where do we get the source from? The first 16 iterations get it from + * the input data, the next mix it from the 512-bit array. + */ +#define SHA_SRC(t) get_be32((unsigned char *) block + (t)*4) +#define SHA_MIX(t) SHA_ROL(W((t)+13) ^ W((t)+8) ^ W((t)+2) ^ W(t), 1); + +#define SHA_ROUND(t, input, fn, constant, A, B, C, D, E) do { \ + unsigned int TEMP = input(t); setW(t, TEMP); \ + E += TEMP + SHA_ROL(A,5) + (fn) + (constant); \ + B = SHA_ROR(B, 2); } while (0) + +#define T_0_15(t, A, B, C, D, E) SHA_ROUND(t, SHA_SRC, (((C^D)&B)^D) , 0x5a827999, A, B, C, D, E ) +#define T_16_19(t, A, B, C, D, E) SHA_ROUND(t, SHA_MIX, (((C^D)&B)^D) , 0x5a827999, A, B, C, D, E ) +#define T_20_39(t, A, B, C, D, E) SHA_ROUND(t, SHA_MIX, (B^C^D) , 0x6ed9eba1, A, B, C, D, E ) +#define T_40_59(t, A, B, C, D, E) SHA_ROUND(t, SHA_MIX, ((B&C)+(D&(B^C))) , 0x8f1bbcdc, A, B, C, D, E ) +#define T_60_79(t, A, B, C, D, E) SHA_ROUND(t, SHA_MIX, (B^C^D) , 0xca62c1d6, A, B, C, D, E ) + +static void blk_SHA1_Block(blk_SHA_CTX *ctx, const void *block) +{ + unsigned int A,B,C,D,E; + unsigned int array[16]; + + A = ctx->H[0]; + B = ctx->H[1]; + C = ctx->H[2]; + D = ctx->H[3]; + E = ctx->H[4]; + + /* Round 1 - iterations 0-16 take their input from 'block' */ + T_0_15( 0, A, B, C, D, E); + T_0_15( 1, E, A, B, C, D); + T_0_15( 2, D, E, A, B, C); + T_0_15( 3, C, D, E, A, B); + T_0_15( 4, B, C, D, E, A); + T_0_15( 5, A, B, C, D, E); + T_0_15( 6, E, A, B, C, D); + T_0_15( 7, D, E, A, B, C); + T_0_15( 8, C, D, E, A, B); + T_0_15( 9, B, C, D, E, A); + T_0_15(10, A, B, C, D, E); + T_0_15(11, E, A, B, C, D); + T_0_15(12, D, E, A, B, C); + T_0_15(13, C, D, E, A, B); + T_0_15(14, B, C, D, E, A); + T_0_15(15, A, B, C, D, E); + + /* Round 1 - tail. Input from 512-bit mixing array */ + T_16_19(16, E, A, B, C, D); + T_16_19(17, D, E, A, B, C); + T_16_19(18, C, D, E, A, B); + T_16_19(19, B, C, D, E, A); + + /* Round 2 */ + T_20_39(20, A, B, C, D, E); + T_20_39(21, E, A, B, C, D); + T_20_39(22, D, E, A, B, C); + T_20_39(23, C, D, E, A, B); + T_20_39(24, B, C, D, E, A); + T_20_39(25, A, B, C, D, E); + T_20_39(26, E, A, B, C, D); + T_20_39(27, D, E, A, B, C); + T_20_39(28, C, D, E, A, B); + T_20_39(29, B, C, D, E, A); + T_20_39(30, A, B, C, D, E); + T_20_39(31, E, A, B, C, D); + T_20_39(32, D, E, A, B, C); + T_20_39(33, C, D, E, A, B); + T_20_39(34, B, C, D, E, A); + T_20_39(35, A, B, C, D, E); + T_20_39(36, E, A, B, C, D); + T_20_39(37, D, E, A, B, C); + T_20_39(38, C, D, E, A, B); + T_20_39(39, B, C, D, E, A); + + /* Round 3 */ + T_40_59(40, A, B, C, D, E); + T_40_59(41, E, A, B, C, D); + T_40_59(42, D, E, A, B, C); + T_40_59(43, C, D, E, A, B); + T_40_59(44, B, C, D, E, A); + T_40_59(45, A, B, C, D, E); + T_40_59(46, E, A, B, C, D); + T_40_59(47, D, E, A, B, C); + T_40_59(48, C, D, E, A, B); + T_40_59(49, B, C, D, E, A); + T_40_59(50, A, B, C, D, E); + T_40_59(51, E, A, B, C, D); + T_40_59(52, D, E, A, B, C); + T_40_59(53, C, D, E, A, B); + T_40_59(54, B, C, D, E, A); + T_40_59(55, A, B, C, D, E); + T_40_59(56, E, A, B, C, D); + T_40_59(57, D, E, A, B, C); + T_40_59(58, C, D, E, A, B); + T_40_59(59, B, C, D, E, A); + + /* Round 4 */ + T_60_79(60, A, B, C, D, E); + T_60_79(61, E, A, B, C, D); + T_60_79(62, D, E, A, B, C); + T_60_79(63, C, D, E, A, B); + T_60_79(64, B, C, D, E, A); + T_60_79(65, A, B, C, D, E); + T_60_79(66, E, A, B, C, D); + T_60_79(67, D, E, A, B, C); + T_60_79(68, C, D, E, A, B); + T_60_79(69, B, C, D, E, A); + T_60_79(70, A, B, C, D, E); + T_60_79(71, E, A, B, C, D); + T_60_79(72, D, E, A, B, C); + T_60_79(73, C, D, E, A, B); + T_60_79(74, B, C, D, E, A); + T_60_79(75, A, B, C, D, E); + T_60_79(76, E, A, B, C, D); + T_60_79(77, D, E, A, B, C); + T_60_79(78, C, D, E, A, B); + T_60_79(79, B, C, D, E, A); + + ctx->H[0] += A; + ctx->H[1] += B; + ctx->H[2] += C; + ctx->H[3] += D; + ctx->H[4] += E; +} + +void blk_SHA1_Init(blk_SHA_CTX *ctx) +{ + ctx->size = 0; + + /* Initialize H with the magic constants (see FIPS180 for constants) */ + ctx->H[0] = 0x67452301; + ctx->H[1] = 0xefcdab89; + ctx->H[2] = 0x98badcfe; + ctx->H[3] = 0x10325476; + ctx->H[4] = 0xc3d2e1f0; +} + +void blk_SHA1_Update(blk_SHA_CTX *ctx, const void *data, unsigned long len) +{ + unsigned int lenW = ctx->size & 63; + + ctx->size += len; + + /* Read the data into W and process blocks as they get full */ + if (lenW) { + unsigned int left = 64 - lenW; + if (len < left) + left = len; + memcpy(lenW + (char *)ctx->W, data, left); + lenW = (lenW + left) & 63; + len -= left; + data = ((const char *)data + left); + if (lenW) + return; + blk_SHA1_Block(ctx, ctx->W); + } + while (len >= 64) { + blk_SHA1_Block(ctx, data); + data = ((const char *)data + 64); + len -= 64; + } + if (len) + memcpy(ctx->W, data, len); +} + +void blk_SHA1_Final(unsigned char hashout[20], blk_SHA_CTX *ctx) +{ + static const unsigned char pad[64] = { 0x80 }; + unsigned int padlen[2]; + int i; + + /* Pad with a binary 1 (ie 0x80), then zeroes, then length */ + padlen[0] = htonl((uint32_t)(ctx->size >> 29)); + padlen[1] = htonl((uint32_t)(ctx->size << 3)); + + i = ctx->size & 63; + blk_SHA1_Update(ctx, pad, 1 + (63 & (55 - i))); + blk_SHA1_Update(ctx, padlen, 8); + + /* Output hash */ + for (i = 0; i < 5; i++) + put_be32(hashout + i * 4, ctx->H[i]); +} diff --git a/tables/sha1.h b/tables/sha1.h new file mode 100644 index 0000000..95b51dc --- /dev/null +++ b/tables/sha1.h @@ -0,0 +1,32 @@ +/* + * SHA1 routine optimized to do word accesses rather than byte accesses, + * and to avoid unnecessary copies into the context array. + * + * This was initially based on the Mozilla SHA1 implementation, although + * none of the original Mozilla code remains. + */ + +#include +#include +#include +#include "bswap.h" + +typedef struct { + unsigned long long size; + unsigned int H[5]; + unsigned int W[16]; +} blk_SHA_CTX; + +void blk_SHA1_Init(blk_SHA_CTX *ctx); +void blk_SHA1_Update(blk_SHA_CTX *ctx, const void *dataIn, unsigned long len); +void blk_SHA1_Final(unsigned char hashout[20], blk_SHA_CTX *ctx); + +#define platform_SHA_CTX blk_SHA_CTX +#define platform_SHA1_Init blk_SHA1_Init +#define platform_SHA1_Update blk_SHA1_Update +#define platform_SHA1_Final blk_SHA1_Final + +#define SHA_CTX blk_SHA_CTX +#define SHA1_Init blk_SHA1_Init +#define SHA1_Update blk_SHA1_Update +#define SHA1_Final blk_SHA1_Final