diff --git a/TestVectors/chacha_tls.txt b/TestVectors/chacha_tls.txt index 6e44e39d..2a9f0912 100644 --- a/TestVectors/chacha_tls.txt +++ b/TestVectors/chacha_tls.txt @@ -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 diff --git a/bench2.cpp b/bench2.cpp index 38da6224..9370df34 100644 --- a/bench2.cpp +++ b/bench2.cpp @@ -141,6 +141,7 @@ void Benchmark2(double t, double hertz) BenchMarkByName("ChaCha", 0, "ChaCha20"); BenchMarkByName("ChaCha", 0, "ChaCha12", MakeParameters(Name::Rounds(), 12)); BenchMarkByName("ChaCha", 0, "ChaCha8", MakeParameters(Name::Rounds(), 8)); + BenchMarkByName("ChaChaTLS"); BenchMarkByName("Sosemanuk"); BenchMarkByName("Rabbit"); BenchMarkByName("RabbitWithIV"); diff --git a/chacha.cpp b/chacha.cpp index 2bde58b1..2df162e0 100644 --- a/chacha.cpp +++ b/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(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(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 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 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::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(); +} + +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(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 diff --git a/chacha.h b/chacha.h index 39246c0f..d59dea0f 100644 --- a/chacha.h +++ b/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 ChaCha, -/// a variant of Salsa20 (2008.01.28). Bernstein's implementation is _slightly_ different from the TLS working group's -/// implementation for cipher suites TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256, -/// TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305_SHA256, and TLS_DHE_RSA_WITH_CHACHA20_POLY1305_SHA256. -/// \since Crypto++ 5.6.4 +/// a variant of Salsa20 (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 +/// TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256, +/// TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305_SHA256, +/// and TLS_DHE_RSA_WITH_CHACHA20_POLY1305_SHA256. +/// \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 { 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 +{ +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 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 +/// TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256, +/// TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305_SHA256, and +/// TLS_DHE_RSA_WITH_CHACHA20_POLY1305_SHA256. +/// \sa ChaCha20 and Poly1305 for +/// IETF Protocols. +/// \since Crypto++ 8.1 +struct ChaChaTLS : public ChaChaTLS_Info, public SymmetricCipherDocumentation +{ + typedef SymmetricCipherFinal >, ChaChaTLS_Info > Encryption; + typedef Encryption Decryption; +}; + NAMESPACE_END #endif // CRYPTOPP_CHACHA_H diff --git a/datatest.cpp b/datatest.cpp index 6a15ecb2..d948421a 100644 --- a/datatest.cpp +++ b/datatest.cpp @@ -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") diff --git a/regtest2.cpp b/regtest2.cpp index e68db6cc..57984c27 100644 --- a/regtest2.cpp +++ b/regtest2.cpp @@ -93,6 +93,7 @@ void RegisterFactories3() RegisterSymmetricCipherDefaultFactories(); RegisterSymmetricCipherDefaultFactories(); RegisterSymmetricCipherDefaultFactories(); + RegisterSymmetricCipherDefaultFactories(); RegisterSymmetricCipherDefaultFactories(); RegisterSymmetricCipherDefaultFactories(); RegisterSymmetricCipherDefaultFactories(); diff --git a/test.cpp b/test.cpp index 70f44526..8226b975 100644 --- a/test.cpp +++ b/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; diff --git a/validat3.cpp b/validat3.cpp index 9a2d454f..1dd9ac2e 100644 --- a/validat3.cpp +++ b/validat3.cpp @@ -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; diff --git a/validat4.cpp b/validat4.cpp index 96161a81..14409cc0 100644 --- a/validat4.cpp +++ b/validat4.cpp @@ -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"; diff --git a/validate.h b/validate.h index 3fa49d12..5337169e 100644 --- a/validate.h +++ b/validate.h @@ -106,6 +106,7 @@ bool ValidateHC256(); bool ValidateRabbit(); bool ValidateSalsa(); bool ValidateChaCha(); +bool ValidateChaChaTLS(); bool ValidateSosemanuk(); bool ValidateVMAC(); diff --git a/xed25519.h b/xed25519.h index e97c63f6..bb6ff228 100644 --- a/xed25519.h +++ b/xed25519.h @@ -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