summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--Filelist.txt3
-rw-r--r--TestVectors/all.txt1
-rw-r--r--TestVectors/rabbit.txt69
-rw-r--r--bench1.cpp2
-rw-r--r--cryptest.nmake4
-rw-r--r--cryptlib.vcxproj2
-rw-r--r--cryptlib.vcxproj.filters6
-rw-r--r--rabbit.cpp255
-rw-r--r--rabbit.h111
-rw-r--r--regtest2.cpp3
-rw-r--r--strciphr.h3
-rw-r--r--test.cpp29
-rw-r--r--validat1.cpp7
-rw-r--r--validate.h1
14 files changed, 479 insertions, 17 deletions
diff --git a/Filelist.txt b/Filelist.txt
index fd6471ed..42d6dc12 100644
--- a/Filelist.txt
+++ b/Filelist.txt
@@ -229,6 +229,8 @@ rabin.cpp
rabin.h
randpool.cpp
randpool.h
+rabbit.cpp
+rabbit.h
rc2.cpp
rc2.h
rc5.cpp
@@ -493,6 +495,7 @@ TestVectors/simon.txt
TestVectors/siphash.txt
TestVectors/sm3.txt
TestVectors/sm4.txt
+TestVectors/rabbit.txt
TestVectors/sosemanuk.txt
TestVectors/speck.txt
TestVectors/tea.txt
diff --git a/TestVectors/all.txt b/TestVectors/all.txt
index e973ae06..65e42dc5 100644
--- a/TestVectors/all.txt
+++ b/TestVectors/all.txt
@@ -40,6 +40,7 @@ Test: TestVectors/salsa.txt
Test: TestVectors/chacha.txt
#Test: TestVectors/tls_chacha.txt
Test: TestVectors/vmac.txt
+Test: TestVectors/rabbit.txt
Test: TestVectors/sosemanuk.txt
Test: TestVectors/ccm.txt
Test: TestVectors/gcm.txt
diff --git a/TestVectors/rabbit.txt b/TestVectors/rabbit.txt
new file mode 100644
index 00000000..f4b86aac
--- /dev/null
+++ b/TestVectors/rabbit.txt
@@ -0,0 +1,69 @@
+AlgorithmType: SymmetricCipher
+Name: Rabbit
+#
+Source: Rabbit test vectors, Test 1
+Key: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+Plaintext: \
+ 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 \
+ 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+Ciphertext: \
+ 02 F7 4A 1C 26 45 6B F5 EC D6 A5 36 F0 54 57 B1 \
+ A7 8A C6 89 47 6C 69 7B 39 0C 9C C5 15 D8 E8 88
+Test: Encrypt
+#
+Source: Rabbit test vectors, Test 2
+Key: C2 1F CF 38 81 CD 5E E8 62 8A CC B0 A9 89 0D F8
+Plaintext: \
+ 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 \
+ 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+Ciphertext: \
+ 3D 02 E0 C7 30 55 91 12 B4 73 B7 90 DE E0 18 DF \
+ CD 6D 73 0C E5 4E 19 F0 C3 5E C4 79 0E B6 C7 4A
+Test: Encrypt
+#
+Source: Rabbit test vectors, Test 3
+Key: 1D 27 2C 6A 2D 8E 3D FC AC 14 05 6B 78 D6 33 A0
+Plaintext: \
+ 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 \
+ 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+Ciphertext: \
+ A3 A9 7A BB 80 39 38 20 B7 E5 0C 4A BB 53 82 3D \
+ C4 42 37 99 C2 EF C9 FF B3 A4 12 5F 1F 4C 99 A8
+Test: Encrypt
+
+
+AlgorithmType: SymmetricCipher
+Name: RabbitWithIV
+#
+Source: Rabbit test vectors, Test 4
+Key: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+IV: 00 00 00 00 00 00 00 00
+Plaintext: \
+ 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 \
+ 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+Ciphertext: \
+ ED B7 05 67 37 5D CD 7C D8 95 54 F8 5E 27 A7 C6 \
+ 8D 4A DC 70 32 29 8F 7B D4 EF F5 04 AC A6 29 5F
+Test: Encrypt
+#
+Source: Rabbit test vectors, Test 5
+Key: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+IV: 59 7E 26 C1 75 F5 73 C3
+Plaintext: \
+ 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 \
+ 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+Ciphertext: \
+ 6D 7D 01 22 92 CC DC E0 E2 12 00 58 B9 4E CD 1F \
+ 2E 6F 93 ED FF 99 24 7B 01 25 21 D1 10 4E 5F A7
+Test: Encrypt
+#
+Source: Rabbit test vectors, Test 6
+Key: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+IV: 27 17 F4 D2 1A 56 EB A6
+Plaintext: \
+ 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 \
+ 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+Ciphertext: \
+ 4D 10 51 A1 23 AF B6 70 BF 8D 85 05 C8 D8 5A 44 \
+ 03 5B C3 AC C6 67 AE AE 5B 2C F4 47 79 F2 C8 96
+Test: Encrypt
diff --git a/bench1.cpp b/bench1.cpp
index 36e1a52d..d54c3657 100644
--- a/bench1.cpp
+++ b/bench1.cpp
@@ -565,6 +565,8 @@ void Benchmark2(double t, double hertz)
BenchMarkByName<SymmetricCipher>("ChaCha12");
BenchMarkByName<SymmetricCipher>("ChaCha8");
BenchMarkByName<SymmetricCipher>("Sosemanuk");
+ BenchMarkByName<SymmetricCipher>("Rabbit");
+ BenchMarkByName<SymmetricCipher>("RabbitWithIV");
BenchMarkByName<SymmetricCipher>("MARC4");
BenchMarkByName<SymmetricCipher>("SEAL-3.0-LE");
BenchMarkByName<SymmetricCipher>("WAKE-OFB-LE");
diff --git a/cryptest.nmake b/cryptest.nmake
index b2015dbf..01ec23ad 100644
--- a/cryptest.nmake
+++ b/cryptest.nmake
@@ -47,9 +47,9 @@
# If you use 'make sources' from Linux makefile, then add 'winpipes.cpp' to the list below.
-LIB_SRCS = cryptlib.cpp cpu.cpp integer.cpp 3way.cpp adler32.cpp algebra.cpp algparam.cpp arc4.cpp aria-simd.cpp aria.cpp ariatab.cpp asn.cpp authenc.cpp base32.cpp base64.cpp basecode.cpp bfinit.cpp blake2-simd.cpp blake2.cpp blowfish.cpp blumshub.cpp camellia.cpp cast.cpp casts.cpp cbcmac.cpp ccm.cpp chacha.cpp cham.cpp cham-simd.cpp channels.cpp cmac.cpp crc-simd.cpp crc.cpp default.cpp des.cpp dessp.cpp dh.cpp dh2.cpp dll.cpp dsa.cpp eax.cpp ec2n.cpp eccrypto.cpp ecp.cpp elgamal.cpp emsa2.cpp eprecomp.cpp esign.cpp files.cpp filters.cpp fips140.cpp fipstest.cpp gcm-simd.cpp gcm.cpp gf256.cpp gf2_32.cpp gf2n.cpp gfpcrypt.cpp gost.cpp gzip.cpp hex.cpp hight.cpp hmac.cpp hrtimer.cpp ida.cpp idea.cpp iterhash.cpp kalyna.cpp kalynatab.cpp keccak.cpp lea.cpp lea-simd.cpp luc.cpp mars.cpp marss.cpp md2.cpp md4.cpp md5.cpp misc.cpp modes.cpp mqueue.cpp mqv.cpp nbtheory.cpp neon-simd.cpp network.cpp oaep.cpp osrng.cpp padlkrng.cpp panama.cpp pkcspad.cpp poly1305.cpp polynomi.cpp pssr.cpp pubkey.cpp queue.cpp rabin.cpp randpool.cpp rc2.cpp rc5.cpp rc6.cpp rdrand.cpp rdtables.cpp rijndael-simd.cpp rijndael.cpp ripemd.cpp rng.cpp rsa.cpp rw.cpp safer.cpp salsa.cpp scrypt.cpp seal.cpp seed.cpp serpent.cpp sha-simd.cpp sha.cpp sha3.cpp shacal2-simd.cpp shacal2.cpp shark.cpp sharkbox.cpp simeck-simd.cpp simeck.cpp simon.cpp simon-simd.cpp skipjack.cpp sm3.cpp sm4.cpp socketft.cpp sosemanuk.cpp speck.cpp speck-simd.cpp square.cpp squaretb.cpp sse-simd.cpp strciphr.cpp tea.cpp tftables.cpp threefish.cpp tiger.cpp tigertab.cpp trdlocal.cpp ttmac.cpp tweetnacl.cpp twofish.cpp vmac.cpp wait.cpp wake.cpp whrlpool.cpp winpipes.cpp xtr.cpp xtrcrypt.cpp zdeflate.cpp zinflate.cpp zlib.cpp
+LIB_SRCS = cryptlib.cpp cpu.cpp integer.cpp 3way.cpp adler32.cpp algebra.cpp algparam.cpp arc4.cpp aria-simd.cpp aria.cpp ariatab.cpp asn.cpp authenc.cpp base32.cpp base64.cpp basecode.cpp bfinit.cpp blake2-simd.cpp blake2.cpp blowfish.cpp blumshub.cpp camellia.cpp cast.cpp casts.cpp cbcmac.cpp ccm.cpp chacha.cpp cham.cpp cham-simd.cpp channels.cpp cmac.cpp crc-simd.cpp crc.cpp default.cpp des.cpp dessp.cpp dh.cpp dh2.cpp dll.cpp dsa.cpp eax.cpp ec2n.cpp eccrypto.cpp ecp.cpp elgamal.cpp emsa2.cpp eprecomp.cpp esign.cpp files.cpp filters.cpp fips140.cpp fipstest.cpp gcm-simd.cpp gcm.cpp gf256.cpp gf2_32.cpp gf2n.cpp gfpcrypt.cpp gost.cpp gzip.cpp hex.cpp hight.cpp hmac.cpp hrtimer.cpp ida.cpp idea.cpp iterhash.cpp kalyna.cpp kalynatab.cpp keccak.cpp lea.cpp lea-simd.cpp luc.cpp mars.cpp marss.cpp md2.cpp md4.cpp md5.cpp misc.cpp modes.cpp mqueue.cpp mqv.cpp nbtheory.cpp neon-simd.cpp network.cpp oaep.cpp osrng.cpp padlkrng.cpp panama.cpp pkcspad.cpp poly1305.cpp polynomi.cpp pssr.cpp pubkey.cpp queue.cpp rabin.cpp randpool.cpp rabbit.cpp rc2.cpp rc5.cpp rc6.cpp rdrand.cpp rdtables.cpp rijndael-simd.cpp rijndael.cpp ripemd.cpp rng.cpp rsa.cpp rw.cpp safer.cpp salsa.cpp scrypt.cpp seal.cpp seed.cpp serpent.cpp sha-simd.cpp sha.cpp sha3.cpp shacal2-simd.cpp shacal2.cpp shark.cpp sharkbox.cpp simeck-simd.cpp simeck.cpp simon.cpp simon-simd.cpp skipjack.cpp sm3.cpp sm4.cpp socketft.cpp sosemanuk.cpp speck.cpp speck-simd.cpp square.cpp squaretb.cpp sse-simd.cpp strciphr.cpp tea.cpp tftables.cpp threefish.cpp tiger.cpp tigertab.cpp trdlocal.cpp ttmac.cpp tweetnacl.cpp twofish.cpp vmac.cpp wait.cpp wake.cpp whrlpool.cpp winpipes.cpp xtr.cpp xtrcrypt.cpp zdeflate.cpp zinflate.cpp zlib.cpp
-LIB_OBJS = cryptlib.obj cpu.obj integer.obj 3way.obj adler32.obj algebra.obj algparam.obj arc4.obj aria-simd.obj aria.obj ariatab.obj asn.obj authenc.obj base32.obj base64.obj basecode.obj bfinit.obj blake2-simd.obj blake2.obj blowfish.obj blumshub.obj camellia.obj cast.obj casts.obj cbcmac.obj ccm.obj chacha.obj cham.obj cham-simd.obj channels.obj cmac.obj crc-simd.obj crc.obj default.obj des.obj dessp.obj dh.obj dh2.obj dll.obj dsa.obj eax.obj ec2n.obj eccrypto.obj ecp.obj elgamal.obj emsa2.obj eprecomp.obj esign.obj files.obj filters.obj fips140.obj fipstest.obj gcm-simd.obj gcm.obj gf256.obj gf2_32.obj gf2n.obj gfpcrypt.obj gost.obj gzip.obj hex.obj hight.obj hmac.obj hrtimer.obj ida.obj idea.obj iterhash.obj kalyna.obj kalynatab.obj keccak.obj lea.obj lea-simd.obj luc.obj mars.obj marss.obj md2.obj md4.obj md5.obj misc.obj modes.obj mqueue.obj mqv.obj nbtheory.obj neon-simd.obj network.obj oaep.obj osrng.obj padlkrng.obj panama.obj pkcspad.obj poly1305.obj polynomi.obj pssr.obj pubkey.obj queue.obj rabin.obj randpool.obj rc2.obj rc5.obj rc6.obj rdrand.obj rdtables.obj rijndael-simd.obj rijndael.obj ripemd.obj rng.obj rsa.obj rw.obj safer.obj salsa.obj scrypt.obj seal.obj seed.obj serpent.obj sha-simd.obj sha.obj sha3.obj shacal2-simd.obj shacal2.obj shark.obj sharkbox.obj simeck-simd.obj simeck.obj simon.obj simon-simd.obj skipjack.obj sm3.obj sm4.obj socketft.obj sosemanuk.obj speck.obj speck-simd.obj square.obj squaretb.obj sse-simd.obj strciphr.obj tea.obj tftables.obj threefish.obj tiger.obj tigertab.obj trdlocal.obj ttmac.obj tweetnacl.obj twofish.obj vmac.obj wait.obj wake.obj whrlpool.obj winpipes.obj xtr.obj xtrcrypt.obj zdeflate.obj zinflate.obj zlib.obj
+LIB_OBJS = cryptlib.obj cpu.obj integer.obj 3way.obj adler32.obj algebra.obj algparam.obj arc4.obj aria-simd.obj aria.obj ariatab.obj asn.obj authenc.obj base32.obj base64.obj basecode.obj bfinit.obj blake2-simd.obj blake2.obj blowfish.obj blumshub.obj camellia.obj cast.obj casts.obj cbcmac.obj ccm.obj chacha.obj cham.obj cham-simd.obj channels.obj cmac.obj crc-simd.obj crc.obj default.obj des.obj dessp.obj dh.obj dh2.obj dll.obj dsa.obj eax.obj ec2n.obj eccrypto.obj ecp.obj elgamal.obj emsa2.obj eprecomp.obj esign.obj files.obj filters.obj fips140.obj fipstest.obj gcm-simd.obj gcm.obj gf256.obj gf2_32.obj gf2n.obj gfpcrypt.obj gost.obj gzip.obj hex.obj hight.obj hmac.obj hrtimer.obj ida.obj idea.obj iterhash.obj kalyna.obj kalynatab.obj keccak.obj lea.obj lea-simd.obj luc.obj mars.obj marss.obj md2.obj md4.obj md5.obj misc.obj modes.obj mqueue.obj mqv.obj nbtheory.obj neon-simd.obj network.obj oaep.obj osrng.obj padlkrng.obj panama.obj pkcspad.obj poly1305.obj polynomi.obj pssr.obj pubkey.obj queue.obj rabin.obj randpool.obj rabbit.obj rc2.obj rc5.obj rc6.obj rdrand.obj rdtables.obj rijndael-simd.obj rijndael.obj ripemd.obj rng.obj rsa.obj rw.obj safer.obj salsa.obj scrypt.obj seal.obj seed.obj serpent.obj sha-simd.obj sha.obj sha3.obj shacal2-simd.obj shacal2.obj shark.obj sharkbox.obj simeck-simd.obj simeck.obj simon.obj simon-simd.obj skipjack.obj sm3.obj sm4.obj socketft.obj sosemanuk.obj speck.obj speck-simd.obj square.obj squaretb.obj sse-simd.obj strciphr.obj tea.obj tftables.obj threefish.obj tiger.obj tigertab.obj trdlocal.obj ttmac.obj tweetnacl.obj twofish.obj vmac.obj wait.obj wake.obj whrlpool.obj winpipes.obj xtr.obj xtrcrypt.obj zdeflate.obj zinflate.obj zlib.obj
TEST_SRCS = bench1.cpp bench2.cpp test.cpp validat0.cpp validat1.cpp validat2.cpp validat3.cpp validat4.cpp datatest.cpp regtest1.cpp regtest2.cpp regtest3.cpp fipsalgt.cpp dlltest.cpp fipstest.cpp
diff --git a/cryptlib.vcxproj b/cryptlib.vcxproj
index a0bff0d4..3a4af531 100644
--- a/cryptlib.vcxproj
+++ b/cryptlib.vcxproj
@@ -271,6 +271,7 @@
<ClCompile Include="queue.cpp" />
<ClCompile Include="rabin.cpp" />
<ClCompile Include="randpool.cpp" />
+ <ClCompile Include="rabbit.cpp" />
<ClCompile Include="rc2.cpp" />
<ClCompile Include="rc5.cpp" />
<ClCompile Include="rc6.cpp" />
@@ -469,6 +470,7 @@
<ClInclude Include="queue.h" />
<ClInclude Include="rabin.h" />
<ClInclude Include="randpool.h" />
+ <ClInclude Include="rabbit.h" />
<ClInclude Include="rc2.h" />
<ClInclude Include="rc5.h" />
<ClInclude Include="rc6.h" />
diff --git a/cryptlib.vcxproj.filters b/cryptlib.vcxproj.filters
index a8478033..63e8bb4e 100644
--- a/cryptlib.vcxproj.filters
+++ b/cryptlib.vcxproj.filters
@@ -305,6 +305,9 @@
<ClCompile Include="randpool.cpp">
<Filter>Source Files</Filter>
</ClCompile>
+ <ClCompile Include="rabbit.cpp">
+ <Filter>Source Files</Filter>
+ </ClCompile>
<ClCompile Include="rc2.cpp">
<Filter>Source Files</Filter>
</ClCompile>
@@ -801,6 +804,9 @@
<ClInclude Include="randpool.h">
<Filter>Header Files</Filter>
</ClInclude>
+ <ClInclude Include="rabbit.h">
+ <Filter>Header Files</Filter>
+ </ClInclude>
<ClInclude Include="rc2.h">
<Filter>Header Files</Filter>
</ClInclude>
diff --git a/rabbit.cpp b/rabbit.cpp
new file mode 100644
index 00000000..a31c53aa
--- /dev/null
+++ b/rabbit.cpp
@@ -0,0 +1,255 @@
+// sosemanuk.cpp - written and placed in the public domain by Jeffrey Walton
+// based on public domain code by Martin Boesgaard, Mette Vesterager,
+// Thomas Pedersen, Jesper Christiansen and Ove Scavenius.
+
+#include "pch.h"
+#include "config.h"
+
+#include "rabbit.h"
+#include "secblock.h"
+#include "misc.h"
+
+ANONYMOUS_NAMESPACE_BEGIN
+
+using CryptoPP::word32;
+using CryptoPP::rotlConstant;
+#define ROTL32(x, y) rotlConstant<y>(x)
+#define U32V(x) static_cast<word32>(x)
+
+word32 G_func(word32 x)
+{
+ /* Temporary variables */
+ word32 a, b, h, l;
+
+ /* Construct high and low argument for squaring */
+ a = x & 0xFFFF;
+ b = x >> 16;
+
+ /* Calculate high and low result of squaring */
+ h = (((U32V(a*a) >> 17U) + U32V(a*b)) >> 15U) + b*b;
+ l = x*x;
+
+ /* Return high XOR low */
+ return U32V(h^l);
+}
+
+word32 NextState(word32 c[8], word32 x[8], word32 carry)
+{
+ /* Temporary variables */
+ word32 g[8], c_old[8], i;
+
+ /* Save old counter values */
+ for (i = 0; i<8; i++)
+ c_old[i] = c[i];
+
+ /* Calculate new counter values */
+ c[0] = U32V(c[0] + 0x4D34D34D + carry);
+ c[1] = U32V(c[1] + 0xD34D34D3 + (c[0] < c_old[0]));
+ c[2] = U32V(c[2] + 0x34D34D34 + (c[1] < c_old[1]));
+ c[3] = U32V(c[3] + 0x4D34D34D + (c[2] < c_old[2]));
+ c[4] = U32V(c[4] + 0xD34D34D3 + (c[3] < c_old[3]));
+ c[5] = U32V(c[5] + 0x34D34D34 + (c[4] < c_old[4]));
+ c[6] = U32V(c[6] + 0x4D34D34D + (c[5] < c_old[5]));
+ c[7] = U32V(c[7] + 0xD34D34D3 + (c[6] < c_old[6]));
+ carry = (c[7] < c_old[7]);
+
+ /* Calculate the g-values */
+ for (i = 0; i<8; i++)
+ g[i] = G_func(U32V(x[i] + c[i]));
+
+ /* Calculate new state values */
+ x[0] = U32V(g[0] + ROTL32(g[7], 16) + ROTL32(g[6], 16));
+ x[1] = U32V(g[1] + ROTL32(g[0], 8) + g[7]);
+ x[2] = U32V(g[2] + ROTL32(g[1], 16) + ROTL32(g[0], 16));
+ x[3] = U32V(g[3] + ROTL32(g[2], 8) + g[1]);
+ x[4] = U32V(g[4] + ROTL32(g[3], 16) + ROTL32(g[2], 16));
+ x[5] = U32V(g[5] + ROTL32(g[4], 8) + g[3]);
+ x[6] = U32V(g[6] + ROTL32(g[5], 16) + ROTL32(g[4], 16));
+ x[7] = U32V(g[7] + ROTL32(g[6], 8) + g[5]);
+
+ return carry;
+}
+
+ANONYMOUS_NAMESPACE_END
+
+NAMESPACE_BEGIN(CryptoPP)
+
+void RabbitPolicy::CipherSetKey(const NameValuePairs &params, const byte *userKey, size_t keylen)
+{
+ /* Generate four subkeys */
+ CRYPTOPP_UNUSED(params);
+ GetUserKey(LITTLE_ENDIAN_ORDER, m_t.begin(), 4, userKey, keylen);
+
+ /* Generate initial state variables */
+ m_mx[0] = m_t[0];
+ m_mx[2] = m_t[1];
+ m_mx[4] = m_t[2];
+ m_mx[6] = m_t[3];
+ m_mx[1] = U32V(m_t[3] << 16) | (m_t[2] >> 16);
+ m_mx[3] = U32V(m_t[0] << 16) | (m_t[3] >> 16);
+ m_mx[5] = U32V(m_t[1] << 16) | (m_t[0] >> 16);
+ m_mx[7] = U32V(m_t[2] << 16) | (m_t[1] >> 16);
+
+ /* Generate initial counter values */
+ m_mc[0] = ROTL32(m_t[2], 16);
+ m_mc[2] = ROTL32(m_t[3], 16);
+ m_mc[4] = ROTL32(m_t[0], 16);
+ m_mc[6] = ROTL32(m_t[1], 16);
+ m_mc[1] = (m_t[0] & 0xFFFF0000) | (m_t[1] & 0xFFFF);
+ m_mc[3] = (m_t[1] & 0xFFFF0000) | (m_t[2] & 0xFFFF);
+ m_mc[5] = (m_t[2] & 0xFFFF0000) | (m_t[3] & 0xFFFF);
+ m_mc[7] = (m_t[3] & 0xFFFF0000) | (m_t[0] & 0xFFFF);
+
+ /* Clear carry bit */
+ m_mcy = 0;
+
+ /* Iterate the system four times */
+ for (unsigned int i = 0; i<4; i++)
+ m_mcy = NextState(m_mc, m_mx, m_mcy);
+
+ /* Modify the counters */
+ for (unsigned int i = 0; i<8; i++)
+ m_mc[i] ^= m_mx[(i + 4) & 0x7];
+
+ /* Copy master instance to work instance */
+ for (unsigned int i = 0; i<8; i++)
+ {
+ m_wx[i] = m_mx[i];
+ m_wc[i] = m_mc[i];
+ }
+ m_wcy = m_mcy;
+}
+
+void RabbitPolicy::OperateKeystream(KeystreamOperation operation, byte *output, const byte *input, size_t iterationCount)
+{
+ // Rabbit's bufferByteSize in AdditiveCipherTemplate
+ const unsigned int BUFFER_SIZE = 16;
+
+ for (unsigned int i = 0; i<iterationCount; ++i)
+ {
+ /* Iterate the system */
+ m_wcy = NextState(m_wc, m_wx, m_wcy);
+
+ /* Encrypt/decrypt 16 bytes of data */
+ PutWord(false, LITTLE_ENDIAN_ORDER, output + 0, m_wx[0] ^ (m_wx[5] >> 16) ^ (m_wx[3] << 16));
+ PutWord(false, LITTLE_ENDIAN_ORDER, output + 4, m_wx[2] ^ (m_wx[7] >> 16) ^ (m_wx[5] << 16));
+ PutWord(false, LITTLE_ENDIAN_ORDER, output + 8, m_wx[4] ^ (m_wx[1] >> 16) ^ (m_wx[7] << 16));
+ PutWord(false, LITTLE_ENDIAN_ORDER, output + 12, m_wx[6] ^ (m_wx[3] >> 16) ^ (m_wx[1] << 16));
+
+ // If AdditiveCipherTemplate does not have an acculated keystream
+ // then it will ask OperateKeystream to XOR the plaintext with
+ // the keystream and write it to the ciphertext buffer.
+ if ((operation & INPUT_NULL) != INPUT_NULL)
+ xorbuf(output, input, BUFFER_SIZE);
+
+ /* Increment pointers to input and output data */
+ input += BUFFER_SIZE;
+ output += BUFFER_SIZE;
+ }
+}
+
+void RabbitWithIVPolicy::CipherSetKey(const NameValuePairs &params, const byte *userKey, size_t keylen)
+{
+ /* Generate four subkeys */
+ CRYPTOPP_UNUSED(params);
+ GetUserKey(LITTLE_ENDIAN_ORDER, m_t.begin(), 4, userKey, keylen);
+
+ /* Generate initial state variables */
+ m_mx[0] = m_t[0];
+ m_mx[2] = m_t[1];
+ m_mx[4] = m_t[2];
+ m_mx[6] = m_t[3];
+ m_mx[1] = U32V(m_t[3] << 16) | (m_t[2] >> 16);
+ m_mx[3] = U32V(m_t[0] << 16) | (m_t[3] >> 16);
+ m_mx[5] = U32V(m_t[1] << 16) | (m_t[0] >> 16);
+ m_mx[7] = U32V(m_t[2] << 16) | (m_t[1] >> 16);
+
+ /* Generate initial counter values */
+ m_mc[0] = ROTL32(m_t[2], 16);
+ m_mc[2] = ROTL32(m_t[3], 16);
+ m_mc[4] = ROTL32(m_t[0], 16);
+ m_mc[6] = ROTL32(m_t[1], 16);
+ m_mc[1] = (m_t[0] & 0xFFFF0000) | (m_t[1] & 0xFFFF);
+ m_mc[3] = (m_t[1] & 0xFFFF0000) | (m_t[2] & 0xFFFF);
+ m_mc[5] = (m_t[2] & 0xFFFF0000) | (m_t[3] & 0xFFFF);
+ m_mc[7] = (m_t[3] & 0xFFFF0000) | (m_t[0] & 0xFFFF);
+
+ /* Clear carry bit */
+ m_mcy = 0;
+
+ /* Iterate the system four times */
+ for (unsigned int i = 0; i<4; i++)
+ m_mcy = NextState(m_mc, m_mx, m_mcy);
+
+ /* Modify the counters */
+ for (unsigned int i = 0; i<8; i++)
+ m_mc[i] ^= m_mx[(i + 4) & 0x7];
+
+ /* Copy master instance to work instance */
+ for (unsigned int i = 0; i<8; i++)
+ {
+ m_wx[i] = m_mx[i];
+ m_wc[i] = m_mc[i];
+ }
+ m_wcy = m_mcy;
+}
+
+void RabbitWithIVPolicy::CipherResynchronize(byte *keystreamBuffer, const byte *iv, size_t length)
+{
+ CRYPTOPP_UNUSED(keystreamBuffer);
+ CRYPTOPP_ASSERT(length == 8);
+
+ /* Generate four subvectors */
+ GetBlock<word32, LittleEndian> v(iv); v(m_t[0])(m_t[2]);
+ m_t[1] = (m_t[0] >> 16) | (m_t[2] & 0xFFFF0000);
+ m_t[3] = (m_t[2] << 16) | (m_t[0] & 0x0000FFFF);
+
+ /* Modify counter values */
+ m_wc[0] = m_mc[0] ^ m_t[0];
+ m_wc[1] = m_mc[1] ^ m_t[1];
+ m_wc[2] = m_mc[2] ^ m_t[2];
+ m_wc[3] = m_mc[3] ^ m_t[3];
+ m_wc[4] = m_mc[4] ^ m_t[0];
+ m_wc[5] = m_mc[5] ^ m_t[1];
+ m_wc[6] = m_mc[6] ^ m_t[2];
+ m_wc[7] = m_mc[7] ^ m_t[3];
+
+ /* Copy state variables */
+ for (unsigned int i = 0; i<8; i++)
+ m_wx[i] = m_mx[i];
+ m_wcy = m_mcy;
+
+ /* Iterate the system four times */
+ for (unsigned int i = 0; i<4; i++)
+ m_wcy = NextState(m_wc, m_wx, m_wcy);
+}
+
+void RabbitWithIVPolicy::OperateKeystream(KeystreamOperation operation, byte *output, const byte *input, size_t iterationCount)
+{
+ // Rabbit's bufferByteSize in AdditiveCipherTemplate
+ const unsigned int BUFFER_SIZE = 16;
+
+ for (unsigned int i = 0; i<iterationCount; ++i)
+ {
+ /* Iterate the system */
+ m_wcy = NextState(m_wc, m_wx, m_wcy);
+
+ /* Encrypt/decrypt 16 bytes of data */
+ PutWord(false, LITTLE_ENDIAN_ORDER, output + 0, m_wx[0] ^ (m_wx[5] >> 16) ^ (m_wx[3] << 16));
+ PutWord(false, LITTLE_ENDIAN_ORDER, output + 4, m_wx[2] ^ (m_wx[7] >> 16) ^ (m_wx[5] << 16));
+ PutWord(false, LITTLE_ENDIAN_ORDER, output + 8, m_wx[4] ^ (m_wx[1] >> 16) ^ (m_wx[7] << 16));
+ PutWord(false, LITTLE_ENDIAN_ORDER, output + 12, m_wx[6] ^ (m_wx[3] >> 16) ^ (m_wx[1] << 16));
+
+ // If AdditiveCipherTemplate does not have an acculated keystream
+ // then it will ask OperateKeystream to XOR the plaintext with
+ // the keystream and write it to the ciphertext buffer.
+ if ((operation & INPUT_NULL) != INPUT_NULL)
+ xorbuf(output, input, BUFFER_SIZE);
+
+ /* Increment pointers to input and output data */
+ input += BUFFER_SIZE;
+ output += BUFFER_SIZE;
+ }
+}
+
+NAMESPACE_END
diff --git a/rabbit.h b/rabbit.h
new file mode 100644
index 00000000..46715f7e
--- /dev/null
+++ b/rabbit.h
@@ -0,0 +1,111 @@
+// rabbit.h - written and placed in the public domain by Jeffrey Walton
+// based on public domain code by Martin Boesgaard, Mette Vesterager,
+// Thomas Pedersen, Jesper Christiansen and Ove Scavenius.
+//
+// The reference materials and source files are available at
+// The eSTREAM Project, http://www.ecrypt.eu.org/stream/rabbitpf.html.
+
+/// \file rabbit.h
+/// \brief Classes for Rabbit stream cipher
+/// \sa <A HREF="http://www.ecrypt.eu.org/stream/p3ciphers/rabbit/rabbit_p3.pdf">The
+/// Stream Cipher Rabbit (v1.1)< /A>, <A HREF="http://www.ecrypt.eu.org/stream/rabbitpf.html">The
+/// eSTREAM Project - eSTREAM Phase 3 - Rabbit</A> and
+/// <A HREF="https://www.cryptopp.com/wiki/Rabbit">Crypto++ Wiki | Rabbit</A>.
+/// \since Crypto++ 7.1
+
+#ifndef CRYPTOPP_RABBIT_H
+#define CRYPTOPP_RABBIT_H
+
+#include "strciphr.h"
+#include "secblock.h"
+
+// The library does not have a way to describe an optional IV. Rabbit takes
+// an optional IV so two classes are offered to bridge the gap. One provides
+// Rabbit without an IV and the second provides Rabbit with an IV.
+
+NAMESPACE_BEGIN(CryptoPP)
+
+/// \brief Rabbit stream cipher information
+/// \since Crypto++ 7.1
+struct RabbitInfo : public FixedKeyLength<16, SimpleKeyingInterface::NOT_RESYNCHRONIZABLE>
+{
+ CRYPTOPP_STATIC_CONSTEXPR const char* StaticAlgorithmName() { return "Rabbit"; }
+};
+
+/// \brief Rabbit stream cipher information
+/// \since Crypto++ 7.1
+struct RabbitWithIVInfo : public FixedKeyLength<16, SimpleKeyingInterface::UNIQUE_IV, 8>
+{
+ CRYPTOPP_STATIC_CONSTEXPR const char* StaticAlgorithmName() { return "RabbitWithIV"; }
+};
+
+/// \brief Rabbit stream cipher implementation
+/// \since Crypto++ 7.1
+class RabbitPolicy : public AdditiveCipherConcretePolicy<word32, 4>, public RabbitInfo
+{
+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 CanOperateKeystream() const { return true; }
+ unsigned int GetOptimalBlockSize() const { return 16; }
+ bool CipherIsRandomAccess() const { return false; }
+
+ // Master and working states
+ FixedSizeSecBlock<word32, 8> m_mx, m_mc, m_wx, m_wc;
+ // Workspace
+ FixedSizeSecBlock<word32, 12> m_t;
+ word32 m_mcy, m_wcy; // carry
+};
+
+/// \brief Rabbit stream cipher implementation
+/// \since Crypto++ 7.1
+class RabbitWithIVPolicy : public AdditiveCipherConcretePolicy<word32, 4>, public RabbitWithIVInfo
+{
+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, size_t length);
+ bool CanOperateKeystream() const { return true; }
+ unsigned int GetOptimalBlockSize() const { return 16; }
+ bool CipherIsRandomAccess() const { return false; }
+
+ // Master and working states
+ FixedSizeSecBlock<word32, 8> m_mx, m_mc, m_wx, m_wc;
+ // Workspace
+ FixedSizeSecBlock<word32, 12> m_t;
+ word32 m_mcy, m_wcy; // carry
+};
+
+/// \brief Rabbit stream cipher
+/// \details is a stream cipher developed by Martin Boesgaard, Mette Vesterager,
+// Thomas Pedersen, Jesper Christiansen and Ove Scavenius. Rabbit is one of the final four
+/// Profile 1 (software) ciphers selected for the eSTREAM Portfolio.
+/// \sa <A HREF="http://www.ecrypt.eu.org/stream/p3ciphers/rabbit/rabbit_p3.pdf">The
+/// Stream Cipher Rabbit (v1.1)< /A>, <A HREF="http://www.ecrypt.eu.org/stream/rabbitpf.html">The
+/// eSTREAM Project - eSTREAM Phase 3 - Rabbit</A> and
+/// <A HREF="https://www.cryptopp.com/wiki/Rabbit">Crypto++ Wiki | Rabbit</A>.
+/// \since Crypto++ 7.1
+struct Rabbit : public RabbitInfo, public SymmetricCipherDocumentation
+{
+ typedef SymmetricCipherFinal<ConcretePolicyHolder<RabbitPolicy, AdditiveCipherTemplate<> >, RabbitInfo> Encryption;
+ typedef Encryption Decryption;
+};
+
+/// \brief Rabbit stream cipher
+/// \details is a stream cipher developed by Martin Boesgaard, Mette Vesterager,
+// Thomas Pedersen, Jesper Christiansen and Ove Scavenius. Rabbit is one of the final four
+/// Profile 1 (software) ciphers selected for the eSTREAM Portfolio.
+/// \sa <A HREF="http://www.ecrypt.eu.org/stream/p3ciphers/rabbit/rabbit_p3.pdf">The
+/// Stream Cipher Rabbit (v1.1)< /A>, <A HREF="http://www.ecrypt.eu.org/stream/rabbitpf.html">The
+/// eSTREAM Project - eSTREAM Phase 3 - Rabbit</A> and
+/// <A HREF="https://www.cryptopp.com/wiki/Rabbit">Crypto++ Wiki | Rabbit</A>.
+/// \since Crypto++ 7.1
+struct RabbitWithIV : public RabbitWithIVInfo, public SymmetricCipherDocumentation
+{
+ typedef SymmetricCipherFinal<ConcretePolicyHolder<RabbitWithIVPolicy, AdditiveCipherTemplate<> >, RabbitWithIVInfo> Encryption;
+ typedef Encryption Decryption;
+};
+
+NAMESPACE_END
+
+#endif // CRYPTOPP_RABBIT_H
diff --git a/regtest2.cpp b/regtest2.cpp
index 4b1cc94e..52477adc 100644
--- a/regtest2.cpp
+++ b/regtest2.cpp
@@ -22,6 +22,7 @@
#include "vmac.h"
#include "tiger.h"
#include "sosemanuk.h"
+#include "rabbit.h"
#include "arc4.h"
#include "ccm.h"
#include "gcm.h"
@@ -119,6 +120,8 @@ void RegisterFactories2()
RegisterSymmetricCipherDefaultFactories<ChaCha12>();
RegisterSymmetricCipherDefaultFactories<ChaCha20>();
RegisterSymmetricCipherDefaultFactories<Sosemanuk>();
+ RegisterSymmetricCipherDefaultFactories<Rabbit>();
+ RegisterSymmetricCipherDefaultFactories<RabbitWithIV>();
RegisterSymmetricCipherDefaultFactories<Weak::MARC4>();
RegisterSymmetricCipherDefaultFactories<WAKE_OFB<LittleEndian> >();
RegisterSymmetricCipherDefaultFactories<WAKE_OFB<BigEndian> >();
diff --git a/strciphr.h b/strciphr.h
index 67665752..99a4d5b1 100644
--- a/strciphr.h
+++ b/strciphr.h
@@ -97,7 +97,8 @@ enum KeystreamOperation {
/// \brief XOR the input buffer and keystream, write to the aligned output buffer
XOR_KEYSTREAM_OUTPUT_ALIGNED= OUTPUT_ALIGNED,
/// \brief XOR the aligned input buffer and keystream, write to the aligned output buffer
- XOR_KEYSTREAM_BOTH_ALIGNED = OUTPUT_ALIGNED | INPUT_ALIGNED};
+ XOR_KEYSTREAM_BOTH_ALIGNED = OUTPUT_ALIGNED | INPUT_ALIGNED
+};
/// \brief Policy object for additive stream ciphers
struct CRYPTOPP_DLL CRYPTOPP_NO_VTABLE AdditiveCipherAbstractPolicy
diff --git a/test.cpp b/test.cpp
index f8e6498f..40255904 100644
--- a/test.cpp
+++ b/test.cpp
@@ -937,20 +937,21 @@ bool Validate(int alg, bool thorough, const char *seedInput)
case 68: result = ValidateTTMAC(); break;
case 69: result = ValidateSalsa(); break;
case 70: result = ValidateSosemanuk(); break;
- case 71: result = ValidateVMAC(); break;
- case 72: result = ValidateCCM(); break;
- case 73: result = ValidateGCM(); break;
- case 74: result = ValidateCMAC(); break;
- case 75: result = ValidateSM3(); break;
- case 76: result = ValidateBLAKE2s(); break;
- case 77: result = ValidateBLAKE2b(); break;
- case 78: result = ValidatePoly1305(); break;
- case 79: result = ValidateSipHash(); break;
- case 80: result = ValidateHashDRBG(); break;
- case 81: result = ValidateHmacDRBG(); break;
- case 82: result = ValidateNaCl(); break;
- case 83: result = ValidateSIMECK(); break;
- case 84: result = ValidateCHAM(); break;
+ case 71: result = ValidateRabbit(); break;
+ case 72: result = ValidateVMAC(); break;
+ case 73: result = ValidateCCM(); break;
+ case 74: result = ValidateGCM(); break;
+ case 75: result = ValidateCMAC(); break;
+ case 76: result = ValidateSM3(); break;
+ case 77: result = ValidateBLAKE2s(); break;
+ case 78: result = ValidateBLAKE2b(); break;
+ case 79: result = ValidatePoly1305(); break;
+ case 80: result = ValidateSipHash(); break;
+ case 81: result = ValidateHashDRBG(); break;
+ case 82: result = ValidateHmacDRBG(); break;
+ case 83: result = ValidateNaCl(); break;
+ case 84: result = ValidateSIMECK(); break;
+ case 85: result = ValidateCHAM(); break;
#if defined(CRYPTOPP_EXTENDED_VALIDATION)
// http://github.com/weidai11/cryptopp/issues/92
diff --git a/validat1.cpp b/validat1.cpp
index 5078733e..d83df2d6 100644
--- a/validat1.cpp
+++ b/validat1.cpp
@@ -178,6 +178,7 @@ bool ValidateAll(bool thorough)
pass=ValidateCamellia() && pass;
pass=ValidateSalsa() && pass;
pass=ValidateSosemanuk() && pass;
+ pass=ValidateRabbit() && pass;
pass=RunTestDataFile(CRYPTOPP_DATA_DIR "TestVectors/seed.txt") && pass;
pass=RunTestDataFile(CRYPTOPP_DATA_DIR "TestVectors/threefish.txt") && pass;
pass=RunTestDataFile(CRYPTOPP_DATA_DIR "TestVectors/kalyna.txt") && pass;
@@ -3474,6 +3475,12 @@ bool ValidateSosemanuk()
return RunTestDataFile(CRYPTOPP_DATA_DIR "TestVectors/sosemanuk.txt");
}
+bool ValidateRabbit()
+{
+ std::cout << "\nRabbit validation suite running...\n";
+ return RunTestDataFile(CRYPTOPP_DATA_DIR "TestVectors/rabbit.txt");
+}
+
bool ValidateVMAC()
{
std::cout << "\nVMAC validation suite running...\n";
diff --git a/validate.h b/validate.h
index 4d471dc9..1019fbcf 100644
--- a/validate.h
+++ b/validate.h
@@ -87,6 +87,7 @@ bool ValidateHIGHT();
bool ValidateLEA();
bool ValidateCamellia();
bool ValidateSalsa();
+bool ValidateRabbit();
bool ValidateSosemanuk();
bool ValidateVMAC();
bool ValidateCCM();