aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--.gitignore4
-rw-r--r--botan_version.py2
-rw-r--r--doc/news.rst15
-rw-r--r--src/cli/speed.cpp (renamed from src/cli/bench.cpp)226
-rw-r--r--src/lib/entropy/entropy_src.h6
-rw-r--r--src/lib/tls/tls_policy.cpp13
-rw-r--r--src/tests/test_mceliece.cpp23
-rw-r--r--src/tests/test_pubkey.cpp40
8 files changed, 209 insertions, 120 deletions
diff --git a/.gitignore b/.gitignore
index c52bc9553..2c4639d6c 100644
--- a/.gitignore
+++ b/.gitignore
@@ -36,6 +36,10 @@ botan-test
.DS_Store
*.swp
+# ctags/etags files
+/TAGS
+/tags
+
# Amalgamation code
botan_all.h
botan_all_internal.h
diff --git a/botan_version.py b/botan_version.py
index 3ffc33e2d..b7938429f 100644
--- a/botan_version.py
+++ b/botan_version.py
@@ -1,7 +1,7 @@
release_major = 1
release_minor = 11
-release_patch = 26
+release_patch = 27
release_so_abi_rev = release_patch
# These are set by the distribution script
diff --git a/doc/news.rst b/doc/news.rst
index a7d99f145..2effcf0fd 100644
--- a/doc/news.rst
+++ b/doc/news.rst
@@ -1,6 +1,21 @@
Release Notes
========================================
+Version 1.11.27, Not Yet Released
+^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+* Use m_ prefix on all member variables. GH #398 and #407
+
+* Use final qualifier on many classes. GH #408
+
+* Use noreturn attribute on assertion failure function to assist
+ static analysis. GH #403
+
+* Use TickCount64 and MemoryStatusEx in the Windows entropy source.
+ Note these calls are only available in Vista/Server 2008. No
+ accomodations are made for XP or Server 2003, both of which are
+ no longer patched by the vendor. GH #365
+
Version 1.11.26, 2016-01-04
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
diff --git a/src/cli/bench.cpp b/src/cli/speed.cpp
index 529f89baf..e044003d9 100644
--- a/src/cli/bench.cpp
+++ b/src/cli/speed.cpp
@@ -17,6 +17,11 @@
#include <botan/hash.h>
#include <botan/mac.h>
#include <botan/cipher_mode.h>
+#include <botan/auto_rng.h>
+
+#if defined(BOTAN_HAS_SYSTEM_RNG)
+ #include <botan/system_rng.h>
+#endif
#if defined(BOTAN_HAS_PUBLIC_KEY_CRYPTO)
#include <botan/pkcs8.h>
@@ -113,57 +118,70 @@ class Timer
return f();
}
- uint64_t value() { stop(); return m_time_used; }
- double seconds() { return milliseconds() / 1000.0; }
- double milliseconds() { return value() / 1000000.0; }
+ template<typename F>
+ void run_until_elapsed(std::chrono::milliseconds msec, F f)
+ {
+ while(this->under(msec))
+ {
+ run(f);
+ }
+ }
+
+ uint64_t value() const { return m_time_used; }
+ double seconds() const { return milliseconds() / 1000.0; }
+ double milliseconds() const { return value() / 1000000.0; }
- double ms_per_event() { return milliseconds() / events(); }
- double seconds_per_event() { return seconds() / events(); }
+ double ms_per_event() const { return milliseconds() / events(); }
+ double seconds_per_event() const { return seconds() / events(); }
uint64_t event_mult() const { return m_event_mult; }
uint64_t events() const { return m_event_count * m_event_mult; }
- std::string get_name() const { return m_name; }
- std::string doing() const { return m_doing.empty() ? m_doing : " " + m_doing; }
+ const std::string& get_name() const { return m_name; }
+ const std::string& doing() const { return m_doing; }
+
+ static std::string result_string_bps(const Timer& t);
+ static std::string result_string_ops(const Timer& t);
private:
std::string m_name, m_doing;
uint64_t m_time_used = 0, m_timer_start = 0;
uint64_t m_event_count = 0, m_event_mult = 0;
};
-std::ostream& operator<<(std::ostream& out, Timer& timer)
+std::string Timer::result_string_bps(const Timer& timer)
{
- const double events_per_second = timer.events() / timer.seconds();
+ const size_t MiB = 1024*1024;
- // use ostringstream to avoid messing with flags on the ostream& itself
+ const double MiB_total = static_cast<double>(timer.events()) / MiB;
+ const double MiB_per_sec = MiB_total / timer.seconds();
std::ostringstream oss;
+ oss << timer.get_name();
+
+ if(!timer.doing().empty())
+ oss << " " << timer.doing();
+
+ oss << " " << std::fixed << std::setprecision(3)
+ << MiB_per_sec << " MiB/sec"
+ << " (" << MiB_total << " MiB in " << timer.milliseconds() << " ms)\n";
- if(timer.event_mult() % 1024 == 0)
- {
- // assumed to be a byte count
- const size_t MiB = 1024*1024;
-
- const double MiB_total = static_cast<double>(timer.events()) / MiB;
- const double MiB_per_sec = MiB_total / timer.seconds();
-
- oss << timer.get_name() << timer.doing() << " "
- << std::fixed << std::setprecision(3) << MiB_per_sec << " MiB/sec"
- << " (" << MiB_total << " MiB in " << timer.milliseconds() << " ms)\n";
- }
- else
- {
- // general event counter
- oss << timer.get_name() << " "
- << static_cast<uint64_t>(events_per_second)
- << timer.doing() << "/sec; "
- << std::setprecision(2) << std::fixed
- << timer.ms_per_event() << " ms/op"
- << " (" << timer.events() << " " << (timer.events() == 1 ? "op" : "ops")
- << " in " << timer.milliseconds() << " ms)\n";
- }
-
- out << oss.str();
- return out;
+ return oss.str();
+ }
+
+std::string Timer::result_string_ops(const Timer& timer)
+ {
+ std::ostringstream oss;
+
+ const double events_per_second = timer.events() / timer.seconds();
+
+ oss << timer.get_name() << " "
+ << static_cast<uint64_t>(events_per_second)
+ << ' ' << timer.doing() << "/sec; "
+ << std::setprecision(2) << std::fixed
+ << timer.ms_per_event() << " ms/op"
+ << " (" << timer.events() << " " << (timer.events() == 1 ? "op" : "ops")
+ << " in " << timer.milliseconds() << " ms)\n";
+
+ return oss.str();
}
std::vector<std::string> default_benchmark_list()
@@ -240,10 +258,10 @@ std::vector<std::string> default_benchmark_list()
}
-class Benchmark final : public Command
+class Speed final : public Command
{
public:
- Benchmark() : Command("bench --msec=1000 --provider= --buf-size=8 *algos") {}
+ Speed() : Command("speed --msec=300 --provider= --buf-size=4096 *algos") {}
void go() override
{
@@ -269,25 +287,25 @@ class Benchmark final : public Command
{
bench_providers_of<Botan::BlockCipher>(
algo, provider, msec, buf_size,
- std::bind(&Benchmark::bench_block_cipher, this, _1, _2, _3, _4));
+ std::bind(&Speed::bench_block_cipher, this, _1, _2, _3, _4));
}
else if(Botan::StreamCipher::providers(algo).size() > 0)
{
bench_providers_of<Botan::StreamCipher>(
algo, provider, msec, buf_size,
- std::bind(&Benchmark::bench_stream_cipher, this, _1, _2, _3, _4));
+ std::bind(&Speed::bench_stream_cipher, this, _1, _2, _3, _4));
}
else if(Botan::HashFunction::providers(algo).size() > 0)
{
bench_providers_of<Botan::HashFunction>(
algo, provider, msec, buf_size,
- std::bind(&Benchmark::bench_hash, this, _1, _2, _3, _4));
+ std::bind(&Speed::bench_hash, this, _1, _2, _3, _4));
}
else if(Botan::MessageAuthenticationCode::providers(algo).size() > 0)
{
bench_providers_of<Botan::MessageAuthenticationCode>(
algo, provider, msec, buf_size,
- std::bind(&Benchmark::bench_mac, this, _1, _2, _3, _4));
+ std::bind(&Speed::bench_mac, this, _1, _2, _3, _4));
}
#if defined(BOTAN_HAS_RSA)
else if(algo == "RSA")
@@ -326,11 +344,20 @@ class Benchmark final : public Command
bench_random_prime(msec);
}
#endif
+ else if(algo == "RNG")
+ {
+#if defined(BOTAN_HAS_SYSTEM_RNG)
+ bench_rng(Botan::system_rng(), "System_RNG", msec, buf_size);
+#endif
+
+ Botan::AutoSeeded_RNG auto_rng;
+ bench_rng(auto_rng, "AutoSeeded_RNG", msec, buf_size);
+ }
else
{
if(verbose() || !using_defaults)
{
- error_output() << "Unknown algorithm to benchmark '" << algo << "'\n";
+ error_output() << "Unknown algorithm '" << algo << "'\n";
}
}
}
@@ -367,24 +394,25 @@ class Benchmark final : public Command
void bench_block_cipher(Botan::BlockCipher& cipher,
const std::string& provider,
- const std::chrono::milliseconds runtime,
+ std::chrono::milliseconds runtime,
size_t buf_size)
{
- Botan::secure_vector<uint8_t> buffer = rng().random_vec(buf_size * 1024);
+ std::vector<uint8_t> buffer(buf_size * cipher.block_size());
Timer encrypt_timer(cipher.name(), provider, "encrypt", buffer.size());
Timer decrypt_timer(cipher.name(), provider, "decrypt", buffer.size());
+ Timer ks_timer(cipher.name(), provider, "key schedule");
- while(encrypt_timer.under(runtime) && decrypt_timer.under(runtime))
- {
- const Botan::SymmetricKey key(rng(), cipher.maximum_keylength());
+ const Botan::SymmetricKey key(rng(), cipher.maximum_keylength());
+ ks_timer.run([&] { cipher.set_key(key); });
- cipher.set_key(key);
- encrypt_timer.run([&] { cipher.encrypt(buffer); });
- decrypt_timer.run([&] { cipher.decrypt(buffer); });
- }
+ std::chrono::milliseconds half = runtime / 2;
- output() << encrypt_timer << decrypt_timer;
+ encrypt_timer.run_until_elapsed(runtime, [&] { cipher.encrypt(buffer); });
+ output() << Timer::result_string_bps(encrypt_timer);
+
+ decrypt_timer.run_until_elapsed(runtime, [&] { cipher.decrypt(buffer); });
+ output() << Timer::result_string_bps(decrypt_timer);
}
void bench_stream_cipher(Botan::StreamCipher& cipher,
@@ -403,7 +431,7 @@ class Benchmark final : public Command
encrypt_timer.run([&] { cipher.encipher(buffer); });
}
- output() << encrypt_timer;
+ output() << Timer::result_string_bps(encrypt_timer);
}
void bench_hash(Botan::HashFunction& hash,
@@ -413,14 +441,9 @@ class Benchmark final : public Command
{
Botan::secure_vector<uint8_t> buffer = rng().random_vec(buf_size * 1024);
- Timer timer(hash.name(), provider, "hashing", buffer.size());
-
- while(timer.under(runtime))
- {
- timer.run([&] { hash.update(buffer); });
- }
-
- output() << timer;
+ Timer timer(hash.name(), provider, "hash", buffer.size());
+ timer.run_until_elapsed(runtime, [&] { hash.update(buffer); });
+ output() << Timer::result_string_bps(timer);
}
void bench_mac(Botan::MessageAuthenticationCode& mac,
@@ -430,7 +453,7 @@ class Benchmark final : public Command
{
Botan::secure_vector<uint8_t> buffer = rng().random_vec(buf_size * 1024);
- Timer timer(mac.name(), provider, "processing", buffer.size());
+ Timer timer(mac.name(), provider, "mac", buffer.size());
while(timer.under(runtime))
{
@@ -439,7 +462,7 @@ class Benchmark final : public Command
timer.run([&] { mac.update(buffer); });
}
- output() << timer;
+ output() << Timer::result_string_bps(timer);
}
void bench_cipher_mode(Botan::Cipher_Mode& enc,
@@ -447,28 +470,53 @@ class Benchmark final : public Command
const std::chrono::milliseconds runtime,
size_t buf_size)
{
- Botan::secure_vector<uint8_t> buffer = rng().random_vec(buf_size * 1024);
+ Botan::secure_vector<uint8_t> buffer = rng().random_vec(buf_size);
+
+ Timer encrypt_timer(enc.name(), enc.provider(), "encrypt", buffer.size());
+ Timer decrypt_timer(enc.name(), enc.provider(), "decrypt", buffer.size());
+ Timer ks_timer(enc.name(), enc.provider(), "key schedule");
+ Timer iv_timer(enc.name(), enc.provider(), "iv setup");
- Timer encrypt_timer(enc.name(), "", "encrypt", buffer.size());
- Timer decrypt_timer(enc.name(), "", "decrypt", buffer.size());
+ const Botan::SymmetricKey key(rng(), enc.key_spec().maximum_keylength());
+
+ ks_timer.run([&] { enc.set_key(key); });
+ ks_timer.run([&] { dec.set_key(key); });
while(encrypt_timer.under(runtime) && decrypt_timer.under(runtime))
{
- const Botan::SymmetricKey key(rng(), enc.key_spec().maximum_keylength());
const Botan::secure_vector<uint8_t> iv = rng().random_vec(enc.default_nonce_length());
- enc.set_key(key);
- dec.set_key(key);
-
- enc.start(iv);
- dec.start(iv);
-
// Must run in this order, or AEADs will reject the ciphertext
+ iv_timer.run([&] { enc.start(iv); });
encrypt_timer.run([&] { enc.finish(buffer); });
+
+ iv_timer.run([&] { dec.start(iv); });
decrypt_timer.run([&] { dec.finish(buffer); });
}
- output() << encrypt_timer << decrypt_timer;
+ output() << Timer::result_string_ops(ks_timer);
+ output() << Timer::result_string_ops(iv_timer);
+ output() << Timer::result_string_bps(encrypt_timer);
+ output() << Timer::result_string_bps(decrypt_timer);
+ }
+
+ void bench_rng(Botan::RandomNumberGenerator& rng,
+ const std::string& rng_name,
+ const std::chrono::milliseconds runtime,
+ size_t buf_size)
+ {
+ Botan::secure_vector<uint8_t> buffer(buf_size);
+
+ Timer timer(rng_name, "", "bytes", buffer.size());
+
+ while(timer.under(runtime))
+ {
+ timer.run([&] { rng.randomize(buffer.data(), buffer.size()); });
+
+ //timer.run([&] { for(size_t i = 0; i != buffer.size(); i++) buffer[i] = rng.next_byte(); });
+ }
+
+ output() << Timer::result_string_bps(timer);
}
#if defined(BOTAN_HAS_NUMBERTHEORY)
@@ -503,7 +551,8 @@ class Benchmark final : public Command
}
}
- output() << genprime_timer << is_prime_timer;
+ output() << Timer::result_string_ops(genprime_timer);
+ output() << Timer::result_string_ops(is_prime_timer);
}
}
#endif
@@ -543,8 +592,8 @@ class Benchmark final : public Command
}
}
- output() << enc_timer;
- output() << dec_timer;
+ output() << Timer::result_string_ops(enc_timer);
+ output() << Timer::result_string_ops(dec_timer);
}
void bench_pk_ka(const Botan::PK_Key_Agreement_Key& key1,
@@ -573,7 +622,7 @@ class Benchmark final : public Command
}
}
- output() << ka_timer;
+ output() << Timer::result_string_ops(ka_timer);
}
void bench_pk_sig(const Botan::Private_Key& key,
@@ -626,8 +675,8 @@ class Benchmark final : public Command
}
}
- output() << sig_timer;
- output() << ver_timer;
+ output() << Timer::result_string_ops(sig_timer);
+ output() << Timer::result_string_ops(ver_timer);
}
#endif
@@ -645,7 +694,7 @@ class Benchmark final : public Command
return new Botan::RSA_PrivateKey(rng(), keylen);
}));
- output() << keygen_timer;
+ output() << Timer::result_string_ops(keygen_timer);
// Using PKCS #1 padding so OpenSSL provider can play along
bench_pk_enc(*key, nm, provider, "EME-PKCS1-v1_5", msec);
@@ -668,7 +717,7 @@ class Benchmark final : public Command
return new Botan::ECDSA_PrivateKey(rng(), grp);
}));
- output() << keygen_timer;
+ output() << Timer::result_string_ops(keygen_timer);
bench_pk_sig(*key, nm, provider, "EMSA1(SHA-256)", msec);
}
}
@@ -692,8 +741,7 @@ class Benchmark final : public Command
return new Botan::DH_PrivateKey(rng(), grp);
}));
- output() << keygen_timer;
-
+ output() << Timer::result_string_ops(keygen_timer);
bench_pk_ka(*key1, *key2, nm, provider, "KDF2(SHA-256)", msec);
}
}
@@ -716,8 +764,7 @@ class Benchmark final : public Command
return new Botan::ECDH_PrivateKey(rng(), grp);
}));
- output() << keygen_timer;
-
+ output() << Timer::result_string_ops(keygen_timer);
bench_pk_ka(*key1, *key2, nm, provider, "KDF2(SHA-256)", msec);
}
}
@@ -738,8 +785,7 @@ class Benchmark final : public Command
return new Botan::Curve25519_PrivateKey(rng());
}));
- output() << keygen_timer;
-
+ output() << Timer::result_string_ops(keygen_timer);
bench_pk_ka(*key1, *key2, nm, provider, "KDF2(SHA-256)", msec);
}
#endif
@@ -747,6 +793,6 @@ class Benchmark final : public Command
};
-BOTAN_REGISTER_COMMAND("bench", Benchmark);
+BOTAN_REGISTER_COMMAND("speed", Speed);
}
diff --git a/src/lib/entropy/entropy_src.h b/src/lib/entropy/entropy_src.h
index 0f4c38358..3bcd8c68d 100644
--- a/src/lib/entropy/entropy_src.h
+++ b/src/lib/entropy/entropy_src.h
@@ -17,7 +17,7 @@ namespace Botan {
/**
* Class used to accumulate the poll results of EntropySources
*/
-class BOTAN_DLL Entropy_Accumulator
+class BOTAN_DLL Entropy_Accumulator final
{
public:
/**
@@ -33,8 +33,6 @@ class BOTAN_DLL Entropy_Accumulator
Entropy_Accumulator(std::function<bool (const byte[], size_t, double)> accum) :
m_accum_fn(accum) {}
- virtual ~Entropy_Accumulator() {}
-
/**
* @return if our polling goal has been achieved
*/
@@ -102,7 +100,7 @@ class BOTAN_DLL Entropy_Source
virtual ~Entropy_Source() {}
};
-class BOTAN_DLL Entropy_Sources
+class BOTAN_DLL Entropy_Sources final
{
public:
static Entropy_Sources& global_sources();
diff --git a/src/lib/tls/tls_policy.cpp b/src/lib/tls/tls_policy.cpp
index 374c5f12b..28ef2f1eb 100644
--- a/src/lib/tls/tls_policy.cpp
+++ b/src/lib/tls/tls_policy.cpp
@@ -1,6 +1,6 @@
/*
* Policies for TLS
-* (C) 2004-2010,2012,2015 Jack Lloyd
+* (C) 2004-2010,2012,2015,2016 Jack Lloyd
*
* Botan is released under the Simplified BSD License (see license.txt)
*/
@@ -270,9 +270,7 @@ std::vector<u16bit> Policy::ciphersuite_list(Protocol_Version version,
const std::vector<std::string> kex = allowed_key_exchange_methods();
const std::vector<std::string> sigs = allowed_signature_methods();
- Ciphersuite_Preference_Ordering order(ciphers, macs, kex, sigs);
-
- std::set<Ciphersuite, Ciphersuite_Preference_Ordering> ciphersuites(order);
+ std::vector<Ciphersuite> ciphersuites;
for(auto&& suite : Ciphersuite::all_known_ciphersuites())
{
@@ -301,13 +299,16 @@ std::vector<u16bit> Policy::ciphersuite_list(Protocol_Version version,
continue;
}
- // OK, allow it:
- ciphersuites.insert(suite);
+ // OK, consider it
+ ciphersuites.push_back(suite);
}
if(ciphersuites.empty())
throw Exception("Policy does not allow any available cipher suite");
+ Ciphersuite_Preference_Ordering order(ciphers, macs, kex, sigs);
+ std::sort(ciphersuites.begin(), ciphersuites.end(), order);
+
std::vector<u16bit> ciphersuite_codes;
for(auto i : ciphersuites)
ciphersuite_codes.push_back(i.ciphersuite_code());
diff --git a/src/tests/test_mceliece.cpp b/src/tests/test_mceliece.cpp
index 36ecd660e..455c50a8d 100644
--- a/src/tests/test_mceliece.cpp
+++ b/src/tests/test_mceliece.cpp
@@ -80,17 +80,24 @@ class McEliece_Keygen_Encrypt_Test : public Text_Based_Test
rng.clear();
rng.add_entropy(encrypt_seed.data(), encrypt_seed.size());
- Botan::PK_KEM_Encryptor kem_enc(mce_priv, "KDF1(SHA-512)");
- Botan::PK_KEM_Decryptor kem_dec(mce_priv, "KDF1(SHA-512)");
+ try
+ {
+ Botan::PK_KEM_Encryptor kem_enc(mce_priv, "KDF1(SHA-512)");
+ Botan::PK_KEM_Decryptor kem_dec(mce_priv, "KDF1(SHA-512)");
+
+ Botan::secure_vector<byte> encap_key, prod_shared_key;
+ kem_enc.encrypt(encap_key, prod_shared_key, 64, rng);
- Botan::secure_vector<byte> encap_key, prod_shared_key;
- kem_enc.encrypt(encap_key, prod_shared_key, 64, rng);
+ Botan::secure_vector<byte> dec_shared_key = kem_dec.decrypt(encap_key.data(), encap_key.size(), 64);
- Botan::secure_vector<byte> dec_shared_key = kem_dec.decrypt(encap_key.data(), encap_key.size(), 64);
+ result.test_eq("ciphertext", encap_key, ciphertext);
+ result.test_eq("encrypt shared", prod_shared_key, shared_key);
+ result.test_eq("decrypt shared", dec_shared_key, shared_key);
+ }
+ catch(Botan::Lookup_Error&)
+ {
+ }
- result.test_eq("ciphertext", encap_key, ciphertext);
- result.test_eq("encrypt shared", prod_shared_key, shared_key);
- result.test_eq("decrypt shared", dec_shared_key, shared_key);
return result;
}
diff --git a/src/tests/test_pubkey.cpp b/src/tests/test_pubkey.cpp
index faa27f322..025628636 100644
--- a/src/tests/test_pubkey.cpp
+++ b/src/tests/test_pubkey.cpp
@@ -260,29 +260,47 @@ Test::Result PK_KEM_Test::run_one_test(const std::string&, const VarMap& vars)
std::unique_ptr<Botan::Private_Key> privkey = load_private_key(vars);
+ const Botan::Public_Key& pubkey = *privkey;
+
const size_t desired_key_len = K.size();
- Botan::PK_KEM_Encryptor enc(*privkey, kdf);
+ std::unique_ptr<Botan::PK_KEM_Encryptor> enc;
+ try
+ {
+ enc.reset(new Botan::PK_KEM_Encryptor(pubkey, kdf));
+ }
+ catch(Botan::Lookup_Error&)
+ {
+ return result;
+ }
Fixed_Output_RNG fixed_output_rng(get_req_bin(vars, "R"));
Botan::secure_vector<byte> produced_encap_key, shared_key;
- enc.encrypt(produced_encap_key,
- shared_key,
- desired_key_len,
- fixed_output_rng,
- salt);
+ enc->encrypt(produced_encap_key,
+ shared_key,
+ desired_key_len,
+ fixed_output_rng,
+ salt);
result.test_eq("C0 matches", produced_encap_key, C0);
result.test_eq("K matches", shared_key, K);
- Botan::PK_KEM_Decryptor dec(*privkey, kdf);
+ std::unique_ptr<Botan::PK_KEM_Decryptor> dec;
+ try
+ {
+ dec.reset(new Botan::PK_KEM_Decryptor(*privkey, kdf));
+ }
+ catch(Botan::Lookup_Error&)
+ {
+ return result;
+ }
const Botan::secure_vector<uint8_t> decr_shared_key =
- dec.decrypt(C0.data(), C0.size(),
- desired_key_len,
- salt.data(),
- salt.size());
+ dec->decrypt(C0.data(), C0.size(),
+ desired_key_len,
+ salt.data(),
+ salt.size());
result.test_eq("decrypted K matches", decr_shared_key, K);