diff --git a/doc/api_ref/cipher_modes.rst b/doc/api_ref/cipher_modes.rst index 19f9ba66feb..1160a1b50b7 100644 --- a/doc/api_ref/cipher_modes.rst +++ b/doc/api_ref/cipher_modes.rst @@ -454,6 +454,26 @@ Algorithm specification name: - Tag size defaults to 16. - Examples: e.g. ``AES-128/GCM``, ``AES-128/GCM(12)`` +GCM-SIV +~~~~~~~~ + +Available if ``BOTAN_HAS_AEAD_GCM_SIV`` is defined. + +AES-GCM-SIV, specified in RFC 8452. Like SIV this mode is resistant to nonce +misuse; if a nonce is ever reused, the only information leaked is if two +messages encrypted under the same nonce were identical. Requires a 128-bit +block cipher with either a 128-bit or 256-bit key. The nonce must be exactly +96 bits, and the tag is always 128 bits. + +Note that unlike SIV, GCM-SIV is not usable as a deterministic (nonce-less) +encryption scheme; a nonce must always be provided. + +Algorithm specification name: +``/GCM-SIV`` (reported name) / +``GCM-SIV()`` + +- Examples: ``AES-128/GCM-SIV``, ``AES-256/GCM-SIV`` + OCB ~~~~~ diff --git a/doc/dev_ref/todo.rst b/doc/dev_ref/todo.rst index 0fc03106059..117e4626a55 100644 --- a/doc/dev_ref/todo.rst +++ b/doc/dev_ref/todo.rst @@ -9,7 +9,6 @@ Request a new feature by opening a pull request to update this file. New Ciphers/Hashes/MACs ---------------------------------------- -* GCM-SIV (RFC 8452) * EME* tweakable block cipher (https://eprint.iacr.org/2004/125) * PMAC * SIV-PMAC diff --git a/src/lib/modes/aead/aead.cpp b/src/lib/modes/aead/aead.cpp index 67345d72cec..d634b70550e 100644 --- a/src/lib/modes/aead/aead.cpp +++ b/src/lib/modes/aead/aead.cpp @@ -32,6 +32,10 @@ #include #endif +#if defined(BOTAN_HAS_AEAD_GCM_SIV) + #include +#endif + #if defined(BOTAN_HAS_AEAD_OCB) #include #endif @@ -141,6 +145,20 @@ std::unique_ptr AEAD_Mode::create(std::string_view algo, Cipher_Dir d } #endif + #if defined(BOTAN_HAS_AEAD_GCM_SIV) + if(req.algo_name() == "GCM-SIV") { + // Unlike GCM the tag length is fixed, so reject eg "AES-128/GCM-SIV(12)" + if(req.arg_count() != 1) { + return std::unique_ptr(); + } + if(dir == Cipher_Dir::Encryption) { + return std::make_unique(std::move(bc)); + } else { + return std::make_unique(std::move(bc)); + } + } + #endif + #if defined(BOTAN_HAS_AEAD_OCB) if(req.algo_name() == "OCB") { const size_t tag_len = req.arg_as_integer(1, 16); diff --git a/src/lib/modes/aead/gcm_siv/gcm_siv.cpp b/src/lib/modes/aead/gcm_siv/gcm_siv.cpp new file mode 100644 index 00000000000..ebd778ce2d8 --- /dev/null +++ b/src/lib/modes/aead/gcm_siv/gcm_siv.cpp @@ -0,0 +1,287 @@ +/* +* GCM-SIV Mode (RFC 8452) +* (C) 2026 Jack Lloyd +* +* Botan is released under the Simplified BSD License (see license.txt) +*/ + +#include + +#include +#include +#include +#include +#include +#include + +namespace Botan { + +namespace { + +Key_Length_Specification gcm_siv_key_spec(const BlockCipher& cipher) { + if(cipher.block_size() != 16) { + throw Invalid_Argument("GCM-SIV requires a 128 bit block cipher"); + } + + // The key-generating key is either 128 or 256 bits, and the derived + // message-encryption key is of the same length + const bool k16 = cipher.valid_keylength(16); + const bool k32 = cipher.valid_keylength(32); + + if(k16 && k32) { + return Key_Length_Specification(16, 32, 16); + } else if(k16) { + return Key_Length_Specification(16); + } else if(k32) { + return Key_Length_Specification(32); + } else { + throw Invalid_Argument("GCM-SIV requires a cipher supporting 128 or 256 bit keys"); + } +} + +} // namespace + +GCM_SIV_Mode::GCM_SIV_Mode(std::unique_ptr cipher) : + m_cipher_name(cipher->name()), + m_key_spec(gcm_siv_key_spec(*cipher)), + m_cipher(std::move(cipher)), + m_msg_cipher(m_cipher->new_object()) {} + +GCM_SIV_Mode::~GCM_SIV_Mode() = default; + +void GCM_SIV_Mode::clear() { + m_cipher->clear(); + m_kgk_len = 0; + zap(m_ad); + reset(); +} + +void GCM_SIV_Mode::reset() { + // The derived keys are per-message; start_msg rekeys both + m_msg_cipher->clear(); + m_polyval.clear(); + secure_scrub_memory(m_nonce); + m_msg_buf.clear(); + m_in_msg = false; +} + +std::string GCM_SIV_Mode::name() const { + return fmt("{}/GCM-SIV", m_cipher_name); +} + +std::string GCM_SIV_Mode::provider() const { + return m_polyval.provider(); +} + +size_t GCM_SIV_Mode::update_granularity() const { + return 1; +} + +size_t GCM_SIV_Mode::ideal_granularity() const { + return BS * std::max(2, BlockCipher::ParallelismMult); +} + +bool GCM_SIV_Mode::valid_nonce_length(size_t len) const { + return len == 12; +} + +Key_Length_Specification GCM_SIV_Mode::key_spec() const { + return m_key_spec; +} + +bool GCM_SIV_Mode::has_keying_material() const { + return m_cipher->has_keying_material(); +} + +void GCM_SIV_Mode::key_schedule(std::span key) { + m_cipher->set_key(key); + m_kgk_len = key.size(); + reset(); +} + +void GCM_SIV_Mode::set_associated_data_n(size_t idx, std::span ad) { + BOTAN_ARG_CHECK(idx == 0, "GCM-SIV: cannot handle non-zero index in set_associated_data_n"); + BOTAN_STATE_CHECK(!m_in_msg); + BOTAN_ARG_CHECK(static_cast(ad.size()) <= MAX_INPUT_LEN, "GCM-SIV AD too large"); + m_ad.assign(ad.begin(), ad.end()); +} + +void GCM_SIV_Mode::start_msg(const uint8_t nonce[], size_t nonce_len) { + assert_key_material_set(); + BOTAN_STATE_CHECK(!m_in_msg); + + if(!valid_nonce_length(nonce_len)) { + throw Invalid_IV_Length(name(), nonce_len); + } + + copy_mem(m_nonce, std::span{nonce, nonce_len}); + + /* + Derive the per-nonce keys, RFC 8452 section 4: + + "These keys are generated by encrypting a series of plaintext blocks + that contain a 32-bit, little-endian counter followed by the nonce, + and then discarding the second half of the resulting ciphertext." + */ + const size_t blocks = (m_kgk_len == 16) ? 4 : 6; + + std::array kb{}; + for(size_t i = 0; i != blocks; ++i) { + store_le(static_cast(i), &kb[BS * i]); + copy_mem(&kb[BS * i + 4], m_nonce.data(), m_nonce.size()); + } + m_cipher->encrypt_n(kb.data(), kb.data(), blocks); + + std::array auth_key{}; + secure_vector enc_key(m_kgk_len); + + for(size_t i = 0; i != 2; ++i) { + copy_mem(&auth_key[8 * i], &kb[BS * i], 8); + } + for(size_t i = 0; i != blocks - 2; ++i) { + copy_mem(&enc_key[8 * i], &kb[BS * (i + 2)], 8); + } + + m_polyval.set_key(auth_key); + m_msg_cipher->set_key(enc_key); + + secure_scrub_memory(kb); + secure_scrub_memory(auth_key); + + m_msg_buf.clear(); + m_in_msg = true; +} + +size_t GCM_SIV_Mode::process_msg(uint8_t buf[], size_t sz) { + BOTAN_STATE_CHECK(m_in_msg); + + // Early rejection to bound buffering; the exact (per-direction) limits + // are checked in finish. The tag is included to allow decryption inputs. + if(sz > MAX_INPUT_LEN + BS - m_msg_buf.size()) { + throw Invalid_State("GCM-SIV message length limit exceeded"); + } + + // All input is buffered until finish + m_msg_buf.insert(m_msg_buf.end(), buf, buf + sz); + return 0; +} + +std::array GCM_SIV_Mode::compute_tag(std::span ptext) { + m_polyval.update(m_ad); + m_polyval.zero_pad(); + m_polyval.update(ptext); + m_polyval.zero_pad(); + + const uint64_t ad_bits = 8 * static_cast(m_ad.size()); + const uint64_t pt_bits = 8 * static_cast(ptext.size()); + m_polyval.update(store_le(ad_bits, pt_bits)); + + std::array S{}; + m_polyval.final(S); + + /* + RFC 8452 section 4: "XOR the first twelve bytes of S_s with the nonce + and clear the most significant bit of the last byte. Encrypt the + result with AES using the message-encryption key to produce the tag." + */ + xor_buf(S.data(), m_nonce.data(), m_nonce.size()); + S[15] &= 0x7f; + m_msg_cipher->encrypt(S); + + return S; +} + +void GCM_SIV_Mode::ctr_xor(std::span tag, uint8_t buf[], size_t len) { + /* + RFC 8452 section 4: "The initial counter block is the tag with the + most significant bit of the last byte set to one. The counter + advances by incrementing the first 32 bits interpreted as an + unsigned, little-endian integer, wrapping at 2^32." + */ + std::array ctr_block{}; + copy_mem(ctr_block, tag); + ctr_block[15] |= 0x80; + + uint32_t ctr32 = load_le(ctr_block.data(), 0); + + secure_vector ks(m_msg_cipher->parallel_bytes()); + + while(len > 0) { + const size_t blocks = std::min((len + BS - 1) / BS, ks.size() / BS); + + for(size_t i = 0; i != blocks; ++i) { + copy_mem(&ks[BS * i], ctr_block.data(), BS); + store_le(ctr32, &ks[BS * i]); + ctr32 += 1; + } + + m_msg_cipher->encrypt_n(ks.data(), ks.data(), blocks); + + const size_t todo = std::min(len, blocks * BS); + xor_buf(buf, ks.data(), todo); + buf += todo; + len -= todo; + } +} + +size_t GCM_SIV_Encryption::output_length(size_t input_length) const { + return add_or_throw(input_length, tag_size(), "GCM-SIV input too large"); +} + +void GCM_SIV_Encryption::finish_msg(secure_vector& buffer, size_t offset) { + BOTAN_STATE_CHECK(in_msg()); + BOTAN_ARG_CHECK(offset <= buffer.size(), "Invalid offset"); + + buffer.insert(buffer.begin() + offset, msg_buf().begin(), msg_buf().end()); + msg_buf().clear(); + + const size_t ptext_len = buffer.size() - offset; + BOTAN_ARG_CHECK(static_cast(ptext_len) <= MAX_INPUT_LEN, "GCM-SIV plaintext too large"); + uint8_t* buf = buffer.data() + offset; + + const auto tag = compute_tag({buf, ptext_len}); + ctr_xor(tag, buf, ptext_len); + + buffer += std::make_pair(tag.data(), tag.size()); + reset(); +} + +size_t GCM_SIV_Decryption::output_length(size_t input_length) const { + BOTAN_ARG_CHECK(input_length >= tag_size(), "Message too short to be valid"); + return input_length - tag_size(); +} + +void GCM_SIV_Decryption::finish_msg(secure_vector& buffer, size_t offset) { + BOTAN_STATE_CHECK(in_msg()); + BOTAN_ARG_CHECK(offset <= buffer.size(), "Invalid offset"); + + if(!msg_buf().empty()) { + buffer.insert(buffer.begin() + offset, msg_buf().begin(), msg_buf().end()); + msg_buf().clear(); + } + + const size_t sz = buffer.size() - offset; + BOTAN_ARG_CHECK(sz >= tag_size(), "input did not include the tag"); + + const size_t ctext_len = sz - tag_size(); + BOTAN_ARG_CHECK(static_cast(ctext_len) <= MAX_INPUT_LEN, "GCM-SIV ciphertext too large"); + uint8_t* buf = buffer.data() + offset; + + std::array included_tag{}; + copy_mem(included_tag, std::span{buf + ctext_len, 16}); + + ctr_xor(included_tag, buf, ctext_len); + + const auto expected_tag = compute_tag({buf, ctext_len}); + + reset(); + + if(!CT::is_equal(expected_tag.data(), included_tag.data(), included_tag.size()).as_bool()) { + clear_mem(std::span{buffer}.subspan(offset, ctext_len)); + throw Invalid_Authentication_Tag("GCM-SIV tag check failed"); + } + + buffer.resize(offset + ctext_len); +} + +} // namespace Botan diff --git a/src/lib/modes/aead/gcm_siv/gcm_siv.h b/src/lib/modes/aead/gcm_siv/gcm_siv.h new file mode 100644 index 00000000000..9f83be60ee0 --- /dev/null +++ b/src/lib/modes/aead/gcm_siv/gcm_siv.h @@ -0,0 +1,128 @@ +/* +* GCM-SIV Mode +* (C) 2026 Jack Lloyd +* +* Botan is released under the Simplified BSD License (see license.txt) +*/ + +#ifndef BOTAN_AEAD_GCM_SIV_H_ +#define BOTAN_AEAD_GCM_SIV_H_ + +#include + +#include +#include + +namespace Botan { + +/** +* GCM-SIV Mode (RFC 8452) +*/ +class GCM_SIV_Mode : public AEAD_Mode /* NOLINT(*-special-member-functions) */ { + public: + void set_associated_data_n(size_t idx, std::span ad) final; + + std::string name() const final; + + size_t update_granularity() const final; + + size_t ideal_granularity() const final; + + Key_Length_Specification key_spec() const final; + + bool valid_nonce_length(size_t len) const final; + + size_t tag_size() const final { return 16; } + + bool requires_entire_message() const final { return true; } + + /// The AD is buffered as-is; it is not processed until finish + bool associated_data_requires_key() const final { return false; } + + void clear() final; + + void reset() final; + + std::string provider() const final; + + bool has_keying_material() const final; + + ~GCM_SIV_Mode() override; + + protected: + explicit GCM_SIV_Mode(std::unique_ptr cipher); + + static constexpr size_t BS = 16; + + /// RFC 8452 limits both the plaintext and the AD to 2**36 bytes + static constexpr uint64_t MAX_INPUT_LEN = static_cast(1) << 36; + + secure_vector& msg_buf() { return m_msg_buf; } + + bool in_msg() const { return m_in_msg; } + + /// Compute the expected tag for the (unpadded) plaintext + std::array compute_tag(std::span ptext); + + /// XOR the buffer with the CTR keystream, starting from the tag-derived counter + void ctr_xor(std::span tag, uint8_t buf[], size_t len); + + private: + void start_msg(const uint8_t nonce[], size_t nonce_len) final; + size_t process_msg(uint8_t buf[], size_t size) final; + + void key_schedule(std::span key) final; + + const std::string m_cipher_name; + const Key_Length_Specification m_key_spec; + + std::unique_ptr m_cipher; // keyed with the key-generating key + std::unique_ptr m_msg_cipher; // keyed with the per-message encryption key + Polyval m_polyval; + + size_t m_kgk_len = 0; + std::array m_nonce{}; + secure_vector m_ad; + secure_vector m_msg_buf; + bool m_in_msg = false; +}; + +/** +* GCM-SIV Encryption +*/ +class GCM_SIV_Encryption final : public GCM_SIV_Mode { + public: + /** + * @param cipher the 128 bit block cipher to use + */ + explicit GCM_SIV_Encryption(std::unique_ptr cipher) : GCM_SIV_Mode(std::move(cipher)) {} + + size_t output_length(size_t input_length) const override; + + size_t minimum_final_size() const override { return 0; } + + private: + void finish_msg(secure_vector& final_block, size_t offset = 0) override; +}; + +/** +* GCM-SIV Decryption +*/ +class GCM_SIV_Decryption final : public GCM_SIV_Mode { + public: + /** + * @param cipher the 128 bit block cipher to use + */ + explicit GCM_SIV_Decryption(std::unique_ptr cipher) : GCM_SIV_Mode(std::move(cipher)) {} + + size_t output_length(size_t input_length) const override; + + size_t minimum_final_size() const override { return tag_size(); } + + private: + void finish_msg(secure_vector& final_block, size_t offset = 0) override; +}; + +} // namespace Botan + +#endif diff --git a/src/lib/modes/aead/gcm_siv/info.txt b/src/lib/modes/aead/gcm_siv/info.txt new file mode 100644 index 00000000000..fd586a75371 --- /dev/null +++ b/src/lib/modes/aead/gcm_siv/info.txt @@ -0,0 +1,13 @@ + +AEAD_GCM_SIV -> 20260719 + + + +name -> "GCM-SIV" +brief -> "GCM-SIV nonce misuse-resistant AEAD (RFC 8452)" + + + +block +polyval + diff --git a/src/lib/utils/ghash/ghash.cpp b/src/lib/utils/ghash/ghash.cpp index 8e76130f966..711beb692e5 100644 --- a/src/lib/utils/ghash/ghash.cpp +++ b/src/lib/utils/ghash/ghash.cpp @@ -64,6 +64,13 @@ void GHASH::ghash_multiply(std::span x, std::span x, + const secure_vector& HM, + std::span input, + size_t blocks) { auto scope = CT::scoped_poison(x); auto X = load_be>(x); @@ -83,11 +90,11 @@ void GHASH::ghash_multiply(std::span x, std::span key) { m_text_len = 0; BOTAN_ASSERT_NOMSG(key.size() == GCM_BS); - auto H = load_be>(key.first()); #if defined(BOTAN_HAS_GHASH_AVX512_CLMUL) if(CPUID::has(CPUID::Feature::AVX512_CLMUL)) { @@ -130,10 +136,16 @@ void GHASH::key_schedule(std::span key) { } #endif + ghash_precompute_base(key.first(), m_HM); +} + +void GHASH::ghash_precompute_base(std::span key, secure_vector& HM) { + auto H = load_be>(key); + const uint64_t R = 0xE100000000000000; - if(m_HM.size() != 256) { - m_HM.resize(256); + if(HM.size() != 256) { + HM.resize(256); } // precompute the multiples of H @@ -143,8 +155,8 @@ void GHASH::key_schedule(std::span key) { we interleave H^1, H^65, H^2, H^66, H3, H67, H4, H68 to make indexing nicer in the multiplication code */ - m_HM[4 * j + 2 * i] = H[0]; - m_HM[4 * j + 2 * i + 1] = H[1]; + HM[4 * j + 2 * i] = H[0]; + HM[4 * j + 2 * i + 1] = H[1]; // GCM's bit ops are reversed so we carry out of the bottom const uint64_t carry = CT::Mask::expand(H[1] & 1).if_set_return(R); diff --git a/src/lib/utils/ghash/ghash.h b/src/lib/utils/ghash/ghash.h index 898affd81fa..1f63503a2de 100644 --- a/src/lib/utils/ghash/ghash.h +++ b/src/lib/utils/ghash/ghash.h @@ -84,6 +84,16 @@ class GHASH final : public SymmetricAlgorithm { void ghash_multiply(std::span x, std::span input, size_t blocks); + static void ghash_precompute_base(std::span key, secure_vector& HM); + + static void ghash_multiply_base(std::span x, + const secure_vector& HM, + std::span input, + size_t blocks); + + /// Polyval reuses the GHASH tables and kernels for its non-CLMUL fallback + friend class Polyval; + private: AlignmentBuffer m_buffer; diff --git a/src/lib/utils/ghash/ghash_avx512_clmul/ghash_avx512_clmul.cpp b/src/lib/utils/ghash/ghash_avx512_clmul/ghash_avx512_clmul.cpp index d7cd696ad7b..c0cf3dcfdc5 100644 --- a/src/lib/utils/ghash/ghash_avx512_clmul/ghash_avx512_clmul.cpp +++ b/src/lib/utils/ghash/ghash_avx512_clmul/ghash_avx512_clmul.cpp @@ -12,10 +12,34 @@ #include #include +#if defined(BOTAN_HAS_POLYVAL) + #include +#endif + namespace Botan { namespace { +template +BOTAN_FORCE_INLINE __m512i BOTAN_FN_ISA_AVX512_CLMUL load_blocks(const uint8_t in[]) { + const auto B = _mm512_loadu_si512(in); + + if constexpr(BSWAP) { + // Byte swap each lane + const auto swap = _mm512_set_epi64(0x0001020304050607, + 0x08090A0B0C0D0E0F, + 0x0001020304050607, + 0x08090A0B0C0D0E0F, + 0x0001020304050607, + 0x08090A0B0C0D0E0F, + 0x0001020304050607, + 0x08090A0B0C0D0E0F); + return _mm512_shuffle_epi8(B, swap); + } else { + return B; + } +} + BOTAN_FORCE_INLINE __m512i BOTAN_FN_ISA_AVX512_CLMUL fold(__m512i H) { return _mm512_xor_si512(H, _mm512_bsrli_epi128(H, 8)); } @@ -44,11 +68,7 @@ BOTAN_FORCE_INLINE __m512i BOTAN_FN_ISA_AVX512_CLMUL insert_a(__m512i M, const S return _mm512_xor_epi64(M, _mm512_inserti64x2(_mm512_setzero_si512(), a.raw(), 0)); } -} // namespace - -void BOTAN_FN_ISA_AVX512_CLMUL GHASH::ghash_precompute_avx512_clmul(const uint8_t H_bytes[16], uint64_t H_pow[16 * 2]) { - const SIMD_4x32 H1 = mulx_polyval(reverse_vector(SIMD_4x32::load_le(H_bytes))); - +void BOTAN_FN_ISA_AVX512_CLMUL precompute_avx512(const SIMD_4x32& H1, uint64_t H_pow[16 * 2]) { const SIMD_4x32 H2 = polyval_multiply(H1, H1); const SIMD_4x32 H3 = polyval_multiply(H1, H2); const SIMD_4x32 H4 = polyval_multiply(H2, H2); @@ -91,21 +111,10 @@ void BOTAN_FN_ISA_AVX512_CLMUL GHASH::ghash_precompute_avx512_clmul(const uint8_ H13.store_le(H_pow + 30); } -void BOTAN_FN_ISA_AVX512_CLMUL GHASH::ghash_multiply_avx512_clmul(uint8_t x[16], - const uint64_t H_pow[16 * 2], - const uint8_t input[], - size_t blocks) { - SIMD_4x32 a = reverse_vector(SIMD_4x32::load_le(x)); - - // Byte swap each lane - const auto BSWAP = _mm512_set_epi64(0x0001020304050607, - 0x08090A0B0C0D0E0F, - 0x0001020304050607, - 0x08090A0B0C0D0E0F, - 0x0001020304050607, - 0x08090A0B0C0D0E0F, - 0x0001020304050607, - 0x08090A0B0C0D0E0F); +template +void BOTAN_FN_ISA_AVX512_CLMUL +multiply_avx512(uint8_t x[16], const uint64_t H_pow[16 * 2], const uint8_t input[], size_t blocks) { + SIMD_4x32 a = load_block(x); if(blocks >= 16) { const auto H1 = _mm512_loadu_si512(H_pow); // [H4,H3,H2,H1] @@ -120,10 +129,10 @@ void BOTAN_FN_ISA_AVX512_CLMUL GHASH::ghash_multiply_avx512_clmul(uint8_t x[16], const auto H4_fold = fold(H4); while(blocks >= 16) { - __m512i M1 = _mm512_shuffle_epi8(_mm512_loadu_si512(input), BSWAP); - const auto M2 = _mm512_shuffle_epi8(_mm512_loadu_si512(input + 64), BSWAP); - const auto M3 = _mm512_shuffle_epi8(_mm512_loadu_si512(input + 128), BSWAP); - const auto M4 = _mm512_shuffle_epi8(_mm512_loadu_si512(input + 192), BSWAP); + __m512i M1 = load_blocks(input); + const auto M2 = load_blocks(input + 64); + const auto M3 = load_blocks(input + 128); + const auto M4 = load_blocks(input + 192); M1 = insert_a(M1, a); @@ -151,8 +160,8 @@ void BOTAN_FN_ISA_AVX512_CLMUL GHASH::ghash_multiply_avx512_clmul(uint8_t x[16], const auto H2_fold = fold(H2); while(blocks >= 8) { - __m512i M1 = _mm512_shuffle_epi8(_mm512_loadu_si512(input), BSWAP); - const __m512i M2 = _mm512_shuffle_epi8(_mm512_loadu_si512(input + 64), BSWAP); + __m512i M1 = load_blocks(input); + const __m512i M2 = load_blocks(input + 64); M1 = insert_a(M1, a); @@ -175,7 +184,7 @@ void BOTAN_FN_ISA_AVX512_CLMUL GHASH::ghash_multiply_avx512_clmul(uint8_t x[16], const auto H1_fold = fold(H1); while(blocks >= 4) { - __m512i M = _mm512_shuffle_epi8(_mm512_loadu_si512(input), BSWAP); + __m512i M = load_blocks(input); M = insert_a(M, a); auto lo = _mm512_clmulepi64_epi128(H1, M, 0x00); @@ -194,14 +203,41 @@ void BOTAN_FN_ISA_AVX512_CLMUL GHASH::ghash_multiply_avx512_clmul(uint8_t x[16], const SIMD_4x32 H1 = SIMD_4x32::load_le(H_pow + 6); for(size_t i = 0; i != blocks; ++i) { - const SIMD_4x32 m = reverse_vector(SIMD_4x32::load_le(input + 16 * i)); + const SIMD_4x32 m = load_block(input + 16 * i); a ^= m; a = polyval_multiply(H1, a); } } - a = reverse_vector(a); - a.store_le(x); + store_block(a, x); } +} // namespace + +void BOTAN_FN_ISA_AVX512_CLMUL GHASH::ghash_precompute_avx512_clmul(const uint8_t H_bytes[16], uint64_t H_pow[16 * 2]) { + precompute_avx512(mulx_polyval(reverse_vector(SIMD_4x32::load_le(H_bytes))), H_pow); +} + +void BOTAN_FN_ISA_AVX512_CLMUL GHASH::ghash_multiply_avx512_clmul(uint8_t x[16], + const uint64_t H_pow[16 * 2], + const uint8_t input[], + size_t blocks) { + multiply_avx512(x, H_pow, input, blocks); +} + +#if defined(BOTAN_HAS_POLYVAL) + +void BOTAN_FN_ISA_AVX512_CLMUL Polyval::polyval_precompute_avx512_clmul(const uint8_t H[16], uint64_t H_pow[16 * 2]) { + precompute_avx512(SIMD_4x32::load_le(H), H_pow); +} + +void BOTAN_FN_ISA_AVX512_CLMUL Polyval::polyval_multiply_avx512_clmul(uint8_t x[16], + const uint64_t H_pow[16 * 2], + const uint8_t input[], + size_t blocks) { + multiply_avx512(x, H_pow, input, blocks); +} + +#endif + } // namespace Botan diff --git a/src/lib/utils/ghash/ghash_cpu/ghash_cpu.cpp b/src/lib/utils/ghash/ghash_cpu/ghash_cpu.cpp index 03978eca4e0..f166139f4d6 100644 --- a/src/lib/utils/ghash/ghash_cpu/ghash_cpu.cpp +++ b/src/lib/utils/ghash/ghash_cpu/ghash_cpu.cpp @@ -11,6 +11,10 @@ #include #include +#if defined(BOTAN_HAS_POLYVAL) + #include +#endif + namespace Botan { namespace { @@ -76,10 +80,7 @@ inline SIMD_4x32 BOTAN_FN_ISA_CLMUL polyval_multiply_x8(const SIMD_4x32& H1, return polyval_reduce(hi ^ mid.shift_elems_right<2>(), lo ^ mid.shift_elems_left<2>()); } -} // namespace - -void BOTAN_FN_ISA_CLMUL GHASH::ghash_precompute_cpu(const uint8_t H_bytes[16], secure_vector& H_pow) { - const SIMD_4x32 H1 = mulx_polyval(reverse_vector(SIMD_4x32::load_le(H_bytes))); +void BOTAN_FN_ISA_CLMUL precompute_clmul(const SIMD_4x32& H1, secure_vector& H_pow) { const SIMD_4x32 H2 = polyval_multiply(H1, H1); const SIMD_4x32 H3 = polyval_multiply(H1, H2); const SIMD_4x32 H4 = polyval_multiply(H2, H2); @@ -92,15 +93,14 @@ void BOTAN_FN_ISA_CLMUL GHASH::ghash_precompute_cpu(const uint8_t H_bytes[16], s H4.store_le(&H_pow[6]); } -void BOTAN_FN_ISA_CLMUL GHASH::ghash_multiply_cpu(uint8_t x[16], - secure_vector& H_pow, - const uint8_t input[], - size_t blocks) { +template +void BOTAN_FN_ISA_CLMUL +multiply_clmul(uint8_t x[16], secure_vector& H_pow, const uint8_t input[], size_t blocks) { BOTAN_ASSERT_NOMSG(H_pow.size() == 2 * 4 || H_pow.size() == 2 * 8); const SIMD_4x32 H1 = SIMD_4x32::load_le(&H_pow[0]); // NOLINT(*-container-data-pointer) - SIMD_4x32 a = reverse_vector(SIMD_4x32::load_le(x)); + SIMD_4x32 a = load_block(x); if(blocks >= 8) { const SIMD_4x32 H2 = SIMD_4x32::load_le(&H_pow[2]); @@ -125,14 +125,14 @@ void BOTAN_FN_ISA_CLMUL GHASH::ghash_multiply_cpu(uint8_t x[16], const SIMD_4x32 H8 = SIMD_4x32::load_le(&H_pow[14]); while(blocks >= 8) { - const SIMD_4x32 m0 = reverse_vector(SIMD_4x32::load_le(input)); - const SIMD_4x32 m1 = reverse_vector(SIMD_4x32::load_le(input + 16 * 1)); - const SIMD_4x32 m2 = reverse_vector(SIMD_4x32::load_le(input + 16 * 2)); - const SIMD_4x32 m3 = reverse_vector(SIMD_4x32::load_le(input + 16 * 3)); - const SIMD_4x32 m4 = reverse_vector(SIMD_4x32::load_le(input + 16 * 4)); - const SIMD_4x32 m5 = reverse_vector(SIMD_4x32::load_le(input + 16 * 5)); - const SIMD_4x32 m6 = reverse_vector(SIMD_4x32::load_le(input + 16 * 6)); - const SIMD_4x32 m7 = reverse_vector(SIMD_4x32::load_le(input + 16 * 7)); + const SIMD_4x32 m0 = load_block(input); + const SIMD_4x32 m1 = load_block(input + 16 * 1); + const SIMD_4x32 m2 = load_block(input + 16 * 2); + const SIMD_4x32 m3 = load_block(input + 16 * 3); + const SIMD_4x32 m4 = load_block(input + 16 * 4); + const SIMD_4x32 m5 = load_block(input + 16 * 5); + const SIMD_4x32 m6 = load_block(input + 16 * 6); + const SIMD_4x32 m7 = load_block(input + 16 * 7); a = polyval_multiply_x8(H1, H2, H3, H4, H5, H6, H7, H8, m7, m6, m5, m4, m3, m2, m1, m0 ^ a); @@ -147,10 +147,10 @@ void BOTAN_FN_ISA_CLMUL GHASH::ghash_multiply_cpu(uint8_t x[16], const SIMD_4x32 H4 = SIMD_4x32::load_le(&H_pow[6]); while(blocks >= 4) { - const SIMD_4x32 m0 = reverse_vector(SIMD_4x32::load_le(input)); - const SIMD_4x32 m1 = reverse_vector(SIMD_4x32::load_le(input + 16 * 1)); - const SIMD_4x32 m2 = reverse_vector(SIMD_4x32::load_le(input + 16 * 2)); - const SIMD_4x32 m3 = reverse_vector(SIMD_4x32::load_le(input + 16 * 3)); + const SIMD_4x32 m0 = load_block(input); + const SIMD_4x32 m1 = load_block(input + 16 * 1); + const SIMD_4x32 m2 = load_block(input + 16 * 2); + const SIMD_4x32 m3 = load_block(input + 16 * 3); a ^= m0; a = polyval_multiply_x4(H1, H2, H3, H4, m3, m2, m1, a); @@ -161,14 +161,41 @@ void BOTAN_FN_ISA_CLMUL GHASH::ghash_multiply_cpu(uint8_t x[16], } for(size_t i = 0; i != blocks; ++i) { - const SIMD_4x32 m = reverse_vector(SIMD_4x32::load_le(input + 16 * i)); + const SIMD_4x32 m = load_block(input + 16 * i); a ^= m; a = polyval_multiply(H1, a); } - a = reverse_vector(a); - a.store_le(x); + store_block(a, x); +} + +} // namespace + +void BOTAN_FN_ISA_CLMUL GHASH::ghash_precompute_cpu(const uint8_t H_bytes[16], secure_vector& H_pow) { + precompute_clmul(mulx_polyval(reverse_vector(SIMD_4x32::load_le(H_bytes))), H_pow); } +void BOTAN_FN_ISA_CLMUL GHASH::ghash_multiply_cpu(uint8_t x[16], + secure_vector& H_pow, + const uint8_t input[], + size_t blocks) { + multiply_clmul(x, H_pow, input, blocks); +} + +#if defined(BOTAN_HAS_POLYVAL) + +void BOTAN_FN_ISA_CLMUL Polyval::polyval_precompute_cpu(const uint8_t H[16], secure_vector& H_pow) { + precompute_clmul(SIMD_4x32::load_le(H), H_pow); +} + +void BOTAN_FN_ISA_CLMUL Polyval::polyval_multiply_cpu(uint8_t x[16], + secure_vector& H_pow, + const uint8_t input[], + size_t blocks) { + multiply_clmul(x, H_pow, input, blocks); +} + +#endif + } // namespace Botan diff --git a/src/lib/utils/ghash/ghash_cpu/polyval_fn.h b/src/lib/utils/ghash/ghash_cpu/polyval_fn.h index f38a431e755..14a1992c3b9 100644 --- a/src/lib/utils/ghash/ghash_cpu/polyval_fn.h +++ b/src/lib/utils/ghash/ghash_cpu/polyval_fn.h @@ -89,6 +89,28 @@ BOTAN_FORCE_INLINE BOTAN_FN_ISA_CLMUL SIMD_4x32 clmul(const SIMD_4x32& H, const // NOLINTEND(portability-simd-intrinsics) +/** +* Load a block in the reflected GHASH convention (BSWAP == true) or the +* natural POLYVAL convention (BSWAP == false) +*/ +template +BOTAN_FORCE_INLINE BOTAN_FN_ISA_SIMD_4X32 SIMD_4x32 load_block(const uint8_t in[]) { + if constexpr(BSWAP) { + return reverse_vector(SIMD_4x32::load_le(in)); + } else { + return SIMD_4x32::load_le(in); + } +} + +template +BOTAN_FORCE_INLINE BOTAN_FN_ISA_SIMD_4X32 void store_block(const SIMD_4x32& b, uint8_t out[]) { + if constexpr(BSWAP) { + reverse_vector(b).store_le(out); + } else { + b.store_le(out); + } +} + BOTAN_FORCE_INLINE SIMD_4x32 BOTAN_FN_ISA_SIMD_4X32 mulx_polyval(const SIMD_4x32& h) { const auto V = SIMD_4x32(0x00000001, 0x00000000, 0x00000000, 0xc2000000); diff --git a/src/lib/utils/ghash/polyval/info.txt b/src/lib/utils/ghash/polyval/info.txt new file mode 100644 index 00000000000..247f05c1e83 --- /dev/null +++ b/src/lib/utils/ghash/polyval/info.txt @@ -0,0 +1,12 @@ + +POLYVAL -> 20260719 + + + +name -> "POLYVAL" +brief -> "POLYVAL universal hash (RFC 8452)" + + + +ghash + diff --git a/src/lib/utils/ghash/polyval/polyval.cpp b/src/lib/utils/ghash/polyval/polyval.cpp new file mode 100644 index 00000000000..db63de07150 --- /dev/null +++ b/src/lib/utils/ghash/polyval/polyval.cpp @@ -0,0 +1,182 @@ +/* +* POLYVAL hash function (RFC 8452) +* (C) 2026 Jack Lloyd +* +* Botan is released under the Simplified BSD License (see license.txt) +*/ + +#include + +#include +#include +#include + +#if defined(BOTAN_HAS_CPUID) + #include +#endif + +namespace Botan { + +namespace { + +std::array byte_reverse(std::span x) { + const auto w = load_le>(x); + return store_be(w[1], w[0]); +} + +} // namespace + +std::string Polyval::provider() const { +#if defined(BOTAN_HAS_GHASH_AVX512_CLMUL) + if(auto feat = CPUID::check(CPUID::Feature::AVX512_CLMUL)) { + return *feat; + } +#endif + +#if defined(BOTAN_HAS_GHASH_CLMUL_CPU) + if(auto feat = CPUID::check(CPUID::Feature::HW_CLMUL)) { + return *feat; + } +#endif + +#if defined(BOTAN_HAS_GHASH_CLMUL_VPERM) + if(auto feat = CPUID::check(CPUID::Feature::SIMD_4X32)) { + return *feat; + } +#endif + + return "base"; +} + +bool Polyval::has_keying_material() const { + return !m_HM.empty() || !m_H_pow.empty(); +} + +void Polyval::key_schedule(std::span key) { + m_state = {0}; + m_buffer.clear(); + + BOTAN_ASSERT_NOMSG(key.size() == BS); + +#if defined(BOTAN_HAS_GHASH_AVX512_CLMUL) + if(CPUID::has(CPUID::Feature::AVX512_CLMUL)) { + zap(m_HM); + if(m_H_pow.size() != 32) { + m_H_pow.resize(32); + } + polyval_precompute_avx512_clmul(key.data(), m_H_pow.data()); + return; + } +#endif + +#if defined(BOTAN_HAS_GHASH_CLMUL_CPU) + if(CPUID::has(CPUID::Feature::HW_CLMUL)) { + zap(m_HM); + polyval_precompute_cpu(key.data(), m_H_pow); + return; + } +#endif + + /* + The fallback reuses the GHASH tables, relying on RFC 8452 Section 3: + + "We note that POLYVAL(H, X_1, X_2, ...) is equal to + ByteReverse(GHASH(ByteReverse(H) * x, ByteReverse(X_1), + ByteReverse(X_2), ...)), where ByteReverse is a function that + reverses the order of 16 bytes." + */ + zap(m_H_pow); + auto H = load_le>(key.first()); + // Byte reversing the key swaps the words and bswaps each; then multiply + // by x in the GHASH convention, carrying out of the bottom bit + std::swap(H[0], H[1]); + const uint64_t R = 0xE100000000000000; + const uint64_t carry = CT::Mask::expand(H[1] & 1).if_set_return(R); + H[1] = (H[1] >> 1) | (H[0] << 63); + H[0] = (H[0] >> 1) ^ carry; + const auto Hx = store_be(H[0], H[1]); + GHASH::ghash_precompute_base(Hx, m_HM); +} + +void Polyval::update(std::span input) { + assert_key_material_set(); + BufferSlicer in(input); + while(!in.empty()) { + if(const auto one_block = m_buffer.handle_unaligned_data(in)) { + polyval_multiply(m_state, one_block.value(), 1); + } + + if(m_buffer.in_alignment()) { + const auto [aligned_data, full_blocks] = m_buffer.aligned_data_to_process(in); + if(full_blocks > 0) { + polyval_multiply(m_state, aligned_data, full_blocks); + } + } + } + BOTAN_ASSERT_NOMSG(in.empty()); +} + +void Polyval::zero_pad() { + if(!m_buffer.in_alignment()) { + m_buffer.fill_up_with_zeros(); + polyval_multiply(m_state, m_buffer.consume(), 1); + } +} + +void Polyval::final(std::span out) { + assert_key_material_set(); + BOTAN_STATE_CHECK(m_buffer.in_alignment()); + + if(m_H_pow.empty()) { + // Fallback path; the state is in the GHASH byte order + copy_mem(out, byte_reverse(m_state)); + } else { + copy_mem(out, m_state); + } + + secure_scrub_memory(m_state); +} + +void Polyval::clear() { + zap(m_HM); + zap(m_H_pow); + secure_scrub_memory(m_state); + m_buffer.clear(); +} + +void Polyval::polyval_multiply(std::span x, std::span input, size_t blocks) { + BOTAN_ASSERT_NOMSG(input.size() % BS == 0); + +#if defined(BOTAN_HAS_GHASH_AVX512_CLMUL) + if(CPUID::has(CPUID::Feature::AVX512_CLMUL)) { + BOTAN_ASSERT_NOMSG(m_H_pow.size() == 32); + return polyval_multiply_avx512_clmul(x.data(), m_H_pow.data(), input.data(), blocks); + } +#endif + +#if defined(BOTAN_HAS_GHASH_CLMUL_CPU) + if(CPUID::has(CPUID::Feature::HW_CLMUL)) { + BOTAN_ASSERT_NOMSG(!m_H_pow.empty()); + return polyval_multiply_cpu(x.data(), m_H_pow, input.data(), blocks); + } +#endif + + // Fallback via GHASH (see key_schedule); each input block is byte + // reversed, and the state is maintained in the GHASH byte order + BufferSlicer in(input); + for(size_t b = 0; b != blocks; ++b) { + const auto rev = byte_reverse(in.take()); + +#if defined(BOTAN_HAS_GHASH_CLMUL_VPERM) + if(CPUID::has(CPUID::Feature::SIMD_2X64)) { + BOTAN_ASSERT_NOMSG(!m_HM.empty()); + GHASH::ghash_multiply_vperm(x.data(), m_HM.data(), rev.data(), 1); + continue; + } +#endif + + GHASH::ghash_multiply_base(x, m_HM, rev, 1); + } +} + +} // namespace Botan diff --git a/src/lib/utils/ghash/polyval/polyval.h b/src/lib/utils/ghash/polyval/polyval.h new file mode 100644 index 00000000000..365df37e163 --- /dev/null +++ b/src/lib/utils/ghash/polyval/polyval.h @@ -0,0 +1,78 @@ +/* +* (C) 2026 Jack Lloyd +* +* Botan is released under the Simplified BSD License (see license.txt) +*/ + +#ifndef BOTAN_POLYVAL_H_ +#define BOTAN_POLYVAL_H_ + +#include +#include + +namespace Botan { + +/** +* POLYVAL universal hash (RFC 8452), used by AES-GCM-SIV +* +* This is a not a secure MAC; it must only be used as a component of a +* construction (like GCM-SIV) which encrypts its output. +*/ +class BOTAN_TEST_API Polyval final : public SymmetricAlgorithm { + private: + static constexpr size_t BS = 16; + + public: + void update(std::span input); + + /// Zero pad the input to a multiple of the block size + void zero_pad(); + + /// Write the current state to out, and reset the state + void final(std::span out); + + Key_Length_Specification key_spec() const override { return Key_Length_Specification(BS); } + + bool has_keying_material() const override; + + void clear() override; + + std::string name() const override { return "Polyval"; } + + std::string provider() const; + + private: + void key_schedule(std::span key) override; + + void polyval_multiply(std::span x, std::span input, size_t blocks); + +#if defined(BOTAN_HAS_GHASH_CLMUL_CPU) + static void polyval_precompute_cpu(const uint8_t H[16], secure_vector& H_pow); + + static void polyval_multiply_cpu(uint8_t x[16], + secure_vector& H_pow, + const uint8_t input[], + size_t blocks); +#endif + +#if defined(BOTAN_HAS_GHASH_AVX512_CLMUL) + static void polyval_precompute_avx512_clmul(const uint8_t H[16], uint64_t H_pow[16 * 2]); + + static void polyval_multiply_avx512_clmul(uint8_t x[16], + const uint64_t H_pow[16 * 2], + const uint8_t input[], + size_t blocks); +#endif + + private: + AlignmentBuffer m_buffer; + + /// hash state; in the GHASH byte order if the fallback path is in use + std::array m_state{}; + secure_vector m_HM; + secure_vector m_H_pow; +}; + +} // namespace Botan + +#endif diff --git a/src/scripts/wycheproof.py b/src/scripts/wycheproof.py index 90d2085d4bb..dde7260c933 100755 --- a/src/scripts/wycheproof.py +++ b/src/scripts/wycheproof.py @@ -382,6 +382,10 @@ def _aead_algorithm( return f"AES-{key_size_bits // 2}/SIV" if algorithm == "AES-EAX": return f"AES-{key_size_bits}/EAX" + if algorithm == "AES-GCM-SIV": + if tag_size_bits is not None and tag_size_bits != 128: + raise ValueError(f"AES-GCM-SIV requires a 128-bit tag not {tag_size_bits}") + return f"AES-{key_size_bits}/GCM-SIV" if algorithm in ("CHACHA20-POLY1305", "XCHACHA20-POLY1305"): return "ChaCha20Poly1305" @@ -415,6 +419,7 @@ def _aead_process( @register( "AES-GCM", + "AES-GCM-SIV", "AES-CCM", "AES-EAX", "AEAD-AES-SIV-CMAC", @@ -1756,7 +1761,6 @@ def handle_primality(_data: dict, _group: dict, test: dict) -> None: _registry.ignore( "AES-FF1", # Not implemented - "AES-GCM-SIV", # Not implemented "A128CBC-HS256", # Not implemented "A192CBC-HS384", # Not implemented "A256CBC-HS512", # Not implemented diff --git a/src/tests/data/aead/gcm.vec b/src/tests/data/aead/gcm.vec index 6d3b6b7f2b0..9c3e3948057 100644 --- a/src/tests/data/aead/gcm.vec +++ b/src/tests/data/aead/gcm.vec @@ -1,5 +1,5 @@ -#test cpuid aesni clmul pmull ssse3 simd128 +#test cpuid aesni clmul armv8pmull ssse3 simd128 [AES-128/GCM] # Nist | Test Case 1 diff --git a/src/tests/data/aead/gcm_siv.vec b/src/tests/data/aead/gcm_siv.vec new file mode 100644 index 00000000000..380ba6b5711 --- /dev/null +++ b/src/tests/data/aead/gcm_siv.vec @@ -0,0 +1,473 @@ +#test cpuid avx512_clmul clmul pmull aesni ssse3 simd128 sse2 + +[AES-128/GCM-SIV] + +# Test vectors from RFC 8452 Appendix C + +Key = 01000000000000000000000000000000 +Nonce = 030000000000000000000000 +In = +Out = DC20E2D83F25705BB49E439ECA56DE25 + +Key = 01000000000000000000000000000000 +Nonce = 030000000000000000000000 +In = 0100000000000000 +Out = B5D839330AC7B786578782FFF6013B815B287C22493A364C + +Key = 01000000000000000000000000000000 +Nonce = 030000000000000000000000 +In = 010000000000000000000000 +Out = 7323EA61D05932260047D942A4978DB357391A0BC4FDEC8B0D106639 + +Key = 01000000000000000000000000000000 +Nonce = 030000000000000000000000 +In = 01000000000000000000000000000000 +Out = 743F7C8077AB25F8624E2E948579CF77303AAF90F6FE21199C6068577437A0C4 + +Key = 01000000000000000000000000000000 +Nonce = 030000000000000000000000 +In = 0100000000000000000000000000000002000000000000000000000000000000 +Out = 84E07E62BA83A6585417245D7EC413A9FE427D6315C09B57CE45F2E3936A94451A8E45DCD4578C667CD86847BF6155FF + +Key = 01000000000000000000000000000000 +Nonce = 030000000000000000000000 +In = 010000000000000000000000000000000200000000000000000000000000000003000000000000000000000000000000 +Out = 3FD24CE1F5A67B75BF2351F181A475C7B800A5B4D3DCF70106B1EEA82FA1D64DF42BF7226122FA92E17A40EEAAC1201B5E6E311DBF395D35B0FE39C2714388F8 + +Key = 01000000000000000000000000000000 +Nonce = 030000000000000000000000 +In = 01000000000000000000000000000000020000000000000000000000000000000300000000000000000000000000000004000000000000000000000000000000 +Out = 2433668F1058190F6D43E360F4F35CD8E475127CFCA7028EA8AB5C20F7AB2AF02516A2BDCBC08D521BE37FF28C152BBA36697F25B4CD169C6590D1DD39566D3F8A263DD317AA88D56BDF3936DBA75BB8 + +Key = 01000000000000000000000000000000 +Nonce = 030000000000000000000000 +In = 0200000000000000 +AD = 01 +Out = 1E6DABA35669F4273B0A1A2560969CDF790D99759ABD1508 + +Key = 01000000000000000000000000000000 +Nonce = 030000000000000000000000 +In = 020000000000000000000000 +AD = 01 +Out = 296C7889FD99F41917F4462008299C5102745AAA3A0C469FAD9E075A + +Key = 01000000000000000000000000000000 +Nonce = 030000000000000000000000 +In = 02000000000000000000000000000000 +AD = 01 +Out = E2B0C5DA79A901C1745F700525CB335B8F8936EC039E4E4BB97EBD8C4457441F + +Key = 01000000000000000000000000000000 +Nonce = 030000000000000000000000 +In = 0200000000000000000000000000000003000000000000000000000000000000 +AD = 01 +Out = 620048EF3C1E73E57E02BB8562C416A319E73E4CAAC8E96A1ECB2933145A1D71E6AF6A7F87287DA059A71684ED3498E1 + +Key = 01000000000000000000000000000000 +Nonce = 030000000000000000000000 +In = 020000000000000000000000000000000300000000000000000000000000000004000000000000000000000000000000 +AD = 01 +Out = 50C8303EA93925D64090D07BD109DFD9515A5A33431019C17D93465999A8B0053201D723120A8562B838CDFF25BF9D1E6A8CC3865F76897C2E4B245CF31C51F2 + +Key = 01000000000000000000000000000000 +Nonce = 030000000000000000000000 +In = 02000000000000000000000000000000030000000000000000000000000000000400000000000000000000000000000005000000000000000000000000000000 +AD = 01 +Out = 2F5C64059DB55EE0FB847ED513003746ACA4E61C711B5DE2E7A77FFD02DA42FEEC601910D3467BB8B36EBBAEBCE5FBA30D36C95F48A3E7980F0E7AC299332A80CDC46AE475563DE037001EF84AE21744 + +Key = 01000000000000000000000000000000 +Nonce = 030000000000000000000000 +In = 02000000 +AD = 010000000000000000000000 +Out = A8FE3E8707EB1F84FB28F8CB73DE8E99E2F48A14 + +Key = 01000000000000000000000000000000 +Nonce = 030000000000000000000000 +In = 0300000000000000000000000000000004000000 +AD = 010000000000000000000000000000000200 +Out = 6BB0FECF5DED9B77F902C7D5DA236A4391DD029724AFC9805E976F451E6D87F6FE106514 + +Key = 01000000000000000000000000000000 +Nonce = 030000000000000000000000 +In = 030000000000000000000000000000000400 +AD = 0100000000000000000000000000000002000000 +Out = 44D0AAF6FB2F1F34ADD5E8064E83E12A2ADABFF9B2EF00FB47920CC72A0C0F13B9FD + +Key = E66021D5EB8E4F4066D4ADB9C33560E4 +Nonce = F46E44BB3DA0015C94F70887 +In = +Out = A4194B79071B01A87D65F706E3949578 + +Key = 36864200E0EAF5284D884A0E77D31646 +Nonce = BAE8E37FC83441B16034566B +In = 7A806C +AD = 46BB91C3C5 +Out = AF60EB711BD85BC1E4D3E0A462E074EEA428A8 + +Key = AEDB64A6C590BC84D1A5E269E4B47801 +Nonce = AFC0577E34699B9E671FDD4F +In = BDC66F146545 +AD = FC880C94A95198874296 +Out = BB93A3E34D3CD6A9C45545CFC11F03AD743DBA20F966 + +Key = D5CC1FD161320B6920CE07787F86743B +Nonce = 275D1AB32F6D1F0434D8848C +In = 1177441F195495860F +AD = 046787F3EA22C127AAF195D1894728 +Out = 4F37281F7AD12949D01D02FD0CD174C84FC5DAE2F60F52FD2B + +Key = B3FED1473C528B8426A582995929A149 +Nonce = 9E9AD8780C8D63D0AB4149C0 +In = 9F572C614B4745914474E7C7 +AD = C9882E5386FD9F92EC489C8FDE2BE2CF97E74E93 +Out = F54673C5DDF710C745641C8BC1DC2F871FB7561DA1286E655E24B7B0 + +Key = 2D4ED87DA44102952EF94B02B805249B +Nonce = AC80E6F61455BFAC8308A2D4 +In = 0D8C8451178082355C9E940FEA2F58 +AD = 2950A70D5A1DB2316FD568378DA107B52B0DA55210CC1C1B0A +Out = C9FF545E07B88A015F05B274540AA183B3449B9F39552DE99DC214A1190B0B + +Key = BDE3B2F204D1E9F8B06BC47F9745B3D1 +Nonce = AE06556FB6AA7890BEBC18FE +In = 6B3DB4DA3D57AA94842B9803A96E07FB6DE7 +AD = 1860F762EBFBD08284E421702DE0DE18BAA9C9596291B08466F37DE21C7F +Out = 6298B296E24E8CC35DCE0BED484B7F30D5803E377094F04709F64D7B985310A4DB84 + +Key = F901CFE8A69615A93FDF7A98CAD48179 +Nonce = 6245709FB18853F68D833640 +In = E42A3C02C25B64869E146D7B233987BDDFC240871D +AD = 7576F7028EC6EB5EA7E298342A94D4B202B370EF9768EC6561C4FE6B7E7296FA859C21 +Out = 391CC328D484A4F46406181BCD62EFD9B3EE197D052D15506C84A9EDD65E13E9D24A2A6E70 + +# Longer messages, generated with python-cryptography, to exercise +# the multi-block and precomputed key power paths + +Key = F112294EED35947CF3F84F37A758E535 +Nonce = 81D89774BE2ABA9AFBD0AAED +In = 29F375B4E367106D8ED5D6BA3CFA80456F3979310EBD263E1DDAA1B26884F75861 +Out = 4B72CA83B2BBC2EF96915D0C8EC0E36FE24DA21C6833E79FACB44AC3B1E2B6141D8AC15BF85FC805980D68B07672FF260A + +Key = 0E3630828D3862EFC13F5FE0FD71AFCE +Nonce = 4F5732E93FF5FDEA778AE6C2 +In = 2985678DE08CF0B17D3715C506066A61C4385F0695DD9EC36C6F486CE53551C50F +AD = 2CC0E95F001A8494B83113A4379AE4857491793F04 +Out = 15D816450BE16549AE14298F77595E7201E9340B4CA93F4348AD90B44FA7ED4AF86D92B904887F53A6D813CA24C937C826 + +Key = B4DECF89610034DB9165400B1118EDEA +Nonce = BF5BFA9A157BDAB85F402EE7 +In = 6E4FEC8B9429C62ED6804B8FFFBA55FB7E2DF8589AB4B3349757543FCC7AD7B77F9860957E87AF358F78551D55FFB40511A68C0216ED3595B3C2A1D3F3C87524 +Out = B0C4DA69B1BB24D8BAB787F836718DEA4ABF38E1DC4E8B16704DF07E67C753A4FCDD5551E27D623E3E445183C658505C489BAB7202B311FDB644CA8CAA1FA38C2416B5ABE82E61173BCA1AD4F2895EFB + +Key = 1F681808679BF9E392478CA40EA3A6B6 +Nonce = D8705F69AE95D07F8B1B6545 +In = D80F2D0AA410CA68E5EDEEDED2CDFBDDD307923DB8D92FC64B215267828E322D63EFB9F3FE4EA9FD4482AF7E6CAFFBBF53DBE9B0382AF72EFB161026F5B55BF3 +AD = 608F650844E97067BB6FB8462EF1F15DFC7F3698B1 +Out = 69B2D063B23DCDEBF7CDCEC38F2995AC44E80EAA5E0A91F313DBD7DAB309BB0ADF7B87569BDC7945FFDC0C2D46CC8C074FA7E0B004AD755A27C2AF6062156A4B41FB83A263225CBCFD776A19013D9BBA + +Key = 3F11ED25286539F4D5B6B8B068A591CD +Nonce = 01706A0064A537C475448192 +In = 5BB6B7D5AE6026E1A64C0B79AAA4F2DC1F49737A67D54BA4EA8F91EE4FBE65BEEF10ADC6435DC30B4FF2C2BCCF399ACDB264FC7955CED4EF10C87CC9A737D569CBB1E21FE2BB984F6A2FCB1B2931C72A7C9475DC72C18A3E157F6C4D037BFE56AC391EC90DD372807AED2649E0E79D085AD6B6CF4F5F438A41EF02F9D43049 +Out = 5D72B3615783223609B458C2F59C64F87B169346E78535053C10EB608CC357EC73B455BE0D4FB7EADD5FE019DE3F7EB9B2166CECBD416A9C848A8CE765C76C3F4FED140BB1ED48CBBBD4199D3E0ED25904545D2BF9E95D43558A97631C49420C690872F7431DF2B77528D97C1BBF20D092D9CD4A47511323E380088FFE26DC92D26A985598C8BBDBC4301588ED4F68 + +Key = 063ACC6D98D8630441586494171BEAA7 +Nonce = CCA7CCF58726319A796A98E9 +In = 60B6C279E862B12ED0F5A0898A487EC2182B647C0795294AA481D709E4DECB2BF2231C3F23D824C7980BA91921A15DACE9853D981654DC8B5FCBB2D89DD560AFF73369F3321BF404DD78EC85B1059B89E0FF18B0DCBCD97F372AA215DA0D77626D01784F3FFC9C91A849D2D6CDE08E2E84B13AC3346CA12734C97D852EB6A9 +AD = 24B24CF9DA5720DD4177F63E13C64B21BD7140E830 +Out = A87C4D7888A4A0F9D09780359FF1E38515CAA2D7E98FF0375154A982C10C6779D5F16E50240E0517DF96DC72429C6D81034E4B0EAA17F61C3CAC88E33E70F49279272B0C60AB67656079FEA37F2634CD2CE6076C4AF3F0FB2E61EC946327C7BD404BD7A0D9826010DCBF3C70E544B8F0685A661C76BB6A2A7F394D5C91A24D6DA519327F1E3FBA77FB78031598DA76 + +Key = 0F3C03D19D564012B7760065A8C3D093 +Nonce = 62FE2F55B59E54A31D3E1111 +In = F6FE49A624A46D02637B6CEECBD8E6D8854CA67E7755CD1FE340D17FBCDF11AB4D749340E473B00EAF1184744247AC6CEC9E3667C2A21AFA14799DCDAC106AADFA4521C6722B0E8989FFA79891A12C777EEEFE735FF87123F1A0E92B0A1CC2AE31D3E6710B5CD5091C05FEB8A0C0F3E0043682C3DC8F8D94B0FB30E9FE6E4CCB +Out = 8ADA97695839A7D4F641BB9D79FCA2C6DB287FDA743122D8EF2CFC8A8587D5D54629264942676257017041D68152C3A4A943F86BC28FCDAA3E78B0873350F0DD02CEAD9B432F2BB5BC5FE22D846ADC7BFB768F841546C1216492AFB46FEF2D4AAA13D34B0CF2C2765144850D6DFD90DCEA150BB7CFB181675373EC8F7267C00515BB0A577392878D9DA8C7A4D208AE4E + +Key = 085134584A7CE669606DED60CA484E1F +Nonce = 143FF8BFC21F6265C037E1C5 +In = 5FD61D4A7BF6B9C2F64E37E260AB8CFF6282FC064CCDE21CB7C7B520427E58EBC11D0727C9E8B00AD9143AFB41A47755010D3990C076C107CDDD85AC98822C5343DF7FFCDB057422DD8F6BBCDB47E051E47CC9095BD635E2C1448E2EAC96F61113F3F55EDF1AEEEA74B263BAF31AB47E3E4CEA725C2B362374F7DF5EEBD88728 +AD = 5558307D4A8616DBADA80CB870D80D2174821FB4F9 +Out = EA475DF02AA70EB253BB002D34C98DB41C7209806229677164F413C91AF3C2936FD37472A11013E6701AA5984785DC6EAD4501FAA7D22A65E06C358F662031ED1C6AA58C215299290DAF35D562CC400012A3B5E24D3FF3090E727E5360F4CB54FBE48C30C82B71111B305C4BCABFFA85F87886A95BA63E64169FAC0C2F10FA467120498FDFE535681E588BAEA034F185 + +Key = 5C3DD5E0290DB1E2DD25FB947B602B62 +Nonce = 30C2E6DB5B5D68DB48E96176 +In = 193F8D6F69A9C33D54D575C59D0F5F0E3F9FACF0AC136E2D1D693358884211C033A04AAD875FF5FB6DFAAD0A68C05712FB3DE29984875D617B3D0D552D9E05F4A38558D5FA909C3B889DBC642A6D168AEF94105FFF8C8E5F8713882EC65430CD3245E651EFE93AB58A798BB9FA3FF37D6142D4E5D2EA617E269E2F39321581509556E5CEE3D290A241058D70CAF8E7B6838EC3E5680C5407D2B0E4D3AF03D637754CD134F2008A124955135FC38E433AE0B2125B3F89265224B0313BBE9738781FB892AD79B127C556EF8C36B373EA52B320DC6FB8CC902DCC932DD1B2615D908506206ABA92AE18C36377656E9BAD09E52AFBCE853FB9E2EF61FA76A4CB8499 +Out = F395BF60838C7CE06E100485C372093C8A865A253D1225AA910DC2567D3C9ECEA20F6B7A3B7BBAE683FF3247E813567A0B96A0AF0D99BDC1493A00C9E02FC16F610B57CC5BD9898BB555404452C3B8128B8AD5127DE109B1B1AA6E5B85DB0C01725E03FF5F187CBBEEA69202E70F8A61D55C29ED16C3FC305A29F2F842A2FD47EFCEAA24C476BA9B21BF0DA304F932BC967CD557DE6BE2019766BD3E78CFAFBC37158E317DC1D9F96FB825B73A3B5FC4EDB43202DD03D9E9F5B6BBF4CB438772FD7409F837962D5DFA8987667DAA8AE13FB5279E2026CBA78C339509601562A7305F1AC51D921BD48BD60C99BC2533FB343C368094B32AF8B03D19A24F96037AC15ED5CE5B5988A50E47DB139E5BA26F + +Key = 1B630E87BF49B08D7BB997A9458D630A +Nonce = 169995DD9A0B501343E3F3A4 +In = 697C5FBB69334A1EBA5C919F57C393919B37E7E42199EC03B1D553F88CD1DAA231B0CD39B95F4A91BE4F3718EBE6C8F47499B32DD3D072C7FED84450114F2F35AB3AE28204782CA78C1A2CEBBE62F840804B9BA8E108A3CFEC1077A45676E90B90BC38A42859FCA2D0603EE5DBBB224F57BEC15DD186034C9FCBAED684F778EB2477F472F6FE8A30BFC380FBDFC4117CE629D7FFEE698F044E822E2BE2DDB387C6DFE2A29F09F487DB3D3EBE14AD616E1553A3197275722AD9BD1192D67C64DCC32F8D5BF7EA87190951958251EAE6BF5E6D1169F313D30CADCA7AD25F97F82DFFD8D9850888C47F31296029B15A1D7A06E7BAFD7C82EDEA4A1FB4C97DF27339 +AD = E027E76EAFF51D81D32F7AE5512D7EE60AF54511B9 +Out = 4796C154D9909FA8086CCA2939250457C4FA40FA502AB065A4B56C63C5D98043ECF3DC54ABD90BF74BB44C7407DA2C14FC9B9722FAF291D042CEA73F980DE242DD1C20823089C001D050DBB87F25057B7DAEB3F6664A5C2FD8A48D1AC95DA0A832DE0ED07B3D6ED562A586D1092251BA9DF5473674B4FE23D90DE8A04A0D4717E6FF639152E4B7FEF19B577941E3DB94851B327E3F0B8B16BBFCADC88CCE46565E13CEEEA983E71653FAF9C6C347CFB3558AB25F6A279851803FF83B92F55DDCEC79B2BD87ACD97889E8C5BA7B7FE06AF00954120A8BA4578D2AFA27435104DD568C36B66EFFC1392B37A863669E37C74676D5A8167A1C48CA99CE1FE852A2C421C1DD32D33592EACDE4FDE73B2B480D + +Key = 330A49E238C87368FABC8C98DDBA5F21 +Nonce = 968D0765F71D057B1FBE3A2C +In = 375F99515299DFDD4A71EE1D2EA908C58BC8B4B562B0DFA7E07C68F2ED5112946EE905B9743DCD26C873A97F93AD141243D46C71518C946BC0726C7287731426324C254A47903951A70DAD39FAB001D84FB6F674EBAC59A9A200CA8A3EA9226F8B7BF12D049357A9FE49CF317B2964ECA733B09E1FA2E9898BBAF095D5296E091A4358BA4F16305DA6C73907CC0EA87BFB6433D27D01FC0259EDBC27FE55BC73F12CB6D7683BC224490AED298655498194036FBD34D668190BCEC7ACFE76814DDF6DB6EC589D34A5A2CFDC9AEBF4E88883E056E0076F875BB8AAC657A4F945BB0660351B018E12B3F0E3E0E9FA559CA79971DA53CA350463008FEB82F5638841584CF8113AC38BCB3DCBA277B300690B +Out = 45472D88AD3BA142743B69B2CD8A78D5D86265A0AECD664397C33AB9C4D642C5BCC0D222D34F0CC89C2B34258E723BC10D4FDDFF06940F19571B1EB8CA1E1D02D849A597A97E7E66F75C6A3D002C9A808DFE584DAEF178A76A2829F0BA6B05F4FD3CAAD80D9C467B3F2F9D16FDC9A8D769B7FD050DE60CC6327014D2E8389BF054F1A314FC9E49621FE2A93832673DE67C5FDD33A99C9A5173A37B0A7A135B47B9740CCAF35D8111E7098F518C7E567A15BE32A6777933FE2A5D03247C1060079162A737C5CB209AC9FB7B050E213084748A85671CFA709205E69F5FCC4EE430F5B4EE19EFB221F150B81916EECD1090C493A441E3E826BF23017C7B9C63AFA7007CB83C3178FC2BF08B0B997AD4712D941AEAA65C06631AEF710D1DC6C770AE + +Key = 5D6822E591ABF0A5A96D2EBCE4DB9100 +Nonce = 82B26C064954AE06A2880825 +In = E399273919A00FAABEF569787698454A9B5631FB10F55CE065E7E49FC62FE2C288A461FD8F52102A9A33D6770935DB0514175E65342646F9EC7BA879A3B53CF17B6CA2401EA3219061C2E07DAE5B309EFB2E1977DB5A556DD8D3B5F94CF837614612EACBE485A9430CA583E7E3C6F08771C154D2F3E5C679C3C2446D84021530CACFA509021B09527B3FB95786669E5080FA2874A9A16E929136A89A1E38D0F4C78AE5D10546CACA18B3629B69455356F4304139A6717A5285661027357B09A2BCA94147095F276651EB240C4D8273796AAC00AA6D3E97DD83B342D8FAA6839245A47C478F159B1A63C51C81DB34B836381FD2CC77F841551F1D0DC62B3530364833E8D592BD20A1E6CFC57A284CBDF9 +AD = 50B579614F5EA0E58B58B8025B62FDB283023FF4ED +Out = 48B2EF4F4282A6D521929233B1B5A2183238FD9D96497723A429D3109F7EEE918A7AD27C2030DEF84352CABA3E6FC108CE757967535426258F08A7A9B80836687EDAF3106313DCAF909728D58F4CEA424F3DFB9C4F38D50976D6403535B00C2F9797504AD7EC87FA0C62509740F9377E14C2177F05CF5D2078E327E07D7658FB9FE3CE78D3C1A14C9FE9C0095D6B19E17E87F098F254B7A700C5FBC86AE92A03071EF6CA6F82C79CA35CD88F12288806A9AE2699A2BF88DA9EE4391C89489DFD4E1CBA08DAA0D301FC607F568EC40837515C94B38BAB09B479BFDFE36DA7410995E23916EAC6F22084ED60FA3C8EE3999CBC1ECAE72D9C56B2817205920F0FC831A437F3E240CDC246957C484755B6E53385DB77C46679259F812FB9F3E2B392 + +Key = 0F309FD434547ABD270C9F919A924C7A +Nonce = 22A0C7648CCD81356C9932B7 +In = D53AAF200306706B09295BACA9525FD694F18A8F9E2B3F869F6C93193EC26264E426D780DD68C48CAA3999BDC227C36BEB84F0F408DA62E286B4D5F3DB09357BFAA0CAF089C4632F3E94F428D748A9F7875FF4BD5C7120DCFFC87E01786C43E2D1C4BFB8434A2EDD393D2E69478005F38381900F26F1AAC9F9E738399915E477124837112DAF79FE4C5FDF3F5C1F23D7011200D5A855818A3E5E9F1332E4BF6A322CDF969E854A8E9FCB45DB8EA474C07991CA0738302B796DF290F552DE050A7D553571D3B4B91513BFC5860F05B5075CD857D2BA9C34F3E5B8EDD4EB2D75FE5E33BD19B14608ADFE89D3250500BE4DCB862C3FD99C3A951744B3AFEF1F36AEE4DCFB698847FBA9D0D6054142285FF1D745F7DA5CF6AE1864B77055A0798618FAED1FFA09D29FC64EFE10A57E549F40357126FC353F7E76A6A755A48389C47EB8AA846B94BCD53BE480C69EC79DB26D31F584EC4EBA3BAF5F7AB6AE92E7D7B42EFB0ACCE3FC4D3713C0106C2AFC0F081300CA6DDFEBBC2CD0AE96EC75D6E257D01CF9256ADB013D079E74EABB487E9F33F2332E5277721DD07B0155B58D3054F8065CD65A07194AF33EF1EC79C47402DB7AF7F89A44C46F3CD95E489F7964194753DD92D75E7BB36DCC6F28E8FD445D4CCAE198CD2A3EE59294535E23AC46CDC1C331CBDFC201597B2063AFAD9A55D13F5C736FB7B69B5AF6B4515978DFA5688A +Out = 05BB01DBD20972D5CA1001E8797C7C8E288DA99130A93ECF20F183B404A967EF184F79EBC43DA5C03F62C0BFF67DE8A7892CCFB931CB2E311874C91F2267280064CE18B86033921D5EC92CDBF33DE8B678EA73DDFC716755B9BB262FD1499CDE68B5BA07E1441630ABF0361C13960D7F75981D6BC4760225EDE8C3ABAF33CEAD2B6A5878F7285ACBF5820323B0E0D6D7E12DCB26A3D2BC5B2A6781253A6A8C624EF258CFAA80BF42EE07464104F4F6FC41410F820B8805712310380CFCD3D7AED35B2742C74FDB571106AED653825554DA52A25B56BC72241A52DD5DF239F09565053D50E02838E9255D21958393718B42D4A89BF82F6BA507D5CA6D74A2C015F6FED2EDEE7A0FB94BF2781C19EF3FFD68694033D44F1903B74FB0887961059ED1B20B86DBE53901255B2F95E0DA966E1FE239707AC8D319498733F98AEFB50FD9DA557FAD55F4013C60E4733A5C314F2B6F1865608495CFF6CE8659D73BE624B0E5A516154A981FA5628AE56F2D08B18DD21FAF6DEDFAAD25CD4672AB4A8C6BF3F34EDCB416996699F0873D75DEAD94F6309D03B1EDB3420F1844519E1FDCFE4F08B3A190F4A6702E7C0FBEDE507733C93B907227B1D31C6BCD0511307C540BB21B90C8DBBBA37113A42AD1466AA06D24353FF1F116C40DCDD67DA92D27C4BACF05A954E119A442C3962E58DB9CF9C53AEFF5B23DD7941086F2A640DF431248EE411D82A1D29D377D1896EE9C0699CB54 + +Key = 2AD6F5C2B3FE0B8ECF475CEA13942B22 +Nonce = C74BE9F99325307A05CCB440 +In = 7D688170E6D2E3975AFBBB6D01C7AB272002C1375C70C63EAFF77EABC4730D46C33D1E52D63D550926B4FA829DA7242738BF22AE30BE18BDDDAE268BFEC6FD82115E2C6AC556F7DDDA3096A4B0D7588C515B01804492B77D4F8F279CA979B9924C8CE4B5E966ABA4E40F4A77C08A0D3C233EF4F5517BD80D5D0F71105D48FDA7B9A791FEFDBEF38BBA3853109F6786D3C5F8756A2301B415848BDD1648FE9DE25794C6C6A9CF464155923FAA635A76A84CED86670986C039B03198EB3CBD14AC61C7B99DD1B2CD8FC5EB3C749F814810B28AE95F7594CE65FC44B1FEEB814C583F70E64D0F269A187CEF1EEEABDE3479043C11EF2A4BFE4C3F42DF373CABFBEFFF037A6220E675DC4EF312E206D174F7C5111BBD3B6B96A246ECE44F60860B882F676ED166AF30D04E0C9079169C727E59FD243FEC607DAF0B8F96C2F67CE11137BA8D284CB08126B30C1BDD55E40C6D846D6E101162CAD8F9A542AC4221DA48C06450D9F0AC82A6E84BA2AAF2CAB38EFB6EDB603C762D4DEE69FC1A789D1DC208F50227E65B9B25DAE534BA6EF2C9A48313FE53D4B027EC9395505A4474890BE1C4AEF38C3FB3D9D1F2F78EDE7927302B64C0DB4CC2AA9A457EA916817783F4ED30554A5A4039E8240CC531B3ED189FC6EFE49F6DB758D5A4F2A4D8A84664722D13DA8D9D4729693B30D9B9241CF2FA92F517A893EFE341C4D343D69D8CAE1197 +AD = 2178F1DD2085F1F12B02489C1A9D3F41B11C65B1FF +Out = DBF4E469EE299D41558B65C31EA7BDD9C229FE9A297DA46BBC7E6F5DA653001E4E87CE23579AD5D18A44B41CB8EC8E42264DA296B49B58BC1024DF79AC27B52C2014A7D8292136A90155683014D0F70D387F304F4AA85E913075D147B3ABAB92D0D1B74345F70A2D23BB2379797A54EBDF82661ED89E61034ADDD6CFA47D08BB9D5999E51FA1F5932FDA6D53F66264A7677DC85CDC33D093C3FC25C04C50F9B54446DC85CCD7301655DD3B26A5E80FF06290BBCED086C9B81169CFD573BACCB35057476BDA3129225DB221319388709CA4C05022DF737B10F39A171D2397127195DFD365C4C0E4C5F80D260E36AB449B5D07A9DD6C4301011B7014EE6E7A7E5C4977E36F510E4E81F74687FCD4AE689E1E6A37D8426F1897FAF16C8A72932B54588B14FC1EBF0C4BD18272E09B29ABC381A5841D456D9F63EC6E71824204B1B55A42336647B6E5A6614FC9E947CB125798786232D551140BD1FBF9EEF08555D0DF09E4A61B691F5CAFF5C62A96592FF20F0775EC34CE87CCDEBDC2EA08B730DD17F233483C4259797B6609FDF826419C51CAE0C27A0D9C9215231674D4629F4E4B9AF05BC36A6940761E2AEEE17F2D12768B420F8BFBC5DA53FF69330E463709366BF9586FC0980EC32349A19C46AA4D5978341C43CA503878C7A453A393DB1D4EA2653A29DCE6F45621BA365C08E05540A06772107F637931D651ECD7F0C443967A5FC29EB3D4B9F7E4C4897E973D78A7 + +Key = 0F4F9151A004E768986F4088133A4A38 +Nonce = F2CB3797A29ED4228A4BAFBE +In = 8C866B78C7C3C15464C7286F93E0A806D5EC7DD43DC1444D385F42C46FBE3447BC6B45472660BC7C89DC4ED21B96EF8AE1E596F9F08E18A3463B90CC91F143D5A1CBB518E04A7BDB6C41C7A3674D7FDA526F3C3798957B7DBFBA6A792D664A16F8111381BD6E91402F509B455BB00B15B404967855131610FC8B3246B6E1DE442B5E05F4CEF4C49DFA1542DDDA10B0C21704C3B8EC6555A22B23989F7DC2F3C21190FC2A4AB76567C89F3E01EE8614D291343CEEF69205CAE4AA6B24BA8A4EB13475EB18B67A1267A8B0AF8B4ED09956A492B5A9A2B552437E5DE0C25D0F6B0DE6D97FCBE2A44A62CAACBBC60C351CA83A116D5C985E5BA9075909BC3DF3C4ED91210870BADA67A055920DDCBEF302B67E4126F79D1C6844177461C1C3D63143F42C448475783988F2225D30539100936FD4648536040F3E31AC791D5FE4535FD3EE7783B257BCE910531DBC1A17D4C3E21E1783CBC248C5EF8458E95B0FE81C4D691E20DB7B905966AA07B7B5ADC081EF2800A77C4DE8882B5F8D67ADBE9DB2CFD62C45D90158F9304A6074F534133B8417D55E1EA7D3034242226C32E2AFA70AD2A72E43ABC4A970DFBB26C9F6EFA3E5A2F1C8F61336C1817680F14F8B9093D827D6B5CE6261689C7176E109FE2AF6F17C9459637433AC74227CD14812269D670C5991D433A11917B2FFEFBA92D4A49DBEBC4862CBFB0980A63409795CC567E7F197155AF3C089B37DD4B0DC605CF6DF3BC5666A6A3BF805AD8080D0E9F79E71982079EFE15AD1737AF44209868D75E9FA63896EE557236C52F9F2B9EDEADD0BD1F80011143E9B2CDF672CDB5D5FA22C059DA3085C85E93CE6D1B260DEC38236C3883F91FF866B51981ADF0CF1AAC8DA52C2F269A6B24B920B7789310B4B43383AFF5F62DDF11F9048DB00B1DCBAB2BC43D26D051F8F4F8A3691BD12415D784529B6A8597592B5C501BA3FE825652A942B5D4A5DAC3ECBAC884734E9621486A0964A54567F03534D1B8569BD7C0B7F197E98865FC780090A50FF25EE120A12EF533FED9FEA94D1D8FB9B7BC76FE4F88D005DB2402A04AB3E984DEB61957F3402A9CD465AD3E5A03AC39428EDD9235189EA67BD5A40423F7A13F3B1E4F9957BCBE4CC7A8D222A6148FBF8C755F67D4ADB487EA01E438861DE1373E7D3424848020EFDFFB1EDC00475536439EF0E4608CC6E3795A9464B25F3F961710C14D55E5603F87E356909F12042758833D630BD4C8D3BBCB512B2F2029E47A815DEF5C065CA68EAECEF17FFD454B57412D315FC558CF37A806D8EED063DE391F6EF54A826A5D5A39D600C79E473F304DACA8C20C3B78D112AF85D54D8463DE005516988A42D51AC2892B55105377DE46BF269C74416B3F21F9D7174F842FF01656826F0997F752782A12E9AD2D344EA879C32FE3DC9A5A5465FA98BF624C1F61996D40D +Out = 30A0E58CFE04F3F8D5693FB6961DDEB99E4809E398BA2482E4DC995B6C67F9B81FA8B9C212004AF21D3CBD30385933189EC156715B1F83607F4EBD861E9004FC033A648913BA7FC6B1D5A78AA882E89725CD404F78343CDCD84EFE6400F957E32081DA3EFE20EE1565E8E6DB4887DAE208CD2A3BDF5883D4A80B7421A94F899B21C081CB1D6633D6B5B3E9D78C9E4E46638263D8EFC11C5B728E6C42486139E26310D44B306E528BBBE8E7867BC4D6153B8C35262A935CCD56FCF75B6EB4D856ED6F5F18126634BEAFA0517D8311C302E099FA7030E6C60F2F69DA2E92C2875C0FFD54CA0F16C46E74CB82762D1FDB1E18C18957A355B011A13E99B9AF3ED60569C829A4862551E60B98A547653BA498F0DDCE1AE1FA529E8AE4A4F82B55E7760D76C0E75F6C6795E5B401E36625DA23E7363D16FA5E2D2DC0FD2533DBEFD938326A8D56AEC69CC66E8783EE227CCDA7297463E7CF5875AAE2D8AECC08C8EC81F2422496AB20267F6E31706A1B4DF79D4EA50D9708ACCE678CD1B40B18D835C9B8E0976DB7FE1586AE67DFD0AEA255782EAE64A69E7C193B90A30A96D05BF20D9E04F89B24985C46F92D7E15FCEA3433E3AF7D19A3FC0803502EBC72DFA79AA8246552DC7D907126BDF008FC5843A36D0CE0958041A5415947AF7E20DD512D8F8BB6192A84AE0292995DCD32177CE7811F7E4B63CF66C9F8E547FE8EEBD17FF931C3D6A2CA1F2E6FF62913878D8AAE1BDC84A495A6B92BD55D44EF526D819CEA646A187B595AF3834CD96C9C34F120559C03FEE969176CABB5575028F63C0B10DD3243EDE711025F2467DC9FD9C5836753A3E1615AA7084600E039C67A8A93CD2471531D25607BA3F6C12B81CC22F5BFB5156E6982A3F4D989C7A6D807F55D8F9DF2457CD4F0E7BAE396B8DAE3236AE2893FB9D702974B9B28A01E50D67CDB88EFFB25296A4C0819617CBB660C8353A3AED9E9459260DA17419D138C623374E69E0CB1492CAC8C51B8690608E93C1AA32FB06F0D3996ACD52361310373C73F96C4A44E74DAAFFEE04363B410CD097CCBCCB8147030A0917C63E261BB75086F4DB602A8BF701D58579D90EA86CF0A511E5928D6613E84F553AF1E3488DB4F2289E8B33C8DB7E6EAAD8A1B57157BA9B4B79FAF734E50CD97B1E4B22B09A7E53ED7102A32770EC6FB88DB10799223A820504E25FB6C5BB3EE0F61A598D3B4C3F42B776A33A08013B8632401FA0B03E8B28A28C6507A204C025D14B0980A6A34217F6D5E8C7FC3E8945304F4D789A78FEE6DECD96E3576E16EC8F279E62C923B6BF071DDEA6BDA2FF57E7F8510D4CAD05134CCECBFE22E4913E2F8FE87DB8F24C3054C7A5E81CBA1623A497CC6C3F47E279B3AA09B7486128C6A72881B9D3DBA3CE203D8ADFD2E9CF79D2BE5F2BE9B3480D3785CB0A8454336094E5E244B34E2D72510394ECE1CF9BDD0D80882B9999D73E2 + +Key = ADA0535E6889CBB63C13850FD2AF3797 +Nonce = 77171BD3DC365786459EA691 +In = 5D2115E63B10429A83EA9C74F1A681488AC98FD7EB4E12B53D9B28986AC4536F041CF32453A18190D72534BAC69388E72282CA2F5359C2B8CE8E34206DD86DC5FDBA03AA7159C5A600965B1F2F080A7A99B79A2A7E9B4DAF64DE5C838868D9AD60C95F69DD12A40DB7EE0184FFFB306788520115F28073B1ADDB1697A1709232BCBF833DED119A6CBDC5890238F7410B5369DDF76B02EF762BF32D3D6ABFCFDB7067984E5F7C101E51F6423C23A1AC9C58FACE0F671D1787A7FF465C75D99309F531DFFEFE5C8A270ADBCFD1B08880C2AA1E4175A1278B565C4C512DC9250EA44093DFE121119BF41F5DDFA233DA28A70E8B39EA41A7B21BE738790EB0EE742AE13AE6396A35B685DC51894C0396C7A6632E5F0C18D15ABE065315E826E4748BAC83910CBE295EA884CFC42DE2EC9C3BD2E43C905DA677F2A1FC0518F10F1145BCBF348B0CF26C1EBD92CE665130F05DD1F0FBC217CAE5CC2806D7AF409CBB0796B954235C84F98ADCB5BDB24D56A69080EFAE7DA5915CFE697EAA5D1C33A9E3987539A16AB8AAD8D4DC81C757A2F4325B783458957F5002B0AA511A67B428E33C2ED6C38051A5CD9508685CD22D879A302E5590D1879B71C1C506BAEDC0B92787C311443AF964BAE9A64E976792FCDB889847DDD74D578F027F8DD70478C3C3D891FA189D920183F356FFBDD3C7FB01252E373BFC7581EA4E10C473055DF6C077851E853F407562DD770337D48CAB9CCECA693DDD05BD1A337ABAFC9D6909620F2858DD214CEB591097286B194EF29C140AE6F8ED059C86365C4D48434C63CE78412ECDA020EC79572B77D2902CFB4E151F4B83417CA4A22F27BF46B1F079C09ED3660FC78261201754D43A072D544301D3105941884B58FFFD465AF283A02FCBA495E0693E6B9399C3F74471CF5BFE4EDEC8DC31ECF2A1B8B0B025ADC7A149A754E2D2EE2AFE5E8A9C9C58AAACEE481412602C6D477025C154FF39917DD795AD893099B58F21A03F8AAEF290A591582F1EAC71A92F6C544E6A7D8D56A6E40BC7E3695154552324C58558E5EB1156E6DE7BF770CCD187836C241ACCC71778721FAE3F511676A7F94337AF6B5B1E7FA9B3DBFE4DEB6EC9B7DC7F9476C97CC17B79A79AB809CC915199DA6D486C90F8D721E4E54F451F1B44C8BFBDCA2FD615AE4D6EC92372F16D6881191A63D3EDA2921E85B0F7E18D275D262725E913187B40D6AB46FD14917A1DE75B414CFB36660F7066161755BD1309B7C5EC8522AEC160B150B5F20C602464DC377C11D3AEBD25BCEC05A7D6E22A734E05F10CBA63FD5669F4EA73DC2A9277084EE2C81EAFC3A9B19F342D60578E4ABCCEF394FCE43280B66BBC43D61D11B565A6992FC97577DB46010F13F5E16748DBCBCEDC488374E36B977E543FD757AC974942B1B2DAB424C70089FB85DEFC84F4822AD6E6B67ED5 +AD = 73E4DD57B2101D85E31F1080754465F00C5E61746D +Out = 324A5D1EB8650BC209D9C590DDA07BFEF71C1035D9740118DFA1FB0DE179B89F4ED17EA51F0A457CB568009C24051E18851D34490A00F72AF6FC93B7A0443F39A24C87A90BF5624C192E19A6C29FF2117DCD0B3E3D55B96AEB0501E774F0F28C56A6DE2FC45F7580C56687269652305E045564D81268E5CA19DBAE23FF590DBBE9A375047207400767FDDEB8AD813B82E0976C5829644214E0FC16FBB10118369AC9DD6224373E3338E42EE750809AAA9B619A57AFDBF14636AC65801B3CAE6B87336264D4E5429B18A053404E6C42AB0851D984215AE623017331A3628AB07B7258B808B95DC0EF79400F905F4F98DE783FEA50DC8F918789F5AB2C693AE8F543CF9DFFD07B4E45740A4D7A332E15AA95ED0CF0798DC0A39E6055713591378EB5832ABB9FBCE8033EC9E8EA5B9126BE5CCEE138C8F9E548A934F07C4EEE49D736EE81390F12FB56DDFD4D6B962863B2ED792DE7BE4D3322534604BEDC087389A50F439F6657A6C3BD2AF2A343A25292BA01293A7C942EBBFF5E6DBCDECC1CF0ED7A19021FE3FA9C75B120B61227EF30F8F94175A51F6636D40BABF3ACA4675A729C01A94ECC9979E1E714739546ABDEA5C95752ECA5EDAD8E71000A9BA8FCBE30C9CC7EC509D61C0C5388E231EFB5875C2D26D393650751FF1DABA490AA86D1DAEA3EB51572E7882F7DA01CC728C6F215E0FC37D1D34B9EEA9B7002782EC075459F26F8EF7111A8D5807AC049484A828E17A2854399C4A8BC6199A218DBB2B94BF08637F456540D3C6E11AED5BAE979E1F1908A4593A5A93DDA3B9B824EA9776C67373514945D985E15565912182C8CDC887331724406F0E6A48C81CF5421711D30B00E4A5F34047690E14C70BC2D60E34560BBB10C60BBA87F1CA691739B99CE05C1A36C24ED0865F49D82811F69D10CA99061D8F5261AAFAD94B29CECAA063957A3EC7E147EE2A0F087547D787C31465345646FDB80D464C90AE8E2B57C0EB13503B2BD01104D7DC4018373CCF8BCE5E8AF2A47E6DEB0EE7363421DC52F238091B6063C7F9A8D39E373ED580875E4898229C36C9BCE708E7522DD3C57545C1F52C930B337C851E6EE5462870A1509CD0AE5084475252E32C16DEB3804B095A0CD3856DEF1229B570DAD65754A8A4401B5E3BC4281F79C8E86C932429D0DE0E30B0F745C57747E8EE968EF4311878807C628AF0196EEFB627ECE91FB759EAEA6D1502FC73D27E11593603C3F140C71278C4DDC72FCEEAC96DD6AFB999113EE7C7BF77B4BE6C780F8CBF32ACC85A2F9A4540472FCDD0E22D12DA4B781B8178A0E46F8FCDE1F7D9E9FCD5FEA09E4A6419C92B6339B9544B8D5EFBFB03C3B0966B81E11462DA6DC27DC19579EB2D77B3AAC72CD987A662EB342D205CAEE13E7DEFC0A12BF0534E687A785F4901B5DBAC579DC20E64AB1B21FDA70AF3F7F28F908C059A2D0C419C3EB55DEDB6CAF24BF49 + +[AES-256/GCM-SIV] + +# Test vectors from RFC 8452 Appendix C + +Key = 0100000000000000000000000000000000000000000000000000000000000000 +Nonce = 030000000000000000000000 +In = +Out = 07F5F4169BBF55A8400CD47EA6FD400F + +Key = 0100000000000000000000000000000000000000000000000000000000000000 +Nonce = 030000000000000000000000 +In = 0100000000000000 +Out = C2EF328E5C71C83B843122130F7364B761E0B97427E3DF28 + +Key = 0100000000000000000000000000000000000000000000000000000000000000 +Nonce = 030000000000000000000000 +In = 010000000000000000000000 +Out = 9AAB2AEB3FAA0A34AEA8E2B18CA50DA9AE6559E48FD10F6E5C9CA17E + +Key = 0100000000000000000000000000000000000000000000000000000000000000 +Nonce = 030000000000000000000000 +In = 01000000000000000000000000000000 +Out = 85A01B63025BA19B7FD3DDFC033B3E76C9EAC6FA700942702E90862383C6C366 + +Key = 0100000000000000000000000000000000000000000000000000000000000000 +Nonce = 030000000000000000000000 +In = 0100000000000000000000000000000002000000000000000000000000000000 +Out = 4A6A9DB4C8C6549201B9EDB53006CBA821EC9CF850948A7C86C68AC7539D027FE819E63ABCD020B006A976397632EB5D + +Key = 0100000000000000000000000000000000000000000000000000000000000000 +Nonce = 030000000000000000000000 +In = 010000000000000000000000000000000200000000000000000000000000000003000000000000000000000000000000 +Out = C00D121893A9FA603F48CCC1CA3C57CE7499245EA0046DB16C53C7C66FE717E39CF6C748837B61F6EE3ADCEE17534ED5790BC96880A99BA804BD12C0E6A22CC4 + +Key = 0100000000000000000000000000000000000000000000000000000000000000 +Nonce = 030000000000000000000000 +In = 01000000000000000000000000000000020000000000000000000000000000000300000000000000000000000000000004000000000000000000000000000000 +Out = C2D5160A1F8683834910ACDAFC41FBB1632D4A353E8B905EC9A5499AC34F96C7E1049EB080883891A4DB8CAAA1F99DD004D80487540735234E3744512C6F90CE112864C269FC0D9D88C61FA47E39AA08 + +Key = 0100000000000000000000000000000000000000000000000000000000000000 +Nonce = 030000000000000000000000 +In = 0200000000000000 +AD = 01 +Out = 1DE22967237A813291213F267E3B452F02D01AE33E4EC854 + +Key = 0100000000000000000000000000000000000000000000000000000000000000 +Nonce = 030000000000000000000000 +In = 020000000000000000000000 +AD = 01 +Out = 163D6F9CC1B346CD453A2E4CC1A4A19AE800941CCDC57CC8413C277F + +Key = 0100000000000000000000000000000000000000000000000000000000000000 +Nonce = 030000000000000000000000 +In = 02000000000000000000000000000000 +AD = 01 +Out = C91545823CC24F17DBB0E9E807D5EC17B292D28FF61189E8E49F3875EF91AFF7 + +Key = 0100000000000000000000000000000000000000000000000000000000000000 +Nonce = 030000000000000000000000 +In = 0200000000000000000000000000000003000000000000000000000000000000 +AD = 01 +Out = 07DAD364BFC2B9DA89116D7BEF6DAAAF6F255510AA654F920AC81B94E8BAD365AEA1BAD12702E1965604374AAB96DBBC + +Key = 0100000000000000000000000000000000000000000000000000000000000000 +Nonce = 030000000000000000000000 +In = 020000000000000000000000000000000300000000000000000000000000000004000000000000000000000000000000 +AD = 01 +Out = C67A1F0F567A5198AA1FCC8E3F21314336F7F51CA8B1AF61FEAC35A86416FA47FBCA3B5F749CDF564527F2314F42FE2503332742B228C647173616CFD44C54EB + +Key = 0100000000000000000000000000000000000000000000000000000000000000 +Nonce = 030000000000000000000000 +In = 02000000000000000000000000000000030000000000000000000000000000000400000000000000000000000000000005000000000000000000000000000000 +AD = 01 +Out = 67FD45E126BFB9A79930C43AAD2D36967D3F0E4D217C1E551F59727870BEEFC98CB933A8FCE9DE887B1E40799988DB1FC3F91880ED405B2DD298318858467C895BDE0285037C5DE81E5B570A049B62A0 + +Key = 0100000000000000000000000000000000000000000000000000000000000000 +Nonce = 030000000000000000000000 +In = 02000000 +AD = 010000000000000000000000 +Out = 22B3F4CD1835E517741DFDDCCFA07FA4661B74CF + +Key = 0100000000000000000000000000000000000000000000000000000000000000 +Nonce = 030000000000000000000000 +In = 0300000000000000000000000000000004000000 +AD = 010000000000000000000000000000000200 +Out = 43DD0163CDB48F9FE3212BF61B201976067F342BB879AD976D8242ACC188AB59CABFE307 + +Key = 0100000000000000000000000000000000000000000000000000000000000000 +Nonce = 030000000000000000000000 +In = 030000000000000000000000000000000400 +AD = 0100000000000000000000000000000002000000 +Out = 462401724B5CE6588D5A54AAE5375513A075CFCDF5042112AA29685C912FC2056543 + +Key = E66021D5EB8E4F4066D4ADB9C33560E4F46E44BB3DA0015C94F7088736864200 +Nonce = E0EAF5284D884A0E77D31646 +In = +Out = 169FBB2FBF389A995F6390AF22228A62 + +Key = BAE8E37FC83441B16034566B7A806C46BB91C3C5AEDB64A6C590BC84D1A5E269 +Nonce = E4B47801AFC0577E34699B9E +In = 671FDD +AD = 4FBDC66F14 +Out = 0EACCB93DA9BB81333AEE0C785B240D319719D + +Key = 6545FC880C94A95198874296D5CC1FD161320B6920CE07787F86743B275D1AB3 +Nonce = 2F6D1F0434D8848C1177441F +In = 195495860F04 +AD = 6787F3EA22C127AAF195 +Out = A254DAD4F3F96B62B84DC40C84636A5EC12020EC8C2C + +Key = D1894728B3FED1473C528B8426A582995929A1499E9AD8780C8D63D0AB4149C0 +Nonce = 9F572C614B4745914474E7C7 +In = C9882E5386FD9F92EC +AD = 489C8FDE2BE2CF97E74E932D4ED87D +Out = 0DF9E308678244C44BC0FD3DC6628DFE55EBB0B9FB2295C8C2 + +Key = A44102952EF94B02B805249BAC80E6F61455BFAC8308A2D40D8C845117808235 +Nonce = 5C9E940FEA2F582950A70D5A +In = 1DB2316FD568378DA107B52B +AD = 0DA55210CC1C1B0ABDE3B2F204D1E9F8B06BC47F +Out = 8DBEB9F7255BF5769DD56692404099C2587F64979F21826706D497D5 + +Key = 9745B3D1AE06556FB6AA7890BEBC18FE6B3DB4DA3D57AA94842B9803A96E07FB +Nonce = 6DE71860F762EBFBD08284E4 +In = 21702DE0DE18BAA9C9596291B08466 +AD = F37DE21C7FF901CFE8A69615A93FDF7A98CAD481796245709F +Out = 793576DFA5C0F88729A7ED3C2F1BFFB3080D28F6EBB5D3648CE97BD5BA67FD + +Key = B18853F68D833640E42A3C02C25B64869E146D7B233987BDDFC240871D7576F7 +Nonce = 028EC6EB5EA7E298342A94D4 +In = B202B370EF9768EC6561C4FE6B7E7296FA85 +AD = 9C2159058B1F0FE91433A5BDC20E214EAB7FECEF4454A10EF0657DF21AC7 +Out = 857E16A64915A787637687DB4A9519635CDD454FC2A154FEA91F8363A39FEC7D0A49 + +Key = 3C535DE192EAED3822A2FBBE2CA9DFC88255E14A661B8AA82CC54236093BBC23 +Nonce = 688089E55540DB1872504E1C +In = CED532CE4159B035277D4DFBB7DB62968B13CD4EEC +AD = 734320CCC9D9BBBB19CB81B2AF4ECBC3E72834321F7AA0F70B7282B4F33DF23F167541 +Out = 626660C26EA6612FB17AD91E8E767639EDD6C9FAEE9D6C7029675B89EAF4BA1DED1A286594 + +Key = 0000000000000000000000000000000000000000000000000000000000000000 +Nonce = 000000000000000000000000 +In = 000000000000000000000000000000004DB923DC793EE6497C76DCC03A98E108 +Out = F3F80F2CF0CB2DD9C5984FCDA908456CC537703B5BA70324A6793A7BF218D3EAFFFFFFFF000000000000000000000000 + +Key = 0000000000000000000000000000000000000000000000000000000000000000 +Nonce = 000000000000000000000000 +In = EB3640277C7FFD1303C7A542D02D3E4C0000000000000000 +Out = 18CE4F0B8CB4D0CAC65FEA8F79257B20888E53E72299E56DFFFFFFFF000000000000000000000000 + +# Longer messages, generated with python-cryptography, to exercise +# the multi-block and precomputed key power paths + +Key = 9FA489DC9ED4DF9CA5D14F4E8464C4C409E3312FDAC60236257BC43EC16B5EBA +Nonce = 9BDDF1616055BDF3D2F67F5C +In = 39268446DA4DDCFF5B257000B80B9483D00E38AFCC57297CA1F79FF6A734AA94C9 +Out = 9E23C943045BCB31B2817658E5F47A016AC854C7F2FB5958B0C2E78FE59D52C25D1BBDA5BC2F27B170C0AE72F001DFCF21 + +Key = 802E7CCC3AA2B2B5E0D3F7D508B6E68B26AB0B8F9A07696C8B224A09E9E94E86 +Nonce = CDD9194E3E3460D8739ED0D5 +In = BF51A45E9636BD82CC9D86275F3BF6B9E4B0317EEEAA78868550D228548E81C04D +AD = A3194BD39C2FA18EA5C76AD6B9F419E5EC947E1BB1 +Out = 5E07F38E83BF8C34ECD6ACF102FE87820D744FE96029815A067F112B64DA0F0A087C88BED291F16737B5F6B2585FC2ABF4 + +Key = 6E0A0F48EB74F6AC748838F2968FC2A23968CA69B6846EC39D4D084D60075851 +Nonce = 7EEF26901834CC2CF87CCC74 +In = 85331EA45A0EED69CB494FB8D121DD310FE0E0E81BA8B45E6E6E64F385CC8F40E7F41D57A4845D1685CBD66C1686944D1D8BC0F395957EACBBBFF02FFC238DA1 +Out = 608F25ED9840706B4A7FAF7478072937EF05F9353F94BB086FA80FC6BFA5C889705AA3D1AABBD8FDDE45631C0A65E2F7E80F1E8E7E4DFBD3FAAE2CB36F685BEFDAC7BD3E95BA184EC0A5A5177EC333A2 + +Key = 5824566D237726A7B52193C2E0F38107A3E9BA8176B949A7E54A8EEF67EDE853 +Nonce = 9006854E7A570508D28BEAFC +In = 4DFE9876B3C6C59B83D5C912E537BEF18AD230BF1D07E1225DEEF66667806028C27B624E8CD84C35B7B1890DC6A8764C0A717FA22896078875F0D2B43E3A2E24 +AD = 4D90F1AB989DB2CCDA32C4D0A5E6EF1339DA1FF13A +Out = 7677697D6802CC6B21B36616670CA2F3E27A90D6EFFF3FA76D1562E282F41B820F4919050E5ADFB3BD7FF7FCC37A0AE2762A181D8678E4430FAB245A41716E295224A96FEF8F7FA69A3DDFC981A374D6 + +Key = 82C415E73FE5D64480E3F0B3F2703FEEC32A083976A3AA767BDCBED65F80D8AD +Nonce = 24BDB1E42616317F68EAEED4 +In = 03D2EA9D707C104CAAFDC39747981504A0B4F3307FD8F6412BD8ACC1695F3E837AF601C3B443234645BE5BBF51880512C4E66271E85DEBBCE29D19A7C10A5300F6B884ABE335AE5DB65FE171AA3CC1029E6DA0CCC3D7FA1634C6E359BE8463489084498F2B241F51E2FA34A776920070AAE7C70897AC7D654109A53166E960 +Out = 1E41911C0E0C03BBE367C0047D58A1CCA7531430107AD80FB94A4CF5FEC916AF8D1CBF0F4CAD4AB77E053A2908C0336ACC41217EB19F3F911F90C13E54E5C37366751544BD150FE3D500AD6746314D56AF19BDEED9B5D33FFC94487C618C7CF575C9E34CC88FDAC4B3A4CA2053BD6A9B89F53A036484FEDF72C6B058D5FCE3121D2F166E3AA95F41A0A94E5F954D1B + +Key = EAFBF85BF78B4F5276AAE9F5740A017A65AE9BC72CEFB9335FE7BA7756A8CC47 +Nonce = 541FEECBA5848257001394E5 +In = 1789BF08DB3FF91BCED1A1EEEC2A664878C98E2E4852E89DAC2E63FE9F5A2E647E6A6B4AC5F41C9E118C760420BF69273ADB5DB73ADFDFC36BB26A973962CBB3C963684988B74C80244B5B589F9BE242050683445668E7376A760402B4227E5860146AA9D301CC56BFB76C2AD1139784D425D191421FB13FF0CB254EF5D986 +AD = 8E6C83FF52973C3B1D722CE1244A82A51FEDBD8D33 +Out = AB6E479D1666B887B157417621154D37B570CD9637B5580D26B69B7FA21B91DDBD6BB2DF57F32A39D0A64E26C0215B38F4EEF5695EC09B7FE1F1FD2FC9A2B993D6E7078EF751A7D6281AF5F341D5E9D7D2C414B5681540F41425B2D551556A2994CD6768F025AAEC37B5B147F0581AF6270A47F66CFB03BA2BF9876932985DD75C20C2687707E0D207C5A24E49BD07 + +Key = 239A923ECEC754F91B9718C8E73076F1F08BD2C841D3BB3F57E8EFCEFBFEBB5C +Nonce = 0BAB96C1C9201622F014FCCE +In = BB66E79584B42BD4ADEF85374973A92C65067A49E16428E7971E7A5B69A9923B33F6C7A8949112C93FBBEB9225FB4C574AF09619672F400021F7D6A876E7AFC50F37BB1B2B67059B9D998B191AD175AD8A570881BF8EADC07F48856AF6520303F94E0A81A0435968F49A700AC4E22689BF5C4223B8452207E5715D7F5F8C8857 +Out = 6090D9E87108C5971463E75A317B81A45185EFF6C966FAFCD47233B1F99AD45077F4A664F90AF97F37B82653CAEB1ACAAE0BBDD87EA29A5BE0DF9864E61BBA7FEAF0FE0F11BBC079CB3F6F7FFC7B1A40C65B47BA0D910BB4CFFF7991C3C0B815D29C711D878951CA59E26BCC0F3219422189E7F0627608D6BC6C02BE7E6F91AE51B578512A365308AE9730FE46081C1A + +Key = B2B66C24F20DC86C962A7B0E68BB1CA7A8296348FFFC3D3AB880B3C6B1E7B63A +Nonce = 1F1C1F6C5A6E0A953FCC8088 +In = 2C924ABFB9D9D414DBB2CCBC88CE3A1A3181FA42DA45C51EFAEC29948D53C9CAE815D44F48EE1C624969E86920E53CA4F17AEDD78E14EDF15A23E03BAC183A1F946F7F77CAF08A0A42DC0DD075B6E10400153C32541DEFBE41DAC1F0EE6F7528576CC29DCDCDFA60D117AC534C9FEC12F8D58EC032E7107E9183251A718874F6 +AD = F1B2B7A2B5A01F657A58DA24288C8AE63B3335AC31 +Out = 3DD0B72503B1C4F6B97C01ED0254793405D61ECFE299E251D8D6BD47F6066E52BA315951949C6E1AB7DCA5A39DEAD741D4E022885B54440114060E9F51308BCD186A2E48E46FEBB95AEAD67780B9DE5A5217583F6711C780DDA176FEC12B2F959ACA84E2036D464274611475B9AEAE82F521A8FD3B8B04A81D3D4BE28F5E8181905A66A4925BB369F1B09ACE8DD42271 + +Key = 697DA08248AA68352DBF2D4114C72A945753C9C0270D7750118E3E1BD3076D84 +Nonce = C5EDD1BB2BA4DE293114519F +In = 73EA1453F72C5DA4EE9017B79DFA7FFB6502ACDA12C72EB4DC43D29DADB410DB86AE17AC74FB66DEC39BA102C5E2378E8BE600E5C40AF2C96D4AFF0B5A3A3F733E70E60A1EB1F809842D7D8EDED888934EA188734D75E3314654DA7753730666B769BAB1E2937950439A2F3971287FBABF7ACFF9BF4348EBC7B7F5F6E3A7C83E1D4672E340FA372843E0FC5FDA6EAA6A9EBEC13D0C01AEB7DBF294429529AC44EDC12141FE2B43CF6F51DBA1932811EA1F0F296B5D5CC932F3EBACE7C2A67E160FC8602E144C2E1354861200322B2ACD2DE05E980A37AE78C67F98D1335E8460ADF29A65D552B623E48030FA86F5093478890702A3F11DB6BB251D2C6E2357E1 +Out = 1DC1D9758DD83B935701E5BD97C994A47D333384EE307DFFE9BD763EF3F39507AAD70346AC791BC2A8DA4F151032331266034314B3707864FA7B31617D2141453D4313BC95C92E8A561298197F42BFAE8C2E11A89AA10D0BCBCA55E1734B5726F2861D2A26106F1879584133D95A0D2F9F3417B672BE93AEFD81A4F7B508823271EE59E0652F6A679D7055E50CB5D5DA2655DEF83FE2DD72C4F6EEF8EBB7F367ADEA3DE03D923D91D6FF1E54ED8D23F19BA9B8411453752CE7CB687B796F8821277382CFBFD909CE42A4021582E5F5DAA54FF56017130DFED1D89DF840D56F2A82401C4DC05E20033CAC593DCC238526035264EEB5D3C8D300508FC6C26AAC27772988F5F22D861783E9B434BB6AB477 + +Key = 3C6900D9ABD6A168DC7D33135E1969DAFC5797F214EB54259D3A7ADCEE372E3E +Nonce = 3A4153D034130F162493BBB4 +In = B463201A0645C0CEB2809F86494573D3B94DEDA3AD044179B63E3EBC08D8EB4B2D87254AF2C0B202A8A8E45E1E7BA1DA11CD777962EB0E7372FC64A1DA7E5442B5D884F35B58AD7E8595E02482117104488E286CB99EFCE768FCF72AF9B9235E3740CB9878BE4543CA3EE06901A2611C970B4F43B93A872C1EC4EB16B36B0F9A3632F0526344A8DC717779BF67627967ED09161D9EE8E2ABE4A95FA0193FE1F39661E27D9FC8E2177E212184F9A4AB83FA8A01F8638E46A4A22CE99DDEA448B7507270D0760A56D034474B28C440536E82AEABC36B101D7CB93765ADFA36F1893CAA44AD1F2F7F4B87BAA6BB8D67A94DEF898B5CAAD0CFD391885570A8102BAD +AD = 14D288EB194910FB2435F976C4B2FD87F9B9721E58 +Out = 1D38798B5E203BA65534F3814860E8FDA3A14E9FAA37B1AE849C2352AF485D5AA96F5856FB0320AB070B05D4A3FC9764A79B829D717A40947B28EC7F1D7FA9C91CD58C07CFA7A62194536D0067F6CB3E13A9BAB19489E4D2FDB1C8B3E680BECDE8082373E3FBF181BA296B4ED11809BA13AD83D3C70D5CC1223EC064EB8580790765EE0BC086B29BAD1D43E64BFC4D35F2FC4A079BC6F4D37181B66FB7133E79DC658CCFD0F8DFD7193F68466849B098A51FA77800745356C3B0481A2EFE2FF82D222BB25EEB6B8E52BCB0A62EA65511B2BFB04C15AA5EC1E9EF35CF59EE79E01E1AB1A859B6BCA28DC0BEE9167ABC261F8C4DE96D33C1DE8086CE9697EAE465CAE1C296E5D2B13BB4662BB75E6A4966 + +Key = 2DDC57557E74554A61340DF381F31B37D766F798A8AA3DAA75269B820C31E072 +Nonce = 8F5248C36251A69D9FABD305 +In = 2EEE84E13D3FE609154A9A36F9562F2C489C882C1F63DBDBDC3AF44DEFC47929FC8423CC76FE2DF019CFD21DC19BAE82263A32F1DC91AB326ADE6542737A57EBC232660203ADF15043386C4A4BB94B958BE0850EAE2746CB4B40DA1E9DFDA6B0E91A4A96BC685E44B415A0CAC1889EA926A3E60B167AF6849C42D4BA9CDEC5EC579DBBF09C771D85DE2A66BD4313EAB71B1FF96812DA85FA5DF14025F1FFC6A7E1C84F2528A9856646754DD34509DB96C5F0CD01757730F320D6D01110E43C3CE37D01CB09ADCAD65C5F555A69130694A0D432DAFFF129FAC3E8B967F56B94D645EFE2BB3F9EE0CD9F6629E5A929C6768B745FC3D42720A87DF8701153E5FDD68F82B80983B11ABCA97B778A5E658136 +Out = 4DBC89C8DDF1448A6AE8185F39ECD43EBDBCBF8125BB68251DDC7155B987AF1126A17427C150C6547FF58D1990295917AF2442253B2E062E8E86FDD20861818D256B7FAE5F346E7959774D9F603C3AB5A22497B44EE194A0AF7BA151BC08AE57D666118EE5D15F5D4AD9E12DF5EA470EC755BF284837F28316DA1EC284D7D06F9555B18BF18D45F8E916311B8F4962C188B146FAC3E758F32932F4B36050923BFAC4408BDE8CFAF2A2FAFC763FC0EE5ABB0AE5FB4A404A59F89263D6B5A600ABFCEDC5DE257F9BF62B222DAFA64D3DB48A601001C1CC6833B7F0D8D5FA02351F08CF3C79D9B12AB5732B2F84DD05F40E046DBD4294F25468971EE37F32131E5D2AB853EEBF0F34C4E36FC076D022D2EBDCCBCFA6BADFA845A177A70A1C6CA945 + +Key = 747C5E3BFCA2617E02A1602E3EA531A5F60A98338D91D13630CAF2AD8A1A8F03 +Nonce = D2A7B29846DCB9527DD7C6BF +In = CAA4E53E49A6704C15270EC2646774709ABEF8C15DD82E2A7EA608033410348339338855B8534B009C30A3EF1693128FC614BC6B1A4B3CF4C9979F82D6C7991EC27999F23BC9F96546A5003EDBDE1AAEB48566AE0B44BA3D475302C2E4F6559DD86FC1179F0B7C3CAE911A6B97D73F5A27B49B2C67B41D3156EEB52940B2AFCD3AB83B558B01AFE1C4A4DB7CCCFCDEE347019E8E00DBC6A53D8B69B02EDEACF49C245C4E5713082F74AFFA965FCA532875CD43FA00B5667AD3AC95B42E4294BF1F5C2867005D2482491BE84443454F5BC008E5417E31FE62BE3C7C4CB16F7D17F5E2A2B83333E2AB29BFDC64136FEF0724AE6F258D4097AD8AFF155E778661B2AF56EBC6EB59FDEF8A789946F7B8750A +AD = B1D1C5648771B89899BBEFE354960ED851932C36C3 +Out = 0BAA9944324B3627F69FAD6D3841E3C979D86DD00E27644BB0D21BF8374FB004BCEB3A6B8A3B9B44968C052B7B2693087DC6237892A712173E9C167988C7074131C9CE61E123B798CEBA12E19F4D340E6E98744F854D238E3A111CFF8AFC960CCFB6D02BDAAD6EE59D7CE4C94332D20C15DA51A7FDC7DBDEA69B606641BCC1D6081BE81DA2A264A0B69F4D92173CE7571C7AD2CE802FB7496493A80506CAF2EADD3C96A114105B36C6CB95F381632CBFB3533D59942669FE9800379598AFFC904A94F73E7529911E3A75A5DDB22D12FF69D3FD24E587F7634C698D00DB94DC1D1E3556D8F302A8AE199149851F5DF920E58FC41AC665A9F3091376A555805E6EA7C8C470FD1AC36464936329A3F5E151E7FC3A8D56AE49AD9B939A8674BE5017 + +Key = DDC6528018567E8341A1919633FC670700F1CADB01AE37EE2B0F20232EE0C7CC +Nonce = FB108A6E02B3C2CEEFD9D7F8 +In = DC97D306BE570F23FEE80239167FC4BE22F6BD58BA8105B00877E8E7A3D5194E640DC668BAE95DB6EC24C46BCF9DE1FFF52F716B6FFC044B26F9859699FF49040074D6C8841386F8A123B0A011CDD9243A88F8DB8F2AB2FA6395163FBC4DDF2E111D88330520681D766ADDDED884003747D34DFF13AA7A2C424A99A135AA6D4B7AF2B6769F6267C9F80855D4DC2A702DFB481A41632BFA563B1A34E500C478397DC7B30F04FEFB20B95A4CA580743F675D1AEB91DD9DAA4BBD2B3689483BDC8195EB4405F54ABEB842307010CE06B74723309B4C2F585E3AB522EC55596EF8FD8CB94B405D8122C6CF67C270E72BDE5A4E41F70ED99585B5182687E25AD4CD0BB9AA890BB6C7E349FA7F62E8B85FB44C0833BC0B778DB4DE4814C4AAD7E7AADC5953E719D6C8070FA5CFE37D0DE5A9BB4B5F6EA6B243E5FF1C5712FEFF66DB1850405D8457CFFF12FAEB8BBEC99FD954B0CA9F640424B63C929DFFFA8A277795CC556E31FB4BA43D584CAF9949D474D50279B917DB1C70825040E0472253F7A6A8CD385D51072C870F699102AB701AB74E91AED6B61006882C0B40BDFF98DEDEF4946EC9B0C8758BA8F347BDD26C61AF36367F42673D5E5709F3EFC3F6ECDA5FF1D889ADB0BB3264B414F8C6AF1649DE32AD210E2D2A00578BD2D5F70A695B4B1C936E258F52F4F1C6F47F9E39213C253BAB2D704BC826A8B2C2CAF492DFBF0AF7 +Out = 8295C57050E9E3DA43D55D6CDB53EFE1C9E908B6CE7FE77642E71FBAB377762885395065EBCF5FD8A08C8E136E0EE793AC0088973251F288C660B837B1D08C8A76061A1DAE76A5B4E047026CA0F05EBF8817B8E91D9F4835C5210F894C11743E74DA22B21689BF2FBAB31EDEF15DC5EF90C0F91CF4CD2E627ED20EF712E08EC1E2EF485D2E3EB0311D54C2EAA6D438597A886C5B641E6F73A6084604FFB41BDA62DF3CDD90F606A6872122F646D6039471F5060658D85833059FE6BCEB3C4243AA0538919EF40209355657BA33BA8E7D63809AF305A83E177A6DFBD92FAA6F429A68E73775F8E51DB25FF507EDBEE09F7F755513537D08091AB2B3C866A504323B4B79336D4175F41AF566A535E4CE73D591022B7148A669A08FEF39E583A0847C22CD52F4522EFCB9A2F8889D087F7B801414E8FAFA54E576769A9D117F146A86ECB89C3D4A573EACA6525AC2A8EED6108FA4920D6F6FA127B2B33B8EA3000D554D620CB5EB6E6BE22BF839899C832CAFF5D4879CED5C1486BE3E41CA989C82C134E6BD838DD3844FEDD36A37B767B312F3DF8EC8EF77F22F02D35DB30F1AF924E9EC3487ED70D965EB52AEFADD38360A5AD567DC92040510715B52AE1E6BCFD22D4113652B5E84921EAAEBD634693841D148418F1CC9970F7859FF7D376E47F1C21DD76A39ABD10E7EF6295771A81637974F660FC569495A34DBB87ED4BC2619293CEB577A3730DFACC938BF995FE43E + +Key = 0CF21D1DDB8032DB1830F27CE1F7CB7A1D40A86F925681500A89CC4A68555CB9 +Nonce = 7C9687A6884FA8771EA66D3E +In = E3656783C655F7AF7775F45596B34EECFD8438AEB4ECFDE69675E6064820755A00501B4601B1B29C1B72AD7C7429B4C82FF1F5A1B2D7ACE25723EBC73A2C077FEA6537AD31079D97C6A7922FC2A2048C803667C2BC70A6FF5C613879F875CF50F3EC54A7562B5F0773AE648835A417D1B28234F817DF0F5E17DBE336F88E7481AFFD2FCBABCE0665659203E6D6E87298324CA864637073D98F8AC96D71CDB93251910D365B0D80D51D6A10D047D85678F4E6194772C75413DDB4C2675A31498340606BD32104A639ABEAB06690BEFE99115CB83A6DB9EBC3988CE091B7FB69FBAD2979FCB56A3B237A27ABC86DD7C14FAEDD6E7C5CAE73E8D65E3988BEE03DF49D6946146DD4023DBC3CE100ED60392F0EA216D15B58A798E8A591ACFBF668137DDCE05C534419DFE21347DFBA3A241FD91E8CD735D45B8A623B6DCACAF31130756FC47DE076F98EC2DFFA63FC464065B8DAB12A0A90585CB334020EB9C855D57325AA4C0E72D56F6CB0B0B6C6AADEC9FAB0CF583D56816057C065B482AB0A19E3E56A81A1D8EBF5BCC8F22A27A352D372A841AA91E4D6457ACBDC60389C281C7E907F9A95A86BA5B33049CABCA652ACC78B0EDE9FD1BFC1B6386865C7F0252608F665BE05D3E8F89CAE2C31DFC43D0AB2926E16486BC2579A2EB60B2874A0B0DFB715E00B1DE6E26BA2C39D75104349376219C15A9774D53DB45D38D2B1FCCD53 +AD = 9D0585EA25149B36B110B48E1C37922C2532A156A3 +Out = A2EE63EDBB46A2C50262A48B07C2031057F2544B6BE06DF9643E095478B144650AAA8968E7CA9BB8C0F1FEC3684B38F0AAB9CB7CF6737AFFA9D55471C44A38617E47C2E8B59EB9683724D30382437046F7F47002AA161980EE786FFC1C31B670E44C2683F1A7DA7D1C231F52AFC53A2E694496CF91E17FF2AFC798075E5DCCD274B1C0CDCFA7F6620E866B5574E99DED63C2DD5FC98B320E2A838709602E48D06673628EFD0F0D5B3378F215FC21BC00459020335E4292041E728B09F588E356438120F4E1EEA99F4D6BBC34EBBADF3082704EE614A1B7F47DA9F59E786F3E25EE49193B1D3FA61B843268BC6E482808A0EAD4DC8BD13634E9BBDC40D9D92E167C4F0CFAF0E85B0BB7A7001DAAD1AF25A4746524550E8A4421C27B1E58BFC7B6A6D8897533E69D57550F7FCE1710BD1CDBF1D68609F776E50ACE684E817629B77D7863BDA6AC08A16A58964016B14C6B5F8FF9C878BDA1C2F7453951B52334F9715050623BE329FD3C4B8BE6210EF359D74E34B8BCE7016E7FA3412A2167D400A31781959BA3F15A5D9718FF00925981293082A4CEED7BE6AB1DF145C3D13AEDAAE3A0B0A8439DB984ED471F372DE339F895A91A7EACEFD79D186285C0BC8B68F11A9B10D730F6BF4F168B0FF4939207011C0306027763189B4C4ABA81EFFC9056F1A1D323B272CC9C6081926EC79B5B9FF404036E735021A59857C0A75D6C4076BB10DADF15CDC2EFDF674628802764EA + +Key = CCF39C0DD315447AB30DF3D3ED717BF7274764AFD348A81FE7872888014ACB65 +Nonce = 3A9042B987FD1AC30B5570E6 +In = B87E7CF7F64F2514B6BF5E1638DEFA868C087C218FC82407DC5C5455C2E590D01638F2812F9E8DCB2FA7F018189AD38D97CAE95CF4A1ABF9CB2658CE6E96B09158FF797B7725F4952F76B47E097EB8862AC23BACB1FA81357F358DB0955EF0C0B339140ECD02633CC75CFDECF640718F6F702E37C94AD343C03484920418BF8ACAE6703F2E407CDEA7047AB9020501D59B761AACA53B73971D97B8F6EA46F2990750DAE478CEB7692C73701DEE61550D4CB544E0787CDE968E4C51E5FA8DEB31FDDA6C96CE32DDCC5CD4DB7EFE03CB38C4F6095921B47CE896B73CA6D1345EE183EF39FFA7A12CF9F5C8FAF97BF695C02A38829A1BDE84AAA233897FAA21B44D903274009CF2566B6EA4B1AAAA473B48CEA2C7A55628BD1D33A8A6351A09649C227345873216808C5BB82E0A9566B5D2F0462D30AAA4D4D8B6C86799A4F873E028E3C85FB8AD8E96115BCB3F6901D9DFDB2344FA56FBF87585102AD8F4C12F347DFFA15F716AA553BE27A9FD9FFF15020CE4EAAB0C6A620E59EC226335FB5FE82D562F17C729BDB0F957EC90109B2008E84BB5D7C283F2A3338CDF91899A9923091CB38D806016E185FCDE9CD0F1E1B2CE3F68339258FE5FF455D16756122E8F0988FB7FD5B5D80941DA59FF8870D555430B4E85F942AB4F38D2755EEE55437D062E216CE69FF3A24CF1FF19E52FA61F6E494243C6753FEDF649CCF9E3FAC2619806FD79C4C362460B67A09433ED3C801C636580C40F77A847533690BB4AA085D3A3501A7702DB00FE872046C33055301ED6AA4CAEE189C2DBB866264BDBBEC4DAA3AF93CFEF6F530B0D78195D014500269BE6BBAB4B7205844B57A091303B171CC3D911B8048C9D2FE9B40592725C04D693FD8D24F342D59C87BF85821187AE0BB38250E7DA8934A103A00762C64CCF57FFD1F2E2F9C238A0BA71E796509E0C75335F468366DA9CF97BA08B22A5489248918B32FCBFF1F16302D8AB9E58A7B09DC926E10D5612E6186A32AADF9A6ABDCED8EBAD15F7BD7DDC38B2E7746529F43F8A4D7BC5508202E6B5162DDEF71CF6A97EA40B25276A257384E02142BF5FAB6D74E4DAA3AE624DF91E1B47614926F86B090BD0647CB174EBD3EB38A067A84E0B39FB4D7E83D274EBCBFC16D400D0328DFF6196888E03D5D752109CED199043F95C6392A99D130EC809B6D7FCC13F1B1EFAA161594B615A3581F9145203A1B06352DDA5C5940177FC40C95151FB845F7F57978844643A5F3F9B0F3A49E89812C4FFF63D0898FBB88885E092E17F270EB95040FEF99AE4F0CEF5E31C3872BD5BCDEF1D69126280C48C9E30FDAD56AE680D0F884E8353ED5C907E3653365D12B85426E9E6AA6799DF92A23DD5EFB3205F9512E9F7C6A2D912EC34CF6BDB0CD4505F018FDA700825F10CCA4B1EE3737166EB2543AE33F979161E92FE5C3AA2CB5B +Out = D3EC724696E409C88E1289E51C1E15F308B2613BAC2124968B500BC560AD861672E2CD70968BECA62934A76DA4AA4B454C15718AF9DE418183E178A26DC368AA7EB0EE87578BED0D4824DAF6CD695BF79C3078D51C61733DEA1C89C6228E07C277FC2433BD7810571E7E9B1A3DE9940DC194268E60F6D9C40F7FED2D5C20F844598F276BD6451C4BF69F20341353D18B35031959E366C8540EB5EAF3318D4FBE7B7D94A1BA83D4C4C0D5A5B235F022BE01A5CDDF2D3EBC8C143925DD61F2E8A6BD22EB2B6B2AB132DBC0773730D20CA99AAAFC7ADD807A7F1367FDF7B9581FEEFF9A4F02801CA3F74630C01BC154B405C6F59EA2F7C386981D7658050D2B6F4D81784BF4EC07FCD2C9D1BD5614A64197C3AA7E5EAD3B58DFA11496A57977BFA1945E079AA6BD88C0283B1EA9466C31E9A8C01CB3A7BFC7B067F6AD0E46270CCE25D1EC714A45F86F3EAD92957A77F310AA1787137643108DCF1660A758DB2466FA5290DE74D3EF1599BBF177DBF22777B85C592E68B624E6CF968B249D814F4C743D5CC027556C8C39EA3933356A1F166DF9AC4E119B3FCFF537A63D08D7AEF1D275580F351CA13CA56C50532C00F5B69967273D234D73B9463E673F4F3B8EF360A61AAFF9662874C2E126C1D6CB9B414B126158CC962B28AA2B1E73DD7E504BEEC319C327FB581DFA5A198F20F011E6361395EE30D16F95A10BD864A55306E530582F09C392E0391DBA24CD4F5E0642C7DBA5FB325906E994B19D28185BB66C302641CC72A478EE9CE074C3E1B22FAB95DC619B48BB813F1EA8A3B693221E45238ADF56608C855B27CA5979137FBA6A7570F035914385A87B220D7269EC106417EDC388630104C73EF1B99159783DD3BA733E6F62FB3ED33F2EBB0E275455EA359E6E5BB1013A208DB907137EE9932FE7171A64D3FF90E1C881FA926BCE56646753B039C3B6B18154C041C05DC51FB8CE1A733848FA11801004C6466C3F8D2B3E3FFCD946333F28B7FD8661CEE8329EE605A5BFD253B04E0C25847EBDE1ED9C519BE0CD64E4FCB195CB1B65AB8F7B21A25DA9A8B7E2A9D1B665723B51D34A4DC4DBC7A2EC5FCD799B496F389B1B28403D463EBAAFE729B30E3928A1B1E4902214ED0EF003F0C8F74E031C0AA8C1233CA9146E6F09CC66BAB274524097A829863BC3B66EC49328E7F748CFC746F8B06324794FBE92CAE7C80CD89617A1D56C2D0764F873051D44A0FBA5F45C89ECF2837454879A4F5207CD1A03DB9B36240F348120AC7F119D765979FB9E65D0117761EDC12B78BE08FA6AD6A32332A1B1CD6149AD17EF57DBD6A50F1B713626E234D2CB86F236A1E224B4976308035D1D16DADF226D3C063BC66B2899BF57BECA2502B35843C0FF57A4706ACB59E8C223ECE52B9870D834C94A101262110C130FDDDE0801399E6F99F8B65E41871F368E7E20D9CDE45BE24AC4949A0B762782A3001D + +Key = 6E6DF006C2250564FAC22B00D71A452765DD2AD77F483E6640C5EC0D28F5551E +Nonce = 7399281788267FF6883D568D +In = 3BA6C435DA1C5DF654B79D92A9263843EAD1A7176DE92D8F67BD5717922247FD8137C8F4B3F4A1789741BD867D2008DD3816E95A87A5875DCCA45F454C254D7D95405D628F20C0AF834BFB2B44F9128EC390393C3F419D99CA41EFB790250DA00C493FF9C112E72EAFF13106912531EE30B709E4A9F9D1DB833A1A7269164142B88C5FD2E058BC78C6F23E72A7E0C4CD6967E2D158D149DFFA68F7D84D57D886C32E98158428B39D5AF7BCDBD91E101E635BC17CAAEBD12080258BFBA67C31126C00F1EB0273D8F0E20C7A9EE334238822CC915838D7B642444C7C93CF7D7EFEDA4B7A422E3944EE028ACFCFE251F88605C7F692BDA15E37494BA4872BCF84513F1E8A1F534B9A67993019E81551E301649D94BE66E7FE4CEEAF327E1E2535D37FD8239BA01E192E6FDC61DC8EE76098AC52B5DBB27C01C6CFFF824338BF4A74D77C194F93DB44250F1DF3C16328F2A0FB921E9ADAD380A2E5895BED1541A062EE3858E251702C5C15E38B9665DC2708C3F4C04FCE8038B193CD63B818C389DF1F319B7112DAD588F835640EC9F2EB9431F9DE49D24816FB9E81147D4E0BAE9FA625BB064B7DB79B65E10254C0C8EBE085C653D57FF57D2F02B61B49FA41236F388815565CAFF1CF63D3FA2B34EC01314838938EB3EEB6105E86A826055319558669955568A8BF850577E814B9BDDC040300B7F344A45B2FAD8B6AC1EFBF75BAECC62C351A8CE75D9067343006463E25D1DB116438512F1A3431B583301F0DD1B352B303E799AF7084A9E9B4BD6E8AF13BD921CFE4A1792CA60472703EF8B4C1F79133574B05DBD649ADD657CE64B42F03B40901A48ECE7FCD312C148A1391D67E1AB98A5FF4A16ED99DC220B955D7B4E5959059A8B14F58494DFBFA4EE64323F7238A19D0D3098D176DFE6DD8E38F5DB075F6D7E0F4967CF2C9B00A6632A1B8537D5621B7D1F415B9C226DA0D9DB5C52D4F8D4E953427D50EFF5018BA0C0312A59187ECC91EF3ED4EDBF7E07B954FA3ABF66F1B0534F5EF9B51663E20B74FFCBE311B03B4E754E1470F68E7B0AF31BDD787DF0B7D736DD40B5ED9D963F92CB8CD0DC8AEECE2D788B3545F80D03315B27F81C9832BC300B3601491276E6172A797E2C94CA37B8D7AD0C7D576992A5A5DB646E398A83C8F9D5CF4AA6E14CE2A8D705F08D074B5E0EE7B12B5580B15BE8B2920F4E536D823F06A58C2DD1789E8C6425F58A832AD37B3E238DEF27CC4911E660BD41F7E55F165FE1D1E4D4E5FF9AAFD9620C0B8EA4159E24EE4B5BDC4CF78366F23D620834513847AAABE592044CDA7371F3895E690492EB5D2949C34E3818B1477669358B6A760D92511920D7176F6D1DD33AEC6633452C1F36D88C35B93E2824E0DD85A321A08E22163AC929F30872525B2D65658583521DEFA1012DF54A7C779B3B6220389DBB10CC1BCC06CA4 +AD = D5E608D88B8EE1C2C1C2B695EEDC9A40EDDB56EF78 +Out = 9C8462101F9ABECE0D5796B6629E006C00503CC7417CC81F633CBC9ED651E99AE6B6DF0DBF6A09964687EA32A57DFB86AA25BED8467957EE23F405E61813E00BB3B571685A204571829282312FDF075DD461519EDD7CD57D06F6624E959FE0AE5223D4F3F52231E8F1BF4317149AB94B47D4AF79E7F49E02F7ECFFA2AB422C6D3D92C1EC90CC4F374233B61959E32CA2499629803B89B98E2F63733695A1C4F4D834213AFB98438904B81781D4DFBC2877D476265B576CFDD9694BF306FBF64899119152BDDD8F10CCD1EABF29A37F1E15C2D8765AAF498914B17108A81992021CAA22F966683C6599912A16F77E75B92916401056D3EF830F464CF7AFBBADE365A67BEFA9A17119256E5E828CDC54E3DD1F47E473BA5D616F8F4F6708E6E49ADB3BB6EE18EDB708CB8F999A53E2BA27B5D417C4FADA953FF7F6D90B73532AD6865A53BFED0254042984DF9FBAB7065BD1605C2F2ACCE7373A442BEBF756C1D9C616B72BE34D2DFC85BB18AF68EBD172B74BF8B2F0502693BADCD4220C6E553E6AB7497DE8A5444304C25A97AB4507F1CFBCE235BF11C87F501984DD0BC9ECC394F26BC8165714D4AC88B965CA7A7AEBB5211FE4CB6202A049770489C74F3A3A85B1A4E63B9F03B09AFC4C66B36D37B43A229D546AF6A9EC99BAF33933540834FF84851F55C9B71109706A4271ACB450A642612A997A0D1BC44EEA695C631371F15E8C7D73DF3CB9B4B83121A5D408D14611BC03A3041E6310BF9ABC14CFC3E541270C1A8435DFFE108B2E812AA48E49032FF6448509324BE58A81198590CFA81C68D8C424ECC5412557D3D79B19C06FEF00FCA5F680259AA46CCDA67D4DF56CD32F26B655823EA79B7A5868297EE18C11BC361C64FA93306DBEB88A4FE5918BC5A318BADF16E5968495F1B33E86A5DD40502DEF9FF88B0B883355499C6E735A69AB2D453C36F6A5506A54FF16561EEBA6924AC781D206801BFD7F38AB8E1A91FDDC60F24CAA91898A18697D2FEFC3701A0EB6D3BFF7A90EEBD9750D9F7C1F8D0EC3F0CBC477BB319681998A5D37E472316D25A96598A229CB21B9E2A4EF3F678C334F94856BD1E90D065B915AEBCF3853DABD10271CC64922273BF7EFFBFBB397215D28ACA406CF838E1DA550C0F5D044359E15249C87C1CCC54F3D1CEA99F608FFDA53354FD46D50B9928DEC31BFB7FCB1E80F9095472EDEEAC8C83368D4C1D6972E44E1D03F22711A02BFA40110CCFF129C2FD52C168EB939B44A06424B01325A2C083DEA99E11C544052B4C851DF70428770A20E072775872BDC06B016456A3F38BDA06935F70160CDC280C95E4F9D2F738583D6EC54229ACA1BF169AEF29D32456682E9055BD5A6D5B0A27B35B383F2C4EE291B6D250BB3496E8BC8D682056D800E606A4A02358E3440C8E5AB6C256905E70A13805E87BD1B900D3F052DA7BE75076D4DE52124EBA8A11FB72AFE diff --git a/src/tests/data/polyval.vec b/src/tests/data/polyval.vec new file mode 100644 index 00000000000..9223edededa --- /dev/null +++ b/src/tests/data/polyval.vec @@ -0,0 +1,315 @@ +# POLYVAL vectors extracted from RFC 8452, plus longer inputs + +#test cpuid avx512_clmul clmul armv8pmull ssse3 simd128 sse2 + +Key = 25629347589242761D31F826BA4B757B +In = 4F4F95668C83DFB6401762BB2D01A262D1A24DDD2721D006BBE45F20D3C9F362 +Out = F7A3B47B846119FAE5B7866CF5E5B77E + +Key = D9B360279694941AC5DBC6987ADA7377 +In = 00000000000000000000000000000000 +Out = 00000000000000000000000000000000 + +Key = D9B360279694941AC5DBC6987ADA7377 +In = 0100000000000000000000000000000000000000000000004000000000000000 +Out = EB93B7740962C5E49D2A90A7DC5CEC74 + +Key = D9B360279694941AC5DBC6987ADA7377 +In = 0100000000000000000000000000000000000000000000006000000000000000 +Out = 48EB6C6C5A2DBE4A1DDE508FEE06361B + +Key = D9B360279694941AC5DBC6987ADA7377 +In = 0100000000000000000000000000000000000000000000008000000000000000 +Out = 20806C26E3C1DE019E111255708031D6 + +Key = D9B360279694941AC5DBC6987ADA7377 +In = 010000000000000000000000000000000200000000000000000000000000000000000000000000000001000000000000 +Out = CE6EDC9A50B36D9A98986BBF6A261C3B + +Key = D9B360279694941AC5DBC6987ADA7377 +In = 01000000000000000000000000000000020000000000000000000000000000000300000000000000000000000000000000000000000000008001000000000000 +Out = 81388746BC22D26B2ABC3DCB15754222 + +Key = D9B360279694941AC5DBC6987ADA7377 +In = 0100000000000000000000000000000002000000000000000000000000000000030000000000000000000000000000000400000000000000000000000000000000000000000000000002000000000000 +Out = 1E39B6D3344D348F6044F89935D1CF78 + +Key = D9B360279694941AC5DBC6987ADA7377 +In = 010000000000000000000000000000000200000000000000000000000000000008000000000000004000000000000000 +Out = B26781E7E2C1376F96BEC195F3709B2A + +Key = D9B360279694941AC5DBC6987ADA7377 +In = 010000000000000000000000000000000200000000000000000000000000000008000000000000006000000000000000 +Out = 111F5AFFB18E4CC1164A01BDC12A4145 + +Key = D9B360279694941AC5DBC6987ADA7377 +In = 010000000000000000000000000000000200000000000000000000000000000008000000000000008000000000000000 +Out = 79745AB508622C8A958543675FAC4688 + +Key = D9B360279694941AC5DBC6987ADA7377 +In = 01000000000000000000000000000000020000000000000000000000000000000300000000000000000000000000000008000000000000000001000000000000 +Out = 2CE7DAAF7C89490822051255B12ECA6B + +Key = D9B360279694941AC5DBC6987ADA7377 +In = 0100000000000000000000000000000002000000000000000000000000000000030000000000000000000000000000000400000000000000000000000000000008000000000000008001000000000000 +Out = 9CA987715D69C1786711DFCD22F830FC + +Key = D9B360279694941AC5DBC6987ADA7377 +In = 010000000000000000000000000000000200000000000000000000000000000003000000000000000000000000000000040000000000000000000000000000000500000000000000000000000000000008000000000000000002000000000000 +Out = FFCD05D5770F34AD9267F0A59994B15A + +Key = D9B360279694941AC5DBC6987ADA7377 +In = 010000000000000000000000000000000200000000000000000000000000000060000000000000002000000000000000 +Out = F6CE9D3DCD68A2FD603C7ECC18FB9918 + +Key = D9B360279694941AC5DBC6987ADA7377 +In = 010000000000000000000000000000000200000000000000000000000000000003000000000000000000000000000000040000000000000000000000000000009000000000000000A000000000000000 +Out = 4781D492CB8F926C504CAA36F61008FE + +Key = D9B360279694941AC5DBC6987ADA7377 +In = 01000000000000000000000000000000020000000000000000000000000000000300000000000000000000000000000004000000000000000000000000000000A0000000000000009000000000000000 +Out = 75CBC23A1A10E348AEB8E384B5CC79FD + +Key = 036EE1FE2D7926AF68898095E54E7B3C +In = 00000000000000000000000000000000 +Out = 00000000000000000000000000000000 + +Key = 3E28DE1120B2981A0155795CA2812AF6 +In = 46BB91C3C500000000000000000000007A806C0000000000000000000000000028000000000000001800000000000000 +Out = 43D9A745511DCFA21B96DD606F1D5720 + +Key = 43B8DE9CEA62330D15CCCFC84A33E8C8 +In = FC880C94A95198874296000000000000BDC66F1465450000000000000000000050000000000000003000000000000000 +Out = 26498E0D2B1EF004E808C458E8F2F515 + +Key = 8A51DF64D93EAF667C2C09BD454CE5C5 +In = 046787F3EA22C127AAF195D1894728001177441F195495860F0000000000000078000000000000004800000000000000 +Out = 63A3451C0B23345AD02BBA59956517CF + +Key = 22F50707A95DD416DF069D670CB775E8 +In = C9882E5386FD9F92EC489C8FDE2BE2CF97E74E930000000000000000000000009F572C614B4745914474E7C700000000A0000000000000006000000000000000 +Out = 0CCA0423FBA9D77FE7E2E6963B08CDD0 + +Key = 0B00A29A83E7E95B92E3A0783B29F140 +In = 2950A70D5A1DB2316FD568378DA107B52B0DA55210CC1C1B0A000000000000000D8C8451178082355C9E940FEA2F5800C8000000000000007800000000000000 +Out = 1086EF25247AA41009BBC40871D9B350 + +Key = 21C874A8BAD3603D1C3E8784DF5B3F9F +In = 1860F762EBFBD08284E421702DE0DE18BAA9C9596291B08466F37DE21C7F00006B3DB4DA3D57AA94842B9803A96E07FB6DE70000000000000000000000000000F0000000000000009000000000000000 +Out = 55462A5AFA0DA8D646481E049EF9C764 + +Key = 3724F55F1D22AC0AB830DA0B6A995D74 +In = 7576F7028EC6EB5EA7E298342A94D4B202B370EF9768EC6561C4FE6B7E7296FA859C2100000000000000000000000000E42A3C02C25B64869E146D7B233987BDDFC240871D00000000000000000000001801000000000000A800000000000000 +Out = 4CBBA090F03F7D1188EA55749FA6C7BD + +Key = B5D3C529DFAFAC43136D2D11BE284D7F +In = 00000000000000000000000000000000 +Out = 00000000000000000000000000000000 + +Key = B5D3C529DFAFAC43136D2D11BE284D7F +In = 0100000000000000000000000000000000000000000000004000000000000000 +Out = 05230F62F0EAC8AA14FE4D646B59CD41 + +Key = B5D3C529DFAFAC43136D2D11BE284D7F +In = 0100000000000000000000000000000000000000000000006000000000000000 +Out = 6D81A24732FD6D03AE5AF544720A1C13 + +Key = B5D3C529DFAFAC43136D2D11BE284D7F +In = 0100000000000000000000000000000000000000000000008000000000000000 +Out = 74EEE2BF7C9A165F8B25DEA73DB32A6D + +Key = B5D3C529DFAFAC43136D2D11BE284D7F +In = 010000000000000000000000000000000200000000000000000000000000000000000000000000000001000000000000 +Out = 899B6381B3D46F0DEF7AA0517BA188F5 + +Key = B5D3C529DFAFAC43136D2D11BE284D7F +In = 01000000000000000000000000000000020000000000000000000000000000000300000000000000000000000000000000000000000000008001000000000000 +Out = C1F8593D8FC29B0C290CAE1992F71F51 + +Key = B5D3C529DFAFAC43136D2D11BE284D7F +In = 0100000000000000000000000000000002000000000000000000000000000000030000000000000000000000000000000400000000000000000000000000000000000000000000000002000000000000 +Out = 6EF38B06046C7C0E225EFAEF8E2EC4C4 + +Key = B5D3C529DFAFAC43136D2D11BE284D7F +In = 010000000000000000000000000000000200000000000000000000000000000008000000000000004000000000000000 +Out = 34E57BAFE011B9B36FC6821B7FFB3354 + +Key = B5D3C529DFAFAC43136D2D11BE284D7F +In = 010000000000000000000000000000000200000000000000000000000000000008000000000000006000000000000000 +Out = 5C47D68A22061C1AD5623A3B66A8E206 + +Key = B5D3C529DFAFAC43136D2D11BE284D7F +In = 010000000000000000000000000000000200000000000000000000000000000008000000000000008000000000000000 +Out = 452896726C616746F01D11D82911D478 + +Key = B5D3C529DFAFAC43136D2D11BE284D7F +In = 01000000000000000000000000000000020000000000000000000000000000000300000000000000000000000000000008000000000000000001000000000000 +Out = 4E58C1E341C9BB0AE34EDA9509DFC90C + +Key = B5D3C529DFAFAC43136D2D11BE284D7F +In = 0100000000000000000000000000000002000000000000000000000000000000030000000000000000000000000000000400000000000000000000000000000008000000000000008001000000000000 +Out = 2566A4AFF9A525DF9772C16D4EAF8D2A + +Key = B5D3C529DFAFAC43136D2D11BE284D7F +In = 010000000000000000000000000000000200000000000000000000000000000003000000000000000000000000000000040000000000000000000000000000000500000000000000000000000000000008000000000000000002000000000000 +Out = DA58D2F61B0A9D343B2F37FB0C519733 + +Key = B5D3C529DFAFAC43136D2D11BE284D7F +In = 010000000000000000000000000000000200000000000000000000000000000060000000000000002000000000000000 +Out = 6DC76AE84B88916E073A303AAFDE05CF + +Key = B5D3C529DFAFAC43136D2D11BE284D7F +In = 010000000000000000000000000000000200000000000000000000000000000003000000000000000000000000000000040000000000000000000000000000009000000000000000A000000000000000 +Out = 973EF4FD04BD31D193816AB26F8655CA + +Key = B5D3C529DFAFAC43136D2D11BE284D7F +In = 01000000000000000000000000000000020000000000000000000000000000000300000000000000000000000000000004000000000000000000000000000000A0000000000000009000000000000000 +Out = 2CBB6B7AB2DBFFEFB797F825F826870C + +Key = E40D26F82774AA27F47B047B608B9585 +In = 00000000000000000000000000000000 +Out = 00000000000000000000000000000000 + +Key = B546F5A850D0A90ADFE39E95C2510FC6 +In = 4FBDC66F140000000000000000000000671FDD0000000000000000000000000028000000000000001800000000000000 +Out = B91F91F96B159A7C611C05035B839E92 + +Key = E156E1F9B0B07B780CBE30F259E3C8DA +In = 6787F3EA22C127AAF195000000000000195495860F040000000000000000000050000000000000003000000000000000 +Out = 2C480ED9D236B1DF24C6EEC109BD40C1 + +Key = 0533FD71F4119257361A3FF1469DD4E5 +In = 489C8FDE2BE2CF97E74E932D4ED87D00C9882E5386FD9F92EC0000000000000078000000000000004800000000000000 +Out = BF160BC9DED8C63057D2C38AAE552FB4 + +Key = 64779AB10EE8A280272F14CC8851B727 +In = 0DA55210CC1C1B0ABDE3B2F204D1E9F8B06BC47F0000000000000000000000001DB2316FD568378DA107B52B00000000A0000000000000006000000000000000 +Out = CC86EE22C861E1FD474C84676B42739C + +Key = 27C2959ED4DAEA3B1F52E849478DE376 +In = F37DE21C7FF901CFE8A69615A93FDF7A98CAD481796245709F0000000000000021702DE0DE18BAA9C9596291B0846600C8000000000000007800000000000000 +Out = C4FA5E5B713853703BCF8E6424505FA5 + +Key = 670B98154076DDB59B7A9137D0DCC0F0 +In = 9C2159058B1F0FE91433A5BDC20E214EAB7FECEF4454A10EF0657DF21AC70000B202B370EF9768EC6561C4FE6B7E7296FA850000000000000000000000000000F0000000000000009000000000000000 +Out = 4E4108F09F41D797DC9256F8DA8D58C7 + +Key = CB8C3AA3F8DBAEB4B28A3E86FF6625F8 +In = 734320CCC9D9BBBB19CB81B2AF4ECBC3E72834321F7AA0F70B7282B4F33DF23F16754100000000000000000000000000CED532CE4159B035277D4DFBB7DB62968B13CD4EEC00000000000000000000001801000000000000A800000000000000 +Out = FFD503C7DD712EB3791B7114B17BB0CF + +Key = DC95C078A24089895275F3D86B4FB868 +In = 000000000000000000000000000000004DB923DC793EE6497C76DCC03A98E10800000000000000000001000000000000 +Out = 7367CDB411B730128DD56E8EDC0EFF56 + +Key = DC95C078A24089895275F3D86B4FB868 +In = EB3640277C7FFD1303C7A542D02D3E4C000000000000000000000000000000000000000000000000C000000000000000 +Out = 7367CDB411B730128DD56E8EDC0EFF56 + +Key = 25629347589242761D31F826BA4B757B +In = 0273E455C637A8198AFB6CDD4EBF30A11283F465D647B8299A0B7CED5ECF40B1 +Out = 3E706A3774E5318020D81682BD0F16FA + +Key = 25629347589242761D31F826BA4B757B +In = 0374E556C738A91A8BFC6DDE4FC031A21384F566D748B92A9B0C7DEE5FD041B223940576E758C93AAB1C8DFE6FE051C2 +Out = 6E2B113A8573B70D5B00C5EC7CC4BDB4 + +Key = 25629347589242761D31F826BA4B757B +In = 0475E657C839AA1B8CFD6EDF50C132A31485F667D849BA2B9C0D7EEF60D142B324950677E859CA3BAC1D8EFF70E152C334A51687F869DA4BBC2D9E0F80F162D3 +Out = 9596AD703FF4DEEB8D0E550E091A61E6 + +Key = 25629347589242761D31F826BA4B757B +In = 0576E758C93AAB1C8DFE6FE051C233A41586F768D94ABB2C9D0E7FF061D243B425960778E95ACB3CAD1E8F0071E253C435A61788F96ADB4CBD2E9F1081F263D445B62798097AEB5CCD3EAF20910273E4 +Out = 624A7E6556C58E4F6779C4A61F50117B + +Key = 25629347589242761D31F826BA4B757B +In = 0778E95ACB3CAD1E8F0071E253C435A61788F96ADB4CBD2E9F1081F263D445B62798097AEB5CCD3EAF20910273E455C637A8198AFB6CDD4EBF30A11283F465D647B8299A0B7CED5ECF40B122930475E657C839AA1B8CFD6EDF50C132A31485F667D849BA2B9C0D7EEF60D142B3249506 +Out = 39BA84BE81214D95F601604FB888A0DE + +Key = 25629347589242761D31F826BA4B757B +In = 0879EA5BCC3DAE1F900172E354C536A71889FA6BDC4DBE2FA01182F364D546B728990A7BEC5DCE3FB021920374E556C738A91A8BFC6DDE4FC031A21384F566D748B92A9B0C7DEE5FD041B223940576E758C93AAB1C8DFE6FE051C233A41586F768D94ABB2C9D0E7FF061D243B425960778E95ACB3CAD1E8F0071E253C435A617 +Out = 390FB93573459F736214F99E4B347EB8 + +Key = 25629347589242761D31F826BA4B757B +In = 097AEB5CCD3EAF20910273E455C637A8198AFB6CDD4EBF30A11283F465D647B8299A0B7CED5ECF40B122930475E657C839AA1B8CFD6EDF50C132A31485F667D849BA2B9C0D7EEF60D142B324950677E859CA3BAC1D8EFF70E152C334A51687F869DA4BBC2D9E0F80F162D344B526970879EA5BCC3DAE1F900172E354C536A71889FA6BDC4DBE2FA01182F364D546B728 +Out = 45C00C09F0618A2E3BD664573227B8A4 + +Key = 25629347589242761D31F826BA4B757B +In = 0F80F162D344B526970879EA5BCC3DAE1F900172E354C536A71889FA6BDC4DBE2FA01182F364D546B728990A7BEC5DCE3FB021920374E556C738A91A8BFC6DDE4FC031A21384F566D748B92A9B0C7DEE5FD041B223940576E758C93AAB1C8DFE6FE051C233A41586F768D94ABB2C9D0E7FF061D243B425960778E95ACB3CAD1E8F0071E253C435A61788F96ADB4CBD2E9F1081F263D445B62798097AEB5CCD3EAF20910273E455C637A8198AFB6CDD4EBF30A11283F465D647B8299A0B7CED5ECF40B122930475E657C839AA1B8CFD6EDF50C132A31485F667D849BA2B9C0D7EEF60D142B324950677E859CA3BAC1D8E +Out = 31E38B06E32D6C6E82D2AFAF98C23834 + +Key = 25629347589242761D31F826BA4B757B +In = 1081F263D445B62798097AEB5CCD3EAF20910273E455C637A8198AFB6CDD4EBF30A11283F465D647B8299A0B7CED5ECF40B122930475E657C839AA1B8CFD6EDF50C132A31485F667D849BA2B9C0D7EEF60D142B324950677E859CA3BAC1D8EFF70E152C334A51687F869DA4BBC2D9E0F80F162D344B526970879EA5BCC3DAE1F900172E354C536A71889FA6BDC4DBE2FA01182F364D546B728990A7BEC5DCE3FB021920374E556C738A91A8BFC6DDE4FC031A21384F566D748B92A9B0C7DEE5FD041B223940576E758C93AAB1C8DFE6FE051C233A41586F768D94ABB2C9D0E7FF061D243B425960778E95ACB3CAD1E8F0071E253C435A61788F96ADB4CBD2E9F +Out = 82A599A74437D0D8335B406975A2A8E7 + +Key = 25629347589242761D31F826BA4B757B +In = 1182F364D546B728990A7BEC5DCE3FB021920374E556C738A91A8BFC6DDE4FC031A21384F566D748B92A9B0C7DEE5FD041B223940576E758C93AAB1C8DFE6FE051C233A41586F768D94ABB2C9D0E7FF061D243B425960778E95ACB3CAD1E8F0071E253C435A61788F96ADB4CBD2E9F1081F263D445B62798097AEB5CCD3EAF20910273E455C637A8198AFB6CDD4EBF30A11283F465D647B8299A0B7CED5ECF40B122930475E657C839AA1B8CFD6EDF50C132A31485F667D849BA2B9C0D7EEF60D142B324950677E859CA3BAC1D8EFF70E152C334A51687F869DA4BBC2D9E0F80F162D344B526970879EA5BCC3DAE1F900172E354C536A71889FA6BDC4DBE2FA01182F364D546B728990A7BEC5DCE3FB0 +Out = E08F17DCCE386FC88F98823A71CDB22E + +Key = 25629347589242761D31F826BA4B757B +In = 1889FA6BDC4DBE2FA01182F364D546B728990A7BEC5DCE3FB021920374E556C738A91A8BFC6DDE4FC031A21384F566D748B92A9B0C7DEE5FD041B223940576E758C93AAB1C8DFE6FE051C233A41586F768D94ABB2C9D0E7FF061D243B425960778E95ACB3CAD1E8F0071E253C435A61788F96ADB4CBD2E9F1081F263D445B62798097AEB5CCD3EAF20910273E455C637A8198AFB6CDD4EBF30A11283F465D647B8299A0B7CED5ECF40B122930475E657C839AA1B8CFD6EDF50C132A31485F667D849BA2B9C0D7EEF60D142B324950677E859CA3BAC1D8EFF70E152C334A51687F869DA4BBC2D9E0F80F162D344B526970879EA5BCC3DAE1F900172E354C536A71889FA6BDC4DBE2FA01182F364D546B728990A7BEC5DCE3FB021920374E556C738A91A8BFC6DDE4FC031A21384F566D748B92A9B0C7DEE5FD041B223940576E758C93AAB1C8DFE6FE051C233A41586F768D94ABB2C9D0E7FF061D243B425960778E95ACB3CAD1E8F0071E253C435A61788F96ADB4CBD2E9F1081F263D445B627 +Out = 4427D3E318C491130B5BCB426201AE99 + +Key = 25629347589242761D31F826BA4B757B +In = 1F900172E354C536A71889FA6BDC4DBE2FA01182F364D546B728990A7BEC5DCE3FB021920374E556C738A91A8BFC6DDE4FC031A21384F566D748B92A9B0C7DEE5FD041B223940576E758C93AAB1C8DFE6FE051C233A41586F768D94ABB2C9D0E7FF061D243B425960778E95ACB3CAD1E8F0071E253C435A61788F96ADB4CBD2E9F1081F263D445B62798097AEB5CCD3EAF20910273E455C637A8198AFB6CDD4EBF30A11283F465D647B8299A0B7CED5ECF40B122930475E657C839AA1B8CFD6EDF50C132A31485F667D849BA2B9C0D7EEF60D142B324950677E859CA3BAC1D8EFF70E152C334A51687F869DA4BBC2D9E0F80F162D344B526970879EA5BCC3DAE1F900172E354C536A71889FA6BDC4DBE2FA01182F364D546B728990A7BEC5DCE3FB021920374E556C738A91A8BFC6DDE4FC031A21384F566D748B92A9B0C7DEE5FD041B223940576E758C93AAB1C8DFE6FE051C233A41586F768D94ABB2C9D0E7FF061D243B425960778E95ACB3CAD1E8F0071E253C435A61788F96ADB4CBD2E9F1081F263D445B62798097AEB5CCD3EAF20910273E455C637A8198AFB6CDD4EBF30A11283F465D647B8299A0B7CED5ECF40B122930475E657C839AA1B8CFD6EDF50C132A31485F667D849BA2B9C0D7EEF60D142B324950677E859CA3BAC1D8EFF70E152C334A51687F869DA4BBC2D9E +Out = 3D3ABC101064372D77425325B2807246 + +Key = 25629347589242761D31F826BA4B757B +In = 20910273E455C637A8198AFB6CDD4EBF30A11283F465D647B8299A0B7CED5ECF40B122930475E657C839AA1B8CFD6EDF50C132A31485F667D849BA2B9C0D7EEF60D142B324950677E859CA3BAC1D8EFF70E152C334A51687F869DA4BBC2D9E0F80F162D344B526970879EA5BCC3DAE1F900172E354C536A71889FA6BDC4DBE2FA01182F364D546B728990A7BEC5DCE3FB021920374E556C738A91A8BFC6DDE4FC031A21384F566D748B92A9B0C7DEE5FD041B223940576E758C93AAB1C8DFE6FE051C233A41586F768D94ABB2C9D0E7FF061D243B425960778E95ACB3CAD1E8F0071E253C435A61788F96ADB4CBD2E9F1081F263D445B62798097AEB5CCD3EAF20910273E455C637A8198AFB6CDD4EBF30A11283F465D647B8299A0B7CED5ECF40B122930475E657C839AA1B8CFD6EDF50C132A31485F667D849BA2B9C0D7EEF60D142B324950677E859CA3BAC1D8EFF70E152C334A51687F869DA4BBC2D9E0F80F162D344B526970879EA5BCC3DAE1F900172E354C536A71889FA6BDC4DBE2FA01182F364D546B728990A7BEC5DCE3FB021920374E556C738A91A8BFC6DDE4FC031A21384F566D748B92A9B0C7DEE5FD041B223940576E758C93AAB1C8DFE6FE051C233A41586F768D94ABB2C9D0E7FF061D243B425960778E95ACB3CAD1E8F0071E253C435A61788F96ADB4CBD2E9F1081F263D445B62798097AEB5CCD3EAF +Out = A492D9D2DD39DD04F504933927C3D243 + +Key = 25629347589242761D31F826BA4B757B +In = 21920374E556C738A91A8BFC6DDE4FC031A21384F566D748B92A9B0C7DEE5FD041B223940576E758C93AAB1C8DFE6FE051C233A41586F768D94ABB2C9D0E7FF061D243B425960778E95ACB3CAD1E8F0071E253C435A61788F96ADB4CBD2E9F1081F263D445B62798097AEB5CCD3EAF20910273E455C637A8198AFB6CDD4EBF30A11283F465D647B8299A0B7CED5ECF40B122930475E657C839AA1B8CFD6EDF50C132A31485F667D849BA2B9C0D7EEF60D142B324950677E859CA3BAC1D8EFF70E152C334A51687F869DA4BBC2D9E0F80F162D344B526970879EA5BCC3DAE1F900172E354C536A71889FA6BDC4DBE2FA01182F364D546B728990A7BEC5DCE3FB021920374E556C738A91A8BFC6DDE4FC031A21384F566D748B92A9B0C7DEE5FD041B223940576E758C93AAB1C8DFE6FE051C233A41586F768D94ABB2C9D0E7FF061D243B425960778E95ACB3CAD1E8F0071E253C435A61788F96ADB4CBD2E9F1081F263D445B62798097AEB5CCD3EAF20910273E455C637A8198AFB6CDD4EBF30A11283F465D647B8299A0B7CED5ECF40B122930475E657C839AA1B8CFD6EDF50C132A31485F667D849BA2B9C0D7EEF60D142B324950677E859CA3BAC1D8EFF70E152C334A51687F869DA4BBC2D9E0F80F162D344B526970879EA5BCC3DAE1F900172E354C536A71889FA6BDC4DBE2FA01182F364D546B728990A7BEC5DCE3FB021920374E556C738A91A8BFC6DDE4FC0 +Out = 61F0CF7A9862F8572FB1394F8AB572FD + +Key = 25629347589242761D31F826BA4B757B +In = 30A11283F465D647B8299A0B7CED5ECF40B122930475E657C839AA1B8CFD6EDF50C132A31485F667D849BA2B9C0D7EEF60D142B324950677E859CA3BAC1D8EFF70E152C334A51687F869DA4BBC2D9E0F80F162D344B526970879EA5BCC3DAE1F900172E354C536A71889FA6BDC4DBE2FA01182F364D546B728990A7BEC5DCE3FB021920374E556C738A91A8BFC6DDE4FC031A21384F566D748B92A9B0C7DEE5FD041B223940576E758C93AAB1C8DFE6FE051C233A41586F768D94ABB2C9D0E7FF061D243B425960778E95ACB3CAD1E8F0071E253C435A61788F96ADB4CBD2E9F1081F263D445B62798097AEB5CCD3EAF20910273E455C637A8198AFB6CDD4EBF30A11283F465D647B8299A0B7CED5ECF40B122930475E657C839AA1B8CFD6EDF50C132A31485F667D849BA2B9C0D7EEF60D142B324950677E859CA3BAC1D8EFF70E152C334A51687F869DA4BBC2D9E0F80F162D344B526970879EA5BCC3DAE1F900172E354C536A71889FA6BDC4DBE2FA01182F364D546B728990A7BEC5DCE3FB021920374E556C738A91A8BFC6DDE4FC031A21384F566D748B92A9B0C7DEE5FD041B223940576E758C93AAB1C8DFE6FE051C233A41586F768D94ABB2C9D0E7FF061D243B425960778E95ACB3CAD1E8F0071E253C435A61788F96ADB4CBD2E9F1081F263D445B62798097AEB5CCD3EAF20910273E455C637A8198AFB6CDD4EBF30A11283F465D647B8299A0B7CED5ECF40B122930475E657C839AA1B8CFD6EDF50C132A31485F667D849BA2B9C0D7EEF60D142B324950677E859CA3BAC1D8EFF70E152C334A51687F869DA4BBC2D9E0F80F162D344B526970879EA5BCC3DAE1F900172E354C536A71889FA6BDC4DBE2FA01182F364D546B728990A7BEC5DCE3FB021920374E556C738A91A8BFC6DDE4FC031A21384F566D748B92A9B0C7DEE5FD041B223940576E758C93AAB1C8DFE6FE051C233A41586F768D94ABB2C9D0E7FF061D243B425960778E95ACB3CAD1E8F0071E253C435A61788F96ADB4CBD2E9F1081F263D445B62798097AEB5CCD3EAF20910273E455C637A8198AFB6CDD4EBF +Out = F4E8116756C807521EDB653E626E8B45 + +Key = 25629347589242761D31F826BA4B757B +In = 40B122930475E657C839AA1B8CFD6EDF50C132A31485F667D849BA2B9C0D7EEF60D142B324950677E859CA3BAC1D8EFF70E152C334A51687F869DA4BBC2D9E0F80F162D344B526970879EA5BCC3DAE1F900172E354C536A71889FA6BDC4DBE2FA01182F364D546B728990A7BEC5DCE3FB021920374E556C738A91A8BFC6DDE4FC031A21384F566D748B92A9B0C7DEE5FD041B223940576E758C93AAB1C8DFE6FE051C233A41586F768D94ABB2C9D0E7FF061D243B425960778E95ACB3CAD1E8F0071E253C435A61788F96ADB4CBD2E9F1081F263D445B62798097AEB5CCD3EAF20910273E455C637A8198AFB6CDD4EBF30A11283F465D647B8299A0B7CED5ECF40B122930475E657C839AA1B8CFD6EDF50C132A31485F667D849BA2B9C0D7EEF60D142B324950677E859CA3BAC1D8EFF70E152C334A51687F869DA4BBC2D9E0F80F162D344B526970879EA5BCC3DAE1F900172E354C536A71889FA6BDC4DBE2FA01182F364D546B728990A7BEC5DCE3FB021920374E556C738A91A8BFC6DDE4FC031A21384F566D748B92A9B0C7DEE5FD041B223940576E758C93AAB1C8DFE6FE051C233A41586F768D94ABB2C9D0E7FF061D243B425960778E95ACB3CAD1E8F0071E253C435A61788F96ADB4CBD2E9F1081F263D445B62798097AEB5CCD3EAF20910273E455C637A8198AFB6CDD4EBF30A11283F465D647B8299A0B7CED5ECF40B122930475E657C839AA1B8CFD6EDF50C132A31485F667D849BA2B9C0D7EEF60D142B324950677E859CA3BAC1D8EFF70E152C334A51687F869DA4BBC2D9E0F80F162D344B526970879EA5BCC3DAE1F900172E354C536A71889FA6BDC4DBE2FA01182F364D546B728990A7BEC5DCE3FB021920374E556C738A91A8BFC6DDE4FC031A21384F566D748B92A9B0C7DEE5FD041B223940576E758C93AAB1C8DFE6FE051C233A41586F768D94ABB2C9D0E7FF061D243B425960778E95ACB3CAD1E8F0071E253C435A61788F96ADB4CBD2E9F1081F263D445B62798097AEB5CCD3EAF20910273E455C637A8198AFB6CDD4EBF30A11283F465D647B8299A0B7CED5ECF40B122930475E657C839AA1B8CFD6EDF50C132A31485F667D849BA2B9C0D7EEF60D142B324950677E859CA3BAC1D8EFF70E152C334A51687F869DA4BBC2D9E0F80F162D344B526970879EA5BCC3DAE1F900172E354C536A71889FA6BDC4DBE2FA01182F364D546B728990A7BEC5DCE3FB021920374E556C738A91A8BFC6DDE4FC031A21384F566D748B92A9B0C7DEE5FD041B223940576E758C93AAB1C8DFE6FE051C233A41586F768D94ABB2C9D0E7FF061D243B425960778E95ACB3CAD1E8F0071E253C435A61788F96ADB4CBD2E9F1081F263D445B62798097AEB5CCD3EAF20910273E455C637A8198AFB6CDD4EBF30A11283F465D647B8299A0B7CED5ECF +Out = F8824C2D09C4E60C2E4C0F9353A2EF15 + +Key = 25629347589242761D31F826BA4B757B +In = 64D546B728990A7BEC5DCE3FB021920374E556C738A91A8BFC6DDE4FC031A21384F566D748B92A9B0C7DEE5FD041B223940576E758C93AAB1C8DFE6FE051C233A41586F768D94ABB2C9D0E7FF061D243B425960778E95ACB3CAD1E8F0071E253C435A61788F96ADB4CBD2E9F1081F263D445B62798097AEB5CCD3EAF20910273E455C637A8198AFB6CDD4EBF30A11283F465D647B8299A0B7CED5ECF40B122930475E657C839AA1B8CFD6EDF50C132A31485F667D849BA2B9C0D7EEF60D142B324950677E859CA3BAC1D8EFF70E152C334A51687F869DA4BBC2D9E0F80F162D344B526970879EA5BCC3DAE1F900172E354C536A71889FA6BDC4DBE2FA01182F364D546B728990A7BEC5DCE3FB021920374E556C738A91A8BFC6DDE4FC031A21384F566D748B92A9B0C7DEE5FD041B223940576E758C93AAB1C8DFE6FE051C233A41586F768D94ABB2C9D0E7FF061D243B425960778E95ACB3CAD1E8F0071E253C435A61788F96ADB4CBD2E9F1081F263D445B62798097AEB5CCD3EAF20910273E455C637A8198AFB6CDD4EBF30A11283F465D647B8299A0B7CED5ECF40B122930475E657C839AA1B8CFD6EDF50C132A31485F667D849BA2B9C0D7EEF60D142B324950677E859CA3BAC1D8EFF70E152C334A51687F869DA4BBC2D9E0F80F162D344B526970879EA5BCC3DAE1F900172E354C536A71889FA6BDC4DBE2FA01182F364D546B728990A7BEC5DCE3FB021920374E556C738A91A8BFC6DDE4FC031A21384F566D748B92A9B0C7DEE5FD041B223940576E758C93AAB1C8DFE6FE051C233A41586F768D94ABB2C9D0E7FF061D243B425960778E95ACB3CAD1E8F0071E253C435A61788F96ADB4CBD2E9F1081F263D445B62798097AEB5CCD3EAF20910273E455C637A8198AFB6CDD4EBF30A11283F465D647B8299A0B7CED5ECF40B122930475E657C839AA1B8CFD6EDF50C132A31485F667D849BA2B9C0D7EEF60D142B324950677E859CA3BAC1D8EFF70E152C334A51687F869DA4BBC2D9E0F80F162D344B526970879EA5BCC3DAE1F900172E354C536A71889FA6BDC4DBE2FA01182F364D546B728990A7BEC5DCE3FB021920374E556C738A91A8BFC6DDE4FC031A21384F566D748B92A9B0C7DEE5FD041B223940576E758C93AAB1C8DFE6FE051C233A41586F768D94ABB2C9D0E7FF061D243B425960778E95ACB3CAD1E8F0071E253C435A61788F96ADB4CBD2E9F1081F263D445B62798097AEB5CCD3EAF20910273E455C637A8198AFB6CDD4EBF30A11283F465D647B8299A0B7CED5ECF40B122930475E657C839AA1B8CFD6EDF50C132A31485F667D849BA2B9C0D7EEF60D142B324950677E859CA3BAC1D8EFF70E152C334A51687F869DA4BBC2D9E0F80F162D344B526970879EA5BCC3DAE1F900172E354C536A71889FA6BDC4DBE2FA01182F364D546B728990A7BEC5DCE3FB021920374E556C738A91A8BFC6DDE4FC031A21384F566D748B92A9B0C7DEE5FD041B223940576E758C93AAB1C8DFE6FE051C233A41586F768D94ABB2C9D0E7FF061D243B425960778E95ACB3CAD1E8F0071E253C435A61788F96ADB4CBD2E9F1081F263D445B62798097AEB5CCD3EAF20910273E455C637A8198AFB6CDD4EBF30A11283F465D647B8299A0B7CED5ECF40B122930475E657C839AA1B8CFD6EDF50C132A31485F667D849BA2B9C0D7EEF60D142B324950677E859CA3BAC1D8EFF70E152C334A51687F869DA4BBC2D9E0F80F162D344B526970879EA5BCC3DAE1F900172E354C536A71889FA6BDC4DBE2FA01182F364D546B728990A7BEC5DCE3FB021920374E556C738A91A8BFC6DDE4FC031A21384F566D748B92A9B0C7DEE5FD041B223940576E758C93AAB1C8DFE6FE051C233A41586F768D94ABB2C9D0E7FF061D243B425960778E95ACB3CAD1E8F0071E253C435A61788F96ADB4CBD2E9F1081F263D445B62798097AEB5CCD3EAF20910273E455C637A8198AFB6CDD4EBF30A11283F465D647B8299A0B7CED5ECF40B122930475E657C839AA1B8CFD6EDF50C132A31485F667D849BA2B9C0D7EEF60D142B324950677E859CA3BAC1D8EFF70E152C334A51687F869DA4BBC2D9E0F80F162D344B526970879EA5BCC3DAE1F900172E354C536A71889FA6BDC4DBE2FA01182F364D546B728990A7BEC5DCE3FB021920374E556C738A91A8BFC6DDE4FC031A21384F566D748B92A9B0C7DEE5FD041B223940576E758C93AAB1C8DFE6FE051C233 +Out = 541F40C7740ECB13ADC63919D71666BA + +Key = D9B360279694941AC5DBC4987576CFC9 +In = 097AEB5CCD3EAF20910273E455C637A8198AFB6CDD4EBF30A11283F465D647B8 +Out = 1ACD990743BA05CFC2BB41E9800ECD3F + +Key = D9B360279694941AC5DBC4987576CFC9 +In = 0E7FF061D243B425960778E95ACB3CAD1E8F0071E253C435A61788F96ADB4CBD2E9F1081F263D445B62798097AEB5CCD3EAF20910273E455C637A8198AFB6CDD4EBF30A11283F465D647B8299A0B7CED5ECF40B122930475E657C839AA1B8CFD6EDF50C132A31485F667D849BA2B9C0D +Out = A99C82D8D964974744601B0E2870140D + +Key = D9B360279694941AC5DBC4987576CFC9 +In = 1788F96ADB4CBD2E9F1081F263D445B62798097AEB5CCD3EAF20910273E455C637A8198AFB6CDD4EBF30A11283F465D647B8299A0B7CED5ECF40B122930475E657C839AA1B8CFD6EDF50C132A31485F667D849BA2B9C0D7EEF60D142B324950677E859CA3BAC1D8EFF70E152C334A51687F869DA4BBC2D9E0F80F162D344B526970879EA5BCC3DAE1F900172E354C536A71889FA6BDC4DBE2FA01182F364D546B728990A7BEC5DCE3FB021920374E556C738A91A8BFC6DDE4FC031A21384F566D748B92A9B0C7DEE5FD041B223940576E758C93AAB1C8DFE6FE051C233A41586F768D94ABB2C9D0E7FF061D243B425960778E95ACB3CAD1E8F0071E253C435A6 +Out = F72478DF729FCD38F27D5909C0C465C9 + +Key = D9B360279694941AC5DBC4987576CFC9 +In = 2798097AEB5CCD3EAF20910273E455C637A8198AFB6CDD4EBF30A11283F465D647B8299A0B7CED5ECF40B122930475E657C839AA1B8CFD6EDF50C132A31485F667D849BA2B9C0D7EEF60D142B324950677E859CA3BAC1D8EFF70E152C334A51687F869DA4BBC2D9E0F80F162D344B526970879EA5BCC3DAE1F900172E354C536A71889FA6BDC4DBE2FA01182F364D546B728990A7BEC5DCE3FB021920374E556C738A91A8BFC6DDE4FC031A21384F566D748B92A9B0C7DEE5FD041B223940576E758C93AAB1C8DFE6FE051C233A41586F768D94ABB2C9D0E7FF061D243B425960778E95ACB3CAD1E8F0071E253C435A61788F96ADB4CBD2E9F1081F263D445B62798097AEB5CCD3EAF20910273E455C637A8198AFB6CDD4EBF30A11283F465D647B8299A0B7CED5ECF40B122930475E657C839AA1B8CFD6EDF50C132A31485F667D849BA2B9C0D7EEF60D142B324950677E859CA3BAC1D8EFF70E152C334A51687F869DA4BBC2D9E0F80F162D344B526970879EA5BCC3DAE1F900172E354C536A71889FA6BDC4DBE2FA01182F364D546B728990A7BEC5DCE3FB021920374E556C738A91A8BFC6DDE4FC031A21384F566D748B92A9B0C7DEE5FD041B223940576E758C93AAB1C8DFE6FE051C233A41586F768D94ABB2C9D0E7FF061D243B425960778E95ACB3CAD1E8F0071E253C435A61788F96ADB4CBD2E9F1081F263D445B6 +Out = 2A586D5B16905B6EBDCFEBF2765E8EF4 + +Key = D9B360279694941AC5DBC4987576CFC9 +In = 6BDC4DBE2FA01182F364D546B728990A7BEC5DCE3FB021920374E556C738A91A8BFC6DDE4FC031A21384F566D748B92A9B0C7DEE5FD041B223940576E758C93AAB1C8DFE6FE051C233A41586F768D94ABB2C9D0E7FF061D243B425960778E95ACB3CAD1E8F0071E253C435A61788F96ADB4CBD2E9F1081F263D445B62798097AEB5CCD3EAF20910273E455C637A8198AFB6CDD4EBF30A11283F465D647B8299A0B7CED5ECF40B122930475E657C839AA1B8CFD6EDF50C132A31485F667D849BA2B9C0D7EEF60D142B324950677E859CA3BAC1D8EFF70E152C334A51687F869DA4BBC2D9E0F80F162D344B526970879EA5BCC3DAE1F900172E354C536A71889FA6BDC4DBE2FA01182F364D546B728990A7BEC5DCE3FB021920374E556C738A91A8BFC6DDE4FC031A21384F566D748B92A9B0C7DEE5FD041B223940576E758C93AAB1C8DFE6FE051C233A41586F768D94ABB2C9D0E7FF061D243B425960778E95ACB3CAD1E8F0071E253C435A61788F96ADB4CBD2E9F1081F263D445B62798097AEB5CCD3EAF20910273E455C637A8198AFB6CDD4EBF30A11283F465D647B8299A0B7CED5ECF40B122930475E657C839AA1B8CFD6EDF50C132A31485F667D849BA2B9C0D7EEF60D142B324950677E859CA3BAC1D8EFF70E152C334A51687F869DA4BBC2D9E0F80F162D344B526970879EA5BCC3DAE1F900172E354C536A71889FA6BDC4DBE2FA01182F364D546B728990A7BEC5DCE3FB021920374E556C738A91A8BFC6DDE4FC031A21384F566D748B92A9B0C7DEE5FD041B223940576E758C93AAB1C8DFE6FE051C233A41586F768D94ABB2C9D0E7FF061D243B425960778E95ACB3CAD1E8F0071E253C435A61788F96ADB4CBD2E9F1081F263D445B62798097AEB5CCD3EAF20910273E455C637A8198AFB6CDD4EBF30A11283F465D647B8299A0B7CED5ECF40B122930475E657C839AA1B8CFD6EDF50C132A31485F667D849BA2B9C0D7EEF60D142B324950677E859CA3BAC1D8EFF70E152C334A51687F869DA4BBC2D9E0F80F162D344B526970879EA5BCC3DAE1F900172E354C536A71889FA6BDC4DBE2FA01182F364D546B728990A7BEC5DCE3FB021920374E556C738A91A8BFC6DDE4FC031A21384F566D748B92A9B0C7DEE5FD041B223940576E758C93AAB1C8DFE6FE051C233A41586F768D94ABB2C9D0E7FF061D243B425960778E95ACB3CAD1E8F0071E253C435A61788F96ADB4CBD2E9F1081F263D445B62798097AEB5CCD3EAF20910273E455C637A8198AFB6CDD4EBF30A11283F465D647B8299A0B7CED5ECF40B122930475E657C839AA1B8CFD6EDF50C132A31485F667D849BA2B9C0D7EEF60D142B324950677E859CA3BAC1D8EFF70E152C334A51687F869DA4BBC2D9E0F80F162D344B526970879EA5BCC3DAE1F900172E354C536A71889FA6BDC4DBE2FA01182F364D546B728990A7BEC5DCE3FB021920374E556C738A91A8BFC6DDE4FC031A21384F566D748B92A9B0C7DEE5FD041B223940576E758C93AAB1C8DFE6FE051C233A41586F768D94ABB2C9D0E7FF061D243B425960778E95ACB3CAD1E8F0071E253C435A61788F96ADB4CBD2E9F1081F263D445B62798097AEB5CCD3EAF20910273E455C637A8198AFB6CDD4EBF30A11283F465D647B8299A0B7CED5ECF40B122930475E657C839AA1B8CFD6EDF50C132A31485F667D849BA2B9C0D7EEF60D142B324950677E859CA3BAC1D8EFF70E152C334A51687F869DA4BBC2D9E0F80F162D344B526970879EA5BCC3DAE1F900172E354C536A71889FA6BDC4DBE2FA01182F364D546B728990A7BEC5DCE3FB021920374E556C738A91A8BFC6DDE4FC031A21384F566D748B92A9B0C7DEE5FD041B223940576E758C93AAB1C8DFE6FE051C233A41586F768D94ABB2C9D0E7FF061D243B425960778E95ACB3CAD1E8F0071E253C435A61788F96ADB4CBD2E9F1081F263D445B62798097AEB5CCD3EAF20910273E455C637A8198AFB6CDD4EBF30A11283F465D647B8299A0B7CED5ECF40B122930475E657C839AA1B8CFD6EDF50C132A31485F667D849BA2B9C0D7EEF60D142B324950677E859CA3BAC1D8EFF70E152C334A51687F869DA4BBC2D9E0F80F162D344B526970879EA5BCC3DAE1F900172E354C536A71889FA6BDC4DBE2FA01182F364D546B728990A7BEC5DCE3FB021920374E556C738A91A8BFC6DDE4FC031A21384F566D748B92A9B0C7DEE5FD041B223940576E758C93A +Out = 6A758FE38E8A97F6B7B7B3F68A579BCE + +Key = 01000000000000000000000000000000 +In = 1081F263D445B62798097AEB5CCD3EAF20910273E455C637A8198AFB6CDD4EBF +Out = 55FEC5B4E148FBFBAA013A4B1E37BC37 + +Key = 01000000000000000000000000000000 +In = 1586F768D94ABB2C9D0E7FF061D243B425960778E95ACB3CAD1E8F0071E253C435A61788F96ADB4CBD2E9F1081F263D445B62798097AEB5CCD3EAF20910273E455C637A8198AFB6CDD4EBF30A11283F465D647B8299A0B7CED5ECF40B122930475E657C839AA1B8CFD6EDF50C132A314 +Out = B212DFB83395E5DC140FF6B008CD22AE + +Key = 01000000000000000000000000000000 +In = 1E8F0071E253C435A61788F96ADB4CBD2E9F1081F263D445B62798097AEB5CCD3EAF20910273E455C637A8198AFB6CDD4EBF30A11283F465D647B8299A0B7CED5ECF40B122930475E657C839AA1B8CFD6EDF50C132A31485F667D849BA2B9C0D7EEF60D142B324950677E859CA3BAC1D8EFF70E152C334A51687F869DA4BBC2D9E0F80F162D344B526970879EA5BCC3DAE1F900172E354C536A71889FA6BDC4DBE2FA01182F364D546B728990A7BEC5DCE3FB021920374E556C738A91A8BFC6DDE4FC031A21384F566D748B92A9B0C7DEE5FD041B223940576E758C93AAB1C8DFE6FE051C233A41586F768D94ABB2C9D0E7FF061D243B425960778E95ACB3CAD +Out = 2A2BD312EBF022458C50F07C401FB811 + +Key = 01000000000000000000000000000000 +In = 2E9F1081F263D445B62798097AEB5CCD3EAF20910273E455C637A8198AFB6CDD4EBF30A11283F465D647B8299A0B7CED5ECF40B122930475E657C839AA1B8CFD6EDF50C132A31485F667D849BA2B9C0D7EEF60D142B324950677E859CA3BAC1D8EFF70E152C334A51687F869DA4BBC2D9E0F80F162D344B526970879EA5BCC3DAE1F900172E354C536A71889FA6BDC4DBE2FA01182F364D546B728990A7BEC5DCE3FB021920374E556C738A91A8BFC6DDE4FC031A21384F566D748B92A9B0C7DEE5FD041B223940576E758C93AAB1C8DFE6FE051C233A41586F768D94ABB2C9D0E7FF061D243B425960778E95ACB3CAD1E8F0071E253C435A61788F96ADB4CBD2E9F1081F263D445B62798097AEB5CCD3EAF20910273E455C637A8198AFB6CDD4EBF30A11283F465D647B8299A0B7CED5ECF40B122930475E657C839AA1B8CFD6EDF50C132A31485F667D849BA2B9C0D7EEF60D142B324950677E859CA3BAC1D8EFF70E152C334A51687F869DA4BBC2D9E0F80F162D344B526970879EA5BCC3DAE1F900172E354C536A71889FA6BDC4DBE2FA01182F364D546B728990A7BEC5DCE3FB021920374E556C738A91A8BFC6DDE4FC031A21384F566D748B92A9B0C7DEE5FD041B223940576E758C93AAB1C8DFE6FE051C233A41586F768D94ABB2C9D0E7FF061D243B425960778E95ACB3CAD1E8F0071E253C435A61788F96ADB4CBD +Out = 25A3E0AF2A6C7F149BB8145DB2859C74 + +Key = 01000000000000000000000000000000 +In = 72E354C536A71889FA6BDC4DBE2FA01182F364D546B728990A7BEC5DCE3FB021920374E556C738A91A8BFC6DDE4FC031A21384F566D748B92A9B0C7DEE5FD041B223940576E758C93AAB1C8DFE6FE051C233A41586F768D94ABB2C9D0E7FF061D243B425960778E95ACB3CAD1E8F0071E253C435A61788F96ADB4CBD2E9F1081F263D445B62798097AEB5CCD3EAF20910273E455C637A8198AFB6CDD4EBF30A11283F465D647B8299A0B7CED5ECF40B122930475E657C839AA1B8CFD6EDF50C132A31485F667D849BA2B9C0D7EEF60D142B324950677E859CA3BAC1D8EFF70E152C334A51687F869DA4BBC2D9E0F80F162D344B526970879EA5BCC3DAE1F900172E354C536A71889FA6BDC4DBE2FA01182F364D546B728990A7BEC5DCE3FB021920374E556C738A91A8BFC6DDE4FC031A21384F566D748B92A9B0C7DEE5FD041B223940576E758C93AAB1C8DFE6FE051C233A41586F768D94ABB2C9D0E7FF061D243B425960778E95ACB3CAD1E8F0071E253C435A61788F96ADB4CBD2E9F1081F263D445B62798097AEB5CCD3EAF20910273E455C637A8198AFB6CDD4EBF30A11283F465D647B8299A0B7CED5ECF40B122930475E657C839AA1B8CFD6EDF50C132A31485F667D849BA2B9C0D7EEF60D142B324950677E859CA3BAC1D8EFF70E152C334A51687F869DA4BBC2D9E0F80F162D344B526970879EA5BCC3DAE1F900172E354C536A71889FA6BDC4DBE2FA01182F364D546B728990A7BEC5DCE3FB021920374E556C738A91A8BFC6DDE4FC031A21384F566D748B92A9B0C7DEE5FD041B223940576E758C93AAB1C8DFE6FE051C233A41586F768D94ABB2C9D0E7FF061D243B425960778E95ACB3CAD1E8F0071E253C435A61788F96ADB4CBD2E9F1081F263D445B62798097AEB5CCD3EAF20910273E455C637A8198AFB6CDD4EBF30A11283F465D647B8299A0B7CED5ECF40B122930475E657C839AA1B8CFD6EDF50C132A31485F667D849BA2B9C0D7EEF60D142B324950677E859CA3BAC1D8EFF70E152C334A51687F869DA4BBC2D9E0F80F162D344B526970879EA5BCC3DAE1F900172E354C536A71889FA6BDC4DBE2FA01182F364D546B728990A7BEC5DCE3FB021920374E556C738A91A8BFC6DDE4FC031A21384F566D748B92A9B0C7DEE5FD041B223940576E758C93AAB1C8DFE6FE051C233A41586F768D94ABB2C9D0E7FF061D243B425960778E95ACB3CAD1E8F0071E253C435A61788F96ADB4CBD2E9F1081F263D445B62798097AEB5CCD3EAF20910273E455C637A8198AFB6CDD4EBF30A11283F465D647B8299A0B7CED5ECF40B122930475E657C839AA1B8CFD6EDF50C132A31485F667D849BA2B9C0D7EEF60D142B324950677E859CA3BAC1D8EFF70E152C334A51687F869DA4BBC2D9E0F80F162D344B526970879EA5BCC3DAE1F900172E354C536A71889FA6BDC4DBE2FA01182F364D546B728990A7BEC5DCE3FB021920374E556C738A91A8BFC6DDE4FC031A21384F566D748B92A9B0C7DEE5FD041B223940576E758C93AAB1C8DFE6FE051C233A41586F768D94ABB2C9D0E7FF061D243B425960778E95ACB3CAD1E8F0071E253C435A61788F96ADB4CBD2E9F1081F263D445B62798097AEB5CCD3EAF20910273E455C637A8198AFB6CDD4EBF30A11283F465D647B8299A0B7CED5ECF40B122930475E657C839AA1B8CFD6EDF50C132A31485F667D849BA2B9C0D7EEF60D142B324950677E859CA3BAC1D8EFF70E152C334A51687F869DA4BBC2D9E0F80F162D344B526970879EA5BCC3DAE1F900172E354C536A71889FA6BDC4DBE2FA01182F364D546B728990A7BEC5DCE3FB021920374E556C738A91A8BFC6DDE4FC031A21384F566D748B92A9B0C7DEE5FD041B223940576E758C93AAB1C8DFE6FE051C233A41586F768D94ABB2C9D0E7FF061D243B425960778E95ACB3CAD1E8F0071E253C435A61788F96ADB4CBD2E9F1081F263D445B62798097AEB5CCD3EAF20910273E455C637A8198AFB6CDD4EBF30A11283F465D647B8299A0B7CED5ECF40B122930475E657C839AA1B8CFD6EDF50C132A31485F667D849BA2B9C0D7EEF60D142B324950677E859CA3BAC1D8EFF70E152C334A51687F869DA4BBC2D9E0F80F162D344B526970879EA5BCC3DAE1F900172E354C536A71889FA6BDC4DBE2FA01182F364D546B728990A7BEC5DCE3FB021920374E556C738A91A8BFC6DDE4FC031A21384F566D748B92A9B0C7DEE5FD041 +Out = 3220FC64561D5314332A0FFCD9F2C6D2 diff --git a/src/tests/test_polyval.cpp b/src/tests/test_polyval.cpp new file mode 100644 index 00000000000..a0ebd820ba9 --- /dev/null +++ b/src/tests/test_polyval.cpp @@ -0,0 +1,117 @@ +/* +* (C) 2026 Jack Lloyd +* +* Botan is released under the Simplified BSD License (see license.txt) +*/ + +#include "tests.h" + +#if defined(BOTAN_HAS_POLYVAL) + #include + #include + #include +#endif + +namespace Botan_Tests { + +namespace { + +#if defined(BOTAN_HAS_POLYVAL) + +class Polyval_Tests final : public Text_Based_Test { + public: + Polyval_Tests() : Text_Based_Test("polyval.vec", "Key,In,Out") {} + + Test::Result run_one_test(const std::string& /*header*/, const VarMap& vars) override { + Test::Result result("POLYVAL"); + + const std::vector key = vars.get_req_bin("Key"); + const std::vector input = vars.get_req_bin("In"); + const std::vector expected = vars.get_req_bin("Out"); + + Botan::Polyval polyval; + std::array digest{}; + + result.test_throws("POLYVAL update requires a key", [&]() { polyval.update(input); }); + result.test_throws("POLYVAL final requires a key", [&]() { polyval.final(digest); }); + + polyval.set_key(key); + + polyval.update(input); + polyval.final(digest); + result.test_bin_eq("POLYVAL one-shot", digest, expected); + + // final resets the state, allowing hashing a further message + polyval.update(input); + polyval.final(digest); + result.test_bin_eq("POLYVAL reused after final", digest, expected); + + // Splitting the input must not affect the result + const size_t split_step = (input.size() <= 256) ? 1 : 37; + for(size_t split = 1; split < input.size(); split += split_step) { + polyval.update(std::span{input}.first(split)); + polyval.update(std::span{input}.subspan(split)); + polyval.final(digest); + result.test_bin_eq("POLYVAL split input", digest, expected); + } + + // Nor must feeding the input in small chunks + for(const size_t chunk : {1, 3, 7, 9, 16, 33}) { + for(size_t off = 0; off < input.size(); off += chunk) { + polyval.update(std::span{input}.subspan(off, std::min(chunk, input.size() - off))); + } + polyval.final(digest); + result.test_bin_eq("POLYVAL chunked input", digest, expected); + } + + return result; + } + + std::vector run_final_tests() override { + Test::Result result("POLYVAL"); + + const auto key = Botan::hex_decode("25629347589242761D31F826BA4B757B"); + const auto block = Botan::hex_decode("4F4F95668C83DFB6401762BB2D01A262"); + + Botan::Polyval p1; + Botan::Polyval p2; + p1.set_key(key); + p2.set_key(key); + + std::array d1{}; + std::array d2{}; + + // zero_pad is equivalent to explicitly padding with zeros + p1.update(std::span{block}.first(12)); + p1.zero_pad(); + p1.final(d1); + + std::vector padded(block.begin(), block.begin() + 12); + padded.resize(16); + p2.update(padded); + p2.final(d2); + result.test_bin_eq("zero_pad matches explicit zero padding", d1, d2); + + // zero_pad of block aligned input does nothing + p1.update(block); + p1.zero_pad(); + p1.update(block); + p1.zero_pad(); + p1.final(d1); + + p2.update(block); + p2.update(block); + p2.final(d2); + result.test_bin_eq("zero_pad of aligned input is a no-op", d1, d2); + + return {result}; + } +}; + +BOTAN_REGISTER_SERIALIZED_TEST("utils", "polyval", Polyval_Tests); + +#endif + +} // namespace + +} // namespace Botan_Tests