-
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
14 changed files
with
454 additions
and
592 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_TAGLEN 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 std::vector<std::byte> zero_vec(BIP324_KEY_LEN, std::byte{0x00}); | ||
|
||
static void BIP324_CIPHER_SUITE(benchmark::Bench& bench, size_t plaintext_len, bool include_decryption) | ||
{ | ||
std::array<std::byte, BIP324_KEY_LEN> zero_arr; | ||
memcpy(zero_arr.data(), zero_vec.data(), BIP324_KEY_LEN); | ||
BIP324CipherSuite enc{zero_arr, zero_arr, zero_arr}; | ||
BIP324CipherSuite dec{zero_arr, zero_arr, zero_arr}; | ||
|
||
auto ciphertext_len = BIP324_LENGTH_FIELD_LEN + BIP324_HEADER_LEN + plaintext_len + RFC8439_TAGLEN; | ||
|
||
std::vector<std::byte> in(plaintext_len, std::byte{0x00}); | ||
std::vector<std::byte> out(ciphertext_len, std::byte{0x00}); | ||
|
||
BIP324HeaderFlags flags{0}; | ||
|
||
bench.batch(plaintext_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> len_ciphertext; | ||
memcpy(len_ciphertext.data(), out.data(), BIP324_LENGTH_FIELD_LEN); | ||
(void)dec.DecryptLength(len_ciphertext); | ||
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(BIP324_CIPHER_SUITE_256BYTES_ONLY_ENCRYPT); | ||
BENCHMARK(BIP324_CIPHER_SUITE_1MB_ONLY_ENCRYPT); | ||
BENCHMARK(BIP324_CIPHER_SUITE_64BYTES_ENCRYPT_DECRYPT); | ||
BENCHMARK(BIP324_CIPHER_SUITE_256BYTES_ENCRYPT_DECRYPT); | ||
BENCHMARK(BIP324_CIPHER_SUITE_1MB_ENCRYPT_DECRYPT); | ||
BENCHMARK(HASH_64BYTES); | ||
BENCHMARK(HASH_256BYTES); | ||
BENCHMARK(HASH_1MB); |
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,113 @@ | ||
// 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 <hash.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(payload_key.data(), payload_key.size()); | ||
memory_cleanse(rekey_salt.data(), rekey_salt.size()); | ||
} | ||
|
||
bool BIP324CipherSuite::Crypt(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 length field, header, ciphertext and MAC | ||
(encrypt && (output.size() < BIP324_LENGTH_FIELD_LEN + BIP324_HEADER_LEN + input.size() + RFC8439_TAGLEN)) || | ||
// if we decrypt, make sure the source contains at least the header + mac and the destination has the space for the source - MAC - header | ||
(!encrypt && (input.size() < BIP324_HEADER_LEN + RFC8439_TAGLEN || output.size() < input.size() - BIP324_HEADER_LEN - RFC8439_TAGLEN))) { | ||
return false; | ||
} | ||
|
||
if (encrypt) { | ||
// input is just the payload | ||
// output will be encrypted length + encrypted (header and payload) + mac tag | ||
uint32_t ciphertext_len = BIP324_HEADER_LEN + input.size(); | ||
ciphertext_len = htole32(ciphertext_len); | ||
auto write_pos = output.data(); | ||
fsc20.Crypt({reinterpret_cast<std::byte*>(&ciphertext_len), BIP324_LENGTH_FIELD_LEN}, {write_pos, BIP324_LENGTH_FIELD_LEN}); | ||
write_pos += BIP324_LENGTH_FIELD_LEN; | ||
|
||
std::vector<std::byte> input_vec; | ||
input_vec.resize(BIP324_HEADER_LEN + input.size()); | ||
|
||
// TODO: this can be optimized by changing the RFC8439Encrypt interface to accept a list of inputs. | ||
// But, at the moment, there's a potential bug in out ChaCha20 implementation for plaintexts that | ||
// are not a multiple of 64 bytes -- the rest of the "block" is discarded. An update is in progress | ||
// which will help here. | ||
memcpy(input_vec.data(), &flags, BIP324_HEADER_LEN); | ||
if (!input.empty()) { | ||
memcpy(input_vec.data() + BIP324_HEADER_LEN, input.data(), input.size()); | ||
} | ||
|
||
auto encrypted = RFC8439Encrypt({}, payload_key, nonce, input_vec); | ||
memcpy(write_pos, encrypted.ciphertext.data(), encrypted.ciphertext.size()); | ||
write_pos += encrypted.ciphertext.size(); | ||
memcpy(write_pos, encrypted.tag.data(), encrypted.tag.size()); | ||
write_pos += encrypted.tag.size(); | ||
} else { | ||
// we must use BIP324CipherSuite::DecryptLength before calling BIP324CipherSuite::Crypt | ||
// input is encrypted (header + payload) and the mac tag | ||
// decrypted header will be put in flags and output will be payload. | ||
auto ciphertext_size = input.size() - RFC8439_TAGLEN; | ||
RFC8439Encrypted encrypted; | ||
encrypted.ciphertext.resize(ciphertext_size); | ||
memcpy(encrypted.ciphertext.data(), input.data(), ciphertext_size); | ||
memcpy(encrypted.tag.data(), input.data() + ciphertext_size, RFC8439_TAGLEN); | ||
auto decrypted = RFC8439Decrypt({}, payload_key, nonce, encrypted); | ||
if (!decrypted.success) { | ||
return false; | ||
} | ||
|
||
memcpy(&flags, decrypted.plaintext.data(), BIP324_HEADER_LEN); | ||
if (!output.empty()) { | ||
memcpy(output.data(), decrypted.plaintext.data() + BIP324_HEADER_LEN, ciphertext_size - BIP324_HEADER_LEN); | ||
} | ||
} | ||
|
||
msg_ctr++; | ||
if (msg_ctr == REKEY_INTERVAL) { | ||
auto new_key = Hash(rekey_salt, payload_key); | ||
memcpy(payload_key.data(), &new_key, BIP324_KEY_LEN); | ||
rekey_ctr++; | ||
msg_ctr = 0; | ||
} | ||
set_nonce(); | ||
return true; | ||
} | ||
|
||
uint32_t BIP324CipherSuite::DecryptLength(const std::array<std::byte, BIP324_LENGTH_FIELD_LEN>& ciphertext) | ||
{ | ||
std::array<uint8_t, BIP324_LENGTH_FIELD_LEN> length_buffer; | ||
fsc20.Crypt(ciphertext, 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.