Skip to content

Commit

Permalink
Allow for RFC8439 AD in cipher suite interface
Browse files Browse the repository at this point in the history
  • Loading branch information
dhruv committed Mar 28, 2023
1 parent 0391176 commit 763f2e9
Show file tree
Hide file tree
Showing 5 changed files with 35 additions and 14 deletions.
4 changes: 2 additions & 2 deletions src/bench/bip324_suite.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -35,15 +35,15 @@ static void BIP324_CIPHER_SUITE(benchmark::Bench& bench, size_t contents_len, bo

bench.batch(contents_len).unit("byte").run([&] {
// encrypt or decrypt the buffer with a static key
const bool crypt_ok_1 = enc.Crypt(in, out, flags, true);
const bool crypt_ok_1 = enc.Crypt({}, in, out, flags, true);
assert(crypt_ok_1);

if (include_decryption) {
// if we decrypt, we need to decrypt the length first
std::array<std::byte, BIP324_LENGTH_FIELD_LEN> encrypted_pkt_len;
std::memcpy(encrypted_pkt_len.data(), out.data(), BIP324_LENGTH_FIELD_LEN);
(void)dec.DecryptLength(encrypted_pkt_len);
const bool crypt_ok_2 = dec.Crypt({out.data() + BIP324_LENGTH_FIELD_LEN, out.size() - BIP324_LENGTH_FIELD_LEN}, in, flags, false);
const bool crypt_ok_2 = dec.Crypt({}, {out.data() + BIP324_LENGTH_FIELD_LEN, out.size() - BIP324_LENGTH_FIELD_LEN}, in, flags, false);
assert(crypt_ok_2);
}
});
Expand Down
8 changes: 5 additions & 3 deletions src/crypto/bip324_suite.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,9 @@ void BIP324CipherSuite::Rekey()
rekey_c20.Keystream(reinterpret_cast<unsigned char*>(key_P.data()), BIP324_KEY_LEN);
}

