mirror of
https://github.com/shadps4-emu/ext-cryptopp.git
synced 2025-02-18 20:37:42 +00:00
Add ChaChaTLS implementation (GH #265)
We tweaked ChaCha to arrive at the IETF's implementation specified by RFC 7539. We are not sure how to handle block counter wrap. At the moment the caller is responsible for managing it. We were not able to find a reference implementation so we disable SIMD implementations like SSE, AVX, NEON and Power4. We need the wide block tests for corner cases to ensure our implementation is correct.
This commit is contained in:
parent
b47f04418c
commit
5603661eec
@ -1,37 +1,93 @@
|
||||
AlgorithmType: SymmetricCipher
|
||||
Name: ChaCha20
|
||||
Name: ChaChaTLS
|
||||
Source: http://tools.ietf.org/html/draft-agl-tls-chacha20poly1305
|
||||
Comment: Section 7, Test 1
|
||||
Key: 0000000000000000000000000000000000000000000000000000000000000000
|
||||
IV: 0000000000000000
|
||||
Plaintext:
|
||||
Ciphertext: 76b8e0ada0f13d90405d6ae55386bd28bdd219b8a08ded1aa836efcc8b770dc7da41597c5157488d7724e03fb8d84a376a43b8f41518a11cc387b669
|
||||
#
|
||||
Comment: Section A.2, ChaCha20 Encryption, Test 1
|
||||
Key: 0000000000000000 0000000000000000 0000000000000000 0000000000000000
|
||||
IV: 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 \
|
||||
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: 76 b8 e0 ad a0 f1 3d 90 40 5d 6a e5 53 86 bd 28 \
|
||||
bd d2 19 b8 a0 8d ed 1a a8 36 ef cc 8b 77 0d c7 \
|
||||
da 41 59 7c 51 57 48 8d 77 24 e0 3f b8 d8 4a 37 \
|
||||
6a 43 b8 f4 15 18 a1 1c c3 87 b6 69 b2 ee 65 86
|
||||
Test: Encrypt
|
||||
Comment: Section 7, Test 2
|
||||
Key: 0000000000000000000000000000000000000000000000000000000000000001
|
||||
IV: 0000000000000000
|
||||
Plaintext:
|
||||
Ciphertext: 4540f05a9f1fb296d7736e7b208e3c96eb4fe1834688d2604f450952ed432d41bbe2a0b6ea7566d2a5d1e7e20d42af2c53d792b1c43fea817e9ad275
|
||||
#
|
||||
Comment: Section A.2, ChaCha20 Encryption, Test 2
|
||||
Key: 0000000000000000 0000000000000000 0000000000000000 0000000000000001
|
||||
IV: 00 00 00 00 00 00 00 00 00 00 00 02
|
||||
Plaintext: 41 6e 79 20 73 75 62 6d 69 73 73 69 6f 6e 20 74 \
|
||||
6f 20 74 68 65 20 49 45 54 46 20 69 6e 74 65 6e \
|
||||
64 65 64 20 62 79 20 74 68 65 20 43 6f 6e 74 72 \
|
||||
69 62 75 74 6f 72 20 66 6f 72 20 70 75 62 6c 69 \
|
||||
63 61 74 69 6f 6e 20 61 73 20 61 6c 6c 20 6f 72 \
|
||||
20 70 61 72 74 20 6f 66 20 61 6e 20 49 45 54 46 \
|
||||
20 49 6e 74 65 72 6e 65 74 2d 44 72 61 66 74 20 \
|
||||
6f 72 20 52 46 43 20 61 6e 64 20 61 6e 79 20 73 \
|
||||
74 61 74 65 6d 65 6e 74 20 6d 61 64 65 20 77 69 \
|
||||
74 68 69 6e 20 74 68 65 20 63 6f 6e 74 65 78 74 \
|
||||
20 6f 66 20 61 6e 20 49 45 54 46 20 61 63 74 69 \
|
||||
76 69 74 79 20 69 73 20 63 6f 6e 73 69 64 65 72 \
|
||||
65 64 20 61 6e 20 22 49 45 54 46 20 43 6f 6e 74 \
|
||||
72 69 62 75 74 69 6f 6e 22 2e 20 53 75 63 68 20 \
|
||||
73 74 61 74 65 6d 65 6e 74 73 20 69 6e 63 6c 75 \
|
||||
64 65 20 6f 72 61 6c 20 73 74 61 74 65 6d 65 6e \
|
||||
74 73 20 69 6e 20 49 45 54 46 20 73 65 73 73 69 \
|
||||
6f 6e 73 2c 20 61 73 20 77 65 6c 6c 20 61 73 20 \
|
||||
77 72 69 74 74 65 6e 20 61 6e 64 20 65 6c 65 63 \
|
||||
74 72 6f 6e 69 63 20 63 6f 6d 6d 75 6e 69 63 61 \
|
||||
74 69 6f 6e 73 20 6d 61 64 65 20 61 74 20 61 6e \
|
||||
79 20 74 69 6d 65 20 6f 72 20 70 6c 61 63 65 2c \
|
||||
20 77 68 69 63 68 20 61 72 65 20 61 64 64 72 65 \
|
||||
73 73 65 64 20 74 6f
|
||||
Ciphertext: a3 fb f0 7d f3 fa 2f de 4f 37 6c a2 3e 82 73 70 \
|
||||
41 60 5d 9f 4f 4f 57 bd 8c ff 2c 1d 4b 79 55 ec \
|
||||
2a 97 94 8b d3 72 29 15 c8 f3 d3 37 f7 d3 70 05 \
|
||||
0e 9e 96 d6 47 b7 c3 9f 56 e0 31 ca 5e b6 25 0d \
|
||||
40 42 e0 27 85 ec ec fa 4b 4b b5 e8 ea d0 44 0e \
|
||||
20 b6 e8 db 09 d8 81 a7 c6 13 2f 42 0e 52 79 50 \
|
||||
42 bd fa 77 73 d8 a9 05 14 47 b3 29 1c e1 41 1c \
|
||||
68 04 65 55 2a a6 c4 05 b7 76 4d 5e 87 be a8 5a \
|
||||
d0 0f 84 49 ed 8f 72 d0 d6 62 ab 05 26 91 ca 66 \
|
||||
42 4b c8 6d 2d f8 0e a4 1f 43 ab f9 37 d3 25 9d \
|
||||
c4 b2 d0 df b4 8a 6c 91 39 dd d7 f7 69 66 e9 28 \
|
||||
e6 35 55 3b a7 6c 5c 87 9d 7b 35 d4 9e b2 e6 2b \
|
||||
08 71 cd ac 63 89 39 e2 5e 8a 1e 0e f9 d5 28 0f \
|
||||
a8 ca 32 8b 35 1c 3c 76 59 89 cb cf 3d aa 8b 6c \
|
||||
cc 3a af 9f 39 79 c9 2b 37 20 fc 88 dc 95 ed 84 \
|
||||
a1 be 05 9c 64 99 b9 fd a2 36 e7 e8 18 b0 4b 0b \
|
||||
c3 9c 1e 87 6b 19 3b fe 55 69 75 3f 88 12 8c c0 \
|
||||
8a aa 9b 63 d1 a1 6f 80 ef 25 54 d7 18 9c 41 1f \
|
||||
58 69 ca 52 c5 b8 3f a3 6f f2 16 b9 c1 d3 00 62 \
|
||||
be bc fd 2d c5 bc e0 91 19 34 fd a7 9a 86 f6 e6 \
|
||||
98 ce d7 59 c3 ff 9b 64 77 33 8f 3d a4 f9 cd 85 \
|
||||
14 ea 99 82 cc af b3 41 b2 38 4d d9 02 f3 d1 ab \
|
||||
7a c6 1d d2 9c 6f 21 ba 5b 86 2f 37 30 e3 7c fd \
|
||||
c4 fd 80 6c 22 f2 21
|
||||
InitialBlock: 1
|
||||
Test: Encrypt
|
||||
Comment: Section 7, Test 3
|
||||
Key: 0000000000000000000000000000000000000000000000000000000000000000
|
||||
IV: 0000000000000001
|
||||
Plaintext:
|
||||
Ciphertext: de9cba7bf3d69ef5e786dc63973f653a0b49e015adbff7134fcb7df137821031e85a050278a7084527214f73efc7fa5b5277062eb7a0433e445f41e3
|
||||
Test: Encrypt
|
||||
Comment: Section 7, Test 4
|
||||
Key: 0000000000000000000000000000000000000000000000000000000000000000
|
||||
IV: 0100000000000000
|
||||
Plaintext:
|
||||
Ciphertext: ef3fdfd6c61578fbf5cf35bd3dd33b8009631634d21e42ac33960bd138e50d32111e4caf237ee53ca8ad6426194a88545ddc497a0b466e7d6bbdb004
|
||||
Test: Encrypt
|
||||
Comment: Section 7, Test 5
|
||||
Key: 000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f
|
||||
IV: 0001020304050607
|
||||
Plaintext:
|
||||
Ciphertext: f798a189f195e66982105ffb640bb7757f579da31602fc93ec01ac56f85ac3c134a4547b733b46413042c9440049176905d3be59ea1c53f1 \
|
||||
5916155c2be8241a38008b9a26bc35941e2444177c8ade6689de95264986d95889fb60e84629c9bd9a5acb1cc118be563eb9b3a4a472f82e \
|
||||
09a7e778492b562ef7130e88dfe031c79db9d4f7c7a899151b9a475032b63fc385245fe054e3dd5a97a5f576fe064025d3ce042c566ab2c5 \
|
||||
07b138db853e3d6959660996546cc9c4a6eafdc777c040d70eaf46f76dad3979e5c5360c3317166a1c894c94a371876a94df7628fe4eaaf2 \
|
||||
ccb27d5aaae0ad7ad0f9d4b6ad3b54098746d4524d38407a6deb
|
||||
#
|
||||
Comment: Section A.2, ChaCha20 Encryption, Test 3
|
||||
Key: 1c 92 40 a5 eb 55 d3 8a f3 33 88 86 04 f6 b5 f0 \
|
||||
47 39 17 c1 40 2b 80 09 9d ca 5c bc 20 70 75 c0
|
||||
IV: 00 00 00 00 00 00 00 00 00 00 00 02
|
||||
Plaintext: 27 54 77 61 73 20 62 72 69 6c 6c 69 67 2c 20 61 \
|
||||
6e 64 20 74 68 65 20 73 6c 69 74 68 79 20 74 6f \
|
||||
76 65 73 0a 44 69 64 20 67 79 72 65 20 61 6e 64 \
|
||||
20 67 69 6d 62 6c 65 20 69 6e 20 74 68 65 20 77 \
|
||||
61 62 65 3a 0a 41 6c 6c 20 6d 69 6d 73 79 20 77 \
|
||||
65 72 65 20 74 68 65 20 62 6f 72 6f 67 6f 76 65 \
|
||||
73 2c 0a 41 6e 64 20 74 68 65 20 6d 6f 6d 65 20 \
|
||||
72 61 74 68 73 20 6f 75 74 67 72 61 62 65 2e
|
||||
Ciphertext: 62 e6 34 7f 95 ed 87 a4 5f fa e7 42 6f 27 a1 df \
|
||||
5f b6 91 10 04 4c 0d 73 11 8e ff a9 5b 01 e5 cf \
|
||||
16 6d 3d f2 d7 21 ca f9 b2 1e 5f b1 4c 61 68 71 \
|
||||
fd 84 c5 4f 9d 65 b2 83 19 6c 7f e4 f6 05 53 eb \
|
||||
f3 9c 64 02 c4 22 34 e3 2a 35 6b 3e 76 43 12 a6 \
|
||||
1a 55 32 05 57 16 ea d6 96 25 68 f8 7d 3f 3f 77 \
|
||||
04 c6 a8 d1 bc d1 bf 4d 50 d6 15 4b 6d a7 31 b1 \
|
||||
87 b5 8d fd 72 8a fa 36 75 7a 79 7a c1 88 d1
|
||||
InitialBlock: 42
|
||||
Test: Encrypt
|
||||
|
@ -141,6 +141,7 @@ void Benchmark2(double t, double hertz)
|
||||
BenchMarkByName<SymmetricCipher>("ChaCha", 0, "ChaCha20");
|
||||
BenchMarkByName<SymmetricCipher>("ChaCha", 0, "ChaCha12", MakeParameters(Name::Rounds(), 12));
|
||||
BenchMarkByName<SymmetricCipher>("ChaCha", 0, "ChaCha8", MakeParameters(Name::Rounds(), 8));
|
||||
BenchMarkByName<SymmetricCipher>("ChaChaTLS");
|
||||
BenchMarkByName<SymmetricCipher>("Sosemanuk");
|
||||
BenchMarkByName<SymmetricCipher>("Rabbit");
|
||||
BenchMarkByName<SymmetricCipher>("RabbitWithIV");
|
||||
|
283
chacha.cpp
283
chacha.cpp
@ -63,9 +63,12 @@ extern void ChaCha_OperateKeystream_ALTIVEC(const word32 *state, const byte* inp
|
||||
void ChaCha_TestInstantiations()
|
||||
{
|
||||
ChaCha::Encryption x;
|
||||
ChaChaTLS::Encryption y;
|
||||
}
|
||||
#endif
|
||||
|
||||
////////////////////////////// Bernstein ChaCha //////////////////////////////
|
||||
|
||||
std::string ChaCha_Policy::AlgorithmName() const
|
||||
{
|
||||
return std::string("ChaCha")+IntToString(m_rounds);
|
||||
@ -102,8 +105,7 @@ std::string ChaCha_Policy::AlgorithmProvider() const
|
||||
|
||||
void ChaCha_Policy::CipherSetKey(const NameValuePairs ¶ms, const byte *key, size_t length)
|
||||
{
|
||||
CRYPTOPP_UNUSED(params);
|
||||
CRYPTOPP_ASSERT(length == 16 || length == 32);
|
||||
CRYPTOPP_ASSERT(key); CRYPTOPP_ASSERT(length == 16 || length == 32);
|
||||
|
||||
m_rounds = params.GetIntValueWithDefault(Name::Rounds(), 20);
|
||||
if (!(m_rounds == 8 || m_rounds == 12 || m_rounds == 20))
|
||||
@ -326,4 +328,281 @@ void ChaCha_Policy::OperateKeystream(KeystreamOperation operation,
|
||||
} while (iterationCount--);
|
||||
}
|
||||
|
||||
////////////////////////////// IETF ChaChaTLS //////////////////////////////
|
||||
|
||||
std::string ChaChaTLS_Policy::AlgorithmName() const
|
||||
{
|
||||
return std::string("ChaChaTLS")+IntToString(static_cast<unsigned int>(m_rounds));
|
||||
}
|
||||
|
||||
std::string ChaChaTLS_Policy::AlgorithmProvider() const
|
||||
{
|
||||
#if (CRYPTOPP_AVX2_AVAILABLE)
|
||||
if (HasAVX2())
|
||||
return "AVX2";
|
||||
else
|
||||
#endif
|
||||
#if (CRYPTOPP_SSE2_INTRIN_AVAILABLE)
|
||||
if (HasSSE2())
|
||||
return "SSE2";
|
||||
else
|
||||
#endif
|
||||
#if (CRYPTOPP_ARM_NEON_AVAILABLE)
|
||||
if (HasNEON())
|
||||
return "NEON";
|
||||
else
|
||||
#endif
|
||||
#if (CRYPTOPP_POWER7_AVAILABLE)
|
||||
if (HasPower7())
|
||||
return "Power7";
|
||||
else
|
||||
#elif (CRYPTOPP_ALTIVEC_AVAILABLE)
|
||||
if (HasAltivec())
|
||||
return "Altivec";
|
||||
else
|
||||
#endif
|
||||
return "C++";
|
||||
}
|
||||
|
||||
void ChaChaTLS_Policy::CipherSetKey(const NameValuePairs ¶ms, const byte *key, size_t length)
|
||||
{
|
||||
CRYPTOPP_ASSERT(key); CRYPTOPP_ASSERT(length == 32);
|
||||
|
||||
// ChaChaTLS is always 20 rounds. Fetch Rounds() to avoid a spurious failure.
|
||||
int rounds = params.GetIntValueWithDefault(Name::Rounds(), m_rounds);
|
||||
if (rounds != 20)
|
||||
throw InvalidRounds(ChaChaTLS::StaticAlgorithmName(), rounds);
|
||||
|
||||
// RFC 7539 test vectors use an initial block counter. However, some of them
|
||||
// don't start at 0. If Resynchronize() is called we set to 0. Hence, stash
|
||||
// the initial block counter in m_state[16]. Then use it in Resynchronize().
|
||||
int block;
|
||||
if (params.GetValue("InitialBlock", block))
|
||||
m_state[16] = static_cast<word32>(block);
|
||||
else
|
||||
m_state[16] = 0;
|
||||
|
||||
// State words are defined in RFC 7539, Section 2.3.
|
||||
m_state[0] = 0x61707865;
|
||||
m_state[1] = 0x3320646e;
|
||||
m_state[2] = 0x79622d32;
|
||||
m_state[3] = 0x6b206574;
|
||||
|
||||
// State words are defined in RFC 7539, Section 2.3. Key is 32-bytes.
|
||||
GetBlock<word32, LittleEndian> get(key);
|
||||
get(m_state[4])(m_state[5])(m_state[6])(m_state[7])(m_state[8])(m_state[9])(m_state[10])(m_state[11]);
|
||||
}
|
||||
|
||||
void ChaChaTLS_Policy::CipherResynchronize(byte *keystreamBuffer, const byte *IV, size_t length)
|
||||
{
|
||||
CRYPTOPP_UNUSED(keystreamBuffer), CRYPTOPP_UNUSED(length);
|
||||
CRYPTOPP_ASSERT(length==12);
|
||||
|
||||
// State words are defined in RFC 7539, Section 2.3
|
||||
GetBlock<word32, LittleEndian> get(IV);
|
||||
m_state[12] = m_state[16];
|
||||
get(m_state[13])(m_state[14])(m_state[15]);
|
||||
}
|
||||
|
||||
void ChaChaTLS_Policy::SeekToIteration(lword iterationCount)
|
||||
{
|
||||
// State words are defined in RFC 7539, Section 2.3
|
||||
// Should we throw here???
|
||||
CRYPTOPP_ASSERT(iterationCount <= std::numeric_limits<word32>::max());
|
||||
m_state[12] = (word32)iterationCount; // low word
|
||||
}
|
||||
|
||||
unsigned int ChaChaTLS_Policy::GetAlignment() const
|
||||
{
|
||||
#if (CRYPTOPP_AVX2_AVAILABLE)
|
||||
if (HasAVX2())
|
||||
return 16;
|
||||
else
|
||||
#endif
|
||||
#if (CRYPTOPP_SSE2_INTRIN_AVAILABLE)
|
||||
if (HasSSE2())
|
||||
return 16;
|
||||
else
|
||||
#endif
|
||||
#if (CRYPTOPP_ALTIVEC_AVAILABLE)
|
||||
if (HasAltivec())
|
||||
return 16;
|
||||
else
|
||||
#endif
|
||||
return GetAlignmentOf<word32>();
|
||||
}
|
||||
|
||||
unsigned int ChaChaTLS_Policy::GetOptimalBlockSize() const
|
||||
{
|
||||
// Disable SIMD until we can generate large block test vectors
|
||||
// https://mailarchive.ietf.org/arch/msg/saag/S0_YjVkzEx2s2bHd8KIzjK1CwZ4
|
||||
#if 0
|
||||
#if (CRYPTOPP_AVX2_AVAILABLE)
|
||||
if (HasAVX2())
|
||||
return 8 * BYTES_PER_ITERATION;
|
||||
else
|
||||
#endif
|
||||
#if (CRYPTOPP_SSE2_INTRIN_AVAILABLE)
|
||||
if (HasSSE2())
|
||||
return 4*BYTES_PER_ITERATION;
|
||||
else
|
||||
#endif
|
||||
#if (CRYPTOPP_ARM_NEON_AVAILABLE)
|
||||
if (HasNEON())
|
||||
return 4*BYTES_PER_ITERATION;
|
||||
else
|
||||
#endif
|
||||
#if (CRYPTOPP_ALTIVEC_AVAILABLE)
|
||||
if (HasAltivec())
|
||||
return 4*BYTES_PER_ITERATION;
|
||||
else
|
||||
#endif
|
||||
#endif
|
||||
return BYTES_PER_ITERATION;
|
||||
}
|
||||
|
||||
// OperateKeystream always produces a key stream. The key stream is written
|
||||
// to output. Optionally a message may be supplied to xor with the key stream.
|
||||
// The message is input, and output = output ^ input.
|
||||
void ChaChaTLS_Policy::OperateKeystream(KeystreamOperation operation,
|
||||
byte *output, const byte *input, size_t iterationCount)
|
||||
{
|
||||
// Disable SIMD until we can generate large block test vectors
|
||||
// https://mailarchive.ietf.org/arch/msg/saag/S0_YjVkzEx2s2bHd8KIzjK1CwZ4
|
||||
#if 0
|
||||
#if (CRYPTOPP_AVX2_AVAILABLE)
|
||||
if (HasAVX2())
|
||||
{
|
||||
while (iterationCount >= 8)
|
||||
{
|
||||
const bool xorInput = (operation & INPUT_NULL) != INPUT_NULL;
|
||||
ChaCha_OperateKeystream_AVX2(m_state, xorInput ? input : NULLPTR, output, m_rounds);
|
||||
|
||||
// MultiBlockSafe avoids overflow on the counter words
|
||||
m_state[12] += 8;
|
||||
//if (m_state[12] < 8)
|
||||
// m_state[13]++;
|
||||
|
||||
input += (!!xorInput) * 8 * BYTES_PER_ITERATION;
|
||||
output += 8 * BYTES_PER_ITERATION;
|
||||
iterationCount -= 8;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
#if (CRYPTOPP_SSE2_INTRIN_AVAILABLE)
|
||||
if (HasSSE2())
|
||||
{
|
||||
while (iterationCount >= 4)
|
||||
{
|
||||
const bool xorInput = (operation & INPUT_NULL) != INPUT_NULL;
|
||||
ChaCha_OperateKeystream_SSE2(m_state, xorInput ? input : NULLPTR, output, m_rounds);
|
||||
|
||||
// MultiBlockSafe avoids overflow on the counter words
|
||||
m_state[12] += 4;
|
||||
//if (m_state[12] < 4)
|
||||
// m_state[13]++;
|
||||
|
||||
input += (!!xorInput)*4*BYTES_PER_ITERATION;
|
||||
output += 4*BYTES_PER_ITERATION;
|
||||
iterationCount -= 4;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
#if (CRYPTOPP_ARM_NEON_AVAILABLE)
|
||||
if (HasNEON())
|
||||
{
|
||||
while (iterationCount >= 4)
|
||||
{
|
||||
const bool xorInput = (operation & INPUT_NULL) != INPUT_NULL;
|
||||
ChaCha_OperateKeystream_NEON(m_state, xorInput ? input : NULLPTR, output, m_rounds);
|
||||
|
||||
// MultiBlockSafe avoids overflow on the counter words
|
||||
m_state[12] += 4;
|
||||
//if (m_state[12] < 4)
|
||||
// m_state[13]++;
|
||||
|
||||
input += (!!xorInput)*4*BYTES_PER_ITERATION;
|
||||
output += 4*BYTES_PER_ITERATION;
|
||||
iterationCount -= 4;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
#if (CRYPTOPP_POWER7_AVAILABLE)
|
||||
if (HasPower7())
|
||||
{
|
||||
while (iterationCount >= 4)
|
||||
{
|
||||
const bool xorInput = (operation & INPUT_NULL) != INPUT_NULL;
|
||||
ChaCha_OperateKeystream_POWER7(m_state, xorInput ? input : NULLPTR, output, m_rounds);
|
||||
|
||||
// MultiBlockSafe avoids overflow on the counter words
|
||||
m_state[12] += 4;
|
||||
//if (m_state[12] < 4)
|
||||
// m_state[13]++;
|
||||
|
||||
input += (!!xorInput)*4*BYTES_PER_ITERATION;
|
||||
output += 4*BYTES_PER_ITERATION;
|
||||
iterationCount -= 4;
|
||||
}
|
||||
}
|
||||
#elif (CRYPTOPP_ALTIVEC_AVAILABLE)
|
||||
if (HasAltivec())
|
||||
{
|
||||
while (iterationCount >= 4)
|
||||
{
|
||||
const bool xorInput = (operation & INPUT_NULL) != INPUT_NULL;
|
||||
ChaCha_OperateKeystream_ALTIVEC(m_state, xorInput ? input : NULLPTR, output, m_rounds);
|
||||
|
||||
// MultiBlockSafe avoids overflow on the counter words
|
||||
m_state[12] += 4;
|
||||
//if (m_state[12] < 4)
|
||||
// m_state[13]++;
|
||||
|
||||
input += (!!xorInput)*4*BYTES_PER_ITERATION;
|
||||
output += 4*BYTES_PER_ITERATION;
|
||||
iterationCount -= 4;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
#endif
|
||||
|
||||
while (iterationCount--)
|
||||
{
|
||||
word32 x0, x1, x2, x3, x4, x5, x6, x7, x8, x9, x10, x11, x12, x13, x14, x15;
|
||||
|
||||
x0 = m_state[0]; x1 = m_state[1]; x2 = m_state[2]; x3 = m_state[3];
|
||||
x4 = m_state[4]; x5 = m_state[5]; x6 = m_state[6]; x7 = m_state[7];
|
||||
x8 = m_state[8]; x9 = m_state[9]; x10 = m_state[10]; x11 = m_state[11];
|
||||
x12 = m_state[12]; x13 = m_state[13]; x14 = m_state[14]; x15 = m_state[15];
|
||||
|
||||
for (int i = static_cast<int>(m_rounds); i > 0; i -= 2)
|
||||
{
|
||||
CHACHA_QUARTER_ROUND(x0, x4, x8, x12);
|
||||
CHACHA_QUARTER_ROUND(x1, x5, x9, x13);
|
||||
CHACHA_QUARTER_ROUND(x2, x6, x10, x14);
|
||||
CHACHA_QUARTER_ROUND(x3, x7, x11, x15);
|
||||
|
||||
CHACHA_QUARTER_ROUND(x0, x5, x10, x15);
|
||||
CHACHA_QUARTER_ROUND(x1, x6, x11, x12);
|
||||
CHACHA_QUARTER_ROUND(x2, x7, x8, x13);
|
||||
CHACHA_QUARTER_ROUND(x3, x4, x9, x14);
|
||||
}
|
||||
|
||||
CRYPTOPP_KEYSTREAM_OUTPUT_SWITCH(CHACHA_OUTPUT, BYTES_PER_ITERATION);
|
||||
|
||||
if (++m_state[12] == 0)
|
||||
{
|
||||
// m_state[13]++;
|
||||
|
||||
// RFC 7539 does not say what to do here. ChaCha-TLS uses state[13]
|
||||
// for part of the nonce. We can't carry into it. Shit or go blind...
|
||||
// https://mailarchive.ietf.org/arch/msg/saag/S0_YjVkzEx2s2bHd8KIzjK1CwZ4
|
||||
CRYPTOPP_ASSERT(0);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
NAMESPACE_END
|
||||
|
84
chacha.h
84
chacha.h
@ -3,13 +3,24 @@
|
||||
// and Bernstein's reference ChaCha family implementation at
|
||||
// http://cr.yp.to/chacha.html.
|
||||
|
||||
// Crypto++ added Bernstein's ChaCha classses at version 5.6.4 of the library.
|
||||
// The IETF uses a slightly different implementation, and the classes were
|
||||
// added at Crypto++ version 8.1. We wanted to maintain ABI compatibility at
|
||||
// the 8.1 release so the original ChaCha classes were not disturbed. Instead
|
||||
// new classes were added for IETF ChaCha. The back-end implementation shares
|
||||
// code as expected, however.
|
||||
|
||||
/// \file chacha.h
|
||||
/// \brief Classes for ChaCha8, ChaCha12 and ChaCha20 stream ciphers
|
||||
/// \details Crypto++ provides Bernstein and ECRYPT's ChaCha from <a href="http://cr.yp.to/chacha/chacha-20080128.pdf">ChaCha,
|
||||
/// a variant of Salsa20</a> (2008.01.28). Bernstein's implementation is _slightly_ different from the TLS working group's
|
||||
/// implementation for cipher suites <tt>TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256</tt>,
|
||||
/// <tt>TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305_SHA256</tt>, and <tt>TLS_DHE_RSA_WITH_CHACHA20_POLY1305_SHA256</tt>.
|
||||
/// \since Crypto++ 5.6.4
|
||||
/// a variant of Salsa20</a> (2008.01.28). Crypto++ also provides the IETF
|
||||
/// implementation of ChaCha using the ChaChaTLS name. Bernstein's
|
||||
/// implementation is _slightly_ different from the TLS working group's
|
||||
/// implementation for cipher suites
|
||||
/// <tt>TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256</tt>,
|
||||
/// <tt>TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305_SHA256</tt>,
|
||||
/// and <tt>TLS_DHE_RSA_WITH_CHACHA20_POLY1305_SHA256</tt>.
|
||||
/// \since ChaCha since Crypto++ 5.6.4, ChaChaTLS since Crypto++ 8.1
|
||||
|
||||
#ifndef CRYPTOPP_CHACHA_H
|
||||
#define CRYPTOPP_CHACHA_H
|
||||
@ -19,6 +30,8 @@
|
||||
|
||||
NAMESPACE_BEGIN(CryptoPP)
|
||||
|
||||
////////////////////////////// Bernstein ChaCha //////////////////////////////
|
||||
|
||||
/// \brief ChaCha stream cipher information
|
||||
/// \since Crypto++ 5.6.4
|
||||
struct ChaCha_Info : public VariableKeyLength<32, 16, 32, 16, SimpleKeyingInterface::UNIQUE_IV, 8>
|
||||
@ -40,8 +53,8 @@ struct ChaCha_Info : public VariableKeyLength<32, 16, 32, 16, SimpleKeyingInterf
|
||||
class CRYPTOPP_NO_VTABLE ChaCha_Policy : public AdditiveCipherConcretePolicy<word32, 16>
|
||||
{
|
||||
public:
|
||||
~ChaCha_Policy() {}
|
||||
ChaCha_Policy() : m_rounds(0) {}
|
||||
virtual ~ChaCha_Policy() {}
|
||||
ChaCha_Policy() : m_rounds(0) {}
|
||||
|
||||
protected:
|
||||
void CipherSetKey(const NameValuePairs ¶ms, const byte *key, size_t length);
|
||||
@ -80,6 +93,65 @@ struct ChaCha : public ChaCha_Info, public SymmetricCipherDocumentation
|
||||
typedef Encryption Decryption;
|
||||
};
|
||||
|
||||
////////////////////////////// IETF ChaChaTLS //////////////////////////////
|
||||
|
||||
/// \brief ChaCha-TLS stream cipher information
|
||||
/// \since Crypto++ 8.1
|
||||
struct ChaChaTLS_Info : public FixedKeyLength<32, SimpleKeyingInterface::UNIQUE_IV, 12>, FixedRounds<20>
|
||||
{
|
||||
/// \brief The algorithm name
|
||||
/// \returns the algorithm name
|
||||
/// \details StaticAlgorithmName returns the algorithm's name as a static
|
||||
/// member function.
|
||||
/// \details This is the IETF's variant of Bernstein's ChaCha from RFC 7539.
|
||||
/// IETF ChaCha is called ChaChaTLS in the Crypto++ library. It is
|
||||
/// _slightly_ different from Bernstein's implementation.
|
||||
static const char* StaticAlgorithmName() {
|
||||
return "ChaChaTLS";
|
||||
}
|
||||
};
|
||||
|
||||
/// \brief ChaCha-TLS stream cipher implementation
|
||||
/// \since Crypto++ 8.1
|
||||
class CRYPTOPP_NO_VTABLE ChaChaTLS_Policy : public AdditiveCipherConcretePolicy<word32, 16>
|
||||
{
|
||||
public:
|
||||
virtual ~ChaChaTLS_Policy() {}
|
||||
ChaChaTLS_Policy() {}
|
||||
|
||||
protected:
|
||||
void CipherSetKey(const NameValuePairs ¶ms, 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 CipherIsRandomAccess() const {return true;}
|
||||
void SeekToIteration(lword iterationCount);
|
||||
unsigned int GetAlignment() const;
|
||||
unsigned int GetOptimalBlockSize() const;
|
||||
|
||||
std::string AlgorithmName() const;
|
||||
std::string AlgorithmProvider() const;
|
||||
|
||||
FixedSizeAlignedSecBlock<word32, 16+1> m_state;
|
||||
CRYPTOPP_CONSTANT(m_rounds = ChaChaTLS_Info::ROUNDS)
|
||||
};
|
||||
|
||||
/// \brief ChaCha-TLS stream cipher
|
||||
/// \details This is the IETF's variant of Bernstein's ChaCha from RFC 7539.
|
||||
/// IETF ChaCha is called ChaChaTLS in the Crypto++ library. It is
|
||||
/// _slightly_ different from the Bernstein's implementation. ChaCha-TLS
|
||||
/// can be used for cipher suites
|
||||
/// <tt>TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256</tt>,
|
||||
/// <tt>TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305_SHA256</tt>, and
|
||||
/// <tt>TLS_DHE_RSA_WITH_CHACHA20_POLY1305_SHA256</tt>.
|
||||
/// \sa <a href="https://tools.ietf.org/html/rfc7539">ChaCha20 and Poly1305 for
|
||||
/// IETF Protocols</a>.
|
||||
/// \since Crypto++ 8.1
|
||||
struct ChaChaTLS : public ChaChaTLS_Info, public SymmetricCipherDocumentation
|
||||
{
|
||||
typedef SymmetricCipherFinal<ConcretePolicyHolder<ChaChaTLS_Policy, AdditiveCipherTemplate<> >, ChaChaTLS_Info > Encryption;
|
||||
typedef Encryption Decryption;
|
||||
};
|
||||
|
||||
NAMESPACE_END
|
||||
|
||||
#endif // CRYPTOPP_CHACHA_H
|
||||
|
@ -527,7 +527,7 @@ void TestSymmetricCipher(TestData &v, const NameValuePairs &overrideParameters)
|
||||
// been processed. Also note we only unlatch from testDataPairs. If
|
||||
// overrideParameters are specified, the caller is responsible for
|
||||
// managing the parameter.
|
||||
v.erase("Tweak"); v.erase("BlockSize"); v.erase("BlockPaddingScheme");
|
||||
v.erase("Tweak"); v.erase("InitialBlock"); v.erase("BlockSize"); v.erase("BlockPaddingScheme");
|
||||
|
||||
std::string encrypted, xorDigest, ciphertext, ciphertextXorDigest;
|
||||
if (test == "EncryptionMCT" || test == "DecryptionMCT")
|
||||
|
@ -93,6 +93,7 @@ void RegisterFactories3()
|
||||
RegisterSymmetricCipherDefaultFactories<Salsa20>();
|
||||
RegisterSymmetricCipherDefaultFactories<XSalsa20>();
|
||||
RegisterSymmetricCipherDefaultFactories<ChaCha>();
|
||||
RegisterSymmetricCipherDefaultFactories<ChaChaTLS>();
|
||||
RegisterSymmetricCipherDefaultFactories<Sosemanuk>();
|
||||
RegisterSymmetricCipherDefaultFactories<Rabbit>();
|
||||
RegisterSymmetricCipherDefaultFactories<RabbitWithIV>();
|
||||
|
9
test.cpp
9
test.cpp
@ -983,10 +983,11 @@ bool Validate(int alg, bool thorough, const char *seedInput)
|
||||
case 68: result = ValidateTTMAC(); break;
|
||||
case 70: result = ValidateSalsa(); break;
|
||||
case 71: result = ValidateChaCha(); break;
|
||||
case 72: result = ValidateSosemanuk(); break;
|
||||
case 73: result = ValidateRabbit(); break;
|
||||
case 74: result = ValidateHC128(); break;
|
||||
case 75: result = ValidateHC256(); break;
|
||||
case 72: result = ValidateChaChaTLS(); break;
|
||||
case 73: result = ValidateSosemanuk(); break;
|
||||
case 74: result = ValidateRabbit(); break;
|
||||
case 75: result = ValidateHC128(); break;
|
||||
case 76: result = ValidateHC256(); break;
|
||||
case 80: result = ValidateVMAC(); break;
|
||||
case 81: result = ValidateCCM(); break;
|
||||
case 82: result = ValidateGCM(); break;
|
||||
|
@ -156,6 +156,7 @@ bool ValidateAll(bool thorough)
|
||||
pass=ValidateCamellia() && pass;
|
||||
pass=ValidateSalsa() && pass;
|
||||
pass=ValidateChaCha() && pass;
|
||||
pass=ValidateChaChaTLS() && pass;
|
||||
pass=ValidateSosemanuk() && pass;
|
||||
pass=ValidateRabbit() && pass;
|
||||
pass=ValidateHC128() && pass;
|
||||
|
@ -1743,6 +1743,13 @@ bool ValidateChaCha()
|
||||
return RunTestDataFile("TestVectors/chacha.txt");
|
||||
}
|
||||
|
||||
bool ValidateChaChaTLS()
|
||||
{
|
||||
std::cout << "\nChaCha-TLS validation suite running...\n";
|
||||
|
||||
return RunTestDataFile("TestVectors/chacha_tls.txt");
|
||||
}
|
||||
|
||||
bool ValidateSosemanuk()
|
||||
{
|
||||
std::cout << "\nSosemanuk validation suite running...\n";
|
||||
|
@ -106,6 +106,7 @@ bool ValidateHC256();
|
||||
bool ValidateRabbit();
|
||||
bool ValidateSalsa();
|
||||
bool ValidateChaCha();
|
||||
bool ValidateChaChaTLS();
|
||||
bool ValidateSosemanuk();
|
||||
|
||||
bool ValidateVMAC();
|
||||
|
@ -598,7 +598,7 @@ protected:
|
||||
/// LSB is at element 0 and the MSB is at element 31.
|
||||
/// If you call GetPublicElement() then the little-endian byte
|
||||
/// array is converted to a big-endian Integer() so it can be
|
||||
/// returned the way a caller expects. And calling
|
||||
/// returned the way a caller expects. And calling
|
||||
/// SetPublicElement() perfoms a similar internal conversion.
|
||||
/// \since Crypto++ 8.0
|
||||
struct ed25519PublicKey : public X509PublicKey
|
||||
|
Loading…
x
Reference in New Issue
Block a user