Line | Count | Source (jump to first uncovered line) |
1 | | // chacha.h - written and placed in the public domain by Jeffrey Walton. |
2 | | // Based on Wei Dai's Salsa20, Botan's SSE2 implementation, |
3 | | // and Bernstein's reference ChaCha family implementation at |
4 | | // http://cr.yp.to/chacha.html. |
5 | | |
6 | | // The library added Bernstein's ChaCha classes at Crypto++ 5.6.4. The IETF |
7 | | // uses a slightly different implementation than Bernstein, and the IETF |
8 | | // ChaCha and XChaCha classes were added at Crypto++ 8.1. We wanted to maintain |
9 | | // ABI compatibility at the 8.1 release so the original ChaCha classes were not |
10 | | // disturbed. Instead new classes were added for IETF ChaCha. The back-end |
11 | | // implementation shares code as expected, however. |
12 | | |
13 | | /// \file chacha.h |
14 | | /// \brief Classes for ChaCha8, ChaCha12 and ChaCha20 stream ciphers |
15 | | /// \details Crypto++ provides Bernstein and ECRYPT's ChaCha from <a |
16 | | /// href="http://cr.yp.to/chacha/chacha-20080128.pdf">ChaCha, a |
17 | | /// variant of Salsa20</a> (2008.01.28). Crypto++ also provides the |
18 | | /// IETF implementation of ChaCha using the ChaChaTLS name. Bernstein's |
19 | | /// implementation is _slightly_ different from the TLS working group's |
20 | | /// implementation for cipher suites |
21 | | /// <tt>TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256</tt>, |
22 | | /// <tt>TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305_SHA256</tt>, |
23 | | /// and <tt>TLS_DHE_RSA_WITH_CHACHA20_POLY1305_SHA256</tt>. Finally, |
24 | | /// the library provides <a |
25 | | /// href="https://tools.ietf.org/html/draft-arciszewski-xchacha">XChaCha: |
26 | | /// eXtended-nonce ChaCha and AEAD_XChaCha20_Poly1305 (rev. 03)</a>. |
27 | | /// \since ChaCha since Crypto++ 5.6.4, ChaChaTLS and XChaCha20 since Crypto++ 8.1 |
28 | | |
29 | | #ifndef CRYPTOPP_CHACHA_H |
30 | | #define CRYPTOPP_CHACHA_H |
31 | | |
32 | | #include "strciphr.h" |
33 | | #include "secblock.h" |
34 | | |
35 | | NAMESPACE_BEGIN(CryptoPP) |
36 | | |
37 | | ////////////////////////////// Bernstein ChaCha ////////////////////////////// |
38 | | |
39 | | /// \brief ChaCha stream cipher information |
40 | | /// \since Crypto++ 5.6.4 |
41 | | struct ChaCha_Info : public VariableKeyLength<32, 16, 32, 16, SimpleKeyingInterface::UNIQUE_IV, 8> |
42 | | { |
43 | | /// \brief The algorithm name |
44 | | /// \return the algorithm name |
45 | | /// \details StaticAlgorithmName returns the algorithm's name as a static |
46 | | /// member function. |
47 | | /// \details Bernstein named the cipher variants ChaCha8, ChaCha12 and |
48 | | /// ChaCha20. More generally, Bernstein called the family ChaCha{r}. |
49 | | /// AlgorithmName() provides the exact name once rounds are set. |
50 | 0 | static const char* StaticAlgorithmName() { |
51 | 0 | return "ChaCha"; |
52 | 0 | } |
53 | | }; |
54 | | |
55 | | /// \brief ChaCha stream cipher implementation |
56 | | /// \since Crypto++ 5.6.4 |
57 | | class CRYPTOPP_NO_VTABLE ChaCha_Policy : public AdditiveCipherConcretePolicy<word32, 16> |
58 | | { |
59 | | public: |
60 | 0 | virtual ~ChaCha_Policy() {} |
61 | 0 | ChaCha_Policy() : m_rounds(ROUNDS) {} |
62 | | |
63 | | protected: |
64 | | void CipherSetKey(const NameValuePairs ¶ms, const byte *key, size_t length); |
65 | | void OperateKeystream(KeystreamOperation operation, byte *output, const byte *input, size_t iterationCount); |
66 | | void CipherResynchronize(byte *keystreamBuffer, const byte *IV, size_t length); |
67 | 0 | bool CipherIsRandomAccess() const {return true;} |
68 | | void SeekToIteration(lword iterationCount); |
69 | | unsigned int GetAlignment() const; |
70 | | unsigned int GetOptimalBlockSize() const; |
71 | | |
72 | | std::string AlgorithmName() const; |
73 | | std::string AlgorithmProvider() const; |
74 | | |
75 | | CRYPTOPP_CONSTANT(ROUNDS = 20); // Default rounds |
76 | | FixedSizeAlignedSecBlock<word32, 16> m_state; |
77 | | unsigned int m_rounds; |
78 | | }; |
79 | | |
80 | | /// \brief ChaCha stream cipher |
81 | | /// \details This is Bernstein and ECRYPT's ChaCha. It is _slightly_ different |
82 | | /// from the IETF's version of ChaCha called ChaChaTLS. |
83 | | /// \sa <a href="http://cr.yp.to/chacha/chacha-20080208.pdf">ChaCha, a variant |
84 | | /// of Salsa20</a> (2008.01.28). |
85 | | /// \since Crypto++ 5.6.4 |
86 | | struct ChaCha : public ChaCha_Info, public SymmetricCipherDocumentation |
87 | | { |
88 | | /// \brief ChaCha Encryption |
89 | | typedef SymmetricCipherFinal<ConcretePolicyHolder<ChaCha_Policy, AdditiveCipherTemplate<> >, ChaCha_Info > Encryption; |
90 | | /// \brief ChaCha Decryption |
91 | | typedef Encryption Decryption; |
92 | | }; |
93 | | |
94 | | ////////////////////////////// IETF ChaChaTLS ////////////////////////////// |
95 | | |
96 | | /// \brief IETF ChaCha20 stream cipher information |
97 | | /// \since Crypto++ 8.1 |
98 | | struct ChaChaTLS_Info : public FixedKeyLength<32, SimpleKeyingInterface::UNIQUE_IV, 12>, FixedRounds<20> |
99 | | { |
100 | | /// \brief The algorithm name |
101 | | /// \return the algorithm name |
102 | | /// \details StaticAlgorithmName returns the algorithm's name as a static |
103 | | /// member function. |
104 | | /// \details This is the IETF's variant of Bernstein's ChaCha from RFC |
105 | | /// 8439. IETF ChaCha is called ChaChaTLS in the Crypto++ library. It |
106 | | /// is _slightly_ different from Bernstein's implementation. |
107 | 1 | static const char* StaticAlgorithmName() { |
108 | 1 | return "ChaChaTLS"; |
109 | 1 | } |
110 | | }; |
111 | | |
112 | | /// \brief IETF ChaCha20 stream cipher implementation |
113 | | /// \since Crypto++ 8.1 |
114 | | class CRYPTOPP_NO_VTABLE ChaChaTLS_Policy : public AdditiveCipherConcretePolicy<word32, 16> |
115 | | { |
116 | | public: |
117 | 27 | virtual ~ChaChaTLS_Policy() {} |
118 | 27 | ChaChaTLS_Policy() : m_counter(0) {} |
119 | | |
120 | | protected: |
121 | | void CipherSetKey(const NameValuePairs ¶ms, const byte *key, size_t length); |
122 | | void OperateKeystream(KeystreamOperation operation, byte *output, const byte *input, size_t iterationCount); |
123 | | void CipherResynchronize(byte *keystreamBuffer, const byte *IV, size_t length); |
124 | 0 | bool CipherIsRandomAccess() const {return true;} |
125 | | void SeekToIteration(lword iterationCount); |
126 | | unsigned int GetAlignment() const; |
127 | | unsigned int GetOptimalBlockSize() const; |
128 | | |
129 | | std::string AlgorithmName() const; |
130 | | std::string AlgorithmProvider() const; |
131 | | |
132 | | FixedSizeAlignedSecBlock<word32, 16+8> m_state; |
133 | | unsigned int m_counter; |
134 | | CRYPTOPP_CONSTANT(ROUNDS = ChaChaTLS_Info::ROUNDS); |
135 | | CRYPTOPP_CONSTANT(KEY = 16); // Index into m_state |
136 | | CRYPTOPP_CONSTANT(CTR = 24); // Index into m_state |
137 | | }; |
138 | | |
139 | | /// \brief IETF ChaCha20 stream cipher |
140 | | /// \details This is the IETF's variant of Bernstein's ChaCha from RFC 8439. |
141 | | /// IETF ChaCha is called ChaChaTLS in the Crypto++ library. It is |
142 | | /// _slightly_ different from the Bernstein implementation. ChaCha-TLS |
143 | | /// can be used for cipher suites |
144 | | /// <tt>TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256</tt>, |
145 | | /// <tt>TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305_SHA256</tt>, and |
146 | | /// <tt>TLS_DHE_RSA_WITH_CHACHA20_POLY1305_SHA256</tt>. |
147 | | /// \sa <a href="https://tools.ietf.org/html/rfc8439">RFC 8439, ChaCha20 and |
148 | | /// Poly1305 for IETF Protocols</a>, <A |
149 | | /// HREF="https://mailarchive.ietf.org/arch/msg/cfrg/gsOnTJzcbgG6OqD8Sc0GO5aR_tU">How |
150 | | /// to handle block counter wrap in IETF's ChaCha algorithm?</A> and |
151 | | /// <A HREF="https://github.com/weidai11/cryptopp/issues/790">Issue |
152 | | /// 790, ChaChaTLS results when counter block wraps</A>. |
153 | | /// \since Crypto++ 8.1 |
154 | | struct ChaChaTLS : public ChaChaTLS_Info, public SymmetricCipherDocumentation |
155 | | { |
156 | | /// \brief ChaCha-TLS Encryption |
157 | | typedef SymmetricCipherFinal<ConcretePolicyHolder<ChaChaTLS_Policy, AdditiveCipherTemplate<> >, ChaChaTLS_Info > Encryption; |
158 | | /// \brief ChaCha-TLS Decryption |
159 | | typedef Encryption Decryption; |
160 | | }; |
161 | | |
162 | | ////////////////////////////// IETF XChaCha20 draft ////////////////////////////// |
163 | | |
164 | | /// \brief IETF XChaCha20 stream cipher information |
165 | | /// \since Crypto++ 8.1 |
166 | | struct XChaCha20_Info : public FixedKeyLength<32, SimpleKeyingInterface::UNIQUE_IV, 24> |
167 | | { |
168 | | /// \brief The algorithm name |
169 | | /// \return the algorithm name |
170 | | /// \details StaticAlgorithmName returns the algorithm's name as a static |
171 | | /// member function. |
172 | | /// \details This is the IETF's XChaCha from draft-arciszewski-xchacha. |
173 | 2 | static const char* StaticAlgorithmName() { |
174 | 2 | return "XChaCha20"; |
175 | 2 | } |
176 | | }; |
177 | | |
178 | | /// \brief IETF XChaCha20 stream cipher implementation |
179 | | /// \since Crypto++ 8.1 |
180 | | class CRYPTOPP_NO_VTABLE XChaCha20_Policy : public AdditiveCipherConcretePolicy<word32, 16> |
181 | | { |
182 | | public: |
183 | 13 | virtual ~XChaCha20_Policy() {} |
184 | 13 | XChaCha20_Policy() : m_counter(0), m_rounds(ROUNDS) {} |
185 | | |
186 | | protected: |
187 | | void CipherSetKey(const NameValuePairs ¶ms, const byte *key, size_t length); |
188 | | void OperateKeystream(KeystreamOperation operation, byte *output, const byte *input, size_t iterationCount); |
189 | | void CipherResynchronize(byte *keystreamBuffer, const byte *IV, size_t length); |
190 | 0 | bool CipherIsRandomAccess() const {return false;} |
191 | | void SeekToIteration(lword iterationCount); |
192 | | unsigned int GetAlignment() const; |
193 | | unsigned int GetOptimalBlockSize() const; |
194 | | |
195 | | std::string AlgorithmName() const; |
196 | | std::string AlgorithmProvider() const; |
197 | | |
198 | | FixedSizeAlignedSecBlock<word32, 16+8> m_state; |
199 | | unsigned int m_counter, m_rounds; |
200 | | CRYPTOPP_CONSTANT(ROUNDS = 20); // Default rounds |
201 | | CRYPTOPP_CONSTANT(KEY = 16); // Index into m_state |
202 | | }; |
203 | | |
204 | | /// \brief IETF XChaCha20 stream cipher |
205 | | /// \details This is the IETF's XChaCha from draft-arciszewski-xchacha. |
206 | | /// \sa <a href="https://tools.ietf.org/html/draft-arciszewski-xchacha">XChaCha: |
207 | | /// eXtended-nonce ChaCha and AEAD_XChaCha20_Poly1305 (rev. 03)</a>, <A |
208 | | /// HREF="https://mailarchive.ietf.org/arch/msg/cfrg/gsOnTJzcbgG6OqD8Sc0GO5aR_tU">How |
209 | | /// to handle block counter wrap in IETF's ChaCha algorithm?</A> and |
210 | | /// <A HREF="https://github.com/weidai11/cryptopp/issues/790">Issue |
211 | | /// 790, ChaCha20 results when counter block wraps</A>. |
212 | | /// \since Crypto++ 8.1 |
213 | | struct XChaCha20 : public XChaCha20_Info, public SymmetricCipherDocumentation |
214 | | { |
215 | | /// \brief XChaCha Encryption |
216 | | typedef SymmetricCipherFinal<ConcretePolicyHolder<XChaCha20_Policy, AdditiveCipherTemplate<> >, XChaCha20_Info > Encryption; |
217 | | /// \brief XChaCha Decryption |
218 | | typedef Encryption Decryption; |
219 | | }; |
220 | | |
221 | | NAMESPACE_END |
222 | | |
223 | | #endif // CRYPTOPP_CHACHA_H |