bool BIP324CipherSuite::Crypt(const Span<const std::byte> input, Span<std::byte> output,
bool BIP324CipherSuite::Crypt(const Span<const std::byte> aad,
const Span<const std::byte> input,
Span<std::byte> output,
BIP324HeaderFlags& flags, bool encrypt)
{
// check buffer boundaries
Expand Down Expand Up @@ -58,13 +60,13 @@ bool BIP324CipherSuite::Crypt(const Span<const std::byte> input, Span<std::byte>
fsc20.Crypt({reinterpret_cast<std::byte*>(&contents_len), BIP324_LENGTH_FIELD_LEN},
{write_pos, BIP324_LENGTH_FIELD_LEN});
write_pos += BIP324_LENGTH_FIELD_LEN;
RFC8439Encrypt({}, key_P, nonce, header_and_contents, {write_pos, BIP324_HEADER_LEN + input.size() + RFC8439_EXPANSION});
RFC8439Encrypt(aad, key_P, nonce, header_and_contents, {write_pos, BIP324_HEADER_LEN + input.size() + RFC8439_EXPANSION});
} else {
// we must use BIP324CipherSuite::DecryptLength before calling BIP324CipherSuite::Crypt
// input is encrypted (header + contents) and the MAC tag i.e. the RFC8439 ciphertext blob
// decrypted header will be put in flags and output will be plaintext contents.
std::vector<std::byte> decrypted_header_and_contents(input.size() - RFC8439_EXPANSION);
auto authenticated = RFC8439Decrypt({}, key_P, nonce, input, decrypted_header_and_contents);
auto authenticated = RFC8439Decrypt(aad, key_P, nonce, input, decrypted_header_and_contents);
if (!authenticated) {
return false;
}
Expand Down
5 changes: 4 additions & 1 deletion src/crypto/bip324_suite.h
Original file line number Diff line number Diff line change
Expand Up @@ -58,7 +58,10 @@ class BIP324CipherSuite
Returns true upon success. Upon failure, the output should not be used.
*/
[[nodiscard]] bool Crypt(const Span<const std::byte> input, Span<std::byte> output, BIP324HeaderFlags& flags, bool encrypt);
[[nodiscard]] bool Crypt(const Span<const std::byte> aad,
const Span<const std::byte> input,
Span<std::byte> output,
BIP324HeaderFlags& flags, bool encrypt);

/** Decrypts the 3 byte encrypted length field (the packet header and contents length) and decodes it into a uint32_t field
The FSChaCha20 keystream will advance. As a result, DecryptLength() cannot be called multiple times to get the same result. The caller must cache the result for re-use.
Expand Down
28 changes: 21 additions & 7 deletions src/test/crypto_tests.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -851,7 +851,7 @@ BOOST_AUTO_TEST_CASE(hkdf_hmac_sha256_l32_tests)
"8da4e775a563c18f715f802a063c5a31b8a11f5c5ee1879ec3454e5f3c738d2d");
}

static void TestBIP324CipherSuite(const std::string& hex_contents, const std::string& hex_key_L, const std::string& hex_key_P, const std::string& hex_expected_output_seq_0, const std::string& hex_expected_output_seq_999)
static void TestBIP324CipherSuite(const std::string& hex_aad, const std::string& hex_contents, const std::string& hex_key_L, const std::string& hex_key_P, const std::string& hex_expected_output_seq_0, const std::string& hex_expected_output_seq_999)
{
auto key_L_vec = ParseHex(hex_key_L);
BIP324Key key_L;
Expand All @@ -861,6 +861,8 @@ static void TestBIP324CipherSuite(const std::string& hex_contents, const std::st
BIP324Key key_P;
std::memcpy(key_P.data(), key_P_vec.data(), BIP324_KEY_LEN);

auto aad = ParseHex(hex_aad);

const auto original_contents_bytes = ParseHex(hex_contents);
auto contents_buf = original_contents_bytes;

Expand All @@ -877,7 +879,7 @@ static void TestBIP324CipherSuite(const std::string& hex_contents, const std::st
// encrypt / decrypt the packet 1000 times
for (size_t i = 0; i < 1000; ++i) {
// encrypt
auto res = suite_enc.Crypt(MakeByteSpan(contents_buf), MakeWritableByteSpan(encrypted_pkt), flags, true);
auto res = suite_enc.Crypt(MakeByteSpan(aad), MakeByteSpan(contents_buf), MakeWritableByteSpan(encrypted_pkt), flags, true);
BOOST_CHECK(res);
// verify ciphertext & mac against the test vector
if (i == 0) {
Expand All @@ -890,7 +892,7 @@ static void TestBIP324CipherSuite(const std::string& hex_contents, const std::st
out_len = suite_dec.DecryptLength(encrypted_pkt_len);
BOOST_CHECK_EQUAL(out_len, contents_buf.size());

res = suite_dec.Crypt({reinterpret_cast<std::byte*>(encrypted_pkt.data()) + BIP324_LENGTH_FIELD_LEN, encrypted_pkt.size() - BIP324_LENGTH_FIELD_LEN}, MakeWritableByteSpan(contents_buf_dec), flags, false);
res = suite_dec.Crypt(MakeByteSpan(aad), {reinterpret_cast<std::byte*>(encrypted_pkt.data()) + BIP324_LENGTH_FIELD_LEN, encrypted_pkt.size() - BIP324_LENGTH_FIELD_LEN}, MakeWritableByteSpan(contents_buf_dec), flags, false);
BOOST_CHECK(res);
BOOST_CHECK_EQUAL(flags, BIP324_NONE);

Expand All @@ -908,29 +910,41 @@ BOOST_AUTO_TEST_CASE(bip324_cipher_suite_testvectors)

// encrypting an empty message should result in 20 bytes:
// 3 bytes of encrypted length, 1 byte header and 16 bytes MAC
TestBIP324CipherSuite(/* plaintext */ "",
TestBIP324CipherSuite(/* aad */ "",
/* plaintext */ "",
/* k_l */ "0000000000000000000000000000000000000000000000000000000000000000",
/* k_p */ "0000000000000000000000000000000000000000000000000000000000000000",
/* ciphertext_and_mac_0 */ "76b8e09fbedcfd1809ff3c10adf8277fcc0581b8",
/* ciphertext_and_mac_999 */ "5dd1ef229ae773099415b4ae56d003d21b4e4a08");

TestBIP324CipherSuite("0000000000000000000000000000000000000000000000000000000000000000",
TestBIP324CipherSuite("",
"0000000000000000000000000000000000000000000000000000000000000000",
"0000000000000000000000000000000000000000000000000000000000000000",
"0000000000000000000000000000000000000000000000000000000000000000",
"56b8e09f07e7be5551387a98ba977c732d080dcb0f29a048e3656912c6533e32ee7aed29e7e38bb44c94b6a43c525ffca66c79e9",
"7dd1ef2205b549ef8e0dc60b16342f037e415cfcd3d6111532f8f9e7553e422129d9df0d58e083ad538381c1e30a51a5d296cce2");

TestBIP324CipherSuite("0100000000000000000000000000000000000000000000000000000000000000",
TestBIP324CipherSuite("",
"0100000000000000000000000000000000000000000000000000000000000000",
"0000000000000000000000000000000000000000000000000000000000000000",
"0000000000000000000000000000000000000000000000000000000000000000",
"56b8e09f06e7be5551387a98ba977c732d080dcb0f29a048e3656912c6533e32ee7aed2929449b86c1e4e213676824f2c48e5336",
"7dd1ef2204b549ef8e0dc60b16342f037e415cfcd3d6111532f8f9e7553e422129d9df0d04fc5b2ab5cb70895a90edddbe642c00");

TestBIP324CipherSuite("fc0000f195e66982105ffb640bb7757f579da31602fc93ec01ac56f85ac3c134a4547b733b46413042c9440049176905d3be59ea1c53f15916155c2be8241a38008b9a26bc35941e2444177c8ade6689de95264986d95889fb60e84629c9bd9a5acb1cc118be563eb9b3a4a472f82e09a7e778492b562ef7130e88dfe031c79db9d4f7c7a899151b9a475032b63fc385245fe054e3dd5a97a5f576fe064025d3ce042c566ab2c507b138db853e3d6959660996546cc9c4a6eafdc777c040d70eaf46f76dad3979e5c5360c3317166a1c894c94a371876a94df7628fe4eaaf2ccb27d5aaae0ad7ad0f9d4b6ad3b54098746d4524d38407a6deb3ab78fab78c9",
TestBIP324CipherSuite("",
"fc0000f195e66982105ffb640bb7757f579da31602fc93ec01ac56f85ac3c134a4547b733b46413042c9440049176905d3be59ea1c53f15916155c2be8241a38008b9a26bc35941e2444177c8ade6689de95264986d95889fb60e84629c9bd9a5acb1cc118be563eb9b3a4a472f82e09a7e778492b562ef7130e88dfe031c79db9d4f7c7a899151b9a475032b63fc385245fe054e3dd5a97a5f576fe064025d3ce042c566ab2c507b138db853e3d6959660996546cc9c4a6eafdc777c040d70eaf46f76dad3979e5c5360c3317166a1c894c94a371876a94df7628fe4eaaf2ccb27d5aaae0ad7ad0f9d4b6ad3b54098746d4524d38407a6deb3ab78fab78c9",
"ff0102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f",
"000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f",
"3940c1184442315c7340b89171039acb48f95287e66e56f7afa7cf00f95044d26fb69d46ac5c16a2d57a1cadc39160644717559e73480734410a3f543c5f231a7d7ed77af2a64681f6a7417283cef85504ac5de9fdea100e6c67ef7a1bfcd888a92a5f1ef2c9074b44b572aa748f29ff61a850ce40470004dff5cc1d926c5abe25ace47a12c5373094a26bab027e008154fb630aa062490b5421e96691a3f79557f7a79e3cfd9100796671ea241703ddf326f113adf1694bbd6e0ca032e16f936e7bfbf174e7ef4af5b53a6a9102e6fa41a8e589290f39a7bc7a6003088c612a43a36c2e9f2e740797ad3a2a1a80e0f67157fb9abc40487077368e94751a266a0b2dac24f0adabd5c6d7ba54316eee951da560",
"2db339c8500d35db91994138b4ab5e698086b4ec7fb66e75d083b18f84a9da7d696be75c349cb1555a58f65f123d4b68e2be2277fd7b38ba26ad93040a22ac8f7782b00d75c7650dcff0442f7ef91980aaabecb2c8cefec5d5eb9d495b5e1768fe316ec2a0d69d46b7289cd2e2049f27d30a6183605651d48ac40e0d06af9ec7012d477e473f2af7842335c36acf4f5bdef45605ca243b9007b5363f095850a78945508cf3fa191b8fe7fc5359d6e00741e6504f1d50904152622f4c0bdeaa0745f00d28b995543621c96d9d9d30fa1fbf403b19a716411b1700e8401a3e1e01bb1546653fbda19d83ba5e561695baea229880ff33058f85754fe9fdc09db4491f47ae64ec030ec6163d2838d9474d40ef0579");

// Repeat test with non-empty aad - only mac tags (last 16 bytes) in the expected outputs change
TestBIP324CipherSuite("c6d7bc3a5079ae98fec7094bdfb42aac61d3ba64af179d672c7c33fd4a139647",
"fc0000f195e66982105ffb640bb7757f579da31602fc93ec01ac56f85ac3c134a4547b733b46413042c9440049176905d3be59ea1c53f15916155c2be8241a38008b9a26bc35941e2444177c8ade6689de95264986d95889fb60e84629c9bd9a5acb1cc118be563eb9b3a4a472f82e09a7e778492b562ef7130e88dfe031c79db9d4f7c7a899151b9a475032b63fc385245fe054e3dd5a97a5f576fe064025d3ce042c566ab2c507b138db853e3d6959660996546cc9c4a6eafdc777c040d70eaf46f76dad3979e5c5360c3317166a1c894c94a371876a94df7628fe4eaaf2ccb27d5aaae0ad7ad0f9d4b6ad3b54098746d4524d38407a6deb3ab78fab78c9",
"ff0102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f",
"000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f",
"3940c1184442315c7340b89171039acb48f95287e66e56f7afa7cf00f95044d26fb69d46ac5c16a2d57a1cadc39160644717559e73480734410a3f543c5f231a7d7ed77af2a64681f6a7417283cef85504ac5de9fdea100e6c67ef7a1bfcd888a92a5f1ef2c9074b44b572aa748f29ff61a850ce40470004dff5cc1d926c5abe25ace47a12c5373094a26bab027e008154fb630aa062490b5421e96691a3f79557f7a79e3cfd9100796671ea241703ddf326f113adf1694bbd6e0ca032e16f936e7bfbf174e7ef4af5b53a6a9102e6fa41a8e589290f39a7bc7a6003088c612a43a36c2e9f2e740797ad3a2a1a80e0f67157fb9abc40487077368e94751a266a0b2dac4d382097b958da569f3b6fae3faaaaf2",
"2db339c8500d35db91994138b4ab5e698086b4ec7fb66e75d083b18f84a9da7d696be75c349cb1555a58f65f123d4b68e2be2277fd7b38ba26ad93040a22ac8f7782b00d75c7650dcff0442f7ef91980aaabecb2c8cefec5d5eb9d495b5e1768fe316ec2a0d69d46b7289cd2e2049f27d30a6183605651d48ac40e0d06af9ec7012d477e473f2af7842335c36acf4f5bdef45605ca243b9007b5363f095850a78945508cf3fa191b8fe7fc5359d6e00741e6504f1d50904152622f4c0bdeaa0745f00d28b995543621c96d9d9d30fa1fbf403b19a716411b1700e8401a3e1e01bb1546653fbda19d83ba5e561695baea229880ff33058f85754fe9fdc09db4491f47ae0623cf23941a59b7c7dc6cad9bd97cc1");
}

BOOST_AUTO_TEST_CASE(countbits_tests)
Expand Down
4 changes: 3 additions & 1 deletion src/test/fuzz/crypto_bip324_suite.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,8 @@ FUZZ_TARGET(crypto_bip324_suite)
std::vector<std::byte> out(BIP324_LENGTH_FIELD_LEN + BIP324_HEADER_LEN + contents_size + RFC8439_EXPANSION, std::byte{0x00});
bool is_encrypt = fdp.ConsumeBool();
BIP324HeaderFlags flags{fdp.ConsumeIntegralInRange<uint8_t>(0, 255)};
size_t aad_size = fdp.ConsumeIntegralInRange<size_t>(0, 255);
auto aad = fdp.ConsumeBytes<std::byte>(aad_size);
LIMITED_WHILE(fdp.ConsumeBool(), 10000)
{
CallOneOf(
Expand All @@ -49,7 +51,7 @@ FUZZ_TARGET(crypto_bip324_suite)
flags = BIP324HeaderFlags{fdp.ConsumeIntegralInRange<uint8_t>(0, 255)};
},
[&] {
(void)suite.Crypt(in, out, flags, is_encrypt);
(void)suite.Crypt(aad, in, out, flags, is_encrypt);
},
[&] {
std::array<std::byte, BIP324_LENGTH_FIELD_LEN> encrypted_pkt_len;
Expand Down

0 comments on commit 763f2e9

Please sign in to comment.