|
|
|
@ -70,10 +70,13 @@ void TestBIP324PacketVector(
|
|
|
|
|
BOOST_CHECK(Span{mid_send_garbage} == cipher.GetSendGarbageTerminator());
|
|
|
|
|
BOOST_CHECK(Span{mid_recv_garbage} == cipher.GetReceiveGarbageTerminator());
|
|
|
|
|
|
|
|
|
|
// Vector of encrypted empty messages, encrypted in order to seek to the right position.
|
|
|
|
|
std::vector<std::vector<std::byte>> dummies(in_idx);
|
|
|
|
|
|
|
|
|
|
// Seek to the numbered packet.
|
|
|
|
|
for (uint32_t i = 0; i < in_idx; ++i) {
|
|
|
|
|
std::vector<std::byte> dummy(cipher.EXPANSION);
|
|
|
|
|
cipher.Encrypt({}, {}, false, dummy);
|
|
|
|
|
dummies[i].resize(cipher.EXPANSION);
|
|
|
|
|
cipher.Encrypt({}, {}, true, dummies[i]);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Construct contents and encrypt it.
|
|
|
|
@ -93,9 +96,68 @@ void TestBIP324PacketVector(
|
|
|
|
|
BOOST_CHECK(Span{out_ciphertext_endswith} == Span{ciphertext}.last(out_ciphertext_endswith.size()));
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Note that we don't test decryption here, as the test vectors don't provide the other party's
|
|
|
|
|
// private key, so we cannot act like them. See the bip324_cipher_roundtrip fuzz test for a test
|
|
|
|
|
// that does cover decryption.
|
|
|
|
|
for (unsigned error = 0; error <= 12; ++error) {
|
|
|
|
|
// error selects a type of error introduced:
|
|
|
|
|
// - error=0: no errors, decryption should be successful
|
|
|
|
|
// - error=1: wrong side
|
|
|
|
|
// - error=2..9: bit error in ciphertext
|
|
|
|
|
// - error=10: bit error in aad
|
|
|
|
|
// - error=11: extra 0x00 at end of aad
|
|
|
|
|
// - error=12: message index wrong
|
|
|
|
|
|
|
|
|
|
// Instantiate self-decrypting BIP324 cipher.
|
|
|
|
|
BIP324Cipher dec_cipher(key, ellswift_ours);
|
|
|
|
|
BOOST_CHECK(!dec_cipher);
|
|
|
|
|
BOOST_CHECK(dec_cipher.GetOurPubKey() == ellswift_ours);
|
|
|
|
|
dec_cipher.Initialize(ellswift_theirs, (error == 1) ^ in_initiating, /*self_decrypt=*/true);
|
|
|
|
|
BOOST_CHECK(dec_cipher);
|
|
|
|
|
|
|
|
|
|
// Compare session variables.
|
|
|
|
|
BOOST_CHECK((Span{out_session_id} == dec_cipher.GetSessionID()) == (error != 1));
|
|
|
|
|
BOOST_CHECK((Span{mid_send_garbage} == dec_cipher.GetSendGarbageTerminator()) == (error != 1));
|
|
|
|
|
BOOST_CHECK((Span{mid_recv_garbage} == dec_cipher.GetReceiveGarbageTerminator()) == (error != 1));
|
|
|
|
|
|
|
|
|
|
// Seek to the numbered packet.
|
|
|
|
|
if (in_idx == 0 && error == 12) continue;
|
|
|
|
|
uint32_t dec_idx = in_idx ^ (error == 12 ? (1U << InsecureRandRange(16)) : 0);
|
|
|
|
|
for (uint32_t i = 0; i < dec_idx; ++i) {
|
|
|
|
|
unsigned use_idx = i < in_idx ? i : 0;
|
|
|
|
|
bool dec_ignore{false};
|
|
|
|
|
dec_cipher.DecryptLength(Span{dummies[use_idx]}.first(cipher.LENGTH_LEN));
|
|
|
|
|
dec_cipher.Decrypt(Span{dummies[use_idx]}.subspan(cipher.LENGTH_LEN), {}, dec_ignore, {});
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Construct copied (and possibly damaged) copy of ciphertext.
|
|
|
|
|
// Decrypt length
|
|
|
|
|
auto to_decrypt = ciphertext;
|
|
|
|
|
if (error >= 2 && error <= 9) {
|
|
|
|
|
to_decrypt[InsecureRandRange(to_decrypt.size())] ^= std::byte(1U << InsecureRandRange(8));
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Decrypt length and resize ciphertext to accomodate.
|
|
|
|
|
uint32_t dec_len = dec_cipher.DecryptLength(MakeByteSpan(to_decrypt).first(cipher.LENGTH_LEN));
|
|
|
|
|
to_decrypt.resize(dec_len + cipher.EXPANSION);
|
|
|
|
|
|
|
|
|
|
// Construct copied (and possibly damaged) copy of aad.
|
|
|
|
|
auto dec_aad = in_aad;
|
|
|
|
|
if (error == 10) {
|
|
|
|
|
if (in_aad.size() == 0) continue;
|
|
|
|
|
dec_aad[InsecureRandRange(dec_aad.size())] ^= std::byte(1U << InsecureRandRange(8));
|
|
|
|
|
}
|
|
|
|
|
if (error == 11) dec_aad.push_back({});
|
|
|
|
|
|
|
|
|
|
// Decrypt contents.
|
|
|
|
|
std::vector<std::byte> decrypted(dec_len);
|
|
|
|
|
bool dec_ignore{false};
|
|
|
|
|
bool dec_ok = dec_cipher.Decrypt(Span{to_decrypt}.subspan(cipher.LENGTH_LEN), dec_aad, dec_ignore, decrypted);
|
|
|
|
|
|
|
|
|
|
// Verify result.
|
|
|
|
|
BOOST_CHECK(dec_ok == !error);
|
|
|
|
|
if (dec_ok) {
|
|
|
|
|
BOOST_CHECK(decrypted == contents);
|
|
|
|
|
BOOST_CHECK(dec_ignore == in_ignore);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
} // namespace
|
|
|
|
|