diff --git a/chacha.cpp b/chacha.cpp index 9f27ff66..437aeff7 100644 --- a/chacha.cpp +++ b/chacha.cpp @@ -39,6 +39,7 @@ void ChaCha_TestInstantiations() { ChaCha::Encryption x; ChaChaTLS::Encryption y; + XChaCha20::Encryption z; } #endif @@ -424,19 +425,14 @@ void ChaChaTLS_Policy::CipherSetKey(const NameValuePairs ¶ms, const byte *ke // the function, so we have to use the heavier-weight SetKey to change it. word64 block; if (params.GetValue("InitialBlock", block)) - m_state[16] = static_cast(block); + m_state[CTR] = static_cast(block); else - m_state[16] = 0; - - // State words are defined in RFC 8439, Section 2.3. - m_state[0] = 0x61707865; - m_state[1] = 0x3320646e; - m_state[2] = 0x79622d32; - m_state[3] = 0x6b206574; + m_state[CTR] = 0; // State words are defined in RFC 8439, 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]); + get(m_state[KEY+0])(m_state[KEY+1])(m_state[KEY+2])(m_state[KEY+3]) + (m_state[KEY+4])(m_state[KEY+5])(m_state[KEY+6])(m_state[KEY+7]); } void ChaChaTLS_Policy::CipherResynchronize(byte *keystreamBuffer, const byte *IV, size_t length) @@ -444,9 +440,16 @@ void ChaChaTLS_Policy::CipherResynchronize(byte *keystreamBuffer, const byte *IV CRYPTOPP_UNUSED(keystreamBuffer), CRYPTOPP_UNUSED(length); CRYPTOPP_ASSERT(length==12); + // State words are defined in RFC 8439, Section 2.3. + m_state[0] = 0x61707865; m_state[1] = 0x3320646e; + m_state[2] = 0x79622d32; m_state[3] = 0x6b206574; + + // Copy saved key into state + std::memcpy(m_state+4, m_state+KEY, 8*sizeof(word32)); + // State words are defined in RFC 8439, Section 2.3 GetBlock get(IV); - m_state[12] = m_state[16]; + m_state[12] = m_state[CTR]; get(m_state[13])(m_state[14])(m_state[15]); } @@ -510,9 +513,9 @@ void XChaCha20_Policy::CipherSetKey(const NameValuePairs ¶ms, const byte *ke word64 block; if (params.GetValue("InitialBlock", block)) - m_state[24] = static_cast(block); + m_state[CTR] = static_cast(block); else - m_state[24] = 1; + m_state[CTR] = 1; // Stash key away for use in CipherResynchronize GetBlock get(key); @@ -545,7 +548,7 @@ void XChaCha20_Policy::CipherResynchronize(byte *keystreamBuffer, const byte *iv m_state[2] = 0x79622d32; m_state[3] = 0x6b206574; // Setup new IV - m_state[12] = m_state[24]; + m_state[12] = m_state[CTR]; m_state[13] = 0; m_state[14] = GetWord(false, LITTLE_ENDIAN_ORDER, iv+16); m_state[15] = GetWord(false, LITTLE_ENDIAN_ORDER, iv+20); diff --git a/chacha.h b/chacha.h index b8d392fd..76aeb01b 100644 --- a/chacha.h +++ b/chacha.h @@ -5,10 +5,10 @@ // The library added Bernstein's ChaCha classses at Crypto++ 5.6.4. The IETF // uses a slightly different implementation than Bernstein, and the IETF -// classes were added at Crypto++ 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. +// ChaCha and XChaCha classes were added at Crypto++ 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 @@ -20,7 +20,10 @@ /// 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. +/// and TLS_DHE_RSA_WITH_CHACHA20_POLY1305_SHA256. Finally, +/// the library provides XChaCha: +/// eXtended-nonce ChaCha and AEAD_XChaCha20_Poly1305 (rev. 03). /// \since ChaCha since Crypto++ 5.6.4, ChaChaTLS and XChaCha20 since Crypto++ 8.1 #ifndef CRYPTOPP_CHACHA_H @@ -125,8 +128,10 @@ protected: std::string AlgorithmName() const; std::string AlgorithmProvider() const; - FixedSizeAlignedSecBlock m_state; + FixedSizeAlignedSecBlock m_state; CRYPTOPP_CONSTANT(ROUNDS = ChaChaTLS_Info::ROUNDS) + CRYPTOPP_CONSTANT(KEY = 16) // Index into m_state + CRYPTOPP_CONSTANT(CTR = 24) // Index into m_state }; /// \brief ChaCha-TLS stream cipher @@ -191,6 +196,7 @@ protected: FixedSizeAlignedSecBlock m_state; CRYPTOPP_CONSTANT(ROUNDS = XChaCha20_Info::ROUNDS) CRYPTOPP_CONSTANT(KEY = 16) // Index into m_state + CRYPTOPP_CONSTANT(CTR = 24) // Index into m_state }; /// \brief XChaCha stream cipher