-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
13 changed files
with
435 additions
and
591 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,117 @@ | ||
// Copyright (c) 2019-2020 The Bitcoin Core developers | ||
// Distributed under the MIT software license, see the accompanying | ||
// file COPYING or http://www.opensource.org/licenses/mit-license.php. | ||
|
||
|
||
#include <assert.h> | ||
#include <bench/bench.h> | ||
#include <crypto/bip324_suite.h> | ||
#include <crypto/rfc8439.h> // for the RFC8439_EXPANSION constant | ||
#include <hash.h> | ||
|
||
#include <array> | ||
#include <cstddef> | ||
#include <vector> | ||
|
||
/* Number of bytes to process per iteration */ | ||
static constexpr uint64_t BUFFER_SIZE_TINY = 64; | ||
static constexpr uint64_t BUFFER_SIZE_SMALL = 256; | ||
static constexpr uint64_t BUFFER_SIZE_LARGE = 1024 * 1024; | ||
|
||
static const std::vector<std::byte> zero_vec(BIP324_KEY_LEN, std::byte{0x00}); | ||
|
||
static void BIP324_CIPHER_SUITE(benchmark::Bench& bench, size_t contents_len, bool include_decryption) | ||
{ | ||
BIP324Key zero_arr; | ||
memcpy(zero_arr.data(), zero_vec.data(), BIP324_KEY_LEN); | ||
BIP324CipherSuite enc{zero_arr, zero_arr}; | ||
BIP324CipherSuite dec{zero_arr, zero_arr}; | ||
|
||
auto packet_len = BIP324_LENGTH_FIELD_LEN + BIP324_HEADER_LEN + contents_len + RFC8439_EXPANSION; | ||
|
||
std::vector<std::byte> in(contents_len, std::byte{0x00}); | ||
std::vector<std::byte> out(packet_len, std::byte{0x00}); | ||
|
||
BIP324HeaderFlags flags{BIP324_NONE}; | ||
|
||
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); | ||
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; | ||
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); | ||
assert(crypt_ok_2); | ||
} | ||
}); | ||
} | ||
|
||
static void BIP324_CIPHER_SUITE_64BYTES_ONLY_ENCRYPT(benchmark::Bench& bench) | ||
{ | ||
BIP324_CIPHER_SUITE(bench, BUFFER_SIZE_TINY, false); | ||
} | ||
|
||
static void BIP324_CIPHER_SUITE_256BYTES_ONLY_ENCRYPT(benchmark::Bench& bench) | ||
{ | ||
BIP324_CIPHER_SUITE(bench, BUFFER_SIZE_SMALL, false); | ||
} | ||
|
||
static void BIP324_CIPHER_SUITE_1MB_ONLY_ENCRYPT(benchmark::Bench& bench) | ||
{ | ||
BIP324_CIPHER_SUITE(bench, BUFFER_SIZE_LARGE, false); | ||
} | ||
|
||
static void BIP324_CIPHER_SUITE_64BYTES_ENCRYPT_DECRYPT(benchmark::Bench& bench) | ||
{ | ||
BIP324_CIPHER_SUITE(bench, BUFFER_SIZE_TINY, true); | ||
} | ||
|
||
static void BIP324_CIPHER_SUITE_256BYTES_ENCRYPT_DECRYPT(benchmark::Bench& bench) | ||
{ | ||
BIP324_CIPHER_SUITE(bench, BUFFER_SIZE_SMALL, true); | ||
} | ||
|
||
static void BIP324_CIPHER_SUITE_1MB_ENCRYPT_DECRYPT(benchmark::Bench& bench) | ||
{ | ||
BIP324_CIPHER_SUITE(bench, BUFFER_SIZE_LARGE, true); | ||
} | ||
|
||
// Add Hash() (dbl-sha256) bench for comparison | ||
|
||
static void HASH(benchmark::Bench& bench, size_t buffersize) | ||
{ | ||
uint8_t hash[CHash256::OUTPUT_SIZE]; | ||
std::vector<uint8_t> in(buffersize, 0); | ||
bench.batch(in.size()).unit("byte").run([&] { | ||
CHash256().Write(in).Finalize(hash); | ||
}); | ||
} | ||
|
||
static void HASH_64BYTES(benchmark::Bench& bench) | ||
{ | ||
HASH(bench, BUFFER_SIZE_TINY); | ||
} | ||
|
||
static void HASH_256BYTES(benchmark::Bench& bench) | ||
{ | ||
HASH(bench, BUFFER_SIZE_SMALL); | ||
} | ||
|
||
static void HASH_1MB(benchmark::Bench& bench) | ||
{ | ||
HASH(bench, BUFFER_SIZE_LARGE); | ||
} | ||
|
||
BENCHMARK(BIP324_CIPHER_SUITE_64BYTES_ONLY_ENCRYPT, benchmark::PriorityLevel::HIGH); | ||
BENCHMARK(BIP324_CIPHER_SUITE_256BYTES_ONLY_ENCRYPT, benchmark::PriorityLevel::HIGH); | ||
BENCHMARK(BIP324_CIPHER_SUITE_1MB_ONLY_ENCRYPT, benchmark::PriorityLevel::HIGH); | ||
BENCHMARK(BIP324_CIPHER_SUITE_64BYTES_ENCRYPT_DECRYPT, benchmark::PriorityLevel::HIGH); | ||
BENCHMARK(BIP324_CIPHER_SUITE_256BYTES_ENCRYPT_DECRYPT, benchmark::PriorityLevel::HIGH); | ||
BENCHMARK(BIP324_CIPHER_SUITE_1MB_ENCRYPT_DECRYPT, benchmark::PriorityLevel::HIGH); | ||
BENCHMARK(HASH_64BYTES, benchmark::PriorityLevel::HIGH); | ||
BENCHMARK(HASH_256BYTES, benchmark::PriorityLevel::HIGH); | ||
BENCHMARK(HASH_1MB, benchmark::PriorityLevel::HIGH); |
This file was deleted.
Oops, something went wrong.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,110 @@ | ||
// Copyright (c) 2019-2021 The Bitcoin Core developers | ||
// Distributed under the MIT software license, see the accompanying | ||
// file COPYING or http://www.opensource.org/licenses/mit-license.php. | ||
|
||
#include <crypto/bip324_suite.h> | ||
|
||
#include <crypto/common.h> | ||
#include <crypto/poly1305.h> | ||
#include <crypto/sha256.h> | ||
#include <support/cleanse.h> | ||
|
||
#include <assert.h> | ||
#include <cstring> | ||
#include <string.h> | ||
|
||
#ifndef HAVE_TIMINGSAFE_BCMP | ||
|
||
int timingsafe_bcmp(const unsigned char* b1, const unsigned char* b2, size_t n) | ||
{ | ||
const unsigned char *p1 = b1, *p2 = b2; | ||
int ret = 0; | ||
|
||
for (; n > 0; n--) | ||
ret |= *p1++ ^ *p2++; | ||
return (ret != 0); | ||
} | ||
|
||
#endif // TIMINGSAFE_BCMP | ||
|
||
BIP324CipherSuite::~BIP324CipherSuite() | ||
{ | ||
memory_cleanse(key_P.data(), key_P.size()); | ||
} | ||
|
||
void BIP324CipherSuite::Rekey() | ||
{ | ||
ChaCha20 rekey_c20(UCharCast(key_P.data())); | ||
std::array<std::byte, NONCE_LENGTH> rekey_nonce; | ||
memset(rekey_nonce.data(), 0xFF, 4); | ||
memcpy(rekey_nonce.data() + 4, nonce.data() + 4, NONCE_LENGTH - 4); | ||
rekey_c20.SetRFC8439Nonce(rekey_nonce); | ||
rekey_c20.SeekRFC8439(1); | ||
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, | ||
BIP324HeaderFlags& flags, bool encrypt) | ||
{ | ||
// check buffer boundaries | ||
if ( | ||
// if we encrypt, make sure the destination has the space for the encrypted length field, header, contents and MAC | ||
(encrypt && (output.size() < BIP324_LENGTH_FIELD_LEN + BIP324_HEADER_LEN + input.size() + RFC8439_EXPANSION)) || | ||
// if we decrypt, make sure the source contains at least the encrypted header + mac and the destination has the space for the input - MAC - header | ||
(!encrypt && (input.size() < BIP324_HEADER_LEN + RFC8439_EXPANSION || output.size() < input.size() - BIP324_HEADER_LEN - RFC8439_EXPANSION))) { | ||
return false; | ||
} | ||
|
||
if (encrypt) { | ||
// input is just the contents | ||
// output will be encrypted contents length + encrypted (header and contents) + mac tag | ||
uint32_t contents_len = input.size(); | ||
WriteLE32(reinterpret_cast<unsigned char*>(&contents_len), contents_len); | ||
|
||
std::vector<std::byte> header_and_contents(BIP324_HEADER_LEN + input.size()); | ||
|
||
memcpy(header_and_contents.data(), &flags, BIP324_HEADER_LEN); | ||
if (!input.empty()) { | ||
memcpy(header_and_contents.data() + BIP324_HEADER_LEN, input.data(), input.size()); | ||
} | ||
|
||
auto write_pos = output.data(); | ||
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}); | ||
} 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); | ||
if (!authenticated) { | ||
return false; | ||
} | ||
|
||
memcpy(&flags, decrypted_header_and_contents.data(), BIP324_HEADER_LEN); | ||
if (!output.empty()) { | ||
memcpy(output.data(), | ||
decrypted_header_and_contents.data() + BIP324_HEADER_LEN, | ||
input.size() - BIP324_HEADER_LEN - RFC8439_EXPANSION); | ||
} | ||
} | ||
|
||
packet_counter++; | ||
if (packet_counter % REKEY_INTERVAL == 0) { | ||
Rekey(); | ||
} | ||
set_nonce(); | ||
return true; | ||
} | ||
|
||
uint32_t BIP324CipherSuite::DecryptLength(const std::array<std::byte, BIP324_LENGTH_FIELD_LEN>& encrypted_length) | ||
{ | ||
std::array<uint8_t, BIP324_LENGTH_FIELD_LEN> length_buffer; | ||
fsc20.Crypt(encrypted_length, MakeWritableByteSpan(length_buffer)); | ||
|
||
return (uint32_t{length_buffer[0]}) | | ||
(uint32_t{length_buffer[1]} << 8) | | ||
(uint32_t{length_buffer[2]} << 16); | ||
} |
Oops, something went wrong.