diff --git a/CMakeLists.txt b/CMakeLists.txt index 42ba5299852..66b7e83f1c8 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -891,6 +891,11 @@ if(BUILD_TESTS) SRCS src/crypto/test/bench.cpp LINK_LIBS ) + add_picobench( + cose_bench + SRCS src/crypto/test/cose_bench.cpp + LINK_LIBS + ) add_picobench( history_bench SRCS src/node/test/history_bench.cpp src/enclave/thread_local.cpp diff --git a/src/crypto/test/cose_bench.cpp b/src/crypto/test/cose_bench.cpp new file mode 100644 index 00000000000..5035d4f3c06 --- /dev/null +++ b/src/crypto/test/cose_bench.cpp @@ -0,0 +1,203 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the Apache 2.0 License. + +#include "ccf/crypto/cose_verifier.h" +#include "crypto/cbor.h" +#include "crypto/cose.h" +#include "crypto/openssl/cose_sign.h" +#include "crypto/openssl/ec_key_pair.h" + +#define PICOBENCH_UNIQUE_SYM_SUFFIX __COUNTER__ +#define PICOBENCH_IMPLEMENT_WITH_MAIN +#include + +using namespace std; +using namespace ccf::crypto; + +static const string lorem_ipsum = + "Lorem ipsum dolor sit amet, consectetur adipiscing " + "elit, sed do eiusmod tempor incididunt ut labore et" + " dolore magna aliqua. Ut enim ad minim veniam, quis" + " nostrud exercitation ullamco laboris nisi ut " + "aliquip ex ea commodo consequat. Duis aute irure " + "dolor in reprehenderit in voluptate velit esse " + "cillum dolore eu fugiat nulla pariatur. Excepteur " + "sint occaecat cupidatat non proident, sunt in culpa " + "qui officia deserunt mollit anim id est laborum."; + +template +inline void do_not_optimize(A const& value) +{ + asm volatile("" : : "r,m"(value) : "memory"); +} + +inline void clobber_memory() +{ + asm volatile("" : : : "memory"); +} + +template +vector make_contents() +{ + vector contents(NBytes); + size_t written = 0; + while (written < NBytes) + { + const auto write_size = min(lorem_ipsum.size(), NBytes - written); + memcpy(contents.data() + written, lorem_ipsum.data(), write_size); + written += write_size; + } + return contents; +} + +static const string bench_kid = "bench-kid"; +static const string bench_issuer = "bench-issuer"; +static const string bench_subject = "bench-subject"; +static const string bench_txid = "2.42"; +static const int64_t bench_iat = 1700000000; + +static ccf::cbor::Value make_protected_headers() +{ + namespace cbor = ccf::cbor; + + std::vector ccf_headers; + ccf_headers.emplace_back( + cbor::make_string(ccf::cose::header::custom::TX_ID), + cbor::make_string(bench_txid)); + + std::vector cwt_headers; + cwt_headers.emplace_back( + cbor::make_signed(ccf::cwt::header::iana::IAT), + cbor::make_signed(bench_iat)); + cwt_headers.emplace_back( + cbor::make_signed(ccf::cwt::header::iana::ISS), + cbor::make_string(bench_issuer)); + cwt_headers.emplace_back( + cbor::make_signed(ccf::cwt::header::iana::SUB), + cbor::make_string(bench_subject)); + + std::vector phdr; + phdr.emplace_back( + cbor::make_signed(ccf::cose::header::iana::KID), + cbor::make_bytes(std::span( + reinterpret_cast(bench_kid.data()), + bench_kid.size()))); + phdr.emplace_back( + cbor::make_signed(ccf::cose::header::iana::VDS), + cbor::make_signed(ccf::cose::value::CCF_LEDGER_SHA256)); + phdr.emplace_back( + cbor::make_signed(ccf::cose::header::iana::CWT_CLAIMS), + cbor::make_map(std::move(cwt_headers))); + phdr.emplace_back( + cbor::make_string(ccf::cose::header::custom::CCF_V1), + cbor::make_map(std::move(ccf_headers))); + + return cbor::make_map(std::move(phdr)); +} + +template +static void benchmark_cose_sign(picobench::state& s) +{ + ECKeyPair_OpenSSL kp(Curve); + auto payload = make_contents(); + + s.start_timer(); + for (auto _ : s) + { + (void)_; + auto phdr = make_protected_headers(); + auto envelope = cose_sign1(kp, phdr, payload); + do_not_optimize(envelope); + clobber_memory(); + } + s.stop_timer(); +} + +template +static void benchmark_cose_verify(picobench::state& s) +{ + ECKeyPair_OpenSSL kp(Curve); + auto payload = make_contents(); + + auto phdr = make_protected_headers(); + auto envelope = cose_sign1(kp, phdr, payload); + auto verifier = make_cose_verifier_from_key(kp.public_key_pem()); + + s.start_timer(); + for (auto _ : s) + { + (void)_; + auto ok = verifier->verify_detached(envelope, payload); + do_not_optimize(ok); + clobber_memory(); + } + s.stop_timer(); +} + +const std::vector sizes = {10}; + +#define PICO_SUFFIX() iterations(sizes) + +PICOBENCH_SUITE("cose sign secp256r1"); +namespace COSE_SIGN_SECP256R1 +{ + auto sign_256r1_1byte = + benchmark_cose_sign; + PICOBENCH(sign_256r1_1byte).PICO_SUFFIX(); + + auto sign_256r1_1k = + benchmark_cose_sign; + PICOBENCH(sign_256r1_1k).PICO_SUFFIX(); + + auto sign_256r1_100k = + benchmark_cose_sign; + PICOBENCH(sign_256r1_100k).PICO_SUFFIX(); +} + +PICOBENCH_SUITE("cose sign secp384r1"); +namespace COSE_SIGN_SECP384R1 +{ + auto sign_384r1_1byte = + benchmark_cose_sign; + PICOBENCH(sign_384r1_1byte).PICO_SUFFIX(); + + auto sign_384r1_1k = + benchmark_cose_sign; + PICOBENCH(sign_384r1_1k).PICO_SUFFIX(); + + auto sign_384r1_100k = + benchmark_cose_sign; + PICOBENCH(sign_384r1_100k).PICO_SUFFIX(); +} + +PICOBENCH_SUITE("cose verify secp256r1"); +namespace COSE_VERIFY_SECP256R1 +{ + auto verify_256r1_1byte = + benchmark_cose_verify; + PICOBENCH(verify_256r1_1byte).PICO_SUFFIX(); + + auto verify_256r1_1k = + benchmark_cose_verify; + PICOBENCH(verify_256r1_1k).PICO_SUFFIX(); + + auto verify_256r1_100k = + benchmark_cose_verify; + PICOBENCH(verify_256r1_100k).PICO_SUFFIX(); +} + +PICOBENCH_SUITE("cose verify secp384r1"); +namespace COSE_VERIFY_SECP384R1 +{ + auto verify_384r1_1byte = + benchmark_cose_verify; + PICOBENCH(verify_384r1_1byte).PICO_SUFFIX(); + + auto verify_384r1_1k = + benchmark_cose_verify; + PICOBENCH(verify_384r1_1k).PICO_SUFFIX(); + + auto verify_384r1_100k = + benchmark_cose_verify; + PICOBENCH(verify_384r1_100k).PICO_SUFFIX(); +}