@@ -255,20 +255,37 @@ static void TestChaCha20Poly1305(const std::string& plain_hex, const std::string
255255 auto key = ParseHex<std::byte>(key_hex);
256256 auto expected_cipher = ParseHex<std::byte>(cipher_hex);
257257
258- std::vector<std::byte> cipher (plain.size () + AEADChaCha20Poly1305::EXPANSION);
259- AEADChaCha20Poly1305 aead{key};
260- aead.Encrypt (plain, aad, nonce, cipher);
261- BOOST_CHECK (cipher == expected_cipher);
258+ for (int i = 0 ; i < 10 ; ++i) {
259+ // During i=0, use single-plain Encrypt/Decrypt; others use a split at prefix.
260+ size_t prefix = i ? InsecureRandRange (plain.size () + 1 ) : plain.size ();
261+ // Encrypt.
262+ std::vector<std::byte> cipher (plain.size () + AEADChaCha20Poly1305::EXPANSION);
263+ AEADChaCha20Poly1305 aead{key};
264+ if (i == 0 ) {
265+ aead.Encrypt (plain, aad, nonce, cipher);
266+ } else {
267+ aead.Encrypt (Span{plain}.first (prefix), Span{plain}.subspan (prefix), aad, nonce, cipher);
268+ }
269+ BOOST_CHECK (cipher == expected_cipher);
262270
263- std::vector<std::byte> decipher (cipher.size () - AEADChaCha20Poly1305::EXPANSION);
264- bool ret = aead.Decrypt (cipher, aad, nonce, decipher);
265- BOOST_CHECK (ret);
266- BOOST_CHECK (decipher == plain);
271+ // Decrypt.
272+ std::vector<std::byte> decipher (cipher.size () - AEADChaCha20Poly1305::EXPANSION);
273+ bool ret{false };
274+ if (i == 0 ) {
275+ ret = aead.Decrypt (cipher, aad, nonce, decipher);
276+ } else {
277+ ret = aead.Decrypt (cipher, aad, nonce, Span{decipher}.first (prefix), Span{decipher}.subspan (prefix));
278+ }
279+ BOOST_CHECK (ret);
280+ BOOST_CHECK (decipher == plain);
281+ }
267282
283+ // Test Keystream output.
268284 std::vector<std::byte> keystream (plain.size ());
285+ AEADChaCha20Poly1305 aead{key};
269286 aead.Keystream (nonce, keystream);
270287 for (size_t i = 0 ; i < plain.size (); ++i) {
271- BOOST_CHECK_EQUAL (plain[i] ^ keystream[i], cipher [i]);
288+ BOOST_CHECK_EQUAL (plain[i] ^ keystream[i], expected_cipher [i]);
272289 }
273290}
274291
@@ -280,25 +297,43 @@ static void TestFSChaCha20Poly1305(const std::string& plain_hex, const std::stri
280297 auto expected_cipher = ParseHex<std::byte>(cipher_hex);
281298 std::vector<std::byte> cipher (plain.size () + FSChaCha20Poly1305::EXPANSION);
282299
283- FSChaCha20Poly1305 enc_aead{key, 224 };
284- for (uint64_t i = 0 ; i < msg_idx; ++i) {
285- std::byte dummy_tag[FSChaCha20Poly1305::EXPANSION] = {{}};
286- enc_aead.Encrypt (Span{dummy_tag}.first (0 ), Span{dummy_tag}.first (0 ), dummy_tag);
287- }
300+ for (int it = 0 ; it < 10 ; ++it) {
301+ // During it==0 we use the single-plain Encrypt/Decrypt; others use a split at prefix.
302+ size_t prefix = it ? InsecureRandRange (plain.size () + 1 ) : plain.size ();
288303
289- enc_aead.Encrypt (plain, aad, cipher);
290- BOOST_CHECK (cipher == expected_cipher);
304+ // Do msg_idx dummy encryptions to seek to the correct packet.
305+ FSChaCha20Poly1305 enc_aead{key, 224 };
306+ for (uint64_t i = 0 ; i < msg_idx; ++i) {
307+ std::byte dummy_tag[FSChaCha20Poly1305::EXPANSION] = {{}};
308+ enc_aead.Encrypt (Span{dummy_tag}.first (0 ), Span{dummy_tag}.first (0 ), dummy_tag);
309+ }
291310
292- FSChaCha20Poly1305 dec_aead{key, 224 };
293- for (uint64_t i = 0 ; i < msg_idx; ++i) {
294- std::byte dummy_tag[FSChaCha20Poly1305::EXPANSION] = {{}};
295- dec_aead.Decrypt (dummy_tag, Span{dummy_tag}.first (0 ), Span{dummy_tag}.first (0 ));
296- }
311+ // Invoke single-plain or plain1/plain2 Encrypt.
312+ if (it == 0 ) {
313+ enc_aead.Encrypt (plain, aad, cipher);
314+ } else {
315+ enc_aead.Encrypt (Span{plain}.first (prefix), Span{plain}.subspan (prefix), aad, cipher);
316+ }
317+ BOOST_CHECK (cipher == expected_cipher);
297318
298- std::vector<std::byte> decipher (cipher.size () - AEADChaCha20Poly1305::EXPANSION);
299- bool ret = dec_aead.Decrypt (cipher, aad, decipher);
300- BOOST_CHECK (ret);
301- BOOST_CHECK (decipher == plain);
319+ // Do msg_idx dummy decryptions to seek to the correct packet.
320+ FSChaCha20Poly1305 dec_aead{key, 224 };
321+ for (uint64_t i = 0 ; i < msg_idx; ++i) {
322+ std::byte dummy_tag[FSChaCha20Poly1305::EXPANSION] = {{}};
323+ dec_aead.Decrypt (dummy_tag, Span{dummy_tag}.first (0 ), Span{dummy_tag}.first (0 ));
324+ }
325+
326+ // Invoke single-plain or plain1/plain2 Decrypt.
327+ std::vector<std::byte> decipher (cipher.size () - AEADChaCha20Poly1305::EXPANSION);
328+ bool ret{false };
329+ if (it == 0 ) {
330+ ret = dec_aead.Decrypt (cipher, aad, decipher);
331+ } else {
332+ ret = dec_aead.Decrypt (cipher, aad, Span{decipher}.first (prefix), Span{decipher}.subspan (prefix));
333+ }
334+ BOOST_CHECK (ret);
335+ BOOST_CHECK (decipher == plain);
336+ }
302337}
303338
304339static void TestHKDF_SHA256_32 (const std::string &ikm_hex, const std::string &salt_hex, const std::string &info_hex, const std::string &okm_check_hex) {
0 commit comments