summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorweidai <weidai@57ff6487-cd31-0410-9ec3-f628ee90f5f0>2009-03-02 02:39:17 +0000
committerweidai <weidai@57ff6487-cd31-0410-9ec3-f628ee90f5f0>2009-03-02 02:39:17 +0000
commitcaf9e032e6b4ccb114a74a3936c916bcfaba262d (patch)
tree0fecaa7a6728d07549a41864ea2cedfb245f0bd3
parent4e4793cc591e26c788b53c487bee7cab2d377f5e (diff)
downloadcryptopp-caf9e032e6b4ccb114a74a3936c916bcfaba262d.tar.gz
changes for 5.6:
- added AuthenticatedSymmetricCipher interface class and Filter wrappers - added CCM, GCM (with SSE2 assembly), CMAC, and SEED - improved AES speed on x86 and x64 - removed WORD64_AVAILABLE; compiler 64-bit int support is now required git-svn-id: svn://svn.code.sf.net/p/cryptopp/code/trunk/c5@433 57ff6487-cd31-0410-9ec3-f628ee90f5f0
-rw-r--r--Doxyfile1
-rw-r--r--Readme.txt20
-rwxr-xr-xTestVectors/aes.txt86
-rw-r--r--TestVectors/all.txt3
-rw-r--r--TestVectors/ccm.txt240
-rw-r--r--TestVectors/cmac.txt38
-rw-r--r--TestVectors/gcm.txt139
-rw-r--r--TestVectors/hmac.txt54
-rwxr-xr-xTestVectors/panama.txt16
-rw-r--r--TestVectors/seed.txt19
-rw-r--r--TestVectors/ttmac.txt18
-rwxr-xr-xTestVectors/vmac.txt48
-rw-r--r--aes.h2
-rw-r--r--algparam.cpp48
-rw-r--r--algparam.h75
-rw-r--r--argnames.h5
-rw-r--r--authenc.cpp179
-rw-r--r--authenc.h49
-rw-r--r--bench.cpp103
-rw-r--r--camellia.cpp21
-rw-r--r--camellia.h1
-rw-r--r--cbcmac.cpp9
-rw-r--r--cbcmac.h3
-rw-r--r--ccm.cpp140
-rw-r--r--ccm.h101
-rw-r--r--cmac.cpp122
-rw-r--r--cmac.h48
-rw-r--r--config.h28
-rwxr-xr-xcpu.h5
-rwxr-xr-xcryptdll.vcproj42
-rwxr-xr-xcryptest.vcproj108
-rw-r--r--cryptlib.cpp123
-rw-r--r--cryptlib.h121
-rwxr-xr-xcryptlib.vcproj126
-rw-r--r--cryptopp.rc10
-rw-r--r--datatest.cpp166
-rw-r--r--default.cpp2
-rw-r--r--factory.h7
-rw-r--r--filters.cpp170
-rw-r--r--filters.h78
-rw-r--r--fipstest.cpp6
-rw-r--r--fltrimpl.h7
-rw-r--r--gcm.cpp735
-rw-r--r--gcm.h105
-rw-r--r--hrtimer.h6
-rw-r--r--idea.h2
-rw-r--r--integer.cpp10
-rw-r--r--iterhash.cpp8
-rw-r--r--iterhash.h2
-rw-r--r--mdc.h2
-rw-r--r--misc.cpp44
-rw-r--r--misc.h41
-rw-r--r--modes.cpp137
-rw-r--r--modes.h54
-rw-r--r--nbtheory.cpp10
-rw-r--r--nbtheory.h13
-rw-r--r--panama.cpp3
-rw-r--r--panama.h2
-rw-r--r--pssr.cpp2
-rw-r--r--pubkey.cpp9
-rw-r--r--rc2.h1
-rw-r--r--rdtables.cpp525
-rw-r--r--regtest.cpp43
-rw-r--r--rijndael.cpp967
-rw-r--r--rijndael.h10
-rw-r--r--rsa.cpp2
-rw-r--r--safer.h2
-rwxr-xr-xsalsa.cpp11
-rwxr-xr-xsalsa.h2
-rw-r--r--seal.cpp8
-rw-r--r--seal.h2
-rw-r--r--secblock.h2
-rw-r--r--seckey.h9
-rw-r--r--seed.cpp104
-rw-r--r--seed.h38
-rw-r--r--sha.cpp4
-rw-r--r--sha.h4
-rw-r--r--shark.cpp5
-rw-r--r--shark.h4
-rw-r--r--sharkbox.cpp4
-rw-r--r--skipjack.h1
-rwxr-xr-xsosemanuk.cpp11
-rwxr-xr-xsosemanuk.h2
-rw-r--r--strciphr.cpp66
-rw-r--r--strciphr.h17
-rw-r--r--test.cpp41
-rw-r--r--tiger.cpp4
-rw-r--r--tiger.h5
-rw-r--r--tigertab.cpp4
-rw-r--r--validat1.cpp43
-rw-r--r--validat2.cpp6
-rw-r--r--validat3.cpp18
-rw-r--r--validate.h5
-rwxr-xr-xvmac.cpp36
-rwxr-xr-xvmac.h13
-rw-r--r--wake.cpp2
-rw-r--r--whrlpool.cpp5
-rw-r--r--whrlpool.h5
-rw-r--r--x64dll.asm665
-rwxr-xr-xx64masm.asm333
-rw-r--r--xtr.cpp2
101 files changed, 4878 insertions, 1925 deletions
diff --git a/Doxyfile b/Doxyfile
index 635f5a0..a3d51d9 100644
--- a/Doxyfile
+++ b/Doxyfile
@@ -942,7 +942,6 @@ INCLUDE_FILE_PATTERNS =
PREDEFINED = _WIN32 \
_WINDOWS \
- WORD64_AVAILABLE \
__FreeBSD__ \
CRYPTOPP_DOXYGEN_PROCESSING
diff --git a/Readme.txt b/Readme.txt
index 95ea2a7..dc4fe0a 100644
--- a/Readme.txt
+++ b/Readme.txt
@@ -1,5 +1,5 @@
Crypto++: a C++ Class Library of Cryptographic Schemes
-Version 5.5.2 (9/24/2007)
+Version 5.6 (in progress)
Crypto++ Library is a free C++ class library of cryptographic schemes.
Currently the library contains the following algorithms:
@@ -13,12 +13,13 @@ Currently the library contains the following algorithms:
IDEA, Triple-DES (DES-EDE2 and DES-EDE3),
other block ciphers Camellia, RC5, Blowfish, TEA, XTEA,
- Skipjack, SHACAL-2
+ Skipjack, SHACAL-2, SEED
block cipher modes of operation ECB, CBC, CBC ciphertext stealing (CTS),
- CFB, OFB, counter mode (CTR)
+ CFB, OFB, counter mode (CTR), GCM, CCM
- message authentication codes VMAC, HMAC, CBC-MAC, DMAC, Two-Track-MAC
+ message authentication codes VMAC, HMAC, GMAC, CBC-MAC, CMAC, DMAC,
+ Two-Track-MAC
SHA-1, SHA-2 (SHA-224, SHA-256, SHA-384, and
hash functions SHA-512), Tiger, WHIRLPOOL, RIPEMD-128,
@@ -411,4 +412,15 @@ the mailing list.
- added support for newly released compilers: MSVC 2008, GCC 4.2, Sun CC 5.9,
Intel C++ Compiler 10.0, and Borland C++Builder 2007
+5.6 - added AuthenticatedSymmetricCipher interface class and Filter wrappers
+ - added CCM, GCM (with SSE2 assembly), CMAC, and SEED
+ - improved AES speed on x86 and x64
+ - fixed run-time validation error on x86-64 with GCC 4.3.2 -O2
+ - fixed HashFilter bug when putMessage=true
+ - fixed warnings with GCC 4.3
+ - fixed compiler error in vmac.cpp on x86 with GCC -fPIC
+ - fixed incorrect VMAC computation on message lengths
+ that are >64 mod 128 (x86 assembly version is not affected)
+ - removed WORD64_AVAILABLE; compiler 64-bit int support is now required
+
Written by Wei Dai
diff --git a/TestVectors/aes.txt b/TestVectors/aes.txt
index 9fb5a97..0012629 100755
--- a/TestVectors/aes.txt
+++ b/TestVectors/aes.txt
@@ -34,6 +34,34 @@ Ciphertext: f58c4c04d6e5f1ba779eabfb5f7bfbd6 9cfc4e967edb808d679f777bc6702c7d 39
Test: Encrypt
AlgorithmType: SymmetricCipher
+Name: AES/CBC
+Source: RFC 3602
+Comment: Case 1: Encrypting 16 bytes (1 block) using AES-CBC with 128-bit key
+Key : 0x06a9214036b8a15b512e03d534120006
+IV : 0x3dafba429d9eb430b422da802c9fac41
+Plaintext : "Single block msg"
+Ciphertext: 0xe353779c1079aeb82708942dbe77181a
+Test: Encrypt
+Comment: Case 2: Encrypting 32 bytes (2 blocks) using AES-CBC with 128-bit key
+Key : 0xc286696d887c9aa0611bbb3e2025a45a
+IV : 0x562e17996d093d28ddb3ba695a2e6f58
+Plaintext : 0x000102030405060708090a0b0c0d0e0f 101112131415161718191a1b1c1d1e1f
+Ciphertext: 0xd296cd94c2cccf8a3a863028b5e1dc0a 7586602d253cfff91b8266bea6d61ab1
+Test: Encrypt
+Comment: Case 3: Encrypting 48 bytes (3 blocks) using AES-CBC with 128-bit key
+Key : 0x6c3ea0477630ce21a2ce334aa746c2cd
+IV : 0xc782dc4c098c66cbd9cd27d825682c81
+Plaintext : "This is a 48-byte message (exactly 3 AES blocks)"
+Ciphertext: 0xd0a02b3836451753d493665d33f0e886 2dea54cdb293abc7506939276772f8d5 021c19216bad525c8579695d83ba2684
+Test: Encrypt
+Comment: Case 4: Encrypting 64 bytes (4 blocks) using AES-CBC with 128-bit key
+Key : 0x56e47a38c5598974bc46903dba290349
+IV : 0x8ce82eefbea0da3c44699ed7db51b7d9
+Plaintext : 0xa0a1a2a3a4a5a6a7a8a9aaabacadaeaf b0b1b2b3b4b5b6b7b8b9babbbcbdbebf c0c1c2c3c4c5c6c7c8c9cacbcccdcecf d0d1d2d3d4d5d6d7d8d9dadbdcdddedf
+Ciphertext: 0xc30e32ffedc0774e6aff6af0869f71aa 0f3af07a9a31a9c684db207eb0ef8e4e 35907aa632c3ffdf868bb7b29d3d46ad 83ce9f9a102ee99d49a53e87f4c3da55
+Test: Encrypt
+
+AlgorithmType: SymmetricCipher
Name: AES/CFB
Source: NIST Special Publication 800-38A
IV: 000102030405060708090a0b0c0d0e0f
@@ -101,3 +129,61 @@ Comment: F.5.5 CTR-AES256.Encrypt
Key: 603deb1015ca71be2b73aef0857d77811f352c073b6108d72d9810a30914dff4
Ciphertext: 601ec313775789a5b7a7f504bbf3d228 f443e3ca4d62b59aca84e990cacaf5c5 2b0930daa23de94ce87017ba2d84988d dfc9c58db67aada613c2dd08457941a6
Test: Encrypt
+
+AlgorithmType: SymmetricCipher
+Name: AES/CTR
+Source: RFC 3686
+#Test Vector #1: Encrypting 16 octets using AES-CTR with 128-bit key
+Key : AE 68 52 F8 12 10 67 CC 4B F7 A5 76 55 77 F3 9E
+Plaintext : 53 69 6E 67 6C 65 20 62 6C 6F 63 6B 20 6D 73 67
+IV: 00 00 00 30 00 00 00 00 00 00 00 00 00 00 00 01
+Ciphertext : E4 09 5D 4F B7 A7 B3 79 2D 61 75 A3 26 13 11 B8
+Test: Encrypt
+#Test Vector #2: Encrypting 32 octets using AES-CTR with 128-bit key
+Key : 7E 24 06 78 17 FA E0 D7 43 D6 CE 1F 32 53 91 63
+Plaintext : 00 01 02 03 04 05 06 07 08 09 0A 0B 0C 0D 0E 0F 10 11 12 13 14 15 16 17 18 19 1A 1B 1C 1D 1E 1F
+IV: 00 6C B6 DB C0 54 3B 59 DA 48 D9 0B 00 00 00 01
+Ciphertext : 51 04 A1 06 16 8A 72 D9 79 0D 41 EE 8E DA D3 88 EB 2E 1E FC 46 DA 57 C8 FC E6 30 DF 91 41 BE 28
+Test: Encrypt
+#Test Vector #3: Encrypting 36 octets using AES-CTR with 128-bit key
+Key : 76 91 BE 03 5E 50 20 A8 AC 6E 61 85 29 F9 A0 DC
+Plaintext : 00 01 02 03 04 05 06 07 08 09 0A 0B 0C 0D 0E 0F 10 11 12 13 14 15 16 17 18 19 1A 1B 1C 1D 1E 1F 20 21 22 23
+IV: 00 E0 01 7B 27 77 7F 3F 4A 17 86 F0 00 00 00 01
+Ciphertext : C1 CF 48 A8 9F 2F FD D9 CF 46 52 E9 EF DB 72 D7 45 40 A4 2B DE 6D 78 36 D5 9A 5C EA AE F3 10 53 25 B2 07 2F
+Test: Encrypt
+#Test Vector #4: Encrypting 16 octets using AES-CTR with 192-bit key
+Key : 16 AF 5B 14 5F C9 F5 79 C1 75 F9 3E 3B FB 0E ED 86 3D 06 CC FD B7 85 15
+Plaintext : 53 69 6E 67 6C 65 20 62 6C 6F 63 6B 20 6D 73 67
+IV: 00 00 00 48 36 73 3C 14 7D 6D 93 CB 00 00 00 01
+Ciphertext : 4B 55 38 4F E2 59 C9 C8 4E 79 35 A0 03 CB E9 28
+Test: Encrypt
+#Test Vector #5: Encrypting 32 octets using AES-CTR with 192-bit key
+Key : 7C 5C B2 40 1B 3D C3 3C 19 E7 34 08 19 E0 F6 9C 67 8C 3D B8 E6 F6 A9 1A
+Plaintext : 00 01 02 03 04 05 06 07 08 09 0A 0B 0C 0D 0E 0F 10 11 12 13 14 15 16 17 18 19 1A 1B 1C 1D 1E 1F
+IV: 00 96 B0 3B 02 0C 6E AD C2 CB 50 0D 00 00 00 01
+Ciphertext : 45 32 43 FC 60 9B 23 32 7E DF AA FA 71 31 CD 9F 84 90 70 1C 5A D4 A7 9C FC 1F E0 FF 42 F4 FB 00
+Test: Encrypt
+#Test Vector #6: Encrypting 36 octets using AES-CTR with 192-bit key
+Key : 02 BF 39 1E E8 EC B1 59 B9 59 61 7B 09 65 27 9B F5 9B 60 A7 86 D3 E0 FE
+Plaintext : 00 01 02 03 04 05 06 07 08 09 0A 0B 0C 0D 0E 0F 10 11 12 13 14 15 16 17 18 19 1A 1B 1C 1D 1E 1F 20 21 22 23
+IV: 00 07 BD FD 5C BD 60 27 8D CC 09 12 00 00 00 01
+Ciphertext : 96 89 3F C5 5E 5C 72 2F 54 0B 7D D1 DD F7 E7 58 D2 88 BC 95 C6 91 65 88 45 36 C8 11 66 2F 21 88 AB EE 09 35
+Test: Encrypt
+#Test Vector #7: Encrypting 16 octets using AES-CTR with 256-bit key
+Key : 77 6B EF F2 85 1D B0 6F 4C 8A 05 42 C8 69 6F 6C 6A 81 AF 1E EC 96 B4 D3 7F C1 D6 89 E6 C1 C1 04
+Plaintext : 53 69 6E 67 6C 65 20 62 6C 6F 63 6B 20 6D 73 67
+IV: 00 00 00 60 DB 56 72 C9 7A A8 F0 B2 00 00 00 01
+Ciphertext : 14 5A D0 1D BF 82 4E C7 56 08 63 DC 71 E3 E0 C0
+Test: Encrypt
+#Test Vector #8: Encrypting 32 octets using AES-CTR with 256-bit key
+Key : F6 D6 6D 6B D5 2D 59 BB 07 96 36 58 79 EF F8 86 C6 6D D5 1A 5B 6A 99 74 4B 50 59 0C 87 A2 38 84
+Plaintext : 00 01 02 03 04 05 06 07 08 09 0A 0B 0C 0D 0E 0F 10 11 12 13 14 15 16 17 18 19 1A 1B 1C 1D 1E 1F
+IV: 00 FA AC 24 C1 58 5E F1 5A 43 D8 75 00 00 00 01
+Ciphertext : F0 5E 23 1B 38 94 61 2C 49 EE 00 0B 80 4E B2 A9 B8 30 6B 50 8F 83 9D 6A 55 30 83 1D 93 44 AF 1C
+Test: Encrypt
+#Test Vector #9: Encrypting 36 octets using AES-CTR with 256-bit key
+Key : FF 7A 61 7C E6 91 48 E4 F1 72 6E 2F 43 58 1D E2 AA 62 D9 F8 05 53 2E DF F1 EE D6 87 FB 54 15 3D
+Plaintext : 00 01 02 03 04 05 06 07 08 09 0A 0B 0C 0D 0E 0F 10 11 12 13 14 15 16 17 18 19 1A 1B 1C 1D 1E 1F 20 21 22 23
+IV: 00 1C C5 B7 51 A5 1D 70 A1 C1 11 48 00 00 00 01
+Ciphertext : EB 6C 52 82 1D 0B BB F7 CE 75 94 46 2A CA 4F AA B4 07 DF 86 65 69 FD 07 F4 8C C0 B5 83 D6 07 1F 1E C0 E6 B8
+Test: Encrypt
diff --git a/TestVectors/all.txt b/TestVectors/all.txt
index b98ac90..f26df0d 100644
--- a/TestVectors/all.txt
+++ b/TestVectors/all.txt
@@ -22,3 +22,6 @@ Test: aes.txt
Test: salsa.txt
Test: vmac.txt
Test: sosemanuk.txt
+Test: ccm.txt
+Test: gcm.txt
+Test: cmac.txt
diff --git a/TestVectors/ccm.txt b/TestVectors/ccm.txt
new file mode 100644
index 0000000..f23f084
--- /dev/null
+++ b/TestVectors/ccm.txt
@@ -0,0 +1,240 @@
+AlgorithmType: AuthenticatedSymmetricCipher
+Name: AES/CCM
+Source: aes-modes-src-07-10-08/Testvals/ccm.1, Basic Tests for CCM (compiled by B. R. Gladman)
+Key: 404142434445464748494a4b4c4d4e4f
+IV: 10111213141516
+Header: 0001020304050607
+Plaintext: 20212223
+Ciphertext: 7162015b
+MAC: 4dac255d
+Test: Encrypt
+Key: 404142434445464748494a4b4c4d4e4f
+IV: 1011121314151617
+Header: 000102030405060708090a0b0c0d0e0f
+Plaintext: 202122232425262728292a2b2c2d2e2f
+Ciphertext: d2a1f0e051ea5f62081a7792073d593d
+MAC: 1fc64fbfaccd
+Test: Encrypt
+Key: 404142434445464748494a4b4c4d4e4f
+IV: 101112131415161718191a1b
+Header: 000102030405060708090a0b0c0d0e0f10111213
+Plaintext: 202122232425262728292a2b2c2d2e2f3031323334353637
+Ciphertext: e3b201a9f5b71a7a9b1ceaeccd97e70b6176aad9a4428aa5
+MAC: 484392fbc1b09951
+Test: Encrypt
+Key: 404142434445464748494a4b4c4d4e4f
+IV: 101112131415161718191a1b1c
+Header: r256 000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f404142434445464748494a4b4c4d4e4f505152535455565758595a5b5c5d5e5f606162636465666768696a6b6c6d6e6f707172737475767778797a7b7c7d7e7f808182838485868788898a8b8c8d8e8f909192939495969798999a9b9c9d9e9fa0a1a2a3a4a5a6a7a8a9aaabacadaeafb0b1b2b3b4b5b6b7b8b9babbbcbdbebfc0c1c2c3c4c5c6c7c8c9cacbcccdcecfd0d1d2d3d4d5d6d7d8d9dadbdcdddedfe0e1e2e3e4e5e6e7e8e9eaebecedeeeff0f1f2f3f4f5f6f7f8f9fafbfcfdfeff
+Plaintext: 202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f
+Ciphertext: 69915dad1e84c6376a68c2967e4dab615ae0fd1faec44cc484828529463ccf72
+MAC: b4ac6bec93e8598e7f0dadbcea5b
+Test: Encrypt
+Key: c97c1f67ce371185514a8a19f2bdd52f
+IV: 005030f1844408b5039776e70c
+Header: 08400fd2e128a57c5030f1844408abaea5b8fcba0000
+Plaintext: f8ba1a55d02f85ae967bb62fb6cda8eb7e78a050
+Ciphertext: f3d0a2fe9a3dbf2342a643e43246e80c3c04d019
+MAC: 7845ce0b16f97623
+Test: Encrypt
+Key: 8f7a053fa577a5597529272097a603d5
+IV: 00eec1762c88de31f3cbba97ea
+Header: 08c0ea100c846850eec1762c88deaf2ee9f46a070000
+Plaintext: 83a0634b5ed7627eb9df225e05740342de194117
+Ciphertext: 814b6965d05bf2b2ed38d4beb069fe82714a610b
+MAC: 542fbf8da06aa4ae
+Test: Encrypt
+Key: 40cfb7a62e88013bd6d3affcc191041e
+IV: 00b6a88adf36912fdca0f3a5ae
+Header: 88c0d9577df763c8b6a88adf3691dc4a8bca94dd00000000
+Plaintext: 2c1bd036831c95496c5f4dbf3d559e72de802a18
+Ciphertext: 89d8580340b626a0b6d4d013bf18f291b89646c8
+MAC: fd1f1f61a9fb4bb3
+Test: Encrypt
+Key: 8c89a2ebc96c7602707fcf24b32d3833
+IV: 078ef822734701f670a55a0fe3
+Header: 88c2712a9ddf11db8ef82273470159140dd646a200000700
+Plaintext: 4fad2b1c290fa5ebd872fbc3f3a074898f8b2fbb
+Ciphertext: 9d59b15f371448c230f4d739052e13ab3b1a7b10
+MAC: 31fc88004f35ee3d
+Test: Encrypt
+Key: a574d5143bb25efddeff30122fdfd066
+IV: 0bf351946bc96ba7ffe03c0e37
+Header: 88c245dec69a7480f351946bc96be276fbe6c12700000b00
+Plaintext: 28969b954f263a8018a9ef70a8b051462481922e
+Ciphertext: eb4ae4956a801da9624b7e0c18b23e615ec03af6
+MAC: ce0c3be197d305eb
+Test: Encrypt
+Key: f71eea4e1f58804b9717230ad0614641
+IV: 0dbff943b9f9a66b81eca48989
+Header: 88425af28430fdabbff943b9f9a6ab1d98c7fe7300000d00
+Plaintext: abfda22d3a0bfc9cc1fc079363c2fca143e6eb1d
+Ciphertext: 9a709b60a39d40b1dfb612e18b5f114badb6cc86
+MAC: 309a8d5c466bbb71
+Test: Encrypt
+Key: 1bdb34980e038124a1db1a892bec366a
+IV: 00efec952016915eec4073e723
+Header: 08419b50f4fd56f6efec9520169183570c4ccdee0000
+Plaintext: 98beca86f4b38da20cfdf24724c58eb835665339
+Ciphertext: 12c537ebf3ab584ef1fef9a1f3547a8c13b3225a
+MAC: 2d0957ecfabe95b9
+Test: Encrypt
+Key: 6eac1bf54bd54edb2321754303024c71
+IV: 0aca3f3aae60c4cefd996eccdd
+Header: 88c1552d5f72bb70ca3f3aae60c48ba9b5f82c2f00000a00
+Plaintext: 57cb5c0e5fcd885e9a4239e9b9cad60d64375979
+Ciphertext: 4bf281ef8ec7739f91591b97a87dc14b3fa17462
+MAC: 6dba8ef7f08087dd
+Test: Encrypt
+Key: 494b501e194675971a48d08c5bc353cb
+IV: 0aa4ad6d319985ba82e93437b3
+Header: 88c19afb798b8a4ba4ad6d319985bc429e8f0afa00000a00
+Plaintext: 25a98f9c1bd9c93cf383ab9d98152d76cb4a32c6
+Ciphertext: 561a0d068eac2eadb0c57fe2d0a6cc7398b6ddbf
+MAC: cfe438cbea61fa9a
+Test: Encrypt
+Key: 489e49bc3cfe3fce3895820e872ee1a3
+IV: 0053f869fe279acf1d3e75fea9
+Header: 084340ec29fa759b53f869fe279af0f9f8a65416000052bfd2703d24
+Plaintext: 7f91f2472d7a121c9cdd4b6c9080675a1020aa00
+Ciphertext: 25df5173835e4fba23bc05a253885ebed3ac4871
+MAC: c868a725552c5565
+Test: Encrypt
+Key: 02be5c4545672a07e4e314d70f1f9e85
+IV: 0d347ceb9aabffd2d6596e55d4
+Header: 88c3298c0baa9190347ceb9aabffd83d4886e5c20000e29d524ae1960d00
+Plaintext: f9a812e4a28af7f3714d4bf6622e5932f2184509
+Ciphertext: 6315500f924295cd3eafbdc3e151b1df46465b71
+MAC: 681fdee8513c62dc
+Test: Encrypt
+Key: 77077ed79453e4a18d60438cc6484d6e
+IV: 00d8ac5a7ec44450b01e77fd8e
+Header: 0843aa288b8435bcd8ac5a7ec444e8b46250538b0000e81402c2ee11
+Plaintext: 431981a2336d02f8cb8448d5428916be95293537
+Ciphertext: cf71b2ccbd590b20800792f359ed1cfd74d800b4
+MAC: fd0f41f426bb8f30
+Test: Encrypt
+Source: aes-modes-src-07-10-08/Testvals/ccm.2, Vectors for IEEE P1619.1 CCM Mode
+Header:
+Key: 0000000000000000000000000000000000000000000000000000000000000000
+IV: 000000000000000000000000
+Plaintext: 00000000000000000000000000000000
+Ciphertext: c1944044c8e7aa95d2de9513c7f3dd8c
+MAC: 4b0a3e5e51f151eb0ffae7c43d010fdb
+Test: Encrypt
+Plaintext:
+Ciphertext:
+Key: 0000000000000000000000000000000000000000000000000000000000000000
+IV: 000000000000000000000000
+Header: 00000000000000000000000000000000
+MAC: 904704e89fb216443cb9d584911fc3c2
+Test: Encrypt
+Key: 0000000000000000000000000000000000000000000000000000000000000000
+IV: 000000000000000000000000
+Header: 00000000000000000000000000000000
+Plaintext: 00000000000000000000000000000000
+Ciphertext: c1944044c8e7aa95d2de9513c7f3dd8c
+MAC: 87314e9c1fa01abe6a6415943dc38521
+Test: Encrypt
+Header:
+Key: fb7615b23d80891dd470980bc79584c8b2fb64ce60978f4d17fce45a49e830b7
+IV: dbd1a3636024b7b402da7d6f
+Plaintext: a845348ec8c5b5f126f50e76fefd1b1e
+Ciphertext: cc881261c6a7fa72b96a1739176b277f
+MAC: 3472e1145f2c0cbe146349062cf0e423
+Test: Encrypt
+Key: 404142434445464748494a4b4c4d4e4f505152535455565758595a5b5c5d5e5f
+IV: 101112131415161718191a1b
+Header: 000102030405060708090a0b0c0d0e0f10111213
+Plaintext: 202122232425262728292a2b2c2d2e2f3031323334353637
+Ciphertext: 04f883aeb3bd0730eaf50bb6de4fa2212034e4e41b0e75e5
+MAC: 9bba3f3a107f3239bd63902923f80371
+Test: Encrypt
+Key: 404142434445464748494a4b4c4d4e4f505152535455565758595a5b5c5d5e5f
+IV: 101112131415161718191a1b
+Header: r256 000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f404142434445464748494a4b4c4d4e4f505152535455565758595a5b5c5d5e5f606162636465666768696a6b6c6d6e6f707172737475767778797a7b7c7d7e7f808182838485868788898a8b8c8d8e8f909192939495969798999a9b9c9d9e9fa0a1a2a3a4a5a6a7a8a9aaabacadaeafb0b1b2b3b4b5b6b7b8b9babbbcbdbebfc0c1c2c3c4c5c6c7c8c9cacbcccdcecfd0d1d2d3d4d5d6d7d8d9dadbdcdddedfe0e1e2e3e4e5e6e7e8e9eaebecedeeeff0f1f2f3f4f5f6f7f8f9fafbfcfdfeff
+Plaintext: 202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f
+Ciphertext: 04f883aeb3bd0730eaf50bb6de4fa2212034e4e41b0e75e577f6bf2422c0f6d2
+MAC: 3376d2cf256ef613c56454cbb5265834
+Test: Encrypt
+Key: 404142434445464748494a4b4c4d4e4f505152535455565758595a5b5c5d5e5f
+IV: 101112131415161718191a1b
+Header: 202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f
+Plaintext: 000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f 202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f 404142434445464748494a4b4c4d4e4f505152535455565758595a5b5c5d5e5f 606162636465666768696a6b6c6d6e6f707172737475767778797a7b7c7d7e7f 808182838485868788898a8b8c8d8e8f909192939495969798999a9b9c9d9e9f a0a1a2a3a4a5a6a7a8a9aaabacadaeafb0b1b2b3b4b5b6b7b8b9babbbcbdbebf c0c1c2c3c4c5c6c7c8c9cacbcccdcecfd0d1d2d3d4d5d6d7d8d9dadbdcdddedf e0e1e2e3e4e5e6e7e8e9eaebecedeeeff0f1f2f3f4f5f6f7f8f9fafbfcfdfeff
+Ciphertext: 24d8a38e939d2710cad52b96fe6f82010014c4c43b2e55c557d69f0402e0d6f2 06c53d6cbd3f1c3c6de5dcdcad9fb74f25741dea741149fe4278a0cc24741e86 58cc0523b8d7838c60fb1de4b7c3941f5b26dea9322aa29656ec37ac18a9b108 a6f38b7917f5a9c398838b22afbd17252e96694a9e6237964a0eae21c0a6e152 15a0e82022926be97268249599e456e05029c3ebc07d78fc5b4a0862e04e68c2 9514c7bdafc4b52e04833bf30622e4eb42504a44a9dcbc774752de7bb82891ad 1eba9dc3281422a8aba8654268d3d9c81705f4c5a531ef856df5609a159af738 eb753423ed2001b8f20c23725f2bef18c409f7e52132341f27cb8f0e79894dd9
+MAC: ebb1fa9d28ccfe21bdfea7e6d91e0bab
+Test: Encrypt
+Key: fb7615b23d80891dd470980bc79584c8b2fb64ce6097878d17fce45a49e830b7
+IV: dbd1a3636024b7b402da7d6f
+Header: 36
+Plaintext: a9
+Ciphertext: 9d
+MAC: 3261b1cf931431e99a32806738ecbd2a
+Test: Encrypt
+Key: f8d476cfd646ea6c2384cb1c27d6195dfef1a9f37b9c8d21a79c21f8cb90d289
+IV: dbd1a3636024b7b402da7d6f
+Header: 7bd859a247961a21823b380e9fe8b65082ba61d3
+Plaintext: 90ae61cf7baebd4cade494c54a29ae70269aec71
+Ciphertext: 6c05313e45dc8ec10bea6c670bd94f31569386a6
+MAC: 8f3829e8e76ee23c04f566189e63c686
+Test: Encrypt
+Source: RFC 3610
+Key: C0 C1 C2 C3 C4 C5 C6 C7 C8 C9 CA CB CC CD CE CF
+IV: 00 00 00 03 02 01 00 A0 A1 A2 A3 A4 A5
+Header: 00 01 02 03 04 05 06 07
+Plaintext: 08 09 0A 0B 0C 0D 0E 0F\
+ 10 11 12 13 14 15 16 17 18 19 1A 1B 1C 1D 1E
+Ciphertext: 58 8C 97 9A 61 C6 63 D2\
+ F0 66 D0 C2 C0 F9 89 80 6D 5F 6B 61 DA C3 84
+MAC: 17 E8 D1 2C FD F9 26 E0
+Test: Encrypt
+MAC: 17 E8 D1 2C FD F9 26 00
+Test: NotVerify
+Key: C0 C1 C2 C3 C4 C5 C6 C7 C8 C9 CA CB CC CD CE CF
+IV: 00 00 00 04 03 02 01 A0 A1 A2 A3 A4 A5
+Header: 00 01 02 03 04 05 06 07
+Plaintext: 08 09 0A 0B 0C 0D 0E 0F 10 11 12 13 14 15 16 17 18 19 1A 1B 1C 1D 1E 1F
+Ciphertext: 72 C9 1A 36 E1 35 F8 CF 29 1C A8 94 08 5C 87 E3 CC 15 C4 39 C9 E4 3A 3B
+MAC: A0 91 D5 6E 10 40 09 16
+Test: Encrypt
+Key: C0 C1 C2 C3 C4 C5 C6 C7 C8 C9 CA CB CC CD CE CF
+IV: 00 00 00 05 04 03 02 A0 A1 A2 A3 A4 A5
+Header: 00 01 02 03 04 05 06 07
+Plaintext: 08 09 0A 0B 0C 0D 0E 0F 10 11 12 13 14 15 16 17 18 19 1A 1B 1C 1D 1E 1F 20
+Ciphertext: 51 B1 E5 F4 4A 19 7D 1D A4 6B 0F 8E 2D 28 2A E8 71 E8 38 BB 64 DA 85 96 57
+MAC: 4A DA A7 6F BD 9F B0 C5
+Test: Encrypt
+Key: C0 C1 C2 C3 C4 C5 C6 C7 C8 C9 CA CB CC CD CE CF
+IV: 00 00 00 06 05 04 03 A0 A1 A2 A3 A4 A5
+Header: 00 01 02 03 04 05 06 07 08 09 0A 0B
+Plaintext: 0C 0D 0E 0F 10 11 12 13 14 15 16 17 18 19 1A 1B 1C 1D 1E
+Ciphertext: A2 8C 68 65 93 9A 9A 79 FA AA 5C 4C 2A 9D 4A 91 CD AC 8C
+MAC: 96 C8 61 B9 C9 E6 1E F1
+Test: Encrypt
+Key: C0 C1 C2 C3 C4 C5 C6 C7 C8 C9 CA CB CC CD CE CF
+IV: 00 00 00 07 06 05 04 A0 A1 A2 A3 A4 A5
+Header: 00 01 02 03 04 05 06 07 08 09 0A 0B
+Plaintext: 0C 0D 0E 0F 10 11 12 13 14 15 16 17 18 19 1A 1B 1C 1D 1E 1F
+Ciphertext: DC F1 FB 7B 5D 9E 23 FB 9D 4E 13 12 53 65 8A D8 6E BD CA 3E
+MAC: 51 E8 3F 07 7D 9C 2D 93
+Test: Encrypt
+Key: C0 C1 C2 C3 C4 C5 C6 C7 C8 C9 CA CB CC CD CE CF
+IV: 00 00 00 08 07 06 05 A0 A1 A2 A3 A4 A5
+Header: 00 01 02 03 04 05 06 07 08 09 0A 0B
+Plaintext: 0C 0D 0E 0F 10 11 12 13 14 15 16 17 18 19 1A 1B 1C 1D 1E 1F 20
+Ciphertext: 6F C1 B0 11 F0 06 56 8B 51 71 A4 2D 95 3D 46 9B 25 70 A4 BD 87
+MAC: 40 5A 04 43 AC 91 CB 94
+Test: Encrypt
+Key: C0 C1 C2 C3 C4 C5 C6 C7 C8 C9 CA CB CC CD CE CF
+IV: 00 00 00 09 08 07 06 A0 A1 A2 A3 A4 A5
+Header: 00 01 02 03 04 05 06 07
+Plaintext: 08 09 0A 0B 0C 0D 0E 0F 10 11 12 13 14 15 16 17 18 19 1A 1B 1C 1D 1E
+Ciphertext: 01 35 D1 B2 C9 5F 41 D5 D1 D4 FE C1 85 D1 66 B8 09 4E 99 9D FE D9 6C
+MAC: 04 8C 56 60 2C 97 AC BB 74 90
+Test: Encrypt
+Key: C0 C1 C2 C3 C4 C5 C6 C7 C8 C9 CA CB CC CD CE CF
+IV: 00 00 00 0A 09 08 07 A0 A1 A2 A3 A4 A5
+Header: 00 01 02 03 04 05 06 07
+Plaintext: 08 09 0A 0B 0C 0D 0E 0F 10 11 12 13 14 15 16 17 18 19 1A 1B 1C 1D 1E 1F
+Ciphertext: 7B 75 39 9A C0 83 1D D2 F0 BB D7 58 79 A2 FD 8F 6C AE 6B 6C D9 B7 DB 24
+MAC: C1 7B 44 33 F4 34 96 3F 34 B4
+Test: Encrypt
diff --git a/TestVectors/cmac.txt b/TestVectors/cmac.txt
new file mode 100644
index 0000000..4fa6c41
--- /dev/null
+++ b/TestVectors/cmac.txt
@@ -0,0 +1,38 @@
+AlgorithmType: MAC
+Name: CMAC(AES)
+Source: RFC 4493
+Key: 2b7e1516 28aed2a6 abf71588 09cf4f3c
+Message:
+MAC: bb1d6929 e9593728 7fa37d12 9b756746
+Test: Verify
+Message: 6bc1bee2 2e409f96 e93d7e11 7393172a
+MAC: 070a16b4 6b4d4144 f79bdd9d d04a287c
+Test: Verify
+Message: 6bc1bee2 2e409f96 e93d7e11 7393172a ae2d8a57 1e03ac9c 9eb76fac 45af8e51 30c81c46 a35ce411
+MAC: dfa66747 de9ae630 30ca3261 1497c827
+Test: Verify
+Message: 6bc1bee2 2e409f96 e93d7e11 7393172a ae2d8a57 1e03ac9c 9eb76fac 45af8e51 30c81c46 a35ce411 e5fbc119 1a0a52ef f69f2445 df4f9b17 ad2b417b e66c3710
+MAC: 51f0bebf 7e3b9d92 fc497417 79363cfe
+Test: Verify
+MAC: 51f0bebf 7e3b9d92 fc497417 79363cff
+Test: NotVerify
+
+AlgorithmType: MAC
+Name: CMAC(DES-EDE3)
+Source: http://csrc.nist.gov/groups/STM/cavp/documents/mac/cmactestvectors.zip
+Key: f8fba7b9b3e9d68a 2f70bfd304d32a15 9e13453e0d16928a
+Message:
+MAC: eb61515b
+Test: VerifyTruncated
+Key: 344a6732dc5e5431 e98a4f7c323dc1c4 6b0275dc150e68e9
+Message: 25db0710fb165d316e7c32dd25648ed0
+MAC: 862f0e2b
+Test: VerifyTruncated
+Key: 20ae32c49bab3bf8 f86bb66173fb54d5 3e700868c46bc291
+Message: 582bd9c8c36ec815d0a9
+MAC: 0d62f14f
+Test: VerifyTruncated
+Key: 62232501b9e9c1b5 54209d7c075d2c31 73a2f289a84c49ce
+Message: adaf4bfffab79ffb60b94647faac634929c56e694052881881e60b1149b6
+MAC: a05674f2c905d153
+Test: Verify
diff --git a/TestVectors/gcm.txt b/TestVectors/gcm.txt
new file mode 100644
index 0000000..e39ed36
--- /dev/null
+++ b/TestVectors/gcm.txt
@@ -0,0 +1,139 @@
+AlgorithmType: AuthenticatedSymmetricCipher
+Name: AES/GCM
+Source: aes-modes-src-07-10-08/Testvals/gcm.1, Basic Tests for GCM (compiled by B. R. Gladman)
+Key: 00000000000000000000000000000000
+IV: 000000000000000000000000
+MAC: 00000000000000000000000000000000
+Test: NotVerify
+Key: 00000000000000000000000000000000
+IV: 000000000000000000000000
+MAC: 58e2fccefa7e3061367f1d57a4e7455a
+Test: Encrypt
+Key: 00000000000000000000000000000000
+IV: 000000000000000000000000
+Plaintext: 00000000000000000000000000000000
+Ciphertext: 0388dace60b6a392f328c2b971b2fe78
+MAC: ab6e47d42cec13bdf53a67b21257bddf
+Test: Encrypt
+Key: feffe9928665731c6d6a8f9467308308
+IV: cafebabefacedbaddecaf888
+Plaintext: d9313225f88406e5a55909c5aff5269a86a7a9531534f7da2e4c303d8a318a72 1c3c0c95956809532fcf0e2449a6b525b16aedf5aa0de657ba637b391aafd255
+Ciphertext: 42831ec2217774244b7221b784d0d49ce3aa212f2c02a4e035c17e2329aca12e 21d514b25466931c7d8f6a5aac84aa051ba30b396a0aac973d58e091473f5985
+MAC: 4d5c2af327cd64a62cf35abd2ba6fab4
+Test: Encrypt
+Key: feffe9928665731c6d6a8f9467308308
+IV: cafebabefacedbaddecaf888
+Header: feedfacedeadbeeffeedfacedeadbeefabaddad2
+Plaintext: d9313225f88406e5a55909c5aff5269a86a7a9531534f7da2e4c303d8a318a72 1c3c0c95956809532fcf0e2449a6b525b16aedf5aa0de657ba637b39
+Ciphertext: 42831ec2217774244b7221b784d0d49ce3aa212f2c02a4e035c17e2329aca12e 21d514b25466931c7d8f6a5aac84aa051ba30b396a0aac973d58e091
+MAC: 5bc94fbc3221a5db94fae95ae7121a47
+Test: Encrypt
+Key: feffe9928665731c6d6a8f9467308308
+IV: cafebabefacedbad
+Header: feedfacedeadbeeffeedfacedeadbeefabaddad2
+Plaintext: d9313225f88406e5a55909c5aff5269a86a7a9531534f7da2e4c303d8a318a72 1c3c0c95956809532fcf0e2449a6b525b16aedf5aa0de657ba637b39
+Ciphertext: 61353b4c2806934a777ff51fa22a4755699b2a714fcdc6f83766e5f97b6c7423 73806900e49f24b22b097544d4896b424989b5e1ebac0f07c23f4598
+MAC: 3612d2e79e3b0785561be14aaca2fccb
+Test: Encrypt
+Key: feffe9928665731c6d6a8f9467308308
+IV: 9313225df88406e555909c5aff5269aa6a7a9538534f7da1e4c303d2a318a728 c3c0c95156809539fcf0e2429a6b525416aedbf5a0de6a57a637b39b
+Header: feedfacedeadbeeffeedfacedeadbeefabaddad2
+Plaintext: d9313225f88406e5a55909c5aff5269a86a7a9531534f7da2e4c303d8a318a72 1c3c0c95956809532fcf0e2449a6b525b16aedf5aa0de657ba637b39
+Ciphertext: 8ce24998625615b603a033aca13fb894be9112a5c3a211a8ba262a3cca7e2ca7 01e4a9a4fba43c90ccdcb281d48c7c6fd62875d2aca417034c34aee5
+MAC: 619cc5aefffe0bfa462af43c1699d050
+Test: Encrypt
+Header:
+Plaintext:
+Ciphertext:
+Key: 000000000000000000000000000000000000000000000000
+IV: 000000000000000000000000
+MAC: cd33b28ac773f74ba00ed1f312572435
+Test: Encrypt
+Key: 000000000000000000000000000000000000000000000000
+IV: 000000000000000000000000
+Plaintext: 00000000000000000000000000000000
+Ciphertext: 98e7247c07f0fe411c267e4384b0f600
+MAC: 2ff58d80033927ab8ef4d4587514f0fb
+Test: Encrypt
+Key: feffe9928665731c6d6a8f9467308308feffe9928665731c
+IV: cafebabefacedbaddecaf888
+Plaintext: d9313225f88406e5a55909c5aff5269a86a7a9531534f7da2e4c303d8a318a72 1c3c0c95956809532fcf0e2449a6b525b16aedf5aa0de657ba637b391aafd255
+Ciphertext: 3980ca0b3c00e841eb06fac4872a2757859e1ceaa6efd984628593b40ca1e19c 7d773d00c144c525ac619d18c84a3f4718e2448b2fe324d9ccda2710acade256
+MAC: 9924a7c8587336bfb118024db8674a14
+Test: Encrypt
+Key: feffe9928665731c6d6a8f9467308308feffe9928665731c
+IV: cafebabefacedbaddecaf888
+Header: feedfacedeadbeeffeedfacedeadbeefabaddad2
+Plaintext: d9313225f88406e5a55909c5aff5269a86a7a9531534f7da2e4c303d8a318a72 1c3c0c95956809532fcf0e2449a6b525b16aedf5aa0de657ba637b39
+Ciphertext: 3980ca0b3c00e841eb06fac4872a2757859e1ceaa6efd984628593b40ca1e19c 7d773d00c144c525ac619d18c84a3f4718e2448b2fe324d9ccda2710
+MAC: 2519498e80f1478f37ba55bd6d27618c
+Test: Encrypt
+Key: feffe9928665731c6d6a8f9467308308feffe9928665731c
+IV: cafebabefacedbad
+Header: feedfacedeadbeeffeedfacedeadbeefabaddad2
+Plaintext: d9313225f88406e5a55909c5aff5269a86a7a9531534f7da2e4c303d8a318a72 1c3c0c95956809532fcf0e2449a6b525b16aedf5aa0de657ba637b39
+Ciphertext: 0f10f599ae14a154ed24b36e25324db8c566632ef2bbb34f8347280fc4507057 fddc29df9a471f75c66541d4d4dad1c9e93a19a58e8b473fa0f062f7
+MAC: 65dcc57fcf623a24094fcca40d3533f8
+Test: Encrypt
+Key: feffe9928665731c6d6a8f9467308308feffe9928665731c
+IV: 9313225df88406e555909c5aff5269aa6a7a9538534f7da1e4c303d2a318a728 c3c0c95156809539fcf0e2429a6b525416aedbf5a0de6a57a637b39b
+Header: feedfacedeadbeeffeedfacedeadbeefabaddad2
+Plaintext: d9313225f88406e5a55909c5aff5269a86a7a9531534f7da2e4c303d8a318a72 1c3c0c95956809532fcf0e2449a6b525b16aedf5aa0de657ba637b39
+Ciphertext: d27e88681ce3243c4830165a8fdcf9ff1de9a1d8e6b447ef6ef7b79828666e45 81e79012af34ddd9e2f037589b292db3e67c036745fa22e7e9b7373b
+MAC: dcf566ff291c25bbb8568fc3d376a6d9
+Test: Encrypt
+Header:
+Plaintext:
+Ciphertext:
+Key: 0000000000000000000000000000000000000000000000000000000000000000
+IV: 000000000000000000000000
+MAC: 530f8afbc74536b9a963b4f1c4cb738b
+Test: Encrypt
+Key: 0000000000000000000000000000000000000000000000000000000000000000
+IV: 000000000000000000000000
+Plaintext: 00000000000000000000000000000000
+Ciphertext: cea7403d4d606b6e074ec5d3baf39d18
+MAC: d0d1c8a799996bf0265b98b5d48ab919
+Test: Encrypt
+Key: feffe9928665731c6d6a8f9467308308feffe9928665731c6d6a8f9467308308
+IV: cafebabefacedbaddecaf888
+Plaintext: d9313225f88406e5a55909c5aff5269a86a7a9531534f7da2e4c303d8a318a72 1c3c0c95956809532fcf0e2449a6b525b16aedf5aa0de657ba637b391aafd255
+Ciphertext: 522dc1f099567d07f47f37a32a84427d643a8cdcbfe5c0c97598a2bd2555d1aa 8cb08e48590dbb3da7b08b1056828838c5f61e6393ba7a0abcc9f662898015ad
+MAC: b094dac5d93471bdec1a502270e3cc6c
+Test: Encrypt
+Key: feffe9928665731c6d6a8f9467308308feffe9928665731c6d6a8f9467308308
+IV: cafebabefacedbaddecaf888
+Header: feedfacedeadbeeffeedfacedeadbeefabaddad2
+Plaintext: d9313225f88406e5a55909c5aff5269a86a7a9531534f7da2e4c303d8a318a72 1c3c0c95956809532fcf0e2449a6b525b16aedf5aa0de657ba637b39
+Ciphertext: 522dc1f099567d07f47f37a32a84427d643a8cdcbfe5c0c97598a2bd2555d1aa 8cb08e48590dbb3da7b08b1056828838c5f61e6393ba7a0abcc9f662
+MAC: 76fc6ece0f4e1768cddf8853bb2d551b
+Test: Encrypt
+Key: feffe9928665731c6d6a8f9467308308feffe9928665731c6d6a8f9467308308
+IV: cafebabefacedbad
+Header: feedfacedeadbeeffeedfacedeadbeefabaddad2
+Plaintext: d9313225f88406e5a55909c5aff5269a86a7a9531534f7da2e4c303d8a318a72 1c3c0c95956809532fcf0e2449a6b525b16aedf5aa0de657ba637b39
+Ciphertext: c3762df1ca787d32ae47c13bf19844cbaf1ae14d0b976afac52ff7d79bba9de0 feb582d33934a4f0954cc2363bc73f7862ac430e64abe499f47c9b1f
+MAC: 3a337dbf46a792c45e454913fe2ea8f2
+Test: Encrypt
+Key: feffe9928665731c6d6a8f9467308308feffe9928665731c6d6a8f9467308308
+IV: 9313225df88406e555909c5aff5269aa6a7a9538534f7da1e4c303d2a318a728 c3c0c95156809539fcf0e2429a6b525416aedbf5a0de6a57a637b39b
+Header: feedfacedeadbeeffeedfacedeadbeefabaddad2
+Plaintext: d9313225f88406e5a55909c5aff5269a86a7a9531534f7da2e4c303d8a318a72 1c3c0c95956809532fcf0e2449a6b525b16aedf5aa0de657ba637b39
+Ciphertext: 5a8def2f0c9e53f1f75d7853659e2a20eeb2b22aafde6419a058ab4f6f746bf4 0fc0c3b780f244452da3ebf1c5d82cdea2418997200ef82e44ae7e3f
+MAC: a44a8266ee1c8eb0c8b5d4cf5ae9f19a
+Test: Encrypt
+Header:
+Plaintext:
+Ciphertext:
+Key: 00000000000000000000000000000000
+IV: 000000000000000000000000
+Plaintext: 000102030405060708090a0b0c0d0e0f 101112131415161718191a1b1c1d1e1f 202122232425262728292a2b2c2d2e2f 303132333435363738393a3b3c3d3e3f 404142434445464748494a4b4c4d4e4f 505152535455565758595a5b5c5d5e5f 606162636465666768696a6b6c6d6e6f 707172737475767778797a7b7c7d7e7f 808182838485868788898a8b8c8d8e8f 909192939495969798999a9b9c9d9e9f a0a1a2a3a4a5a6a7a8a9aaabacadaeaf b0b1b2b3b4b5b6b7b8b9babbbcbdbebf c0c1c2c3c4c5c6c7c8c9cacbcccdcecf d0d1d2d3d4d5d6d7d8d9dadbdcdddedf
+Ciphertext: 0389d8cd64b3a595fb21c8b27dbff077 e784b8b85d5e4f34efe493e48896dfff 002333026a56b2fd08a09c87fcbe85cf f97c902a25bb1f4a43478687f5feb6cd ca9f3fc6ecab732627386ee2996a4cde c5e91f48c293c6a87774b950aeb1d7bf 62321a0d76006297b2d06623cf6e4fb1 433494c3326b0ae914120085a195413f 5e3278e4107d7b08dd2107405610e67d 83ed5b5ba0b591e9e46b1029f5f6936f fdb0e788fc09f60d861a0b3e1ab6294a 76ebdf6663421ef7dd6c1bc448dfcdb7 a0c38bae72fa627ed327f2b46fcec25a 77ee5fd7e3354788643c0d7df15075d5
+MAC: 6b385f3012eafda4189da7ad3b6eafbf
+Test: Encrypt
+Key: 00000000000000000000000000000000
+IV: 000000000000000000000000
+Plaintext: 000102030405060708090a0b0c0d0e0f 101112131415161718191a1b1c1d1e1f 202122232425262728292a2b2c2d2e2f 303132333435363738393a3b3c3d3e3f 404142434445464748494a4b4c4d4e4f 505152535455565758595a5b5c5d5e5f 606162636465666768696a6b6c6d6e6f 707172737475767778797a7b7c7d7e7f 808182838485868788898a8b8c8d8e8f 909192939495969798999a9b9c9d9e9f a0a1a2a3a4a5a6a7a8a9aaabacadaeaf b0b1b2b3b4b5b6b7b8b9babbbcbdbebf c0c1c2c3c4c5c6c7c8c9cacbcccdcecf d0d1d2d3d4d5d6d7d8d9dadbdcdddedf
+Ciphertext: 0389d8cd64b3a595fb21c8b27dbff077 e784b8b85d5e4f34efe493e48896dfff 002333026a56b2fd08a09c87fcbe85cf f97c902a25bb1f4a43478687f5feb6cd ca9f3fc6ecab732627386ee2996a4cde c5e91f48c293c6a87774b950aeb1d7bf 62321a0d76006297b2d06623cf6e4fb1 433494c3326b0ae914120085a195413f 5e3278e4107d7b08dd2107405610e67d 83ed5b5ba0b591e9e46b1029f5f6936f fdb0e788fc09f60d861a0b3e1ab6294a 76ebdf6663421ef7dd6c1bc448dfcdb7 a0c38bae72fa627ed327f2b46fcec25a 77ee5fd7e3354788643c0d7df15075d5
+MAC: 6b385f3012eafda4189da7ad3b6eafbf
+Test: Encrypt
diff --git a/TestVectors/hmac.txt b/TestVectors/hmac.txt
index b380bab..52f85fd 100644
--- a/TestVectors/hmac.txt
+++ b/TestVectors/hmac.txt
@@ -4,40 +4,40 @@ Source: RFC 2202
Comment: Test Case 1
Key: 0x0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b
Message: "Hi There"
-Digest: 0x9294727a3638bb1c13f48ef8158bfc9d
+MAC: 0x9294727a3638bb1c13f48ef8158bfc9d
Test: Verify
Comment: Test Case 2
Key: "Jefe"
Message: "what do ya want for nothing?"
-Digest: 0x750c783e6ab0b503eaa86e310a5db738
+MAC: 0x750c783e6ab0b503eaa86e310a5db738
Test: Verify
Comment: Test Case 3
Key: 0xaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
Message: r50 0xdd
-Digest: 0x56be34521d144c88dbb8c733f0e8b3f6
+MAC: 0x56be34521d144c88dbb8c733f0e8b3f6
Test: Verify
Comment: Test Case 4
Key: 0x0102030405060708090a0b0c0d0e0f10111213141516171819
Message: r50 0xcd
-Digest: 0x697eaf0aca3a3aea3a75164746ffaa79
+MAC: 0x697eaf0aca3a3aea3a75164746ffaa79
Test: Verify
Comment: Test Case 5
Key: 0x0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c
Message: "Test With Truncation"
-Digest: 0x56461ef2342edc00f9bab995690efd4c
+MAC: 0x56461ef2342edc00f9bab995690efd4c
Test: Verify
-Digest: 0x56461ef2342edc00f9bab995
-TruncatedSize: 12
+MAC: 0x56461ef2342edc00f9bab995
+#TruncatedSize: 12
Test: VerifyTruncated
Comment: Test Case 6
Key: r80 0xaa
Message: "Test Using Larger Than Block-Size Key - Hash Key First"
-Digest: 0x6b1ab7fe4bd7bf8f0b62e6ce61b9d0cd
+MAC: 0x6b1ab7fe4bd7bf8f0b62e6ce61b9d0cd
Test: Verify
Comment: Test Case 7
Key: r80 0xaa
Message: "Test Using Larger Than Block-Size Key and Larger Than One Block-Size Data"
-Digest: 0x6f630fad67cda0ee1fb1f562db3aa53e
+MAC: 0x6f630fad67cda0ee1fb1f562db3aa53e
Test: Verify
AlgorithmType: MAC
@@ -46,40 +46,40 @@ Source: RFC 2202
Comment: Test Case 1
Key: 0x0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b
Message: "Hi There"
-Digest: 0xb617318655057264e28bc0b6fb378c8ef146be00
+MAC: 0xb617318655057264e28bc0b6fb378c8ef146be00
Test: Verify
Comment: Test Case 2
Key: "Jefe"
Message: "what do ya want for nothing?"
-Digest: 0xeffcdf6ae5eb2fa2d27416d5f184df9c259a7c79
+MAC: 0xeffcdf6ae5eb2fa2d27416d5f184df9c259a7c79
Test: Verify
Comment: Test Case 3
Key: 0xaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
Message: r50 0xdd
-Digest: 0x125d7342b9ac11cd91a39af48aa17b4f63f175d3
+MAC: 0x125d7342b9ac11cd91a39af48aa17b4f63f175d3
Test: Verify
Comment: Test Case 4
Key: 0x0102030405060708090a0b0c0d0e0f10111213141516171819
Message: r50 0xcd
-Digest: 0x4c9007f4026250c6bc8414f9bf50c86c2d7235da
+MAC: 0x4c9007f4026250c6bc8414f9bf50c86c2d7235da
Test: Verify
Comment: Test Case 5
Key: 0x0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c
Message: "Test With Truncation"
-Digest: 0x4c1a03424b55e07fe7f27be1d58bb9324a9a5a04
+MAC: 0x4c1a03424b55e07fe7f27be1d58bb9324a9a5a04
Test: Verify
-Digest: 0x4c1a03424b55e07fe7f27be1
-TruncatedSize: 12
+MAC: 0x4c1a03424b55e07fe7f27be1
+#TruncatedSize: 12
Test: VerifyTruncated
Comment: Test Case 6
Key: r80 0xaa
Message: "Test Using Larger Than Block-Size Key - Hash Key First"
-Digest: 0xaa4ae5e15272d00e95705637ce8a3b55ed402112
+MAC: 0xaa4ae5e15272d00e95705637ce8a3b55ed402112
Test: Verify
Comment: Test Case 7
Key: r80 0xaa
Message: "Test Using Larger Than Block-Size Key and Larger Than One Block-Size Data"
-Digest: 0xe8e99d0f45237d786d6bbaa7965c7808bbff1a91
+MAC: 0xe8e99d0f45237d786d6bbaa7965c7808bbff1a91
Test: Verify
AlgorithmType: MAC
@@ -88,38 +88,38 @@ Source: RFC 2286
Comment: Test Case 1
Key: 0x0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b
Message: "Hi There"
-Digest: 0x24cb4bd67d20fc1a5d2ed7732dcc39377f0a5668
+MAC: 0x24cb4bd67d20fc1a5d2ed7732dcc39377f0a5668
Test: Verify
Comment: Test Case 2
Key: "Jefe"
Message: "what do ya want for nothing?"
-Digest: 0xdda6c0213a485a9e24f4742064a7f033b43c4069
+MAC: 0xdda6c0213a485a9e24f4742064a7f033b43c4069
Test: Verify
Comment: Test Case 3
Key: 0xaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
Message: r50 0xdd
-Digest: 0xb0b105360de759960ab4f35298e116e295d8e7c1
+MAC: 0xb0b105360de759960ab4f35298e116e295d8e7c1
Test: Verify
Comment: Test Case 4
Key: 0x0102030405060708090a0b0c0d0e0f10111213141516171819
Message: r50 0xcd
-Digest: 0xd5ca862f4d21d5e610e18b4cf1beb97a4365ecf4
+MAC: 0xd5ca862f4d21d5e610e18b4cf1beb97a4365ecf4
Test: Verify
Comment: Test Case 5
Key: 0x0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c
Message: "Test With Truncation"
-Digest: 0x7619693978f91d90539ae786500ff3d8e0518e39
+MAC: 0x7619693978f91d90539ae786500ff3d8e0518e39
Test: Verify
-Digest: 0x7619693978f91d90539ae786
-TruncatedSize: 12
+MAC: 0x7619693978f91d90539ae786
+#TruncatedSize: 12
Test: VerifyTruncated
Comment: Test Case 6
Key: r80 0xaa
Message: "Test Using Larger Than Block-Size Key - Hash Key First"
-Digest: 0x6466ca07ac5eac29e1bd523e5ada7605b791fd8b
+MAC: 0x6466ca07ac5eac29e1bd523e5ada7605b791fd8b
Test: Verify
Comment: Test Case 7
Key: r80 0xaa
Message: "Test Using Larger Than Block-Size Key and Larger Than One Block-Size Data"
-Digest: 0x69ea60798d71616cce5fd0871e23754cd75d5a0a
+MAC: 0x69ea60798d71616cce5fd0871e23754cd75d5a0a
Test: Verify
diff --git a/TestVectors/panama.txt b/TestVectors/panama.txt
index 112011c..bd4d4ee 100755
--- a/TestVectors/panama.txt
+++ b/TestVectors/panama.txt
@@ -31,17 +31,17 @@ Name: Panama-LE
Source: modified from Panama hash test vectors
Key: ""
Message: ""
-Digest: aa0cc954d757d7ac7779ca3342334ca471abd47d5952ac91ed837ecd5b16922b
+MAC: aa0cc954d757d7ac7779ca3342334ca471abd47d5952ac91ed837ecd5b16922b
Test: Verify
Message: "The quick brown fox jumps over the lazy dog"
-Digest: 5f5ca355b90ac622b0aa7e654ef5f27e9e75111415b48b8afe3add1c6b89cba1
+MAC: 5f5ca355b90ac622b0aa7e654ef5f27e9e75111415b48b8afe3add1c6b89cba1
Test: Verify
Message: r15625 "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
-Digest: af9c66fb6058e2232a5dfba063ee14b0f86f0e334e165812559435464dd9bb60
+MAC: af9c66fb6058e2232a5dfba063ee14b0f86f0e334e165812559435464dd9bb60
Test: Verify
Key: "The "
Message: "quick brown fox jumps over the lazy dog"
-Digest: 5f5ca355b90ac622b0aa7e654ef5f27e9e75111415b48b8afe3add1c6b89cba1
+MAC: 5f5ca355b90ac622b0aa7e654ef5f27e9e75111415b48b8afe3add1c6b89cba1
Test: Verify
AlgorithmType: MAC
@@ -49,17 +49,17 @@ Name: Panama-BE
Source: modified from Panama hash test vectors
Key: ""
Message: ""
-Digest: e81aa04523532dd7267e5c5bc3ba0e289837a62ba032350351980e960a84b0af
+MAC: e81aa04523532dd7267e5c5bc3ba0e289837a62ba032350351980e960a84b0af
Test: Verify
Message: "The quick brown fox jumps over the lazy dog"
-Digest: 8fa7dadce0110f979a0b795e76b2c25628d8bda88747758149c42e3bc13f85bc
+MAC: 8fa7dadce0110f979a0b795e76b2c25628d8bda88747758149c42e3bc13f85bc
Test: Verify
Message: r15625 "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
-Digest: cb34f0937e8d870d3bd7ff6311765f2c229a6c2154e4db119538db5159437cab
+MAC: cb34f0937e8d870d3bd7ff6311765f2c229a6c2154e4db119538db5159437cab
Test: Verify
Key: "The "
Message: "quick brown fox jumps over the lazy dog"
-Digest: 8fa7dadce0110f979a0b795e76b2c25628d8bda88747758149c42e3bc13f85bc
+MAC: 8fa7dadce0110f979a0b795e76b2c25628d8bda88747758149c42e3bc13f85bc
Test: Verify
AlgorithmType: SymmetricCipher
diff --git a/TestVectors/seed.txt b/TestVectors/seed.txt
new file mode 100644
index 0000000..a08a102
--- /dev/null
+++ b/TestVectors/seed.txt
@@ -0,0 +1,19 @@
+AlgorithmType: SymmetricCipher
+Name: SEED/ECB
+Source: RFC 4269
+Key: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+Plaintext: 00 01 02 03 04 05 06 07 08 09 0A 0B 0C 0D 0E 0F
+Ciphertext: 5E BA C6 E0 05 4E 16 68 19 AF F1 CC 6D 34 6C DB
+Test: Encrypt
+Key: 00 01 02 03 04 05 06 07 08 09 0A 0B 0C 0D 0E 0F
+Plaintext: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+Ciphertext: C1 1F 22 F2 01 40 50 50 84 48 35 97 E4 37 0F 43
+Test: Encrypt
+Key: 47 06 48 08 51 E6 1B E8 5D 74 BF B3 FD 95 61 85
+Plaintext: 83 A2 F8 A2 88 64 1F B9 A4 E9 A5 CC 2F 13 1C 7D
+Ciphertext: EE 54 D1 3E BC AE 70 6D 22 6B C3 14 2C D4 0D 4A
+Test: Encrypt
+Key: 28 DB C3 BC 49 FF D8 7D CF A5 09 B1 1D 42 2B E7
+Plaintext: B4 1E 6B E2 EB A8 4A 14 8E 2E ED 84 59 3C 5E C7
+Ciphertext: 9B 9B 7B FC D1 81 3C B9 5D 0B 36 18 F4 0F 51 22
+Test: Encrypt
diff --git a/TestVectors/ttmac.txt b/TestVectors/ttmac.txt
index 537a333..ec2e683 100644
--- a/TestVectors/ttmac.txt
+++ b/TestVectors/ttmac.txt
@@ -5,36 +5,36 @@ Comment: Key for all test cases
Key: 00112233445566778899aabbccddeeff01234567
Comment: Test Case 1
Message: ""
-Digest: 2dec8ed4a0fd712ed9fbf2ab466ec2df21215e4a
+MAC: 2dec8ed4a0fd712ed9fbf2ab466ec2df21215e4a
Test: Verify
Comment: Test Case 2
Message: "a"
-Digest: 5893e3e6e306704dd77ad6e6ed432cde321a7756
+MAC: 5893e3e6e306704dd77ad6e6ed432cde321a7756
Test: Verify
Comment: Test Case 3
Message: "abc"
-Digest: 70bfd1029797a5c16da5b557a1f0b2779b78497e
+MAC: 70bfd1029797a5c16da5b557a1f0b2779b78497e
Test: Verify
Comment: Test Case 4
Message: "message digest"
-Digest: 8289f4f19ffe4f2af737de4bd71c829d93a972fa
+MAC: 8289f4f19ffe4f2af737de4bd71c829d93a972fa
Test: Verify
Comment: Test Case 5
Message: "abcdefghijklmnopqrstuvwxyz"
-Digest: 2186ca09c5533198b7371f245273504ca92bae60
+MAC: 2186ca09c5533198b7371f245273504ca92bae60
Test: Verify
Comment: Test Case 6
Message: "abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq"
-Digest: 8a7bf77aef62a2578497a27c0d6518a429e7c14d
+MAC: 8a7bf77aef62a2578497a27c0d6518a429e7c14d
Test: Verify
Comment: Test Case 7
Message: "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789"
-Digest: 54bac392a886806d169556fcbb6789b54fb364fb
+MAC: 54bac392a886806d169556fcbb6789b54fb364fb
Test: Verify
Comment: Test Case 8
Message: r8 "1234567890"
-Digest: 0ced2c9f8f0d9d03981ab5c8184bac43dd54c484
+MAC: 0ced2c9f8f0d9d03981ab5c8184bac43dd54c484
Test: Verify
Comment: Test Case 9
Message: r15625 "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
-Digest: 27b3aedb5df8b629f0142194daa3846e1895f3d2
+MAC: 27b3aedb5df8b629f0142194daa3846e1895f3d2
diff --git a/TestVectors/vmac.txt b/TestVectors/vmac.txt
index ad7db7a..1d983cd 100755
--- a/TestVectors/vmac.txt
+++ b/TestVectors/vmac.txt
@@ -2,76 +2,76 @@ AlgorithmType: MAC
Name: VMAC(AES)-64
Source: http://www.fastcrypto.org/vmac/draft-krovetz-vmac-01.txt
Key: "abcdefghijklmnop"
-IV: r8 00 "bcdefghi"
+IV: "bcdefghi"
Message: ""
-Digest: 2576BE1C56D8B81B
+MAC: 2576BE1C56D8B81B
Test: Verify
Message: "abc"
-Digest: 2D376CF5B1813CE5
+MAC: 2D376CF5B1813CE5
Test: Verify
Message: r16 "abc"
-Digest: E8421F61D573D298
+MAC: E8421F61D573D298
Test: Verify
Message: r100 "abc"
-Digest: 4492DF6C5CAC1BBE
+MAC: 4492DF6C5CAC1BBE
Test: Verify
Message: r1000000 "abc"
-Digest: 09BA597DD7601113
+MAC: 09BA597DD7601113
Test: Verify
Message: r42 "abc" "ab"
-Digest: D638B73921F184DE
+MAC: D638B73921F184DE
Test: Verify
Message: r170 "abc" "ab"
-Digest: 9DA310281E6FD0A0
+MAC: 9DA310281E6FD0A0
Test: Verify
Message: r65 "a"
-Digest: 90 ea 57 cb 51 bc 92 a3
+MAC: 90 ea 57 cb 51 bc 92 a3
Test: Verify
Message: r129 "a"
-Digest: 86 34 83 87 d1 3d 82 33
+MAC: 86 34 83 87 d1 3d 82 33
Test: Verify
Message: r65 "abc"
-Digest: E86A86EC77A8BF61
+MAC: E86A86EC77A8BF61
Test: Verify
Message: "abc"
-Digest: 2D376CF5B1813CE0
+MAC: 2D376CF5B1813CE0
Test: NotVerify
AlgorithmType: MAC
Name: VMAC(AES)-128
Source: http://www.fastcrypto.org/vmac/draft-krovetz-vmac-01.txt
Key: "abcdefghijklmnop"
-IV: r8 00 "bcdefghi"
+IV: "bcdefghi"
Message: ""
-Digest: 472766C70F74ED23481D6D7DE4E80DAC
+MAC: 472766C70F74ED23481D6D7DE4E80DAC
Test: Verify
Message: "abc"
-Digest: 4EE815A06A1D71EDD36FC75D51188A42
+MAC: 4EE815A06A1D71EDD36FC75D51188A42
Test: Verify
Message: r16 "abc"
-Digest: 09F2C80C8E1007A0C12FAE19FE4504AE
+MAC: 09F2C80C8E1007A0C12FAE19FE4504AE
Test: Verify
Message: r100 "abc"
-Digest: 66438817154850C61D8A412164803BCB
+MAC: 66438817154850C61D8A412164803BCB
Test: Verify
Message: r1000000 "abc"
-Digest: 2B6B02288FFC461B75485DE893C629DC
+MAC: 2B6B02288FFC461B75485DE893C629DC
Test: Verify
Message: r42 "abc" "ab"
-Digest: F7E95FE3DA8DB9E6BB973E65D0B4CEA5
+MAC: F7E95FE3DA8DB9E6BB973E65D0B4CEA5
Test: Verify
Message: r170 "abc" "ab"
-Digest: BF53B8D2D70C05A85880C2E21CAF1299
+MAC: BF53B8D2D70C05A85880C2E21CAF1299
Test: Verify
Message: r65 "a"
-Digest: b2 9b 00 76 0a 58 c7 ab 92 d6 60 24 d6 9c 1b 92
+MAC: b2 9b 00 76 0a 58 c7 ab 92 d6 60 24 d6 9c 1b 92
Test: Verify
Message: r129 "a"
-Digest: a7 e5 2c 32 89 d9 b7 3b 53 57 6f 05 95 85 ee 79
+MAC: a7 e5 2c 32 89 d9 b7 3b 53 57 6f 05 95 85 ee 79
Test: Verify
Message: r65 "abc"
-Digest: 0A1B2F973044F469F405917E45010334
+MAC: 0A1B2F973044F469F405917E45010334
Test: Verify
Message: "abc"
-Digest: 4EE815A06A1D71EDD36FC75D51188A40
+MAC: 4EE815A06A1D71EDD36FC75D51188A40
Test: NotVerify
diff --git a/aes.h b/aes.h
index 7c82566..0087542 100644
--- a/aes.h
+++ b/aes.h
@@ -5,7 +5,7 @@
NAMESPACE_BEGIN(CryptoPP)
-//! AES winner, announced on 10/2/2000
+//! <a href="http://www.cryptolounge.org/wiki/AES">AES</a> winner, announced on 10/2/2000
DOCUMENTED_TYPEDEF(Rijndael, AES);
typedef RijndaelEncryption AESEncryption;
diff --git a/algparam.cpp b/algparam.cpp
index c9da677..84f8be0 100644
--- a/algparam.cpp
+++ b/algparam.cpp
@@ -22,7 +22,7 @@ bool AlgorithmParametersBase::GetVoidValue(const char *name, const std::type_inf
{
if (strcmp(name, "ValueNames") == 0)
{
- ThrowIfTypeMismatch(name, typeid(std::string), valueType);
+ NameValuePairs::ThrowIfTypeMismatch(name, typeid(std::string), valueType);
if (m_next.get())
m_next->GetVoidValue(name, valueType, pValue);
(*reinterpret_cast<std::string *>(pValue) += m_name) += ";";
@@ -40,9 +40,53 @@ bool AlgorithmParametersBase::GetVoidValue(const char *name, const std::type_inf
return false;
}
+AlgorithmParameters::AlgorithmParameters()
+ : m_constructed(false), m_defaultThrowIfNotUsed(true)
+{
+ new(m_first) member_ptr<AlgorithmParametersBase>;
+}
+
+AlgorithmParameters::AlgorithmParameters(const AlgorithmParameters &x)
+ : m_constructed(false), m_defaultThrowIfNotUsed(x.m_defaultThrowIfNotUsed)
+{
+ if (x.m_constructed)
+ {
+ x.First().MoveInto(m_first);
+ m_constructed = true;
+ }
+ else
+ new(m_first) member_ptr<AlgorithmParametersBase>(x.Next().release());
+}
+
+AlgorithmParameters::~AlgorithmParameters()
+{
+ if (m_constructed)
+ First().~AlgorithmParametersBase();
+ else
+ Next().~member_ptr<AlgorithmParametersBase>();
+}
+
bool AlgorithmParameters::GetVoidValue(const char *name, const std::type_info &valueType, void *pValue) const
{
- return m_ptr->GetVoidValue(name, valueType, pValue);
+ if (m_constructed)
+ return First().GetVoidValue(name, valueType, pValue);
+ else if (Next().get())
+ return Next()->GetVoidValue(name, valueType, pValue);
+ else
+ return false;
+}
+
+AlgorithmParametersBase & AlgorithmParameters::First()
+{
+ return *reinterpret_cast<AlgorithmParametersBase *>(m_first);
+}
+
+member_ptr<AlgorithmParametersBase> & AlgorithmParameters::Next()
+{
+ if (m_constructed)
+ return First().m_next;
+ else
+ return *reinterpret_cast<member_ptr<AlgorithmParametersBase> *>(m_first);
}
NAMESPACE_END
diff --git a/algparam.h b/algparam.h
index 36cc16f..80bbbc6 100644
--- a/algparam.h
+++ b/algparam.h
@@ -245,7 +245,7 @@ CRYPTOPP_DLL extern PAssignIntToInteger g_pAssignIntToInteger;
CRYPTOPP_DLL const std::type_info & CRYPTOPP_API IntegerTypeId();
-class CRYPTOPP_DLL AlgorithmParametersBase : public NameValuePairs
+class CRYPTOPP_DLL AlgorithmParametersBase
{
public:
class ParameterNotUsed : public Exception
@@ -254,10 +254,18 @@ public:
ParameterNotUsed(const char *name) : Exception(OTHER_ERROR, std::string("AlgorithmParametersBase: parameter \"") + name + "\" not used") {}
};
+ // this is actually a move, not a copy
+ AlgorithmParametersBase(const AlgorithmParametersBase &x)
+ : m_name(x.m_name), m_throwIfNotUsed(x.m_throwIfNotUsed), m_used(x.m_used)
+ {
+ m_next.reset(const_cast<AlgorithmParametersBase &>(x).m_next.release());
+ x.m_used = true;
+ }
+
AlgorithmParametersBase(const char *name, bool throwIfNotUsed)
: m_name(name), m_throwIfNotUsed(throwIfNotUsed), m_used(false) {}
- ~AlgorithmParametersBase()
+ virtual ~AlgorithmParametersBase()
{
#ifdef CRYPTOPP_UNCAUGHT_EXCEPTION_AVAILABLE
if (!std::uncaught_exception())
@@ -281,62 +289,91 @@ protected:
friend class AlgorithmParameters;
virtual void AssignValue(const char *name, const std::type_info &valueType, void *pValue) const =0;
+ virtual void MoveInto(void *p) const =0; // not really const
const char *m_name;
bool m_throwIfNotUsed;
mutable bool m_used;
- member_ptr<NameValuePairs> m_next;
+ member_ptr<AlgorithmParametersBase> m_next;
};
template <class T>
class AlgorithmParametersTemplate : public AlgorithmParametersBase
{
public:
- AlgorithmParametersTemplate(const char *name, const T &value, bool throwIfNotUsed) : AlgorithmParametersBase(name, throwIfNotUsed), m_value(value) {}
+ AlgorithmParametersTemplate(const char *name, const T &value, bool throwIfNotUsed)
+ : AlgorithmParametersBase(name, throwIfNotUsed), m_value(value)
+ {
+ }
void AssignValue(const char *name, const std::type_info &valueType, void *pValue) const
{
// special case for retrieving an Integer parameter when an int was passed in
if (!(g_pAssignIntToInteger != NULL && typeid(T) == typeid(int) && g_pAssignIntToInteger(valueType, pValue, &m_value)))
{
- ThrowIfTypeMismatch(name, typeid(T), valueType);
+ NameValuePairs::ThrowIfTypeMismatch(name, typeid(T), valueType);
*reinterpret_cast<T *>(pValue) = m_value;
}
}
+ void MoveInto(void *buffer) const
+ {
+ AlgorithmParametersTemplate<T>* p = new(buffer) AlgorithmParametersTemplate<T>(*this);
+ }
+
protected:
T m_value;
};
-class AlgorithmParameters : public NameValuePairs
+CRYPTOPP_DLL_TEMPLATE_CLASS AlgorithmParametersTemplate<bool>;
+CRYPTOPP_DLL_TEMPLATE_CLASS AlgorithmParametersTemplate<int>;
+CRYPTOPP_DLL_TEMPLATE_CLASS AlgorithmParametersTemplate<ConstByteArrayParameter>;
+
+class CRYPTOPP_DLL AlgorithmParameters : public NameValuePairs
{
public:
- AlgorithmParameters(AlgorithmParameters &x) : m_ptr(x.m_ptr.release()) {}
-
- AlgorithmParameters(AlgorithmParametersBase *p) : m_ptr(p) {}
-
+ AlgorithmParameters();
+
+ AlgorithmParameters(const AlgorithmParameters &x);
+
+ ~AlgorithmParameters();
+
template <class T>
AlgorithmParameters & operator()(const char *name, const T &value, bool throwIfNotUsed)
{
- member_ptr<AlgorithmParametersBase> p(new AlgorithmParametersTemplate<T>(name, value, throwIfNotUsed));
- p->m_next.reset(m_ptr.release());
- m_ptr.reset(p.release());
+ if (m_constructed || sizeof(m_first) < sizeof(AlgorithmParametersTemplate<T>))
+ {
+ member_ptr<AlgorithmParametersBase> p(new AlgorithmParametersTemplate<T>(name, value, throwIfNotUsed));
+ p->m_next.reset(Next().release());
+ Next().reset(p.release());
+ }
+ else
+ {
+ member_ptr<AlgorithmParametersBase> temp(Next().release());
+ AlgorithmParametersTemplate<T>* p = new(m_first) AlgorithmParametersTemplate<T>(name, value, throwIfNotUsed);
+ p->m_next.reset(temp.release());
+ m_constructed = true;
+ }
+ m_defaultThrowIfNotUsed = throwIfNotUsed;
return *this;
}
template <class T>
AlgorithmParameters & operator()(const char *name, const T &value)
{
- member_ptr<AlgorithmParametersBase> p(new AlgorithmParametersTemplate<T>(name, value, m_ptr->m_throwIfNotUsed));
- p->m_next.reset(m_ptr.release());
- m_ptr.reset(p.release());
- return *this;
+ return operator()(name, value, m_defaultThrowIfNotUsed);
}
bool GetVoidValue(const char *name, const std::type_info &valueType, void *pValue) const;
protected:
- member_ptr<AlgorithmParametersBase> m_ptr;
+ AlgorithmParametersBase & First();
+ member_ptr<AlgorithmParametersBase> & Next();
+ const AlgorithmParametersBase & First() const {return const_cast<AlgorithmParameters *>(this)->First();}
+ member_ptr<AlgorithmParametersBase> & Next() const {return const_cast<AlgorithmParameters *>(this)->Next();}
+
+ bool m_constructed, m_defaultThrowIfNotUsed;
+ char m_first[sizeof(AlgorithmParametersBase) + 16];
};
//! Create an object that implements NameValuePairs for passing parameters
@@ -350,7 +387,7 @@ protected:
template <class T>
AlgorithmParameters MakeParameters(const char *name, const T &value, bool throwIfNotUsed = true)
{
- return AlgorithmParameters(new AlgorithmParametersTemplate<T>(name, value, throwIfNotUsed));
+ return AlgorithmParameters()(name, value, throwIfNotUsed);
}
#define CRYPTOPP_GET_FUNCTION_ENTRY(name) (Name::name(), &ThisClass::Get##name)
diff --git a/argnames.h b/argnames.h
index 7be2d71..23add3c 100644
--- a/argnames.h
+++ b/argnames.h
@@ -13,7 +13,7 @@ CRYPTOPP_DEFINE_NAME_STRING(ValueNames) //!< string, a list of value names wit
CRYPTOPP_DEFINE_NAME_STRING(Version) //!< int
CRYPTOPP_DEFINE_NAME_STRING(Seed) //!< ConstByteArrayParameter
CRYPTOPP_DEFINE_NAME_STRING(Key) //!< ConstByteArrayParameter
-CRYPTOPP_DEFINE_NAME_STRING(IV) //!< const byte *
+CRYPTOPP_DEFINE_NAME_STRING(IV) //!< ConstByteArrayParameter, also accepts const byte * for backwards compatibility
CRYPTOPP_DEFINE_NAME_STRING(StolenIV) //!< byte *
CRYPTOPP_DEFINE_NAME_STRING(Rounds) //!< int
CRYPTOPP_DEFINE_NAME_STRING(FeedbackSize) //!< int
@@ -43,7 +43,9 @@ CRYPTOPP_DEFINE_NAME_STRING(QuadraticResidueModPrime1) //!< Integer
CRYPTOPP_DEFINE_NAME_STRING(QuadraticResidueModPrime2) //!< Integer
CRYPTOPP_DEFINE_NAME_STRING(PutMessage) //!< bool
CRYPTOPP_DEFINE_NAME_STRING(TruncatedDigestSize) //!< int
+CRYPTOPP_DEFINE_NAME_STRING(BlockPaddingScheme) //!< StreamTransformationFilter::BlockPaddingScheme
CRYPTOPP_DEFINE_NAME_STRING(HashVerificationFilterFlags) //!< word32
+CRYPTOPP_DEFINE_NAME_STRING(AuthenticatedDecryptionFilterFlags) //!< word32
CRYPTOPP_DEFINE_NAME_STRING(SignatureVerificationFilterFlags) //!< word32
CRYPTOPP_DEFINE_NAME_STRING(InputBuffer) //!< ConstByteArrayParameter
CRYPTOPP_DEFINE_NAME_STRING(OutputBuffer) //!< ByteArrayParameter
@@ -68,6 +70,7 @@ CRYPTOPP_DEFINE_NAME_STRING(InsertLineBreaks) //< bool
CRYPTOPP_DEFINE_NAME_STRING(MaxLineLength) //< int
CRYPTOPP_DEFINE_NAME_STRING(DigestSize) //!< int, in bytes
CRYPTOPP_DEFINE_NAME_STRING(L1KeyLength) //!< int, in bytes
+CRYPTOPP_DEFINE_NAME_STRING(TableSize) //!< int, in bytes
DOCUMENTED_NAMESPACE_END
diff --git a/authenc.cpp b/authenc.cpp
new file mode 100644
index 0000000..c9c22e3
--- /dev/null
+++ b/authenc.cpp
@@ -0,0 +1,179 @@
+// authenc.cpp - written and placed in the public domain by Wei Dai
+
+#include "pch.h"
+
+#ifndef CRYPTOPP_IMPORTS
+
+#include "authenc.h"
+
+NAMESPACE_BEGIN(CryptoPP)
+
+void AuthenticatedSymmetricCipherBase::AuthenticateData(const byte *input, size_t len)
+{
+ unsigned int blockSize = AuthenticationBlockSize();
+ unsigned int &num = m_bufferedDataLength;
+ byte* data = m_buffer.begin();
+
+ if (num != 0) // process left over data
+ {
+ if (num+len >= blockSize)
+ {
+ memcpy(data+num, input, blockSize-num);
+ AuthenticateBlocks(data, blockSize);
+ input += (blockSize-num);
+ len -= (blockSize-num);
+ num = 0;
+ // drop through and do the rest
+ }
+ else
+ {
+ memcpy(data+num, input, len);
+ num += (unsigned int)len;
+ return;
+ }
+ }
+
+ // now process the input data in blocks of blockSize bytes and save the leftovers to m_data
+ if (len >= blockSize)
+ {
+ size_t leftOver = AuthenticateBlocks(input, len);
+ input += (len - leftOver);
+ len = leftOver;
+ }
+
+ memcpy(data, input, len);
+ num = (unsigned int)len;
+}
+
+void AuthenticatedSymmetricCipherBase::SetKey(const byte *userKey, size_t keylength, const NameValuePairs &params)
+{
+ m_bufferedDataLength = 0;
+ m_state = State_Start;
+
+ SetKeyWithoutResync(userKey, keylength, params);
+ m_state = State_KeySet;
+
+ size_t length;
+ const byte *iv = GetIVAndThrowIfInvalid(params, length);
+ if (iv)
+ Resynchronize(iv, (int)length);
+}
+
+void AuthenticatedSymmetricCipherBase::Resynchronize(const byte *iv, int length)
+{
+ if (m_state < State_KeySet)
+ throw BadState(AlgorithmName(), "Resynchronize", "State_KeySet");
+
+ m_bufferedDataLength = 0;
+ m_totalHeaderLength = m_totalMessageLength = m_totalFooterLength = 0;
+ m_state = State_KeySet;
+
+ Resync(iv, this->ThrowIfInvalidIVLength(length));
+ m_state = State_IVSet;
+}
+
+void AuthenticatedSymmetricCipherBase::Update(const byte *input, size_t length)
+{
+ if (length == 0)
+ return;
+
+ switch (m_state)
+ {
+ case State_Start:
+ case State_KeySet:
+ throw BadState(AlgorithmName(), "Update", "State_IVSet");
+ case State_IVSet:
+ AuthenticateData(input, length);
+ m_totalHeaderLength += length;
+ break;
+ case State_AuthUntransformed:
+ case State_AuthTransformed:
+ AuthenticateLastConfidentialBlock();
+ m_bufferedDataLength = 0;
+ m_state = State_AuthFooter;
+ // fall through
+ case State_AuthFooter:
+ AuthenticateData(input, length);
+ m_totalFooterLength += length;
+ break;
+ default:
+ assert(false);
+ }
+}
+
+void AuthenticatedSymmetricCipherBase::ProcessData(byte *outString, const byte *inString, size_t length)
+{
+ m_totalMessageLength += length;
+ if (m_totalMessageLength > MaxMessageLength())
+ throw InvalidArgument(AlgorithmName() + ": message length exceeds maximum");
+
+reswitch:
+ switch (m_state)
+ {
+ case State_Start:
+ case State_KeySet:
+ case State_AuthFooter:
+ throw BadState(AlgorithmName(), "ProcessData", "State_IVSet or after State_AuthFooter");
+ case State_IVSet:
+ AuthenticateLastHeaderBlock();
+ m_bufferedDataLength = 0;
+ m_state = AuthenticationIsOnPlaintext()==IsForwardTransformation() ? State_AuthUntransformed : State_AuthTransformed;
+ goto reswitch;
+ case State_AuthUntransformed:
+ AuthenticateData(inString, length);
+ AccessSymmetricCipher().ProcessData(outString, inString, length);
+ break;
+ case State_AuthTransformed:
+ AccessSymmetricCipher().ProcessData(outString, inString, length);
+ AuthenticateData(outString, length);
+ break;
+ default:
+ assert(false);
+ }
+}
+
+void AuthenticatedSymmetricCipherBase::TruncatedFinal(byte *mac, size_t macSize)
+{
+ if (m_totalHeaderLength > MaxHeaderLength())
+ throw InvalidArgument(AlgorithmName() + ": header length of " + IntToString(m_totalHeaderLength) + " exceeds the maximum of " + IntToString(MaxHeaderLength()));
+
+ if (m_totalFooterLength > MaxFooterLength())
+ {
+ if (MaxFooterLength() == 0)
+ throw InvalidArgument(AlgorithmName() + ": unencrypted authenticated data cannot be input after encrypted data");
+ else
+ throw InvalidArgument(AlgorithmName() + ": footer length of " + IntToString(m_totalFooterLength) + " exceeds the maximum of " + IntToString(MaxFooterLength()));
+ }
+
+ switch (m_state)
+ {
+ case State_Start:
+ case State_KeySet:
+ throw BadState(AlgorithmName(), "TruncatedFinal", "State_IVSet");
+
+ case State_IVSet:
+ AuthenticateLastHeaderBlock();
+ m_bufferedDataLength = 0;
+ // fall through
+
+ case State_AuthUntransformed:
+ case State_AuthTransformed:
+ AuthenticateLastConfidentialBlock();
+ m_bufferedDataLength = 0;
+ // fall through
+
+ case State_AuthFooter:
+ AuthenticateLastFooterBlock(mac, macSize);
+ m_bufferedDataLength = 0;
+ break;
+
+ default:
+ assert(false);
+ }
+
+ m_state = State_KeySet;
+}
+
+NAMESPACE_END
+
+#endif
diff --git a/authenc.h b/authenc.h
new file mode 100644
index 0000000..afc2791
--- /dev/null
+++ b/authenc.h
@@ -0,0 +1,49 @@
+#ifndef CRYPTOPP_AUTHENC_H
+#define CRYPTOPP_AUTHENC_H
+
+#include "cryptlib.h"
+#include "secblock.h"
+
+NAMESPACE_BEGIN(CryptoPP)
+
+//! .
+class CRYPTOPP_DLL CRYPTOPP_NO_VTABLE AuthenticatedSymmetricCipherBase : public AuthenticatedSymmetricCipher
+{
+public:
+ AuthenticatedSymmetricCipherBase() : m_state(State_Start) {}
+
+ bool IsRandomAccess() const {return false;}
+ bool IsSelfInverting() const {return true;}
+ void UncheckedSetKey(const byte *,unsigned int,const CryptoPP::NameValuePairs &) {assert(false);}
+
+ void SetKey(const byte *userKey, size_t keylength, const NameValuePairs &params);
+ void Restart() {if (m_state > State_KeySet) m_state = State_KeySet;}
+ void Resynchronize(const byte *iv, int length=-1);
+ void Update(const byte *input, size_t length);
+ void ProcessData(byte *outString, const byte *inString, size_t length);
+ void TruncatedFinal(byte *mac, size_t macSize);
+
+protected:
+ void AuthenticateData(const byte *data, size_t len);
+ const SymmetricCipher & GetSymmetricCipher() const {return const_cast<AuthenticatedSymmetricCipherBase *>(this)->AccessSymmetricCipher();};
+
+ virtual SymmetricCipher & AccessSymmetricCipher() =0;
+ virtual bool AuthenticationIsOnPlaintext() const =0;
+ virtual unsigned int AuthenticationBlockSize() const =0;
+ virtual void SetKeyWithoutResync(const byte *userKey, size_t keylength, const NameValuePairs &params) =0;
+ virtual void Resync(const byte *iv, size_t len) =0;
+ virtual size_t AuthenticateBlocks(const byte *data, size_t len) =0;
+ virtual void AuthenticateLastHeaderBlock() =0;
+ virtual void AuthenticateLastConfidentialBlock() =0;
+ virtual void AuthenticateLastFooterBlock(byte *mac, size_t macSize) =0;
+
+ enum State {State_Start, State_KeySet, State_IVSet, State_AuthUntransformed, State_AuthTransformed, State_AuthFooter};
+ State m_state;
+ unsigned int m_bufferedDataLength;
+ lword m_totalHeaderLength, m_totalMessageLength, m_totalFooterLength;
+ AlignedSecByteBlock m_buffer;
+};
+
+NAMESPACE_END
+
+#endif
diff --git a/bench.cpp b/bench.cpp
index 3190087..88f1501 100644
--- a/bench.cpp
+++ b/bench.cpp
@@ -5,20 +5,8 @@
#include "bench.h"
#include "crc.h"
#include "adler32.h"
-#include "idea.h"
-#include "des.h"
-#include "rc5.h"
-#include "blowfish.h"
#include "wake.h"
-#include "cast.h"
#include "seal.h"
-#include "rc6.h"
-#include "mars.h"
-#include "twofish.h"
-#include "serpent.h"
-#include "skipjack.h"
-#include "cbcmac.h"
-#include "dmac.h"
#include "aes.h"
#include "blumshub.h"
#include "rng.h"
@@ -85,6 +73,7 @@ void OutputResultOperations(const char *name, const char *operation, bool pc, un
logcount++;
}
+/*
void BenchMark(const char *name, BlockTransformation &cipher, double timeTotal)
{
const int BUF_SIZE = RoundUpToMultipleOf(2048U, cipher.OptimalNumberOfParallelBlocks() * cipher.BlockSize());
@@ -105,6 +94,7 @@ void BenchMark(const char *name, BlockTransformation &cipher, double timeTotal)
OutputResultBytes(name, double(blocks) * BUF_SIZE, timeTaken);
}
+*/
void BenchMark(const char *name, StreamTransformation &cipher, double timeTotal)
{
@@ -192,9 +182,9 @@ template <class T>
void BenchMarkKeyed(const char *name, double timeTotal, const NameValuePairs &params = g_nullNameValuePairs, T *x=NULL)
{
T c;
- c.SetKey(key, c.DefaultKeyLength(), CombinedNameValuePairs(params, MakeParameters(Name::IV(), key, false)));
+ c.SetKey(key, c.DefaultKeyLength(), CombinedNameValuePairs(params, MakeParameters(Name::IV(), ConstByteArrayParameter(key, c.IVSize()), false)));
BenchMark(name, c, timeTotal);
- BenchMarkKeying(c, c.DefaultKeyLength(), CombinedNameValuePairs(params, MakeParameters(Name::IV(), key, false)));
+ BenchMarkKeying(c, c.DefaultKeyLength(), CombinedNameValuePairs(params, MakeParameters(Name::IV(), ConstByteArrayParameter(key, c.IVSize()), false)));
}
//VC60 workaround: compiler bug triggered without the extra dummy parameters
@@ -202,9 +192,9 @@ template <class T>
void BenchMarkKeyedVariable(const char *name, double timeTotal, unsigned int keyLength, const NameValuePairs &params = g_nullNameValuePairs, T *x=NULL)
{
T c;
- c.SetKey(key, keyLength, CombinedNameValuePairs(params, MakeParameters(Name::IV(), key, false)));
+ c.SetKey(key, keyLength, CombinedNameValuePairs(params, MakeParameters(Name::IV(), ConstByteArrayParameter(key, c.IVSize()), false)));
BenchMark(name, c, timeTotal);
- BenchMarkKeying(c, keyLength, CombinedNameValuePairs(params, MakeParameters(Name::IV(), key, false)));
+ BenchMarkKeying(c, keyLength, CombinedNameValuePairs(params, MakeParameters(Name::IV(), ConstByteArrayParameter(key, c.IVSize()), false)));
}
//VC60 workaround: compiler bug triggered without the extra dummy parameters
@@ -216,8 +206,8 @@ void BenchMarkKeyless(const char *name, double timeTotal, T *x=NULL)
}
//VC60 workaround: compiler bug triggered without the extra dummy parameters
-template <class T>
-void BenchMarkByName(const char *factoryName, size_t keyLength = 0, const char *displayName=NULL, const NameValuePairs &params = g_nullNameValuePairs, T *x=NULL)
+template <class T_FactoryOutput, class T_Interface>
+void BenchMarkByName(const char *factoryName, size_t keyLength = 0, const char *displayName=NULL, const NameValuePairs &params = g_nullNameValuePairs, T_FactoryOutput *x=NULL, T_Interface *y=NULL)
{
std::string name = factoryName;
if (displayName)
@@ -225,12 +215,19 @@ void BenchMarkByName(const char *factoryName, size_t keyLength = 0, const char *
else if (keyLength)
name += " (" + IntToString(keyLength * 8) + "-bit key)";
- std::auto_ptr<T> obj(ObjectFactoryRegistry<T>::Registry().CreateObject(factoryName));
+ std::auto_ptr<T_FactoryOutput> obj(ObjectFactoryRegistry<T_FactoryOutput>::Registry().CreateObject(factoryName));
if (!keyLength)
keyLength = obj->DefaultKeyLength();
- obj->SetKey(key, keyLength, CombinedNameValuePairs(params, MakeParameters(Name::IV(), key, false)));
- BenchMark(name.c_str(), *obj, g_allocatedTime);
- BenchMarkKeying(*obj, keyLength, CombinedNameValuePairs(params, MakeParameters(Name::IV(), key, false)));
+ obj->SetKey(key, keyLength, CombinedNameValuePairs(params, MakeParameters(Name::IV(), ConstByteArrayParameter(key, obj->IVSize()), false)));
+ BenchMark(name.c_str(), *static_cast<T_Interface *>(obj.get()), g_allocatedTime);
+ BenchMarkKeying(*obj, keyLength, CombinedNameValuePairs(params, MakeParameters(Name::IV(), ConstByteArrayParameter(key, obj->IVSize()), false)));
+}
+
+//VC60 workaround: compiler bug triggered without the extra dummy parameters
+template <class T_FactoryOutput>
+void BenchMarkByName(const char *factoryName, size_t keyLength = 0, const char *displayName=NULL, const NameValuePairs &params = g_nullNameValuePairs, T_FactoryOutput *x=NULL)
+{
+ BenchMarkByName<T_FactoryOutput, T_FactoryOutput>(factoryName, keyLength, displayName, params, x, x);
}
template <class T>
@@ -268,13 +265,20 @@ void BenchmarkAll(double t, double hertz)
cout << "<TABLE border=1><COLGROUP><COL align=left><COL align=right><COL align=right><COL align=right><COL align=right>" << endl;
cout << "<THEAD><TR><TH>Algorithm<TH>MiB/Second" << cpb << "<TH>Microseconds to<br>Setup Key and IV" << cpk << endl;
+ cout << "\n<TBODY style=\"background: yellow\">";
+ BenchMarkByName<AuthenticatedSymmetricCipher, StreamTransformation>("AES/GCM", 0, "AES/GCM (2K tables)", MakeParameters(Name::TableSize(), 2048));
+ BenchMarkByName<AuthenticatedSymmetricCipher, StreamTransformation>("AES/GCM", 0, "AES/GCM (64K tables)", MakeParameters(Name::TableSize(), 64*1024));
+ BenchMarkByName<AuthenticatedSymmetricCipher, StreamTransformation>("AES/CCM");
+
cout << "\n<TBODY style=\"background: white\">";
+ BenchMarkByName<AuthenticatedSymmetricCipher, MessageAuthenticationCode>("AES/GCM", 0, "GMAC(AES) (2K tables)", MakeParameters(Name::TableSize(), 2048));
+ BenchMarkByName<AuthenticatedSymmetricCipher, MessageAuthenticationCode>("AES/GCM", 0, "GMAC(AES) (64K tables)", MakeParameters(Name::TableSize(), 64*1024));
BenchMarkByName<MessageAuthenticationCode>("VMAC(AES)-64");
BenchMarkByName<MessageAuthenticationCode>("VMAC(AES)-128");
BenchMarkByName<MessageAuthenticationCode>("HMAC(SHA-1)");
BenchMarkByName<MessageAuthenticationCode>("Two-Track-MAC");
- BenchMarkKeyed<CBC_MAC<AES> >("CBC-MAC/AES", t);
- BenchMarkKeyed<DMAC<AES> >("DMAC/AES", t);
+ BenchMarkByName<MessageAuthenticationCode>("CMAC(AES)");
+ BenchMarkByName<MessageAuthenticationCode>("DMAC(AES)");
cout << "\n<TBODY style=\"background: yellow\">";
BenchMarkKeyless<CRC32>("CRC-32", t);
@@ -282,11 +286,9 @@ void BenchmarkAll(double t, double hertz)
BenchMarkByNameKeyLess<HashTransformation>("MD5");
BenchMarkByNameKeyLess<HashTransformation>("SHA-1");
BenchMarkByNameKeyLess<HashTransformation>("SHA-256");
-#ifdef WORD64_AVAILABLE
BenchMarkByNameKeyLess<HashTransformation>("SHA-512");
BenchMarkByNameKeyLess<HashTransformation>("Tiger");
BenchMarkByNameKeyLess<HashTransformation>("Whirlpool");
-#endif
BenchMarkByNameKeyLess<HashTransformation>("RIPEMD-160");
BenchMarkByNameKeyLess<HashTransformation>("RIPEMD-320");
BenchMarkByNameKeyLess<HashTransformation>("RIPEMD-128");
@@ -306,32 +308,35 @@ void BenchmarkAll(double t, double hertz)
BenchMarkKeyed<WAKE_OFB<LittleEndian>::Encryption>("WAKE-OFB-LE", t);
cout << "\n<TBODY style=\"background: yellow\">";
- BenchMarkByName<SymmetricCipher>("AES/ECB", 16);
- BenchMarkByName<SymmetricCipher>("AES/ECB", 24);
- BenchMarkByName<SymmetricCipher>("AES/ECB", 32);
BenchMarkByName<SymmetricCipher>("AES/CTR", 16);
+ BenchMarkByName<SymmetricCipher>("AES/CTR", 24);
+ BenchMarkByName<SymmetricCipher>("AES/CTR", 32);
+ BenchMarkByName<SymmetricCipher>("AES/CBC", 16);
+ BenchMarkByName<SymmetricCipher>("AES/CBC", 24);
+ BenchMarkByName<SymmetricCipher>("AES/CBC", 32);
BenchMarkByName<SymmetricCipher>("AES/OFB", 16);
BenchMarkByName<SymmetricCipher>("AES/CFB", 16);
- BenchMarkByName<SymmetricCipher>("AES/CBC", 16);
- BenchMarkByName<SymmetricCipher>("Camellia/ECB", 16);
- BenchMarkByName<SymmetricCipher>("Camellia/ECB", 32);
- BenchMarkKeyed<Twofish::Encryption>("Twofish", t);
- BenchMarkKeyed<Serpent::Encryption>("Serpent", t);
- BenchMarkKeyed<CAST256::Encryption>("CAST-256", t);
- BenchMarkKeyed<RC6::Encryption>("RC6", t);
- BenchMarkKeyed<MARS::Encryption>("MARS", t);
- BenchMarkByName<SymmetricCipher>("SHACAL-2/ECB", 16);
- BenchMarkByName<SymmetricCipher>("SHACAL-2/ECB", 64);
- BenchMarkKeyed<DES::Encryption>("DES", t);
- BenchMarkKeyed<DES_XEX3::Encryption>("DES-XEX3", t);
- BenchMarkKeyed<DES_EDE3::Encryption>("DES-EDE3", t);
- BenchMarkKeyed<IDEA::Encryption>("IDEA", t);
- BenchMarkKeyed<RC5::Encryption>("RC5 (r=16)", t);
- BenchMarkKeyed<Blowfish::Encryption>("Blowfish", t);
- BenchMarkByName<SymmetricCipher>("TEA/ECB");
- BenchMarkByName<SymmetricCipher>("XTEA/ECB");
- BenchMarkKeyed<CAST128::Encryption>("CAST-128", t);
- BenchMarkKeyed<SKIPJACK::Encryption>("SKIPJACK", t);
+ BenchMarkByName<SymmetricCipher>("AES/ECB", 16);
+ BenchMarkByName<SymmetricCipher>("Camellia/CTR", 16);
+ BenchMarkByName<SymmetricCipher>("Camellia/CTR", 32);
+ BenchMarkByName<SymmetricCipher>("Twofish/CTR");
+ BenchMarkByName<SymmetricCipher>("Serpent/CTR");
+ BenchMarkByName<SymmetricCipher>("CAST-256/CTR");
+ BenchMarkByName<SymmetricCipher>("RC6/CTR");
+ BenchMarkByName<SymmetricCipher>("MARS/CTR");
+ BenchMarkByName<SymmetricCipher>("SHACAL-2/CTR", 16);
+ BenchMarkByName<SymmetricCipher>("SHACAL-2/CTR", 64);
+ BenchMarkByName<SymmetricCipher>("DES/CTR");
+ BenchMarkByName<SymmetricCipher>("DES-XEX3/CTR");
+ BenchMarkByName<SymmetricCipher>("DES-EDE3/CTR");
+ BenchMarkByName<SymmetricCipher>("IDEA/CTR");
+ BenchMarkByName<SymmetricCipher>("RC5/CTR", 0, "RC5 (r=16)");
+ BenchMarkByName<SymmetricCipher>("Blowfish/CTR");
+ BenchMarkByName<SymmetricCipher>("TEA/CTR");
+ BenchMarkByName<SymmetricCipher>("XTEA/CTR");
+ BenchMarkByName<SymmetricCipher>("CAST-128/CTR");
+ BenchMarkByName<SymmetricCipher>("SKIPJACK/CTR");
+ BenchMarkByName<SymmetricCipher>("SEED/CTR", 0, "SEED/CTR (1/2 K table)");
cout << "</TABLE>" << endl;
BenchmarkAll2(t, hertz);
diff --git a/camellia.cpp b/camellia.cpp
index cdd7906..80b3e28 100644
--- a/camellia.cpp
+++ b/camellia.cpp
@@ -69,27 +69,14 @@ void Camellia::Base::UncheckedSetKey(const byte *key, unsigned int keylen, const
m = -1, a = kslen-1;
word32 kl0, kl1, kl2, kl3;
- GetBlock<word32, BigEndian, false> getBlock(key);
+ GetBlock<word32, BigEndian> getBlock(key);
getBlock(kl0)(kl1)(kl2)(kl3);
word32 k0=kl0, k1=kl1, k2=kl2, k3=kl3;
#define CALC_ADDR2(base, i, j) ((byte *)(base)+8*(i)+4*(j)+((-16*(i))&m))
#define CALC_ADDR(base, i) CALC_ADDR2(base, i, 0)
-#if !defined(WORD64_AVAILABLE)
- ks32 += 2*a;
-#define PREPARE_KS_ROUNDS
-#define KS_ROUND_0(i) \
- *(word32*)CALC_ADDR2(ks32, i+EFI(0), EFI(0)) = k0; \
- *(word32*)CALC_ADDR2(ks32, i+EFI(0), EFI(1)) = k1; \
- *(word32*)CALC_ADDR2(ks32, i+EFI(1), EFI(0)) = k2; \
- *(word32*)CALC_ADDR2(ks32, i+EFI(1), EFI(1)) = k3
-#define KS_ROUND(i, r, which) \
- if (which & (1<<((7-r/32)%4/2))) *(word32*)CALC_ADDR2(ks32, i+EFI((7-r/32)%4/2), EFI((7-r/32)%2)) = (k3 << (r%32)) | (k0 >> (32-r%32)); \
- if (which & (1<<((6-r/32)%4/2))) *(word32*)CALC_ADDR2(ks32, i+EFI((6-r/32)%4/2), EFI((6-r/32)%2)) = (k2 << (r%32)) | (k3 >> (32-r%32)); \
- if (which & (1<<((5-r/32)%4/2))) *(word32*)CALC_ADDR2(ks32, i+EFI((5-r/32)%4/2), EFI((5-r/32)%2)) = (k1 << (r%32)) | (k2 >> (32-r%32)); \
- if (which & (1<<((4-r/32)%4/2))) *(word32*)CALC_ADDR2(ks32, i+EFI((4-r/32)%4/2), EFI((4-r/32)%2)) = (k0 << (r%32)) | (k1 >> (32-r%32))
-#elif 1
+#if 1
word64 kwl, kwr;
ks32 += 2*a;
#define PREPARE_KS_ROUNDS \
@@ -161,11 +148,11 @@ void Camellia::Base::UncheckedSetKey(const byte *key, unsigned int keylen, const
// KR
word32 kr0, kr1, kr2, kr3;
- GetBlock<word32, BigEndian, false>(key+16)(kr0)(kr1);
+ GetBlock<word32, BigEndian>(key+16)(kr0)(kr1);
if (keylen == 24)
kr2 = ~kr0, kr3 = ~kr1;
else
- GetBlock<word32, BigEndian, false>(key+24)(kr2)(kr3);
+ GetBlock<word32, BigEndian>(key+24)(kr2)(kr3);
k0=kr0, k1=kr1, k2=kr2, k3=kr3;
PREPARE_KS_ROUNDS;
diff --git a/camellia.h b/camellia.h
index 599824d..d8700cb 100644
--- a/camellia.h
+++ b/camellia.h
@@ -25,7 +25,6 @@ class Camellia : public Camellia_Info, public BlockCipherDocumentation
public:
void UncheckedSetKey(const byte *key, unsigned int keylen, const NameValuePairs &params);
void ProcessAndXorBlock(const byte *inBlock, const byte *xorBlock, byte *outBlock) const;
- unsigned int BlockAlignment() const {return 8;}
protected:
static const byte s1[256];
diff --git a/cbcmac.cpp b/cbcmac.cpp
index dfac071..6b0e885 100644
--- a/cbcmac.cpp
+++ b/cbcmac.cpp
@@ -25,12 +25,11 @@ void CBC_MAC_Base::Update(const byte *input, size_t length)
length--;
}
- while (length >= blockSize)
+ if (length >= blockSize)
{
- xorbuf(m_reg, input, blockSize);
- ProcessBuf();
- input += blockSize;
- length -= blockSize;
+ size_t leftOver = AccessCipher().AdvancedProcessBlocks(m_reg, input, m_reg, length, BlockTransformation::BT_DontIncrementInOutPointers|BlockTransformation::BT_XorInput);
+ input += (length - leftOver);
+ length = leftOver;
}
while (length--)
diff --git a/cbcmac.h b/cbcmac.h
index a8c88d3..4675dcb 100644
--- a/cbcmac.h
+++ b/cbcmac.h
@@ -28,8 +28,7 @@ private:
//! <a href="http://www.weidai.com/scan-mirror/mac.html#CBC-MAC">CBC-MAC</a>
/*! Compatible with FIPS 113. T should be a class derived from BlockCipherDocumentation.
- Secure only for fixed length messages. For variable length
- messages use DMAC.
+ Secure only for fixed length messages. For variable length messages use CMAC or DMAC.
*/
template <class T>
class CBC_MAC : public MessageAuthenticationCodeImpl<CBC_MAC_Base, CBC_MAC<T> >, public SameKeyLengthAs<T>
diff --git a/ccm.cpp b/ccm.cpp
new file mode 100644
index 0000000..0368787
--- /dev/null
+++ b/ccm.cpp
@@ -0,0 +1,140 @@
+// ccm.cpp - written and placed in the public domain by Wei Dai
+
+#include "pch.h"
+
+#ifndef CRYPTOPP_IMPORTS
+
+#include "ccm.h"
+
+NAMESPACE_BEGIN(CryptoPP)
+
+void CCM_Base::SetKeyWithoutResync(const byte *userKey, size_t keylength, const NameValuePairs &params)
+{
+ BlockCipher &blockCipher = AccessBlockCipher();
+
+ blockCipher.SetKey(userKey, keylength, params);
+
+ if (blockCipher.BlockSize() != REQUIRED_BLOCKSIZE)
+ throw InvalidArgument(AlgorithmName() + ": block size of underlying block cipher is not 16");
+
+ m_digestSize = params.GetIntValueWithDefault(Name::DigestSize(), DefaultDigestSize());
+ if (m_digestSize % 2 > 0 || m_digestSize < 4 || m_digestSize > 16)
+ throw InvalidArgument(AlgorithmName() + ": DigestSize must be 4, 6, 8, 10, 12, 14, or 16");
+
+ m_buffer.Grow(2*REQUIRED_BLOCKSIZE);
+ m_L = 8;
+}
+
+void CCM_Base::Resync(const byte *iv, size_t len)
+{
+ BlockCipher &cipher = AccessBlockCipher();
+
+ m_L = REQUIRED_BLOCKSIZE-1-(int)len;
+ assert(m_L >= 2);
+ if (m_L > 8)
+ m_L = 8;
+
+ m_buffer[0] = byte(m_L-1); // flag
+ memcpy(m_buffer+1, iv, len);
+ memset(m_buffer+1+len, 0, REQUIRED_BLOCKSIZE-1-len);
+
+ if (m_state >= State_IVSet)
+ m_ctr.Resynchronize(m_buffer, REQUIRED_BLOCKSIZE);
+ else
+ m_ctr.SetCipherWithIV(cipher, m_buffer);
+
+ m_ctr.Seek(REQUIRED_BLOCKSIZE);
+ m_aadLength = 0;
+ m_messageLength = 0;
+}
+
+void CCM_Base::UncheckedSpecifyDataLengths(lword headerLength, lword messageLength, lword footerLength)
+{
+ if (m_state != State_IVSet)
+ throw BadState(AlgorithmName(), "SpecifyDataLengths", "or after State_IVSet");
+
+ m_aadLength = headerLength;
+ m_messageLength = messageLength;
+
+ byte *cbcBuffer = CBC_Buffer();
+ const BlockCipher &cipher = GetBlockCipher();
+
+ cbcBuffer[0] = byte(64*(headerLength>0) + 8*((m_digestSize-2)/2) + (m_L-1)); // flag
+ PutWord<word64>(true, BIG_ENDIAN_ORDER, cbcBuffer+REQUIRED_BLOCKSIZE-8, m_messageLength);
+ memcpy(cbcBuffer+1, m_buffer+1, REQUIRED_BLOCKSIZE-1-m_L);
+ cipher.ProcessBlock(cbcBuffer);
+
+ if (headerLength>0)
+ {
+ assert(m_bufferedDataLength == 0);
+
+ if (headerLength < ((1<<16) - (1<<8)))
+ {
+ PutWord<word16>(true, BIG_ENDIAN_ORDER, m_buffer, (word16)headerLength);
+ m_bufferedDataLength = 2;
+ }
+ else if (headerLength < (W64LIT(1)<<32))
+ {
+ m_buffer[0] = 0xff;
+ m_buffer[1] = 0xfe;
+ PutWord<word32>(false, BIG_ENDIAN_ORDER, m_buffer+2, (word32)headerLength);
+ m_bufferedDataLength = 6;
+ }
+ else
+ {
+ m_buffer[0] = 0xff;
+ m_buffer[1] = 0xff;
+ PutWord<word64>(false, BIG_ENDIAN_ORDER, m_buffer+2, headerLength);
+ m_bufferedDataLength = 10;
+ }
+ }
+}
+
+size_t CCM_Base::AuthenticateBlocks(const byte *data, size_t len)
+{
+ byte *cbcBuffer = CBC_Buffer();
+ const BlockCipher &cipher = GetBlockCipher();
+ return cipher.AdvancedProcessBlocks(cbcBuffer, data, cbcBuffer, len, BlockTransformation::BT_DontIncrementInOutPointers|BlockTransformation::BT_XorInput);
+}
+
+void CCM_Base::AuthenticateLastHeaderBlock()
+{
+ byte *cbcBuffer = CBC_Buffer();
+ const BlockCipher &cipher = GetBlockCipher();
+
+ if (m_aadLength != m_totalHeaderLength)
+ throw InvalidArgument(AlgorithmName() + ": header length doesn't match that given in SpecifyDataLengths");
+
+ if (m_bufferedDataLength > 0)
+ {
+ xorbuf(cbcBuffer, m_buffer, m_bufferedDataLength);
+ cipher.ProcessBlock(cbcBuffer);
+ m_bufferedDataLength = 0;
+ }
+}
+
+void CCM_Base::AuthenticateLastConfidentialBlock()
+{
+ byte *cbcBuffer = CBC_Buffer();
+ const BlockCipher &cipher = GetBlockCipher();
+
+ if (m_messageLength != m_totalMessageLength)
+ throw InvalidArgument(AlgorithmName() + ": message length doesn't match that given in SpecifyDataLengths");
+
+ if (m_bufferedDataLength > 0)
+ {
+ xorbuf(cbcBuffer, m_buffer, m_bufferedDataLength);
+ cipher.ProcessBlock(cbcBuffer);
+ m_bufferedDataLength = 0;
+ }
+}
+
+void CCM_Base::AuthenticateLastFooterBlock(byte *mac, size_t macSize)
+{
+ m_ctr.Seek(0);
+ m_ctr.ProcessData(mac, CBC_Buffer(), macSize);
+}
+
+NAMESPACE_END
+
+#endif
diff --git a/ccm.h b/ccm.h
new file mode 100644
index 0000000..aa39dc0
--- /dev/null
+++ b/ccm.h
@@ -0,0 +1,101 @@
+#ifndef CRYPTOPP_CCM_H
+#define CRYPTOPP_CCM_H
+
+#include "authenc.h"
+#include "modes.h"
+
+NAMESPACE_BEGIN(CryptoPP)
+
+//! .
+class CRYPTOPP_DLL CRYPTOPP_NO_VTABLE CCM_Base : public AuthenticatedSymmetricCipherBase
+{
+public:
+ CCM_Base()
+ : m_digestSize(0), m_L(0) {}
+
+ // AuthenticatedSymmetricCipher
+ std::string AlgorithmName() const
+ {return GetBlockCipher().AlgorithmName() + std::string("/CCM");}
+ size_t MinKeyLength() const
+ {return GetBlockCipher().MinKeyLength();}
+ size_t MaxKeyLength() const
+ {return GetBlockCipher().MaxKeyLength();}
+ size_t DefaultKeyLength() const
+ {return GetBlockCipher().DefaultKeyLength();}
+ size_t GetValidKeyLength(size_t n) const
+ {return GetBlockCipher().GetValidKeyLength(n);}
+ bool IsValidKeyLength(size_t n) const
+ {return GetBlockCipher().IsValidKeyLength(n);}
+ unsigned int OptimalDataAlignment() const
+ {return GetBlockCipher().OptimalDataAlignment();}
+ IV_Requirement IVRequirement() const
+ {return UNIQUE_IV;}
+ unsigned int IVSize() const
+ {return 8;}
+ unsigned int MinIVLength() const
+ {return 7;}
+ unsigned int MaxIVLength() const
+ {return 13;}
+ unsigned int DigestSize(void) const
+ {return m_digestSize;}
+ lword MaxHeaderLength() const
+ {return W64LIT(0)-1;}
+ lword MaxMessageLength() const
+ {return m_L<8 ? (W64LIT(1)<<(8*m_L))-1 : W64LIT(0)-1;}
+ bool NeedsPrespecifiedDataLengths() const
+ {return true;}
+ void UncheckedSpecifyDataLengths(lword headerLength, lword messageLength, lword footerLength);
+
+protected:
+ // AuthenticatedSymmetricCipherBase
+ bool AuthenticationIsOnPlaintext() const
+ {return true;}
+ unsigned int AuthenticationBlockSize() const
+ {return GetBlockCipher().BlockSize();}
+ void SetKeyWithoutResync(const byte *userKey, size_t keylength, const NameValuePairs &params);
+ void Resync(const byte *iv, size_t len);
+ size_t AuthenticateBlocks(const byte *data, size_t len);
+ void AuthenticateLastHeaderBlock();
+ void AuthenticateLastConfidentialBlock();
+ void AuthenticateLastFooterBlock(byte *mac, size_t macSize);
+ SymmetricCipher & AccessSymmetricCipher() {return m_ctr;}
+
+ virtual BlockCipher & AccessBlockCipher() =0;
+ virtual int DefaultDigestSize() const =0;
+
+ const BlockCipher & GetBlockCipher() const {return const_cast<CCM_Base *>(this)->AccessBlockCipher();};
+ byte *CBC_Buffer() {return m_buffer+REQUIRED_BLOCKSIZE;}
+
+ enum {REQUIRED_BLOCKSIZE = 16};
+ int m_digestSize, m_L;
+ word64 m_messageLength, m_aadLength;
+ CTR_Mode_ExternalCipher::Encryption m_ctr;
+};
+
+//! .
+template <class T_BlockCipher, int T_DefaultDigestBitSize, bool T_IsEncryption>
+class CCM_Final : public CCM_Base
+{
+public:
+ static std::string StaticAlgorithmName()
+ {return T_BlockCipher::StaticAlgorithmName() + std::string("/CCM");}
+ bool IsForwardTransformation() const
+ {return T_IsEncryption;}
+
+private:
+ BlockCipher & AccessBlockCipher() {return m_cipher;}
+ int DefaultDigestSize() const {return T_DefaultDigestBitSize/8;}
+ typename T_BlockCipher::Encryption m_cipher;
+};
+
+/// <a href="http://www.cryptolounge.org/wiki/CCM">CCM</a>
+template <class T_BlockCipher, int T_DefaultDigestBitSize = 128>
+struct CCM : public AuthenticatedSymmetricCipherDocumentation
+{
+ typedef CCM_Final<T_BlockCipher, T_DefaultDigestBitSize, true> Encryption;
+ typedef CCM_Final<T_BlockCipher, T_DefaultDigestBitSize, false> Decryption;
+};
+
+NAMESPACE_END
+
+#endif
diff --git a/cmac.cpp b/cmac.cpp
new file mode 100644
index 0000000..e8fa6fe
--- /dev/null
+++ b/cmac.cpp
@@ -0,0 +1,122 @@
+// cmac.cpp - written and placed in the public domain by Wei Dai
+
+#include "pch.h"
+
+#ifndef CRYPTOPP_IMPORTS
+
+#include "cmac.h"
+
+NAMESPACE_BEGIN(CryptoPP)
+
+static void MulU(byte *k, unsigned int length)
+{
+ byte carry = 0;
+
+ for (int i=length-1; i>=1; i-=2)
+ {
+ byte carry2 = k[i] >> 7;
+ k[i] += k[i] + carry;
+ carry = k[i-1] >> 7;
+ k[i-1] += k[i-1] + carry2;
+ }
+
+ if (carry)
+ {
+ switch (length)
+ {
+ case 8:
+ k[7] ^= 0x1b;
+ break;
+ case 16:
+ k[15] ^= 0x87;
+ break;
+ case 32:
+ k[30] ^= 4;
+ k[31] ^= 0x23;
+ break;
+ default:
+ throw InvalidArgument("CMAC: " + IntToString(length) + " is not a supported cipher block size");
+ }
+ }
+}
+
+void CMAC_Base::UncheckedSetKey(const byte *key, unsigned int length, const NameValuePairs &params)
+{
+ BlockCipher &cipher = AccessCipher();
+ unsigned int blockSize = cipher.BlockSize();
+
+ cipher.SetKey(key, length, params);
+ m_reg.CleanNew(3*blockSize);
+ m_counter = 0;
+
+ cipher.ProcessBlock(m_reg, m_reg+blockSize);
+ MulU(m_reg+blockSize, blockSize);
+ memcpy(m_reg+2*blockSize, m_reg+blockSize, blockSize);
+ MulU(m_reg+2*blockSize, blockSize);
+}
+
+void CMAC_Base::Update(const byte *input, size_t length)
+{
+ if (!length)
+ return;
+
+ BlockCipher &cipher = AccessCipher();
+ unsigned int blockSize = cipher.BlockSize();
+
+ if (m_counter > 0)
+ {
+ unsigned int len = UnsignedMin(blockSize - m_counter, length);
+ xorbuf(m_reg+m_counter, input, len);
+ length -= len;
+ input += len;
+ m_counter += len;
+
+ if (m_counter == blockSize && length > 0)
+ {
+ cipher.ProcessBlock(m_reg);
+ m_counter = 0;
+ }
+ }
+
+ if (length > blockSize)
+ {
+ assert(m_counter == 0);
+ size_t leftOver = 1 + cipher.AdvancedProcessBlocks(m_reg, input, m_reg, length-1, BlockTransformation::BT_DontIncrementInOutPointers|BlockTransformation::BT_XorInput);
+ input += (length - leftOver);
+ length = leftOver;
+ }
+
+ if (length > 0)
+ {
+ assert(m_counter + length <= blockSize);
+ xorbuf(m_reg+m_counter, input, length);
+ m_counter += (unsigned int)length;
+ }
+
+ assert(m_counter > 0);
+}
+
+void CMAC_Base::TruncatedFinal(byte *mac, size_t size)
+{
+ ThrowIfInvalidTruncatedSize(size);
+
+ BlockCipher &cipher = AccessCipher();
+ unsigned int blockSize = cipher.BlockSize();
+
+ if (m_counter < blockSize)
+ {
+ m_reg[m_counter] ^= 0x80;
+ cipher.AdvancedProcessBlocks(m_reg, m_reg+2*blockSize, m_reg, blockSize, BlockTransformation::BT_DontIncrementInOutPointers|BlockTransformation::BT_XorInput);
+ }
+ else
+ cipher.AdvancedProcessBlocks(m_reg, m_reg+blockSize, m_reg, blockSize, BlockTransformation::BT_DontIncrementInOutPointers|BlockTransformation::BT_XorInput);
+
+ memcpy(mac, m_reg, size);
+
+ m_counter = 0;
+ memset(m_reg, 0, blockSize);
+}
+
+NAMESPACE_END
+
+#endif
diff --git a/cmac.h b/cmac.h
new file mode 100644
index 0000000..176a8b7
--- /dev/null
+++ b/cmac.h
@@ -0,0 +1,48 @@
+#ifndef CRYPTOPP_CMAC_H
+#define CRYPTOPP_CMAC_H
+
+#include "seckey.h"
+#include "secblock.h"
+
+NAMESPACE_BEGIN(CryptoPP)
+
+//! _
+class CRYPTOPP_DLL CRYPTOPP_NO_VTABLE CMAC_Base : public MessageAuthenticationCode
+{
+public:
+ CMAC_Base() {}
+
+ void UncheckedSetKey(const byte *key, unsigned int length, const NameValuePairs &params);
+ void Update(const byte *input, size_t length);
+ void TruncatedFinal(byte *mac, size_t size);
+ unsigned int DigestSize() const {return const_cast<CMAC_Base*>(this)->AccessCipher().BlockSize();}
+
+protected:
+ virtual BlockCipher & AccessCipher() =0;
+
+private:
+ void ProcessBuf();
+ SecByteBlock m_reg;
+ unsigned int m_counter;
+};
+
+/// <a href="http://www.cryptolounge.org/wiki/CMAC">CMAC</a>
+/*! Template parameter T should be a class derived from BlockCipherDocumentation, for example AES, with a block size of 8, 16, or 32 */
+template <class T>
+class CMAC : public MessageAuthenticationCodeImpl<CMAC_Base, CMAC<T> >, public SameKeyLengthAs<T>
+{
+public:
+ CMAC() {}
+ CMAC(const byte *key, size_t length=SameKeyLengthAs<T>::DEFAULT_KEYLENGTH)
+ {this->SetKey(key, length);}
+
+ static std::string StaticAlgorithmName() {return std::string("CMAC(") + T::StaticAlgorithmName() + ")";}
+
+private:
+ BlockCipher & AccessCipher() {return m_cipher;}
+ typename T::Encryption m_cipher;
+};
+
+NAMESPACE_END
+
+#endif
diff --git a/config.h b/config.h
index c6ee26c..2805953 100644
--- a/config.h
+++ b/config.h
@@ -104,7 +104,6 @@ NAMESPACE_BEGIN(CryptoPP)
typedef unsigned short word16;
typedef unsigned int word32;
-#define WORD64_AVAILABLE
#if defined(_MSC_VER) || defined(__BORLANDC__)
typedef unsigned __int64 word64;
#define W64LIT(x) x##ui64
@@ -114,13 +113,8 @@ typedef unsigned int word32;
#endif
// define large word type, used for file offsets and such
-#ifdef WORD64_AVAILABLE
- typedef word64 lword;
- const lword LWORD_MAX = W64LIT(0xffffffffffffffff);
-#else
- typedef word32 lword;
- const lword LWORD_MAX = 0xffffffffUL;
-#endif
+typedef word64 lword;
+const lword LWORD_MAX = W64LIT(0xffffffffffffffff);
#ifdef __GNUC__
#define CRYPTOPP_GCC_VERSION (__GNUC__ * 10000 + __GNUC_MINOR__ * 100 + __GNUC_PATCHLEVEL__)
@@ -147,17 +141,17 @@ typedef unsigned int word32;
typedef word32 word;
typedef word64 dword;
#endif
- #elif defined(WORD64_AVAILABLE)
- #define CRYPTOPP_SLOW_WORD64 // use alternative code that avoids word64
+ #else
+ // being here means the native register size is probably 32 bits or less
+ #define CRYPTOPP_BOOL_SLOW_WORD64 1
typedef word16 hword;
typedef word32 word;
typedef word64 dword;
- #else
- typedef byte hword;
- typedef word16 word;
- typedef word32 dword;
#endif
#endif
+#ifndef CRYPTOPP_BOOL_SLOW_WORD64
+ #define CRYPTOPP_BOOL_SLOW_WORD64 0
+#endif
const unsigned int WORD_SIZE = sizeof(word);
const unsigned int WORD_BITS = WORD_SIZE * 8;
@@ -336,11 +330,11 @@ NAMESPACE_END
#define CRYPTOPP_BOOL_X86 0
#endif
-#if CRYPTOPP_BOOL_X64 || CRYPTOPP_BOOL_X86
+#if CRYPTOPP_BOOL_X64 || CRYPTOPP_BOOL_X86 || defined(__powerpc__)
#define CRYPTOPP_ALLOW_UNALIGNED_DATA_ACCESS
#endif
-#define CRYPTOPP_VERSION 553
+#define CRYPTOPP_VERSION 560
// ***************** determine availability of OS features ********************
@@ -354,7 +348,7 @@ NAMESPACE_END
#define CRYPTOPP_UNIX_AVAILABLE
#endif
-#if defined(WORD64_AVAILABLE) && (defined(CRYPTOPP_WIN32_AVAILABLE) || defined(CRYPTOPP_UNIX_AVAILABLE))
+#if defined(CRYPTOPP_WIN32_AVAILABLE) || defined(CRYPTOPP_UNIX_AVAILABLE)
# define HIGHRES_TIMER_AVAILABLE
#endif
diff --git a/cpu.h b/cpu.h
index ab545d2..7f01dad 100755
--- a/cpu.h
+++ b/cpu.h
@@ -117,7 +117,7 @@ inline bool HasMMX() {return false;}
#define ASL(x) label##x:*newline*
#define ASJ(x, y, z) x label##y*newline*
#define ASC(x, y) x label##y*newline*
- #define AS_HEX(y) y##h
+ #define AS_HEX(y) 0##y##h
#elif defined(__GNUC__)
// define these in two steps to allow arguments to be expanded
#define GNU_AS1(x) #x ";"
@@ -146,6 +146,9 @@ inline bool HasMMX() {return false;}
#define AS_HEX(y) 0x##y
#endif
+#define IF0(y)
+#define IF1(y) y
+
#ifdef CRYPTOPP_GENERATE_X64_MASM
#define ASM_MOD(x, y) ((x) MOD (y))
#define XMMWORD_PTR XMMWORD PTR
diff --git a/cryptdll.vcproj b/cryptdll.vcproj
index 24daad4..f0d2b28 100755
--- a/cryptdll.vcproj
+++ b/cryptdll.vcproj
@@ -543,6 +543,10 @@
</FileConfiguration>
</File>
<File
+ RelativePath=".\authenc.cpp"
+ >
+ </File>
+ <File
RelativePath="basecode.cpp"
>
<FileConfiguration
@@ -627,6 +631,10 @@
</FileConfiguration>
</File>
<File
+ RelativePath=".\ccm.cpp"
+ >
+ </File>
+ <File
RelativePath="channels.cpp"
>
<FileConfiguration
@@ -669,6 +677,10 @@
</FileConfiguration>
</File>
<File
+ RelativePath=".\cmac.cpp"
+ >
+ </File>
+ <File
RelativePath=".\cpu.cpp"
>
</File>
@@ -1269,6 +1281,10 @@
</FileConfiguration>
</File>
<File
+ RelativePath=".\gcm.cpp"
+ >
+ </File>
+ <File
RelativePath="gf2n.cpp"
>
<FileConfiguration
@@ -2381,15 +2397,15 @@
</FileConfiguration>
</File>
<File
- RelativePath=".\x64masm.asm"
+ RelativePath=".\x64dll.asm"
>
<FileConfiguration
Name="Release|x64"
>
<Tool
Name="VCCustomBuildTool"
- CommandLine="ml64.exe /c /nologo /Fo&quot;$(IntDir)\x64masm.obj&quot; /Zi &quot;$(InputPath)&quot;"
- Outputs="$(IntDir)\x64masm.obj"
+ CommandLine="ml64.exe /c /nologo /Fo&quot;$(IntDir)\x64dll.obj&quot; /Zi &quot;$(InputPath)&quot;&#x0D;&#x0A;"
+ Outputs="$(IntDir)\x64dll.obj"
/>
</FileConfiguration>
<FileConfiguration
@@ -2397,8 +2413,8 @@
>
<Tool
Name="VCCustomBuildTool"
- CommandLine="ml64.exe /c /nologo /Fo&quot;$(IntDir)\x64masm.obj&quot; /Zi &quot;$(InputPath)&quot;"
- Outputs="$(IntDir)\x64masm.obj"
+ CommandLine="ml64.exe /c /nologo /Fo&quot;$(IntDir)\x64dll.obj&quot; /Zi &quot;$(InputPath)&quot;&#x0D;&#x0A;"
+ Outputs="$(IntDir)\x64dll.obj"
/>
</FileConfiguration>
</File>
@@ -2428,6 +2444,10 @@
>
</File>
<File
+ RelativePath=".\authenc.h"
+ >
+ </File>
+ <File
RelativePath="basecode.h"
>
</File>
@@ -2436,10 +2456,18 @@
>
</File>
<File
+ RelativePath=".\ccm.h"
+ >
+ </File>
+ <File
RelativePath="channels.h"
>
</File>
<File
+ RelativePath=".\cmac.h"
+ >
+ </File>
+ <File
RelativePath="config.h"
>
</File>
@@ -2504,6 +2532,10 @@
>
</File>
<File
+ RelativePath=".\gcm.h"
+ >
+ </File>
+ <File
RelativePath="gf2n.h"
>
</File>
diff --git a/cryptest.vcproj b/cryptest.vcproj
index b93f394..f31c8f6 100755
--- a/cryptest.vcproj
+++ b/cryptest.vcproj
@@ -745,10 +745,22 @@
>
</File>
<File
+ RelativePath=".\TestVectors\aes.txt"
+ >
+ </File>
+ <File
+ RelativePath=".\TestVectors\all.txt"
+ >
+ </File>
+ <File
RelativePath="camellia.dat"
>
</File>
<File
+ RelativePath=".\TestVectors\camellia.txt"
+ >
+ </File>
+ <File
RelativePath="cast128v.dat"
>
</File>
@@ -757,6 +769,14 @@
>
</File>
<File
+ RelativePath=".\TestVectors\ccm.txt"
+ >
+ </File>
+ <File
+ RelativePath=".\TestVectors\cmac.txt"
+ >
+ </File>
+ <File
RelativePath="descert.dat"
>
</File>
@@ -769,7 +789,11 @@
>
</File>
<File
- RelativePath="diamond.dat"
+ RelativePath=".\TestVectors\dlies.txt"
+ >
+ </File>
+ <File
+ RelativePath=".\TestVectors\dsa.txt"
>
</File>
<File
@@ -785,6 +809,10 @@
>
</File>
<File
+ RelativePath=".\TestVectors\dsa_1363.txt"
+ >
+ </File>
+ <File
RelativePath="elgc1024.dat"
>
</File>
@@ -801,11 +829,19 @@
>
</File>
<File
+ RelativePath=".\TestVectors\esign.txt"
+ >
+ </File>
+ <File
+ RelativePath=".\TestVectors\gcm.txt"
+ >
+ </File>
+ <File
RelativePath="gostval.dat"
>
</File>
<File
- RelativePath="havalcer.dat"
+ RelativePath=".\TestVectors\hmac.txt"
>
</File>
<File
@@ -857,6 +893,10 @@
>
</File>
<File
+ RelativePath=".\TestVectors\nr.txt"
+ >
+ </File>
+ <File
RelativePath="nr1024.dat"
>
</File>
@@ -865,6 +905,10 @@
>
</File>
<File
+ RelativePath=".\TestVectors\panama.txt"
+ >
+ </File>
+ <File
RelativePath="rabi1024.dat"
>
</File>
@@ -885,6 +929,10 @@
>
</File>
<File
+ RelativePath=".\TestVectors\Readme.txt"
+ >
+ </File>
+ <File
RelativePath="rijndael.dat"
>
</File>
@@ -909,6 +957,22 @@
>
</File>
<File
+ RelativePath=".\TestVectors\rsa_oaep.txt"
+ >
+ </File>
+ <File
+ RelativePath=".\TestVectors\rsa_pkcs1_1_5.txt"
+ >
+ </File>
+ <File
+ RelativePath=".\TestVectors\rsa_pss.txt"
+ >
+ </File>
+ <File
+ RelativePath=".\TestVectors\rw.txt"
+ >
+ </File>
+ <File
RelativePath="rw1024.dat"
>
</File>
@@ -921,10 +985,30 @@
>
</File>
<File
+ RelativePath=".\TestVectors\salsa.txt"
+ >
+ </File>
+ <File
+ RelativePath=".\TestVectors\seal.txt"
+ >
+ </File>
+ <File
+ RelativePath=".\TestVectors\seed.txt"
+ >
+ </File>
+ <File
RelativePath="serpentv.dat"
>
</File>
<File
+ RelativePath=".\TestVectors\sha.txt"
+ >
+ </File>
+ <File
+ RelativePath=".\TestVectors\shacal2.txt"
+ >
+ </File>
+ <File
RelativePath="shacal2v.dat"
>
</File>
@@ -937,10 +1021,22 @@
>
</File>
<File
+ RelativePath=".\TestVectors\sosemanuk.txt"
+ >
+ </File>
+ <File
RelativePath="squareva.dat"
>
</File>
<File
+ RelativePath=".\TestVectors\tea.txt"
+ >
+ </File>
+ <File
+ RelativePath=".\TestVectors\ttmac.txt"
+ >
+ </File>
+ <File
RelativePath="twofishv.dat"
>
</File>
@@ -949,6 +1045,14 @@
>
</File>
<File
+ RelativePath=".\TestVectors\vmac.txt"
+ >
+ </File>
+ <File
+ RelativePath=".\TestVectors\whrlpool.txt"
+ >
+ </File>
+ <File
RelativePath="xtrdh171.dat"
>
</File>
diff --git a/cryptlib.cpp b/cryptlib.cpp
index bbab37c..1d0a002 100644
--- a/cryptlib.cpp
+++ b/cryptlib.cpp
@@ -21,9 +21,7 @@ NAMESPACE_BEGIN(CryptoPP)
CRYPTOPP_COMPILE_ASSERT(sizeof(byte) == 1);
CRYPTOPP_COMPILE_ASSERT(sizeof(word16) == 2);
CRYPTOPP_COMPILE_ASSERT(sizeof(word32) == 4);
-#ifdef WORD64_AVAILABLE
CRYPTOPP_COMPILE_ASSERT(sizeof(word64) == 8);
-#endif
#ifdef CRYPTOPP_NATIVE_DWORD_AVAILABLE
CRYPTOPP_COMPILE_ASSERT(sizeof(dword) == 2*sizeof(word));
#endif
@@ -60,9 +58,9 @@ void SimpleKeyingInterface::SetKeyWithRounds(const byte *key, size_t length, int
SetKey(key, length, MakeParameters(Name::Rounds(), rounds));
}
-void SimpleKeyingInterface::SetKeyWithIV(const byte *key, size_t length, const byte *iv)
+void SimpleKeyingInterface::SetKeyWithIV(const byte *key, size_t length, const byte *iv, size_t ivLength)
{
- SetKey(key, length, MakeParameters(Name::IV(), iv));
+ SetKey(key, length, MakeParameters(Name::IV(), ConstByteArrayParameter(iv, ivLength)));
}
void SimpleKeyingInterface::ThrowIfInvalidKeyLength(size_t length)
@@ -83,14 +81,46 @@ void SimpleKeyingInterface::ThrowIfInvalidIV(const byte *iv)
throw InvalidArgument(GetAlgorithm().AlgorithmName() + ": this object cannot use a null IV");
}
-const byte * SimpleKeyingInterface::GetIVAndThrowIfInvalid(const NameValuePairs &params)
+size_t SimpleKeyingInterface::ThrowIfInvalidIVLength(int size)
+{
+ if (size < 0)
+ return IVSize();
+ else if ((size_t)size < MinIVLength())
+ throw InvalidArgument(GetAlgorithm().AlgorithmName() + ": IV length " + IntToString(size) + " is less than the minimum of " + IntToString(MinIVLength()));
+ else if ((size_t)size > MaxIVLength())
+ throw InvalidArgument(GetAlgorithm().AlgorithmName() + ": IV length " + IntToString(size) + " exceeds the maximum of " + IntToString(MaxIVLength()));
+ else
+ return size;
+}
+
+const byte * SimpleKeyingInterface::GetIVAndThrowIfInvalid(const NameValuePairs &params, size_t &size)
{
+ ConstByteArrayParameter ivWithLength;
const byte *iv;
- if (params.GetValue(Name::IV(), iv))
+ bool found = false;
+
+ try {found = params.GetValue(Name::IV(), ivWithLength);}
+ catch (const NameValuePairs::ValueTypeMismatch &) {}
+
+ if (found)
+ {
+ iv = ivWithLength.begin();
ThrowIfInvalidIV(iv);
+ size = ThrowIfInvalidIVLength((int)ivWithLength.size());
+ return iv;
+ }
+ else if (params.GetValue(Name::IV(), iv))
+ {
+ ThrowIfInvalidIV(iv);
+ size = IVSize();
+ return iv;
+ }
else
+ {
ThrowIfResynchronizable();
- return iv;
+ size = 0;
+ return NULL;
+ }
}
void SimpleKeyingInterface::GetNextIV(RandomNumberGenerator &rng, byte *IV)
@@ -98,20 +128,55 @@ void SimpleKeyingInterface::GetNextIV(RandomNumberGenerator &rng, byte *IV)
rng.GenerateBlock(IV, IVSize());
}
-void BlockTransformation::ProcessAndXorMultipleBlocks(const byte *inBlocks, const byte *xorBlocks, byte *outBlocks, size_t numberOfBlocks) const
+size_t BlockTransformation::AdvancedProcessBlocks(const byte *inBlocks, const byte *xorBlocks, byte *outBlocks, size_t length, word32 flags) const
{
- unsigned int blockSize = BlockSize();
- while (numberOfBlocks--)
+ size_t blockSize = BlockSize();
+ size_t inIncrement = (flags & (BT_InBlockIsCounter|BT_DontIncrementInOutPointers)) ? 0 : blockSize;
+ size_t xorIncrement = xorBlocks ? blockSize : 0;
+ size_t outIncrement = (flags & BT_DontIncrementInOutPointers) ? 0 : blockSize;
+
+ if (flags & BT_ReverseDirection)
+ {
+ assert(length % blockSize == 0);
+ inBlocks += length - blockSize;
+ xorBlocks += length - blockSize;
+ outBlocks += length - blockSize;
+ inIncrement = 0-inIncrement;
+ xorIncrement = 0-xorIncrement;
+ outIncrement = 0-outIncrement;
+ }
+
+ while (length >= blockSize)
{
- ProcessAndXorBlock(inBlocks, xorBlocks, outBlocks);
- inBlocks += blockSize;
- outBlocks += blockSize;
- if (xorBlocks)
- xorBlocks += blockSize;
+ if (flags & BT_XorInput)
+ {
+ xorbuf(outBlocks, xorBlocks, inBlocks, blockSize);
+ ProcessBlock(outBlocks);
+ }
+ else
+ ProcessAndXorBlock(inBlocks, xorBlocks, outBlocks);
+ if (flags & BT_InBlockIsCounter)
+ const_cast<byte *>(inBlocks)[blockSize-1]++;
+ inBlocks += inIncrement;
+ outBlocks += outIncrement;
+ xorBlocks += xorIncrement;
+ length -= blockSize;
}
+
+ return length;
}
-unsigned int BlockTransformation::BlockAlignment() const
+unsigned int BlockTransformation::OptimalDataAlignment() const
+{
+ return GetAlignmentOf<word32>();
+}
+
+unsigned int StreamTransformation::OptimalDataAlignment() const
+{
+ return GetAlignmentOf<word32>();
+}
+
+unsigned int HashTransformation::OptimalDataAlignment() const
{
return GetAlignmentOf<word32>();
}
@@ -123,7 +188,21 @@ void StreamTransformation::ProcessLastBlock(byte *outString, const byte *inStrin
if (length == MandatoryBlockSize())
ProcessData(outString, inString, length);
else if (length != 0)
- throw NotImplemented("StreamTransformation: this object does't support a special last block");
+ throw NotImplemented(AlgorithmName() + ": this object does't support a special last block");
+}
+
+void AuthenticatedSymmetricCipher::SpecifyDataLengths(lword headerLength, lword messageLength, lword footerLength)
+{
+ if (headerLength > MaxHeaderLength())
+ throw InvalidArgument(GetAlgorithm().AlgorithmName() + ": header length " + IntToString(headerLength) + " exceeds the maximum of " + IntToString(MaxHeaderLength()));
+
+ if (messageLength > MaxMessageLength())
+ throw InvalidArgument(GetAlgorithm().AlgorithmName() + ": message length " + IntToString(messageLength) + " exceeds the maximum of " + IntToString(MaxMessageLength()));
+
+ if (footerLength > MaxFooterLength())
+ throw InvalidArgument(GetAlgorithm().AlgorithmName() + ": footer length " + IntToString(footerLength) + " exceeds the maximum of " + IntToString(MaxFooterLength()));
+
+ UncheckedSpecifyDataLengths(headerLength, messageLength, footerLength);
}
unsigned int RandomNumberGenerator::GenerateBit()
@@ -196,7 +275,7 @@ bool HashTransformation::TruncatedVerify(const byte *digestIn, size_t digestLeng
ThrowIfInvalidTruncatedSize(digestLength);
SecByteBlock digest(digestLength);
TruncatedFinal(digest, digestLength);
- return memcmp(digest, digestIn, digestLength) == 0;
+ return VerifyBufsEqual(digest, digestIn, digestLength);
}
void HashTransformation::ThrowIfInvalidTruncatedSize(size_t size) const
@@ -241,7 +320,7 @@ byte * BufferedTransformation::ChannelCreatePutSpace(const std::string &channel,
if (channel.empty())
return CreatePutSpace(size);
else
- throw NoChannelSupport();
+ throw NoChannelSupport(AlgorithmName());
}
size_t BufferedTransformation::ChannelPut2(const std::string &channel, const byte *begin, size_t length, int messageEnd, bool blocking)
@@ -249,7 +328,7 @@ size_t BufferedTransformation::ChannelPut2(const std::string &channel, const byt
if (channel.empty())
return Put2(begin, length, messageEnd, blocking);
else
- throw NoChannelSupport();
+ throw NoChannelSupport(AlgorithmName());
}
size_t BufferedTransformation::ChannelPutModifiable2(const std::string &channel, byte *begin, size_t length, int messageEnd, bool blocking)
@@ -265,7 +344,7 @@ bool BufferedTransformation::ChannelFlush(const std::string &channel, bool compl
if (channel.empty())
return Flush(completeFlush, propagation, blocking);
else
- throw NoChannelSupport();
+ throw NoChannelSupport(AlgorithmName());
}
bool BufferedTransformation::ChannelMessageSeriesEnd(const std::string &channel, int propagation, bool blocking)
@@ -273,7 +352,7 @@ bool BufferedTransformation::ChannelMessageSeriesEnd(const std::string &channel,
if (channel.empty())
return MessageSeriesEnd(propagation, blocking);
else
- throw NoChannelSupport();
+ throw NoChannelSupport(AlgorithmName());
}
lword BufferedTransformation::MaxRetrievable() const
diff --git a/cryptlib.h b/cryptlib.h
index be42cd2..0016b64 100644
--- a/cryptlib.h
+++ b/cryptlib.h
@@ -4,7 +4,7 @@
classes that provide a uniform interface to this library.
*/
-/*! \mainpage <a href="http://www.cryptopp.com">Crypto++</a><sup><small>&reg;</small></sup> Library 5.5.2 Reference Manual
+/*! \mainpage <a href="http://www.cryptopp.com">Crypto++</a><sup><small>&reg;</small></sup> Library 5.6.0 Reference Manual
<dl>
<dt>Abstract Base Classes<dd>
cryptlib.h
@@ -15,7 +15,9 @@
<dt>Non-Cryptographic Checksums<dd>
CRC32, Adler32
<dt>Message Authentication Codes<dd>
- VMAC, HMAC, CBC_MAC, DMAC, TTMAC
+ VMAC, HMAC, CBC_MAC, CMAC, DMAC, TTMAC, GCM
+<dt>Authenticated Encryption<dd>
+ AuthenticatedSymmetricCipherDocumentation
<dt>Random Number Generators<dd>
NullRNG(), LC_RNG, RandomPool, BlockingRng, NonblockingRng, AutoSeededRandomPool, AutoSeededX917RNG, DefaultAutoSeededRNG
<dt>Password-based Cryptography<dd>
@@ -88,7 +90,7 @@ class RandomNumberGenerator;
class BufferedTransformation;
//! used to specify a direction for a cipher to operate in (encrypt or decrypt)
-enum CipherDir {ENCRYPTION, DECRYPTION};
+enum CipherDir {ENCRYPTION, DECRYPTION};
//! used to represent infinite time
const unsigned long INFINITE_TIME = ULONG_MAX;
@@ -349,7 +351,6 @@ public:
};
//! keying interface for crypto algorithms that take byte strings as keys
-
class CRYPTOPP_DLL CRYPTOPP_NO_VTABLE SimpleKeyingInterface
{
public:
@@ -370,14 +371,18 @@ public:
{return n == GetValidKeyLength(n);}
//! set or reset the key of this object
- /*! \param params is used to specify Rounds, BlockSize, etc */
+ /*! \param params is used to specify Rounds, BlockSize, etc. */
virtual void SetKey(const byte *key, size_t length, const NameValuePairs &params = g_nullNameValuePairs);
//! calls SetKey() with an NameValuePairs object that just specifies "Rounds"
void SetKeyWithRounds(const byte *key, size_t length, int rounds);
- //! calls SetKey() with an NameValuePairs object that just specifies "IV"
- void SetKeyWithIV(const byte *key, size_t length, const byte *iv);
+ //! calls SetKey() with an NameValuePairs object that just specifies "IVWithLength"
+ void SetKeyWithIV(const byte *key, size_t length, const byte *iv, size_t ivLength);
+
+ //! calls SetKey() with an NameValuePairs object that just specifies "IVWithLength"
+ void SetKeyWithIV(const byte *key, size_t length, const byte *iv)
+ {SetKeyWithIV(key, length, iv, IVSize());}
enum IV_Requirement {UNIQUE_IV = 0, RANDOM_IV, UNPREDICTABLE_RANDOM_IV, INTERNALLY_GENERATED_IV, NOT_RESYNCHRONIZABLE};
//! returns the minimal requirement for secure IVs
@@ -393,10 +398,15 @@ public:
//! returns whether this object can use structured IVs, for example a counter (in addition to ones returned by GetNextIV)
bool CanUseStructuredIVs() const {return IVRequirement() <= UNIQUE_IV;}
- //! returns size of IVs used by this object
- virtual unsigned int IVSize() const {throw NotImplemented("SimpleKeyingInterface: this object doesn't support resynchronization");}
- //! resynchronize with an IV
- virtual void Resynchronize(const byte *IV) {throw NotImplemented("SimpleKeyingInterface: this object doesn't support resynchronization");}
+ virtual unsigned int IVSize() const {throw NotImplemented(GetAlgorithm().AlgorithmName() + ": this object doesn't support resynchronization");}
+ //! returns default length of IVs accepted by this object
+ unsigned int DefaultIVLength() const {return IVSize();}
+ //! returns minimal length of IVs accepted by this object
+ virtual unsigned int MinIVLength() const {return IVSize();}
+ //! returns maximal length of IVs accepted by this object
+ virtual unsigned int MaxIVLength() const {return IVSize();}
+ //! resynchronize with an IV. ivLength=-1 means use IVSize()
+ virtual void Resynchronize(const byte *iv, int ivLength=-1) {throw NotImplemented(GetAlgorithm().AlgorithmName() + ": this object doesn't support resynchronization");}
//! get a secure IV for the next message
/*! This method should be called after you finish encrypting one message and are ready to start the next one.
After calling it, you must call SetKey() or Resynchronize() before using this object again.
@@ -410,7 +420,8 @@ protected:
void ThrowIfInvalidKeyLength(size_t length);
void ThrowIfResynchronizable(); // to be called when no IV is passed
void ThrowIfInvalidIV(const byte *iv); // check for NULL IV if it can't be used
- const byte * GetIVAndThrowIfInvalid(const NameValuePairs &params);
+ size_t ThrowIfInvalidIVLength(int size);
+ const byte * GetIVAndThrowIfInvalid(const NameValuePairs &params, size_t &size);
inline void AssertValidKeyLength(size_t length) const
{assert(IsValidKeyLength(length));}
};
@@ -418,8 +429,7 @@ protected:
//! interface for the data processing part of block ciphers
/*! Classes derived from BlockTransformation are block ciphers
- in ECB mode (for example the DES::Encryption class), which are stateless,
- and they can make assumptions about the memory alignment of their inputs and outputs.
+ in ECB mode (for example the DES::Encryption class), which are stateless.
These classes should not be used directly, but only in combination with
a mode class (see CipherModeDocumentation in modes.h).
*/
@@ -441,8 +451,8 @@ public:
//! block size of the cipher in bytes
virtual unsigned int BlockSize() const =0;
- //! block pointers must be divisible by this
- virtual unsigned int BlockAlignment() const; // returns alignment of word32 by default
+ //! returns how inputs and outputs should be aligned for optimal performance
+ virtual unsigned int OptimalDataAlignment() const;
//! returns true if this is a permutation (i.e. there is an inverse transformation)
virtual bool IsPermutation() const {return true;}
@@ -453,8 +463,11 @@ public:
//! return number of blocks that can be processed in parallel, for bit-slicing implementations
virtual unsigned int OptimalNumberOfParallelBlocks() const {return 1;}
- //! encrypt or decrypt multiple blocks, for bit-slicing implementations
- virtual void ProcessAndXorMultipleBlocks(const byte *inBlocks, const byte *xorBlocks, byte *outBlocks, size_t numberOfBlocks) const;
+ enum {BT_InBlockIsCounter=1, BT_DontIncrementInOutPointers=2, BT_XorInput=4, BT_ReverseDirection=8} FlagsForAdvancedProcessBlocks;
+
+ //! encrypt and xor blocks according to flags (see FlagsForAdvancedProcessBlocks)
+ /*! /note If BT_InBlockIsCounter is set, last byte of inBlocks may be modified. */
+ virtual size_t AdvancedProcessBlocks(const byte *inBlocks, const byte *xorBlocks, byte *outBlocks, size_t length, word32 flags) const;
inline CipherDir GetCipherDirection() const {return IsForwardTransformation() ? ENCRYPTION : DECRYPTION;}
};
@@ -479,7 +492,7 @@ public:
virtual unsigned int GetOptimalBlockSizeUsed() const {return 0;}
//! returns how input should be aligned for optimal performance
- virtual unsigned int OptimalDataAlignment() const {return 1;}
+ virtual unsigned int OptimalDataAlignment() const;
//! encrypt or decrypt an array of bytes of specified length
/*! \note either inString == outString, or they don't overlap */
@@ -557,7 +570,7 @@ public:
virtual unsigned int OptimalBlockSize() const {return 1;}
//! returns how input should be aligned for optimal performance
- virtual unsigned int OptimalDataAlignment() const {return 1;}
+ virtual unsigned int OptimalDataAlignment() const;
//! use this if your input is in one piece and you don't want to call Update() and Final() separately
virtual void CalculateDigest(byte *digest, const byte *input, size_t length)
@@ -593,30 +606,60 @@ protected:
typedef HashTransformation HashFunction;
-template <class T>
-class CRYPTOPP_DLL CRYPTOPP_NO_VTABLE SimpleKeyedTransformation : public T, public SimpleKeyingInterface
+//! interface for one direction (encryption or decryption) of a block cipher
+/*! \note These objects usually should not be used directly. See BlockTransformation for more details. */
+class CRYPTOPP_DLL CRYPTOPP_NO_VTABLE BlockCipher : public SimpleKeyingInterface, public BlockTransformation
{
protected:
const Algorithm & GetAlgorithm() const {return *this;}
};
-#ifdef CRYPTOPP_DOXYGEN_PROCESSING
-//! interface for one direction (encryption or decryption) of a block cipher
-/*! \note These objects usually should not be used directly. See BlockTransformation for more details. */
-class BlockCipher : public BlockTransformation, public SimpleKeyingInterface {};
//! interface for one direction (encryption or decryption) of a stream cipher or cipher mode
-class SymmetricCipher : public StreamTransformation, public SimpleKeyingInterface {};
+class CRYPTOPP_DLL CRYPTOPP_NO_VTABLE SymmetricCipher : public SimpleKeyingInterface, public StreamTransformation
+{
+protected:
+ const Algorithm & GetAlgorithm() const {return *this;}
+};
+
//! interface for message authentication codes
-class MessageAuthenticationCode : public HashTransformation, public SimpleKeyingInterface {};
-#else
-typedef SimpleKeyedTransformation<BlockTransformation> BlockCipher;
-typedef SimpleKeyedTransformation<StreamTransformation> SymmetricCipher;
-typedef SimpleKeyedTransformation<HashTransformation> MessageAuthenticationCode;
-#endif
+class CRYPTOPP_DLL CRYPTOPP_NO_VTABLE MessageAuthenticationCode : public SimpleKeyingInterface, public HashTransformation
+{
+protected:
+ const Algorithm & GetAlgorithm() const {return *this;}
+};
-CRYPTOPP_DLL_TEMPLATE_CLASS SimpleKeyedTransformation<BlockTransformation>;
-CRYPTOPP_DLL_TEMPLATE_CLASS SimpleKeyedTransformation<StreamTransformation>;
-CRYPTOPP_DLL_TEMPLATE_CLASS SimpleKeyedTransformation<HashTransformation>;
+//! interface for for one direction (encryption or decryption) of a stream cipher or block cipher mode with authentication
+/*! The StreamTransformation part of this interface is used to encrypt/decrypt the data, and the MessageAuthenticationCode part of this
+ interface is used to input additional authenticated data (AAD, which is MAC'ed but not encrypted), and to generate/verify the MAC. */
+class CRYPTOPP_DLL CRYPTOPP_NO_VTABLE AuthenticatedSymmetricCipher : public MessageAuthenticationCode, public StreamTransformation
+{
+public:
+ //! this indicates that a member function was called in the wrong state, for example trying to encrypt a message before having set the key or IV
+ class BadState : public Exception
+ {
+ public:
+ explicit BadState(const std::string &name, const char *function, const char *state) : Exception(OTHER_ERROR, name + ": " + function + " was called before " + state) {}
+ };
+
+ // redeclare this to avoid compiler ambiguity errors
+ virtual std::string AlgorithmName() const =0;
+
+ //! the maximum length of AAD that can be input before the encrypted data
+ virtual lword MaxHeaderLength() const =0;
+ //! the maximum length of encrypted data
+ virtual lword MaxMessageLength() const =0;
+ //! the maximum length of AAD that can be input after the encrypted data
+ virtual lword MaxFooterLength() const {return 0;}
+ //! if this function returns true, SpecifyDataLengths() must be called before attempting to input data
+ /*! This is the case for some schemes, such as CCM. */
+ virtual bool NeedsPrespecifiedDataLengths() const {return false;}
+ //! this function only needs to be called if NeedsPrespecifiedDataLengths() returns true
+ void SpecifyDataLengths(lword headerLength, lword messageLength, lword footerLength=0);
+
+protected:
+ const Algorithm & GetAlgorithm() const {return *static_cast<const MessageAuthenticationCode *>(this);}
+ virtual void UncheckedSpecifyDataLengths(lword headerLength, lword messageLength, lword footerLength) {}
+};
#ifdef CRYPTOPP_MAINTAIN_BACKWARDS_COMPATIBILITY
typedef SymmetricCipher StreamCipher;
@@ -921,7 +964,9 @@ public:
//! \name CHANNELS
//@{
struct NoChannelSupport : public NotImplemented
- {NoChannelSupport() : NotImplemented("BufferedTransformation: this object doesn't support multiple channels") {}};
+ {NoChannelSupport(const std::string &name) : NotImplemented(name + ": this object doesn't support multiple channels") {}};
+ struct InvalidChannelName : public InvalidArgument
+ {InvalidChannelName(const std::string &name, const std::string &channel) : InvalidArgument(name + ": unexpected channel name \"" + channel + "\"") {}};
size_t ChannelPut(const std::string &channel, byte inByte, bool blocking=true)
{return ChannelPut(channel, &inByte, 1, blocking);}
@@ -1043,7 +1088,7 @@ public:
// for internal library use
void DoQuickSanityCheck() const {ThrowIfInvalid(NullRNG(), 0);}
-#ifdef __SUNPRO_CC
+#if (defined(__SUNPRO_CC) && __SUNPRO_CC < 0x590)
// Sun Studio 11/CC 5.8 workaround: it generates incorrect code when casting to an empty virtual base class
char m_sunCCworkaround;
#endif
diff --git a/cryptlib.vcproj b/cryptlib.vcproj
index fbb97b2..c14e64e 100755
--- a/cryptlib.vcproj
+++ b/cryptlib.vcproj
@@ -1106,6 +1106,10 @@
</FileConfiguration>
</File>
<File
+ RelativePath=".\authenc.cpp"
+ >
+ </File>
+ <File
RelativePath="base32.cpp"
>
<FileConfiguration
@@ -1846,6 +1850,10 @@
</FileConfiguration>
</File>
<File
+ RelativePath=".\ccm.cpp"
+ >
+ </File>
+ <File
RelativePath="channels.cpp"
>
<FileConfiguration
@@ -1920,6 +1928,10 @@
</FileConfiguration>
</File>
<File
+ RelativePath=".\cmac.cpp"
+ >
+ </File>
+ <File
RelativePath=".\cpu.cpp"
>
</File>
@@ -3358,6 +3370,10 @@
</FileConfiguration>
</File>
<File
+ RelativePath=".\gcm.cpp"
+ >
+ </File>
+ <File
RelativePath="gf256.cpp"
>
<FileConfiguration
@@ -6857,6 +6873,10 @@
</FileConfiguration>
</File>
<File
+ RelativePath=".\seed.cpp"
+ >
+ </File>
+ <File
RelativePath="serpent.cpp"
>
<FileConfiguration
@@ -8493,6 +8513,80 @@
</FileConfiguration>
</File>
<File
+ RelativePath=".\x64dll.asm"
+ >
+ <FileConfiguration
+ Name="Release|Win32"
+ ExcludedFromBuild="true"
+ >
+ <Tool
+ Name="VCCustomBuildTool"
+ />
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Release|x64"
+ >
+ <Tool
+ Name="VCCustomBuildTool"
+ CommandLine="ml64.exe /c /nologo /Fo&quot;$(IntDir)\x64dll.obj&quot; /Zi &quot;$(InputPath)&quot;"
+ Outputs="$(IntDir)\x64dll.obj"
+ />
+ </FileConfiguration>
+ <FileConfiguration
+ Name="DLL-Import Release|Win32"
+ ExcludedFromBuild="true"
+ >
+ <Tool
+ Name="VCCustomBuildTool"
+ />
+ </FileConfiguration>
+ <FileConfiguration
+ Name="DLL-Import Release|x64"
+ ExcludedFromBuild="true"
+ >
+ <Tool
+ Name="VCCustomBuildTool"
+ CommandLine="ml64.exe /c /nologo /Fo&quot;$(IntDir)\x64dll.obj&quot; /Zi &quot;$(InputPath)&quot;"
+ Outputs="$(IntDir)\x64dll.obj"
+ />
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Debug|Win32"
+ ExcludedFromBuild="true"
+ >
+ <Tool
+ Name="VCCustomBuildTool"
+ />
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Debug|x64"
+ >
+ <Tool
+ Name="VCCustomBuildTool"
+ CommandLine="ml64.exe /c /nologo /Fo&quot;$(IntDir)\x64dll.obj&quot; /Zi &quot;$(InputPath)&quot;"
+ Outputs="$(IntDir)\x64dll.obj"
+ />
+ </FileConfiguration>
+ <FileConfiguration
+ Name="DLL-Import Debug|Win32"
+ ExcludedFromBuild="true"
+ >
+ <Tool
+ Name="VCCustomBuildTool"
+ />
+ </FileConfiguration>
+ <FileConfiguration
+ Name="DLL-Import Debug|x64"
+ ExcludedFromBuild="true"
+ >
+ <Tool
+ Name="VCCustomBuildTool"
+ CommandLine="ml64.exe /c /nologo /Fo&quot;$(IntDir)\x64dll.obj&quot; /Zi &quot;$(InputPath)&quot;"
+ Outputs="$(IntDir)\x64dll.obj"
+ />
+ </FileConfiguration>
+ </File>
+ <File
RelativePath=".\x64masm.asm"
>
<FileConfiguration
@@ -8508,7 +8602,7 @@
>
<Tool
Name="VCCustomBuildTool"
- CommandLine="ml64.exe /c /nologo /Fo&quot;$(IntDir)\x64masm.obj&quot; /Zi &quot;$(InputPath)&quot;"
+ CommandLine="ml64.exe /c /nologo /Fo&quot;$(IntDir)\x64masm.obj&quot; /Zi &quot;$(InputPath)&quot;&#x0D;&#x0A;"
Outputs="$(IntDir)\x64masm.obj"
/>
</FileConfiguration>
@@ -8525,7 +8619,7 @@
>
<Tool
Name="VCCustomBuildTool"
- CommandLine="ml64.exe /c /nologo /Fo&quot;$(IntDir)\x64masm.obj&quot; /Zi &quot;$(InputPath)&quot;"
+ CommandLine="ml64.exe /c /nologo /Fo&quot;$(IntDir)\x64masm.obj&quot; /Zi &quot;$(InputPath)&quot;&#x0D;&#x0A;"
Outputs="$(IntDir)\x64masm.obj"
/>
</FileConfiguration>
@@ -8542,7 +8636,7 @@
>
<Tool
Name="VCCustomBuildTool"
- CommandLine="ml64.exe /c /nologo /Fo&quot;$(IntDir)\x64masm.obj&quot; /Zi &quot;$(InputPath)&quot;"
+ CommandLine="ml64.exe /c /nologo /Fo&quot;$(IntDir)\x64masm.obj&quot; /Zi &quot;$(InputPath)&quot;&#x0D;&#x0A;"
Outputs="$(IntDir)\x64masm.obj"
/>
</FileConfiguration>
@@ -8559,7 +8653,7 @@
>
<Tool
Name="VCCustomBuildTool"
- CommandLine="ml64.exe /c /nologo /Fo&quot;$(IntDir)\x64masm.obj&quot; /Zi &quot;$(InputPath)&quot;"
+ CommandLine="ml64.exe /c /nologo /Fo&quot;$(IntDir)\x64masm.obj&quot; /Zi &quot;$(InputPath)&quot;&#x0D;&#x0A;"
Outputs="$(IntDir)\x64masm.obj"
/>
</FileConfiguration>
@@ -8972,6 +9066,10 @@
>
</File>
<File
+ RelativePath=".\authenc.h"
+ >
+ </File>
+ <File
RelativePath="base32.h"
>
</File>
@@ -9004,10 +9102,18 @@
>
</File>
<File
+ RelativePath=".\ccm.h"
+ >
+ </File>
+ <File
RelativePath="channels.h"
>
</File>
<File
+ RelativePath=".\cmac.h"
+ >
+ </File>
+ <File
RelativePath="config.h"
>
</File>
@@ -9092,6 +9198,10 @@
>
</File>
<File
+ RelativePath=".\gcm.h"
+ >
+ </File>
+ <File
RelativePath="gf256.h"
>
</File>
@@ -9316,6 +9426,10 @@
>
</File>
<File
+ RelativePath=".\seed.h"
+ >
+ </File>
+ <File
RelativePath="serpent.h"
>
</File>
@@ -9452,10 +9566,6 @@
>
</File>
</Filter>
- <File
- RelativePath=".\VTune\cryptlib.vpj"
- >
- </File>
</Files>
<Globals>
</Globals>
diff --git a/cryptopp.rc b/cryptopp.rc
index d4f43e5..b1012ef 100644
--- a/cryptopp.rc
+++ b/cryptopp.rc
@@ -27,8 +27,8 @@ LANGUAGE LANG_ENGLISH, SUBLANG_ENGLISH_US
//
VS_VERSION_INFO VERSIONINFO
- FILEVERSION 5,5,2,0
- PRODUCTVERSION 5,5,2,0
+ FILEVERSION 5,6,0,0
+ PRODUCTVERSION 5,6,0,0
FILEFLAGSMASK 0x3fL
#ifdef _DEBUG
FILEFLAGS 0x1L
@@ -46,13 +46,13 @@ BEGIN
VALUE "Comments", "free crypto library, more information available at www.cryptopp.com"
VALUE "CompanyName", "Wei Dai"
VALUE "FileDescription", "Crypto++® Library DLL"
- VALUE "FileVersion", "5, 5, 2, 0"
+ VALUE "FileVersion", "5, 6, 0, 0"
VALUE "InternalName", "cryptopp"
- VALUE "LegalCopyright", "Copyright © 1995-2007 by Wei Dai"
+ VALUE "LegalCopyright", "Copyright © 1995-2009 by Wei Dai"
VALUE "LegalTrademarks", "Crypto++®"
VALUE "OriginalFilename", "cryptopp.dll"
VALUE "ProductName", "Crypto++® Library"
- VALUE "ProductVersion", "5, 5, 2, 0"
+ VALUE "ProductVersion", "5, 6, 0, 0"
END
END
BLOCK "VarFileInfo"
diff --git a/datatest.cpp b/datatest.cpp
index 950e4f9..72d3b28 100644
--- a/datatest.cpp
+++ b/datatest.cpp
@@ -43,6 +43,12 @@ static void SignalTestError()
throw Exception(Exception::OTHER_ERROR, "Unexpected error during validation test");
}
+bool DataExists(const TestData &data, const char *name)
+{
+ TestData::const_iterator i = data.find(name);
+ return (i != data.end());
+}
+
const std::string & GetRequiredDatum(const TestData &data, const char *name)
{
TestData::const_iterator i = data.find(name);
@@ -102,6 +108,14 @@ std::string GetDecodedDatum(const TestData &data, const char *name)
return s;
}
+std::string GetOptionalDecodedDatum(const TestData &data, const char *name)
+{
+ std::string s;
+ if (DataExists(data, name))
+ PutDecodedDatumInto(data, name, StringSink(s).Ref());
+ return s;
+}
+
class TestDataNameValuePairs : public NameValuePairs
{
public:
@@ -111,7 +125,23 @@ public:
{
TestData::const_iterator i = m_data.find(name);
if (i == m_data.end())
- return false;
+ {
+ if (std::string(name) == Name::DigestSize() && valueType == typeid(int))
+ {
+ i = m_data.find("MAC");
+ if (i == m_data.end())
+ i = m_data.find("Digest");
+ if (i == m_data.end())
+ return false;
+
+ m_temp.resize(0);
+ PutDecodedDatumInto(m_data, i->first.c_str(), StringSink(m_temp).Ref());
+ *reinterpret_cast<int *>(pValue) = (int)m_temp.size();
+ return true;
+ }
+ else
+ return false;
+ }
const std::string &value = i->second;
@@ -123,13 +153,7 @@ public:
{
m_temp.resize(0);
PutDecodedDatumInto(m_data, name, StringSink(m_temp).Ref());
- reinterpret_cast<ConstByteArrayParameter *>(pValue)->Assign((const byte *)m_temp.data(), m_temp.size(), true);
- }
- else if (valueType == typeid(const byte *))
- {
- m_temp.resize(0);
- PutDecodedDatumInto(m_data, name, StringSink(m_temp).Ref());
- *reinterpret_cast<const byte * *>(pValue) = (const byte *)m_temp.data();
+ reinterpret_cast<ConstByteArrayParameter *>(pValue)->Assign((const byte *)m_temp.data(), m_temp.size(), false);
}
else
throw ValueTypeMismatch(name, typeid(std::string), valueType);
@@ -271,7 +295,7 @@ void TestAsymmetricCipher(TestData &v)
}
}
-void TestSymmetricCipher(TestData &v)
+void TestSymmetricCipher(TestData &v, const NameValuePairs &overrideParameters)
{
std::string name = GetRequiredDatum(v, "Name");
std::string test = GetRequiredDatum(v, "Test");
@@ -279,7 +303,8 @@ void TestSymmetricCipher(TestData &v)
std::string key = GetDecodedDatum(v, "Key");
std::string plaintext = GetDecodedDatum(v, "Plaintext");
- TestDataNameValuePairs pairs(v);
+ TestDataNameValuePairs testDataPairs(v);
+ CombinedNameValuePairs pairs(overrideParameters, testDataPairs);
if (test == "Encrypt" || test == "EncryptXorDigest")
{
@@ -339,13 +364,95 @@ void TestSymmetricCipher(TestData &v)
SignalTestFailure();
}
}
- else if (test == "Decrypt")
+ else
{
+ std::cout << "unexpected test name\n";
+ SignalTestError();
+ }
+}
+
+void TestAuthenticatedSymmetricCipher(TestData &v, const NameValuePairs &overrideParameters)
+{
+ std::string type = GetRequiredDatum(v, "AlgorithmType");
+ std::string name = GetRequiredDatum(v, "Name");
+ std::string test = GetRequiredDatum(v, "Test");
+ std::string key = GetDecodedDatum(v, "Key");
+
+ std::string plaintext = GetOptionalDecodedDatum(v, "Plaintext");
+ std::string ciphertext = GetOptionalDecodedDatum(v, "Ciphertext");
+ std::string header = GetOptionalDecodedDatum(v, "Header");
+ std::string footer = GetOptionalDecodedDatum(v, "Footer");
+ std::string mac = GetOptionalDecodedDatum(v, "MAC");
+
+ TestDataNameValuePairs testDataPairs(v);
+ CombinedNameValuePairs pairs(overrideParameters, testDataPairs);
+
+ if (test == "Encrypt" || test == "EncryptXorDigest" || test == "NotVerify")
+ {
+ member_ptr<AuthenticatedSymmetricCipher> asc1, asc2;
+ asc1.reset(ObjectFactoryRegistry<AuthenticatedSymmetricCipher, ENCRYPTION>::Registry().CreateObject(name.c_str()));
+ asc2.reset(ObjectFactoryRegistry<AuthenticatedSymmetricCipher, DECRYPTION>::Registry().CreateObject(name.c_str()));
+ asc1->SetKey((const byte *)key.data(), key.size(), pairs);
+ asc2->SetKey((const byte *)key.data(), key.size(), pairs);
+
+ std::string encrypted, decrypted;
+ AuthenticatedEncryptionFilter ef(*asc1, new StringSink(encrypted));
+ AuthenticatedDecryptionFilter df(*asc2, new StringSink(decrypted), AuthenticatedDecryptionFilter::DEFAULT_PADDING, AuthenticatedDecryptionFilter::MAC_AT_BEGIN);
+
+ if (asc1->NeedsPrespecifiedDataLengths())
+ {
+ asc1->SpecifyDataLengths(header.size(), plaintext.size(), footer.size());
+ asc2->SpecifyDataLengths(header.size(), plaintext.size(), footer.size());
+ }
+
+ StringStore sh(header), sp(plaintext), sc(ciphertext), sf(footer), sm(mac);
+
+ sm.TransferTo(df);
+ sh.CopyTo(df, LWORD_MAX, "AAD");
+ sc.TransferTo(df);
+ sf.CopyTo(df, LWORD_MAX, "AAD");
+ df.MessageEnd();
+
+ sh.TransferTo(ef, sh.MaxRetrievable()/2+1, "AAD");
+ sh.TransferTo(ef, LWORD_MAX, "AAD");
+ sp.TransferTo(ef, sp.MaxRetrievable()/2+1);
+ sp.TransferTo(ef);
+ sf.TransferTo(ef, sf.MaxRetrievable()/2+1, "AAD");
+ sf.TransferTo(ef, LWORD_MAX, "AAD");
+ ef.MessageEnd();
+
+ if (test == "Encrypt" && encrypted != ciphertext+mac)
+ {
+ std::cout << "incorrectly encrypted: ";
+ StringSource xx(encrypted, false, new HexEncoder(new FileSink(std::cout)));
+ xx.Pump(256); xx.Flush(false);
+ std::cout << "\n";
+ SignalTestFailure();
+ }
+ if (decrypted != plaintext)
+ {
+ std::cout << "incorrectly decrypted: ";
+ StringSource xx(decrypted, false, new HexEncoder(new FileSink(std::cout)));
+ xx.Pump(256); xx.Flush(false);
+ std::cout << "\n";
+ SignalTestFailure();
+ }
+
+ if (mac.size() != asc1->DigestSize())
+ {
+ std::cout << "bad MAC size\n";
+ SignalTestFailure();
+ }
+ if (df.GetLastResult() != (test == "Encrypt"))
+ {
+ std::cout << "MAC incorrectly verified\n";
+ SignalTestFailure();
+ }
}
else
{
+ std::cout << "unexpected test name\n";
SignalTestError();
- assert(false);
}
}
@@ -353,6 +460,7 @@ void TestDigestOrMAC(TestData &v, bool testDigest)
{
std::string name = GetRequiredDatum(v, "Name");
std::string test = GetRequiredDatum(v, "Test");
+ const char *digestName = testDigest ? "Digest" : "MAC";
member_ptr<MessageAuthenticationCode> mac;
member_ptr<HashTransformation> hash;
@@ -369,21 +477,17 @@ void TestDigestOrMAC(TestData &v, bool testDigest)
{
mac.reset(ObjectFactoryRegistry<MessageAuthenticationCode>::Registry().CreateObject(name.c_str()));
pHash = mac.get();
- ConstByteArrayParameter iv;
- if (pairs.GetValue(Name::IV(), iv) && iv.size() != mac->IVSize())
- SignalTestFailure();
std::string key = GetDecodedDatum(v, "Key");
mac->SetKey((const byte *)key.c_str(), key.size(), pairs);
}
if (test == "Verify" || test == "VerifyTruncated" || test == "NotVerify")
{
- int digestSize = pHash->DigestSize();
+ int digestSize = -1;
if (test == "VerifyTruncated")
- digestSize = atoi(GetRequiredDatum(v, "TruncatedSize").c_str());
- TruncatedHashModule thash(*pHash, digestSize);
- HashVerificationFilter verifierFilter(thash, NULL, HashVerificationFilter::HASH_AT_BEGIN);
- PutDecodedDatumInto(v, "Digest", verifierFilter);
+ pairs.GetIntValue(Name::DigestSize(), digestSize);
+ HashVerificationFilter verifierFilter(*pHash, NULL, HashVerificationFilter::HASH_AT_BEGIN, digestSize);
+ PutDecodedDatumInto(v, digestName, verifierFilter);
PutDecodedDatumInto(v, "Message", verifierFilter);
verifierFilter.MessageEnd();
if (verifierFilter.GetLastResult() == (test == "NotVerify"))
@@ -404,8 +508,14 @@ bool GetField(std::istream &is, std::string &name, std::string &value)
return false;
if (name[name.size()-1] != ':')
- SignalTestError();
- name.erase(name.size()-1);
+ {
+ char c;
+ is >> skipws >> c;
+ if (c != ':')
+ SignalTestError();
+ }
+ else
+ name.erase(name.size()-1);
while (is.peek() == ' ')
is.ignore(1);
@@ -477,7 +587,7 @@ void OutputNameValuePairs(const NameValuePairs &v)
}
}
-void TestDataFile(const std::string &filename, unsigned int &totalTests, unsigned int &failedTests)
+void TestDataFile(const std::string &filename, const NameValuePairs &overrideParameters, unsigned int &totalTests, unsigned int &failedTests)
{
std::ifstream file(filename.c_str());
if (!file.good())
@@ -514,7 +624,9 @@ void TestDataFile(const std::string &filename, unsigned int &totalTests, unsigne
if (algType == "Signature")
TestSignatureScheme(v);
else if (algType == "SymmetricCipher")
- TestSymmetricCipher(v);
+ TestSymmetricCipher(v, overrideParameters);
+ else if (algType == "AuthenticatedSymmetricCipher")
+ TestAuthenticatedSymmetricCipher(v, overrideParameters);
else if (algType == "AsymmetricCipher")
TestAsymmetricCipher(v);
else if (algType == "MessageDigest")
@@ -522,7 +634,7 @@ void TestDataFile(const std::string &filename, unsigned int &totalTests, unsigne
else if (algType == "MAC")
TestDigestOrMAC(v, false);
else if (algType == "FileList")
- TestDataFile(GetRequiredDatum(v, "Test"), totalTests, failedTests);
+ TestDataFile(GetRequiredDatum(v, "Test"), g_nullNameValuePairs, totalTests, failedTests);
else
SignalTestError();
failed = false;
@@ -553,10 +665,10 @@ void TestDataFile(const std::string &filename, unsigned int &totalTests, unsigne
}
}
-bool RunTestDataFile(const char *filename)
+bool RunTestDataFile(const char *filename, const NameValuePairs &overrideParameters)
{
unsigned int totalTests = 0, failedTests = 0;
- TestDataFile(filename, totalTests, failedTests);
+ TestDataFile(filename, overrideParameters, totalTests, failedTests);
cout << "\nTests complete. Total tests = " << totalTests << ". Failed tests = " << failedTests << ".\n";
if (failedTests != 0)
cout << "SOME TESTS FAILED!\n";
diff --git a/default.cpp b/default.cpp
index 11cbe7e..7294078 100644
--- a/default.cpp
+++ b/default.cpp
@@ -180,7 +180,7 @@ void DefaultDecryptor::CheckKey(const byte *salt, const byte *keyCheck)
SetFilter(decryptor.release());
- if (memcmp(check, check+BLOCKSIZE, BLOCKSIZE))
+ if (!VerifyBufsEqual(check, check+BLOCKSIZE, BLOCKSIZE))
{
m_state = KEY_BAD;
if (m_throwException)
diff --git a/factory.h b/factory.h
index 482057d..ef5a59e 100644
--- a/factory.h
+++ b/factory.h
@@ -123,6 +123,13 @@ void RegisterSymmetricCipherDefaultFactories(const char *name=NULL, SchemeClass
RegisterDefaultFactoryFor<SymmetricCipher, CPP_TYPENAME SchemeClass::Decryption, DECRYPTION>((const char *)name);
}
+template <class SchemeClass>
+void RegisterAuthenticatedSymmetricCipherDefaultFactories(const char *name=NULL, SchemeClass *dummy=NULL)
+{
+ RegisterDefaultFactoryFor<AuthenticatedSymmetricCipher, CPP_TYPENAME SchemeClass::Encryption, ENCRYPTION>((const char *)name);
+ RegisterDefaultFactoryFor<AuthenticatedSymmetricCipher, CPP_TYPENAME SchemeClass::Decryption, DECRYPTION>((const char *)name);
+}
+
NAMESPACE_END
#endif
diff --git a/filters.cpp b/filters.cpp
index 28b6929..e9ca428 100644
--- a/filters.cpp
+++ b/filters.cpp
@@ -103,7 +103,7 @@ size_t Filter::OutputModifiable(int outputSite, byte *inString, size_t length, i
{
if (messageEnd)
messageEnd--;
- size_t result = AttachedTransformation()->PutModifiable2(inString, length, messageEnd, blocking);
+ size_t result = AttachedTransformation()->ChannelPutModifiable2(channel, inString, length, messageEnd, blocking);
m_continueAt = result ? outputSite : 0;
return result;
}
@@ -112,7 +112,7 @@ size_t Filter::Output(int outputSite, const byte *inString, size_t length, int m
{
if (messageEnd)
messageEnd--;
- size_t result = AttachedTransformation()->Put2(inString, length, messageEnd, blocking);
+ size_t result = AttachedTransformation()->ChannelPut2(channel, inString, length, messageEnd, blocking);
m_continueAt = result ? outputSite : 0;
return result;
}
@@ -551,25 +551,30 @@ size_t StreamTransformationFilter::LastBlockSize(StreamTransformation &c, BlockP
}
StreamTransformationFilter::StreamTransformationFilter(StreamTransformation &c, BufferedTransformation *attachment, BlockPaddingScheme padding)
- : FilterWithBufferedInput(0, c.MandatoryBlockSize(), LastBlockSize(c, padding), attachment)
+ : FilterWithBufferedInput(attachment)
, m_cipher(c)
{
assert(c.MinLastBlockSize() == 0 || c.MinLastBlockSize() > c.MandatoryBlockSize());
- bool isBlockCipher = (c.MandatoryBlockSize() > 1 && c.MinLastBlockSize() == 0);
+ IsolatedInitialize(MakeParameters(Name::BlockPaddingScheme(), padding));
+}
+
+void StreamTransformationFilter::InitializeDerivedAndReturnNewSizes(const NameValuePairs &parameters, size_t &firstSize, size_t &blockSize, size_t &lastSize)
+{
+ BlockPaddingScheme padding = parameters.GetValueWithDefault(Name::BlockPaddingScheme(), DEFAULT_PADDING);
+ bool isBlockCipher = (m_cipher.MandatoryBlockSize() > 1 && m_cipher.MinLastBlockSize() == 0);
if (padding == DEFAULT_PADDING)
- {
- if (isBlockCipher)
- m_padding = PKCS_PADDING;
- else
- m_padding = NO_PADDING;
- }
+ m_padding = isBlockCipher ? PKCS_PADDING : NO_PADDING;
else
m_padding = padding;
if (!isBlockCipher && (m_padding == PKCS_PADDING || m_padding == ONE_AND_ZEROS_PADDING))
- throw InvalidArgument("StreamTransformationFilter: PKCS_PADDING and ONE_AND_ZEROS_PADDING cannot be used with " + c.AlgorithmName());
+ throw InvalidArgument("StreamTransformationFilter: PKCS_PADDING and ONE_AND_ZEROS_PADDING cannot be used with " + m_cipher.AlgorithmName());
+
+ firstSize = 0;
+ blockSize = m_cipher.MandatoryBlockSize();
+ lastSize = LastBlockSize(m_cipher, m_padding);
}
void StreamTransformationFilter::FirstPut(const byte *inString)
@@ -705,59 +710,63 @@ void StreamTransformationFilter::LastPut(const byte *inString, size_t length)
// *************************************************************
+HashFilter::HashFilter(HashTransformation &hm, BufferedTransformation *attachment, bool putMessage, int truncatedDigestSize, const std::string &messagePutChannel, const std::string &hashPutChannel)
+ : m_hashModule(hm), m_putMessage(putMessage), m_messagePutChannel(messagePutChannel), m_hashPutChannel(hashPutChannel)
+{
+ m_digestSize = truncatedDigestSize < 0 ? m_hashModule.DigestSize() : truncatedDigestSize;
+ Detach(attachment);
+}
+
void HashFilter::IsolatedInitialize(const NameValuePairs &parameters)
{
m_putMessage = parameters.GetValueWithDefault(Name::PutMessage(), false);
- m_truncatedDigestSize = parameters.GetIntValueWithDefault(Name::TruncatedDigestSize(), -1);
- m_hashModule.Restart();
+ int s = parameters.GetIntValueWithDefault(Name::TruncatedDigestSize(), -1);
+ m_digestSize = s < 0 ? m_hashModule.DigestSize() : s;
}
size_t HashFilter::Put2(const byte *inString, size_t length, int messageEnd, bool blocking)
{
FILTER_BEGIN;
if (m_putMessage)
- FILTER_OUTPUT(1, inString, length, 0);
+ FILTER_OUTPUT3(1, 0, inString, length, 0, m_messagePutChannel);
m_hashModule.Update(inString, length);
if (messageEnd)
{
{
size_t size;
- m_digestSize = m_hashModule.DigestSize();
- if (m_truncatedDigestSize >= 0 && (unsigned int)m_truncatedDigestSize < m_digestSize)
- m_digestSize = m_truncatedDigestSize;
- m_space = HelpCreatePutSpace(*AttachedTransformation(), NULL_CHANNEL, m_digestSize, m_digestSize, size = m_digestSize);
+ m_space = HelpCreatePutSpace(*AttachedTransformation(), m_hashPutChannel, m_digestSize, m_digestSize, size = m_digestSize);
m_hashModule.TruncatedFinal(m_space, m_digestSize);
}
- FILTER_OUTPUT(2, m_space, m_digestSize, messageEnd);
+ FILTER_OUTPUT3(2, 0, m_space, m_digestSize, messageEnd, m_hashPutChannel);
}
FILTER_END_NO_MESSAGE_END;
}
// *************************************************************
-HashVerificationFilter::HashVerificationFilter(HashTransformation &hm, BufferedTransformation *attachment, word32 flags)
+HashVerificationFilter::HashVerificationFilter(HashTransformation &hm, BufferedTransformation *attachment, word32 flags, int truncatedDigestSize)
: FilterWithBufferedInput(attachment)
, m_hashModule(hm)
{
- IsolatedInitialize(MakeParameters(Name::HashVerificationFilterFlags(), flags));
+ IsolatedInitialize(MakeParameters(Name::HashVerificationFilterFlags(), flags)(Name::TruncatedDigestSize(), truncatedDigestSize));
}
void HashVerificationFilter::InitializeDerivedAndReturnNewSizes(const NameValuePairs &parameters, size_t &firstSize, size_t &blockSize, size_t &lastSize)
{
m_flags = parameters.GetValueWithDefault(Name::HashVerificationFilterFlags(), (word32)DEFAULT_FLAGS);
- m_hashModule.Restart();
- size_t size = m_hashModule.DigestSize();
+ int s = parameters.GetIntValueWithDefault(Name::TruncatedDigestSize(), -1);
+ m_digestSize = s < 0 ? m_hashModule.DigestSize() : s;
m_verified = false;
- firstSize = m_flags & HASH_AT_BEGIN ? size : 0;
+ firstSize = m_flags & HASH_AT_BEGIN ? m_digestSize : 0;
blockSize = 1;
- lastSize = m_flags & HASH_AT_BEGIN ? 0 : size;
+ lastSize = m_flags & HASH_AT_BEGIN ? 0 : m_digestSize;
}
void HashVerificationFilter::FirstPut(const byte *inString)
{
if (m_flags & HASH_AT_BEGIN)
{
- m_expectedHash.New(m_hashModule.DigestSize());
+ m_expectedHash.New(m_digestSize);
memcpy(m_expectedHash, inString, m_expectedHash.size());
if (m_flags & PUT_HASH)
AttachedTransformation()->Put(inString, m_expectedHash.size());
@@ -776,11 +785,11 @@ void HashVerificationFilter::LastPut(const byte *inString, size_t length)
if (m_flags & HASH_AT_BEGIN)
{
assert(length == 0);
- m_verified = m_hashModule.Verify(m_expectedHash);
+ m_verified = m_hashModule.TruncatedVerify(m_expectedHash, m_digestSize);
}
else
{
- m_verified = (length==m_hashModule.DigestSize() && m_hashModule.Verify(inString));
+ m_verified = (length==m_digestSize && m_hashModule.TruncatedVerify(inString, length));
if (m_flags & PUT_HASH)
AttachedTransformation()->Put(inString, length);
}
@@ -794,6 +803,111 @@ void HashVerificationFilter::LastPut(const byte *inString, size_t length)
// *************************************************************
+AuthenticatedEncryptionFilter::AuthenticatedEncryptionFilter(AuthenticatedSymmetricCipher &c, BufferedTransformation *attachment,
+ BlockPaddingScheme padding, bool putMessage, int truncatedDigestSize, const std::string &macChannel)
+ : StreamTransformationFilter(c, attachment, padding)
+ , m_hf(c, new OutputProxy(*this, false), putMessage, truncatedDigestSize, "AAD", macChannel)
+{
+ assert(c.IsForwardTransformation());
+}
+
+void AuthenticatedEncryptionFilter::IsolatedInitialize(const NameValuePairs &parameters)
+{
+ m_hf.IsolatedInitialize(parameters);
+ StreamTransformationFilter::IsolatedInitialize(parameters);
+}
+
+byte * AuthenticatedEncryptionFilter::ChannelCreatePutSpace(const std::string &channel, size_t &size)
+{
+ if (channel.empty())
+ return StreamTransformationFilter::CreatePutSpace(size);
+
+ if (channel == "AAD")
+ return m_hf.CreatePutSpace(size);
+
+ throw InvalidChannelName("AuthenticatedEncryptionFilter", channel);
+}
+
+size_t AuthenticatedEncryptionFilter::ChannelPut2(const std::string &channel, const byte *begin, size_t length, int messageEnd, bool blocking)
+{
+ if (channel.empty())
+ return StreamTransformationFilter::Put2(begin, length, messageEnd, blocking);
+
+ if (channel == "AAD")
+ return m_hf.Put2(begin, length, 0, blocking);
+
+ throw InvalidChannelName("AuthenticatedEncryptionFilter", channel);
+}
+
+void AuthenticatedEncryptionFilter::LastPut(const byte *inString, size_t length)
+{
+ StreamTransformationFilter::LastPut(inString, length);
+ m_hf.MessageEnd();
+}
+
+// *************************************************************
+
+AuthenticatedDecryptionFilter::AuthenticatedDecryptionFilter(AuthenticatedSymmetricCipher &c, BufferedTransformation *attachment, BlockPaddingScheme padding, word32 flags, int truncatedDigestSize)
+ : FilterWithBufferedInput(attachment)
+ , m_hashVerifier(c, new OutputProxy(*this, false))
+ , m_streamFilter(c, new OutputProxy(*this, false))
+{
+ assert(!c.IsForwardTransformation() || c.IsSelfInverting());
+ IsolatedInitialize(MakeParameters(Name::BlockPaddingScheme(), padding)(Name::AuthenticatedDecryptionFilterFlags(), flags)(Name::TruncatedDigestSize(), truncatedDigestSize));
+}
+
+void AuthenticatedDecryptionFilter::InitializeDerivedAndReturnNewSizes(const NameValuePairs &parameters, size_t &firstSize, size_t &blockSize, size_t &lastSize)
+{
+ word32 flags = parameters.GetValueWithDefault(Name::AuthenticatedDecryptionFilterFlags(), (word32)DEFAULT_FLAGS);
+
+ m_hashVerifier.Initialize(CombinedNameValuePairs(parameters, MakeParameters(Name::HashVerificationFilterFlags(), flags)));
+ m_streamFilter.Initialize(parameters);
+
+ firstSize = m_hashVerifier.m_firstSize;
+ blockSize = 1;
+ lastSize = m_hashVerifier.m_lastSize;
+}
+
+byte * AuthenticatedDecryptionFilter::ChannelCreatePutSpace(const std::string &channel, size_t &size)
+{
+ if (channel.empty())
+ return m_streamFilter.CreatePutSpace(size);
+
+ if (channel == "AAD")
+ return m_hashVerifier.CreatePutSpace(size);
+
+ throw InvalidChannelName("AuthenticatedDecryptionFilter", channel);
+}
+
+size_t AuthenticatedDecryptionFilter::ChannelPut2(const std::string &channel, const byte *begin, size_t length, int messageEnd, bool blocking)
+{
+ if (channel.empty())
+ return FilterWithBufferedInput::Put2(begin, length, messageEnd, blocking);
+
+ if (channel == "AAD")
+ return m_hashVerifier.Put2(begin, length, 0, blocking);
+
+ throw InvalidChannelName("AuthenticatedDecryptionFilter", channel);
+}
+
+void AuthenticatedDecryptionFilter::FirstPut(const byte *inString)
+{
+ m_hashVerifier.Put(inString, m_firstSize);
+}
+
+void AuthenticatedDecryptionFilter::NextPutMultiple(const byte *inString, size_t length)
+{
+ m_streamFilter.Put(inString, length);
+}
+
+void AuthenticatedDecryptionFilter::LastPut(const byte *inString, size_t length)
+{
+ m_streamFilter.MessageEnd();
+ m_hashVerifier.PutMessageEnd(inString, length);
+}
+
+// *************************************************************
+
void SignerFilter::IsolatedInitialize(const NameValuePairs &parameters)
{
m_putMessage = parameters.GetValueWithDefault(Name::PutMessage(), false);
diff --git a/filters.h b/filters.h
index ce6c734..a03cebf 100644
--- a/filters.h
+++ b/filters.h
@@ -190,7 +190,7 @@ protected:
virtual void LastPut(const byte *inString, size_t length) =0;
virtual void FlushDerived() {}
-private:
+protected:
size_t PutMaybeModifiable(byte *begin, size_t length, int messageEnd, bool blocking, bool modifiable);
void NextPutMaybeModifiable(byte *inString, size_t length, bool modifiable)
{
@@ -251,23 +251,29 @@ protected:
ByteQueue m_inQueue;
};
+struct BlockPaddingSchemeDef
+{
+ enum BlockPaddingScheme {NO_PADDING, ZEROS_PADDING, PKCS_PADDING, ONE_AND_ZEROS_PADDING, DEFAULT_PADDING};
+};
+
//! Filter Wrapper for StreamTransformation, optionally handling padding/unpadding when needed
-class CRYPTOPP_DLL StreamTransformationFilter : public FilterWithBufferedInput, private FilterPutSpaceHelper
+class CRYPTOPP_DLL StreamTransformationFilter : public FilterWithBufferedInput, public BlockPaddingSchemeDef, private FilterPutSpaceHelper
{
public:
- enum BlockPaddingScheme {NO_PADDING, ZEROS_PADDING, PKCS_PADDING, ONE_AND_ZEROS_PADDING, DEFAULT_PADDING};
/*! DEFAULT_PADDING means PKCS_PADDING if c.MandatoryBlockSize() > 1 && c.MinLastBlockSize() == 0 (e.g. ECB or CBC mode),
otherwise NO_PADDING (OFB, CFB, CTR, CBC-CTS modes).
See http://www.weidai.com/scan-mirror/csp.html for details of the padding schemes. */
StreamTransformationFilter(StreamTransformation &c, BufferedTransformation *attachment = NULL, BlockPaddingScheme padding = DEFAULT_PADDING);
+ std::string AlgorithmName() const {return m_cipher.AlgorithmName();}
+
+protected:
+ void InitializeDerivedAndReturnNewSizes(const NameValuePairs &parameters, size_t &firstSize, size_t &blockSize, size_t &lastSize);
void FirstPut(const byte *inString);
void NextPutMultiple(const byte *inString, size_t length);
void NextPutModifiable(byte *inString, size_t length);
void LastPut(const byte *inString, size_t length);
-// byte * CreatePutSpace(size_t &size);
-protected:
static size_t LastBlockSize(StreamTransformation &c, BlockPaddingScheme padding);
StreamTransformation &m_cipher;
@@ -283,22 +289,19 @@ typedef StreamTransformationFilter StreamCipherFilter;
class CRYPTOPP_DLL HashFilter : public Bufferless<Filter>, private FilterPutSpaceHelper
{
public:
- HashFilter(HashTransformation &hm, BufferedTransformation *attachment = NULL, bool putMessage=false, int truncatedDigestSize=-1)
- : m_hashModule(hm), m_putMessage(putMessage), m_truncatedDigestSize(truncatedDigestSize) {Detach(attachment);}
+ HashFilter(HashTransformation &hm, BufferedTransformation *attachment = NULL, bool putMessage=false, int truncatedDigestSize=-1, const std::string &messagePutChannel=NULL_CHANNEL, const std::string &hashPutChannel=NULL_CHANNEL);
std::string AlgorithmName() const {return m_hashModule.AlgorithmName();}
-
void IsolatedInitialize(const NameValuePairs &parameters);
size_t Put2(const byte *begin, size_t length, int messageEnd, bool blocking);
-
byte * CreatePutSpace(size_t &size) {return m_hashModule.CreateUpdateSpace(size);}
private:
HashTransformation &m_hashModule;
bool m_putMessage;
- int m_truncatedDigestSize;
- byte *m_space;
unsigned int m_digestSize;
+ byte *m_space;
+ std::string m_messagePutChannel, m_hashPutChannel;
};
//! Filter Wrapper for HashTransformation
@@ -309,14 +312,13 @@ public:
{
public:
HashVerificationFailed()
- : Exception(DATA_INTEGRITY_CHECK_FAILED, "HashVerifier: message hash not valid") {}
+ : Exception(DATA_INTEGRITY_CHECK_FAILED, "HashVerificationFilter: message hash or MAC not valid") {}
};
enum Flags {HASH_AT_BEGIN=1, PUT_MESSAGE=2, PUT_HASH=4, PUT_RESULT=8, THROW_EXCEPTION=16, DEFAULT_FLAGS = HASH_AT_BEGIN | PUT_RESULT};
- HashVerificationFilter(HashTransformation &hm, BufferedTransformation *attachment = NULL, word32 flags = DEFAULT_FLAGS);
+ HashVerificationFilter(HashTransformation &hm, BufferedTransformation *attachment = NULL, word32 flags = DEFAULT_FLAGS, int truncatedDigestSize=-1);
std::string AlgorithmName() const {return m_hashModule.AlgorithmName();}
-
bool GetLastResult() const {return m_verified;}
protected:
@@ -326,17 +328,59 @@ protected:
void LastPut(const byte *inString, size_t length);
private:
- static inline unsigned int FirstSize(word32 flags, HashTransformation &hm) {return flags & HASH_AT_BEGIN ? hm.DigestSize() : 0;}
- static inline unsigned int LastSize(word32 flags, HashTransformation &hm) {return flags & HASH_AT_BEGIN ? 0 : hm.DigestSize();}
+ friend class AuthenticatedDecryptionFilter;
HashTransformation &m_hashModule;
word32 m_flags;
- SecByteBlock m_expectedHash;
+ unsigned int m_digestSize;
bool m_verified;
+ SecByteBlock m_expectedHash;
};
typedef HashVerificationFilter HashVerifier; // for backwards compatibility
+//! Filter wrapper for encrypting with AuthenticatedSymmetricCipher, optionally handling padding/unpadding when needed
+/*! Additional authenticated data should be given in channel "AAD". If putMessage is true, AAD will be Put() to the attached BufferedTransformation in channel "AAD". */
+class CRYPTOPP_DLL AuthenticatedEncryptionFilter : public StreamTransformationFilter
+{
+public:
+ /*! See StreamTransformationFilter for documentation on BlockPaddingScheme */
+ AuthenticatedEncryptionFilter(AuthenticatedSymmetricCipher &c, BufferedTransformation *attachment = NULL, BlockPaddingScheme padding = DEFAULT_PADDING, bool putMessage=false, int truncatedDigestSize=-1, const std::string &macChannel=NULL_CHANNEL);
+
+ void IsolatedInitialize(const NameValuePairs &parameters);
+ byte * ChannelCreatePutSpace(const std::string &channel, size_t &size);
+ size_t ChannelPut2(const std::string &channel, const byte *begin, size_t length, int messageEnd, bool blocking);
+ void LastPut(const byte *inString, size_t length);
+
+protected:
+ HashFilter m_hf;
+};
+
+//! Filter wrapper for decrypting with AuthenticatedSymmetricCipher, optionally handling padding/unpadding when needed
+/*! Additional authenticated data should be given in channel "AAD". */
+class CRYPTOPP_DLL AuthenticatedDecryptionFilter : public FilterWithBufferedInput, public BlockPaddingSchemeDef
+{
+public:
+ enum Flags {MAC_AT_BEGIN=1, THROW_EXCEPTION=16, DEFAULT_FLAGS = THROW_EXCEPTION};
+
+ /*! See StreamTransformationFilter for documentation on BlockPaddingScheme */
+ AuthenticatedDecryptionFilter(AuthenticatedSymmetricCipher &c, BufferedTransformation *attachment = NULL, BlockPaddingScheme padding = DEFAULT_PADDING, word32 flags = DEFAULT_FLAGS, int truncatedDigestSize=-1);
+
+ std::string AlgorithmName() const {return m_hashVerifier.AlgorithmName();}
+ byte * ChannelCreatePutSpace(const std::string &channel, size_t &size);
+ size_t ChannelPut2(const std::string &channel, const byte *begin, size_t length, int messageEnd, bool blocking);
+ bool GetLastResult() const {return m_hashVerifier.GetLastResult();}
+
+protected:
+ void InitializeDerivedAndReturnNewSizes(const NameValuePairs &parameters, size_t &firstSize, size_t &blockSize, size_t &lastSize);
+ void FirstPut(const byte *inString);
+ void NextPutMultiple(const byte *inString, size_t length);
+ void LastPut(const byte *inString, size_t length);
+
+ HashVerificationFilter m_hashVerifier;
+ StreamTransformationFilter m_streamFilter;
+};
+
//! Filter Wrapper for PK_Signer
class CRYPTOPP_DLL SignerFilter : public Unflushable<Filter>
{
diff --git a/fipstest.cpp b/fipstest.cpp
index 3298a40..9a6c560 100644
--- a/fipstest.cpp
+++ b/fipstest.cpp
@@ -399,7 +399,7 @@ bool IntegrityCheckModule(const char *moduleFilename, const byte *expectedModule
#ifdef CRYPTOPP_WIN32_AVAILABLE
// if that fails (could be caused by debug breakpoints or DLL base relocation modifying image in memory),
// hash from disk instead
- if (memcmp(expectedModuleMac, actualMac, macSize) != 0)
+ if (!VerifyBufsEqual(expectedModuleMac, actualMac, macSize))
{
OutputDebugString("In memory integrity check failed. This may be caused by debug breakpoints or DLL relocation.\n");
moduleStream.clear();
@@ -414,7 +414,7 @@ bool IntegrityCheckModule(const char *moduleFilename, const byte *expectedModule
}
#endif
- if (memcmp(expectedModuleMac, actualMac, macSize) == 0)
+ if (VerifyBufsEqual(expectedModuleMac, actualMac, macSize))
return true;
#ifdef CRYPTOPP_WIN32_AVAILABLE
@@ -499,7 +499,6 @@ void DoPowerUpSelfTest(const char *moduleFilename, const byte *expectedModuleMac
"abc",
"ba7816bf8f01cfea414140de5dae2223b00361a396177a9cb410ff61f20015ad");
-#ifdef WORD64_AVAILABLE
SecureHashKnownAnswerTest<SHA384>(
"abc",
"cb00753f45a35e8bb5a03d699ac65007272c32ab0eded1631a8b605a43ff5bed8086072ba1e7cc2358baeca134c825a7");
@@ -507,7 +506,6 @@ void DoPowerUpSelfTest(const char *moduleFilename, const byte *expectedModuleMac
SecureHashKnownAnswerTest<SHA512>(
"abc",
"ddaf35a193617abacc417349ae20413112e6fa4e89a97ea20a9eeee64b55d39a2192992a274fc1a836ba3c23a3feebbd454d4423643ce80e2a9ac94fa54ca49f");
-#endif
MAC_KnownAnswerTest<HMAC<SHA1> >(
"303132333435363738393a3b3c3d3e3f40414243",
diff --git a/fltrimpl.h b/fltrimpl.h
index d78bb6b..40d70ff 100644
--- a/fltrimpl.h
+++ b/fltrimpl.h
@@ -25,14 +25,17 @@
FILTER_END_NO_MESSAGE_END
*/
-#define FILTER_OUTPUT2(site, statement, output, length, messageEnd) \
+#define FILTER_OUTPUT3(site, statement, output, length, messageEnd, channel) \
{\
case site: \
statement; \
- if (Output(site, output, length, messageEnd, blocking)) \
+ if (Output(site, output, length, messageEnd, blocking, channel)) \
return STDMAX(size_t(1), length-m_inputPosition);\
}
+#define FILTER_OUTPUT2(site, statement, output, length, messageEnd) \
+ FILTER_OUTPUT3(site, statement, output, length, messageEnd, NULL_CHANNEL)
+
#define FILTER_OUTPUT(site, output, length, messageEnd) \
FILTER_OUTPUT2(site, 0, output, length, messageEnd)
diff --git a/gcm.cpp b/gcm.cpp
new file mode 100644
index 0000000..4d02ef3
--- /dev/null
+++ b/gcm.cpp
@@ -0,0 +1,735 @@
+// gcm.cpp - written and placed in the public domain by Wei Dai
+
+// use "cl /EP /P /DCRYPTOPP_GENERATE_X64_MASM gcm.cpp" to generate MASM code
+
+#include "pch.h"
+
+#ifndef CRYPTOPP_IMPORTS
+#ifndef CRYPTOPP_GENERATE_X64_MASM
+
+#include "gcm.h"
+#include "cpu.h"
+
+NAMESPACE_BEGIN(CryptoPP)
+
+word16 GCM_Base::s_reductionTable[256];
+bool GCM_Base::s_reductionTableInitialized = false;
+
+void GCM_Base::GCTR::IncrementCounterBy256()
+{
+ IncrementCounterByOne(m_counterArray+BlockSize()-4, 3);
+}
+
+#if 0
+// preserved for testing
+void gcm_gf_mult(const unsigned char *a, const unsigned char *b, unsigned char *c)
+{
+ word64 Z0=0, Z1=0, V0, V1;
+
+ typedef BlockGetAndPut<word64, BigEndian> Block;
+ Block::Get(a)(V0)(V1);
+
+ for (int i=0; i<16; i++)
+ {
+ for (int j=0x80; j!=0; j>>=1)
+ {
+ int x = b[i] & j;
+ Z0 ^= x ? V0 : 0;
+ Z1 ^= x ? V1 : 0;
+ x = (int)V1 & 1;
+ V1 = (V1>>1) | (V0<<63);
+ V0 = (V0>>1) ^ (x ? W64LIT(0xe1) << 56 : 0);
+ }
+ }
+ Block::Put(NULL, c)(Z0)(Z1);
+}
+#endif
+
+void GCM_Base::SetKeyWithoutResync(const byte *userKey, size_t keylength, const NameValuePairs &params)
+{
+ BlockCipher &blockCipher = AccessBlockCipher();
+ blockCipher.SetKey(userKey, keylength, params);
+
+ if (blockCipher.BlockSize() != REQUIRED_BLOCKSIZE)
+ throw InvalidArgument(AlgorithmName() + ": block size of underlying block cipher is not 16");
+
+ int tableSize;
+ if (params.GetIntValue(Name::TableSize(), tableSize))
+ tableSize = (tableSize >= 64*1024) ? 64*1024 : 2*1024;
+ else
+ tableSize = (GetTablesOption() == GCM_64K_Tables) ? 64*1024 : 2*1024;
+
+ m_buffer.resize(3*REQUIRED_BLOCKSIZE + tableSize);
+ byte *hashKey = HashKey();
+ memset(hashKey, 0, REQUIRED_BLOCKSIZE);
+ blockCipher.ProcessBlock(hashKey);
+
+ byte *table = MulTable();
+ int i, j, k;
+ word64 V0, V1;
+
+ typedef BlockGetAndPut<word64, BigEndian> Block;
+ Block::Get(hashKey)(V0)(V1);
+
+ if (tableSize == 64*1024)
+ {
+ for (i=0; i<128; i++)
+ {
+ k = i%8;
+ Block::Put(NULL, table+(i/8)*256*16+(size_t(1)<<(11-k)))(V0)(V1);
+
+ int x = (int)V1 & 1;
+ V1 = (V1>>1) | (V0<<63);
+ V0 = (V0>>1) ^ (x ? W64LIT(0xe1) << 56 : 0);
+ }
+
+ for (i=0; i<16; i++)
+ {
+ memset(table+i*256*16, 0, 16);
+ for (j=2; j<=0x80; j*=2)
+ for (k=1; k<j; k++)
+ xorbuf(table+i*256*16+(j+k)*16, table+i*256*16+j*16, table+i*256*16+k*16, 16);
+ }
+ }
+ else
+ {
+ if (!s_reductionTableInitialized)
+ {
+ s_reductionTable[0] = 0;
+ word16 x = 0x01c2;
+ s_reductionTable[1] = ConditionalByteReverse(BIG_ENDIAN_ORDER, x);
+ for (int i=2; i<=0x80; i*=2)
+ {
+ x <<= 1;
+ s_reductionTable[i] = ConditionalByteReverse(BIG_ENDIAN_ORDER, x);
+ for (int j=1; j<i; j++)
+ s_reductionTable[i+j] = s_reductionTable[i] ^ s_reductionTable[j];
+ }
+ s_reductionTableInitialized = true;
+ }
+
+ for (i=0; i<128-24; i++)
+ {
+ k = i%32;
+ if (k < 4)
+ Block::Put(NULL, table+1024+(i/32)*256+(size_t(1)<<(7-k)))(V0)(V1);
+ else if (k < 8)
+ Block::Put(NULL, table+(i/32)*256+(size_t(1)<<(11-k)))(V0)(V1);
+
+ int x = (int)V1 & 1;
+ V1 = (V1>>1) | (V0<<63);
+ V0 = (V0>>1) ^ (x ? W64LIT(0xe1) << 56 : 0);
+ }
+
+ for (i=0; i<4; i++)
+ {
+ memset(table+i*256, 0, 16);
+ memset(table+1024+i*256, 0, 16);
+ for (j=2; j<=8; j*=2)
+ for (k=1; k<j; k++)
+ {
+ xorbuf(table+i*256+(j+k)*16, table+i*256+j*16, table+i*256+k*16, 16);
+ xorbuf(table+1024+i*256+(j+k)*16, table+1024+i*256+j*16, table+1024+i*256+k*16, 16);
+ }
+ }
+ }
+}
+
+void GCM_Base::Resync(const byte *iv, size_t len)
+{
+ BlockCipher &cipher = AccessBlockCipher();
+ byte *hashBuffer = HashBuffer();
+
+ if (len == 12)
+ {
+ memcpy(hashBuffer, iv, len);
+ memset(hashBuffer+len, 0, 3);
+ hashBuffer[len+3] = 1;
+ }
+ else
+ {
+ size_t origLen = len;
+ memset(hashBuffer, 0, HASH_BLOCKSIZE);
+
+ if (len >= HASH_BLOCKSIZE)
+ {
+ len = GCM_Base::AuthenticateBlocks(iv, len);
+ iv += (origLen - len);
+ }
+
+ if (len > 0)
+ {
+ memcpy(m_buffer, iv, len);
+ memset(m_buffer+len, 0, HASH_BLOCKSIZE-len);
+ GCM_Base::AuthenticateBlocks(m_buffer, HASH_BLOCKSIZE);
+ }
+
+ PutBlock<word64, BigEndian, true>::PutBlock(NULL, m_buffer)(0)(origLen*8);
+ GCM_Base::AuthenticateBlocks(m_buffer, HASH_BLOCKSIZE);
+ }
+
+ if (m_state >= State_IVSet)
+ m_ctr.Resynchronize(hashBuffer, REQUIRED_BLOCKSIZE);
+ else
+ m_ctr.SetCipherWithIV(cipher, hashBuffer);
+
+ m_ctr.Seek(HASH_BLOCKSIZE);
+
+ memset(hashBuffer, 0, HASH_BLOCKSIZE);
+}
+
+unsigned int GCM_Base::OptimalDataAlignment() const
+{
+ return HasSSE2() ? 16 : GetBlockCipher().OptimalDataAlignment();
+}
+
+#pragma warning(disable: 4731) // frame pointer register 'ebp' modified by inline assembly code
+
+#endif // #ifndef CRYPTOPP_GENERATE_X64_MASM
+
+#ifdef CRYPTOPP_X64_MASM_AVAILABLE
+extern "C" {
+void GCM_AuthenticateBlocks_2K(const byte *data, size_t blocks, word64 *hashBuffer, const word16 *reductionTable);
+void GCM_AuthenticateBlocks_64K(const byte *data, size_t blocks, word64 *hashBuffer);
+}
+#endif
+
+#ifndef CRYPTOPP_GENERATE_X64_MASM
+
+size_t GCM_Base::AuthenticateBlocks(const byte *data, size_t len)
+{
+ typedef BlockGetAndPut<word64, NativeByteOrder, false, true> Block;
+ word64 *hashBuffer = (word64 *)HashBuffer();
+
+ switch (2*(m_buffer.size()>=64*1024)
+#if CRYPTOPP_BOOL_SSE2_ASM_AVAILABLE || defined(CRYPTOPP_X64_MASM_AVAILABLE)
+ + HasSSE2()
+#endif
+ )
+ {
+ case 0: // non-SSE2 and 2K tables
+ {
+ byte *table = MulTable();
+ word64 x0 = hashBuffer[0], x1 = hashBuffer[1];
+
+ do
+ {
+ word64 y0, y1, a0, a1, b0, b1, c0, c1, d0, d1;
+ Block::Get(data)(y0)(y1);
+ x0 ^= y0;
+ x1 ^= y1;
+
+ data += HASH_BLOCKSIZE;
+ len -= HASH_BLOCKSIZE;
+
+ #define READ_TABLE_WORD64_COMMON(a, b, c, d) *(word64 *)(table+(a*1024)+(b*256)+c+d*8)
+
+ #ifdef IS_LITTLE_ENDIAN
+ #if CRYPTOPP_BOOL_SLOW_WORD64
+ word32 z0 = (word32)x0;
+ word32 z1 = (word32)(x0>>32);
+ word32 z2 = (word32)x1;
+ word32 z3 = (word32)(x1>>32);
+ #define READ_TABLE_WORD64(a, b, c, d, e) READ_TABLE_WORD64_COMMON((d%2), c, (d?(z##c>>((d?d-1:0)*4))&0xf0:(z##c&0xf)<<4), e)
+ #else
+ #define READ_TABLE_WORD64(a, b, c, d, e) READ_TABLE_WORD64_COMMON((d%2), c, ((d+8*b)?(x##a>>(((d+8*b)?(d+8*b)-1:1)*4))&0xf0:(x##a&0xf)<<4), e)
+ #endif
+ #define GF_MOST_SIG_8BITS(a) (a##1 >> 7*8)
+ #define GF_SHIFT_8(a) a##1 = (a##1 << 8) ^ (a##0 >> 7*8); a##0 <<= 8;
+ #else
+ #define READ_TABLE_WORD64(a, b, c, d, e) READ_TABLE_WORD64_COMMON((1-d%2), c, ((15-d-8*b)?(x##a>>(((15-d-8*b)?(15-d-8*b)-1:0)*4))&0xf0:(x##a&0xf)<<4), e)
+ #define GF_MOST_SIG_8BITS(a) (a##1 & 0xff)
+ #define GF_SHIFT_8(a) a##1 = (a##1 >> 8) ^ (a##0 << 7*8); a##0 >>= 8;
+ #endif
+
+ #define GF_MUL_32BY128(op, a, b, c) \
+ a0 op READ_TABLE_WORD64(a, b, c, 0, 0) ^ READ_TABLE_WORD64(a, b, c, 1, 0);\
+ a1 op READ_TABLE_WORD64(a, b, c, 0, 1) ^ READ_TABLE_WORD64(a, b, c, 1, 1);\
+ b0 op READ_TABLE_WORD64(a, b, c, 2, 0) ^ READ_TABLE_WORD64(a, b, c, 3, 0);\
+ b1 op READ_TABLE_WORD64(a, b, c, 2, 1) ^ READ_TABLE_WORD64(a, b, c, 3, 1);\
+ c0 op READ_TABLE_WORD64(a, b, c, 4, 0) ^ READ_TABLE_WORD64(a, b, c, 5, 0);\
+ c1 op READ_TABLE_WORD64(a, b, c, 4, 1) ^ READ_TABLE_WORD64(a, b, c, 5, 1);\
+ d0 op READ_TABLE_WORD64(a, b, c, 6, 0) ^ READ_TABLE_WORD64(a, b, c, 7, 0);\
+ d1 op READ_TABLE_WORD64(a, b, c, 6, 1) ^ READ_TABLE_WORD64(a, b, c, 7, 1);\
+
+ GF_MUL_32BY128(=, 0, 0, 0)
+ GF_MUL_32BY128(^=, 0, 1, 1)
+ GF_MUL_32BY128(^=, 1, 0, 2)
+ GF_MUL_32BY128(^=, 1, 1, 3)
+
+ word32 r = (word32)s_reductionTable[GF_MOST_SIG_8BITS(d)] << 16;
+ GF_SHIFT_8(d)
+ c0 ^= d0; c1 ^= d1;
+ r ^= (word32)s_reductionTable[GF_MOST_SIG_8BITS(c)] << 8;
+ GF_SHIFT_8(c)
+ b0 ^= c0; b1 ^= c1;
+ r ^= s_reductionTable[GF_MOST_SIG_8BITS(b)];
+ GF_SHIFT_8(b)
+ a0 ^= b0; a1 ^= b1;
+ a0 ^= ConditionalByteReverse<word64>(LITTLE_ENDIAN_ORDER, r);
+ x0 = a0; x1 = a1;
+ }
+ while (len >= HASH_BLOCKSIZE);
+
+ hashBuffer[0] = x0; hashBuffer[1] = x1;
+ return len;
+ }
+
+ case 2: // non-SSE2 and 64K tables
+ {
+ byte *table = MulTable();
+ word64 x0 = hashBuffer[0], x1 = hashBuffer[1];
+
+ do
+ {
+ word64 y0, y1, a0, a1;
+ Block::Get(data)(y0)(y1);
+ x0 ^= y0;
+ x1 ^= y1;
+
+ data += HASH_BLOCKSIZE;
+ len -= HASH_BLOCKSIZE;
+
+ #undef READ_TABLE_WORD64_COMMON
+ #undef READ_TABLE_WORD64
+
+ #define READ_TABLE_WORD64_COMMON(a, c, d) *(word64 *)(table+(a)*256*16+(c)+(d)*8)
+
+ #ifdef IS_LITTLE_ENDIAN
+ #if CRYPTOPP_BOOL_SLOW_WORD64
+ word32 z0 = (word32)x0;
+ word32 z1 = (word32)(x0>>32);
+ word32 z2 = (word32)x1;
+ word32 z3 = (word32)(x1>>32);
+ #define READ_TABLE_WORD64(b, c, d, e) READ_TABLE_WORD64_COMMON(c*4+d, (d?(z##c>>((d?d:1)*8-4))&0xff0:(z##c&0xff)<<4), e)
+ #else
+ #define READ_TABLE_WORD64(b, c, d, e) READ_TABLE_WORD64_COMMON(c*4+d, ((d+4*(c%2))?(x##b>>(((d+4*(c%2))?(d+4*(c%2)):1)*8-4))&0xff0:(x##b&0xff)<<4), e)
+ #endif
+ #else
+ #define READ_TABLE_WORD64(b, c, d, e) READ_TABLE_WORD64_COMMON(c*4+d, ((7-d-4*(c%2))?(x##b>>(((7-d-4*(c%2))?(7-d-4*(c%2)):1)*8-4))&0xff0:(x##b&0xff)<<4), e)
+ #endif
+
+ #define GF_MUL_8BY128(op, b, c, d) \
+ a0 op READ_TABLE_WORD64(b, c, d, 0);\
+ a1 op READ_TABLE_WORD64(b, c, d, 1);\
+
+ GF_MUL_8BY128(=, 0, 0, 0)
+ GF_MUL_8BY128(^=, 0, 0, 1)
+ GF_MUL_8BY128(^=, 0, 0, 2)
+ GF_MUL_8BY128(^=, 0, 0, 3)
+ GF_MUL_8BY128(^=, 0, 1, 0)
+ GF_MUL_8BY128(^=, 0, 1, 1)
+ GF_MUL_8BY128(^=, 0, 1, 2)
+ GF_MUL_8BY128(^=, 0, 1, 3)
+ GF_MUL_8BY128(^=, 1, 2, 0)
+ GF_MUL_8BY128(^=, 1, 2, 1)
+ GF_MUL_8BY128(^=, 1, 2, 2)
+ GF_MUL_8BY128(^=, 1, 2, 3)
+ GF_MUL_8BY128(^=, 1, 3, 0)
+ GF_MUL_8BY128(^=, 1, 3, 1)
+ GF_MUL_8BY128(^=, 1, 3, 2)
+ GF_MUL_8BY128(^=, 1, 3, 3)
+
+ x0 = a0; x1 = a1;
+ }
+ while (len >= HASH_BLOCKSIZE);
+
+ hashBuffer[0] = x0; hashBuffer[1] = x1;
+ return len;
+ }
+#endif // #ifndef CRYPTOPP_GENERATE_X64_MASM
+
+#ifdef CRYPTOPP_X64_MASM_AVAILABLE
+ case 1: // SSE2 and 2K tables
+ GCM_AuthenticateBlocks_2K(data, len/16, hashBuffer, s_reductionTable);
+ return len % 16;
+ case 3: // SSE2 and 64K tables
+ GCM_AuthenticateBlocks_64K(data, len/16, hashBuffer);
+ return len % 16;
+#endif
+
+#if CRYPTOPP_BOOL_SSE2_ASM_AVAILABLE
+ case 1: // SSE2 and 2K tables
+ {
+ #ifdef __GNUC__
+ __asm__ __volatile__
+ (
+ ".intel_syntax noprefix;"
+ #elif defined(CRYPTOPP_GENERATE_X64_MASM)
+ ALIGN 8
+ GCM_AuthenticateBlocks_2K PROC FRAME
+ rex_push_reg rsi
+ push_reg rdi
+ push_reg rbx
+ .endprolog
+ mov rsi, r8
+ mov r11, r9
+ #else
+ AS2( mov WORD_REG(cx), data )
+ AS2( mov WORD_REG(dx), len )
+ AS2( mov WORD_REG(si), hashBuffer )
+ AS2( shr WORD_REG(dx), 4 )
+ #endif
+
+ #if !defined(_MSC_VER) || (_MSC_VER < 1300)
+ AS_PUSH_IF86( bx)
+ #endif
+ AS_PUSH_IF86( bp)
+
+ #ifdef __GNUC__
+ AS2( mov AS_REG_7, WORD_REG(di))
+ #elif CRYPTOPP_BOOL_X86
+ AS2( lea AS_REG_7, s_reductionTable)
+ #endif
+
+ AS2( movdqa xmm0, [WORD_REG(si)] )
+
+ #define MUL_TABLE_0 WORD_REG(si) + 32
+ #define MUL_TABLE_1 WORD_REG(si) + 32 + 1024
+ #define RED_TABLE AS_REG_7
+
+ ASL(0)
+ AS2( movdqu xmm4, [WORD_REG(cx)] )
+ AS2( pxor xmm0, xmm4 )
+
+ AS2( movd ebx, xmm0 )
+ AS2( mov eax, AS_HEX(f0f0f0f0) )
+ AS2( and eax, ebx )
+ AS2( shl ebx, 4 )
+ AS2( and ebx, AS_HEX(f0f0f0f0) )
+ AS2( movzx edi, ah )
+ AS2( movdqa xmm5, XMMWORD_PTR [MUL_TABLE_1 + WORD_REG(di)] )
+ AS2( movzx edi, al )
+ AS2( movdqa xmm4, XMMWORD_PTR [MUL_TABLE_1 + WORD_REG(di)] )
+ AS2( shr eax, 16 )
+ AS2( movzx edi, ah )
+ AS2( movdqa xmm3, XMMWORD_PTR [MUL_TABLE_1 + WORD_REG(di)] )
+ AS2( movzx edi, al )
+ AS2( movdqa xmm2, XMMWORD_PTR [MUL_TABLE_1 + WORD_REG(di)] )
+
+ #define SSE2_MUL_32BITS(i) \
+ AS2( psrldq xmm0, 4 )\
+ AS2( movd eax, xmm0 )\
+ AS2( and eax, AS_HEX(f0f0f0f0) )\
+ AS2( movzx edi, bh )\
+ AS2( pxor xmm5, XMMWORD_PTR [MUL_TABLE_0 + (i-1)*256 + WORD_REG(di)] )\
+ AS2( movzx edi, bl )\
+ AS2( pxor xmm4, XMMWORD_PTR [MUL_TABLE_0 + (i-1)*256 + WORD_REG(di)] )\
+ AS2( shr ebx, 16 )\
+ AS2( movzx edi, bh )\
+ AS2( pxor xmm3, XMMWORD_PTR [MUL_TABLE_0 + (i-1)*256 + WORD_REG(di)] )\
+ AS2( movzx edi, bl )\
+ AS2( pxor xmm2, XMMWORD_PTR [MUL_TABLE_0 + (i-1)*256 + WORD_REG(di)] )\
+ AS2( movd ebx, xmm0 )\
+ AS2( shl ebx, 4 )\
+ AS2( and ebx, AS_HEX(f0f0f0f0) )\
+ AS2( movzx edi, ah )\
+ AS2( pxor xmm5, XMMWORD_PTR [MUL_TABLE_1 + i*256 + WORD_REG(di)] )\
+ AS2( movzx edi, al )\
+ AS2( pxor xmm4, XMMWORD_PTR [MUL_TABLE_1 + i*256 + WORD_REG(di)] )\
+ AS2( shr eax, 16 )\
+ AS2( movzx edi, ah )\
+ AS2( pxor xmm3, XMMWORD_PTR [MUL_TABLE_1 + i*256 + WORD_REG(di)] )\
+ AS2( movzx edi, al )\
+ AS2( pxor xmm2, XMMWORD_PTR [MUL_TABLE_1 + i*256 + WORD_REG(di)] )\
+
+ SSE2_MUL_32BITS(1)
+ SSE2_MUL_32BITS(2)
+ SSE2_MUL_32BITS(3)
+
+ AS2( movzx edi, bh )
+ AS2( pxor xmm5, XMMWORD_PTR [MUL_TABLE_0 + 3*256 + WORD_REG(di)] )
+ AS2( movzx edi, bl )
+ AS2( pxor xmm4, XMMWORD_PTR [MUL_TABLE_0 + 3*256 + WORD_REG(di)] )
+ AS2( shr ebx, 16 )
+ AS2( movzx edi, bh )
+ AS2( pxor xmm3, XMMWORD_PTR [MUL_TABLE_0 + 3*256 + WORD_REG(di)] )
+ AS2( movzx edi, bl )
+ AS2( pxor xmm2, XMMWORD_PTR [MUL_TABLE_0 + 3*256 + WORD_REG(di)] )
+
+ AS2( movdqa xmm0, xmm3 )
+ AS2( pslldq xmm3, 1 )
+ AS2( pxor xmm2, xmm3 )
+ AS2( movdqa xmm1, xmm2 )
+ AS2( pslldq xmm2, 1 )
+ AS2( pxor xmm5, xmm2 )
+
+ AS2( psrldq xmm0, 15 )
+ AS2( movd WORD_REG(di), xmm0 )
+ AS2( movzx eax, WORD PTR [RED_TABLE + WORD_REG(di)*2] )
+ AS2( shl eax, 8 )
+
+ AS2( movdqa xmm0, xmm5 )
+ AS2( pslldq xmm5, 1 )
+ AS2( pxor xmm4, xmm5 )
+
+ AS2( psrldq xmm1, 15 )
+ AS2( movd WORD_REG(di), xmm1 )
+ AS2( xor ax, WORD PTR [RED_TABLE + WORD_REG(di)*2] )
+ AS2( shl eax, 8 )
+
+ AS2( psrldq xmm0, 15 )
+ AS2( movd WORD_REG(di), xmm0 )
+ AS2( xor ax, WORD PTR [RED_TABLE + WORD_REG(di)*2] )
+
+ AS2( movd xmm0, eax )
+ AS2( pxor xmm0, xmm4 )
+
+ AS2( add WORD_REG(cx), 16 )
+ AS2( sub WORD_REG(dx), 1 )
+ ASJ( jnz, 0, b )
+ AS2( movdqa [WORD_REG(si)], xmm0 )
+
+ AS_POP_IF86( bp)
+ #if !defined(_MSC_VER) || (_MSC_VER < 1300)
+ AS_POP_IF86( bx)
+ #endif
+
+ #ifdef __GNUC__
+ ".att_syntax prefix;"
+ :
+ : "c" (data), "d" (len/16), "S" (hashBuffer), "D" (s_reductionTable)
+ : "memory", "cc", "%eax"
+ #if CRYPTOPP_BOOL_X64
+ , "%ebx", "%r11"
+ #endif
+ );
+ #elif defined(CRYPTOPP_GENERATE_X64_MASM)
+ pop rbx
+ pop rdi
+ pop rsi
+ ret
+ GCM_AuthenticateBlocks_2K ENDP
+ #endif
+
+ return len%16;
+ }
+ case 3: // SSE2 and 64K tables
+ {
+ #ifdef __GNUC__
+ __asm__ __volatile__
+ (
+ ".intel_syntax noprefix;"
+ #elif defined(CRYPTOPP_GENERATE_X64_MASM)
+ ALIGN 8
+ GCM_AuthenticateBlocks_64K PROC FRAME
+ rex_push_reg rsi
+ push_reg rdi
+ .endprolog
+ mov rsi, r8
+ #else
+ AS2( mov WORD_REG(cx), data )
+ AS2( mov WORD_REG(dx), len )
+ AS2( mov WORD_REG(si), hashBuffer )
+ AS2( shr WORD_REG(dx), 4 )
+ #endif
+
+ AS2( movdqa xmm0, [WORD_REG(si)] )
+
+ #undef MUL_TABLE
+ #define MUL_TABLE(i,j) WORD_REG(si) + 32 + (i*4+j)*256*16
+
+ ASL(1)
+ AS2( movdqu xmm1, [WORD_REG(cx)] )
+ AS2( pxor xmm1, xmm0 )
+ AS2( pxor xmm0, xmm0 )
+
+ #undef SSE2_MUL_32BITS
+ #define SSE2_MUL_32BITS(i) \
+ AS2( movd eax, xmm1 )\
+ AS2( psrldq xmm1, 4 )\
+ AS2( movzx edi, al )\
+ AS2( add WORD_REG(di), WORD_REG(di) )\
+ AS2( pxor xmm0, [MUL_TABLE(i,0) + WORD_REG(di)*8] )\
+ AS2( movzx edi, ah )\
+ AS2( add WORD_REG(di), WORD_REG(di) )\
+ AS2( pxor xmm0, [MUL_TABLE(i,1) + WORD_REG(di)*8] )\
+ AS2( shr eax, 16 )\
+ AS2( movzx edi, al )\
+ AS2( add WORD_REG(di), WORD_REG(di) )\
+ AS2( pxor xmm0, [MUL_TABLE(i,2) + WORD_REG(di)*8] )\
+ AS2( movzx edi, ah )\
+ AS2( add WORD_REG(di), WORD_REG(di) )\
+ AS2( pxor xmm0, [MUL_TABLE(i,3) + WORD_REG(di)*8] )\
+
+ SSE2_MUL_32BITS(0)
+ SSE2_MUL_32BITS(1)
+ SSE2_MUL_32BITS(2)
+ SSE2_MUL_32BITS(3)
+
+ AS2( add WORD_REG(cx), 16 )
+ AS2( sub WORD_REG(dx), 1 )
+ ASJ( jnz, 1, b )
+ AS2( movdqa [WORD_REG(si)], xmm0 )
+
+ #ifdef __GNUC__
+ ".att_syntax prefix;"
+ :
+ : "c" (data), "d" (len/16), "S" (hashBuffer)
+ : "memory", "cc", "%edi", "%eax"
+ );
+ #elif defined(CRYPTOPP_GENERATE_X64_MASM)
+ pop rdi
+ pop rsi
+ ret
+ GCM_AuthenticateBlocks_64K ENDP
+ #endif
+
+ return len%16;
+ }
+#endif
+#ifndef CRYPTOPP_GENERATE_X64_MASM
+ }
+
+ return len%16;
+
+#if 0
+ byte *hashBuffer = HashBuffer(), *hashKey = HashKey();
+
+ __m128i b = _mm_load_si128((__m128i *)hashBuffer);
+ __m128i mask = _mm_load_si128((__m128i *)s_GCM_mask);
+ byte *table = MulTable();
+
+ do
+ {
+ b = _mm_xor_si128(b, _mm_loadu_si128((__m128i *)data));
+ data += HASH_BLOCKSIZE;
+ len -= HASH_BLOCKSIZE;
+
+#define SSE2_READ_TABLE(a, b, c) *(__m128i *)(table+(a*1024)+(b*16*16)+(c?(x>>((c?c-1:1)*4))&0xf0:(x&0xf)<<4))
+
+ word32 x = _mm_cvtsi128_si32(b);
+ __m128i a0 = _mm_xor_si128(SSE2_READ_TABLE(0, 0, 0), SSE2_READ_TABLE(1, 0, 1));
+ __m128i a1 = _mm_xor_si128(SSE2_READ_TABLE(0, 0, 2), SSE2_READ_TABLE(1, 0, 3));
+ __m128i a2 = _mm_xor_si128(SSE2_READ_TABLE(0, 0, 4), SSE2_READ_TABLE(1, 0, 5));
+ __m128i a3 = _mm_xor_si128(SSE2_READ_TABLE(0, 0, 6), SSE2_READ_TABLE(1, 0, 7));
+
+#define SSE2_MULTIPLY_32(i) \
+ b = _mm_srli_si128(b, 4); \
+ x = _mm_cvtsi128_si32(b); \
+ a0 = _mm_xor_si128(a0, SSE2_READ_TABLE(0, i, 0)); \
+ a0 = _mm_xor_si128(a0, SSE2_READ_TABLE(1, i, 1)); \
+ a1 = _mm_xor_si128(a1, SSE2_READ_TABLE(0, i, 2)); \
+ a1 = _mm_xor_si128(a1, SSE2_READ_TABLE(1, i, 3)); \
+ a2 = _mm_xor_si128(a2, SSE2_READ_TABLE(0, i, 4)); \
+ a2 = _mm_xor_si128(a2, SSE2_READ_TABLE(1, i, 5)); \
+ a3 = _mm_xor_si128(a3, SSE2_READ_TABLE(0, i, 6)); \
+ a3 = _mm_xor_si128(a3, SSE2_READ_TABLE(1, i, 7));
+
+ SSE2_MULTIPLY_32(1)
+ SSE2_MULTIPLY_32(2)
+ SSE2_MULTIPLY_32(3)
+
+ word32 r = (word32)s_reductionTable[_mm_cvtsi128_si32(_mm_srli_si128(a3, 15))] << 16;
+ a3 = _mm_slli_si128(a3, 1);
+ a2 = _mm_xor_si128(a2, a3);
+ r ^= (word32)s_reductionTable[_mm_cvtsi128_si32(_mm_srli_si128(a2, 15))] << 8;
+ a2 = _mm_slli_si128(a2, 1);
+ a1 = _mm_xor_si128(a1, a2);
+ r ^= s_reductionTable[_mm_cvtsi128_si32(_mm_srli_si128(a1, 15))];
+ a1 = _mm_slli_si128(a1, 1);
+ a0 = _mm_xor_si128(a0, a1);
+ b = _mm_xor_si128(a0, _mm_cvtsi32_si128(r));
+ }
+ while (len >= HASH_BLOCKSIZE);
+
+ _mm_store_si128((__m128i *)hashBuffer, b);
+ __m128i b = *(__m128i *)hashBuffer;
+ __m128i mask = *(__m128i *)s_GCM_mask;
+ byte *table = MulTable();
+
+ do
+ {
+ b = _mm_xor_si128(b, _mm_loadu_si128((__m128i *)data));
+ data += HASH_BLOCKSIZE;
+ len -= HASH_BLOCKSIZE;
+
+ __m128i c0 = _mm_and_si128(_mm_slli_epi16(b, 4), mask);
+ __m128i c1 = _mm_and_si128(b, mask);
+ __m128i c2 = _mm_and_si128(_mm_srli_epi16(b, 4), mask);
+ __m128i c3 = _mm_and_si128(_mm_srli_epi16(b, 8), mask);
+
+#define SSE2_READ_TABLE(a, c, d) *(__m128i *)(table+(a*1024)+((d/2)*16*16)+(size_t)(word16)_mm_extract_epi16(c, d))
+
+ __m128i a3 = SSE2_READ_TABLE(0, c2, 1);
+ a3 = _mm_xor_si128(a3, SSE2_READ_TABLE(1, c3, 1));
+ a3 = _mm_xor_si128(a3, SSE2_READ_TABLE(0, c2, 3));
+ a3 = _mm_xor_si128(a3, SSE2_READ_TABLE(1, c3, 3));
+ a3 = _mm_xor_si128(a3, SSE2_READ_TABLE(0, c2, 5));
+ a3 = _mm_xor_si128(a3, SSE2_READ_TABLE(1, c3, 5));
+ a3 = _mm_xor_si128(a3, SSE2_READ_TABLE(0, c2, 7));
+ a3 = _mm_xor_si128(a3, SSE2_READ_TABLE(1, c3, 7));
+
+ word32 r = (word32)s_reductionTable[((word16)_mm_extract_epi16(a3, 7))>>8] << 16;
+ a3 = _mm_slli_si128(a3, 1);
+
+ __m128i a2 = _mm_xor_si128(a3, SSE2_READ_TABLE(0, c0, 1));
+ a2 = _mm_xor_si128(a2, SSE2_READ_TABLE(1, c1, 1));
+ a2 = _mm_xor_si128(a2, SSE2_READ_TABLE(0, c0, 3));
+ a2 = _mm_xor_si128(a2, SSE2_READ_TABLE(1, c1, 3));
+ a2 = _mm_xor_si128(a2, SSE2_READ_TABLE(0, c0, 5));
+ a2 = _mm_xor_si128(a2, SSE2_READ_TABLE(1, c1, 5));
+ a2 = _mm_xor_si128(a2, SSE2_READ_TABLE(0, c0, 7));
+ a2 = _mm_xor_si128(a2, SSE2_READ_TABLE(1, c1, 7));
+
+ r ^= (word32)s_reductionTable[_mm_cvtsi128_si32(_mm_srli_si128(a2, 15))] << 8;
+ a2 = _mm_slli_si128(a2, 1);
+
+ __m128i a1 = _mm_xor_si128(a2, SSE2_READ_TABLE(0, c2, 0));
+ a1 = _mm_xor_si128(a1, SSE2_READ_TABLE(1, c3, 0));
+ a1 = _mm_xor_si128(a1, SSE2_READ_TABLE(0, c2, 2));
+ a1 = _mm_xor_si128(a1, SSE2_READ_TABLE(1, c3, 2));
+ a1 = _mm_xor_si128(a1, SSE2_READ_TABLE(0, c2, 4));
+ a1 = _mm_xor_si128(a1, SSE2_READ_TABLE(1, c3, 4));
+ a1 = _mm_xor_si128(a1, SSE2_READ_TABLE(0, c2, 6));
+ a1 = _mm_xor_si128(a1, SSE2_READ_TABLE(1, c3, 6));
+
+ r ^= s_reductionTable[_mm_cvtsi128_si32(_mm_srli_si128(a1, 15))];
+ a1 = _mm_slli_si128(a1, 1);
+
+ __m128i a0 = _mm_xor_si128(a1, SSE2_READ_TABLE(0, c0, 0));
+ a0 = _mm_xor_si128(a0, SSE2_READ_TABLE(1, c1, 0));
+ a0 = _mm_xor_si128(a0, SSE2_READ_TABLE(0, c0, 2));
+ a0 = _mm_xor_si128(a0, SSE2_READ_TABLE(1, c1, 2));
+ a0 = _mm_xor_si128(a0, SSE2_READ_TABLE(0, c0, 4));
+ a0 = _mm_xor_si128(a0, SSE2_READ_TABLE(1, c1, 4));
+ a0 = _mm_xor_si128(a0, SSE2_READ_TABLE(0, c0, 6));
+ a0 = _mm_xor_si128(a0, SSE2_READ_TABLE(1, c1, 6));
+
+ b = _mm_xor_si128(a0, _mm_cvtsi32_si128(r));
+ }
+ while (len >= HASH_BLOCKSIZE);
+
+ _mm_store_si128((__m128i *)hashBuffer, b);
+
+ return len;
+#endif
+}
+
+void GCM_Base::AuthenticateLastHeaderBlock()
+{
+ if (m_bufferedDataLength > 0)
+ {
+ memset(m_buffer+m_bufferedDataLength, 0, HASH_BLOCKSIZE-m_bufferedDataLength);
+ m_bufferedDataLength = 0;
+ GCM_Base::AuthenticateBlocks(m_buffer, HASH_BLOCKSIZE);
+ }
+}
+
+void GCM_Base::AuthenticateLastConfidentialBlock()
+{
+ GCM_Base::AuthenticateLastHeaderBlock();
+ PutBlock<word64, BigEndian, true>(NULL, m_buffer)(m_totalHeaderLength*8)(m_totalMessageLength*8);
+ GCM_Base::AuthenticateBlocks(m_buffer, HASH_BLOCKSIZE);
+}
+
+void GCM_Base::AuthenticateLastFooterBlock(byte *mac, size_t macSize)
+{
+ m_ctr.Seek(0);
+ m_ctr.ProcessData(mac, HashBuffer(), macSize);
+}
+
+NAMESPACE_END
+
+#endif // #ifndef CRYPTOPP_GENERATE_X64_MASM
+#endif
diff --git a/gcm.h b/gcm.h
new file mode 100644
index 0000000..6be06d4
--- /dev/null
+++ b/gcm.h
@@ -0,0 +1,105 @@
+#ifndef CRYPTOPP_GCM_H
+#define CRYPTOPP_GCM_H
+
+#include "authenc.h"
+#include "modes.h"
+
+NAMESPACE_BEGIN(CryptoPP)
+
+//! .
+enum GCM_TablesOption {GCM_2K_Tables, GCM_64K_Tables};
+
+//! .
+class CRYPTOPP_DLL CRYPTOPP_NO_VTABLE GCM_Base : public AuthenticatedSymmetricCipherBase
+{
+public:
+ // AuthenticatedSymmetricCipher
+ std::string AlgorithmName() const
+ {return GetBlockCipher().AlgorithmName() + std::string("/GCM");}
+ size_t MinKeyLength() const
+ {return GetBlockCipher().MinKeyLength();}
+ size_t MaxKeyLength() const
+ {return GetBlockCipher().MaxKeyLength();}
+ size_t DefaultKeyLength() const
+ {return GetBlockCipher().DefaultKeyLength();}
+ size_t GetValidKeyLength(size_t n) const
+ {return GetBlockCipher().GetValidKeyLength(n);}
+ bool IsValidKeyLength(size_t n) const
+ {return GetBlockCipher().IsValidKeyLength(n);}
+ unsigned int OptimalDataAlignment() const;
+ IV_Requirement IVRequirement() const
+ {return UNIQUE_IV;}
+ unsigned int IVSize() const
+ {return 12;}
+ unsigned int MinIVLength() const
+ {return 1;}
+ unsigned int MaxIVLength() const
+ {return UINT_MAX;} // (W64LIT(1)<<61)-1 in the standard
+ unsigned int DigestSize(void) const
+ {return 16;}
+ lword MaxHeaderLength() const
+ {return (W64LIT(1)<<61)-1;}
+ lword MaxMessageLength() const
+ {return ((W64LIT(1)<<39)-256)/8;}
+
+protected:
+ // AuthenticatedSymmetricCipherBase
+ bool AuthenticationIsOnPlaintext() const
+ {return false;}
+ unsigned int AuthenticationBlockSize() const
+ {return HASH_BLOCKSIZE;}
+ void SetKeyWithoutResync(const byte *userKey, size_t keylength, const NameValuePairs &params);
+ void Resync(const byte *iv, size_t len);
+ size_t AuthenticateBlocks(const byte *data, size_t len);
+ void AuthenticateLastHeaderBlock();
+ void AuthenticateLastConfidentialBlock();
+ void AuthenticateLastFooterBlock(byte *mac, size_t macSize);
+ SymmetricCipher & AccessSymmetricCipher() {return m_ctr;}
+
+ virtual BlockCipher & AccessBlockCipher() =0;
+ virtual GCM_TablesOption GetTablesOption() const =0;
+
+ const BlockCipher & GetBlockCipher() const {return const_cast<GCM_Base *>(this)->AccessBlockCipher();};
+ byte *HashBuffer() {return m_buffer+REQUIRED_BLOCKSIZE;}
+ byte *HashKey() {return m_buffer+2*REQUIRED_BLOCKSIZE;}
+ byte *MulTable() {return m_buffer+3*REQUIRED_BLOCKSIZE;}
+
+ class GCTR : public CTR_Mode_ExternalCipher::Encryption
+ {
+ protected:
+ void IncrementCounterBy256();
+ };
+
+ GCTR m_ctr;
+ static word16 s_reductionTable[256];
+ static bool s_reductionTableInitialized;
+ enum {REQUIRED_BLOCKSIZE = 16, HASH_BLOCKSIZE = 16};
+};
+
+//! .
+template <class T_BlockCipher, GCM_TablesOption T_TablesOption, bool T_IsEncryption>
+class GCM_Final : public GCM_Base
+{
+public:
+ static std::string StaticAlgorithmName()
+ {return T_BlockCipher::StaticAlgorithmName() + std::string("/GCM");}
+ bool IsForwardTransformation() const
+ {return T_IsEncryption;}
+
+private:
+ GCM_TablesOption GetTablesOption() const {return T_TablesOption;}
+ BlockCipher & AccessBlockCipher() {return m_cipher;}
+ typename T_BlockCipher::Encryption m_cipher;
+};
+
+//! <a href="http://www.cryptolounge.org/wiki/GCM">GCM</a>
+template <class T_BlockCipher, GCM_TablesOption T_TablesOption=GCM_2K_Tables>
+struct GCM : public AuthenticatedSymmetricCipherDocumentation
+{
+ typedef GCM_Final<T_BlockCipher, T_TablesOption, true> Encryption;
+ typedef GCM_Final<T_BlockCipher, T_TablesOption, false> Decryption;
+};
+
+NAMESPACE_END
+
+#endif
diff --git a/hrtimer.h b/hrtimer.h
index 01c156c..858dbd2 100644
--- a/hrtimer.h
+++ b/hrtimer.h
@@ -9,11 +9,7 @@
NAMESPACE_BEGIN(CryptoPP)
#ifdef HIGHRES_TIMER_AVAILABLE
- #ifdef WORD64_AVAILABLE
- typedef word64 TimerWord;
- #else
- typedef word32 TimerWord;
- #endif
+ typedef word64 TimerWord;
#else
typedef clock_t TimerWord;
#endif
diff --git a/idea.h b/idea.h
index d823f8f..ce026a1 100644
--- a/idea.h
+++ b/idea.h
@@ -29,7 +29,7 @@ private:
class CRYPTOPP_NO_VTABLE Base : public BlockCipherImpl<IDEA_Info>
{
public:
- unsigned int GetAlignment() const {return 2;}
+ unsigned int OptimalDataAlignment() const {return 2;}
void ProcessAndXorBlock(const byte *inBlock, const byte *xorBlock, byte *outBlock) const;
void UncheckedSetKey(const byte *userKey, unsigned int length, const NameValuePairs &params);
diff --git a/integer.cpp b/integer.cpp
index 7bbc51f..f1a563c 100644
--- a/integer.cpp
+++ b/integer.cpp
@@ -3285,7 +3285,7 @@ bool Integer::GenerateRandomNoThrow(RandomNumberGenerator &i_rng, const NameValu
member_ptr<KDF2_RNG> kdf2Rng;
ConstByteArrayParameter seed;
- if (params.GetValue("Seed", seed))
+ if (params.GetValue(Name::Seed(), seed))
{
ByteQueue bq;
DERSequenceEncoder seq(bq);
@@ -3717,7 +3717,7 @@ void PositiveDivide(Integer &remainder, Integer &quotient,
if (!bSize)
throw Integer::DivideByZero();
- if (a.PositiveCompare(b) == -1)
+ if (aSize < bSize)
{
remainder = a;
remainder.sign = Integer::POSITIVE;
@@ -3965,8 +3965,8 @@ Integer Integer::InverseMod(const Integer &m) const
{
assert(m.NotNegative());
- if (IsNegative() || *this>=m)
- return (*this%m).InverseMod(m);
+ if (IsNegative())
+ return Modulo(m).InverseMod(m);
if (m.IsEven())
{
@@ -3975,7 +3975,7 @@ Integer Integer::InverseMod(const Integer &m) const
if (*this == One())
return One();
- Integer u = m.InverseMod(*this);
+ Integer u = m.Modulo(*this).InverseMod(*this);
return !u ? Zero() : (m*(*this-u)+1)/(*this);
}
diff --git a/iterhash.cpp b/iterhash.cpp
index 44360b1..642a7ca 100644
--- a/iterhash.cpp
+++ b/iterhash.cpp
@@ -25,13 +25,13 @@ template <class T, class BASE> void IteratedHashBase<T, BASE>::Update(const byte
if (num != 0) // process left over data
{
- if ((num+len) >= blockSize)
+ if (num+len >= blockSize)
{
memcpy(data+num, input, blockSize-num);
HashBlock(dataBuf);
input += (blockSize-num);
- len-=(blockSize - num);
- num=0;
+ len -= (blockSize-num);
+ num = 0;
// drop through and do the rest
}
else
@@ -145,10 +145,8 @@ template <class T, class BASE> void IteratedHashBase<T, BASE>::TruncatedFinal(by
}
#ifdef __GNUC__
- #ifdef WORD64_AVAILABLE
template class IteratedHashBase<word64, HashTransformation>;
template class IteratedHashBase<word64, MessageAuthenticationCode>;
- #endif
template class IteratedHashBase<word32, HashTransformation>;
template class IteratedHashBase<word32, MessageAuthenticationCode>;
diff --git a/iterhash.h b/iterhash.h
index a22b57d..8af3177 100644
--- a/iterhash.h
+++ b/iterhash.h
@@ -94,10 +94,8 @@ protected:
};
#ifndef __GNUC__
- #ifdef WORD64_AVAILABLE
CRYPTOPP_DLL_TEMPLATE_CLASS IteratedHashBase<word64, HashTransformation>;
CRYPTOPP_STATIC_TEMPLATE_CLASS IteratedHashBase<word64, MessageAuthenticationCode>;
- #endif
CRYPTOPP_DLL_TEMPLATE_CLASS IteratedHashBase<word32, HashTransformation>;
CRYPTOPP_STATIC_TEMPLATE_CLASS IteratedHashBase<word32, MessageAuthenticationCode>;
diff --git a/mdc.h b/mdc.h
index 3512089..cc90cdc 100644
--- a/mdc.h
+++ b/mdc.h
@@ -50,7 +50,7 @@ class MDC : public MDC_Info<T>
bool IsPermutation() const {return false;}
- unsigned int GetAlignment() const {return sizeof(HashWordType);}
+ unsigned int OptimalDataAlignment() const {return sizeof(HashWordType);}
private:
HashWordType *Key() {return (HashWordType *)m_key.data();}
diff --git a/misc.cpp b/misc.cpp
index 305edfd..7e4fa89 100644
--- a/misc.cpp
+++ b/misc.cpp
@@ -16,8 +16,7 @@ void xorbuf(byte *buf, const byte *mask, size_t count)
if (IsAligned<word32>(buf) && IsAligned<word32>(mask))
{
- #if defined(WORD64_AVAILABLE) && !defined(CRYPTOPP_SLOW_WORD64)
- if (IsAligned<word64>(buf) && IsAligned<word64>(mask))
+ if (!CRYPTOPP_BOOL_SLOW_WORD64 && IsAligned<word64>(buf) && IsAligned<word64>(mask))
{
for (i=0; i<count/8; i++)
((word64*)buf)[i] ^= ((word64*)mask)[i];
@@ -27,7 +26,6 @@ void xorbuf(byte *buf, const byte *mask, size_t count)
buf += 8*i;
mask += 8*i;
}
- #endif
for (i=0; i<count/4; i++)
((word32*)buf)[i] ^= ((word32*)mask)[i];
@@ -48,8 +46,7 @@ void xorbuf(byte *output, const byte *input, const byte *mask, size_t count)
if (IsAligned<word32>(output) && IsAligned<word32>(input) && IsAligned<word32>(mask))
{
- #if defined(WORD64_AVAILABLE) && !defined(CRYPTOPP_SLOW_WORD64)
- if (IsAligned<word64>(output) && IsAligned<word64>(input) && IsAligned<word64>(mask))
+ if (!CRYPTOPP_BOOL_SLOW_WORD64 && IsAligned<word64>(output) && IsAligned<word64>(input) && IsAligned<word64>(mask))
{
for (i=0; i<count/8; i++)
((word64*)output)[i] = ((word64*)input)[i] ^ ((word64*)mask)[i];
@@ -60,7 +57,6 @@ void xorbuf(byte *output, const byte *input, const byte *mask, size_t count)
input += 8*i;
mask += 8*i;
}
- #endif
for (i=0; i<count/4; i++)
((word32*)output)[i] = ((word32*)input)[i] ^ ((word32*)mask)[i];
@@ -76,6 +72,42 @@ void xorbuf(byte *output, const byte *input, const byte *mask, size_t count)
output[i] = input[i] ^ mask[i];
}
+bool VerifyBufsEqual(const byte *buf, const byte *mask, size_t count)
+{
+ size_t i;
+ byte acc8 = 0;
+
+ if (IsAligned<word32>(buf) && IsAligned<word32>(mask))
+ {
+ word32 acc32 = 0;
+ if (!CRYPTOPP_BOOL_SLOW_WORD64 && IsAligned<word64>(buf) && IsAligned<word64>(mask))
+ {
+ word64 acc64 = 0;
+ for (i=0; i<count/8; i++)
+ acc64 |= ((word64*)buf)[i] ^ ((word64*)mask)[i];
+ count -= 8*i;
+ if (!count)
+ return acc64 == 0;
+ buf += 8*i;
+ mask += 8*i;
+ acc32 = word32(acc64) | word32(acc64>>32);
+ }
+
+ for (i=0; i<count/4; i++)
+ acc32 |= ((word32*)buf)[i] ^ ((word32*)mask)[i];
+ count -= 4*i;
+ if (!count)
+ return acc32 == 0;
+ buf += 4*i;
+ mask += 4*i;
+ acc8 = byte(acc32) | byte(acc32>>8) | byte(acc32>>16) | byte(acc32>>24);
+ }
+
+ for (i=0; i<count; i++)
+ acc8 |= buf[i] ^ mask[i];
+ return acc8 == 0;
+}
+
#if !(defined(_MSC_VER) && (_MSC_VER < 1300))
using std::new_handler;
using std::set_new_handler;
diff --git a/misc.h b/misc.h
index 5c3a6d1..c6c743a 100644
--- a/misc.h
+++ b/misc.h
@@ -298,6 +298,8 @@ inline size_t BitsToDwords(size_t bitCount)
CRYPTOPP_DLL void CRYPTOPP_API xorbuf(byte *buf, const byte *mask, size_t count);
CRYPTOPP_DLL void CRYPTOPP_API xorbuf(byte *output, const byte *input, const byte *mask, size_t count);
+CRYPTOPP_DLL bool CRYPTOPP_API VerifyBufsEqual(const byte *buf1, const byte *buf2, size_t count);
+
template <class T>
inline bool IsPowerOf2(const T &n)
{
@@ -331,16 +333,16 @@ inline T1 RoundUpToMultipleOf(const T1 &n, const T2 &m)
template <class T>
inline unsigned int GetAlignmentOf(T *dummy=NULL) // VC60 workaround
{
-#if CRYPTOPP_BOOL_X64 || CRYPTOPP_BOOL_X86
+#ifdef CRYPTOPP_ALLOW_UNALIGNED_DATA_ACCESS
if (sizeof(T) < 16)
- return 1; // alignment not needed on x86 and x64
+ return 1;
#endif
#if (_MSC_VER >= 1300)
return __alignof(T);
#elif defined(__GNUC__)
return __alignof__(T);
-#elif defined(CRYPTOPP_SLOW_WORD64)
+#elif CRYPTOPP_BOOL_SLOW_WORD64
return UnsignedMin(4U, sizeof(T));
#else
return sizeof(T);
@@ -699,7 +701,6 @@ inline word32 ByteReverse(word32 value)
#endif
}
-#ifdef WORD64_AVAILABLE
inline word64 ByteReverse(word64 value)
{
#if defined(__GNUC__) && defined(CRYPTOPP_X86_ASM_AVAILABLE) && defined(__x86_64__)
@@ -709,7 +710,7 @@ inline word64 ByteReverse(word64 value)
return bswap_64(value);
#elif defined(_MSC_VER) && _MSC_VER >= 1300
return _byteswap_uint64(value);
-#elif defined(CRYPTOPP_SLOW_WORD64)
+#elif CRYPTOPP_BOOL_SLOW_WORD64
return (word64(ByteReverse(word32(value))) << 32) | ByteReverse(word32(value>>32));
#else
value = ((value & W64LIT(0xFF00FF00FF00FF00)) >> 8) | ((value & W64LIT(0x00FF00FF00FF00FF)) << 8);
@@ -717,7 +718,6 @@ inline word64 ByteReverse(word64 value)
return rotlFixed(value, 32U);
#endif
}
-#endif
inline byte BitReverse(byte value)
{
@@ -742,10 +742,9 @@ inline word32 BitReverse(word32 value)
return ByteReverse(value);
}
-#ifdef WORD64_AVAILABLE
inline word64 BitReverse(word64 value)
{
-#ifdef CRYPTOPP_SLOW_WORD64
+#if CRYPTOPP_BOOL_SLOW_WORD64
return (word64(BitReverse(word32(value))) << 32) | BitReverse(word32(value>>32));
#else
value = ((value & W64LIT(0xAAAAAAAAAAAAAAAA)) >> 1) | ((value & W64LIT(0x5555555555555555)) << 1);
@@ -754,7 +753,6 @@ inline word64 BitReverse(word64 value)
return ByteReverse(value);
#endif
}
-#endif
template <class T>
inline T BitReverse(T value)
@@ -767,13 +765,8 @@ inline T BitReverse(T value)
return (T)BitReverse((word32)value);
else
{
-#ifdef WORD64_AVAILABLE
assert(sizeof(T) == 8);
return (T)BitReverse((word64)value);
-#else
- assert(false);
- return 0;
-#endif
}
}
@@ -831,7 +824,6 @@ inline word32 UnalignedGetWordNonTemplate(ByteOrder order, const byte *block, co
: word32(block[0]) | (word32(block[1]) << 8) | (word32(block[2]) << 16) | (word32(block[3]) << 24);
}
-#ifdef WORD64_AVAILABLE
inline word64 UnalignedGetWordNonTemplate(ByteOrder order, const byte *block, const word64 *)
{
return (order == BIG_ENDIAN_ORDER)
@@ -854,7 +846,6 @@ inline word64 UnalignedGetWordNonTemplate(ByteOrder order, const byte *block, co
(word64(block[6]) << 48) |
(word64(block[7]) << 56));
}
-#endif
inline void UnalignedPutWordNonTemplate(ByteOrder order, byte *block, byte value, const byte *xorBlock)
{
@@ -929,7 +920,6 @@ inline void UnalignedPutWordNonTemplate(ByteOrder order, byte *block, word32 val
}
}
-#ifdef WORD64_AVAILABLE
inline void UnalignedPutWordNonTemplate(ByteOrder order, byte *block, word64 value, const byte *xorBlock)
{
if (order == BIG_ENDIAN_ORDER)
@@ -983,7 +973,6 @@ inline void UnalignedPutWordNonTemplate(ByteOrder order, byte *block, word64 val
}
}
}
-#endif
#endif // #ifndef CRYPTOPP_ALLOW_UNALIGNED_DATA_ACCESS
template <class T>
@@ -1015,7 +1004,7 @@ inline void PutWord(bool assumeAligned, ByteOrder order, byte *block, T value, c
*reinterpret_cast<T *>(block) = ConditionalByteReverse(order, value) ^ (xorBlock ? *reinterpret_cast<const T *>(xorBlock) : 0);
}
-template <class T, class B, bool A=true>
+template <class T, class B, bool A=false>
class GetBlock
{
public:
@@ -1057,7 +1046,7 @@ private:
byte *m_block;
};
-template <class T, class B, bool GA=true, bool PA=false>
+template <class T, class B, bool GA=false, bool PA=false>
struct BlockGetAndPut
{
// function needed because of C++ grammatical ambiguity between expression-statements and declarations
@@ -1128,6 +1117,18 @@ inline T SafeLeftShift(T value)
return SafeShifter<(bits>=(8*sizeof(T)))>::LeftShift(value, bits);
}
+// ************** use one buffer for multiple data members ***************
+
+#define CRYPTOPP_BLOCK_1(n, t, s) t* m_##n() {return (t *)(m_aggregate+0);} size_t SS1() {return sizeof(t)*(s);} size_t m_##n##Size() {return (s);}
+#define CRYPTOPP_BLOCK_2(n, t, s) t* m_##n() {return (t *)(m_aggregate+SS1());} size_t SS2() {return SS1()+sizeof(t)*(s);} size_t m_##n##Size() {return (s);}
+#define CRYPTOPP_BLOCK_3(n, t, s) t* m_##n() {return (t *)(m_aggregate+SS2());} size_t SS3() {return SS2()+sizeof(t)*(s);} size_t m_##n##Size() {return (s);}
+#define CRYPTOPP_BLOCK_4(n, t, s) t* m_##n() {return (t *)(m_aggregate+SS3());} size_t SS4() {return SS3()+sizeof(t)*(s);} size_t m_##n##Size() {return (s);}
+#define CRYPTOPP_BLOCK_5(n, t, s) t* m_##n() {return (t *)(m_aggregate+SS4());} size_t SS5() {return SS4()+sizeof(t)*(s);} size_t m_##n##Size() {return (s);}
+#define CRYPTOPP_BLOCK_6(n, t, s) t* m_##n() {return (t *)(m_aggregate+SS5());} size_t SS6() {return SS5()+sizeof(t)*(s);} size_t m_##n##Size() {return (s);}
+#define CRYPTOPP_BLOCK_7(n, t, s) t* m_##n() {return (t *)(m_aggregate+SS6());} size_t SS7() {return SS6()+sizeof(t)*(s);} size_t m_##n##Size() {return (s);}
+#define CRYPTOPP_BLOCK_8(n, t, s) t* m_##n() {return (t *)(m_aggregate+SS7());} size_t SS8() {return SS7()+sizeof(t)*(s);} size_t m_##n##Size() {return (s);}
+#define CRYPTOPP_BLOCKS_END(i) size_t SST() {return SS##i();} void AllocateBlocks() {m_aggregate.New(SST());} AlignedSecByteBlock m_aggregate;
+
NAMESPACE_END
#endif
diff --git a/modes.cpp b/modes.cpp
index b67ce75..cd7450f 100644
--- a/modes.cpp
+++ b/modes.cpp
@@ -24,6 +24,21 @@ void Modes_TestInstantiations()
}
#endif
+void OFB_ModePolicy::WriteKeystream(byte *keystreamBuffer, size_t iterationCount)
+{
+ assert(m_cipher->IsForwardTransformation()); // OFB mode needs the "encrypt" direction of the underlying block cipher, even to decrypt
+ unsigned int s = BlockSize();
+ m_cipher->ProcessBlock(m_register, keystreamBuffer);
+ if (iterationCount > 1)
+ m_cipher->AdvancedProcessBlocks(keystreamBuffer, NULL, keystreamBuffer+s, s*(iterationCount-1), 0);
+ memcpy(m_register, keystreamBuffer+s*(iterationCount-1), s);
+}
+
+void OFB_ModePolicy::CipherResynchronize(byte *keystreamBuffer, const byte *iv, size_t length)
+{
+ CopyOrZero(m_register, iv, length);
+}
+
void CTR_ModePolicy::SeekToIteration(lword iterationCount)
{
int carry=0;
@@ -36,52 +51,36 @@ void CTR_ModePolicy::SeekToIteration(lword iterationCount)
}
}
-inline void CTR_ModePolicy::ProcessMultipleBlocks(byte *output, const byte *input, size_t n)
+void CTR_ModePolicy::IncrementCounterBy256()
{
- unsigned int s = BlockSize(), j = 0;
- for (unsigned int i=1; i<n; i++, j+=s)
- IncrementCounterByOne(m_counterArray + j + s, m_counterArray + j, s);
- m_cipher->ProcessAndXorMultipleBlocks(m_counterArray, input, output, n);
- IncrementCounterByOne(m_counterArray, m_counterArray + s*(n-1), s);
+ IncrementCounterByOne(m_counterArray, BlockSize()-1);
}
void CTR_ModePolicy::OperateKeystream(KeystreamOperation operation, byte *output, const byte *input, size_t iterationCount)
{
assert(m_cipher->IsForwardTransformation()); // CTR mode needs the "encrypt" direction of the underlying block cipher, even to decrypt
- unsigned int maxBlocks = m_cipher->OptimalNumberOfParallelBlocks();
- if (maxBlocks == 1)
- {
- unsigned int sizeIncrement = BlockSize();
- while (iterationCount)
- {
- m_cipher->ProcessAndXorBlock(m_counterArray, input, output);
- IncrementCounterByOne(m_counterArray, sizeIncrement);
- output += sizeIncrement;
- input += sizeIncrement;
- iterationCount -= 1;
- }
- }
- else
+ unsigned int s = BlockSize();
+ unsigned int inputIncrement = input ? s : 0;
+
+ while (iterationCount)
{
- unsigned int sizeIncrement = maxBlocks * BlockSize();
- while (iterationCount >= maxBlocks)
- {
- ProcessMultipleBlocks(output, input, maxBlocks);
- output += sizeIncrement;
- input += sizeIncrement;
- iterationCount -= maxBlocks;
- }
- if (iterationCount > 0)
- ProcessMultipleBlocks(output, input, iterationCount);
+ byte lsb = m_counterArray[s-1];
+ size_t blocks = UnsignedMin(iterationCount, 256U-lsb);
+ m_cipher->AdvancedProcessBlocks(m_counterArray, input, output, blocks*s, BlockTransformation::BT_InBlockIsCounter);
+ if ((m_counterArray[s-1] = lsb + (byte)blocks) == 0)
+ IncrementCounterBy256();
+
+ output += blocks*s;
+ input += blocks*inputIncrement;
+ iterationCount -= blocks;
}
}
-void CTR_ModePolicy::CipherResynchronize(byte *keystreamBuffer, const byte *iv)
+void CTR_ModePolicy::CipherResynchronize(byte *keystreamBuffer, const byte *iv, size_t length)
{
- unsigned int s = BlockSize();
- CopyOrZero(m_register, iv, s);
- m_counterArray.New(s * m_cipher->OptimalNumberOfParallelBlocks());
- CopyOrZero(m_counterArray, iv, s);
+ assert(length == BlockSize());
+ CopyOrZero(m_register, iv, length);
+ m_counterArray = m_register;
}
void BlockOrientedCipherModeBase::UncheckedSetKey(const byte *key, unsigned int length, const NameValuePairs &params)
@@ -89,45 +88,30 @@ void BlockOrientedCipherModeBase::UncheckedSetKey(const byte *key, unsigned int
m_cipher->SetKey(key, length, params);
ResizeBuffers();
if (IsResynchronizable())
- Resynchronize(GetIVAndThrowIfInvalid(params));
+ {
+ size_t ivLength;
+ const byte *iv = GetIVAndThrowIfInvalid(params, ivLength);
+ Resynchronize(iv, (int)ivLength);
+ }
}
-void BlockOrientedCipherModeBase::ProcessData(byte *outString, const byte *inString, size_t length)
+void ECB_OneWay::ProcessData(byte *outString, const byte *inString, size_t length)
{
- if (!length)
- return;
-
- unsigned int s = BlockSize();
- assert(length % s == 0);
-
- if (!RequireAlignedInput() || IsAlignedOn(inString, m_cipher->BlockAlignment()))
- ProcessBlocks(outString, inString, length / s);
- else
- {
- do
- {
- memcpy(m_buffer, inString, s);
- ProcessBlocks(outString, m_buffer, 1);
- inString += s;
- outString += s;
- length -= s;
- } while (length > 0);
- }
+ assert(length%BlockSize()==0);
+ m_cipher->AdvancedProcessBlocks(inString, NULL, outString, length, 0);
}
-void CBC_Encryption::ProcessBlocks(byte *outString, const byte *inString, size_t numberOfBlocks)
+void CBC_Encryption::ProcessData(byte *outString, const byte *inString, size_t length)
{
+ if (!length)
+ return;
+ assert(length%BlockSize()==0);
+
unsigned int blockSize = BlockSize();
- xorbuf(m_register, inString, blockSize);
- while (--numberOfBlocks)
- {
- m_cipher->ProcessBlock(m_register, outString);
- inString += blockSize;
- xorbuf(m_register, inString, outString, blockSize);
- outString += blockSize;
- }
- m_cipher->ProcessBlock(m_register);
- memcpy(outString, m_register, blockSize);
+ m_cipher->AdvancedProcessBlocks(inString, m_register, outString, blockSize, BlockTransformation::BT_XorInput);
+ if (length > blockSize)
+ m_cipher->AdvancedProcessBlocks(inString+blockSize, outString, outString+blockSize, length-blockSize, BlockTransformation::BT_XorInput);
+ memcpy(m_register, outString + length - blockSize, blockSize);
}
void CBC_CTS_Encryption::ProcessLastBlock(byte *outString, const byte *inString, size_t length)
@@ -157,17 +141,18 @@ void CBC_CTS_Encryption::ProcessLastBlock(byte *outString, const byte *inString,
memcpy(outString, m_register, BlockSize());
}
-void CBC_Decryption::ProcessBlocks(byte *outString, const byte *inString, size_t numberOfBlocks)
+void CBC_Decryption::ProcessData(byte *outString, const byte *inString, size_t length)
{
+ if (!length)
+ return;
+ assert(length%BlockSize()==0);
+
unsigned int blockSize = BlockSize();
- do
- {
- memcpy(m_temp, inString, blockSize); // make copy in case we're doing in place decryption
- m_cipher->ProcessAndXorBlock(m_temp, m_register, outString);
- m_register.swap(m_temp);
- inString += blockSize;
- outString += blockSize;
- } while (--numberOfBlocks);
+ memcpy(m_temp, inString+length-blockSize, blockSize); // save copy now in case of in-place decryption
+ if (length > blockSize)
+ m_cipher->AdvancedProcessBlocks(inString+blockSize, inString, outString+blockSize, length-blockSize, BlockTransformation::BT_ReverseDirection);
+ m_cipher->ProcessAndXorBlock(inString, m_register, outString);
+ m_register.swap(m_temp);
}
void CBC_CTS_Decryption::ProcessLastBlock(byte *outString, const byte *inString, size_t length)
diff --git a/modes.h b/modes.h
index 1bf36ae..91a61b6 100644
--- a/modes.h
+++ b/modes.h
@@ -13,7 +13,7 @@
NAMESPACE_BEGIN(CryptoPP)
-//! Cipher mode documentation. See NIST SP 800-38A for definitions of these modes.
+//! Cipher modes documentation. See NIST SP 800-38A for definitions of these modes. See AuthenticatedSymmetricCipherDocumentation for authenticated encryption modes.
/*! Each class derived from this one defines two types, Encryption and Decryption,
both of which implement the SymmetricCipher interface.
@@ -37,7 +37,7 @@ public:
size_t GetValidKeyLength(size_t n) const {return m_cipher->GetValidKeyLength(n);}
bool IsValidKeyLength(size_t n) const {return m_cipher->IsValidKeyLength(n);}
- unsigned int OptimalDataAlignment() const {return BlockSize();}
+ unsigned int OptimalDataAlignment() const {return m_cipher->OptimalDataAlignment();}
unsigned int IVSize() const {return BlockSize();}
virtual IV_Requirement IVRequirement() const =0;
@@ -60,6 +60,7 @@ public:
}
protected:
+ CipherModeBase() : m_cipher(NULL) {}
inline unsigned int BlockSize() const {assert(m_register.size() > 0); return (unsigned int)m_register.size();}
virtual void SetFeedbackSize(unsigned int feedbackSize)
{
@@ -72,13 +73,13 @@ protected:
}
BlockCipher *m_cipher;
- SecByteBlock m_register;
+ AlignedSecByteBlock m_register;
};
template <class POLICY_INTERFACE>
class CRYPTOPP_NO_VTABLE ModePolicyCommonTemplate : public CipherModeBase, public POLICY_INTERFACE
{
- unsigned int GetAlignment() const {return m_cipher->BlockAlignment();}
+ unsigned int GetAlignment() const {return m_cipher->OptimalDataAlignment();}
void CipherSetKey(const NameValuePairs &params, const byte *key, size_t length);
};
@@ -108,7 +109,7 @@ protected:
memmove_s(m_register, m_register.size(), m_register+m_feedbackSize, updateSize);
memcpy_s(m_register+updateSize, m_register.size()-updateSize, m_temp, m_feedbackSize);
}
- void CipherResynchronize(const byte *iv)
+ void CipherResynchronize(const byte *iv, size_t length)
{
memcpy_s(m_register, m_register.size(), iv, BlockSize());
TransformRegister();
@@ -146,40 +147,32 @@ public:
private:
unsigned int GetBytesPerIteration() const {return BlockSize();}
- unsigned int GetIterationsToBuffer() const {return 1;}
- void WriteKeystream(byte *keystreamBuffer, size_t iterationCount)
- {
- assert(iterationCount == 1);
- assert(m_cipher->IsForwardTransformation()); // OFB mode needs the "encrypt" direction of the underlying block cipher, even to decrypt
- m_cipher->ProcessBlock(keystreamBuffer);
- }
- void CipherResynchronize(byte *keystreamBuffer, const byte *iv)
- {
- CopyOrZero(keystreamBuffer, iv, BlockSize());
- }
+ unsigned int GetIterationsToBuffer() const {return m_cipher->OptimalNumberOfParallelBlocks();}
+ void WriteKeystream(byte *keystreamBuffer, size_t iterationCount);
+ void CipherResynchronize(byte *keystreamBuffer, const byte *iv, size_t length);
};
class CRYPTOPP_DLL CRYPTOPP_NO_VTABLE CTR_ModePolicy : public ModePolicyCommonTemplate<AdditiveCipherAbstractPolicy>
{
public:
bool CipherIsRandomAccess() const {return true;}
- IV_Requirement IVRequirement() const {return UNIQUE_IV;}
+ IV_Requirement IVRequirement() const {return RANDOM_IV;}
static const char * CRYPTOPP_API StaticAlgorithmName() {return "CTR";}
-private:
- unsigned int GetAlignment() const {return m_cipher->BlockAlignment();}
+protected:
+ virtual void IncrementCounterBy256();
+
+ unsigned int GetAlignment() const {return m_cipher->OptimalDataAlignment();}
unsigned int GetBytesPerIteration() const {return BlockSize();}
unsigned int GetIterationsToBuffer() const {return m_cipher->OptimalNumberOfParallelBlocks();}
void WriteKeystream(byte *buffer, size_t iterationCount)
{OperateKeystream(WRITE_KEYSTREAM, buffer, NULL, iterationCount);}
bool CanOperateKeystream() const {return true;}
void OperateKeystream(KeystreamOperation operation, byte *output, const byte *input, size_t iterationCount);
- void CipherResynchronize(byte *keystreamBuffer, const byte *iv);
+ void CipherResynchronize(byte *keystreamBuffer, const byte *iv, size_t length);
void SeekToIteration(lword iterationCount);
- inline void ProcessMultipleBlocks(byte *output, const byte *input, size_t n);
-
- SecByteBlock m_counterArray;
+ AlignedSecByteBlock m_counterArray;
};
class CRYPTOPP_DLL CRYPTOPP_NO_VTABLE BlockOrientedCipherModeBase : public CipherModeBase
@@ -190,12 +183,10 @@ public:
bool IsRandomAccess() const {return false;}
bool IsSelfInverting() const {return false;}
bool IsForwardTransformation() const {return m_cipher->IsForwardTransformation();}
- void Resynchronize(const byte *iv) {memcpy_s(m_register, m_register.size(), iv, BlockSize());}
- void ProcessData(byte *outString, const byte *inString, size_t length);
+ void Resynchronize(const byte *iv, int length=-1) {memcpy_s(m_register, m_register.size(), iv, ThrowIfInvalidIVLength(length));}
protected:
bool RequireAlignedInput() const {return true;}
- virtual void ProcessBlocks(byte *outString, const byte *inString, size_t numberOfBlocks) =0;
void ResizeBuffers()
{
CipherModeBase::ResizeBuffers();
@@ -212,8 +203,7 @@ public:
{m_cipher->SetKey(key, length, params); BlockOrientedCipherModeBase::ResizeBuffers();}
IV_Requirement IVRequirement() const {return NOT_RESYNCHRONIZABLE;}
unsigned int OptimalBlockSize() const {return BlockSize() * m_cipher->OptimalNumberOfParallelBlocks();}
- void ProcessBlocks(byte *outString, const byte *inString, size_t numberOfBlocks)
- {m_cipher->ProcessAndXorMultipleBlocks(inString, NULL, outString, numberOfBlocks);}
+ void ProcessData(byte *outString, const byte *inString, size_t length);
static const char * CRYPTOPP_API StaticAlgorithmName() {return "ECB";}
};
@@ -229,7 +219,7 @@ public:
class CRYPTOPP_DLL CRYPTOPP_NO_VTABLE CBC_Encryption : public CBC_ModeBase
{
public:
- void ProcessBlocks(byte *outString, const byte *inString, size_t numberOfBlocks);
+ void ProcessData(byte *outString, const byte *inString, size_t length);
};
class CRYPTOPP_DLL CRYPTOPP_NO_VTABLE CBC_CTS_Encryption : public CBC_Encryption
@@ -253,7 +243,7 @@ protected:
class CRYPTOPP_DLL CRYPTOPP_NO_VTABLE CBC_Decryption : public CBC_ModeBase
{
public:
- void ProcessBlocks(byte *outString, const byte *inString, size_t numberOfBlocks);
+ void ProcessData(byte *outString, const byte *inString, size_t length);
protected:
void ResizeBuffers()
@@ -261,7 +251,7 @@ protected:
BlockOrientedCipherModeBase::ResizeBuffers();
m_temp.New(BlockSize());
}
- SecByteBlock m_temp;
+ AlignedSecByteBlock m_temp;
};
class CRYPTOPP_DLL CRYPTOPP_NO_VTABLE CBC_CTS_Decryption : public CBC_Decryption
@@ -313,7 +303,7 @@ public:
{this->SetCipherWithIV(cipher, iv, feedbackSize);}
std::string AlgorithmName() const
- {return this->m_cipher->AlgorithmName() + "/" + BASE::StaticAlgorithmName();}
+ {return (this->m_cipher ? this->m_cipher->AlgorithmName() + "/" : std::string("")) + BASE::StaticAlgorithmName();}
};
CRYPTOPP_DLL_TEMPLATE_CLASS CFB_CipherTemplate<AbstractPolicyHolder<CFB_CipherAbstractPolicy, CFB_ModePolicy> >;
diff --git a/nbtheory.cpp b/nbtheory.cpp
index 77dd556..3fdea4e 100644
--- a/nbtheory.cpp
+++ b/nbtheory.cpp
@@ -569,11 +569,6 @@ Integer CRT(const Integer &xp, const Integer &p, const Integer &xq, const Intege
*/
}
-Integer CRT(const Integer &xp, const Integer &p, const Integer &xq, const Integer &q)
-{
- return CRT(xp, p, xq, q, EuclideanMultiplicativeInverse(p, q));
-}
-
Integer ModularSquareRoot(const Integer &a, const Integer &p)
{
if (p%4 == 3)
@@ -1021,11 +1016,6 @@ Integer InverseLucas(const Integer &e, const Integer &m, const Integer &p, const
return CRT(p2, p, q2, q, u);
}
-Integer InverseLucas(const Integer &e, const Integer &m, const Integer &p, const Integer &q)
-{
- return InverseLucas(e, m, p, q, EuclideanMultiplicativeInverse(p, q));
-}
-
unsigned int FactoringWorkFactor(unsigned int n)
{
// extrapolated from the table in Odlyzko's "The Future of Integer Factorization"
diff --git a/nbtheory.h b/nbtheory.h
index c89de6f..6364792 100644
--- a/nbtheory.h
+++ b/nbtheory.h
@@ -69,9 +69,7 @@ inline Integer LCM(const Integer &a, const Integer &b)
inline Integer EuclideanMultiplicativeInverse(const Integer &a, const Integer &b)
{return a.InverseMod(b);}
-// use Chinese Remainder Theorem to calculate x given x mod p and x mod q
-CRYPTOPP_DLL Integer CRYPTOPP_API CRT(const Integer &xp, const Integer &p, const Integer &xq, const Integer &q);
-// use this one if u = inverse of p mod q has been precalculated
+// use Chinese Remainder Theorem to calculate x given x mod p and x mod q, and u = inverse of p mod q
CRYPTOPP_DLL Integer CRYPTOPP_API CRT(const Integer &xp, const Integer &p, const Integer &xq, const Integer &q, const Integer &u);
// if b is prime, then Jacobi(a, b) returns 0 if a%b==0, 1 if a is quadratic residue mod b, -1 otherwise
@@ -80,9 +78,7 @@ CRYPTOPP_DLL int CRYPTOPP_API Jacobi(const Integer &a, const Integer &b);
// calculates the Lucas function V_e(p, 1) mod n
CRYPTOPP_DLL Integer CRYPTOPP_API Lucas(const Integer &e, const Integer &p, const Integer &n);
-// calculates x such that m==Lucas(e, x, p*q), p q primes
-CRYPTOPP_DLL Integer CRYPTOPP_API InverseLucas(const Integer &e, const Integer &m, const Integer &p, const Integer &q);
-// use this one if u=inverse of p mod q has been precalculated
+// calculates x such that m==Lucas(e, x, p*q), p q primes, u=inverse of p mod q
CRYPTOPP_DLL Integer CRYPTOPP_API InverseLucas(const Integer &e, const Integer &m, const Integer &p, const Integer &q, const Integer &u);
inline Integer ModularExponentiation(const Integer &a, const Integer &e, const Integer &m)
@@ -91,9 +87,8 @@ inline Integer ModularExponentiation(const Integer &a, const Integer &e, const I
CRYPTOPP_DLL Integer CRYPTOPP_API ModularSquareRoot(const Integer &a, const Integer &p);
// returns x such that a==ModularExponentiation(x, e, p*q), p q primes,
// and e relatively prime to (p-1)*(q-1)
-CRYPTOPP_DLL Integer CRYPTOPP_API ModularRoot(const Integer &a, const Integer &e, const Integer &p, const Integer &q);
-// use this one if dp=d%(p-1), dq=d%(q-1), (d is inverse of e mod (p-1)*(q-1))
-// and u=inverse of p mod q have been precalculated
+// dp=d%(p-1), dq=d%(q-1), (d is inverse of e mod (p-1)*(q-1))
+// and u=inverse of p mod q
CRYPTOPP_DLL Integer CRYPTOPP_API ModularRoot(const Integer &a, const Integer &dp, const Integer &dq, const Integer &p, const Integer &q, const Integer &u);
// find r1 and r2 such that ax^2 + bx + c == 0 (mod p) for x in {r1, r2}, p prime
diff --git a/panama.cpp b/panama.cpp
index 879ea5d..da84e36 100644
--- a/panama.cpp
+++ b/panama.cpp
@@ -443,8 +443,9 @@ void PanamaCipherPolicy<B>::CipherSetKey(const NameValuePairs &params, const byt
}
template <class B>
-void PanamaCipherPolicy<B>::CipherResynchronize(byte *keystreamBuffer, const byte *iv)
+void PanamaCipherPolicy<B>::CipherResynchronize(byte *keystreamBuffer, const byte *iv, size_t length)
{
+ assert(length==32);
this->Reset();
this->Iterate(1, m_key);
if (iv && IsAligned<word32>(iv))
diff --git a/panama.h b/panama.h
index 466e528..5a23681 100644
--- a/panama.h
+++ b/panama.h
@@ -123,7 +123,7 @@ protected:
void CipherSetKey(const NameValuePairs &params, const byte *key, size_t length);
void OperateKeystream(KeystreamOperation operation, byte *output, const byte *input, size_t iterationCount);
bool CipherIsRandomAccess() const {return false;}
- void CipherResynchronize(byte *keystreamBuffer, const byte *iv);
+ void CipherResynchronize(byte *keystreamBuffer, const byte *iv, size_t length);
#if CRYPTOPP_BOOL_X86 || CRYPTOPP_BOOL_X64
unsigned int GetAlignment() const;
#endif
diff --git a/pssr.cpp b/pssr.cpp
index c11cab5..ccbe4ee 100644
--- a/pssr.cpp
+++ b/pssr.cpp
@@ -102,7 +102,7 @@ DecodingResult PSSR_MEM_Base::RecoverMessageFromRepresentative(
size_t &recoverableMessageLength = result.messageLength;
valid = (representative[representativeByteLength - 1] == (hashIdentifier.second ? 0xcc : 0xbc)) && valid;
- valid = (memcmp(representative + representativeByteLength - u, hashIdentifier.first, hashIdentifier.second) == 0) && valid;
+ valid = VerifyBufsEqual(representative + representativeByteLength - u, hashIdentifier.first, hashIdentifier.second) && valid;
GetMGF().GenerateAndMask(hash, representative, representativeByteLength - u - digestSize, h, digestSize);
if (representativeBitLength % 8 != 0)
diff --git a/pubkey.cpp b/pubkey.cpp
index 5e9c7ba..7336e8b 100644
--- a/pubkey.cpp
+++ b/pubkey.cpp
@@ -28,7 +28,7 @@ bool PK_DeterministicSignatureMessageEncodingMethod::VerifyMessageRepresentative
{
SecByteBlock computedRepresentative(BitsToBytes(representativeBitLength));
ComputeMessageRepresentative(NullRNG(), NULL, 0, hash, hashIdentifier, messageEmpty, computedRepresentative, representativeBitLength);
- return memcmp(representative, computedRepresentative, computedRepresentative.size()) == 0;
+ return VerifyBufsEqual(representative, computedRepresentative, computedRepresentative.size());
}
bool PK_RecoverableSignatureMessageEncodingMethod::VerifyMessageRepresentative(
@@ -145,7 +145,12 @@ DecodingResult TF_DecryptorBase::Decrypt(RandomNumberGenerator &rng, const byte
void TF_EncryptorBase::Encrypt(RandomNumberGenerator &rng, const byte *plaintext, size_t plaintextLength, byte *ciphertext, const NameValuePairs &parameters) const
{
if (plaintextLength > FixedMaxPlaintextLength())
- throw InvalidArgument(AlgorithmName() + ": message too long for this public key");
+ {
+ if (FixedMaxPlaintextLength() < 1)
+ throw InvalidArgument(AlgorithmName() + ": this key is too short to encrypt any messages");
+ else
+ throw InvalidArgument(AlgorithmName() + ": message length of " + IntToString(plaintextLength) + " exceeds the maximum of " + IntToString(FixedMaxPlaintextLength()) + " for this public key");
+ }
SecByteBlock paddedBlock(PaddedBlockByteLength());
GetMessageEncodingInterface().Pad(rng, plaintext, plaintextLength, paddedBlock, PaddedBlockBitLength(), parameters);
diff --git a/rc2.h b/rc2.h
index 90c2a06..ebff798 100644
--- a/rc2.h
+++ b/rc2.h
@@ -25,6 +25,7 @@ class RC2 : public RC2_Info, public BlockCipherDocumentation
{
public:
void UncheckedSetKey(const byte *userKey, unsigned int length, const NameValuePairs &params);
+ unsigned int OptimalDataAlignment() const {return GetAlignmentOf<word16>();}
protected:
FixedSizeSecBlock<word16, 64> K; // expanded key table
diff --git a/rdtables.cpp b/rdtables.cpp
index af0a072..4937932 100644
--- a/rdtables.cpp
+++ b/rdtables.cpp
@@ -161,531 +161,6 @@ const byte Rijndael::Base::Sd[256] = {
0x55, 0x21, 0x0c, 0x7d,
};
-const word32 Rijndael::Base::Te[4*256] = {
- 0xc66363a5U, 0xf87c7c84U, 0xee777799U, 0xf67b7b8dU,
- 0xfff2f20dU, 0xd66b6bbdU, 0xde6f6fb1U, 0x91c5c554U,
- 0x60303050U, 0x02010103U, 0xce6767a9U, 0x562b2b7dU,
- 0xe7fefe19U, 0xb5d7d762U, 0x4dababe6U, 0xec76769aU,
- 0x8fcaca45U, 0x1f82829dU, 0x89c9c940U, 0xfa7d7d87U,
- 0xeffafa15U, 0xb25959ebU, 0x8e4747c9U, 0xfbf0f00bU,
- 0x41adadecU, 0xb3d4d467U, 0x5fa2a2fdU, 0x45afafeaU,
- 0x239c9cbfU, 0x53a4a4f7U, 0xe4727296U, 0x9bc0c05bU,
- 0x75b7b7c2U, 0xe1fdfd1cU, 0x3d9393aeU, 0x4c26266aU,
- 0x6c36365aU, 0x7e3f3f41U, 0xf5f7f702U, 0x83cccc4fU,
- 0x6834345cU, 0x51a5a5f4U, 0xd1e5e534U, 0xf9f1f108U,
- 0xe2717193U, 0xabd8d873U, 0x62313153U, 0x2a15153fU,
- 0x0804040cU, 0x95c7c752U, 0x46232365U, 0x9dc3c35eU,
- 0x30181828U, 0x379696a1U, 0x0a05050fU, 0x2f9a9ab5U,
- 0x0e070709U, 0x24121236U, 0x1b80809bU, 0xdfe2e23dU,
- 0xcdebeb26U, 0x4e272769U, 0x7fb2b2cdU, 0xea75759fU,
- 0x1209091bU, 0x1d83839eU, 0x582c2c74U, 0x341a1a2eU,
- 0x361b1b2dU, 0xdc6e6eb2U, 0xb45a5aeeU, 0x5ba0a0fbU,
- 0xa45252f6U, 0x763b3b4dU, 0xb7d6d661U, 0x7db3b3ceU,
- 0x5229297bU, 0xdde3e33eU, 0x5e2f2f71U, 0x13848497U,
- 0xa65353f5U, 0xb9d1d168U, 0x00000000U, 0xc1eded2cU,
- 0x40202060U, 0xe3fcfc1fU, 0x79b1b1c8U, 0xb65b5bedU,
- 0xd46a6abeU, 0x8dcbcb46U, 0x67bebed9U, 0x7239394bU,
- 0x944a4adeU, 0x984c4cd4U, 0xb05858e8U, 0x85cfcf4aU,
- 0xbbd0d06bU, 0xc5efef2aU, 0x4faaaae5U, 0xedfbfb16U,
- 0x864343c5U, 0x9a4d4dd7U, 0x66333355U, 0x11858594U,
- 0x8a4545cfU, 0xe9f9f910U, 0x04020206U, 0xfe7f7f81U,
- 0xa05050f0U, 0x783c3c44U, 0x259f9fbaU, 0x4ba8a8e3U,
- 0xa25151f3U, 0x5da3a3feU, 0x804040c0U, 0x058f8f8aU,
- 0x3f9292adU, 0x219d9dbcU, 0x70383848U, 0xf1f5f504U,
- 0x63bcbcdfU, 0x77b6b6c1U, 0xafdada75U, 0x42212163U,
- 0x20101030U, 0xe5ffff1aU, 0xfdf3f30eU, 0xbfd2d26dU,
- 0x81cdcd4cU, 0x180c0c14U, 0x26131335U, 0xc3ecec2fU,
- 0xbe5f5fe1U, 0x359797a2U, 0x884444ccU, 0x2e171739U,
- 0x93c4c457U, 0x55a7a7f2U, 0xfc7e7e82U, 0x7a3d3d47U,
- 0xc86464acU, 0xba5d5de7U, 0x3219192bU, 0xe6737395U,
- 0xc06060a0U, 0x19818198U, 0x9e4f4fd1U, 0xa3dcdc7fU,
- 0x44222266U, 0x542a2a7eU, 0x3b9090abU, 0x0b888883U,
- 0x8c4646caU, 0xc7eeee29U, 0x6bb8b8d3U, 0x2814143cU,
- 0xa7dede79U, 0xbc5e5ee2U, 0x160b0b1dU, 0xaddbdb76U,
- 0xdbe0e03bU, 0x64323256U, 0x743a3a4eU, 0x140a0a1eU,
- 0x924949dbU, 0x0c06060aU, 0x4824246cU, 0xb85c5ce4U,
- 0x9fc2c25dU, 0xbdd3d36eU, 0x43acacefU, 0xc46262a6U,
- 0x399191a8U, 0x319595a4U, 0xd3e4e437U, 0xf279798bU,
- 0xd5e7e732U, 0x8bc8c843U, 0x6e373759U, 0xda6d6db7U,
- 0x018d8d8cU, 0xb1d5d564U, 0x9c4e4ed2U, 0x49a9a9e0U,
- 0xd86c6cb4U, 0xac5656faU, 0xf3f4f407U, 0xcfeaea25U,
- 0xca6565afU, 0xf47a7a8eU, 0x47aeaee9U, 0x10080818U,
- 0x6fbabad5U, 0xf0787888U, 0x4a25256fU, 0x5c2e2e72U,
- 0x381c1c24U, 0x57a6a6f1U, 0x73b4b4c7U, 0x97c6c651U,
- 0xcbe8e823U, 0xa1dddd7cU, 0xe874749cU, 0x3e1f1f21U,
- 0x964b4bddU, 0x61bdbddcU, 0x0d8b8b86U, 0x0f8a8a85U,
- 0xe0707090U, 0x7c3e3e42U, 0x71b5b5c4U, 0xcc6666aaU,
- 0x904848d8U, 0x06030305U, 0xf7f6f601U, 0x1c0e0e12U,
- 0xc26161a3U, 0x6a35355fU, 0xae5757f9U, 0x69b9b9d0U,
- 0x17868691U, 0x99c1c158U, 0x3a1d1d27U, 0x279e9eb9U,
- 0xd9e1e138U, 0xebf8f813U, 0x2b9898b3U, 0x22111133U,
- 0xd26969bbU, 0xa9d9d970U, 0x078e8e89U, 0x339494a7U,
- 0x2d9b9bb6U, 0x3c1e1e22U, 0x15878792U, 0xc9e9e920U,
- 0x87cece49U, 0xaa5555ffU, 0x50282878U, 0xa5dfdf7aU,
- 0x038c8c8fU, 0x59a1a1f8U, 0x09898980U, 0x1a0d0d17U,
- 0x65bfbfdaU, 0xd7e6e631U, 0x844242c6U, 0xd06868b8U,
- 0x824141c3U, 0x299999b0U, 0x5a2d2d77U, 0x1e0f0f11U,
- 0x7bb0b0cbU, 0xa85454fcU, 0x6dbbbbd6U, 0x2c16163aU,
-
- 0xa5c66363U, 0x84f87c7cU, 0x99ee7777U, 0x8df67b7bU,
- 0x0dfff2f2U, 0xbdd66b6bU, 0xb1de6f6fU, 0x5491c5c5U,
- 0x50603030U, 0x03020101U, 0xa9ce6767U, 0x7d562b2bU,
- 0x19e7fefeU, 0x62b5d7d7U, 0xe64dababU, 0x9aec7676U,
- 0x458fcacaU, 0x9d1f8282U, 0x4089c9c9U, 0x87fa7d7dU,
- 0x15effafaU, 0xebb25959U, 0xc98e4747U, 0x0bfbf0f0U,
- 0xec41adadU, 0x67b3d4d4U, 0xfd5fa2a2U, 0xea45afafU,
- 0xbf239c9cU, 0xf753a4a4U, 0x96e47272U, 0x5b9bc0c0U,
- 0xc275b7b7U, 0x1ce1fdfdU, 0xae3d9393U, 0x6a4c2626U,
- 0x5a6c3636U, 0x417e3f3fU, 0x02f5f7f7U, 0x4f83ccccU,
- 0x5c683434U, 0xf451a5a5U, 0x34d1e5e5U, 0x08f9f1f1U,
- 0x93e27171U, 0x73abd8d8U, 0x53623131U, 0x3f2a1515U,
- 0x0c080404U, 0x5295c7c7U, 0x65462323U, 0x5e9dc3c3U,
- 0x28301818U, 0xa1379696U, 0x0f0a0505U, 0xb52f9a9aU,
- 0x090e0707U, 0x36241212U, 0x9b1b8080U, 0x3ddfe2e2U,
- 0x26cdebebU, 0x694e2727U, 0xcd7fb2b2U, 0x9fea7575U,
- 0x1b120909U, 0x9e1d8383U, 0x74582c2cU, 0x2e341a1aU,
- 0x2d361b1bU, 0xb2dc6e6eU, 0xeeb45a5aU, 0xfb5ba0a0U,
- 0xf6a45252U, 0x4d763b3bU, 0x61b7d6d6U, 0xce7db3b3U,
- 0x7b522929U, 0x3edde3e3U, 0x715e2f2fU, 0x97138484U,
- 0xf5a65353U, 0x68b9d1d1U, 0x00000000U, 0x2cc1ededU,
- 0x60402020U, 0x1fe3fcfcU, 0xc879b1b1U, 0xedb65b5bU,
- 0xbed46a6aU, 0x468dcbcbU, 0xd967bebeU, 0x4b723939U,
- 0xde944a4aU, 0xd4984c4cU, 0xe8b05858U, 0x4a85cfcfU,
- 0x6bbbd0d0U, 0x2ac5efefU, 0xe54faaaaU, 0x16edfbfbU,
- 0xc5864343U, 0xd79a4d4dU, 0x55663333U, 0x94118585U,
- 0xcf8a4545U, 0x10e9f9f9U, 0x06040202U, 0x81fe7f7fU,
- 0xf0a05050U, 0x44783c3cU, 0xba259f9fU, 0xe34ba8a8U,
- 0xf3a25151U, 0xfe5da3a3U, 0xc0804040U, 0x8a058f8fU,
- 0xad3f9292U, 0xbc219d9dU, 0x48703838U, 0x04f1f5f5U,
- 0xdf63bcbcU, 0xc177b6b6U, 0x75afdadaU, 0x63422121U,
- 0x30201010U, 0x1ae5ffffU, 0x0efdf3f3U, 0x6dbfd2d2U,
- 0x4c81cdcdU, 0x14180c0cU, 0x35261313U, 0x2fc3ececU,
- 0xe1be5f5fU, 0xa2359797U, 0xcc884444U, 0x392e1717U,
- 0x5793c4c4U, 0xf255a7a7U, 0x82fc7e7eU, 0x477a3d3dU,
- 0xacc86464U, 0xe7ba5d5dU, 0x2b321919U, 0x95e67373U,
- 0xa0c06060U, 0x98198181U, 0xd19e4f4fU, 0x7fa3dcdcU,
- 0x66442222U, 0x7e542a2aU, 0xab3b9090U, 0x830b8888U,
- 0xca8c4646U, 0x29c7eeeeU, 0xd36bb8b8U, 0x3c281414U,
- 0x79a7dedeU, 0xe2bc5e5eU, 0x1d160b0bU, 0x76addbdbU,
- 0x3bdbe0e0U, 0x56643232U, 0x4e743a3aU, 0x1e140a0aU,
- 0xdb924949U, 0x0a0c0606U, 0x6c482424U, 0xe4b85c5cU,
- 0x5d9fc2c2U, 0x6ebdd3d3U, 0xef43acacU, 0xa6c46262U,
- 0xa8399191U, 0xa4319595U, 0x37d3e4e4U, 0x8bf27979U,
- 0x32d5e7e7U, 0x438bc8c8U, 0x596e3737U, 0xb7da6d6dU,
- 0x8c018d8dU, 0x64b1d5d5U, 0xd29c4e4eU, 0xe049a9a9U,
- 0xb4d86c6cU, 0xfaac5656U, 0x07f3f4f4U, 0x25cfeaeaU,
- 0xafca6565U, 0x8ef47a7aU, 0xe947aeaeU, 0x18100808U,
- 0xd56fbabaU, 0x88f07878U, 0x6f4a2525U, 0x725c2e2eU,
- 0x24381c1cU, 0xf157a6a6U, 0xc773b4b4U, 0x5197c6c6U,
- 0x23cbe8e8U, 0x7ca1ddddU, 0x9ce87474U, 0x213e1f1fU,
- 0xdd964b4bU, 0xdc61bdbdU, 0x860d8b8bU, 0x850f8a8aU,
- 0x90e07070U, 0x427c3e3eU, 0xc471b5b5U, 0xaacc6666U,
- 0xd8904848U, 0x05060303U, 0x01f7f6f6U, 0x121c0e0eU,
- 0xa3c26161U, 0x5f6a3535U, 0xf9ae5757U, 0xd069b9b9U,
- 0x91178686U, 0x5899c1c1U, 0x273a1d1dU, 0xb9279e9eU,
- 0x38d9e1e1U, 0x13ebf8f8U, 0xb32b9898U, 0x33221111U,
- 0xbbd26969U, 0x70a9d9d9U, 0x89078e8eU, 0xa7339494U,
- 0xb62d9b9bU, 0x223c1e1eU, 0x92158787U, 0x20c9e9e9U,
- 0x4987ceceU, 0xffaa5555U, 0x78502828U, 0x7aa5dfdfU,
- 0x8f038c8cU, 0xf859a1a1U, 0x80098989U, 0x171a0d0dU,
- 0xda65bfbfU, 0x31d7e6e6U, 0xc6844242U, 0xb8d06868U,
- 0xc3824141U, 0xb0299999U, 0x775a2d2dU, 0x111e0f0fU,
- 0xcb7bb0b0U, 0xfca85454U, 0xd66dbbbbU, 0x3a2c1616U,
-
- 0x63a5c663U, 0x7c84f87cU, 0x7799ee77U, 0x7b8df67bU,
- 0xf20dfff2U, 0x6bbdd66bU, 0x6fb1de6fU, 0xc55491c5U,
- 0x30506030U, 0x01030201U, 0x67a9ce67U, 0x2b7d562bU,
- 0xfe19e7feU, 0xd762b5d7U, 0xabe64dabU, 0x769aec76U,
- 0xca458fcaU, 0x829d1f82U, 0xc94089c9U, 0x7d87fa7dU,
- 0xfa15effaU, 0x59ebb259U, 0x47c98e47U, 0xf00bfbf0U,
- 0xadec41adU, 0xd467b3d4U, 0xa2fd5fa2U, 0xafea45afU,
- 0x9cbf239cU, 0xa4f753a4U, 0x7296e472U, 0xc05b9bc0U,
- 0xb7c275b7U, 0xfd1ce1fdU, 0x93ae3d93U, 0x266a4c26U,
- 0x365a6c36U, 0x3f417e3fU, 0xf702f5f7U, 0xcc4f83ccU,
- 0x345c6834U, 0xa5f451a5U, 0xe534d1e5U, 0xf108f9f1U,
- 0x7193e271U, 0xd873abd8U, 0x31536231U, 0x153f2a15U,
- 0x040c0804U, 0xc75295c7U, 0x23654623U, 0xc35e9dc3U,
- 0x18283018U, 0x96a13796U, 0x050f0a05U, 0x9ab52f9aU,
- 0x07090e07U, 0x12362412U, 0x809b1b80U, 0xe23ddfe2U,
- 0xeb26cdebU, 0x27694e27U, 0xb2cd7fb2U, 0x759fea75U,
- 0x091b1209U, 0x839e1d83U, 0x2c74582cU, 0x1a2e341aU,
- 0x1b2d361bU, 0x6eb2dc6eU, 0x5aeeb45aU, 0xa0fb5ba0U,
- 0x52f6a452U, 0x3b4d763bU, 0xd661b7d6U, 0xb3ce7db3U,
- 0x297b5229U, 0xe33edde3U, 0x2f715e2fU, 0x84971384U,
- 0x53f5a653U, 0xd168b9d1U, 0x00000000U, 0xed2cc1edU,
- 0x20604020U, 0xfc1fe3fcU, 0xb1c879b1U, 0x5bedb65bU,
- 0x6abed46aU, 0xcb468dcbU, 0xbed967beU, 0x394b7239U,
- 0x4ade944aU, 0x4cd4984cU, 0x58e8b058U, 0xcf4a85cfU,
- 0xd06bbbd0U, 0xef2ac5efU, 0xaae54faaU, 0xfb16edfbU,
- 0x43c58643U, 0x4dd79a4dU, 0x33556633U, 0x85941185U,
- 0x45cf8a45U, 0xf910e9f9U, 0x02060402U, 0x7f81fe7fU,
- 0x50f0a050U, 0x3c44783cU, 0x9fba259fU, 0xa8e34ba8U,
- 0x51f3a251U, 0xa3fe5da3U, 0x40c08040U, 0x8f8a058fU,
- 0x92ad3f92U, 0x9dbc219dU, 0x38487038U, 0xf504f1f5U,
- 0xbcdf63bcU, 0xb6c177b6U, 0xda75afdaU, 0x21634221U,
- 0x10302010U, 0xff1ae5ffU, 0xf30efdf3U, 0xd26dbfd2U,
- 0xcd4c81cdU, 0x0c14180cU, 0x13352613U, 0xec2fc3ecU,
- 0x5fe1be5fU, 0x97a23597U, 0x44cc8844U, 0x17392e17U,
- 0xc45793c4U, 0xa7f255a7U, 0x7e82fc7eU, 0x3d477a3dU,
- 0x64acc864U, 0x5de7ba5dU, 0x192b3219U, 0x7395e673U,
- 0x60a0c060U, 0x81981981U, 0x4fd19e4fU, 0xdc7fa3dcU,
- 0x22664422U, 0x2a7e542aU, 0x90ab3b90U, 0x88830b88U,
- 0x46ca8c46U, 0xee29c7eeU, 0xb8d36bb8U, 0x143c2814U,
- 0xde79a7deU, 0x5ee2bc5eU, 0x0b1d160bU, 0xdb76addbU,
- 0xe03bdbe0U, 0x32566432U, 0x3a4e743aU, 0x0a1e140aU,
- 0x49db9249U, 0x060a0c06U, 0x246c4824U, 0x5ce4b85cU,
- 0xc25d9fc2U, 0xd36ebdd3U, 0xacef43acU, 0x62a6c462U,
- 0x91a83991U, 0x95a43195U, 0xe437d3e4U, 0x798bf279U,
- 0xe732d5e7U, 0xc8438bc8U, 0x37596e37U, 0x6db7da6dU,
- 0x8d8c018dU, 0xd564b1d5U, 0x4ed29c4eU, 0xa9e049a9U,
- 0x6cb4d86cU, 0x56faac56U, 0xf407f3f4U, 0xea25cfeaU,
- 0x65afca65U, 0x7a8ef47aU, 0xaee947aeU, 0x08181008U,
- 0xbad56fbaU, 0x7888f078U, 0x256f4a25U, 0x2e725c2eU,
- 0x1c24381cU, 0xa6f157a6U, 0xb4c773b4U, 0xc65197c6U,
- 0xe823cbe8U, 0xdd7ca1ddU, 0x749ce874U, 0x1f213e1fU,
- 0x4bdd964bU, 0xbddc61bdU, 0x8b860d8bU, 0x8a850f8aU,
- 0x7090e070U, 0x3e427c3eU, 0xb5c471b5U, 0x66aacc66U,
- 0x48d89048U, 0x03050603U, 0xf601f7f6U, 0x0e121c0eU,
- 0x61a3c261U, 0x355f6a35U, 0x57f9ae57U, 0xb9d069b9U,
- 0x86911786U, 0xc15899c1U, 0x1d273a1dU, 0x9eb9279eU,
- 0xe138d9e1U, 0xf813ebf8U, 0x98b32b98U, 0x11332211U,
- 0x69bbd269U, 0xd970a9d9U, 0x8e89078eU, 0x94a73394U,
- 0x9bb62d9bU, 0x1e223c1eU, 0x87921587U, 0xe920c9e9U,
- 0xce4987ceU, 0x55ffaa55U, 0x28785028U, 0xdf7aa5dfU,
- 0x8c8f038cU, 0xa1f859a1U, 0x89800989U, 0x0d171a0dU,
- 0xbfda65bfU, 0xe631d7e6U, 0x42c68442U, 0x68b8d068U,
- 0x41c38241U, 0x99b02999U, 0x2d775a2dU, 0x0f111e0fU,
- 0xb0cb7bb0U, 0x54fca854U, 0xbbd66dbbU, 0x163a2c16U,
-
- 0x6363a5c6U, 0x7c7c84f8U, 0x777799eeU, 0x7b7b8df6U,
- 0xf2f20dffU, 0x6b6bbdd6U, 0x6f6fb1deU, 0xc5c55491U,
- 0x30305060U, 0x01010302U, 0x6767a9ceU, 0x2b2b7d56U,
- 0xfefe19e7U, 0xd7d762b5U, 0xababe64dU, 0x76769aecU,
- 0xcaca458fU, 0x82829d1fU, 0xc9c94089U, 0x7d7d87faU,
- 0xfafa15efU, 0x5959ebb2U, 0x4747c98eU, 0xf0f00bfbU,
- 0xadadec41U, 0xd4d467b3U, 0xa2a2fd5fU, 0xafafea45U,
- 0x9c9cbf23U, 0xa4a4f753U, 0x727296e4U, 0xc0c05b9bU,
- 0xb7b7c275U, 0xfdfd1ce1U, 0x9393ae3dU, 0x26266a4cU,
- 0x36365a6cU, 0x3f3f417eU, 0xf7f702f5U, 0xcccc4f83U,
- 0x34345c68U, 0xa5a5f451U, 0xe5e534d1U, 0xf1f108f9U,
- 0x717193e2U, 0xd8d873abU, 0x31315362U, 0x15153f2aU,
- 0x04040c08U, 0xc7c75295U, 0x23236546U, 0xc3c35e9dU,
- 0x18182830U, 0x9696a137U, 0x05050f0aU, 0x9a9ab52fU,
- 0x0707090eU, 0x12123624U, 0x80809b1bU, 0xe2e23ddfU,
- 0xebeb26cdU, 0x2727694eU, 0xb2b2cd7fU, 0x75759feaU,
- 0x09091b12U, 0x83839e1dU, 0x2c2c7458U, 0x1a1a2e34U,
- 0x1b1b2d36U, 0x6e6eb2dcU, 0x5a5aeeb4U, 0xa0a0fb5bU,
- 0x5252f6a4U, 0x3b3b4d76U, 0xd6d661b7U, 0xb3b3ce7dU,
- 0x29297b52U, 0xe3e33eddU, 0x2f2f715eU, 0x84849713U,
- 0x5353f5a6U, 0xd1d168b9U, 0x00000000U, 0xeded2cc1U,
- 0x20206040U, 0xfcfc1fe3U, 0xb1b1c879U, 0x5b5bedb6U,
- 0x6a6abed4U, 0xcbcb468dU, 0xbebed967U, 0x39394b72U,
- 0x4a4ade94U, 0x4c4cd498U, 0x5858e8b0U, 0xcfcf4a85U,
- 0xd0d06bbbU, 0xefef2ac5U, 0xaaaae54fU, 0xfbfb16edU,
- 0x4343c586U, 0x4d4dd79aU, 0x33335566U, 0x85859411U,
- 0x4545cf8aU, 0xf9f910e9U, 0x02020604U, 0x7f7f81feU,
- 0x5050f0a0U, 0x3c3c4478U, 0x9f9fba25U, 0xa8a8e34bU,
- 0x5151f3a2U, 0xa3a3fe5dU, 0x4040c080U, 0x8f8f8a05U,
- 0x9292ad3fU, 0x9d9dbc21U, 0x38384870U, 0xf5f504f1U,
- 0xbcbcdf63U, 0xb6b6c177U, 0xdada75afU, 0x21216342U,
- 0x10103020U, 0xffff1ae5U, 0xf3f30efdU, 0xd2d26dbfU,
- 0xcdcd4c81U, 0x0c0c1418U, 0x13133526U, 0xecec2fc3U,
- 0x5f5fe1beU, 0x9797a235U, 0x4444cc88U, 0x1717392eU,
- 0xc4c45793U, 0xa7a7f255U, 0x7e7e82fcU, 0x3d3d477aU,
- 0x6464acc8U, 0x5d5de7baU, 0x19192b32U, 0x737395e6U,
- 0x6060a0c0U, 0x81819819U, 0x4f4fd19eU, 0xdcdc7fa3U,
- 0x22226644U, 0x2a2a7e54U, 0x9090ab3bU, 0x8888830bU,
- 0x4646ca8cU, 0xeeee29c7U, 0xb8b8d36bU, 0x14143c28U,
- 0xdede79a7U, 0x5e5ee2bcU, 0x0b0b1d16U, 0xdbdb76adU,
- 0xe0e03bdbU, 0x32325664U, 0x3a3a4e74U, 0x0a0a1e14U,
- 0x4949db92U, 0x06060a0cU, 0x24246c48U, 0x5c5ce4b8U,
- 0xc2c25d9fU, 0xd3d36ebdU, 0xacacef43U, 0x6262a6c4U,
- 0x9191a839U, 0x9595a431U, 0xe4e437d3U, 0x79798bf2U,
- 0xe7e732d5U, 0xc8c8438bU, 0x3737596eU, 0x6d6db7daU,
- 0x8d8d8c01U, 0xd5d564b1U, 0x4e4ed29cU, 0xa9a9e049U,
- 0x6c6cb4d8U, 0x5656faacU, 0xf4f407f3U, 0xeaea25cfU,
- 0x6565afcaU, 0x7a7a8ef4U, 0xaeaee947U, 0x08081810U,
- 0xbabad56fU, 0x787888f0U, 0x25256f4aU, 0x2e2e725cU,
- 0x1c1c2438U, 0xa6a6f157U, 0xb4b4c773U, 0xc6c65197U,
- 0xe8e823cbU, 0xdddd7ca1U, 0x74749ce8U, 0x1f1f213eU,
- 0x4b4bdd96U, 0xbdbddc61U, 0x8b8b860dU, 0x8a8a850fU,
- 0x707090e0U, 0x3e3e427cU, 0xb5b5c471U, 0x6666aaccU,
- 0x4848d890U, 0x03030506U, 0xf6f601f7U, 0x0e0e121cU,
- 0x6161a3c2U, 0x35355f6aU, 0x5757f9aeU, 0xb9b9d069U,
- 0x86869117U, 0xc1c15899U, 0x1d1d273aU, 0x9e9eb927U,
- 0xe1e138d9U, 0xf8f813ebU, 0x9898b32bU, 0x11113322U,
- 0x6969bbd2U, 0xd9d970a9U, 0x8e8e8907U, 0x9494a733U,
- 0x9b9bb62dU, 0x1e1e223cU, 0x87879215U, 0xe9e920c9U,
- 0xcece4987U, 0x5555ffaaU, 0x28287850U, 0xdfdf7aa5U,
- 0x8c8c8f03U, 0xa1a1f859U, 0x89898009U, 0x0d0d171aU,
- 0xbfbfda65U, 0xe6e631d7U, 0x4242c684U, 0x6868b8d0U,
- 0x4141c382U, 0x9999b029U, 0x2d2d775aU, 0x0f0f111eU,
- 0xb0b0cb7bU, 0x5454fca8U, 0xbbbbd66dU, 0x16163a2cU,
-};
-
-const word32 Rijndael::Base::Td[4*256] = {
- 0x51f4a750U, 0x7e416553U, 0x1a17a4c3U, 0x3a275e96U,
- 0x3bab6bcbU, 0x1f9d45f1U, 0xacfa58abU, 0x4be30393U,
- 0x2030fa55U, 0xad766df6U, 0x88cc7691U, 0xf5024c25U,
- 0x4fe5d7fcU, 0xc52acbd7U, 0x26354480U, 0xb562a38fU,
- 0xdeb15a49U, 0x25ba1b67U, 0x45ea0e98U, 0x5dfec0e1U,
- 0xc32f7502U, 0x814cf012U, 0x8d4697a3U, 0x6bd3f9c6U,
- 0x038f5fe7U, 0x15929c95U, 0xbf6d7aebU, 0x955259daU,
- 0xd4be832dU, 0x587421d3U, 0x49e06929U, 0x8ec9c844U,
- 0x75c2896aU, 0xf48e7978U, 0x99583e6bU, 0x27b971ddU,
- 0xbee14fb6U, 0xf088ad17U, 0xc920ac66U, 0x7dce3ab4U,
- 0x63df4a18U, 0xe51a3182U, 0x97513360U, 0x62537f45U,
- 0xb16477e0U, 0xbb6bae84U, 0xfe81a01cU, 0xf9082b94U,
- 0x70486858U, 0x8f45fd19U, 0x94de6c87U, 0x527bf8b7U,
- 0xab73d323U, 0x724b02e2U, 0xe31f8f57U, 0x6655ab2aU,
- 0xb2eb2807U, 0x2fb5c203U, 0x86c57b9aU, 0xd33708a5U,
- 0x302887f2U, 0x23bfa5b2U, 0x02036abaU, 0xed16825cU,
- 0x8acf1c2bU, 0xa779b492U, 0xf307f2f0U, 0x4e69e2a1U,
- 0x65daf4cdU, 0x0605bed5U, 0xd134621fU, 0xc4a6fe8aU,
- 0x342e539dU, 0xa2f355a0U, 0x058ae132U, 0xa4f6eb75U,
- 0x0b83ec39U, 0x4060efaaU, 0x5e719f06U, 0xbd6e1051U,
- 0x3e218af9U, 0x96dd063dU, 0xdd3e05aeU, 0x4de6bd46U,
- 0x91548db5U, 0x71c45d05U, 0x0406d46fU, 0x605015ffU,
- 0x1998fb24U, 0xd6bde997U, 0x894043ccU, 0x67d99e77U,
- 0xb0e842bdU, 0x07898b88U, 0xe7195b38U, 0x79c8eedbU,
- 0xa17c0a47U, 0x7c420fe9U, 0xf8841ec9U, 0x00000000U,
- 0x09808683U, 0x322bed48U, 0x1e1170acU, 0x6c5a724eU,
- 0xfd0efffbU, 0x0f853856U, 0x3daed51eU, 0x362d3927U,
- 0x0a0fd964U, 0x685ca621U, 0x9b5b54d1U, 0x24362e3aU,
- 0x0c0a67b1U, 0x9357e70fU, 0xb4ee96d2U, 0x1b9b919eU,
- 0x80c0c54fU, 0x61dc20a2U, 0x5a774b69U, 0x1c121a16U,
- 0xe293ba0aU, 0xc0a02ae5U, 0x3c22e043U, 0x121b171dU,
- 0x0e090d0bU, 0xf28bc7adU, 0x2db6a8b9U, 0x141ea9c8U,
- 0x57f11985U, 0xaf75074cU, 0xee99ddbbU, 0xa37f60fdU,
- 0xf701269fU, 0x5c72f5bcU, 0x44663bc5U, 0x5bfb7e34U,
- 0x8b432976U, 0xcb23c6dcU, 0xb6edfc68U, 0xb8e4f163U,
- 0xd731dccaU, 0x42638510U, 0x13972240U, 0x84c61120U,
- 0x854a247dU, 0xd2bb3df8U, 0xaef93211U, 0xc729a16dU,
- 0x1d9e2f4bU, 0xdcb230f3U, 0x0d8652ecU, 0x77c1e3d0U,
- 0x2bb3166cU, 0xa970b999U, 0x119448faU, 0x47e96422U,
- 0xa8fc8cc4U, 0xa0f03f1aU, 0x567d2cd8U, 0x223390efU,
- 0x87494ec7U, 0xd938d1c1U, 0x8ccaa2feU, 0x98d40b36U,
- 0xa6f581cfU, 0xa57ade28U, 0xdab78e26U, 0x3fadbfa4U,
- 0x2c3a9de4U, 0x5078920dU, 0x6a5fcc9bU, 0x547e4662U,
- 0xf68d13c2U, 0x90d8b8e8U, 0x2e39f75eU, 0x82c3aff5U,
- 0x9f5d80beU, 0x69d0937cU, 0x6fd52da9U, 0xcf2512b3U,
- 0xc8ac993bU, 0x10187da7U, 0xe89c636eU, 0xdb3bbb7bU,
- 0xcd267809U, 0x6e5918f4U, 0xec9ab701U, 0x834f9aa8U,
- 0xe6956e65U, 0xaaffe67eU, 0x21bccf08U, 0xef15e8e6U,
- 0xbae79bd9U, 0x4a6f36ceU, 0xea9f09d4U, 0x29b07cd6U,
- 0x31a4b2afU, 0x2a3f2331U, 0xc6a59430U, 0x35a266c0U,
- 0x744ebc37U, 0xfc82caa6U, 0xe090d0b0U, 0x33a7d815U,
- 0xf104984aU, 0x41ecdaf7U, 0x7fcd500eU, 0x1791f62fU,
- 0x764dd68dU, 0x43efb04dU, 0xccaa4d54U, 0xe49604dfU,
- 0x9ed1b5e3U, 0x4c6a881bU, 0xc12c1fb8U, 0x4665517fU,
- 0x9d5eea04U, 0x018c355dU, 0xfa877473U, 0xfb0b412eU,
- 0xb3671d5aU, 0x92dbd252U, 0xe9105633U, 0x6dd64713U,
- 0x9ad7618cU, 0x37a10c7aU, 0x59f8148eU, 0xeb133c89U,
- 0xcea927eeU, 0xb761c935U, 0xe11ce5edU, 0x7a47b13cU,
- 0x9cd2df59U, 0x55f2733fU, 0x1814ce79U, 0x73c737bfU,
- 0x53f7cdeaU, 0x5ffdaa5bU, 0xdf3d6f14U, 0x7844db86U,
- 0xcaaff381U, 0xb968c43eU, 0x3824342cU, 0xc2a3405fU,
- 0x161dc372U, 0xbce2250cU, 0x283c498bU, 0xff0d9541U,
- 0x39a80171U, 0x080cb3deU, 0xd8b4e49cU, 0x6456c190U,
- 0x7bcb8461U, 0xd532b670U, 0x486c5c74U, 0xd0b85742U,
-
- 0x5051f4a7U, 0x537e4165U, 0xc31a17a4U, 0x963a275eU,
- 0xcb3bab6bU, 0xf11f9d45U, 0xabacfa58U, 0x934be303U,
- 0x552030faU, 0xf6ad766dU, 0x9188cc76U, 0x25f5024cU,
- 0xfc4fe5d7U, 0xd7c52acbU, 0x80263544U, 0x8fb562a3U,
- 0x49deb15aU, 0x6725ba1bU, 0x9845ea0eU, 0xe15dfec0U,
- 0x02c32f75U, 0x12814cf0U, 0xa38d4697U, 0xc66bd3f9U,
- 0xe7038f5fU, 0x9515929cU, 0xebbf6d7aU, 0xda955259U,
- 0x2dd4be83U, 0xd3587421U, 0x2949e069U, 0x448ec9c8U,
- 0x6a75c289U, 0x78f48e79U, 0x6b99583eU, 0xdd27b971U,
- 0xb6bee14fU, 0x17f088adU, 0x66c920acU, 0xb47dce3aU,
- 0x1863df4aU, 0x82e51a31U, 0x60975133U, 0x4562537fU,
- 0xe0b16477U, 0x84bb6baeU, 0x1cfe81a0U, 0x94f9082bU,
- 0x58704868U, 0x198f45fdU, 0x8794de6cU, 0xb7527bf8U,
- 0x23ab73d3U, 0xe2724b02U, 0x57e31f8fU, 0x2a6655abU,
- 0x07b2eb28U, 0x032fb5c2U, 0x9a86c57bU, 0xa5d33708U,
- 0xf2302887U, 0xb223bfa5U, 0xba02036aU, 0x5ced1682U,
- 0x2b8acf1cU, 0x92a779b4U, 0xf0f307f2U, 0xa14e69e2U,
- 0xcd65daf4U, 0xd50605beU, 0x1fd13462U, 0x8ac4a6feU,
- 0x9d342e53U, 0xa0a2f355U, 0x32058ae1U, 0x75a4f6ebU,
- 0x390b83ecU, 0xaa4060efU, 0x065e719fU, 0x51bd6e10U,
- 0xf93e218aU, 0x3d96dd06U, 0xaedd3e05U, 0x464de6bdU,
- 0xb591548dU, 0x0571c45dU, 0x6f0406d4U, 0xff605015U,
- 0x241998fbU, 0x97d6bde9U, 0xcc894043U, 0x7767d99eU,
- 0xbdb0e842U, 0x8807898bU, 0x38e7195bU, 0xdb79c8eeU,
- 0x47a17c0aU, 0xe97c420fU, 0xc9f8841eU, 0x00000000U,
- 0x83098086U, 0x48322bedU, 0xac1e1170U, 0x4e6c5a72U,
- 0xfbfd0effU, 0x560f8538U, 0x1e3daed5U, 0x27362d39U,
- 0x640a0fd9U, 0x21685ca6U, 0xd19b5b54U, 0x3a24362eU,
- 0xb10c0a67U, 0x0f9357e7U, 0xd2b4ee96U, 0x9e1b9b91U,
- 0x4f80c0c5U, 0xa261dc20U, 0x695a774bU, 0x161c121aU,
- 0x0ae293baU, 0xe5c0a02aU, 0x433c22e0U, 0x1d121b17U,
- 0x0b0e090dU, 0xadf28bc7U, 0xb92db6a8U, 0xc8141ea9U,
- 0x8557f119U, 0x4caf7507U, 0xbbee99ddU, 0xfda37f60U,
- 0x9ff70126U, 0xbc5c72f5U, 0xc544663bU, 0x345bfb7eU,
- 0x768b4329U, 0xdccb23c6U, 0x68b6edfcU, 0x63b8e4f1U,
- 0xcad731dcU, 0x10426385U, 0x40139722U, 0x2084c611U,
- 0x7d854a24U, 0xf8d2bb3dU, 0x11aef932U, 0x6dc729a1U,
- 0x4b1d9e2fU, 0xf3dcb230U, 0xec0d8652U, 0xd077c1e3U,
- 0x6c2bb316U, 0x99a970b9U, 0xfa119448U, 0x2247e964U,
- 0xc4a8fc8cU, 0x1aa0f03fU, 0xd8567d2cU, 0xef223390U,
- 0xc787494eU, 0xc1d938d1U, 0xfe8ccaa2U, 0x3698d40bU,
- 0xcfa6f581U, 0x28a57adeU, 0x26dab78eU, 0xa43fadbfU,
- 0xe42c3a9dU, 0x0d507892U, 0x9b6a5fccU, 0x62547e46U,
- 0xc2f68d13U, 0xe890d8b8U, 0x5e2e39f7U, 0xf582c3afU,
- 0xbe9f5d80U, 0x7c69d093U, 0xa96fd52dU, 0xb3cf2512U,
- 0x3bc8ac99U, 0xa710187dU, 0x6ee89c63U, 0x7bdb3bbbU,
- 0x09cd2678U, 0xf46e5918U, 0x01ec9ab7U, 0xa8834f9aU,
- 0x65e6956eU, 0x7eaaffe6U, 0x0821bccfU, 0xe6ef15e8U,
- 0xd9bae79bU, 0xce4a6f36U, 0xd4ea9f09U, 0xd629b07cU,
- 0xaf31a4b2U, 0x312a3f23U, 0x30c6a594U, 0xc035a266U,
- 0x37744ebcU, 0xa6fc82caU, 0xb0e090d0U, 0x1533a7d8U,
- 0x4af10498U, 0xf741ecdaU, 0x0e7fcd50U, 0x2f1791f6U,
- 0x8d764dd6U, 0x4d43efb0U, 0x54ccaa4dU, 0xdfe49604U,
- 0xe39ed1b5U, 0x1b4c6a88U, 0xb8c12c1fU, 0x7f466551U,
- 0x049d5eeaU, 0x5d018c35U, 0x73fa8774U, 0x2efb0b41U,
- 0x5ab3671dU, 0x5292dbd2U, 0x33e91056U, 0x136dd647U,
- 0x8c9ad761U, 0x7a37a10cU, 0x8e59f814U, 0x89eb133cU,
- 0xeecea927U, 0x35b761c9U, 0xede11ce5U, 0x3c7a47b1U,
- 0x599cd2dfU, 0x3f55f273U, 0x791814ceU, 0xbf73c737U,
- 0xea53f7cdU, 0x5b5ffdaaU, 0x14df3d6fU, 0x867844dbU,
- 0x81caaff3U, 0x3eb968c4U, 0x2c382434U, 0x5fc2a340U,
- 0x72161dc3U, 0x0cbce225U, 0x8b283c49U, 0x41ff0d95U,
- 0x7139a801U, 0xde080cb3U, 0x9cd8b4e4U, 0x906456c1U,
- 0x617bcb84U, 0x70d532b6U, 0x74486c5cU, 0x42d0b857U,
-
- 0xa75051f4U, 0x65537e41U, 0xa4c31a17U, 0x5e963a27U,
- 0x6bcb3babU, 0x45f11f9dU, 0x58abacfaU, 0x03934be3U,
- 0xfa552030U, 0x6df6ad76U, 0x769188ccU, 0x4c25f502U,
- 0xd7fc4fe5U, 0xcbd7c52aU, 0x44802635U, 0xa38fb562U,
- 0x5a49deb1U, 0x1b6725baU, 0x0e9845eaU, 0xc0e15dfeU,
- 0x7502c32fU, 0xf012814cU, 0x97a38d46U, 0xf9c66bd3U,
- 0x5fe7038fU, 0x9c951592U, 0x7aebbf6dU, 0x59da9552U,
- 0x832dd4beU, 0x21d35874U, 0x692949e0U, 0xc8448ec9U,
- 0x896a75c2U, 0x7978f48eU, 0x3e6b9958U, 0x71dd27b9U,
- 0x4fb6bee1U, 0xad17f088U, 0xac66c920U, 0x3ab47dceU,
- 0x4a1863dfU, 0x3182e51aU, 0x33609751U, 0x7f456253U,
- 0x77e0b164U, 0xae84bb6bU, 0xa01cfe81U, 0x2b94f908U,
- 0x68587048U, 0xfd198f45U, 0x6c8794deU, 0xf8b7527bU,
- 0xd323ab73U, 0x02e2724bU, 0x8f57e31fU, 0xab2a6655U,
- 0x2807b2ebU, 0xc2032fb5U, 0x7b9a86c5U, 0x08a5d337U,
- 0x87f23028U, 0xa5b223bfU, 0x6aba0203U, 0x825ced16U,
- 0x1c2b8acfU, 0xb492a779U, 0xf2f0f307U, 0xe2a14e69U,
- 0xf4cd65daU, 0xbed50605U, 0x621fd134U, 0xfe8ac4a6U,
- 0x539d342eU, 0x55a0a2f3U, 0xe132058aU, 0xeb75a4f6U,
- 0xec390b83U, 0xefaa4060U, 0x9f065e71U, 0x1051bd6eU,
-
- 0x8af93e21U, 0x063d96ddU, 0x05aedd3eU, 0xbd464de6U,
- 0x8db59154U, 0x5d0571c4U, 0xd46f0406U, 0x15ff6050U,
- 0xfb241998U, 0xe997d6bdU, 0x43cc8940U, 0x9e7767d9U,
- 0x42bdb0e8U, 0x8b880789U, 0x5b38e719U, 0xeedb79c8U,
- 0x0a47a17cU, 0x0fe97c42U, 0x1ec9f884U, 0x00000000U,
- 0x86830980U, 0xed48322bU, 0x70ac1e11U, 0x724e6c5aU,
- 0xfffbfd0eU, 0x38560f85U, 0xd51e3daeU, 0x3927362dU,
- 0xd9640a0fU, 0xa621685cU, 0x54d19b5bU, 0x2e3a2436U,
- 0x67b10c0aU, 0xe70f9357U, 0x96d2b4eeU, 0x919e1b9bU,
- 0xc54f80c0U, 0x20a261dcU, 0x4b695a77U, 0x1a161c12U,
- 0xba0ae293U, 0x2ae5c0a0U, 0xe0433c22U, 0x171d121bU,
- 0x0d0b0e09U, 0xc7adf28bU, 0xa8b92db6U, 0xa9c8141eU,
- 0x198557f1U, 0x074caf75U, 0xddbbee99U, 0x60fda37fU,
- 0x269ff701U, 0xf5bc5c72U, 0x3bc54466U, 0x7e345bfbU,
- 0x29768b43U, 0xc6dccb23U, 0xfc68b6edU, 0xf163b8e4U,
- 0xdccad731U, 0x85104263U, 0x22401397U, 0x112084c6U,
- 0x247d854aU, 0x3df8d2bbU, 0x3211aef9U, 0xa16dc729U,
- 0x2f4b1d9eU, 0x30f3dcb2U, 0x52ec0d86U, 0xe3d077c1U,
- 0x166c2bb3U, 0xb999a970U, 0x48fa1194U, 0x642247e9U,
- 0x8cc4a8fcU, 0x3f1aa0f0U, 0x2cd8567dU, 0x90ef2233U,
- 0x4ec78749U, 0xd1c1d938U, 0xa2fe8ccaU, 0x0b3698d4U,
- 0x81cfa6f5U, 0xde28a57aU, 0x8e26dab7U, 0xbfa43fadU,
- 0x9de42c3aU, 0x920d5078U, 0xcc9b6a5fU, 0x4662547eU,
- 0x13c2f68dU, 0xb8e890d8U, 0xf75e2e39U, 0xaff582c3U,
- 0x80be9f5dU, 0x937c69d0U, 0x2da96fd5U, 0x12b3cf25U,
- 0x993bc8acU, 0x7da71018U, 0x636ee89cU, 0xbb7bdb3bU,
- 0x7809cd26U, 0x18f46e59U, 0xb701ec9aU, 0x9aa8834fU,
- 0x6e65e695U, 0xe67eaaffU, 0xcf0821bcU, 0xe8e6ef15U,
- 0x9bd9bae7U, 0x36ce4a6fU, 0x09d4ea9fU, 0x7cd629b0U,
- 0xb2af31a4U, 0x23312a3fU, 0x9430c6a5U, 0x66c035a2U,
- 0xbc37744eU, 0xcaa6fc82U, 0xd0b0e090U, 0xd81533a7U,
- 0x984af104U, 0xdaf741ecU, 0x500e7fcdU, 0xf62f1791U,
- 0xd68d764dU, 0xb04d43efU, 0x4d54ccaaU, 0x04dfe496U,
- 0xb5e39ed1U, 0x881b4c6aU, 0x1fb8c12cU, 0x517f4665U,
- 0xea049d5eU, 0x355d018cU, 0x7473fa87U, 0x412efb0bU,
- 0x1d5ab367U, 0xd25292dbU, 0x5633e910U, 0x47136dd6U,
- 0x618c9ad7U, 0x0c7a37a1U, 0x148e59f8U, 0x3c89eb13U,
- 0x27eecea9U, 0xc935b761U, 0xe5ede11cU, 0xb13c7a47U,
- 0xdf599cd2U, 0x733f55f2U, 0xce791814U, 0x37bf73c7U,
- 0xcdea53f7U, 0xaa5b5ffdU, 0x6f14df3dU, 0xdb867844U,
- 0xf381caafU, 0xc43eb968U, 0x342c3824U, 0x405fc2a3U,
- 0xc372161dU, 0x250cbce2U, 0x498b283cU, 0x9541ff0dU,
- 0x017139a8U, 0xb3de080cU, 0xe49cd8b4U, 0xc1906456U,
- 0x84617bcbU, 0xb670d532U, 0x5c74486cU, 0x5742d0b8U,
-
- 0xf4a75051U, 0x4165537eU, 0x17a4c31aU, 0x275e963aU,
- 0xab6bcb3bU, 0x9d45f11fU, 0xfa58abacU, 0xe303934bU,
- 0x30fa5520U, 0x766df6adU, 0xcc769188U, 0x024c25f5U,
- 0xe5d7fc4fU, 0x2acbd7c5U, 0x35448026U, 0x62a38fb5U,
- 0xb15a49deU, 0xba1b6725U, 0xea0e9845U, 0xfec0e15dU,
- 0x2f7502c3U, 0x4cf01281U, 0x4697a38dU, 0xd3f9c66bU,
- 0x8f5fe703U, 0x929c9515U, 0x6d7aebbfU, 0x5259da95U,
- 0xbe832dd4U, 0x7421d358U, 0xe0692949U, 0xc9c8448eU,
- 0xc2896a75U, 0x8e7978f4U, 0x583e6b99U, 0xb971dd27U,
- 0xe14fb6beU, 0x88ad17f0U, 0x20ac66c9U, 0xce3ab47dU,
- 0xdf4a1863U, 0x1a3182e5U, 0x51336097U, 0x537f4562U,
- 0x6477e0b1U, 0x6bae84bbU, 0x81a01cfeU, 0x082b94f9U,
- 0x48685870U, 0x45fd198fU, 0xde6c8794U, 0x7bf8b752U,
- 0x73d323abU, 0x4b02e272U, 0x1f8f57e3U, 0x55ab2a66U,
- 0xeb2807b2U, 0xb5c2032fU, 0xc57b9a86U, 0x3708a5d3U,
- 0x2887f230U, 0xbfa5b223U, 0x036aba02U, 0x16825cedU,
- 0xcf1c2b8aU, 0x79b492a7U, 0x07f2f0f3U, 0x69e2a14eU,
- 0xdaf4cd65U, 0x05bed506U, 0x34621fd1U, 0xa6fe8ac4U,
- 0x2e539d34U, 0xf355a0a2U, 0x8ae13205U, 0xf6eb75a4U,
- 0x83ec390bU, 0x60efaa40U, 0x719f065eU, 0x6e1051bdU,
- 0x218af93eU, 0xdd063d96U, 0x3e05aeddU, 0xe6bd464dU,
- 0x548db591U, 0xc45d0571U, 0x06d46f04U, 0x5015ff60U,
- 0x98fb2419U, 0xbde997d6U, 0x4043cc89U, 0xd99e7767U,
- 0xe842bdb0U, 0x898b8807U, 0x195b38e7U, 0xc8eedb79U,
- 0x7c0a47a1U, 0x420fe97cU, 0x841ec9f8U, 0x00000000U,
- 0x80868309U, 0x2bed4832U, 0x1170ac1eU, 0x5a724e6cU,
- 0x0efffbfdU, 0x8538560fU, 0xaed51e3dU, 0x2d392736U,
- 0x0fd9640aU, 0x5ca62168U, 0x5b54d19bU, 0x362e3a24U,
- 0x0a67b10cU, 0x57e70f93U, 0xee96d2b4U, 0x9b919e1bU,
- 0xc0c54f80U, 0xdc20a261U, 0x774b695aU, 0x121a161cU,
- 0x93ba0ae2U, 0xa02ae5c0U, 0x22e0433cU, 0x1b171d12U,
- 0x090d0b0eU, 0x8bc7adf2U, 0xb6a8b92dU, 0x1ea9c814U,
- 0xf1198557U, 0x75074cafU, 0x99ddbbeeU, 0x7f60fda3U,
- 0x01269ff7U, 0x72f5bc5cU, 0x663bc544U, 0xfb7e345bU,
- 0x4329768bU, 0x23c6dccbU, 0xedfc68b6U, 0xe4f163b8U,
- 0x31dccad7U, 0x63851042U, 0x97224013U, 0xc6112084U,
- 0x4a247d85U, 0xbb3df8d2U, 0xf93211aeU, 0x29a16dc7U,
- 0x9e2f4b1dU, 0xb230f3dcU, 0x8652ec0dU, 0xc1e3d077U,
- 0xb3166c2bU, 0x70b999a9U, 0x9448fa11U, 0xe9642247U,
- 0xfc8cc4a8U, 0xf03f1aa0U, 0x7d2cd856U, 0x3390ef22U,
- 0x494ec787U, 0x38d1c1d9U, 0xcaa2fe8cU, 0xd40b3698U,
- 0xf581cfa6U, 0x7ade28a5U, 0xb78e26daU, 0xadbfa43fU,
- 0x3a9de42cU, 0x78920d50U, 0x5fcc9b6aU, 0x7e466254U,
- 0x8d13c2f6U, 0xd8b8e890U, 0x39f75e2eU, 0xc3aff582U,
- 0x5d80be9fU, 0xd0937c69U, 0xd52da96fU, 0x2512b3cfU,
- 0xac993bc8U, 0x187da710U, 0x9c636ee8U, 0x3bbb7bdbU,
- 0x267809cdU, 0x5918f46eU, 0x9ab701ecU, 0x4f9aa883U,
- 0x956e65e6U, 0xffe67eaaU, 0xbccf0821U, 0x15e8e6efU,
- 0xe79bd9baU, 0x6f36ce4aU, 0x9f09d4eaU, 0xb07cd629U,
- 0xa4b2af31U, 0x3f23312aU, 0xa59430c6U, 0xa266c035U,
- 0x4ebc3774U, 0x82caa6fcU, 0x90d0b0e0U, 0xa7d81533U,
- 0x04984af1U, 0xecdaf741U, 0xcd500e7fU, 0x91f62f17U,
- 0x4dd68d76U, 0xefb04d43U, 0xaa4d54ccU, 0x9604dfe4U,
- 0xd1b5e39eU, 0x6a881b4cU, 0x2c1fb8c1U, 0x65517f46U,
- 0x5eea049dU, 0x8c355d01U, 0x877473faU, 0x0b412efbU,
- 0x671d5ab3U, 0xdbd25292U, 0x105633e9U, 0xd647136dU,
- 0xd7618c9aU, 0xa10c7a37U, 0xf8148e59U, 0x133c89ebU,
- 0xa927eeceU, 0x61c935b7U, 0x1ce5ede1U, 0x47b13c7aU,
- 0xd2df599cU, 0xf2733f55U, 0x14ce7918U, 0xc737bf73U,
- 0xf7cdea53U, 0xfdaa5b5fU, 0x3d6f14dfU, 0x44db8678U,
- 0xaff381caU, 0x68c43eb9U, 0x24342c38U, 0xa3405fc2U,
- 0x1dc37216U, 0xe2250cbcU, 0x3c498b28U, 0x0d9541ffU,
- 0xa8017139U, 0x0cb3de08U, 0xb4e49cd8U, 0x56c19064U,
- 0xcb84617bU, 0x32b670d5U, 0x6c5c7448U, 0xb85742d0U,
-};
-
const word32 Rijndael::Base::rcon[] = {
0x01000000, 0x02000000, 0x04000000, 0x08000000,
0x10000000, 0x20000000, 0x40000000, 0x80000000,
diff --git a/regtest.cpp b/regtest.cpp
index b89eaad..8f85bc9 100644
--- a/regtest.cpp
+++ b/regtest.cpp
@@ -25,6 +25,23 @@
#include "md5.h"
#include "sosemanuk.h"
#include "arc4.h"
+#include "ccm.h"
+#include "gcm.h"
+#include "twofish.h"
+#include "serpent.h"
+#include "cast.h"
+#include "rc6.h"
+#include "mars.h"
+#include "shacal2.h"
+#include "des.h"
+#include "idea.h"
+#include "rc5.h"
+#include "tea.h"
+#include "skipjack.h"
+#include "cmac.h"
+#include "dmac.h"
+#include "blowfish.h"
+#include "seed.h"
USING_NAMESPACE(CryptoPP)
@@ -39,12 +56,10 @@ void RegisterFactories()
RegisterDefaultFactoryFor<HashTransformation, SHA1>();
RegisterDefaultFactoryFor<HashTransformation, SHA224>();
RegisterDefaultFactoryFor<HashTransformation, SHA256>();
-#ifdef WORD64_AVAILABLE
RegisterDefaultFactoryFor<HashTransformation, SHA384>();
RegisterDefaultFactoryFor<HashTransformation, SHA512>();
RegisterDefaultFactoryFor<HashTransformation, Whirlpool>();
RegisterDefaultFactoryFor<HashTransformation, Tiger>();
-#endif
RegisterDefaultFactoryFor<HashTransformation, RIPEMD160>();
RegisterDefaultFactoryFor<HashTransformation, RIPEMD320>();
RegisterDefaultFactoryFor<HashTransformation, RIPEMD128>();
@@ -59,6 +74,9 @@ void RegisterFactories()
RegisterDefaultFactoryFor<MessageAuthenticationCode, VMAC<AES, 64> >();
RegisterDefaultFactoryFor<MessageAuthenticationCode, Weak::PanamaMAC<LittleEndian> >();
RegisterDefaultFactoryFor<MessageAuthenticationCode, Weak::PanamaMAC<BigEndian> >();
+ RegisterDefaultFactoryFor<MessageAuthenticationCode, CMAC<AES> >();
+ RegisterDefaultFactoryFor<MessageAuthenticationCode, DMAC<AES> >();
+ RegisterDefaultFactoryFor<MessageAuthenticationCode, CMAC<DES_EDE3> >();
RegisterAsymmetricCipherDefaultFactories<RSAES<OAEP<SHA1> > >("RSA/OAEP-MGF1(SHA-1)");
RegisterAsymmetricCipherDefaultFactories<DLIES<> >("DLIES(NoCofactorMultiplication, KDF2(SHA-1), XOR, HMAC(SHA-1), DHAES)");
RegisterSignatureSchemeDefaultFactories<DSA>("DSA(1363)");
@@ -84,6 +102,27 @@ void RegisterFactories()
RegisterSymmetricCipherDefaultFactories<Salsa20>();
RegisterSymmetricCipherDefaultFactories<Sosemanuk>();
RegisterSymmetricCipherDefaultFactories<Weak::MARC4>();
+ RegisterAuthenticatedSymmetricCipherDefaultFactories<CCM<AES> >();
+ RegisterAuthenticatedSymmetricCipherDefaultFactories<GCM<AES> >();
+ RegisterSymmetricCipherDefaultFactories<CTR_Mode<Camellia> >();
+ RegisterSymmetricCipherDefaultFactories<CTR_Mode<Twofish> >();
+ RegisterSymmetricCipherDefaultFactories<CTR_Mode<Serpent> >();
+ RegisterSymmetricCipherDefaultFactories<CTR_Mode<CAST256> >();
+ RegisterSymmetricCipherDefaultFactories<CTR_Mode<RC6> >();
+ RegisterSymmetricCipherDefaultFactories<CTR_Mode<MARS> >();
+ RegisterSymmetricCipherDefaultFactories<CTR_Mode<SHACAL2> >();
+ RegisterSymmetricCipherDefaultFactories<CTR_Mode<DES> >();
+ RegisterSymmetricCipherDefaultFactories<CTR_Mode<DES_XEX3> >();
+ RegisterSymmetricCipherDefaultFactories<CTR_Mode<DES_EDE3> >();
+ RegisterSymmetricCipherDefaultFactories<CTR_Mode<IDEA> >();
+ RegisterSymmetricCipherDefaultFactories<CTR_Mode<RC5> >();
+ RegisterSymmetricCipherDefaultFactories<CTR_Mode<TEA> >();
+ RegisterSymmetricCipherDefaultFactories<CTR_Mode<XTEA> >();
+ RegisterSymmetricCipherDefaultFactories<CTR_Mode<CAST128> >();
+ RegisterSymmetricCipherDefaultFactories<CTR_Mode<SKIPJACK> >();
+ RegisterSymmetricCipherDefaultFactories<CTR_Mode<Blowfish> >();
+ RegisterSymmetricCipherDefaultFactories<ECB_Mode<SEED> >();
+ RegisterSymmetricCipherDefaultFactories<CTR_Mode<SEED> >();
s_registered = true;
}
diff --git a/rijndael.cpp b/rijndael.cpp
index b89e3b3..05c403a 100644
--- a/rijndael.cpp
+++ b/rijndael.cpp
@@ -5,6 +5,16 @@
// use "cl /EP /P /DCRYPTOPP_GENERATE_X64_MASM rijndael.cpp" to generate MASM code
/*
+The assembly code was rewritten in Feb 2009 by Wei Dai to do counter mode
+caching, which was invented by Hongjun Wu and popularized by Daniel J. Bernstein
+and Peter Schwabe in their paper "New AES software speed records". The round
+function was also modified to include a trick similar to one in Brian Gladman's
+x86 assembly code, doing an 8-bit register move to minimize the number of
+register spills. Also switched to compressed tables and copying round keys to
+the stack.
+*/
+
+/*
Defense against timing attacks was added in July 2006 by Wei Dai.
The code now uses smaller tables in the first and last rounds,
@@ -58,6 +68,72 @@ being unloaded from L1 cache, until that round is finished.
NAMESPACE_BEGIN(CryptoPP)
+#ifdef CRYPTOPP_ALLOW_UNALIGNED_DATA_ACCESS
+#if CRYPTOPP_BOOL_SSE2_ASM_AVAILABLE || defined(CRYPTOPP_X64_MASM_AVAILABLE)
+namespace rdtable {CRYPTOPP_ALIGN_DATA(16) word64 Te[256+2];}
+using namespace rdtable;
+#else
+static word64 Te[256];
+#endif
+static word32 Td[256*4];
+#else
+static word32 Te[256*4], Td[256*4];
+#endif
+static bool s_TeFilled = false, s_TdFilled = false;
+
+#define f2(x) ((x<<1)^(((x>>7)&1)*0x11b))
+#define f4(x) ((x<<2)^(((x>>6)&1)*0x11b)^(((x>>6)&2)*0x11b))
+#define f8(x) ((x<<3)^(((x>>5)&1)*0x11b)^(((x>>5)&2)*0x11b)^(((x>>5)&4)*0x11b))
+
+#define f3(x) (f2(x) ^ x)
+#define f9(x) (f8(x) ^ x)
+#define fb(x) (f8(x) ^ f2(x) ^ x)
+#define fd(x) (f8(x) ^ f4(x) ^ x)
+#define fe(x) (f8(x) ^ f4(x) ^ f2(x))
+
+void Rijndael::Base::FillEncTable()
+{
+ for (int i=0; i<256; i++)
+ {
+ byte x = Se[i];
+#ifdef CRYPTOPP_ALLOW_UNALIGNED_DATA_ACCESS
+ word32 y = word32(x)<<8 | word32(x)<<16 | word32(f2(x))<<24;
+ Te[i] = word64(y | f3(x))<<32 | y;
+#else
+ word32 y = f3(x) | word32(x)<<8 | word32(x)<<16 | word32(f2(x))<<24;
+ for (int j=0; j<4; j++)
+ {
+ Te[i+j*256] = y;
+ y = rotrFixed(y, 8);
+ }
+#endif
+ }
+#if CRYPTOPP_BOOL_SSE2_ASM_AVAILABLE
+ Te[256] = Te[257] = 0;
+#endif
+ s_TeFilled = true;
+}
+
+void Rijndael::Base::FillDecTable()
+{
+ for (int i=0; i<256; i++)
+ {
+ byte x = Sd[i];
+#ifdef CRYPTOPP_ALLOW_UNALIGNED_DATA_ACCESS_
+ word32 y = word32(fd(x))<<8 | word32(f9(x))<<16 | word32(fe(x))<<24;
+ Td[i] = word64(y | fb(x))<<32 | y | x;
+#else
+ word32 y = fb(x) | word32(fd(x))<<8 | word32(f9(x))<<16 | word32(fe(x))<<24;;
+ for (int j=0; j<4; j++)
+ {
+ Td[i+j*256] = y;
+ y = rotrFixed(y, 8);
+ }
+#endif
+ }
+ s_TdFilled = true;
+}
+
void Rijndael::Base::UncheckedSetKey(const byte *userKey, unsigned int keylen, const NameValuePairs &)
{
AssertValidKeyLength(keylen);
@@ -106,8 +182,16 @@ void Rijndael::Base::UncheckedSetKey(const byte *userKey, unsigned int keylen, c
rk += keylen/4;
}
- if (!IsForwardTransformation())
+ if (IsForwardTransformation())
{
+ if (!s_TeFilled)
+ FillEncTable();
+ }
+ else
+ {
+ if (!s_TdFilled)
+ FillDecTable();
+
unsigned int i, j;
rk = m_key;
@@ -148,349 +232,530 @@ void Rijndael::Base::UncheckedSetKey(const byte *userKey, unsigned int keylen, c
ConditionalByteReverse(BIG_ENDIAN_ORDER, m_key + m_rounds*4, m_key + m_rounds*4, 16);
}
-#ifdef CRYPTOPP_X64_MASM_AVAILABLE
-extern "C" {
-void Rijndael_Enc_ProcessAndXorBlock(const word32 *table, word32 cacheLineSize, const word32 *k, const word32 *kLoopEnd, const byte *inBlock, const byte *xorBlock, byte *outBlock);
-}
-#endif
-
#pragma warning(disable: 4731) // frame pointer register 'ebp' modified by inline assembly code
-void Rijndael::Enc::ProcessAndXorBlock(const byte *inBlock, const byte *xorBlock, byte *outBlock) const
+#endif // #ifndef CRYPTOPP_GENERATE_X64_MASM
+
+#if CRYPTOPP_BOOL_SSE2_ASM_AVAILABLE
+
+CRYPTOPP_NAKED void CRYPTOPP_FASTCALL Rijndael_Enc_AdvancedProcessBlocks(void *locals, const word32 *k)
{
-#endif // #ifdef CRYPTOPP_GENERATE_X64_MASM
+#if CRYPTOPP_BOOL_X86
+
+#define L_REG esp
+#define L_INDEX(i) (L_REG+512+i)
+#define L_INXORBLOCKS L_INBLOCKS+4
+#define L_OUTXORBLOCKS L_INBLOCKS+8
+#define L_OUTBLOCKS L_INBLOCKS+12
+#define L_INCREMENTS L_INDEX(16*15)
+#define L_SP L_INDEX(16*16)
+#define L_LENGTH L_INDEX(16*16+4)
+#define L_KEYS_BEGIN L_INDEX(16*16+8)
+
+#define MOVD movd
+#define MM(i) mm##i
+
+#define MXOR(a,b,c) \
+ AS2( movzx ebp, b)\
+ AS2( movd mm7, DWORD PTR [WORD_REG(si)+8*WORD_REG(bp)+MAP0TO4(c)])\
+ AS2( pxor MM(a), mm7)\
+
+#define MMOV(a,b,c) \
+ AS2( movzx ebp, b)\
+ AS2( movd MM(a), DWORD PTR [WORD_REG(si)+8*WORD_REG(bp)+MAP0TO4(c)])\
+
+#else
+
+#define L_REG r8
+#define L_INDEX(i) (r8+i)
+#define L_INXORBLOCKS L_INBLOCKS+8
+#define L_OUTXORBLOCKS L_INBLOCKS+16
+#define L_OUTBLOCKS L_INBLOCKS+24
+#define L_INCREMENTS L_INDEX(16*16)
+#define L_BP L_INDEX(16*18)
+#define L_LENGTH L_INDEX(16*18+8)
+#define L_KEYS_BEGIN L_INDEX(16*19)
+
+#define MOVD mov
+#define MM(i) r1##i##d
+
+#define MXOR(a,b,c) \
+ AS2( movzx ebp, b)\
+ AS2( xor MM(a), DWORD PTR [WORD_REG(si)+8*WORD_REG(bp)+MAP0TO4(c)])\
+
+#define MMOV(a,b,c) \
+ AS2( movzx ebp, b)\
+ AS2( mov MM(a), DWORD PTR [WORD_REG(si)+8*WORD_REG(bp)+MAP0TO4(c)])\
-#ifdef CRYPTOPP_X64_MASM_AVAILABLE
- Rijndael_Enc_ProcessAndXorBlock(Te, g_cacheLineSize, m_key, m_key + m_rounds*4, inBlock, xorBlock, outBlock);
- return;
#endif
-#if defined(CRYPTOPP_X86_ASM_AVAILABLE)
- #ifdef CRYPTOPP_GENERATE_X64_MASM
+#define L_SUBKEYS L_INDEX(0)
+#define L_SAVED_X L_SUBKEYS
+#define L_KEY12 L_INDEX(16*12)
+#define L_LASTROUND L_INDEX(16*13)
+#define L_INBLOCKS L_INDEX(16*14)
+#define MAP0TO4(i) (ASM_MOD(i+3,4)+1)
+
+#define XOR(a,b,c) \
+ AS2( movzx ebp, b)\
+ AS2( xor a, DWORD PTR [WORD_REG(si)+8*WORD_REG(bp)+MAP0TO4(c)])\
+
+#define MOV(a,b,c) \
+ AS2( movzx ebp, b)\
+ AS2( mov a, DWORD PTR [WORD_REG(si)+8*WORD_REG(bp)+MAP0TO4(c)])\
+
+#ifdef CRYPTOPP_GENERATE_X64_MASM
ALIGN 8
- Rijndael_Enc_ProcessAndXorBlock PROC FRAME
- rex_push_reg rbx
- push_reg rsi
+ Rijndael_Enc_AdvancedProcessBlocks PROC FRAME
+ rex_push_reg rsi
push_reg rdi
+ push_reg rbx
+ push_reg rbp
push_reg r12
- push_reg r13
- push_reg r14
- push_reg r15
.endprolog
- mov AS_REG_7, rcx
- mov rdi, [rsp + 5*8 + 7*8] ; inBlock
- #else
- if (HasMMX())
- {
- const word32 *k = m_key;
- const word32 *kLoopEnd = k + m_rounds*4;
- #endif
-
- #if CRYPTOPP_BOOL_X64
- #define K_REG r8
- #define K_END_REG r9
- #define SAVE_K
- #define RESTORE_K
- #define RESTORE_K_END
- #define SAVE_0(x) AS2(mov r13d, x)
- #define SAVE_1(x) AS2(mov r14d, x)
- #define SAVE_2(x) AS2(mov r15d, x)
- #define RESTORE_0(x) AS2(mov x, r13d)
- #define RESTORE_1(x) AS2(mov x, r14d)
- #define RESTORE_2(x) AS2(mov x, r15d)
- #else
- #define K_REG esi
- #define K_END_REG edi
- #define SAVE_K AS2(movd mm4, esi)
- #define RESTORE_K AS2(movd esi, mm4)
- #define RESTORE_K_END AS2(movd edi, mm5)
- #define SAVE_0(x) AS2(movd mm0, x)
- #define SAVE_1(x) AS2(movd mm1, x)
- #define SAVE_2(x) AS2(movd mm2, x)
- #define RESTORE_0(x) AS2(movd x, mm0)
- #define RESTORE_1(x) AS2(movd x, mm1)
- #define RESTORE_2(x) AS2(movd x, mm2)
- #endif
-#ifdef __GNUC__
- word32 t0, t1, t2, t3;
- __asm__ __volatile__
- (
- ".intel_syntax noprefix;"
+ mov r8, rcx
+ mov rsi, ?Te@rdtable@CryptoPP@@3PA_KA
+ mov rdi, QWORD PTR [?g_cacheLineSize@CryptoPP@@3IA]
+#elif defined(__GNUC__)
+ __asm__ __volatile__
+ (
+ ".intel_syntax noprefix;"
+ ASL(Rijndael_Enc_AdvancedProcessBlocks)
#if CRYPTOPP_BOOL_X64
- AS2( mov K_REG, rsi)
- AS2( mov K_END_REG, rcx)
- #else
- AS1( push ebx)
- AS1( push ebp)
- AS2( movd mm5, ecx)
+ AS2( mov r8, rcx)
+ AS2( mov [L_BP], rbp)
#endif
- AS2( mov AS_REG_7, WORD_REG(ax))
-#elif CRYPTOPP_BOOL_X86
- #if _MSC_VER < 1300
- const word32 *t = Te;
- AS2( mov eax, t)
- #endif
- AS2( mov edx, g_cacheLineSize)
- AS2( mov WORD_REG(di), inBlock)
- AS2( mov K_REG, k)
- AS2( movd mm5, kLoopEnd)
- #if _MSC_VER < 1300
- AS1( push ebx)
- AS1( push ebp)
- AS2( mov AS_REG_7, eax)
- #else
- AS1( push ebp)
- AS2( lea AS_REG_7, Te)
- #endif
-#endif
- AS2( mov eax, [K_REG+0*4]) // s0
- AS2( xor eax, [WORD_REG(di)+0*4])
- SAVE_0(eax)
- AS2( mov ebx, [K_REG+1*4])
- AS2( xor ebx, [WORD_REG(di)+1*4])
- SAVE_1(ebx)
- AS2( and ebx, eax)
- AS2( mov eax, [K_REG+2*4])
- AS2( xor eax, [WORD_REG(di)+2*4])
- SAVE_2(eax)
- AS2( and ebx, eax)
- AS2( mov ecx, [K_REG+3*4])
- AS2( xor ecx, [WORD_REG(di)+3*4])
- AS2( and ebx, ecx)
-
- // read Te0 into L1 cache. this code could be simplifed by using lfence, but that is an SSE2 instruction
- AS2( and ebx, 0)
- AS2( mov edi, ebx) // make index depend on previous loads to simulate lfence
- ASL(2)
- AS2( and ebx, [AS_REG_7+WORD_REG(di)])
- AS2( add edi, edx)
- AS2( and ebx, [AS_REG_7+WORD_REG(di)])
- AS2( add edi, edx)
- AS2( and ebx, [AS_REG_7+WORD_REG(di)])
- AS2( add edi, edx)
- AS2( and ebx, [AS_REG_7+WORD_REG(di)])
- AS2( add edi, edx)
- AS2( cmp edi, 1024)
- ASJ( jl, 2, b)
- AS2( and ebx, [AS_REG_7+1020])
-#if CRYPTOPP_BOOL_X64
- AS2( xor r13d, ebx)
- AS2( xor r14d, ebx)
- AS2( xor r15d, ebx)
#else
- AS2( movd mm6, ebx)
- AS2( pxor mm2, mm6)
- AS2( pxor mm1, mm6)
- AS2( pxor mm0, mm6)
+ AS1( push esi)
+ AS1( push edi)
+ AS2( lea esi, [Te])
+ AS2( mov edi, [g_cacheLineSize])
#endif
- AS2( xor ecx, ebx)
- AS2( mov edi, [K_REG+4*4]) // t0
- AS2( mov eax, [K_REG+5*4])
- AS2( mov ebx, [K_REG+6*4])
- AS2( mov edx, [K_REG+7*4])
- AS2( add K_REG, 8*4)
- SAVE_K
-
-#define QUARTER_ROUND(t, a, b, c, d) \
- AS2(movzx esi, t##l)\
- AS2(d, [AS_REG_7+0*1024+4*WORD_REG(si)])\
- AS2(movzx esi, t##h)\
- AS2(c, [AS_REG_7+1*1024+4*WORD_REG(si)])\
- AS2(shr e##t##x, 16)\
- AS2(movzx esi, t##l)\
- AS2(b, [AS_REG_7+2*1024+4*WORD_REG(si)])\
- AS2(movzx esi, t##h)\
- AS2(a, [AS_REG_7+3*1024+4*WORD_REG(si)])
-
-#define s0 xor edi
-#define s1 xor eax
-#define s2 xor ebx
-#define s3 xor ecx
-#define t0 xor edi
-#define t1 xor eax
-#define t2 xor ebx
-#define t3 xor edx
-
- QUARTER_ROUND(c, t0, t1, t2, t3)
- RESTORE_2(ecx)
- QUARTER_ROUND(c, t3, t0, t1, t2)
- RESTORE_1(ecx)
- QUARTER_ROUND(c, t2, t3, t0, t1)
- RESTORE_0(ecx)
- QUARTER_ROUND(c, t1, t2, t3, t0)
- SAVE_2(ebx)
- SAVE_1(eax)
- SAVE_0(edi)
-#undef QUARTER_ROUND
+#if CRYPTOPP_BOOL_X86
+ AS_PUSH_IF86( bx)
+ AS_PUSH_IF86( bp)
+ AS2( mov [ecx+16*12+16*4], esp)
+ AS2( lea esp, [ecx-512])
+#endif
- RESTORE_K
+ // copy subkeys to stack
+ AS2( mov WORD_REG(bp), [L_KEYS_BEGIN])
+ AS2( mov WORD_REG(ax), 16)
+ AS2( and WORD_REG(ax), WORD_REG(bp))
+ AS2( movdqa xmm3, XMMWORD_PTR [WORD_REG(dx)+16+WORD_REG(ax)]) // subkey 1 (non-counter) or 2 (counter)
+ AS2( movdqa [L_KEY12], xmm3)
+ AS2( lea WORD_REG(ax), [WORD_REG(dx)+WORD_REG(ax)+2*16])
+ AS2( sub WORD_REG(ax), WORD_REG(bp))
+ ASL(0)
+ AS2( movdqa xmm0, [WORD_REG(ax)+WORD_REG(bp)])
+ AS2( movdqa XMMWORD_PTR [L_SUBKEYS+WORD_REG(bp)], xmm0)
+ AS2( add WORD_REG(bp), 16)
+ AS2( cmp WORD_REG(bp), 16*12)
+ ASJ( jl, 0, b)
+
+ // read subkeys 0, 1 and last
+ AS2( movdqa xmm4, [WORD_REG(ax)+WORD_REG(bp)]) // last subkey
+ AS2( movdqa xmm1, [WORD_REG(dx)]) // subkey 0
+ AS2( MOVD MM(1), [WORD_REG(dx)+4*4]) // 0,1,2,3
+ AS2( mov ebx, [WORD_REG(dx)+5*4]) // 4,5,6,7
+ AS2( mov ecx, [WORD_REG(dx)+6*4]) // 8,9,10,11
+ AS2( mov edx, [WORD_REG(dx)+7*4]) // 12,13,14,15
+
+ // load table into cache
+ AS2( xor WORD_REG(ax), WORD_REG(ax))
+ ASL(9)
+ AS2( mov ebp, [WORD_REG(si)+WORD_REG(ax)])
+ AS2( add WORD_REG(ax), WORD_REG(di))
+ AS2( mov ebp, [WORD_REG(si)+WORD_REG(ax)])
+ AS2( add WORD_REG(ax), WORD_REG(di))
+ AS2( mov ebp, [WORD_REG(si)+WORD_REG(ax)])
+ AS2( add WORD_REG(ax), WORD_REG(di))
+ AS2( mov ebp, [WORD_REG(si)+WORD_REG(ax)])
+ AS2( add WORD_REG(ax), WORD_REG(di))
+ AS2( cmp WORD_REG(ax), 2048)
+ ASJ( jl, 9, b)
+ AS1( lfence)
+
+ AS2( test DWORD PTR [L_LENGTH], 1)
+ ASJ( jz, 8, f)
+
+ // counter mode one-time setup
+ AS2( mov WORD_REG(bp), [L_INBLOCKS])
+ AS2( movdqa xmm2, [WORD_REG(bp)]) // counter
+ AS2( pxor xmm2, xmm1)
+ AS2( psrldq xmm1, 14)
+ AS2( movd eax, xmm1)
+ AS2( mov al, BYTE PTR [WORD_REG(bp)+15])
+ AS2( MOVD MM(2), eax)
+#if CRYPTOPP_BOOL_X86
+ AS2( mov eax, 1)
+ AS2( movd mm3, eax)
+#endif
- ASL(0)
- AS2( mov edi, [K_REG+0*4])
- AS2( mov eax, [K_REG+1*4])
- AS2( mov ebx, [K_REG+2*4])
- AS2( mov ecx, [K_REG+3*4])
+ // partial first round, in: xmm2(15,14,13,12;11,10,9,8;7,6,5,4;3,2,1,0), out: mm1, ebx, ecx, edx
+ AS2( movd eax, xmm2)
+ AS2( psrldq xmm2, 4)
+ AS2( movd edi, xmm2)
+ AS2( psrldq xmm2, 4)
+ MXOR( 1, al, 0) // 0
+ XOR( edx, ah, 1) // 1
+ AS2( shr eax, 16)
+ XOR( ecx, al, 2) // 2
+ XOR( ebx, ah, 3) // 3
+ AS2( mov eax, edi)
+ AS2( movd edi, xmm2)
+ AS2( psrldq xmm2, 4)
+ XOR( ebx, al, 0) // 4
+ MXOR( 1, ah, 1) // 5
+ AS2( shr eax, 16)
+ XOR( edx, al, 2) // 6
+ XOR( ecx, ah, 3) // 7
+ AS2( mov eax, edi)
+ AS2( movd edi, xmm2)
+ XOR( ecx, al, 0) // 8
+ XOR( ebx, ah, 1) // 9
+ AS2( shr eax, 16)
+ MXOR( 1, al, 2) // 10
+ XOR( edx, ah, 3) // 11
+ AS2( mov eax, edi)
+ XOR( edx, al, 0) // 12
+ XOR( ecx, ah, 1) // 13
+ AS2( shr eax, 16)
+ XOR( ebx, al, 2) // 14
+ AS2( psrldq xmm2, 3)
+
+ // partial second round, in: ebx(4,5,6,7), ecx(8,9,10,11), edx(12,13,14,15), out: eax, ebx, edi, mm0
+ AS2( mov eax, [L_KEY12+0*4])
+ AS2( mov edi, [L_KEY12+2*4])
+ AS2( MOVD MM(0), [L_KEY12+3*4])
+ MXOR( 0, cl, 3) /* 11 */
+ XOR( edi, bl, 3) /* 7 */
+ MXOR( 0, bh, 2) /* 6 */
+ AS2( shr ebx, 16) /* 4,5 */
+ XOR( eax, bl, 1) /* 5 */
+ MOV( ebx, bh, 0) /* 4 */
+ AS2( xor ebx, [L_KEY12+1*4])
+ XOR( eax, ch, 2) /* 10 */
+ AS2( shr ecx, 16) /* 8,9 */
+ XOR( eax, dl, 3) /* 15 */
+ XOR( ebx, dh, 2) /* 14 */
+ AS2( shr edx, 16) /* 12,13 */
+ XOR( edi, ch, 0) /* 8 */
+ XOR( ebx, cl, 1) /* 9 */
+ XOR( edi, dl, 1) /* 13 */
+ MXOR( 0, dh, 0) /* 12 */
+
+ AS2( movd ecx, xmm2)
+ AS2( MOVD edx, MM(1))
+ AS2( MOVD [L_SAVED_X+3*4], MM(0))
+ AS2( mov [L_SAVED_X+0*4], eax)
+ AS2( mov [L_SAVED_X+1*4], ebx)
+ AS2( mov [L_SAVED_X+2*4], edi)
+ ASJ( jmp, 5, f)
+
+ ASL(3)
+ // non-counter mode per-block setup
+ AS2( MOVD MM(1), [L_KEY12+0*4]) // 0,1,2,3
+ AS2( mov ebx, [L_KEY12+1*4]) // 4,5,6,7
+ AS2( mov ecx, [L_KEY12+2*4]) // 8,9,10,11
+ AS2( mov edx, [L_KEY12+3*4]) // 12,13,14,15
+ ASL(8)
+ AS2( mov WORD_REG(ax), [L_INBLOCKS])
+ AS2( movdqu xmm2, [WORD_REG(ax)])
+ AS2( mov WORD_REG(bp), [L_INXORBLOCKS])
+ AS2( movdqu xmm5, [WORD_REG(bp)])
+ AS2( pxor xmm2, xmm1)
+ AS2( pxor xmm2, xmm5)
+
+ // first round, in: xmm2(15,14,13,12;11,10,9,8;7,6,5,4;3,2,1,0), out: eax, ebx, ecx, edx
+ AS2( movd eax, xmm2)
+ AS2( psrldq xmm2, 4)
+ AS2( movd edi, xmm2)
+ AS2( psrldq xmm2, 4)
+ MXOR( 1, al, 0) // 0
+ XOR( edx, ah, 1) // 1
+ AS2( shr eax, 16)
+ XOR( ecx, al, 2) // 2
+ XOR( ebx, ah, 3) // 3
+ AS2( mov eax, edi)
+ AS2( movd edi, xmm2)
+ AS2( psrldq xmm2, 4)
+ XOR( ebx, al, 0) // 4
+ MXOR( 1, ah, 1) // 5
+ AS2( shr eax, 16)
+ XOR( edx, al, 2) // 6
+ XOR( ecx, ah, 3) // 7
+ AS2( mov eax, edi)
+ AS2( movd edi, xmm2)
+ XOR( ecx, al, 0) // 8
+ XOR( ebx, ah, 1) // 9
+ AS2( shr eax, 16)
+ MXOR( 1, al, 2) // 10
+ XOR( edx, ah, 3) // 11
+ AS2( mov eax, edi)
+ XOR( edx, al, 0) // 12
+ XOR( ecx, ah, 1) // 13
+ AS2( shr eax, 16)
+ XOR( ebx, al, 2) // 14
+ MXOR( 1, ah, 3) // 15
+ AS2( MOVD eax, MM(1))
+
+ AS2( add L_REG, [L_KEYS_BEGIN])
+ AS2( add L_REG, 4*16)
+ ASJ( jmp, 2, f)
+
+ ASL(1)
+ // counter-mode per-block setup
+ AS2( MOVD ecx, MM(2))
+ AS2( MOVD edx, MM(1))
+ AS2( mov eax, [L_SAVED_X+0*4])
+ AS2( mov ebx, [L_SAVED_X+1*4])
+ AS2( xor cl, ch)
+ AS2( and WORD_REG(cx), 255)
+ ASL(5)
+#if CRYPTOPP_BOOL_X86
+ AS2( paddb MM(2), mm3)
+#else
+ AS2( add MM(2), 1)
+#endif
+ // remaining part of second round, in: edx(previous round),ebp(keyed counter byte) eax,ebx,[L_SAVED_X+2*4],[L_SAVED_X+3*4], out: eax,ebx,ecx,edx
+ AS2( xor edx, DWORD PTR [WORD_REG(si)+WORD_REG(cx)*8+3])
+ XOR( ebx, dl, 3)
+ MOV( ecx, dh, 2)
+ AS2( shr edx, 16)
+ AS2( xor ecx, [L_SAVED_X+2*4])
+ XOR( eax, dh, 0)
+ MOV( edx, dl, 1)
+ AS2( xor edx, [L_SAVED_X+3*4])
+
+ AS2( add L_REG, [L_KEYS_BEGIN])
+ AS2( add L_REG, 3*16)
+ ASJ( jmp, 4, f)
+
+// in: eax(0,1,2,3), ebx(4,5,6,7), ecx(8,9,10,11), edx(12,13,14,15)
+// out: eax, ebx, edi, mm0
+#define ROUND() \
+ MXOR( 0, cl, 3) /* 11 */\
+ AS2( mov cl, al) /* 8,9,10,3 */\
+ XOR( edi, ah, 2) /* 2 */\
+ AS2( shr eax, 16) /* 0,1 */\
+ XOR( edi, bl, 3) /* 7 */\
+ MXOR( 0, bh, 2) /* 6 */\
+ AS2( shr ebx, 16) /* 4,5 */\
+ MXOR( 0, al, 1) /* 1 */\
+ MOV( eax, ah, 0) /* 0 */\
+ XOR( eax, bl, 1) /* 5 */\
+ MOV( ebx, bh, 0) /* 4 */\
+ XOR( eax, ch, 2) /* 10 */\
+ XOR( ebx, cl, 3) /* 3 */\
+ AS2( shr ecx, 16) /* 8,9 */\
+ XOR( eax, dl, 3) /* 15 */\
+ XOR( ebx, dh, 2) /* 14 */\
+ AS2( shr edx, 16) /* 12,13 */\
+ XOR( edi, ch, 0) /* 8 */\
+ XOR( ebx, cl, 1) /* 9 */\
+ XOR( edi, dl, 1) /* 13 */\
+ MXOR( 0, dh, 0) /* 12 */\
+
+ ASL(2) // 2-round loop
+ AS2( MOVD MM(0), [L_SUBKEYS-4*16+3*4])
+ AS2( mov edi, [L_SUBKEYS-4*16+2*4])
+ ROUND()
+ AS2( mov ecx, edi)
+ AS2( xor eax, [L_SUBKEYS-4*16+0*4])
+ AS2( xor ebx, [L_SUBKEYS-4*16+1*4])
+ AS2( MOVD edx, MM(0))
+
+ ASL(4)
+ AS2( MOVD MM(0), [L_SUBKEYS-4*16+7*4])
+ AS2( mov edi, [L_SUBKEYS-4*16+6*4])
+ ROUND()
+ AS2( mov ecx, edi)
+ AS2( xor eax, [L_SUBKEYS-4*16+4*4])
+ AS2( xor ebx, [L_SUBKEYS-4*16+5*4])
+ AS2( MOVD edx, MM(0))
+
+ AS2( add L_REG, 32)
+ AS2( test L_REG, 255)
+ ASJ( jnz, 2, b)
+ AS2( sub L_REG, 16*16)
+
+#define LAST(a, b, c) \
+ AS2( movzx ebp, a )\
+ AS2( movzx edi, BYTE PTR [WORD_REG(si)+WORD_REG(bp)*8+1] )\
+ AS2( movzx ebp, b )\
+ AS2( xor edi, DWORD PTR [WORD_REG(si)+WORD_REG(bp)*8+0] )\
+ AS2( mov WORD PTR [L_LASTROUND+c], di )\
+
+ // last round
+ LAST(ch, dl, 2)
+ LAST(dh, al, 6)
+ AS2( shr edx, 16)
+ LAST(ah, bl, 10)
+ AS2( shr eax, 16)
+ LAST(bh, cl, 14)
+ AS2( shr ebx, 16)
+ LAST(dh, al, 12)
+ AS2( shr ecx, 16)
+ LAST(ah, bl, 0)
+ LAST(bh, cl, 4)
+ LAST(ch, dl, 8)
+
+ AS2( mov WORD_REG(ax), [L_OUTXORBLOCKS])
+ AS2( mov WORD_REG(bx), [L_OUTBLOCKS])
+
+ AS2( mov WORD_REG(cx), [L_LENGTH])
+ AS2( sub WORD_REG(cx), 16)
+
+ AS2( movdqu xmm2, [WORD_REG(ax)])
+ AS2( pxor xmm2, xmm4)
-#define QUARTER_ROUND(t, a, b, c, d) \
- AS2(movzx esi, t##l)\
- AS2(a, [AS_REG_7+3*1024+4*WORD_REG(si)])\
- AS2(movzx esi, t##h)\
- AS2(b, [AS_REG_7+2*1024+4*WORD_REG(si)])\
- AS2(shr e##t##x, 16)\
- AS2(movzx esi, t##l)\
- AS2(c, [AS_REG_7+1*1024+4*WORD_REG(si)])\
- AS2(movzx esi, t##h)\
- AS2(d, [AS_REG_7+0*1024+4*WORD_REG(si)])
-
- QUARTER_ROUND(d, s0, s1, s2, s3)
- RESTORE_2(edx)
- QUARTER_ROUND(d, s3, s0, s1, s2)
- RESTORE_1(edx)
- QUARTER_ROUND(d, s2, s3, s0, s1)
- RESTORE_0(edx)
- QUARTER_ROUND(d, s1, s2, s3, s0)
- RESTORE_K
- SAVE_2(ebx)
- SAVE_1(eax)
- SAVE_0(edi)
-
- AS2( mov edi, [K_REG+4*4])
- AS2( mov eax, [K_REG+5*4])
- AS2( mov ebx, [K_REG+6*4])
- AS2( mov edx, [K_REG+7*4])
-
- QUARTER_ROUND(c, t0, t1, t2, t3)
- RESTORE_2(ecx)
- QUARTER_ROUND(c, t3, t0, t1, t2)
- RESTORE_1(ecx)
- QUARTER_ROUND(c, t2, t3, t0, t1)
- RESTORE_0(ecx)
- QUARTER_ROUND(c, t1, t2, t3, t0)
- SAVE_2(ebx)
- SAVE_1(eax)
- SAVE_0(edi)
-
- RESTORE_K
- RESTORE_K_END
- AS2( add K_REG, 8*4)
- SAVE_K
- AS2( cmp K_END_REG, K_REG)
- ASJ( jne, 0, b)
+#if CRYPTOPP_BOOL_X86
+ AS2( movdqa xmm0, [L_INCREMENTS])
+ AS2( paddd xmm0, [L_INBLOCKS])
+ AS2( movdqa [L_INBLOCKS], xmm0)
+#else
+ AS2( movdqa xmm0, [L_INCREMENTS+16])
+ AS2( paddq xmm0, [L_INBLOCKS+16])
+ AS2( movdqa [L_INBLOCKS+16], xmm0)
+#endif
-#undef QUARTER_ROUND
-#undef s0
-#undef s1
-#undef s2
-#undef s3
-#undef t0
-#undef t1
-#undef t2
-#undef t3
-
- AS2( mov eax, [K_END_REG+0*4])
- AS2( mov ecx, [K_END_REG+1*4])
- AS2( mov esi, [K_END_REG+2*4])
- AS2( mov edi, [K_END_REG+3*4])
-
-#define QUARTER_ROUND(a, b, c, d) \
- AS2( movzx ebx, dl)\
- AS2( movzx ebx, BYTE PTR [AS_REG_7+1+4*WORD_REG(bx)])\
- AS2( shl ebx, 3*8)\
- AS2( xor a, ebx)\
- AS2( movzx ebx, dh)\
- AS2( movzx ebx, BYTE PTR [AS_REG_7+1+4*WORD_REG(bx)])\
- AS2( shl ebx, 2*8)\
- AS2( xor b, ebx)\
- AS2( shr edx, 16)\
- AS2( movzx ebx, dl)\
- AS2( shr edx, 8)\
- AS2( movzx ebx, BYTE PTR [AS_REG_7+1+4*WORD_REG(bx)])\
- AS2( shl ebx, 1*8)\
- AS2( xor c, ebx)\
- AS2( movzx ebx, BYTE PTR [AS_REG_7+1+4*WORD_REG(dx)])\
- AS2( xor d, ebx)
-
- QUARTER_ROUND(eax, ecx, esi, edi)
- RESTORE_2(edx)
- QUARTER_ROUND(edi, eax, ecx, esi)
- RESTORE_1(edx)
- QUARTER_ROUND(esi, edi, eax, ecx)
- RESTORE_0(edx)
- QUARTER_ROUND(ecx, esi, edi, eax)
+ AS2( pxor xmm2, [L_LASTROUND])
+ AS2( movdqu [WORD_REG(bx)], xmm2)
-#undef QUARTER_ROUND
+ ASJ( jle, 7, f)
+ AS2( mov [L_LENGTH], WORD_REG(cx))
+ AS2( test WORD_REG(cx), 1)
+ ASJ( jnz, 1, b)
+#if CRYPTOPP_BOOL_X64
+ AS2( movdqa xmm0, [L_INCREMENTS])
+ AS2( paddd xmm0, [L_INBLOCKS])
+ AS2( movdqa [L_INBLOCKS], xmm0)
+#endif
+ ASJ( jmp, 3, b)
+ ASL(7)
#if CRYPTOPP_BOOL_X86
- AS1(emms)
- AS1(pop ebp)
- #if defined(__GNUC__) || (defined(_MSC_VER) && _MSC_VER < 1300)
- AS1(pop ebx)
- #endif
+ AS2( mov esp, [L_SP])
+ AS1( emms)
+#else
+ AS2( mov rbp, [L_BP])
+#endif
+ AS_POP_IF86( bp)
+ AS_POP_IF86( bx)
+#ifndef __GNUC__
+ AS_POP_IF86( di)
+ AS_POP_IF86( si)
+#endif
+#ifdef CRYPTOPP_GENERATE_X64_MASM
+ pop r12
+ pop rbp
+ pop rbx
+ pop rdi
+ pop rsi
+ ret
+ Rijndael_Enc_AdvancedProcessBlocks ENDP
+#else
+ AS1( ret)
#endif
-
#ifdef __GNUC__
- ".att_syntax prefix;"
- : "=a" (t0), "=c" (t1), "=S" (t2), "=D" (t3)
- : "a" (Te), "D" (inBlock), "S" (k), "c" (kLoopEnd), "d" (g_cacheLineSize)
- : "memory", "cc"
- #if CRYPTOPP_BOOL_X64
- , "%ebx", "%r8", "%r9", "%r10", "%r11", "%r12", "%r13", "%r14", "%r15"
- #endif
- );
+ ".att_syntax prefix;"
+ );
+#endif
+}
- if (xorBlock)
- {
- t0 ^= ((const word32 *)xorBlock)[0];
- t1 ^= ((const word32 *)xorBlock)[1];
- t2 ^= ((const word32 *)xorBlock)[2];
- t3 ^= ((const word32 *)xorBlock)[3];
- }
- ((word32 *)outBlock)[0] = t0;
- ((word32 *)outBlock)[1] = t1;
- ((word32 *)outBlock)[2] = t2;
- ((word32 *)outBlock)[3] = t3;
-#else
- #if CRYPTOPP_BOOL_X64
- mov rbx, [rsp + 6*8 + 7*8] ; xorBlock
- #else
- AS2( mov ebx, xorBlock)
- #endif
- AS2( test WORD_REG(bx), WORD_REG(bx))
- ASJ( jz, 1, f)
- AS2( xor eax, [WORD_REG(bx)+0*4])
- AS2( xor ecx, [WORD_REG(bx)+1*4])
- AS2( xor esi, [WORD_REG(bx)+2*4])
- AS2( xor edi, [WORD_REG(bx)+3*4])
- ASL(1)
- #if CRYPTOPP_BOOL_X64
- mov rbx, [rsp + 7*8 + 7*8] ; outBlock
- #else
- AS2( mov ebx, outBlock)
- #endif
- AS2( mov [WORD_REG(bx)+0*4], eax)
- AS2( mov [WORD_REG(bx)+1*4], ecx)
- AS2( mov [WORD_REG(bx)+2*4], esi)
- AS2( mov [WORD_REG(bx)+3*4], edi)
#endif
-#if CRYPTOPP_GENERATE_X64_MASM
- pop r15
- pop r14
- pop r13
- pop r12
- pop rdi
- pop rsi
- pop rbx
- ret
- Rijndael_Enc_ProcessAndXorBlock ENDP
-#else
+#ifndef CRYPTOPP_GENERATE_X64_MASM
+
+#ifdef CRYPTOPP_X64_MASM_AVAILABLE
+extern "C" {
+void Rijndael_Enc_AdvancedProcessBlocks(void *locals, const word32 *k);
+}
+#endif
+
+static inline bool AliasedWithTable(const byte *begin, const byte *end)
+{
+ size_t s0 = size_t(begin)%4096, s1 = size_t(end)%4096;
+ size_t t0 = size_t(Te)%4096, t1 = (size_t(Te)+sizeof(Te))%4096;
+ if (t1 > t0)
+ return (s0 >= t0 && s0 < t1) || (s1 > t0 && s1 <= t1);
+ else
+ return (s0 < t1 || s1 <= t1) || (s0 >= t0 || s1 > t0);
+}
+
+size_t Rijndael::Enc::AdvancedProcessBlocks(const byte *inBlocks, const byte *xorBlocks, byte *outBlocks, size_t length, word32 flags) const
+{
+ if (length < BLOCKSIZE)
+ return length;
+
+ if (HasSSE2())
+ {
+ struct Locals
+ {
+ word32 subkeys[4*12], workspace[8];
+ const byte *inBlocks, *inXorBlocks, *outXorBlocks;
+ byte *outBlocks;
+ size_t inIncrement, inXorIncrement, outXorIncrement, outIncrement;
+ size_t regSpill, lengthAndCounterFlag, keysBegin;
+ };
+
+ const byte* zeros = (byte *)(Te+256);
+ byte *space;
+
+ do {
+ space = (byte *)alloca(255+sizeof(Locals));
+ space += (256-(size_t)space%256)%256;
+ }
+ while (AliasedWithTable(space, space+sizeof(Locals)));
+
+ Locals &locals = *(Locals *)space;
+
+ locals.inBlocks = inBlocks;
+ locals.inXorBlocks = (flags & BT_XorInput) && xorBlocks ? xorBlocks : zeros;
+ locals.outXorBlocks = (flags & BT_XorInput) || !xorBlocks ? zeros : xorBlocks;
+ locals.outBlocks = outBlocks;
+
+ locals.inIncrement = (flags & BT_DontIncrementInOutPointers) ? 0 : BLOCKSIZE;
+ locals.inXorIncrement = (flags & BT_XorInput) && xorBlocks ? BLOCKSIZE : 0;
+ locals.outXorIncrement = (flags & BT_XorInput) || !xorBlocks ? 0 : BLOCKSIZE;
+ locals.outIncrement = (flags & BT_DontIncrementInOutPointers) ? 0 : BLOCKSIZE;
+
+ locals.lengthAndCounterFlag = length - (length%16) - bool(flags & BT_InBlockIsCounter);
+ int keysToCopy = m_rounds - (flags & BT_InBlockIsCounter ? 3 : 2);
+ locals.keysBegin = (12-keysToCopy)*16;
+
+ #ifdef __GNUC__
+ __asm__ __volatile__
+ (
+ AS1(call Rijndael_Enc_AdvancedProcessBlocks)
+ :
+ : "c" (&locals), "d" (m_key.begin()), "S" (Te), "D" (g_cacheLineSize)
+ : "memory", "cc", "%eax"
+ #if CRYPTOPP_BOOL_X64
+ , "%rbx", "%r8", "%r10", "%r11", "%r12"
+ #endif
+ );
+ #else
+ Rijndael_Enc_AdvancedProcessBlocks(&locals, m_key);
+ #endif
+ return length%16;
}
else
-#endif
-#endif // #ifdef CRYPTOPP_X86_ASM_AVAILABLE
-#ifndef CRYPTOPP_GENERATE_X64_MASM
+ return BlockTransformation::AdvancedProcessBlocks(inBlocks, xorBlocks, outBlocks, length, flags);
+}
+
+void Rijndael::Enc::ProcessAndXorBlock(const byte *inBlock, const byte *xorBlock, byte *outBlock) const
+{
+#if CRYPTOPP_BOOL_SSE2_ASM_AVAILABLE
+ if (HasSSE2())
{
+ Rijndael::Enc::AdvancedProcessBlocks(inBlock, xorBlock, outBlock, 16, 0);
+ return;
+ }
+#endif
+
word32 s0, s1, s2, s3, t0, t1, t2, t3;
const word32 *rk = m_key;
@@ -508,42 +773,56 @@ void Rijndael::Enc::ProcessAndXorBlock(const byte *inBlock, const byte *xorBlock
const int cacheLineSize = GetCacheLineSize();
unsigned int i;
word32 u = 0;
+#ifdef CRYPTOPP_ALLOW_UNALIGNED_DATA_ACCESS
+ for (i=0; i<2048; i+=cacheLineSize)
+#else
for (i=0; i<1024; i+=cacheLineSize)
+#endif
u &= *(const word32 *)(((const byte *)Te)+i);
u &= Te[255];
s0 |= u; s1 |= u; s2 |= u; s3 |= u;
- // first round
-#ifdef IS_BIG_ENDIAN
#define QUARTER_ROUND(t, a, b, c, d) \
- a ^= rotrFixed(Te[byte(t)], 24); t >>= 8;\
- b ^= rotrFixed(Te[byte(t)], 16); t >>= 8;\
- c ^= rotrFixed(Te[byte(t)], 8); t >>= 8;\
- d ^= Te[t];
+ a ^= TL(3, byte(t)); t >>= 8;\
+ b ^= TL(2, byte(t)); t >>= 8;\
+ c ^= TL(1, byte(t)); t >>= 8;\
+ d ^= TL(0, t);
+
+#ifdef IS_LITTLE_ENDIAN
+ #ifdef CRYPTOPP_ALLOW_UNALIGNED_DATA_ACCESS
+ #define TL(i, x) (*(word32 *)((byte *)Te + x*8 + (6-i)%4+1))
+ #else
+ #define TL(i, x) rotrFixed(Te[x], (3-i)*8)
+ #endif
+ #define QUARTER_ROUND1(t, a, b, c, d) QUARTER_ROUND(t, d, c, b, a)
#else
-#define QUARTER_ROUND(t, a, b, c, d) \
- d ^= Te[byte(t)]; t >>= 8;\
- c ^= rotrFixed(Te[byte(t)], 8); t >>= 8;\
- b ^= rotrFixed(Te[byte(t)], 16); t >>= 8;\
- a ^= rotrFixed(Te[t], 24);
+ #ifdef CRYPTOPP_ALLOW_UNALIGNED_DATA_ACCESS
+ #define TL(i, x) (*(word32 *)((byte *)Te + x*8 + (4-i)%4))
+ #else
+ #define TL(i, x) rotrFixed(Te[x], i*8)
+ #endif
+ #define QUARTER_ROUND1 QUARTER_ROUND
#endif
- QUARTER_ROUND(s3, t0, t1, t2, t3)
- QUARTER_ROUND(s2, t3, t0, t1, t2)
- QUARTER_ROUND(s1, t2, t3, t0, t1)
- QUARTER_ROUND(s0, t1, t2, t3, t0)
-#undef QUARTER_ROUND
+ QUARTER_ROUND1(s3, t0, t1, t2, t3)
+ QUARTER_ROUND1(s2, t3, t0, t1, t2)
+ QUARTER_ROUND1(s1, t2, t3, t0, t1)
+ QUARTER_ROUND1(s0, t1, t2, t3, t0)
+
+#if defined(CRYPTOPP_ALLOW_UNALIGNED_DATA_ACCESS) && defined(IS_LITTLE_ENDIAN)
+ #undef TL
+ #define TL(i, x) (*(word32 *)((byte *)Te + x*8 + (i+3)%4+1))
+#endif
+
+#ifndef CRYPTOPP_ALLOW_UNALIGNED_DATA_ACCESS
+ #undef TL
+ #define TL(i, x) Te[i*256 + x]
+#endif
// Nr - 2 full rounds:
unsigned int r = m_rounds/2 - 1;
do
{
-#define QUARTER_ROUND(t, a, b, c, d) \
- a ^= Te[3*256+byte(t)]; t >>= 8;\
- b ^= Te[2*256+byte(t)]; t >>= 8;\
- c ^= Te[1*256+byte(t)]; t >>= 8;\
- d ^= Te[t];
-
s0 = rk[0]; s1 = rk[1]; s2 = rk[2]; s3 = rk[3];
QUARTER_ROUND(t3, s0, s1, s2, s3)
@@ -562,23 +841,16 @@ void Rijndael::Enc::ProcessAndXorBlock(const byte *inBlock, const byte *xorBlock
rk += 8;
} while (--r);
- // timing attack countermeasure. see comments at top for more details
- u = 0;
- for (i=0; i<256; i+=cacheLineSize)
- u &= *(const word32 *)(Se+i);
- u &= *(const word32 *)(Se+252);
- t0 |= u; t1 |= u; t2 |= u; t3 |= u;
-
word32 tbw[4];
byte *const tempBlock = (byte *)tbw;
word32 *const obw = (word32 *)outBlock;
const word32 *const xbw = (const word32 *)xorBlock;
#define QUARTER_ROUND(t, a, b, c, d) \
- tempBlock[a] = Se[byte(t)]; t >>= 8;\
- tempBlock[b] = Se[byte(t)]; t >>= 8;\
- tempBlock[c] = Se[byte(t)]; t >>= 8;\
- tempBlock[d] = Se[t];
+ tempBlock[a] = ((byte *)(Te+byte(t)))[1]; t >>= 8;\
+ tempBlock[b] = ((byte *)(Te+byte(t)))[1]; t >>= 8;\
+ tempBlock[c] = ((byte *)(Te+byte(t)))[1]; t >>= 8;\
+ tempBlock[d] = ((byte *)(Te+t))[1];
QUARTER_ROUND(t2, 15, 2, 5, 8)
QUARTER_ROUND(t1, 11, 14, 1, 4)
@@ -600,7 +872,6 @@ void Rijndael::Enc::ProcessAndXorBlock(const byte *inBlock, const byte *xorBlock
obw[2] = tbw[2] ^ rk[2];
obw[3] = tbw[3] ^ rk[3];
}
- }
}
void Rijndael::Dec::ProcessAndXorBlock(const byte *inBlock, const byte *xorBlock, byte *outBlock) const
diff --git a/rijndael.h b/rijndael.h
index 7866adc..e34f6c9 100644
--- a/rijndael.h
+++ b/rijndael.h
@@ -24,22 +24,26 @@ class CRYPTOPP_DLL Rijndael : public Rijndael_Info, public BlockCipherDocumentat
void UncheckedSetKey(const byte *userKey, unsigned int length, const NameValuePairs &params);
protected:
+ static void FillEncTable();
+ static void FillDecTable();
+
// VS2005 workaround: have to put these on seperate lines, or error C2487 is triggered in DLL build
static const byte Se[256];
static const byte Sd[256];
- static const word32 Te[4*256];
- static const word32 Td[4*256];
static const word32 rcon[];
unsigned int m_rounds;
- SecBlock<word32> m_key;
+ SecBlock<word32, AllocatorWithCleanup<word32, CRYPTOPP_BOOL_X86> > m_key;
};
class CRYPTOPP_DLL CRYPTOPP_NO_VTABLE Enc : public Base
{
public:
void ProcessAndXorBlock(const byte *inBlock, const byte *xorBlock, byte *outBlock) const;
+#if CRYPTOPP_BOOL_SSE2_ASM_AVAILABLE || defined(CRYPTOPP_X64_MASM_AVAILABLE)
+ size_t AdvancedProcessBlocks(const byte *inBlocks, const byte *xorBlocks, byte *outBlocks, size_t length, word32 flags) const;
+#endif
};
class CRYPTOPP_DLL CRYPTOPP_NO_VTABLE Dec : public Base
diff --git a/rsa.cpp b/rsa.cpp
index 8fab061..59449c4 100644
--- a/rsa.cpp
+++ b/rsa.cpp
@@ -120,7 +120,7 @@ void InvertibleRSAFunction::GenerateRandom(RandomNumberGenerator &rng, const Nam
m_p.GenerateRandom(rng, primeParam);
m_q.GenerateRandom(rng, primeParam);
- m_d = EuclideanMultiplicativeInverse(m_e, LCM(m_p-1, m_q-1));
+ m_d = m_e.InverseMod(LCM(m_p-1, m_q-1));
assert(m_d.IsPositive());
m_dp = m_d % (m_p-1);
diff --git a/safer.h b/safer.h
index 3b51c3f..f9a3c9e 100644
--- a/safer.h
+++ b/safer.h
@@ -16,7 +16,7 @@ public:
class CRYPTOPP_NO_VTABLE Base : public BlockCipher
{
public:
- unsigned int GetAlignment() const {return 1;}
+ unsigned int OptimalDataAlignment() const {return 1;}
void UncheckedSetKey(const byte *userkey, unsigned int length, const NameValuePairs &params);
protected:
diff --git a/salsa.cpp b/salsa.cpp
index 2c3b649..623edc7 100755
--- a/salsa.cpp
+++ b/salsa.cpp
@@ -30,9 +30,9 @@ void Salsa20_Policy::CipherSetKey(const NameValuePairs &params, const byte *key,
throw InvalidRounds(StaticAlgorithmName(), m_rounds);
// m_state is reordered for SSE2
- GetBlock<word32, LittleEndian, false> get1(key);
+ GetBlock<word32, LittleEndian> get1(key);
get1(m_state[13])(m_state[10])(m_state[7])(m_state[4]);
- GetBlock<word32, LittleEndian, false> get2(key + length - 16);
+ GetBlock<word32, LittleEndian> get2(key + length - 16);
get2(m_state[15])(m_state[12])(m_state[9])(m_state[6]);
// "expand 16-byte k" or "expand 32-byte k"
@@ -42,9 +42,10 @@ void Salsa20_Policy::CipherSetKey(const NameValuePairs &params, const byte *key,
m_state[3] = 0x6b206574;
}
-void Salsa20_Policy::CipherResynchronize(byte *keystreamBuffer, const byte *IV)
+void Salsa20_Policy::CipherResynchronize(byte *keystreamBuffer, const byte *IV, size_t length)
{
- GetBlock<word32, LittleEndian, false> get(IV);
+ assert(length==8);
+ GetBlock<word32, LittleEndian> get(IV);
get(m_state[14])(m_state[11]);
m_state[8] = m_state[5] = 0;
}
@@ -63,7 +64,7 @@ unsigned int Salsa20_Policy::GetAlignment() const
return 16;
else
#endif
- return 1;
+ return GetAlignmentOf<word32>();
}
unsigned int Salsa20_Policy::GetOptimalBlockSize() const
diff --git a/salsa.h b/salsa.h
index 46e0136..69dbd2c 100755
--- a/salsa.h
+++ b/salsa.h
@@ -18,7 +18,7 @@ class CRYPTOPP_NO_VTABLE Salsa20_Policy : public AdditiveCipherConcretePolicy<wo
protected:
void CipherSetKey(const NameValuePairs &params, const byte *key, size_t length);
void OperateKeystream(KeystreamOperation operation, byte *output, const byte *input, size_t iterationCount);
- void CipherResynchronize(byte *keystreamBuffer, const byte *IV);
+ void CipherResynchronize(byte *keystreamBuffer, const byte *IV, size_t length);
bool CipherIsRandomAccess() const {return true;}
void SeekToIteration(lword iterationCount);
#if CRYPTOPP_BOOL_X86 || CRYPTOPP_BOOL_X64
diff --git a/seal.cpp b/seal.cpp
index 196965f..f49b522 100644
--- a/seal.cpp
+++ b/seal.cpp
@@ -3,9 +3,6 @@
#include "pch.h"
-// prevent Sun's CC compiler from including this file automatically
-#if !(defined(__SUNPRO_CC) && defined(CRYPTOPP_ITERHASH_H))
-
#include "seal.h"
#include "sha.h"
#include "misc.h"
@@ -69,8 +66,9 @@ void SEAL_Policy<B>::CipherSetKey(const NameValuePairs &params, const byte *key,
}
template <class B>
-void SEAL_Policy<B>::CipherResynchronize(byte *keystreamBuffer, const byte *IV)
+void SEAL_Policy<B>::CipherResynchronize(byte *keystreamBuffer, const byte *IV, size_t length)
{
+ assert(length==4);
m_outsideCounter = IV ? GetWord<word32>(false, BIG_ENDIAN_ORDER, IV) : 0;
m_startCount = m_outsideCounter;
m_insideCounter = 0;
@@ -213,5 +211,3 @@ template class SEAL_Policy<BigEndian>;
template class SEAL_Policy<LittleEndian>;
NAMESPACE_END
-
-#endif
diff --git a/seal.h b/seal.h
index f914253..e14ae1c 100644
--- a/seal.h
+++ b/seal.h
@@ -18,7 +18,7 @@ class CRYPTOPP_NO_VTABLE SEAL_Policy : public AdditiveCipherConcretePolicy<word3
protected:
void CipherSetKey(const NameValuePairs &params, const byte *key, size_t length);
void OperateKeystream(KeystreamOperation operation, byte *output, const byte *input, size_t iterationCount);
- void CipherResynchronize(byte *keystreamBuffer, const byte *IV);
+ void CipherResynchronize(byte *keystreamBuffer, const byte *IV, size_t length);
bool CipherIsRandomAccess() const {return true;}
void SeekToIteration(lword iterationCount);
diff --git a/secblock.h b/secblock.h
index 3d309e6..c2e9c00 100644
--- a/secblock.h
+++ b/secblock.h
@@ -382,7 +382,7 @@ public:
bool operator==(const SecBlock<T, A> &t) const
{
- return m_size == t.m_size && memcmp(m_ptr, t.m_ptr, m_size*sizeof(T)) == 0;
+ return m_size == t.m_size && VerifyBufsEqual(m_ptr, t.m_ptr, m_size*sizeof(T));
}
bool operator!=(const SecBlock<T, A> &t) const
diff --git a/seckey.h b/seckey.h
index 4adca4b..a918f75 100644
--- a/seckey.h
+++ b/seckey.h
@@ -206,6 +206,15 @@ struct SymmetricCipherDocumentation
typedef SymmetricCipher Decryption;
};
+//! Authenticated encryption modes documentation.
+struct AuthenticatedSymmetricCipherDocumentation : public SymmetricCipherDocumentation
+{
+ //! implements the SymmetricCipher interface
+ typedef AuthenticatedSymmetricCipher Encryption;
+ //! implements the SymmetricCipher interface
+ typedef AuthenticatedSymmetricCipher Decryption;
+};
+
NAMESPACE_END
#endif
diff --git a/seed.cpp b/seed.cpp
new file mode 100644
index 0000000..6c739b4
--- /dev/null
+++ b/seed.cpp
@@ -0,0 +1,104 @@
+// seed.cpp - written and placed in the public domain by Wei Dai
+
+#include "pch.h"
+#include "seed.h"
+#include "misc.h"
+
+NAMESPACE_BEGIN(CryptoPP)
+
+static const word32 s_kc[16] = {
+ 0x9e3779b9, 0x3c6ef373, 0x78dde6e6, 0xf1bbcdcc, 0xe3779b99, 0xc6ef3733, 0x8dde6e67, 0x1bbcdccf,
+ 0x3779b99e, 0x6ef3733c, 0xdde6e678, 0xbbcdccf1, 0x779b99e3, 0xef3733c6, 0xde6e678d, 0xbcdccf1b};
+
+static const byte s_s0[256] = {
+ 0xA9, 0x85, 0xD6, 0xD3, 0x54, 0x1D, 0xAC, 0x25, 0x5D, 0x43, 0x18, 0x1E, 0x51, 0xFC, 0xCA, 0x63, 0x28,
+ 0x44, 0x20, 0x9D, 0xE0, 0xE2, 0xC8, 0x17, 0xA5, 0x8F, 0x03, 0x7B, 0xBB, 0x13, 0xD2, 0xEE, 0x70, 0x8C,
+ 0x3F, 0xA8, 0x32, 0xDD, 0xF6, 0x74, 0xEC, 0x95, 0x0B, 0x57, 0x5C, 0x5B, 0xBD, 0x01, 0x24, 0x1C, 0x73,
+ 0x98, 0x10, 0xCC, 0xF2, 0xD9, 0x2C, 0xE7, 0x72, 0x83, 0x9B, 0xD1, 0x86, 0xC9, 0x60, 0x50, 0xA3, 0xEB,
+ 0x0D, 0xB6, 0x9E, 0x4F, 0xB7, 0x5A, 0xC6, 0x78, 0xA6, 0x12, 0xAF, 0xD5, 0x61, 0xC3, 0xB4, 0x41, 0x52,
+ 0x7D, 0x8D, 0x08, 0x1F, 0x99, 0x00, 0x19, 0x04, 0x53, 0xF7, 0xE1, 0xFD, 0x76, 0x2F, 0x27, 0xB0, 0x8B,
+ 0x0E, 0xAB, 0xA2, 0x6E, 0x93, 0x4D, 0x69, 0x7C, 0x09, 0x0A, 0xBF, 0xEF, 0xF3, 0xC5, 0x87, 0x14, 0xFE,
+ 0x64, 0xDE, 0x2E, 0x4B, 0x1A, 0x06, 0x21, 0x6B, 0x66, 0x02, 0xF5, 0x92, 0x8A, 0x0C, 0xB3, 0x7E, 0xD0,
+ 0x7A, 0x47, 0x96, 0xE5, 0x26, 0x80, 0xAD, 0xDF, 0xA1, 0x30, 0x37, 0xAE, 0x36, 0x15, 0x22, 0x38, 0xF4,
+ 0xA7, 0x45, 0x4C, 0x81, 0xE9, 0x84, 0x97, 0x35, 0xCB, 0xCE, 0x3C, 0x71, 0x11, 0xC7, 0x89, 0x75, 0xFB,
+ 0xDA, 0xF8, 0x94, 0x59, 0x82, 0xC4, 0xFF, 0x49, 0x39, 0x67, 0xC0, 0xCF, 0xD7, 0xB8, 0x0F, 0x8E, 0x42,
+ 0x23, 0x91, 0x6C, 0xDB, 0xA4, 0x34, 0xF1, 0x48, 0xC2, 0x6F, 0x3D, 0x2D, 0x40, 0xBE, 0x3E, 0xBC, 0xC1,
+ 0xAA, 0xBA, 0x4E, 0x55, 0x3B, 0xDC, 0x68, 0x7F, 0x9C, 0xD8, 0x4A, 0x56, 0x77, 0xA0, 0xED, 0x46, 0xB5,
+ 0x2B, 0x65, 0xFA, 0xE3, 0xB9, 0xB1, 0x9F, 0x5E, 0xF9, 0xE6, 0xB2, 0x31, 0xEA, 0x6D, 0x5F, 0xE4, 0xF0,
+ 0xCD, 0x88, 0x16, 0x3A, 0x58, 0xD4, 0x62, 0x29, 0x07, 0x33, 0xE8, 0x1B, 0x05, 0x79, 0x90, 0x6A, 0x2A,
+ 0x9A};
+
+static const byte s_s1[256] = {
+ 0x38, 0xE8, 0x2D, 0xA6, 0xCF, 0xDE, 0xB3, 0xB8, 0xAF, 0x60, 0x55, 0xC7, 0x44, 0x6F, 0x6B, 0x5B, 0xC3,
+ 0x62, 0x33, 0xB5, 0x29, 0xA0, 0xE2, 0xA7, 0xD3, 0x91, 0x11, 0x06, 0x1C, 0xBC, 0x36, 0x4B, 0xEF, 0x88,
+ 0x6C, 0xA8, 0x17, 0xC4, 0x16, 0xF4, 0xC2, 0x45, 0xE1, 0xD6, 0x3F, 0x3D, 0x8E, 0x98, 0x28, 0x4E, 0xF6,
+ 0x3E, 0xA5, 0xF9, 0x0D, 0xDF, 0xD8, 0x2B, 0x66, 0x7A, 0x27, 0x2F, 0xF1, 0x72, 0x42, 0xD4, 0x41, 0xC0,
+ 0x73, 0x67, 0xAC, 0x8B, 0xF7, 0xAD, 0x80, 0x1F, 0xCA, 0x2C, 0xAA, 0x34, 0xD2, 0x0B, 0xEE, 0xE9, 0x5D,
+ 0x94, 0x18, 0xF8, 0x57, 0xAE, 0x08, 0xC5, 0x13, 0xCD, 0x86, 0xB9, 0xFF, 0x7D, 0xC1, 0x31, 0xF5, 0x8A,
+ 0x6A, 0xB1, 0xD1, 0x20, 0xD7, 0x02, 0x22, 0x04, 0x68, 0x71, 0x07, 0xDB, 0x9D, 0x99, 0x61, 0xBE, 0xE6,
+ 0x59, 0xDD, 0x51, 0x90, 0xDC, 0x9A, 0xA3, 0xAB, 0xD0, 0x81, 0x0F, 0x47, 0x1A, 0xE3, 0xEC, 0x8D, 0xBF,
+ 0x96, 0x7B, 0x5C, 0xA2, 0xA1, 0x63, 0x23, 0x4D, 0xC8, 0x9E, 0x9C, 0x3A, 0x0C, 0x2E, 0xBA, 0x6E, 0x9F,
+ 0x5A, 0xF2, 0x92, 0xF3, 0x49, 0x78, 0xCC, 0x15, 0xFB, 0x70, 0x75, 0x7F, 0x35, 0x10, 0x03, 0x64, 0x6D,
+ 0xC6, 0x74, 0xD5, 0xB4, 0xEA, 0x09, 0x76, 0x19, 0xFE, 0x40, 0x12, 0xE0, 0xBD, 0x05, 0xFA, 0x01, 0xF0,
+ 0x2A, 0x5E, 0xA9, 0x56, 0x43, 0x85, 0x14, 0x89, 0x9B, 0xB0, 0xE5, 0x48, 0x79, 0x97, 0xFC, 0x1E, 0x82,
+ 0x21, 0x8C, 0x1B, 0x5F, 0x77, 0x54, 0xB2, 0x1D, 0x25, 0x4F, 0x00, 0x46, 0xED, 0x58, 0x52, 0xEB, 0x7E,
+ 0xDA, 0xC9, 0xFD, 0x30, 0x95, 0x65, 0x3C, 0xB6, 0xE4, 0xBB, 0x7C, 0x0E, 0x50, 0x39, 0x26, 0x32, 0x84,
+ 0x69, 0x93, 0x37, 0xE7, 0x24, 0xA4, 0xCB, 0x53, 0x0A, 0x87, 0xD9, 0x4C, 0x83, 0x8F, 0xCE, 0x3B, 0x4A,
+ 0xB7};
+
+#define SS0(x) ((s_s0[x]*0x01010101UL) & 0x3FCFF3FC)
+#define SS1(x) ((s_s1[x]*0x01010101UL) & 0xFC3FCFF3)
+#define SS2(x) ((s_s0[x]*0x01010101UL) & 0xF3FC3FCF)
+#define SS3(x) ((s_s1[x]*0x01010101UL) & 0xCFF3FC3F)
+#define G(x) (SS0(GETBYTE(x, 0)) ^ SS1(GETBYTE(x, 1)) ^ SS2(GETBYTE(x, 2)) ^ SS3(GETBYTE(x, 3)))
+
+void SEED::Base::UncheckedSetKey(const byte *userKey, unsigned int length, const NameValuePairs &params)
+{
+ AssertValidKeyLength(length);
+
+ word64 key01, key23;
+ GetBlock<word64, BigEndian> get(userKey);
+ get(key01)(key23);
+ word32 *k = m_k;
+ size_t kInc = 2;
+ if (!IsForwardTransformation())
+ {
+ k = k+30;
+ kInc = 0-kInc;
+ }
+
+ for (int i=0; i<ROUNDS; i++)
+ {
+ word32 t0 = word32(key01>>32) + word32(key23>>32) - s_kc[i];
+ word32 t1 = word32(key01) - word32(key23) + s_kc[i];
+ k[0] = G(t0);
+ k[1] = G(t1);
+ k+=kInc;
+ if (i&1)
+ key23 = rotlFixed<word64>(key23, 8);
+ else
+ key01 = rotrFixed<word64>(key01, 8);
+ }
+}
+
+void SEED::Base::ProcessAndXorBlock(const byte *inBlock, const byte *xorBlock, byte *outBlock) const
+{
+ typedef BlockGetAndPut<word32, BigEndian> Block;
+ word32 a0, a1, b0, b1, t0, t1;
+ Block::Get(inBlock)(a0)(a1)(b0)(b1);
+
+ for (int i=0; i<ROUNDS; i+=2)
+ {
+ t0 = b0 ^ m_k[2*i+0]; t1 = b1 ^ m_k[2*i+1] ^ t0;
+ t1 = G(t1); t0 += t1; t0 = G(t0); t1 += t0; t1 = G(t1);
+ a0 ^= t0 + t1; a1 ^= t1;
+
+ t0 = a0 ^ m_k[2*i+2]; t1 = a1 ^ m_k[2*i+3] ^ t0;
+ t1 = G(t1); t0 += t1; t0 = G(t0); t1 += t0; t1 = G(t1);
+ b0 ^= t0 + t1; b1 ^= t1;
+ }
+
+ Block::Put(xorBlock, outBlock)(b0)(b1)(a0)(a1);
+}
+
+NAMESPACE_END
diff --git a/seed.h b/seed.h
new file mode 100644
index 0000000..871284d
--- /dev/null
+++ b/seed.h
@@ -0,0 +1,38 @@
+#ifndef CRYPTOPP_SEED_H
+#define CRYPTOPP_SEED_H
+
+/** \file
+*/
+
+#include "seckey.h"
+#include "secblock.h"
+
+NAMESPACE_BEGIN(CryptoPP)
+
+//! _
+struct SEED_Info : public FixedBlockSize<16>, public FixedKeyLength<16>, public FixedRounds<16>
+{
+ static const char *StaticAlgorithmName() {return "SEED";}
+};
+
+/// <a href="http://www.cryptolounge.org/wiki/SEED">SEED</a>
+class SEED : public SEED_Info, public BlockCipherDocumentation
+{
+ class CRYPTOPP_NO_VTABLE Base : public BlockCipherImpl<SEED_Info>
+ {
+ public:
+ void UncheckedSetKey(const byte *key, unsigned int length, const NameValuePairs &params);
+ void ProcessAndXorBlock(const byte *inBlock, const byte *xorBlock, byte *outBlock) const;
+
+ protected:
+ FixedSizeSecBlock<word32, 32> m_k;
+ };
+
+public:
+ typedef BlockCipherFinal<ENCRYPTION, Base> Encryption;
+ typedef BlockCipherFinal<DECRYPTION, Base> Decryption;
+};
+
+NAMESPACE_END
+
+#endif
diff --git a/sha.cpp b/sha.cpp
index 4f8d656..7322543 100644
--- a/sha.cpp
+++ b/sha.cpp
@@ -243,8 +243,6 @@ void SHA256_Transform(word32 *state, const word32 *data)
// *************************************************************
-#ifdef WORD64_AVAILABLE
-
void SHA384::InitState(HashWordType *state)
{
static const word64 s[8] = {
@@ -550,8 +548,6 @@ void SHA512::Transform(word64 *state, const word64 *data)
state[7] += h(0);
}
-#endif
-
NAMESPACE_END
#endif // #ifndef CRYPTOPP_IMPORTS
diff --git a/sha.h b/sha.h
index 40eb6df..09ef24a 100644
--- a/sha.h
+++ b/sha.h
@@ -34,8 +34,6 @@ public:
static const char * CRYPTOPP_API StaticAlgorithmName() {return "SHA-224";}
};
-#ifdef WORD64_AVAILABLE
-
//! implements the SHA-512 standard
class CRYPTOPP_DLL SHA512 : public IteratedHashWithStaticTransform<word64, BigEndian, 128, 64, SHA512>
{
@@ -54,8 +52,6 @@ public:
static const char * CRYPTOPP_API StaticAlgorithmName() {return "SHA-384";}
};
-#endif
-
NAMESPACE_END
#endif
diff --git a/shark.cpp b/shark.cpp
index 56277ce..361147e 100644
--- a/shark.cpp
+++ b/shark.cpp
@@ -1,9 +1,6 @@
// shark.cpp - written and placed in the public domain by Wei Dai
#include "pch.h"
-
-#ifdef WORD64_AVAILABLE
-
#include "shark.h"
#include "misc.h"
#include "modes.h"
@@ -137,5 +134,3 @@ void SHARK::Dec::ProcessAndXorBlock(const byte *inBlock, const byte *xorBlock, b
}
NAMESPACE_END
-
-#endif // WORD64_AVAILABLE
diff --git a/shark.h b/shark.h
index 398c7f5..8d5ce9b 100644
--- a/shark.h
+++ b/shark.h
@@ -5,9 +5,6 @@
*/
#include "config.h"
-
-#ifdef WORD64_AVAILABLE
-
#include "seckey.h"
#include "secblock.h"
@@ -66,4 +63,3 @@ typedef SHARK::Decryption SHARKDecryption;
NAMESPACE_END
#endif
-#endif
diff --git a/sharkbox.cpp b/sharkbox.cpp
index ff89313..a0ff31f 100644
--- a/sharkbox.cpp
+++ b/sharkbox.cpp
@@ -1,8 +1,6 @@
#include "pch.h"
#include "shark.h"
-#ifdef WORD64_AVAILABLE
-
NAMESPACE_BEGIN(CryptoPP)
const byte SHARK::Enc::sbox[256] = {
@@ -4162,5 +4160,3 @@ W64LIT(0xfb2043685f73ab5f),
};
NAMESPACE_END
-
-#endif // WORD64_AVAILABLE
diff --git a/skipjack.h b/skipjack.h
index d6e4296..2cf10d2 100644
--- a/skipjack.h
+++ b/skipjack.h
@@ -22,6 +22,7 @@ class SKIPJACK : public SKIPJACK_Info, public BlockCipherDocumentation
{
public:
void UncheckedSetKey(const byte *userKey, unsigned int length, const NameValuePairs &params);
+ unsigned int OptimalDataAlignment() const {return GetAlignmentOf<word16>();}
protected:
static const byte fTable[256];
diff --git a/sosemanuk.cpp b/sosemanuk.cpp
index 1f9bde4..e0e411f 100755
--- a/sosemanuk.cpp
+++ b/sosemanuk.cpp
@@ -23,8 +23,10 @@ void SosemanukPolicy::CipherSetKey(const NameValuePairs &params, const byte *use
Serpent_KeySchedule(m_key, 24, userKey, keylen);
}
-void SosemanukPolicy::CipherResynchronize(byte *keystreamBuffer, const byte *iv)
+void SosemanukPolicy::CipherResynchronize(byte *keystreamBuffer, const byte *iv, size_t length)
{
+ assert(length==16);
+
word32 a, b, c, d, e;
typedef BlockGetAndPut<word32, LittleEndian> Block;
@@ -295,7 +297,7 @@ unsigned int SosemanukPolicy::GetAlignment() const
return 16;
else
#endif
- return 1;
+ return GetAlignmentOf<word32>();
}
unsigned int SosemanukPolicy::GetOptimalBlockSize() const
@@ -418,12 +420,15 @@ void SosemanukPolicy::OperateKeystream(KeystreamOperation operation, byte *outpu
#define R11 edx
#define R20 edx
#define R21 ecx
+// workaround bug in GAS 2.15
+#define R20r WORD_REG(dx)
+#define R21r WORD_REG(cx)
#define SSE2_STEP(i, j) \
AS2( mov eax, [s(i+0)])\
AS2( mov [v(i)], eax)\
AS2( rol eax, 8)\
- AS2( lea AS_REG_7d, [AS_REG_6d + R2##j])\
+ AS2( lea AS_REG_7, [AS_REG_6 + R2##j##r])\
AS2( xor AS_REG_7d, R1##j)\
AS2( mov [u(i)], AS_REG_7d)\
AS2( mov AS_REG_7d, 1)\
diff --git a/sosemanuk.h b/sosemanuk.h
index ee78914..ff1d820 100755
--- a/sosemanuk.h
+++ b/sosemanuk.h
@@ -17,7 +17,7 @@ class SosemanukPolicy : public AdditiveCipherConcretePolicy<word32, 20>, public
protected:
void CipherSetKey(const NameValuePairs &params, const byte *key, size_t length);
void OperateKeystream(KeystreamOperation operation, byte *output, const byte *input, size_t iterationCount);
- void CipherResynchronize(byte *keystreamBuffer, const byte *iv);
+ void CipherResynchronize(byte *keystreamBuffer, const byte *iv, size_t length);
bool CipherIsRandomAccess() const {return false;}
#if CRYPTOPP_BOOL_X86 || CRYPTOPP_BOOL_X64
unsigned int GetAlignment() const;
diff --git a/strciphr.cpp b/strciphr.cpp
index 45dd4de..53e0073 100644
--- a/strciphr.cpp
+++ b/strciphr.cpp
@@ -2,9 +2,6 @@
#include "pch.h"
-// prevent Sun's CC compiler from including this file automatically
-#if !defined(__SUNPRO_CC) || defined(CRYPTOPP_MANUALLY_INSTANTIATE_TEMPLATES)
-
#ifndef CRYPTOPP_IMPORTS
#include "strciphr.h"
@@ -17,10 +14,15 @@ void AdditiveCipherTemplate<S>::UncheckedSetKey(const byte *key, unsigned int le
PolicyInterface &policy = this->AccessPolicy();
policy.CipherSetKey(params, key, length);
m_leftOver = 0;
- m_buffer.New(GetBufferByteSize(policy));
+ unsigned int bufferByteSize = policy.CanOperateKeystream() ? GetBufferByteSize(policy) : RoundUpToMultipleOf(1024U, GetBufferByteSize(policy));
+ m_buffer.New(bufferByteSize);
if (this->IsResynchronizable())
- policy.CipherResynchronize(m_buffer, this->GetIVAndThrowIfInvalid(params));
+ {
+ size_t ivLength;
+ const byte *iv = this->GetIVAndThrowIfInvalid(params, ivLength);
+ policy.CipherResynchronize(m_buffer, iv, ivLength);
+ }
}
template <class S>
@@ -48,27 +50,16 @@ void AdditiveCipherTemplate<S>::GenerateBlock(byte *outString, size_t length)
policy.WriteKeystream(outString, iterations);
outString += iterations * bytesPerIteration;
length -= iterations * bytesPerIteration;
-
- if (!length)
- return;
- }
-
- unsigned int bufferByteSize = GetBufferByteSize(policy);
- unsigned int bufferIterations = policy.GetIterationsToBuffer();
-
- while (length >= bufferByteSize)
- {
- policy.WriteKeystream(m_buffer, bufferIterations);
- memcpy(outString, KeystreamBufferBegin(), bufferByteSize);
- length -= bufferByteSize;
- outString += bufferByteSize;
}
if (length > 0)
{
- policy.WriteKeystream(m_buffer, bufferIterations);
- memcpy(outString, KeystreamBufferBegin(), length);
- m_leftOver = bytesPerIteration - length;
+ size_t bufferByteSize = RoundUpToMultipleOf(length, bytesPerIteration);
+ size_t bufferIterations = bufferByteSize / bytesPerIteration;
+
+ policy.WriteKeystream(KeystreamBufferEnd()-bufferByteSize, bufferIterations);
+ memcpy(outString, KeystreamBufferEnd()-bufferByteSize, length);
+ m_leftOver = bufferByteSize - length;
}
}
@@ -108,8 +99,8 @@ void AdditiveCipherTemplate<S>::ProcessData(byte *outString, const byte *inStrin
return;
}
- unsigned int bufferByteSize = GetBufferByteSize(policy);
- unsigned int bufferIterations = policy.GetIterationsToBuffer();
+ size_t bufferByteSize = m_buffer.size();
+ size_t bufferIterations = bufferByteSize / bytesPerIteration;
while (length >= bufferByteSize)
{
@@ -122,19 +113,22 @@ void AdditiveCipherTemplate<S>::ProcessData(byte *outString, const byte *inStrin
if (length > 0)
{
- policy.WriteKeystream(m_buffer, bufferIterations);
- xorbuf(outString, inString, KeystreamBufferBegin(), length);
- m_leftOver = bytesPerIteration - length;
+ bufferByteSize = RoundUpToMultipleOf(length, bytesPerIteration);
+ bufferIterations = bufferByteSize / bytesPerIteration;
+
+ policy.WriteKeystream(KeystreamBufferEnd()-bufferByteSize, bufferIterations);
+ xorbuf(outString, inString, KeystreamBufferEnd()-bufferByteSize, length);
+ m_leftOver = bufferByteSize - length;
}
}
template <class S>
-void AdditiveCipherTemplate<S>::Resynchronize(const byte *iv)
+void AdditiveCipherTemplate<S>::Resynchronize(const byte *iv, int length)
{
PolicyInterface &policy = this->AccessPolicy();
m_leftOver = 0;
m_buffer.New(GetBufferByteSize(policy));
- policy.CipherResynchronize(m_buffer, iv);
+ policy.CipherResynchronize(m_buffer, iv, this->ThrowIfInvalidIVLength(length));
}
template <class BASE>
@@ -148,7 +142,7 @@ void AdditiveCipherTemplate<BASE>::Seek(lword position)
if (position > 0)
{
- policy.WriteKeystream(m_buffer, 1);
+ policy.WriteKeystream(KeystreamBufferEnd()-bytesPerIteration, 1);
m_leftOver = bytesPerIteration - (unsigned int)position;
}
else
@@ -162,16 +156,20 @@ void CFB_CipherTemplate<BASE>::UncheckedSetKey(const byte *key, unsigned int len
policy.CipherSetKey(params, key, length);
if (this->IsResynchronizable())
- policy.CipherResynchronize(this->GetIVAndThrowIfInvalid(params));
+ {
+ size_t ivLength;
+ const byte *iv = this->GetIVAndThrowIfInvalid(params, ivLength);
+ policy.CipherResynchronize(iv, ivLength);
+ }
m_leftOver = policy.GetBytesPerIteration();
}
template <class BASE>
-void CFB_CipherTemplate<BASE>::Resynchronize(const byte *iv)
+void CFB_CipherTemplate<BASE>::Resynchronize(const byte *iv, int length)
{
PolicyInterface &policy = this->AccessPolicy();
- policy.CipherResynchronize(iv);
+ policy.CipherResynchronize(iv, this->ThrowIfInvalidIVLength(length));
m_leftOver = policy.GetBytesPerIteration();
}
@@ -252,5 +250,3 @@ void CFB_DecryptionTemplate<BASE>::CombineMessageAndShiftRegister(byte *output,
NAMESPACE_END
#endif
-
-#endif
diff --git a/strciphr.h b/strciphr.h
index 71a87e9..9334b0c 100644
--- a/strciphr.h
+++ b/strciphr.h
@@ -74,7 +74,7 @@ struct CRYPTOPP_DLL CRYPTOPP_NO_VTABLE AdditiveCipherAbstractPolicy
virtual bool CanOperateKeystream() const {return false;}
virtual void OperateKeystream(KeystreamOperation operation, byte *output, const byte *input, size_t iterationCount) {assert(false);}
virtual void CipherSetKey(const NameValuePairs &params, const byte *key, size_t length) =0;
- virtual void CipherResynchronize(byte *keystreamBuffer, const byte *iv) {throw NotImplemented("SimpleKeyingInterface: this object doesn't support resynchronization");}
+ virtual void CipherResynchronize(byte *keystreamBuffer, const byte *iv, size_t length) {throw NotImplemented("SimpleKeyingInterface: this object doesn't support resynchronization");}
virtual bool CipherIsRandomAccess() const =0;
virtual void SeekToIteration(lword iterationCount) {assert(!CipherIsRandomAccess()); throw NotImplemented("StreamTransformation: this object doesn't support random access");}
};
@@ -129,13 +129,13 @@ struct CRYPTOPP_NO_VTABLE AdditiveCipherConcretePolicy : public BASE
} \
output += y;
-template <class BASE = AbstractPolicyHolder<AdditiveCipherAbstractPolicy, TwoBases<SymmetricCipher, RandomNumberGenerator> > >
-class CRYPTOPP_NO_VTABLE AdditiveCipherTemplate : public BASE
+template <class BASE = AbstractPolicyHolder<AdditiveCipherAbstractPolicy, SymmetricCipher> >
+class CRYPTOPP_NO_VTABLE AdditiveCipherTemplate : public BASE, public RandomNumberGenerator
{
public:
void GenerateBlock(byte *output, size_t size);
void ProcessData(byte *outString, const byte *inString, size_t length);
- void Resynchronize(const byte *iv);
+ void Resynchronize(const byte *iv, int length=-1);
unsigned int OptimalBlockSize() const {return this->GetPolicy().GetOptimalBlockSize();}
unsigned int GetOptimalNextBlockSize() const {return (unsigned int)this->m_leftOver;}
unsigned int OptimalDataAlignment() const {return this->GetPolicy().GetAlignment();}
@@ -169,7 +169,7 @@ public:
virtual bool CanIterate() const {return false;}
virtual void Iterate(byte *output, const byte *input, CipherDir dir, size_t iterationCount) {assert(false);}
virtual void CipherSetKey(const NameValuePairs &params, const byte *key, size_t length) =0;
- virtual void CipherResynchronize(const byte *iv) {throw NotImplemented("SimpleKeyingInterface: this object doesn't support resynchronization");}
+ virtual void CipherResynchronize(const byte *iv, size_t length) {throw NotImplemented("SimpleKeyingInterface: this object doesn't support resynchronization");}
};
template <typename WT, unsigned int W, class BASE = CFB_CipherAbstractPolicy>
@@ -234,7 +234,7 @@ class CRYPTOPP_NO_VTABLE CFB_CipherTemplate : public BASE
{
public:
void ProcessData(byte *outString, const byte *inString, size_t length);
- void Resynchronize(const byte *iv);
+ void Resynchronize(const byte *iv, int length=-1);
unsigned int OptimalBlockSize() const {return this->GetPolicy().GetBytesPerIteration();}
unsigned int GetOptimalNextBlockSize() const {return (unsigned int)m_leftOver;}
unsigned int OptimalDataAlignment() const {return this->GetPolicy().GetAlignment();}
@@ -295,9 +295,8 @@ NAMESPACE_END
#endif
NAMESPACE_BEGIN(CryptoPP)
-CRYPTOPP_DLL_TEMPLATE_CLASS TwoBases<SymmetricCipher, RandomNumberGenerator>;
-CRYPTOPP_DLL_TEMPLATE_CLASS AbstractPolicyHolder<AdditiveCipherAbstractPolicy, TwoBases<SymmetricCipher, RandomNumberGenerator> >;
-CRYPTOPP_DLL_TEMPLATE_CLASS AdditiveCipherTemplate<AbstractPolicyHolder<AdditiveCipherAbstractPolicy, TwoBases<SymmetricCipher, RandomNumberGenerator> > >;
+CRYPTOPP_DLL_TEMPLATE_CLASS AbstractPolicyHolder<AdditiveCipherAbstractPolicy, SymmetricCipher>;
+CRYPTOPP_DLL_TEMPLATE_CLASS AdditiveCipherTemplate<AbstractPolicyHolder<AdditiveCipherAbstractPolicy, SymmetricCipher> >;
CRYPTOPP_DLL_TEMPLATE_CLASS CFB_CipherTemplate<AbstractPolicyHolder<CFB_CipherAbstractPolicy, SymmetricCipher> >;
CRYPTOPP_DLL_TEMPLATE_CLASS CFB_EncryptionTemplate<AbstractPolicyHolder<CFB_CipherAbstractPolicy, SymmetricCipher> >;
CRYPTOPP_DLL_TEMPLATE_CLASS CFB_DecryptionTemplate<AbstractPolicyHolder<CFB_CipherAbstractPolicy, SymmetricCipher> >;
diff --git a/test.cpp b/test.cpp
index d98a2db..de995fd 100644
--- a/test.cpp
+++ b/test.cpp
@@ -94,6 +94,13 @@ bool Validate(int, bool, const char *);
int (*AdhocTest)(int argc, char *argv[]) = NULL;
+static OFB_Mode<AES>::Encryption s_globalRNG;
+
+RandomNumberGenerator & GlobalRNG()
+{
+ return s_globalRNG;
+}
+
int CRYPTOPP_API main(int argc, char *argv[])
{
#ifdef _CRTDBG_LEAK_CHECK_DF
@@ -111,6 +118,10 @@ int CRYPTOPP_API main(int argc, char *argv[])
{
RegisterFactories();
+ std::string seed = IntToString(time(NULL));
+ seed.resize(16);
+ s_globalRNG.SetKeyWithIV((byte *)seed.data(), 16, (byte *)seed.data());
+
std::string command, executableName, macFilename;
if (argc < 2)
@@ -294,7 +305,7 @@ int CRYPTOPP_API main(int argc, char *argv[])
InformationDisperseFile(atoi(argv[2]), atoi(argv[3]), argv[4]);
else if (command == "ir")
InformationRecoverFile(argc-3, argv[2], argv+3);
- else if (command == "v")
+ else if (command == "v" || command == "vv")
return !Validate(argc>2 ? atoi(argv[2]) : 0, argv[1][1] == 'v', argc>3 ? argv[3] : NULL);
else if (command == "b")
BenchmarkAll(argc<3 ? 1 : atof(argv[2]), argc<4 ? 0 : atof(argv[3])*1e9);
@@ -374,12 +385,6 @@ SecByteBlock HexDecodeString(const char *hex)
return result;
}
-RandomNumberGenerator & GlobalRNG()
-{
- static RandomPool randomPool;
- return randomPool;
-}
-
void GenerateRSAKey(unsigned int keyLength, const char *privFilename, const char *pubFilename, const char *seed)
{
RandomPool randPool;
@@ -449,7 +454,6 @@ void DigestFile(const char *filename)
SHA1 sha;
RIPEMD160 ripemd;
SHA256 sha256;
-#ifdef WORD64_AVAILABLE
Tiger tiger;
SHA512 sha512;
Whirlpool whirlpool;
@@ -460,12 +464,6 @@ void DigestFile(const char *filename)
filters[3].reset(new HashFilter(sha256));
filters[4].reset(new HashFilter(sha512));
filters[5].reset(new HashFilter(whirlpool));
-#else
- vector_member_ptrs<HashFilter> filters(3);
- filters[0].reset(new HashFilter(sha));
- filters[1].reset(new HashFilter(ripemd));
- filters[2].reset(new HashFilter(sha256));
-#endif
auto_ptr<ChannelSwitch> channelSwitch(new ChannelSwitch);
size_t i;
@@ -762,19 +760,15 @@ void ForwardTcpPort(const char *sourcePortName, const char *destinationHost, con
#endif
}
-bool Validate(int alg, bool thorough, const char *seed)
+bool Validate(int alg, bool thorough, const char *seedInput)
{
bool result;
- std::string timeSeed;
- if (!seed)
- {
- timeSeed = IntToString(time(NULL));
- seed = timeSeed.c_str();
- }
+ std::string seed = seedInput ? std::string(seedInput) : IntToString(time(NULL));
+ seed.resize(16);
cout << "Using seed: " << seed << endl << endl;
- GlobalRNG().IncorporateEntropy((const byte *)seed, strlen(seed));
+ s_globalRNG.SetKeyWithIV((byte *)seed.data(), 16, (byte *)seed.data());
switch (alg)
{
@@ -844,6 +838,9 @@ bool Validate(int alg, bool thorough, const char *seed)
case 64: result = ValidateSalsa(); break;
case 65: result = ValidateSosemanuk(); break;
case 66: result = ValidateVMAC(); break;
+ case 67: result = ValidateCCM(); break;
+ case 68: result = ValidateGCM(); break;
+ case 69: result = ValidateCMAC(); break;
default: return false;
}
diff --git a/tiger.cpp b/tiger.cpp
index 87ec74f..c6c05ca 100644
--- a/tiger.cpp
+++ b/tiger.cpp
@@ -5,8 +5,6 @@
#include "misc.h"
#include "cpu.h"
-#ifdef WORD64_AVAILABLE
-
NAMESPACE_BEGIN(CryptoPP)
void Tiger::InitState(HashWordType *state)
@@ -265,5 +263,3 @@ void Tiger::Transform (word64 *digest, const word64 *X)
}
NAMESPACE_END
-
-#endif // WORD64_AVAILABLE
diff --git a/tiger.h b/tiger.h
index 42bf161..5f6e941 100644
--- a/tiger.h
+++ b/tiger.h
@@ -2,9 +2,6 @@
#define CRYPTOPP_TIGER_H
#include "config.h"
-
-#ifdef WORD64_AVAILABLE
-
#include "iterhash.h"
NAMESPACE_BEGIN(CryptoPP)
@@ -25,5 +22,3 @@ protected:
NAMESPACE_END
#endif
-
-#endif
diff --git a/tigertab.cpp b/tigertab.cpp
index 0197c21..5c1595b 100644
--- a/tigertab.cpp
+++ b/tigertab.cpp
@@ -1,8 +1,6 @@
#include "pch.h"
#include "tiger.h"
-#ifdef WORD64_AVAILABLE
-
NAMESPACE_BEGIN(CryptoPP)
const word64 Tiger::table[4*256+3] =
@@ -525,5 +523,3 @@ const word64 Tiger::table[4*256+3] =
};
NAMESPACE_END
-
-#endif
diff --git a/validat1.cpp b/validat1.cpp
index 1fb26c7..e0aac92 100644
--- a/validat1.cpp
+++ b/validat1.cpp
@@ -93,6 +93,10 @@ bool ValidateAll(bool thorough)
pass=ValidateSalsa() && pass;
pass=ValidateSosemanuk() && pass;
pass=ValidateVMAC() && pass;
+ pass=ValidateCCM() && pass;
+ pass=ValidateGCM() && pass;
+ pass=ValidateCMAC() && pass;
+ pass=RunTestDataFile("TestVectors/seed.txt") && pass;
pass=ValidateBBS() && pass;
pass=ValidateDH() && pass;
@@ -181,7 +185,6 @@ bool TestSettings()
}
cout << "sizeof(word32) == " << sizeof(word32) << endl;
-#ifdef WORD64_AVAILABLE
if (sizeof(word64) == 8)
cout << "passed: ";
else
@@ -190,15 +193,6 @@ bool TestSettings()
pass = false;
}
cout << "sizeof(word64) == " << sizeof(word64) << endl;
-#elif defined(CRYPTOPP_NATIVE_DWORD_AVAILABLE)
- if (sizeof(dword) >= 8)
- {
- cout << "FAILED: sizeof(dword) >= 8, but WORD64_AVAILABLE not defined" << endl;
- pass = false;
- }
- else
- cout << "passed: word64 not available" << endl;
-#endif
#ifdef CRYPTOPP_WORD128_AVAILABLE
if (sizeof(word128) == 16)
@@ -1080,13 +1074,14 @@ bool ValidateMARS()
bool ValidateRijndael()
{
- cout << "\nRijndael validation suite running...\n\n";
+ cout << "\nRijndael (AES) validation suite running...\n\n";
FileSource valdata("rijndael.dat", true, new HexDecoder);
bool pass = true;
pass = BlockTransformationTest(FixedRoundsCipherFactory<RijndaelEncryption, RijndaelDecryption>(16), valdata, 4) && pass;
pass = BlockTransformationTest(FixedRoundsCipherFactory<RijndaelEncryption, RijndaelDecryption>(24), valdata, 3) && pass;
pass = BlockTransformationTest(FixedRoundsCipherFactory<RijndaelEncryption, RijndaelDecryption>(32), valdata, 2) && pass;
+ pass = RunTestDataFile("TestVectors/aes.txt") && pass;
return pass;
}
@@ -1168,13 +1163,8 @@ bool ValidateSHARK()
{
cout << "\nSHARK validation suite running...\n\n";
-#ifdef WORD64_AVAILABLE
FileSource valdata("sharkval.dat", true, new HexDecoder);
return BlockTransformationTest(FixedRoundsCipherFactory<SHARKEncryption, SHARKDecryption>(), valdata);
-#else
- cout << "word64 not available, skipping SHARK validation." << endl;
- return true;
-#endif
}
bool ValidateCAST()
@@ -1350,3 +1340,24 @@ bool ValidateVMAC()
cout << "\nVMAC validation suite running...\n";
return RunTestDataFile("TestVectors/vmac.txt");
}
+
+bool ValidateCCM()
+{
+ cout << "\nAES/CCM validation suite running...\n";
+ return RunTestDataFile("TestVectors/ccm.txt");
+}
+
+bool ValidateGCM()
+{
+ cout << "\nAES/GCM validation suite running...\n";
+ cout << "\n2K tables:";
+ bool pass = RunTestDataFile("TestVectors/gcm.txt", MakeParameters(Name::TableSize(), (int)2048));
+ cout << "\n64K tables:";
+ return RunTestDataFile("TestVectors/gcm.txt", MakeParameters(Name::TableSize(), (int)64*1024)) && pass;
+}
+
+bool ValidateCMAC()
+{
+ cout << "\nCMAC validation suite running...\n";
+ return RunTestDataFile("TestVectors/cmac.txt");
+}
diff --git a/validat2.cpp b/validat2.cpp
index b9ed716..6ec6250 100644
--- a/validat2.cpp
+++ b/validat2.cpp
@@ -300,6 +300,12 @@ bool ValidateRSA()
pass = CryptoSystemValidate(rsaPriv, rsaPub) && pass;
}
{
+ RSAES<OAEP<SHA> >::Decryptor rsaPriv(GlobalRNG(), 512);
+ RSAES<OAEP<SHA> >::Encryptor rsaPub(rsaPriv);
+
+ pass = CryptoSystemValidate(rsaPriv, rsaPub) && pass;
+ }
+ {
byte *plain = (byte *)
"\x54\x85\x9b\x34\x2c\x49\xea\x2a";
byte *encrypted = (byte *)
diff --git a/validat3.cpp b/validat3.cpp
index 0130c35..209741c 100644
--- a/validat3.cpp
+++ b/validat3.cpp
@@ -196,7 +196,6 @@ bool ValidateSHA2()
cout << "\nSHA-384 validation suite running...\n\n";
-#ifdef WORD64_AVAILABLE
HashTestTuple testSet384[] =
{
HashTestTuple("abc", "\xcb\x00\x75\x3f\x45\xa3\x5e\x8b\xb5\xa0\x3d\x69\x9a\xc6\x50\x07\x27\x2c\x32\xab\x0e\xde\xd1\x63\x1a\x8b\x60\x5a\x43\xff\x5b\xed\x80\x86\x07\x2b\xa1\xe7\xcc\x23\x58\xba\xec\xa1\x34\xc8\x25\xa7"),
@@ -205,13 +204,9 @@ bool ValidateSHA2()
SHA384 sha384;
pass = HashModuleTest(sha384, testSet384, sizeof(testSet384)/sizeof(testSet384[0])) && pass;
-#else
- cout << "word64 not available, skipping SHA-384 validation." << endl;
-#endif
cout << "\nSHA-512 validation suite running...\n\n";
-#ifdef WORD64_AVAILABLE
HashTestTuple testSet512[] =
{
HashTestTuple("abc", "\xdd\xaf\x35\xa1\x93\x61\x7a\xba\xcc\x41\x73\x49\xae\x20\x41\x31\x12\xe6\xfa\x4e\x89\xa9\x7e\xa2\x0a\x9e\xee\xe6\x4b\x55\xd3\x9a\x21\x92\x99\x2a\x27\x4f\xc1\xa8\x36\xba\x3c\x23\xa3\xfe\xeb\xbd\x45\x4d\x44\x23\x64\x3c\xe8\x0e\x2a\x9a\xc9\x4f\xa5\x4c\xa4\x9f"),
@@ -220,9 +215,6 @@ bool ValidateSHA2()
SHA512 sha512;
pass = HashModuleTest(sha512, testSet512, sizeof(testSet512)/sizeof(testSet512[0])) && pass;
-#else
- cout << "word64 not available, skipping SHA-512 validation." << endl;
-#endif
return pass;
}
@@ -231,7 +223,6 @@ bool ValidateTiger()
{
cout << "\nTiger validation suite running...\n\n";
-#ifdef WORD64_AVAILABLE
HashTestTuple testSet[] =
{
HashTestTuple("", "\x32\x93\xac\x63\x0c\x13\xf0\x24\x5f\x92\xbb\xb1\x76\x6e\x16\x16\x7a\x4e\x58\x49\x2d\xde\x73\xf3"),
@@ -248,10 +239,6 @@ bool ValidateTiger()
Tiger tiger;
return HashModuleTest(tiger, testSet, sizeof(testSet)/sizeof(testSet[0]));
-#else
- cout << "word64 not available, skipping Tiger validation." << endl;
- return true;
-#endif
}
bool ValidateRIPEMD()
@@ -385,12 +372,7 @@ bool ValidateWhirlpool()
{
cout << "\nWhirlpool Hash Function validation suite running...\n";
-#ifdef WORD64_AVAILABLE
return RunTestDataFile("TestVectors/whrlpool.txt");
-#else
- cout << "word64 not available, skipping Whirlpool validation." << endl;
- return true;
-#endif
}
#ifdef CRYPTOPP_REMOVED
diff --git a/validate.h b/validate.h
index a111965..6853407 100644
--- a/validate.h
+++ b/validate.h
@@ -51,6 +51,9 @@ bool ValidateCamellia();
bool ValidateSalsa();
bool ValidateSosemanuk();
bool ValidateVMAC();
+bool ValidateCCM();
+bool ValidateGCM();
+bool ValidateCMAC();
bool ValidateBBS();
bool ValidateDH();
@@ -73,6 +76,6 @@ bool ValidateECDSA();
bool ValidateESIGN();
CryptoPP::RandomNumberGenerator & GlobalRNG();
-bool RunTestDataFile(const char *filename);
+bool RunTestDataFile(const char *filename, const CryptoPP::NameValuePairs &overrideParameters=CryptoPP::g_nullNameValuePairs);
#endif
diff --git a/vmac.cpp b/vmac.cpp
index ecfd278..cf95f41 100755
--- a/vmac.cpp
+++ b/vmac.cpp
@@ -8,7 +8,7 @@
NAMESPACE_BEGIN(CryptoPP)
-#if defined(_MSC_VER) && !defined(CRYPTOPP_SLOW_WORD64)
+#if defined(_MSC_VER) && !CRYPTOPP_BOOL_SLOW_WORD64
#include <intrin.h>
#endif
@@ -84,7 +84,9 @@ void VMAC_Base::UncheckedSetKey(const byte *userKey, unsigned int keylength, con
} while ((l3Key[i*2+0] >= p64) || (l3Key[i*2+1] >= p64));
m_padCached = false;
- Resynchronize(GetIVAndThrowIfInvalid(params));
+ size_t nonceLength;
+ const byte *nonce = GetIVAndThrowIfInvalid(params, nonceLength);
+ Resynchronize(nonce, (int)nonceLength);
}
void VMAC_Base::GetNextIV(RandomNumberGenerator &rng, byte *IV)
@@ -93,25 +95,35 @@ void VMAC_Base::GetNextIV(RandomNumberGenerator &rng, byte *IV)
IV[0] &= 0x7f;
}
-void VMAC_Base::Resynchronize(const byte *IV)
+void VMAC_Base::Resynchronize(const byte *nonce, int len)
{
- int s = IVSize();
+ size_t length = ThrowIfInvalidIVLength(len);
+ size_t s = IVSize();
+ byte *storedNonce = m_nonce();
+
if (m_is128)
{
- memcpy(m_nonce(), IV, s);
- AccessCipher().ProcessBlock(m_nonce(), m_pad());
+ memset(storedNonce, 0, s-length);
+ memcpy(storedNonce+s-length, nonce, length);
+ AccessCipher().ProcessBlock(storedNonce, m_pad());
}
else
{
- m_padCached = m_padCached && (m_nonce()[s-1] | 1) == (IV[s-1] | 1) && memcmp(m_nonce(), IV, s-1) == 0;
+ if (m_padCached && (storedNonce[s-1] | 1) == (nonce[length-1] | 1))
+ {
+ m_padCached = VerifyBufsEqual(storedNonce+s-length, nonce, length-1);
+ for (size_t i=0; m_padCached && i<s-length; i++)
+ m_padCached = (storedNonce[i] == 0);
+ }
if (!m_padCached)
{
- memcpy(m_nonce(), IV, s);
- m_nonce()[s-1] &= 0xfe;
- AccessCipher().ProcessBlock(m_nonce(), m_pad());
+ memset(storedNonce, 0, s-length);
+ memcpy(storedNonce+s-length, nonce, length-1);
+ storedNonce[s-1] = nonce[length-1] & 0xfe;
+ AccessCipher().ProcessBlock(storedNonce, m_pad());
m_padCached = true;
}
- m_nonce()[s-1] = IV[s-1];
+ storedNonce[s-1] = nonce[length-1];
}
m_isFirstBlock = true;
Restart();
@@ -385,7 +397,7 @@ VMAC_Base::VHASH_Update_SSE2(const word64 *data, size_t blocksRemainingInWord64,
#define MUL64(rh,rl,i1,i2) asm ("mulq %3" : "=a"(rl), "=d"(rh) : "a"(i1), "g"(i2) : "cc");
#define AccumulateNH(a, b, c) asm ("mulq %3; addq %%rax, %0; adcq %%rdx, %1" : "+r"(a##0), "+r"(a##1) : "a"(b), "g"(c) : "%rdx", "cc");
#define ADD128(rh,rl,ih,il) asm ("addq %3, %1; adcq %2, %0" : "+r"(rh),"+r"(rl) : "r"(ih),"r"(il) : "cc");
- #elif defined(_MSC_VER) && !defined(CRYPTOPP_SLOW_WORD64)
+ #elif defined(_MSC_VER) && !CRYPTOPP_BOOL_SLOW_WORD64
#define DeclareNH(a) word64 a##0=0, a##1=0
#define MUL64(rh,rl,i1,i2) (rl) = _umul128(i1,i2,&(rh));
#define AccumulateNH(a, b, c) {\
diff --git a/vmac.h b/vmac.h
index 9540617..0724017 100755
--- a/vmac.h
+++ b/vmac.h
@@ -6,23 +6,14 @@
NAMESPACE_BEGIN(CryptoPP)
-#define CRYPTOPP_BLOCK_1(n, t, s) t* m_##n() {return (t *)(m_aggregate+0);} size_t SS1() {return sizeof(t)*(s);} size_t m_##n##Size() {return (s);}
-#define CRYPTOPP_BLOCK_2(n, t, s) t* m_##n() {return (t *)(m_aggregate+SS1());} size_t SS2() {return SS1()+sizeof(t)*(s);} size_t m_##n##Size() {return (s);}
-#define CRYPTOPP_BLOCK_3(n, t, s) t* m_##n() {return (t *)(m_aggregate+SS2());} size_t SS3() {return SS2()+sizeof(t)*(s);} size_t m_##n##Size() {return (s);}
-#define CRYPTOPP_BLOCK_4(n, t, s) t* m_##n() {return (t *)(m_aggregate+SS3());} size_t SS4() {return SS3()+sizeof(t)*(s);} size_t m_##n##Size() {return (s);}
-#define CRYPTOPP_BLOCK_5(n, t, s) t* m_##n() {return (t *)(m_aggregate+SS4());} size_t SS5() {return SS4()+sizeof(t)*(s);} size_t m_##n##Size() {return (s);}
-#define CRYPTOPP_BLOCK_6(n, t, s) t* m_##n() {return (t *)(m_aggregate+SS5());} size_t SS6() {return SS5()+sizeof(t)*(s);} size_t m_##n##Size() {return (s);}
-#define CRYPTOPP_BLOCK_7(n, t, s) t* m_##n() {return (t *)(m_aggregate+SS6());} size_t SS7() {return SS6()+sizeof(t)*(s);} size_t m_##n##Size() {return (s);}
-#define CRYPTOPP_BLOCK_8(n, t, s) t* m_##n() {return (t *)(m_aggregate+SS7());} size_t SS8() {return SS7()+sizeof(t)*(s);} size_t m_##n##Size() {return (s);}
-#define CRYPTOPP_BLOCKS_END(i) size_t SST() {return SS##i();} void AllocateBlocks() {m_aggregate.New(SST());} AlignedSecByteBlock m_aggregate;
-
/// .
class VMAC_Base : public IteratedHashBase<word64, MessageAuthenticationCode>
{
public:
std::string AlgorithmName() const {return std::string("VMAC(") + GetCipher().AlgorithmName() + ")-" + IntToString(DigestSize()*8);}
unsigned int IVSize() const {return GetCipher().BlockSize();}
- void Resynchronize(const byte *IV);
+ unsigned int MinIVLength() const {return 1;}
+ void Resynchronize(const byte *nonce, int length=-1);
void GetNextIV(RandomNumberGenerator &rng, byte *IV);
unsigned int DigestSize() const {return m_is128 ? 16 : 8;};
void UncheckedSetKey(const byte *userKey, unsigned int keylength, const NameValuePairs &params);
diff --git a/wake.cpp b/wake.cpp
index 504c2d3..78c243b 100644
--- a/wake.cpp
+++ b/wake.cpp
@@ -61,7 +61,7 @@ template <class B>
void WAKE_Policy<B>::CipherSetKey(const NameValuePairs &params, const byte *key, size_t length)
{
word32 k0, k1, k2, k3;
- BlockGetAndPut<word32, BigEndian, false>::Get(key)(r3)(r4)(r5)(r6)(k0)(k1)(k2)(k3);
+ BlockGetAndPut<word32, BigEndian>::Get(key)(r3)(r4)(r5)(r6)(k0)(k1)(k2)(k3);
GenKey(k0, k1, k2, k3);
}
diff --git a/whrlpool.cpp b/whrlpool.cpp
index b78bc7d..1ebdecd 100644
--- a/whrlpool.cpp
+++ b/whrlpool.cpp
@@ -64,9 +64,6 @@
*/
#include "pch.h"
-
-#ifdef WORD64_AVAILABLE
-
#include "whrlpool.h"
#include "misc.h"
#include "cpu.h"
@@ -706,5 +703,3 @@ void Whirlpool::Transform(word64 *digest, const word64 *block)
}
NAMESPACE_END
-
-#endif // WORD64_AVAILABLE
diff --git a/whrlpool.h b/whrlpool.h
index 298850a..62c9d8a 100644
--- a/whrlpool.h
+++ b/whrlpool.h
@@ -2,9 +2,6 @@
#define CRYPTOPP_WHIRLPOOL_H
#include "config.h"
-
-#ifdef WORD64_AVAILABLE
-
#include "iterhash.h"
NAMESPACE_BEGIN(CryptoPP)
@@ -22,5 +19,3 @@ public:
NAMESPACE_END
#endif
-
-#endif
diff --git a/x64dll.asm b/x64dll.asm
new file mode 100644
index 0000000..643dbe4
--- /dev/null
+++ b/x64dll.asm
@@ -0,0 +1,665 @@
+include ksamd64.inc
+EXTERNDEF ?Te@rdtable@CryptoPP@@3PA_KA:FAR
+EXTERNDEF ?g_cacheLineSize@CryptoPP@@3IA:FAR
+.CODE
+
+ ALIGN 8
+Baseline_Add PROC
+ lea rdx, [rdx+8*rcx]
+ lea r8, [r8+8*rcx]
+ lea r9, [r9+8*rcx]
+ neg rcx ; rcx is negative index
+ jz $1@Baseline_Add
+ mov rax,[r8+8*rcx]
+ add rax,[r9+8*rcx]
+ mov [rdx+8*rcx],rax
+$0@Baseline_Add:
+ mov rax,[r8+8*rcx+8]
+ adc rax,[r9+8*rcx+8]
+ mov [rdx+8*rcx+8],rax
+ lea rcx,[rcx+2] ; advance index, avoid inc which causes slowdown on Intel Core 2
+ jrcxz $1@Baseline_Add ; loop until rcx overflows and becomes zero
+ mov rax,[r8+8*rcx]
+ adc rax,[r9+8*rcx]
+ mov [rdx+8*rcx],rax
+ jmp $0@Baseline_Add
+$1@Baseline_Add:
+ mov rax, 0
+ adc rax, rax ; store carry into rax (return result register)
+ ret
+Baseline_Add ENDP
+
+ ALIGN 8
+Baseline_Sub PROC
+ lea rdx, [rdx+8*rcx]
+ lea r8, [r8+8*rcx]
+ lea r9, [r9+8*rcx]
+ neg rcx ; rcx is negative index
+ jz $1@Baseline_Sub
+ mov rax,[r8+8*rcx]
+ sub rax,[r9+8*rcx]
+ mov [rdx+8*rcx],rax
+$0@Baseline_Sub:
+ mov rax,[r8+8*rcx+8]
+ sbb rax,[r9+8*rcx+8]
+ mov [rdx+8*rcx+8],rax
+ lea rcx,[rcx+2] ; advance index, avoid inc which causes slowdown on Intel Core 2
+ jrcxz $1@Baseline_Sub ; loop until rcx overflows and becomes zero
+ mov rax,[r8+8*rcx]
+ sbb rax,[r9+8*rcx]
+ mov [rdx+8*rcx],rax
+ jmp $0@Baseline_Sub
+$1@Baseline_Sub:
+ mov rax, 0
+ adc rax, rax ; store carry into rax (return result register)
+
+ ret
+Baseline_Sub ENDP
+
+ALIGN 8
+Rijndael_Enc_AdvancedProcessBlocks PROC FRAME
+rex_push_reg rsi
+push_reg rdi
+push_reg rbx
+push_reg rbp
+push_reg r12
+.endprolog
+mov r8, rcx
+mov rsi, ?Te@rdtable@CryptoPP@@3PA_KA
+mov rdi, QWORD PTR [?g_cacheLineSize@CryptoPP@@3IA]
+mov rbp, [(r8+16*19)]
+mov rax, 16
+and rax, rbp
+movdqa xmm3, XMMWORD PTR [rdx+16+rax]
+movdqa [(r8+16*12)], xmm3
+lea rax, [rdx+rax+2*16]
+sub rax, rbp
+label0:
+movdqa xmm0, [rax+rbp]
+movdqa XMMWORD PTR [(r8+0)+rbp], xmm0
+add rbp, 16
+cmp rbp, 16*12
+jl label0
+movdqa xmm4, [rax+rbp]
+movdqa xmm1, [rdx]
+mov r11d, [rdx+4*4]
+mov ebx, [rdx+5*4]
+mov ecx, [rdx+6*4]
+mov edx, [rdx+7*4]
+xor rax, rax
+label9:
+mov ebp, [rsi+rax]
+add rax, rdi
+mov ebp, [rsi+rax]
+add rax, rdi
+mov ebp, [rsi+rax]
+add rax, rdi
+mov ebp, [rsi+rax]
+add rax, rdi
+cmp rax, 2048
+jl label9
+lfence
+test DWORD PTR [(r8+16*18+8)], 1
+jz label8
+mov rbp, [(r8+16*14)]
+movdqa xmm2, [rbp]
+pxor xmm2, xmm1
+psrldq xmm1, 14
+movd eax, xmm1
+mov al, BYTE PTR [rbp+15]
+mov r12d, eax
+movd eax, xmm2
+psrldq xmm2, 4
+movd edi, xmm2
+psrldq xmm2, 4
+movzx ebp, al
+xor r11d, DWORD PTR [rsi+8*rbp+(((0+3) MOD (4))+1)]
+movzx ebp, ah
+xor edx, DWORD PTR [rsi+8*rbp+(((1+3) MOD (4))+1)]
+shr eax, 16
+movzx ebp, al
+xor ecx, DWORD PTR [rsi+8*rbp+(((2+3) MOD (4))+1)]
+movzx ebp, ah
+xor ebx, DWORD PTR [rsi+8*rbp+(((3+3) MOD (4))+1)]
+mov eax, edi
+movd edi, xmm2
+psrldq xmm2, 4
+movzx ebp, al
+xor ebx, DWORD PTR [rsi+8*rbp+(((0+3) MOD (4))+1)]
+movzx ebp, ah
+xor r11d, DWORD PTR [rsi+8*rbp+(((1+3) MOD (4))+1)]
+shr eax, 16
+movzx ebp, al
+xor edx, DWORD PTR [rsi+8*rbp+(((2+3) MOD (4))+1)]
+movzx ebp, ah
+xor ecx, DWORD PTR [rsi+8*rbp+(((3+3) MOD (4))+1)]
+mov eax, edi
+movd edi, xmm2
+movzx ebp, al
+xor ecx, DWORD PTR [rsi+8*rbp+(((0+3) MOD (4))+1)]
+movzx ebp, ah
+xor ebx, DWORD PTR [rsi+8*rbp+(((1+3) MOD (4))+1)]
+shr eax, 16
+movzx ebp, al
+xor r11d, DWORD PTR [rsi+8*rbp+(((2+3) MOD (4))+1)]
+movzx ebp, ah
+xor edx, DWORD PTR [rsi+8*rbp+(((3+3) MOD (4))+1)]
+mov eax, edi
+movzx ebp, al
+xor edx, DWORD PTR [rsi+8*rbp+(((0+3) MOD (4))+1)]
+movzx ebp, ah
+xor ecx, DWORD PTR [rsi+8*rbp+(((1+3) MOD (4))+1)]
+shr eax, 16
+movzx ebp, al
+xor ebx, DWORD PTR [rsi+8*rbp+(((2+3) MOD (4))+1)]
+psrldq xmm2, 3
+mov eax, [(r8+16*12)+0*4]
+mov edi, [(r8+16*12)+2*4]
+mov r10d, [(r8+16*12)+3*4]
+movzx ebp, cl
+xor r10d, DWORD PTR [rsi+8*rbp+(((3+3) MOD (4))+1)]
+movzx ebp, bl
+xor edi, DWORD PTR [rsi+8*rbp+(((3+3) MOD (4))+1)]
+movzx ebp, bh
+xor r10d, DWORD PTR [rsi+8*rbp+(((2+3) MOD (4))+1)]
+shr ebx, 16
+movzx ebp, bl
+xor eax, DWORD PTR [rsi+8*rbp+(((1+3) MOD (4))+1)]
+movzx ebp, bh
+mov ebx, DWORD PTR [rsi+8*rbp+(((0+3) MOD (4))+1)]
+xor ebx, [(r8+16*12)+1*4]
+movzx ebp, ch
+xor eax, DWORD PTR [rsi+8*rbp+(((2+3) MOD (4))+1)]
+shr ecx, 16
+movzx ebp, dl
+xor eax, DWORD PTR [rsi+8*rbp+(((3+3) MOD (4))+1)]
+movzx ebp, dh
+xor ebx, DWORD PTR [rsi+8*rbp+(((2+3) MOD (4))+1)]
+shr edx, 16
+movzx ebp, ch
+xor edi, DWORD PTR [rsi+8*rbp+(((0+3) MOD (4))+1)]
+movzx ebp, cl
+xor ebx, DWORD PTR [rsi+8*rbp+(((1+3) MOD (4))+1)]
+movzx ebp, dl
+xor edi, DWORD PTR [rsi+8*rbp+(((1+3) MOD (4))+1)]
+movzx ebp, dh
+xor r10d, DWORD PTR [rsi+8*rbp+(((0+3) MOD (4))+1)]
+movd ecx, xmm2
+mov edx, r11d
+mov [(r8+0)+3*4], r10d
+mov [(r8+0)+0*4], eax
+mov [(r8+0)+1*4], ebx
+mov [(r8+0)+2*4], edi
+jmp label5
+label3:
+mov r11d, [(r8+16*12)+0*4]
+mov ebx, [(r8+16*12)+1*4]
+mov ecx, [(r8+16*12)+2*4]
+mov edx, [(r8+16*12)+3*4]
+label8:
+mov rax, [(r8+16*14)]
+movdqu xmm2, [rax]
+mov rbp, [(r8+16*14)+8]
+movdqu xmm5, [rbp]
+pxor xmm2, xmm1
+pxor xmm2, xmm5
+movd eax, xmm2
+psrldq xmm2, 4
+movd edi, xmm2
+psrldq xmm2, 4
+movzx ebp, al
+xor r11d, DWORD PTR [rsi+8*rbp+(((0+3) MOD (4))+1)]
+movzx ebp, ah
+xor edx, DWORD PTR [rsi+8*rbp+(((1+3) MOD (4))+1)]
+shr eax, 16
+movzx ebp, al
+xor ecx, DWORD PTR [rsi+8*rbp+(((2+3) MOD (4))+1)]
+movzx ebp, ah
+xor ebx, DWORD PTR [rsi+8*rbp+(((3+3) MOD (4))+1)]
+mov eax, edi
+movd edi, xmm2
+psrldq xmm2, 4
+movzx ebp, al
+xor ebx, DWORD PTR [rsi+8*rbp+(((0+3) MOD (4))+1)]
+movzx ebp, ah
+xor r11d, DWORD PTR [rsi+8*rbp+(((1+3) MOD (4))+1)]
+shr eax, 16
+movzx ebp, al
+xor edx, DWORD PTR [rsi+8*rbp+(((2+3) MOD (4))+1)]
+movzx ebp, ah
+xor ecx, DWORD PTR [rsi+8*rbp+(((3+3) MOD (4))+1)]
+mov eax, edi
+movd edi, xmm2
+movzx ebp, al
+xor ecx, DWORD PTR [rsi+8*rbp+(((0+3) MOD (4))+1)]
+movzx ebp, ah
+xor ebx, DWORD PTR [rsi+8*rbp+(((1+3) MOD (4))+1)]
+shr eax, 16
+movzx ebp, al
+xor r11d, DWORD PTR [rsi+8*rbp+(((2+3) MOD (4))+1)]
+movzx ebp, ah
+xor edx, DWORD PTR [rsi+8*rbp+(((3+3) MOD (4))+1)]
+mov eax, edi
+movzx ebp, al
+xor edx, DWORD PTR [rsi+8*rbp+(((0+3) MOD (4))+1)]
+movzx ebp, ah
+xor ecx, DWORD PTR [rsi+8*rbp+(((1+3) MOD (4))+1)]
+shr eax, 16
+movzx ebp, al
+xor ebx, DWORD PTR [rsi+8*rbp+(((2+3) MOD (4))+1)]
+movzx ebp, ah
+xor r11d, DWORD PTR [rsi+8*rbp+(((3+3) MOD (4))+1)]
+mov eax, r11d
+add r8, [(r8+16*19)]
+add r8, 4*16
+jmp label2
+label1:
+mov ecx, r12d
+mov edx, r11d
+mov eax, [(r8+0)+0*4]
+mov ebx, [(r8+0)+1*4]
+xor cl, ch
+and rcx, 255
+label5:
+add r12d, 1
+xor edx, DWORD PTR [rsi+rcx*8+3]
+movzx ebp, dl
+xor ebx, DWORD PTR [rsi+8*rbp+(((3+3) MOD (4))+1)]
+movzx ebp, dh
+mov ecx, DWORD PTR [rsi+8*rbp+(((2+3) MOD (4))+1)]
+shr edx, 16
+xor ecx, [(r8+0)+2*4]
+movzx ebp, dh
+xor eax, DWORD PTR [rsi+8*rbp+(((0+3) MOD (4))+1)]
+movzx ebp, dl
+mov edx, DWORD PTR [rsi+8*rbp+(((1+3) MOD (4))+1)]
+xor edx, [(r8+0)+3*4]
+add r8, [(r8+16*19)]
+add r8, 3*16
+jmp label4
+label2:
+mov r10d, [(r8+0)-4*16+3*4]
+mov edi, [(r8+0)-4*16+2*4]
+movzx ebp, cl
+xor r10d, DWORD PTR [rsi+8*rbp+(((3+3) MOD (4))+1)]
+mov cl, al
+movzx ebp, ah
+xor edi, DWORD PTR [rsi+8*rbp+(((2+3) MOD (4))+1)]
+shr eax, 16
+movzx ebp, bl
+xor edi, DWORD PTR [rsi+8*rbp+(((3+3) MOD (4))+1)]
+movzx ebp, bh
+xor r10d, DWORD PTR [rsi+8*rbp+(((2+3) MOD (4))+1)]
+shr ebx, 16
+movzx ebp, al
+xor r10d, DWORD PTR [rsi+8*rbp+(((1+3) MOD (4))+1)]
+movzx ebp, ah
+mov eax, DWORD PTR [rsi+8*rbp+(((0+3) MOD (4))+1)]
+movzx ebp, bl
+xor eax, DWORD PTR [rsi+8*rbp+(((1+3) MOD (4))+1)]
+movzx ebp, bh
+mov ebx, DWORD PTR [rsi+8*rbp+(((0+3) MOD (4))+1)]
+movzx ebp, ch
+xor eax, DWORD PTR [rsi+8*rbp+(((2+3) MOD (4))+1)]
+movzx ebp, cl
+xor ebx, DWORD PTR [rsi+8*rbp+(((3+3) MOD (4))+1)]
+shr ecx, 16
+movzx ebp, dl
+xor eax, DWORD PTR [rsi+8*rbp+(((3+3) MOD (4))+1)]
+movzx ebp, dh
+xor ebx, DWORD PTR [rsi+8*rbp+(((2+3) MOD (4))+1)]
+shr edx, 16
+movzx ebp, ch
+xor edi, DWORD PTR [rsi+8*rbp+(((0+3) MOD (4))+1)]
+movzx ebp, cl
+xor ebx, DWORD PTR [rsi+8*rbp+(((1+3) MOD (4))+1)]
+movzx ebp, dl
+xor edi, DWORD PTR [rsi+8*rbp+(((1+3) MOD (4))+1)]
+movzx ebp, dh
+xor r10d, DWORD PTR [rsi+8*rbp+(((0+3) MOD (4))+1)]
+mov ecx, edi
+xor eax, [(r8+0)-4*16+0*4]
+xor ebx, [(r8+0)-4*16+1*4]
+mov edx, r10d
+label4:
+mov r10d, [(r8+0)-4*16+7*4]
+mov edi, [(r8+0)-4*16+6*4]
+movzx ebp, cl
+xor r10d, DWORD PTR [rsi+8*rbp+(((3+3) MOD (4))+1)]
+mov cl, al
+movzx ebp, ah
+xor edi, DWORD PTR [rsi+8*rbp+(((2+3) MOD (4))+1)]
+shr eax, 16
+movzx ebp, bl
+xor edi, DWORD PTR [rsi+8*rbp+(((3+3) MOD (4))+1)]
+movzx ebp, bh
+xor r10d, DWORD PTR [rsi+8*rbp+(((2+3) MOD (4))+1)]
+shr ebx, 16
+movzx ebp, al
+xor r10d, DWORD PTR [rsi+8*rbp+(((1+3) MOD (4))+1)]
+movzx ebp, ah
+mov eax, DWORD PTR [rsi+8*rbp+(((0+3) MOD (4))+1)]
+movzx ebp, bl
+xor eax, DWORD PTR [rsi+8*rbp+(((1+3) MOD (4))+1)]
+movzx ebp, bh
+mov ebx, DWORD PTR [rsi+8*rbp+(((0+3) MOD (4))+1)]
+movzx ebp, ch
+xor eax, DWORD PTR [rsi+8*rbp+(((2+3) MOD (4))+1)]
+movzx ebp, cl
+xor ebx, DWORD PTR [rsi+8*rbp+(((3+3) MOD (4))+1)]
+shr ecx, 16
+movzx ebp, dl
+xor eax, DWORD PTR [rsi+8*rbp+(((3+3) MOD (4))+1)]
+movzx ebp, dh
+xor ebx, DWORD PTR [rsi+8*rbp+(((2+3) MOD (4))+1)]
+shr edx, 16
+movzx ebp, ch
+xor edi, DWORD PTR [rsi+8*rbp+(((0+3) MOD (4))+1)]
+movzx ebp, cl
+xor ebx, DWORD PTR [rsi+8*rbp+(((1+3) MOD (4))+1)]
+movzx ebp, dl
+xor edi, DWORD PTR [rsi+8*rbp+(((1+3) MOD (4))+1)]
+movzx ebp, dh
+xor r10d, DWORD PTR [rsi+8*rbp+(((0+3) MOD (4))+1)]
+mov ecx, edi
+xor eax, [(r8+0)-4*16+4*4]
+xor ebx, [(r8+0)-4*16+5*4]
+mov edx, r10d
+add r8, 32
+test r8, 255
+jnz label2
+sub r8, 16*16
+movzx ebp, ch
+movzx edi, BYTE PTR [rsi+rbp*8+1]
+movzx ebp, dl
+xor edi, DWORD PTR [rsi+rbp*8+0]
+mov WORD PTR [(r8+16*13)+2], di
+movzx ebp, dh
+movzx edi, BYTE PTR [rsi+rbp*8+1]
+movzx ebp, al
+xor edi, DWORD PTR [rsi+rbp*8+0]
+mov WORD PTR [(r8+16*13)+6], di
+shr edx, 16
+movzx ebp, ah
+movzx edi, BYTE PTR [rsi+rbp*8+1]
+movzx ebp, bl
+xor edi, DWORD PTR [rsi+rbp*8+0]
+mov WORD PTR [(r8+16*13)+10], di
+shr eax, 16
+movzx ebp, bh
+movzx edi, BYTE PTR [rsi+rbp*8+1]
+movzx ebp, cl
+xor edi, DWORD PTR [rsi+rbp*8+0]
+mov WORD PTR [(r8+16*13)+14], di
+shr ebx, 16
+movzx ebp, dh
+movzx edi, BYTE PTR [rsi+rbp*8+1]
+movzx ebp, al
+xor edi, DWORD PTR [rsi+rbp*8+0]
+mov WORD PTR [(r8+16*13)+12], di
+shr ecx, 16
+movzx ebp, ah
+movzx edi, BYTE PTR [rsi+rbp*8+1]
+movzx ebp, bl
+xor edi, DWORD PTR [rsi+rbp*8+0]
+mov WORD PTR [(r8+16*13)+0], di
+movzx ebp, bh
+movzx edi, BYTE PTR [rsi+rbp*8+1]
+movzx ebp, cl
+xor edi, DWORD PTR [rsi+rbp*8+0]
+mov WORD PTR [(r8+16*13)+4], di
+movzx ebp, ch
+movzx edi, BYTE PTR [rsi+rbp*8+1]
+movzx ebp, dl
+xor edi, DWORD PTR [rsi+rbp*8+0]
+mov WORD PTR [(r8+16*13)+8], di
+mov rax, [(r8+16*14)+16]
+mov rbx, [(r8+16*14)+24]
+mov rcx, [(r8+16*18+8)]
+sub rcx, 16
+movdqu xmm2, [rax]
+pxor xmm2, xmm4
+movdqa xmm0, [(r8+16*16)+16]
+paddq xmm0, [(r8+16*14)+16]
+movdqa [(r8+16*14)+16], xmm0
+pxor xmm2, [(r8+16*13)]
+movdqu [rbx], xmm2
+jle label7
+mov [(r8+16*18+8)], rcx
+test rcx, 1
+jnz label1
+movdqa xmm0, [(r8+16*16)]
+paddd xmm0, [(r8+16*14)]
+movdqa [(r8+16*14)], xmm0
+jmp label3
+label7:
+mov rbp, [(r8+16*18)]
+pop r12
+pop rbp
+pop rbx
+pop rdi
+pop rsi
+ret
+Rijndael_Enc_AdvancedProcessBlocks ENDP
+
+ALIGN 8
+GCM_AuthenticateBlocks_2K PROC FRAME
+rex_push_reg rsi
+push_reg rdi
+push_reg rbx
+.endprolog
+mov rsi, r8
+mov r11, r9
+movdqa xmm0, [rsi]
+label0:
+movdqu xmm4, [rcx]
+pxor xmm0, xmm4
+movd ebx, xmm0
+mov eax, 0f0f0f0f0h
+and eax, ebx
+shl ebx, 4
+and ebx, 0f0f0f0f0h
+movzx edi, ah
+movdqa xmm5, XMMWORD PTR [rsi + 32 + 1024 + rdi]
+movzx edi, al
+movdqa xmm4, XMMWORD PTR [rsi + 32 + 1024 + rdi]
+shr eax, 16
+movzx edi, ah
+movdqa xmm3, XMMWORD PTR [rsi + 32 + 1024 + rdi]
+movzx edi, al
+movdqa xmm2, XMMWORD PTR [rsi + 32 + 1024 + rdi]
+psrldq xmm0, 4
+movd eax, xmm0
+and eax, 0f0f0f0f0h
+movzx edi, bh
+pxor xmm5, XMMWORD PTR [rsi + 32 + (1-1)*256 + rdi]
+movzx edi, bl
+pxor xmm4, XMMWORD PTR [rsi + 32 + (1-1)*256 + rdi]
+shr ebx, 16
+movzx edi, bh
+pxor xmm3, XMMWORD PTR [rsi + 32 + (1-1)*256 + rdi]
+movzx edi, bl
+pxor xmm2, XMMWORD PTR [rsi + 32 + (1-1)*256 + rdi]
+movd ebx, xmm0
+shl ebx, 4
+and ebx, 0f0f0f0f0h
+movzx edi, ah
+pxor xmm5, XMMWORD PTR [rsi + 32 + 1024 + 1*256 + rdi]
+movzx edi, al
+pxor xmm4, XMMWORD PTR [rsi + 32 + 1024 + 1*256 + rdi]
+shr eax, 16
+movzx edi, ah
+pxor xmm3, XMMWORD PTR [rsi + 32 + 1024 + 1*256 + rdi]
+movzx edi, al
+pxor xmm2, XMMWORD PTR [rsi + 32 + 1024 + 1*256 + rdi]
+psrldq xmm0, 4
+movd eax, xmm0
+and eax, 0f0f0f0f0h
+movzx edi, bh
+pxor xmm5, XMMWORD PTR [rsi + 32 + (2-1)*256 + rdi]
+movzx edi, bl
+pxor xmm4, XMMWORD PTR [rsi + 32 + (2-1)*256 + rdi]
+shr ebx, 16
+movzx edi, bh
+pxor xmm3, XMMWORD PTR [rsi + 32 + (2-1)*256 + rdi]
+movzx edi, bl
+pxor xmm2, XMMWORD PTR [rsi + 32 + (2-1)*256 + rdi]
+movd ebx, xmm0
+shl ebx, 4
+and ebx, 0f0f0f0f0h
+movzx edi, ah
+pxor xmm5, XMMWORD PTR [rsi + 32 + 1024 + 2*256 + rdi]
+movzx edi, al
+pxor xmm4, XMMWORD PTR [rsi + 32 + 1024 + 2*256 + rdi]
+shr eax, 16
+movzx edi, ah
+pxor xmm3, XMMWORD PTR [rsi + 32 + 1024 + 2*256 + rdi]
+movzx edi, al
+pxor xmm2, XMMWORD PTR [rsi + 32 + 1024 + 2*256 + rdi]
+psrldq xmm0, 4
+movd eax, xmm0
+and eax, 0f0f0f0f0h
+movzx edi, bh
+pxor xmm5, XMMWORD PTR [rsi + 32 + (3-1)*256 + rdi]
+movzx edi, bl
+pxor xmm4, XMMWORD PTR [rsi + 32 + (3-1)*256 + rdi]
+shr ebx, 16
+movzx edi, bh
+pxor xmm3, XMMWORD PTR [rsi + 32 + (3-1)*256 + rdi]
+movzx edi, bl
+pxor xmm2, XMMWORD PTR [rsi + 32 + (3-1)*256 + rdi]
+movd ebx, xmm0
+shl ebx, 4
+and ebx, 0f0f0f0f0h
+movzx edi, ah
+pxor xmm5, XMMWORD PTR [rsi + 32 + 1024 + 3*256 + rdi]
+movzx edi, al
+pxor xmm4, XMMWORD PTR [rsi + 32 + 1024 + 3*256 + rdi]
+shr eax, 16
+movzx edi, ah
+pxor xmm3, XMMWORD PTR [rsi + 32 + 1024 + 3*256 + rdi]
+movzx edi, al
+pxor xmm2, XMMWORD PTR [rsi + 32 + 1024 + 3*256 + rdi]
+movzx edi, bh
+pxor xmm5, XMMWORD PTR [rsi + 32 + 3*256 + rdi]
+movzx edi, bl
+pxor xmm4, XMMWORD PTR [rsi + 32 + 3*256 + rdi]
+shr ebx, 16
+movzx edi, bh
+pxor xmm3, XMMWORD PTR [rsi + 32 + 3*256 + rdi]
+movzx edi, bl
+pxor xmm2, XMMWORD PTR [rsi + 32 + 3*256 + rdi]
+movdqa xmm0, xmm3
+pslldq xmm3, 1
+pxor xmm2, xmm3
+movdqa xmm1, xmm2
+pslldq xmm2, 1
+pxor xmm5, xmm2
+psrldq xmm0, 15
+movd rdi, xmm0
+movzx eax, WORD PTR [r11 + rdi*2]
+shl eax, 8
+movdqa xmm0, xmm5
+pslldq xmm5, 1
+pxor xmm4, xmm5
+psrldq xmm1, 15
+movd rdi, xmm1
+xor ax, WORD PTR [r11 + rdi*2]
+shl eax, 8
+psrldq xmm0, 15
+movd rdi, xmm0
+xor ax, WORD PTR [r11 + rdi*2]
+movd xmm0, eax
+pxor xmm0, xmm4
+add rcx, 16
+sub rdx, 1
+jnz label0
+movdqa [rsi], xmm0
+pop rbx
+pop rdi
+pop rsi
+ret
+GCM_AuthenticateBlocks_2K ENDP
+
+ALIGN 8
+GCM_AuthenticateBlocks_64K PROC FRAME
+rex_push_reg rsi
+push_reg rdi
+.endprolog
+mov rsi, r8
+movdqa xmm0, [rsi]
+label1:
+movdqu xmm1, [rcx]
+pxor xmm1, xmm0
+pxor xmm0, xmm0
+movd eax, xmm1
+psrldq xmm1, 4
+movzx edi, al
+add rdi, rdi
+pxor xmm0, [rsi + 32 + (0*4+0)*256*16 + rdi*8]
+movzx edi, ah
+add rdi, rdi
+pxor xmm0, [rsi + 32 + (0*4+1)*256*16 + rdi*8]
+shr eax, 16
+movzx edi, al
+add rdi, rdi
+pxor xmm0, [rsi + 32 + (0*4+2)*256*16 + rdi*8]
+movzx edi, ah
+add rdi, rdi
+pxor xmm0, [rsi + 32 + (0*4+3)*256*16 + rdi*8]
+movd eax, xmm1
+psrldq xmm1, 4
+movzx edi, al
+add rdi, rdi
+pxor xmm0, [rsi + 32 + (1*4+0)*256*16 + rdi*8]
+movzx edi, ah
+add rdi, rdi
+pxor xmm0, [rsi + 32 + (1*4+1)*256*16 + rdi*8]
+shr eax, 16
+movzx edi, al
+add rdi, rdi
+pxor xmm0, [rsi + 32 + (1*4+2)*256*16 + rdi*8]
+movzx edi, ah
+add rdi, rdi
+pxor xmm0, [rsi + 32 + (1*4+3)*256*16 + rdi*8]
+movd eax, xmm1
+psrldq xmm1, 4
+movzx edi, al
+add rdi, rdi
+pxor xmm0, [rsi + 32 + (2*4+0)*256*16 + rdi*8]
+movzx edi, ah
+add rdi, rdi
+pxor xmm0, [rsi + 32 + (2*4+1)*256*16 + rdi*8]
+shr eax, 16
+movzx edi, al
+add rdi, rdi
+pxor xmm0, [rsi + 32 + (2*4+2)*256*16 + rdi*8]
+movzx edi, ah
+add rdi, rdi
+pxor xmm0, [rsi + 32 + (2*4+3)*256*16 + rdi*8]
+movd eax, xmm1
+psrldq xmm1, 4
+movzx edi, al
+add rdi, rdi
+pxor xmm0, [rsi + 32 + (3*4+0)*256*16 + rdi*8]
+movzx edi, ah
+add rdi, rdi
+pxor xmm0, [rsi + 32 + (3*4+1)*256*16 + rdi*8]
+shr eax, 16
+movzx edi, al
+add rdi, rdi
+pxor xmm0, [rsi + 32 + (3*4+2)*256*16 + rdi*8]
+movzx edi, ah
+add rdi, rdi
+pxor xmm0, [rsi + 32 + (3*4+3)*256*16 + rdi*8]
+add rcx, 16
+sub rdx, 1
+jnz label1
+movdqa [rsi], xmm0
+pop rdi
+pop rsi
+ret
+GCM_AuthenticateBlocks_64K ENDP
+
+_TEXT ENDS
+END
diff --git a/x64masm.asm b/x64masm.asm
index a395c9a..f27c002 100755
--- a/x64masm.asm
+++ b/x64masm.asm
@@ -1,59 +1,6 @@
include ksamd64.inc
EXTERNDEF s_sosemanukMulTables:FAR
-
.CODE
- ALIGN 8
-Baseline_Add PROC
- lea rdx, [rdx+8*rcx]
- lea r8, [r8+8*rcx]
- lea r9, [r9+8*rcx]
- neg rcx ; rcx is negative index
- jz $1@Baseline_Add
- mov rax,[r8+8*rcx]
- add rax,[r9+8*rcx]
- mov [rdx+8*rcx],rax
-$0@Baseline_Add:
- mov rax,[r8+8*rcx+8]
- adc rax,[r9+8*rcx+8]
- mov [rdx+8*rcx+8],rax
- lea rcx,[rcx+2] ; advance index, avoid inc which causes slowdown on Intel Core 2
- jrcxz $1@Baseline_Add ; loop until rcx overflows and becomes zero
- mov rax,[r8+8*rcx]
- adc rax,[r9+8*rcx]
- mov [rdx+8*rcx],rax
- jmp $0@Baseline_Add
-$1@Baseline_Add:
- mov rax, 0
- adc rax, rax ; store carry into rax (return result register)
- ret
-Baseline_Add ENDP
-
- ALIGN 8
-Baseline_Sub PROC
- lea rdx, [rdx+8*rcx]
- lea r8, [r8+8*rcx]
- lea r9, [r9+8*rcx]
- neg rcx ; rcx is negative index
- jz $1@Baseline_Sub
- mov rax,[r8+8*rcx]
- sub rax,[r9+8*rcx]
- mov [rdx+8*rcx],rax
-$0@Baseline_Sub:
- mov rax,[r8+8*rcx+8]
- sbb rax,[r9+8*rcx+8]
- mov [rdx+8*rcx+8],rax
- lea rcx,[rcx+2] ; advance index, avoid inc which causes slowdown on Intel Core 2
- jrcxz $1@Baseline_Sub ; loop until rcx overflows and becomes zero
- mov rax,[r8+8*rcx]
- sbb rax,[r9+8*rcx]
- mov [rdx+8*rcx],rax
- jmp $0@Baseline_Sub
-$1@Baseline_Sub:
- mov rax, 0
- adc rax, rax ; store carry into rax (return result register)
-
- ret
-Baseline_Sub ENDP
ALIGN 8
Salsa20_OperateKeystream PROC FRAME
@@ -761,286 +708,6 @@ movdqa xmm15, [rsp + 0290h]
add rsp, 10*16 + 32*16 + 8
ret
Salsa20_OperateKeystream ENDP
-ALIGN 8
-Rijndael_Enc_ProcessAndXorBlock PROC FRAME
-rex_push_reg rbx
-push_reg rsi
-push_reg rdi
-push_reg r12
-push_reg r13
-push_reg r14
-push_reg r15
-.endprolog
-mov r11, rcx
-mov rdi, [rsp + 5*8 + 7*8] ; inBlock
-mov eax, [r8+0*4]
-xor eax, [rdi+0*4]
-mov r13d, eax
-mov ebx, [r8+1*4]
-xor ebx, [rdi+1*4]
-mov r14d, ebx
-and ebx, eax
-mov eax, [r8+2*4]
-xor eax, [rdi+2*4]
-mov r15d, eax
-and ebx, eax
-mov ecx, [r8+3*4]
-xor ecx, [rdi+3*4]
-and ebx, ecx
-and ebx, 0
-mov edi, ebx
-label2:
-and ebx, [r11+rdi]
-add edi, edx
-and ebx, [r11+rdi]
-add edi, edx
-and ebx, [r11+rdi]
-add edi, edx
-and ebx, [r11+rdi]
-add edi, edx
-cmp edi, 1024
-jl label2
-and ebx, [r11+1020]
-xor r13d, ebx
-xor r14d, ebx
-xor r15d, ebx
-xor ecx, ebx
-mov edi, [r8+4*4]
-mov eax, [r8+5*4]
-mov ebx, [r8+6*4]
-mov edx, [r8+7*4]
-add r8, 8*4
-movzx esi, cl
-xor edx, [r11+0*1024+4*rsi]
-movzx esi, ch
-xor ebx, [r11+1*1024+4*rsi]
-shr ecx, 16
-movzx esi, cl
-xor eax, [r11+2*1024+4*rsi]
-movzx esi, ch
-xor edi, [r11+3*1024+4*rsi]
-mov ecx, r15d
-movzx esi, cl
-xor ebx, [r11+0*1024+4*rsi]
-movzx esi, ch
-xor eax, [r11+1*1024+4*rsi]
-shr ecx, 16
-movzx esi, cl
-xor edi, [r11+2*1024+4*rsi]
-movzx esi, ch
-xor edx, [r11+3*1024+4*rsi]
-mov ecx, r14d
-movzx esi, cl
-xor eax, [r11+0*1024+4*rsi]
-movzx esi, ch
-xor edi, [r11+1*1024+4*rsi]
-shr ecx, 16
-movzx esi, cl
-xor edx, [r11+2*1024+4*rsi]
-movzx esi, ch
-xor ebx, [r11+3*1024+4*rsi]
-mov ecx, r13d
-movzx esi, cl
-xor edi, [r11+0*1024+4*rsi]
-movzx esi, ch
-xor edx, [r11+1*1024+4*rsi]
-shr ecx, 16
-movzx esi, cl
-xor ebx, [r11+2*1024+4*rsi]
-movzx esi, ch
-xor eax, [r11+3*1024+4*rsi]
-mov r15d, ebx
-mov r14d, eax
-mov r13d, edi
-label0:
-mov edi, [r8+0*4]
-mov eax, [r8+1*4]
-mov ebx, [r8+2*4]
-mov ecx, [r8+3*4]
-movzx esi, dl
-xor edi, [r11+3*1024+4*rsi]
-movzx esi, dh
-xor eax, [r11+2*1024+4*rsi]
-shr edx, 16
-movzx esi, dl
-xor ebx, [r11+1*1024+4*rsi]
-movzx esi, dh
-xor ecx, [r11+0*1024+4*rsi]
-mov edx, r15d
-movzx esi, dl
-xor ecx, [r11+3*1024+4*rsi]
-movzx esi, dh
-xor edi, [r11+2*1024+4*rsi]
-shr edx, 16
-movzx esi, dl
-xor eax, [r11+1*1024+4*rsi]
-movzx esi, dh
-xor ebx, [r11+0*1024+4*rsi]
-mov edx, r14d
-movzx esi, dl
-xor ebx, [r11+3*1024+4*rsi]
-movzx esi, dh
-xor ecx, [r11+2*1024+4*rsi]
-shr edx, 16
-movzx esi, dl
-xor edi, [r11+1*1024+4*rsi]
-movzx esi, dh
-xor eax, [r11+0*1024+4*rsi]
-mov edx, r13d
-movzx esi, dl
-xor eax, [r11+3*1024+4*rsi]
-movzx esi, dh
-xor ebx, [r11+2*1024+4*rsi]
-shr edx, 16
-movzx esi, dl
-xor ecx, [r11+1*1024+4*rsi]
-movzx esi, dh
-xor edi, [r11+0*1024+4*rsi]
-mov r15d, ebx
-mov r14d, eax
-mov r13d, edi
-mov edi, [r8+4*4]
-mov eax, [r8+5*4]
-mov ebx, [r8+6*4]
-mov edx, [r8+7*4]
-movzx esi, cl
-xor edi, [r11+3*1024+4*rsi]
-movzx esi, ch
-xor eax, [r11+2*1024+4*rsi]
-shr ecx, 16
-movzx esi, cl
-xor ebx, [r11+1*1024+4*rsi]
-movzx esi, ch
-xor edx, [r11+0*1024+4*rsi]
-mov ecx, r15d
-movzx esi, cl
-xor edx, [r11+3*1024+4*rsi]
-movzx esi, ch
-xor edi, [r11+2*1024+4*rsi]
-shr ecx, 16
-movzx esi, cl
-xor eax, [r11+1*1024+4*rsi]
-movzx esi, ch
-xor ebx, [r11+0*1024+4*rsi]
-mov ecx, r14d
-movzx esi, cl
-xor ebx, [r11+3*1024+4*rsi]
-movzx esi, ch
-xor edx, [r11+2*1024+4*rsi]
-shr ecx, 16
-movzx esi, cl
-xor edi, [r11+1*1024+4*rsi]
-movzx esi, ch
-xor eax, [r11+0*1024+4*rsi]
-mov ecx, r13d
-movzx esi, cl
-xor eax, [r11+3*1024+4*rsi]
-movzx esi, ch
-xor ebx, [r11+2*1024+4*rsi]
-shr ecx, 16
-movzx esi, cl
-xor edx, [r11+1*1024+4*rsi]
-movzx esi, ch
-xor edi, [r11+0*1024+4*rsi]
-mov r15d, ebx
-mov r14d, eax
-mov r13d, edi
-add r8, 8*4
-cmp r9, r8
-jne label0
-mov eax, [r9+0*4]
-mov ecx, [r9+1*4]
-mov esi, [r9+2*4]
-mov edi, [r9+3*4]
-movzx ebx, dl
-movzx ebx, BYTE PTR [r11+1+4*rbx]
-shl ebx, 3*8
-xor eax, ebx
-movzx ebx, dh
-movzx ebx, BYTE PTR [r11+1+4*rbx]
-shl ebx, 2*8
-xor ecx, ebx
-shr edx, 16
-movzx ebx, dl
-shr edx, 8
-movzx ebx, BYTE PTR [r11+1+4*rbx]
-shl ebx, 1*8
-xor esi, ebx
-movzx ebx, BYTE PTR [r11+1+4*rdx]
-xor edi, ebx
-mov edx, r15d
-movzx ebx, dl
-movzx ebx, BYTE PTR [r11+1+4*rbx]
-shl ebx, 3*8
-xor edi, ebx
-movzx ebx, dh
-movzx ebx, BYTE PTR [r11+1+4*rbx]
-shl ebx, 2*8
-xor eax, ebx
-shr edx, 16
-movzx ebx, dl
-shr edx, 8
-movzx ebx, BYTE PTR [r11+1+4*rbx]
-shl ebx, 1*8
-xor ecx, ebx
-movzx ebx, BYTE PTR [r11+1+4*rdx]
-xor esi, ebx
-mov edx, r14d
-movzx ebx, dl
-movzx ebx, BYTE PTR [r11+1+4*rbx]
-shl ebx, 3*8
-xor esi, ebx
-movzx ebx, dh
-movzx ebx, BYTE PTR [r11+1+4*rbx]
-shl ebx, 2*8
-xor edi, ebx
-shr edx, 16
-movzx ebx, dl
-shr edx, 8
-movzx ebx, BYTE PTR [r11+1+4*rbx]
-shl ebx, 1*8
-xor eax, ebx
-movzx ebx, BYTE PTR [r11+1+4*rdx]
-xor ecx, ebx
-mov edx, r13d
-movzx ebx, dl
-movzx ebx, BYTE PTR [r11+1+4*rbx]
-shl ebx, 3*8
-xor ecx, ebx
-movzx ebx, dh
-movzx ebx, BYTE PTR [r11+1+4*rbx]
-shl ebx, 2*8
-xor esi, ebx
-shr edx, 16
-movzx ebx, dl
-shr edx, 8
-movzx ebx, BYTE PTR [r11+1+4*rbx]
-shl ebx, 1*8
-xor edi, ebx
-movzx ebx, BYTE PTR [r11+1+4*rdx]
-xor eax, ebx
-mov rbx, [rsp + 6*8 + 7*8] ; xorBlock
-test rbx, rbx
-jz label1
-xor eax, [rbx+0*4]
-xor ecx, [rbx+1*4]
-xor esi, [rbx+2*4]
-xor edi, [rbx+3*4]
-label1:
-mov rbx, [rsp + 7*8 + 7*8] ; outBlock
-mov [rbx+0*4], eax
-mov [rbx+1*4], ecx
-mov [rbx+2*4], esi
-mov [rbx+3*4], edi
-pop r15
-pop r14
-pop r13
-pop r12
-pop rdi
-pop rsi
-pop rbx
-ret
-Rijndael_Enc_ProcessAndXorBlock ENDP
ALIGN 8
Sosemanuk_OperateKeystream PROC FRAME
diff --git a/xtr.cpp b/xtr.cpp
index cdb3fc8..6739070 100644
--- a/xtr.cpp
+++ b/xtr.cpp
@@ -30,7 +30,7 @@ void XTR_FindPrimesAndGenerator(RandomNumberGenerator &rng, Integer &p, Integer
assert(qFound);
bool solutionsExist = SolveModularQuadraticEquation(r1, r2, 1, -1, 1, q);
assert(solutionsExist);
- } while (!p.Randomize(rng, minP, maxP, Integer::PRIME, CRT(rng.GenerateBit()?r1:r2, q, 2, 3), 3*q));
+ } while (!p.Randomize(rng, minP, maxP, Integer::PRIME, CRT(rng.GenerateBit()?r1:r2, q, 2, 3, EuclideanMultiplicativeInverse(p, 3)), 3*q));
assert(((p.Squared() - p + 1) % q).IsZero());
GFP2_ONB<ModularArithmetic> gfp2(p);