diff --git a/contrib/cryptomb/private_key_providers/source/cryptomb_private_key_provider.cc b/contrib/cryptomb/private_key_providers/source/cryptomb_private_key_provider.cc index 7ed6246805ee..58c670e7c4df 100644 --- a/contrib/cryptomb/private_key_providers/source/cryptomb_private_key_provider.cc +++ b/contrib/cryptomb/private_key_providers/source/cryptomb_private_key_provider.cc @@ -183,6 +183,65 @@ ssl_private_key_result_t ecdsaPrivateKeyDecrypt(SSL*, uint8_t*, size_t*, size_t, return ssl_private_key_failure; } +ssl_private_key_result_t ecdsaPrivateKeyCompleteInternal(CryptoMbPrivateKeyConnection* ops, + uint8_t* out, size_t* out_len, + size_t max_out) { + if (ops == nullptr) { + return ssl_private_key_failure; + } + + // Check if the MB operation is ready yet. This can happen if someone calls + // the top-level SSL function too early. The op status is only set from this + // thread. + if (ops->mb_ctx_->getStatus() == RequestStatus::Retry) { + return ssl_private_key_retry; + } + + // If this point is reached, the MB processing must be complete. + + // See if the operation failed. + if (ops->mb_ctx_->getStatus() != RequestStatus::Success) { + ops->logWarnMsg("private key operation failed."); + return ssl_private_key_failure; + } + + CryptoMbEcdsaContextSharedPtr mb_ctx = + std::static_pointer_cast(ops->mb_ctx_); + if (mb_ctx->sig_len_ > max_out) { + return ssl_private_key_failure; + } + + ECDSA_SIG* sig = ECDSA_SIG_new(); + if (sig == nullptr) { + return ssl_private_key_failure; + } + BIGNUM* sig_r = BN_bin2bn(mb_ctx->sig_r_, 32, nullptr); + BIGNUM* sig_s = BN_bin2bn(mb_ctx->sig_s_, 32, nullptr); + ECDSA_SIG_set0(sig, sig_r, sig_s); + + // Marshal signature into out. + CBB cbb; + if (!CBB_init_fixed(&cbb, out, mb_ctx->sig_len_) || !ECDSA_SIG_marshal(&cbb, sig) || + !CBB_finish(&cbb, nullptr, out_len)) { + CBB_cleanup(&cbb); + ECDSA_SIG_free(sig); + return ssl_private_key_failure; + } + + ECDSA_SIG_free(sig); + + return ssl_private_key_success; +} + +ssl_private_key_result_t ecdsaPrivateKeyComplete(SSL* ssl, uint8_t* out, size_t* out_len, + size_t max_out) { + return ssl == nullptr ? ssl_private_key_failure + : ecdsaPrivateKeyCompleteInternal( + static_cast(SSL_get_ex_data( + ssl, CryptoMbPrivateKeyMethodProvider::connectionIndex())), + out, out_len, max_out); +} + ssl_private_key_result_t rsaPrivateKeySignInternal(CryptoMbPrivateKeyConnection* ops, uint8_t*, size_t*, size_t, uint16_t signature_algorithm, const uint8_t* in, size_t in_len) { @@ -337,8 +396,9 @@ ssl_private_key_result_t rsaPrivateKeyDecrypt(SSL* ssl, uint8_t* out, size_t* ou out, out_len, max_out, in, in_len); } -ssl_private_key_result_t privateKeyCompleteInternal(CryptoMbPrivateKeyConnection* ops, uint8_t* out, - size_t* out_len, size_t max_out) { +ssl_private_key_result_t rsaPrivateKeyCompleteInternal(CryptoMbPrivateKeyConnection* ops, + uint8_t* out, size_t* out_len, + size_t max_out) { if (ops == nullptr) { return ssl_private_key_failure; } @@ -358,21 +418,22 @@ ssl_private_key_result_t privateKeyCompleteInternal(CryptoMbPrivateKeyConnection return ssl_private_key_failure; } - *out_len = ops->mb_ctx_->out_len_; + CryptoMbRsaContextSharedPtr mb_ctx = std::static_pointer_cast(ops->mb_ctx_); + *out_len = mb_ctx->out_len_; if (*out_len > max_out) { return ssl_private_key_failure; } - memcpy(out, ops->mb_ctx_->out_buf_, *out_len); // NOLINT(safe-memcpy) + memcpy(out, mb_ctx->out_buf_, *out_len); // NOLINT(safe-memcpy) return ssl_private_key_success; } -ssl_private_key_result_t privateKeyComplete(SSL* ssl, uint8_t* out, size_t* out_len, - size_t max_out) { +ssl_private_key_result_t rsaPrivateKeyComplete(SSL* ssl, uint8_t* out, size_t* out_len, + size_t max_out) { return ssl == nullptr ? ssl_private_key_failure - : privateKeyCompleteInternal( + : rsaPrivateKeyCompleteInternal( static_cast(SSL_get_ex_data( ssl, CryptoMbPrivateKeyMethodProvider::connectionIndex())), out, out_len, max_out); @@ -381,9 +442,15 @@ ssl_private_key_result_t privateKeyComplete(SSL* ssl, uint8_t* out, size_t* out_ } // namespace // External linking, meant for testing without SSL context. -ssl_private_key_result_t privateKeyCompleteForTest(CryptoMbPrivateKeyConnection* ops, uint8_t* out, - size_t* out_len, size_t max_out) { - return privateKeyCompleteInternal(ops, out, out_len, max_out); +ssl_private_key_result_t ecdsaPrivateKeyCompleteForTest(CryptoMbPrivateKeyConnection* ops, + uint8_t* out, size_t* out_len, + size_t max_out) { + return ecdsaPrivateKeyCompleteInternal(ops, out, out_len, max_out); +} +ssl_private_key_result_t rsaPrivateKeyCompleteForTest(CryptoMbPrivateKeyConnection* ops, + uint8_t* out, size_t* out_len, + size_t max_out) { + return rsaPrivateKeyCompleteInternal(ops, out, out_len, max_out); } ssl_private_key_result_t ecdsaPrivateKeySignForTest(CryptoMbPrivateKeyConnection* ops, uint8_t* out, size_t* out_len, size_t max_out, @@ -519,12 +586,8 @@ void CryptoMbQueue::processRsaRequests() { } void CryptoMbQueue::processEcdsaRequests() { - uint8_t sig_r[MULTIBUFF_BATCH][32]; - uint8_t sig_s[MULTIBUFF_BATCH][32]; - uint8_t* pa_sig_r[MULTIBUFF_BATCH] = {sig_r[0], sig_r[1], sig_r[2], sig_r[3], - sig_r[4], sig_r[5], sig_r[6], sig_r[7]}; - uint8_t* pa_sig_s[MULTIBUFF_BATCH] = {sig_s[0], sig_s[1], sig_s[2], sig_s[3], - sig_s[4], sig_s[5], sig_s[6], sig_s[7]}; + uint8_t* pa_sig_r[MULTIBUFF_BATCH] = {}; + uint8_t* pa_sig_s[MULTIBUFF_BATCH] = {}; const unsigned char* digest[MULTIBUFF_BATCH] = {nullptr}; const BIGNUM* eph_key[MULTIBUFF_BATCH] = {nullptr}; const BIGNUM* priv_key[MULTIBUFF_BATCH] = {nullptr}; @@ -533,6 +596,8 @@ void CryptoMbQueue::processEcdsaRequests() { for (unsigned req_num = 0; req_num < request_queue_.size(); req_num++) { CryptoMbEcdsaContextSharedPtr mb_ctx = std::static_pointer_cast(request_queue_[req_num]); + pa_sig_r[req_num] = mb_ctx->sig_r_; + pa_sig_s[req_num] = mb_ctx->sig_s_; digest[req_num] = mb_ctx->in_buf_.get(); eph_key[req_num] = mb_ctx->k_; priv_key[req_num] = mb_ctx->priv_key_; @@ -551,11 +616,7 @@ void CryptoMbQueue::processEcdsaRequests() { enum RequestStatus ctx_status; if (ipp_->mbxGetSts(ecdsa_sts, req_num)) { ENVOY_LOG(debug, "Multibuffer ECDSA request {} success", req_num); - if (postprocessEcdsaRequest(mb_ctx, pa_sig_r[req_num], pa_sig_s[req_num])) { - status[req_num] = RequestStatus::Success; - } else { - status[req_num] = RequestStatus::Error; - } + status[req_num] = RequestStatus::Success; } else { ENVOY_LOG(debug, "Multibuffer ECDSA request {} failure", req_num); status[req_num] = RequestStatus::Error; @@ -569,29 +630,6 @@ void CryptoMbQueue::processEcdsaRequests() { } } -bool CryptoMbQueue::postprocessEcdsaRequest(CryptoMbEcdsaContextSharedPtr mb_ctx, - const uint8_t* pa_sig_r, const uint8_t* pa_sig_s) { - ECDSA_SIG* sig = ECDSA_SIG_new(); - if (sig == nullptr) { - return false; - } - BIGNUM* sig_r = BN_bin2bn(pa_sig_r, 32, nullptr); - BIGNUM* sig_s = BN_bin2bn(pa_sig_s, 32, nullptr); - ECDSA_SIG_set0(sig, sig_r, sig_s); - - // Marshal signature into out_buf_. - CBB cbb; - if (!CBB_init_fixed(&cbb, mb_ctx->out_buf_, mb_ctx->sig_len_) || !ECDSA_SIG_marshal(&cbb, sig) || - !CBB_finish(&cbb, nullptr, &mb_ctx->out_len_)) { - CBB_cleanup(&cbb); - ECDSA_SIG_free(sig); - return false; - } - - ECDSA_SIG_free(sig); - return true; -} - CryptoMbPrivateKeyConnection::CryptoMbPrivateKeyConnection(Ssl::PrivateKeyConnectionCallbacks& cb, Event::Dispatcher& dispatcher, bssl::UniquePtr pkey, @@ -678,7 +716,7 @@ CryptoMbPrivateKeyMethodProvider::CryptoMbPrivateKeyMethodProvider( method_->sign = rsaPrivateKeySign; method_->decrypt = rsaPrivateKeyDecrypt; - method_->complete = privateKeyComplete; + method_->complete = rsaPrivateKeyComplete; RSA* rsa = EVP_PKEY_get0_RSA(pkey.get()); switch (RSA_bits(rsa)) { @@ -722,7 +760,7 @@ CryptoMbPrivateKeyMethodProvider::CryptoMbPrivateKeyMethodProvider( method_->sign = ecdsaPrivateKeySign; method_->decrypt = ecdsaPrivateKeyDecrypt; - method_->complete = privateKeyComplete; + method_->complete = ecdsaPrivateKeyComplete; const EC_GROUP* ecdsa_group = EC_KEY_get0_group(EVP_PKEY_get0_EC_KEY(pkey.get())); if (ecdsa_group == nullptr) { diff --git a/contrib/cryptomb/private_key_providers/source/cryptomb_private_key_provider.h b/contrib/cryptomb/private_key_providers/source/cryptomb_private_key_provider.h index b3da76dab5a8..9806f64bac0d 100644 --- a/contrib/cryptomb/private_key_providers/source/cryptomb_private_key_provider.h +++ b/contrib/cryptomb/private_key_providers/source/cryptomb_private_key_provider.h @@ -40,10 +40,6 @@ class CryptoMbContext { enum RequestStatus getStatus() { return status_; } void scheduleCallback(enum RequestStatus status); - // Buffer length is the same as the max signature length (4096 bits = 512 bytes) - unsigned char out_buf_[MAX_SIGNATURE_SIZE]; - // The real length of the signature. - size_t out_len_{}; // Incoming data buffer. std::unique_ptr in_buf_; @@ -75,6 +71,10 @@ class CryptoMbEcdsaContext : public CryptoMbContext { // BoringSSL ECDSA key structure, so not wrapped in smart pointers. const BIGNUM* priv_key_{}; size_t sig_len_{}; + + // ECDSA signature. + uint8_t sig_r_[32]{}; + uint8_t sig_s_[32]{}; }; // CryptoMbRsaContext is a CryptoMbContext which holds the extra RSA parameters and has @@ -103,6 +103,11 @@ class CryptoMbRsaContext : public CryptoMbContext { // Buffer for `Lenstra` check. unsigned char lenstra_to_[MAX_SIGNATURE_SIZE]; + + // Buffer length is the same as the max signature length (4096 bits = 512 bytes) + unsigned char out_buf_[MAX_SIGNATURE_SIZE]; + // The real length of the signature. + size_t out_len_{}; }; using CryptoMbContextSharedPtr = std::shared_ptr; @@ -123,8 +128,6 @@ class CryptoMbQueue : public Logger::Loggable { void processRequests(); void processRsaRequests(); void processEcdsaRequests(); - bool postprocessEcdsaRequest(CryptoMbEcdsaContextSharedPtr mb_ctx, const uint8_t* sign_r, - const uint8_t* sign_s); void startTimer(); void stopTimer(); diff --git a/contrib/cryptomb/private_key_providers/test/BUILD b/contrib/cryptomb/private_key_providers/test/BUILD index 6b4c01fa3ec4..2940695756b1 100644 --- a/contrib/cryptomb/private_key_providers/test/BUILD +++ b/contrib/cryptomb/private_key_providers/test/BUILD @@ -1,5 +1,6 @@ load( "//bazel:envoy_build_system.bzl", + "envoy_cc_benchmark_binary", "envoy_cc_test", "envoy_cc_test_library", "envoy_contrib_package", @@ -82,3 +83,17 @@ envoy_cc_test( "//test/test_common:utility_lib", ], ) + +envoy_cc_benchmark_binary( + name = "speed_test", + srcs = ["speed_test.cc"], + external_deps = [ + "benchmark", + "ssl", + ], + deps = [ + "//contrib/cryptomb/private_key_providers/source:ipp_crypto_wrapper_lib", + "//source/common/common:assert_lib", + "//source/common/common:utility_lib", + ], +) diff --git a/contrib/cryptomb/private_key_providers/test/ops_test.cc b/contrib/cryptomb/private_key_providers/test/ops_test.cc index d5f35db774b3..14761d8fea62 100644 --- a/contrib/cryptomb/private_key_providers/test/ops_test.cc +++ b/contrib/cryptomb/private_key_providers/test/ops_test.cc @@ -22,8 +22,12 @@ namespace PrivateKeyMethodProvider { namespace CryptoMb { // Testing interface -ssl_private_key_result_t privateKeyCompleteForTest(CryptoMbPrivateKeyConnection* ops, uint8_t* out, - size_t* out_len, size_t max_out); +ssl_private_key_result_t ecdsaPrivateKeyCompleteForTest(CryptoMbPrivateKeyConnection* ops, + uint8_t* out, size_t* out_len, + size_t max_out); +ssl_private_key_result_t rsaPrivateKeyCompleteForTest(CryptoMbPrivateKeyConnection* ops, + uint8_t* out, size_t* out_len, + size_t max_out); ssl_private_key_result_t ecdsaPrivateKeySignForTest(CryptoMbPrivateKeyConnection* ops, uint8_t* out, size_t* out_len, size_t max_out, uint16_t signature_algorithm, const uint8_t* in, @@ -148,14 +152,14 @@ TEST_F(CryptoMbProviderEcdsaTest, TestEcdsaSigning) { // No processing done after first requests. // After the last request, the status is set only from the event loop which is not run. This // should still be "retry", the cryptographic result is present anyway. - res_ = privateKeyCompleteForTest(connections[i].get(), nullptr, nullptr, max_out_len_); + res_ = ecdsaPrivateKeyCompleteForTest(connections[i].get(), nullptr, nullptr, max_out_len_); EXPECT_EQ(res_, ssl_private_key_retry); } // Timeout does not have to be triggered when queue is at maximum size. dispatcher_->run(Event::Dispatcher::RunType::NonBlock); - res_ = privateKeyCompleteForTest(connections[0].get(), out_, &out_len_, max_out_len_); + res_ = ecdsaPrivateKeyCompleteForTest(connections[0].get(), out_, &out_len_, max_out_len_); EXPECT_EQ(res_, ssl_private_key_success); EXPECT_NE(out_len_, 0); } @@ -179,14 +183,14 @@ TEST_F(CryptoMbProviderRsaTest, TestRsaPkcs1Signing) { // No processing done after first requests. // After the last request, the status is set only from the event loop which is not run. This // should still be "retry", the cryptographic result is present anyway. - res_ = privateKeyCompleteForTest(connections[i].get(), nullptr, nullptr, max_out_len_); + res_ = rsaPrivateKeyCompleteForTest(connections[i].get(), nullptr, nullptr, max_out_len_); EXPECT_EQ(res_, ssl_private_key_retry); } // Timeout does not have to be triggered when queue is at maximum size. dispatcher_->run(Event::Dispatcher::RunType::NonBlock); - res_ = privateKeyCompleteForTest(connections[0].get(), out_, &out_len_, max_out_len_); + res_ = rsaPrivateKeyCompleteForTest(connections[0].get(), out_, &out_len_, max_out_len_); EXPECT_EQ(res_, ssl_private_key_success); EXPECT_NE(out_len_, 0); @@ -217,14 +221,14 @@ TEST_F(CryptoMbProviderRsaTest, TestRsaPssSigning) { // No processing done after first requests. // After the last request, the status is set only from the event loop which is not run. This // should still be "retry", the cryptographic result is present anyway. - res_ = privateKeyCompleteForTest(connections[i].get(), nullptr, nullptr, max_out_len_); + res_ = rsaPrivateKeyCompleteForTest(connections[i].get(), nullptr, nullptr, max_out_len_); EXPECT_EQ(res_, ssl_private_key_retry); } // Timeout does not have to be triggered when queue is at maximum size. dispatcher_->run(Event::Dispatcher::RunType::NonBlock); - res_ = privateKeyCompleteForTest(connections[0].get(), out_, &out_len_, max_out_len_); + res_ = rsaPrivateKeyCompleteForTest(connections[0].get(), out_, &out_len_, max_out_len_); EXPECT_EQ(res_, ssl_private_key_success); EXPECT_NE(out_len_, 0); @@ -263,14 +267,14 @@ TEST_F(CryptoMbProviderRsaTest, TestRsaDecrypt) { // No processing done after first requests. // After the last request, the status is set only from the event loop which is not run. This // should still be "retry", the cryptographic result is present anyway. - res_ = privateKeyCompleteForTest(connections[i].get(), nullptr, nullptr, max_out_len_); + res_ = rsaPrivateKeyCompleteForTest(connections[i].get(), nullptr, nullptr, max_out_len_); EXPECT_EQ(res_, ssl_private_key_retry); } // Timeout does not have to be triggered when queue is at maximum size. dispatcher_->run(Event::Dispatcher::RunType::NonBlock); - res_ = privateKeyCompleteForTest(connections[0].get(), out_, &out_len_, max_out_len_); + res_ = rsaPrivateKeyCompleteForTest(connections[0].get(), out_, &out_len_, max_out_len_); EXPECT_EQ(res_, ssl_private_key_success); EXPECT_NE(out_len_, 0); } @@ -333,14 +337,14 @@ TEST_F(CryptoMbProviderEcdsaTest, TestEcdsaTimer) { SSL_SIGN_ECDSA_SECP256R1_SHA256, in_, in_len_); EXPECT_EQ(res_, ssl_private_key_retry); - res_ = privateKeyCompleteForTest(&op0, nullptr, nullptr, max_out_len_); + res_ = ecdsaPrivateKeyCompleteForTest(&op0, nullptr, nullptr, max_out_len_); // No processing done yet after first request EXPECT_EQ(res_, ssl_private_key_retry); time_system_.advanceTimeAndRun(std::chrono::seconds(1), *dispatcher_, Event::Dispatcher::RunType::NonBlock); - res_ = privateKeyCompleteForTest(&op0, out_, &out_len_, max_out_len_); + res_ = ecdsaPrivateKeyCompleteForTest(&op0, out_, &out_len_, max_out_len_); EXPECT_EQ(res_, ssl_private_key_success); EXPECT_NE(out_len_, 0); @@ -354,14 +358,14 @@ TEST_F(CryptoMbProviderEcdsaTest, TestEcdsaTimer) { SSL_SIGN_ECDSA_SECP256R1_SHA256, in_, in_len_); EXPECT_EQ(res_, ssl_private_key_retry); - res_ = privateKeyCompleteForTest(&op1, nullptr, nullptr, max_out_len_); + res_ = ecdsaPrivateKeyCompleteForTest(&op1, nullptr, nullptr, max_out_len_); // No processing done yet after first request EXPECT_EQ(res_, ssl_private_key_retry); time_system_.advanceTimeAndRun(std::chrono::seconds(1), *dispatcher_, Event::Dispatcher::RunType::NonBlock); - res_ = privateKeyCompleteForTest(&op1, out_, &out_len_, max_out_len_); + res_ = ecdsaPrivateKeyCompleteForTest(&op1, out_, &out_len_, max_out_len_); EXPECT_EQ(res_, ssl_private_key_failure); } @@ -374,14 +378,14 @@ TEST_F(CryptoMbProviderRsaTest, TestRsaTimer) { in_, in_len_); EXPECT_EQ(res_, ssl_private_key_retry); - res_ = privateKeyCompleteForTest(&op0, nullptr, nullptr, max_out_len_); + res_ = rsaPrivateKeyCompleteForTest(&op0, nullptr, nullptr, max_out_len_); // No processing done yet after first request EXPECT_EQ(res_, ssl_private_key_retry); time_system_.advanceTimeAndRun(std::chrono::seconds(1), *dispatcher_, Event::Dispatcher::RunType::NonBlock); - res_ = privateKeyCompleteForTest(&op0, out_, &out_len_, max_out_len_); + res_ = rsaPrivateKeyCompleteForTest(&op0, out_, &out_len_, max_out_len_); EXPECT_EQ(res_, ssl_private_key_success); EXPECT_NE(out_len_, 0); @@ -395,14 +399,14 @@ TEST_F(CryptoMbProviderRsaTest, TestRsaTimer) { in_, in_len_); EXPECT_EQ(res_, ssl_private_key_retry); - res_ = privateKeyCompleteForTest(&op1, nullptr, nullptr, max_out_len_); + res_ = rsaPrivateKeyCompleteForTest(&op1, nullptr, nullptr, max_out_len_); // No processing done yet after first request EXPECT_EQ(res_, ssl_private_key_retry); time_system_.advanceTimeAndRun(std::chrono::seconds(1), *dispatcher_, Event::Dispatcher::RunType::NonBlock); - res_ = privateKeyCompleteForTest(&op1, out_, &out_len_, max_out_len_); + res_ = rsaPrivateKeyCompleteForTest(&op1, out_, &out_len_, max_out_len_); EXPECT_EQ(res_, ssl_private_key_failure); } @@ -428,7 +432,7 @@ TEST_F(CryptoMbProviderEcdsaTest, TestEcdsaQueueSizeStatistics) { Event::Dispatcher::RunType::NonBlock); out_len_ = 0; - res_ = privateKeyCompleteForTest(connections[0].get(), out_, &out_len_, max_out_len_); + res_ = ecdsaPrivateKeyCompleteForTest(connections[0].get(), out_, &out_len_, max_out_len_); EXPECT_EQ(res_, ssl_private_key_success); EXPECT_NE(out_len_, 0); @@ -451,7 +455,7 @@ TEST_F(CryptoMbProviderEcdsaTest, TestEcdsaQueueSizeStatistics) { dispatcher_->run(Event::Dispatcher::RunType::NonBlock); out_len_ = 0; - res_ = privateKeyCompleteForTest(connections[0].get(), out_, &out_len_, max_out_len_); + res_ = ecdsaPrivateKeyCompleteForTest(connections[0].get(), out_, &out_len_, max_out_len_); EXPECT_EQ(res_, ssl_private_key_success); EXPECT_NE(out_len_, 0); @@ -483,7 +487,7 @@ TEST_F(CryptoMbProviderRsaTest, TestRsaQueueSizeStatistics) { Event::Dispatcher::RunType::NonBlock); out_len_ = 0; - res_ = privateKeyCompleteForTest(connections[0].get(), out_, &out_len_, max_out_len_); + res_ = rsaPrivateKeyCompleteForTest(connections[0].get(), out_, &out_len_, max_out_len_); EXPECT_EQ(res_, ssl_private_key_success); EXPECT_NE(out_len_, 0); @@ -506,7 +510,7 @@ TEST_F(CryptoMbProviderRsaTest, TestRsaQueueSizeStatistics) { dispatcher_->run(Event::Dispatcher::RunType::NonBlock); out_len_ = 0; - res_ = privateKeyCompleteForTest(connections[0].get(), out_, &out_len_, max_out_len_); + res_ = rsaPrivateKeyCompleteForTest(connections[0].get(), out_, &out_len_, max_out_len_); EXPECT_EQ(res_, ssl_private_key_success); EXPECT_NE(out_len_, 0); diff --git a/contrib/cryptomb/private_key_providers/test/speed_test.cc b/contrib/cryptomb/private_key_providers/test/speed_test.cc new file mode 100644 index 000000000000..f5e8b87b9f47 --- /dev/null +++ b/contrib/cryptomb/private_key_providers/test/speed_test.cc @@ -0,0 +1,523 @@ +#include "source/common/common/assert.h" + +#include "benchmark/benchmark.h" +#include "gtest/gtest.h" +#include "openssl/curve25519.h" +#include "openssl/evp.h" +#include "openssl/pem.h" +#include "openssl/rand.h" +#include "openssl/ssl.h" + +#ifndef IPP_CRYPTO_DISABLED +#include "crypto_mb/ec_nistp256.h" +#include "crypto_mb/rsa.h" +#include "crypto_mb/x25519.h" +#endif + +namespace Envoy { + +constexpr absl::string_view RsaKey = R"EOF( +-----BEGIN RSA PRIVATE KEY----- +MIIEogIBAAKCAQEAtBPRFC+8WpCauAyIr1uCTSK6qtAeevEW1vRkn/KkFQX27UWS +NgU/IukTbA091BDae7HEiWSp7IA1IDbu2q4IwY9UksjF8yFVNZYifr/IzS6lbHOI +ZRxuBzQOWgn0+7WNqzylXQ4y88yVVqSsdfiB8kJHi9o5r+M/3TBOrWCu75iYJeBV +w0nhMYIYOxB0RkPqB1+5z4cgLjyZYuC6iZe+9m718J4LRHTd60lg9wtg4H7RUE3u +VgjLSNpNyvVpOW2qHq+o21gdS7xBQ3pbD619vBWeNDkvCaBp6YZw4ENhUxeg4xaZ +nOrNEKZw4HQnzklDJe1a69InQI6F2b/26VEGgQIDAQABAoIBABKTzMkBV7QcIOoF +2QAGN74PbCR9Dffu8UVBtzPNC2Jj2CKIP9o01luaofdOsmczSebi4vytlt4gJ9rn +7+I9fAfD6pyt+8XmVW0OzQY4cNXCDyzOCm8r7Knvk990EYL6KuBUhFbCRT1jiLCE +koolFfrRHaJu4+6iSg9ekW9PfxyWfAxtEp4XrrqgN4jN3Lrx1rYCZnuYp3Lb+7WI +fJC/rK6MTphUMLbPMvmUwHjFzoe7g9MZxRRY3kY3h1n3Ju1ZbaCbP0Vi/+tdgKAl +290J2MStWWJfOoTNnnOSYhWIPQUiFtuUiab7tJ90GGb1DyLbOrr6wG2awJoqF9ZM +Qwvkf/UCgYEA5dsHhxuX+cTHF6m+aGuyB0pF/cnFccTtwWz2WwiH6tldnOAIPfSi +WJU33C988KwJFmAurcW43VVVs7fxYbC6ptQluEI+/L/3Mj/3WgwZaqX00cEPkzKA +M1XbvanQAU0nGfq+ja7sZVpdbBoBUb6Bh7HFyLM3LgliT0kMQeolKXMCgYEAyI9W +tEHnkHoPjAVSSobBOqCVpTp1WGb7XoxhahjjZcTOgxucna26mUyJeHQrOPp88PJo +xxdDJU410p/tZARtFBoAa++IK9qC6QLjN23CuwhD7y6RNZsRZg0kOCg9SLj+zVj5 +mrvZFf6663EpL82UZ2zUGl4L1sMhYkia0TMjYzsCgYAFHuAIDoFQOyYETO/E+8E3 +kFwGz1vqsOxrBrZmSMZeYQFI4WTNnImRV6Gq8hPieLKrIPFpRaJcq+4A1vQ1rO47 +kTZV6IPmtZAYOnyUMPjP+2p80cQ7D0Dz49HFY+cSYFmipodgOKljiKPUKLAm1guk +rj0tv3BXQjZCdeoj/cdeKQKBgF8u3+hWqs5/j2dVkzN5drUbR0oOT2iwHzZFC2pt ++2XuHFBOx2px6/AbSdbX0zeMccVsVlu+Z4iJ8LNQYTqpexciK/cNzCN75csuKqXA +ur1G8+7Mu++j84LqU7kvJ76exZaxVmygICv3I8DfiLt+JqNbG+KTpay8GNjrOkZ0 +raPHAoGAQ1p/Qvp7DHP2qOnUB/rItEVgWECD3uPx4NOCq7Zcx7mb9p7CI6nePT5y +heHpaJIqVyaS5/LHJDwvdB1nvtlgc9xKa5d1fWhLL3dwFCa98x5PDlN/JztH8DIt +tTlD+8NECIvI+ytbzLS0PZWBYctAR2rP2qlMCGdYerdjwl8S98E= +-----END RSA PRIVATE KEY----- +)EOF"; + +constexpr absl::string_view EcdsaKey = R"EOF( +-----BEGIN EC PRIVATE KEY----- +MHcCAQEEIMpJw5U66K+DcA963b+/jZYrMrZDjaB0khHSwZte3vYCoAoGCCqGSM49 +AwEHoUQDQgAELp3XvBfkVWQBOKo3ttAaJ6SUaUb8uKqCS504WXHWMO4h89F+nYtC +Ecgl8EiLXXyc86tawKjGdizcCjrKMiFo3A== +-----END EC PRIVATE KEY----- +)EOF"; + +bssl::UniquePtr makeEcdsaKey() { + bssl::UniquePtr bio(BIO_new_mem_buf(EcdsaKey.data(), EcdsaKey.size())); + bssl::UniquePtr key(EVP_PKEY_new()); + EC_KEY* ec = PEM_read_bio_ECPrivateKey(bio.get(), nullptr, nullptr, nullptr); + RELEASE_ASSERT(ec != nullptr, "PEM_read_bio_ECPrivateKey failed."); + RELEASE_ASSERT(1 == EVP_PKEY_assign_EC_KEY(key.get(), ec), "EVP_PKEY_assign_EC_KEY failed."); + return key; +} + +bssl::UniquePtr makeRsaKey() { + bssl::UniquePtr bio(BIO_new_mem_buf(RsaKey.data(), RsaKey.size())); + bssl::UniquePtr key(EVP_PKEY_new()); + RSA* rsa = PEM_read_bio_RSAPrivateKey(bio.get(), nullptr, nullptr, nullptr); + RELEASE_ASSERT(rsa != nullptr, "PEM_read_bio_RSAPrivateKey failed."); + RELEASE_ASSERT(1 == EVP_PKEY_assign_RSA(key.get(), rsa), "EVP_PKEY_assign_RSA failed."); + return key; +} + +const std::vector& message() { CONSTRUCT_ON_FIRST_USE(std::vector, 32, 127); } + +int calculateDigest(const EVP_MD* md, const uint8_t* in, size_t in_len, unsigned char* hash, + unsigned int* hash_len) { + bssl::ScopedEVP_MD_CTX ctx; + + // Calculate the message digest for signing. + if (!EVP_DigestInit_ex(ctx.get(), md, nullptr) || !EVP_DigestUpdate(ctx.get(), in, in_len) || + !EVP_DigestFinal_ex(ctx.get(), hash, hash_len)) { + return 0; + } + return 1; +} + +void verifyEcdsa(EC_KEY* ec_key, uint8_t* out, uint32_t out_len) { + const EVP_MD* md = SSL_get_signature_algorithm_digest(SSL_SIGN_ECDSA_SECP256R1_SHA256); + uint8_t hash[EVP_MAX_MD_SIZE]; + uint32_t hash_len; + calculateDigest(md, message().data(), message().size(), hash, &hash_len); + + EXPECT_EQ(ECDSA_verify(0, hash, hash_len, out, out_len, ec_key), 1); +} + +void verifyRsa(RSA* rsa, uint8_t* out, uint32_t out_len) { + const EVP_MD* md = SSL_get_signature_algorithm_digest(SSL_SIGN_RSA_PSS_SHA256); + uint8_t buf[32]; + uint32_t buf_len; + calculateDigest(md, message().data(), message().size(), buf, &buf_len); + + EXPECT_EQ(RSA_verify_pss_mgf1(rsa, buf, buf_len, md, nullptr, -1, out, out_len), 1); +} + +// NOLINTNEXTLINE(readability-identifier-naming) +static void BM_ECDSA_Signing(benchmark::State& state) { + bssl::UniquePtr pkey = makeEcdsaKey(); + uint8_t out[512]; + uint32_t out_len; + for (auto _ : state) { // NOLINT + EC_KEY* ec_key = EVP_PKEY_get0_EC_KEY(pkey.get()); + const EVP_MD* md = SSL_get_signature_algorithm_digest(SSL_SIGN_ECDSA_SECP256R1_SHA256); + + unsigned char hash[EVP_MAX_MD_SIZE]; + unsigned int hash_len; + calculateDigest(md, message().data(), message().size(), hash, &hash_len); + + ECDSA_sign(0, hash, hash_len, out, &out_len, ec_key); + } + + EC_KEY* ec_key = EVP_PKEY_get0_EC_KEY(pkey.get()); + verifyEcdsa(ec_key, out, out_len); + + state.counters["Requests"] = benchmark::Counter(state.iterations(), benchmark::Counter::kIsRate); +} +BENCHMARK(BM_ECDSA_Signing); + +#ifndef IPP_CRYPTO_DISABLED +// NOLINTNEXTLINE(readability-identifier-naming) +static void BM_ECDSA_Signing_CryptoMB(benchmark::State& state) { + bssl::UniquePtr pkey = makeEcdsaKey(); + uint8_t out[8][512]; + size_t out_len[8]; + for (auto _ : state) { // NOLINT + std::unique_ptr in_buf[8]; + size_t sig_len[8]; + const BIGNUM* priv_key[8]; + bssl::UniquePtr ctx[8]; + BIGNUM* k[8]; + for (int i = 0; i < 8; i++) { + EC_KEY* ec_key = EVP_PKEY_get0_EC_KEY(pkey.get()); + const EVP_MD* md = SSL_get_signature_algorithm_digest(SSL_SIGN_ECDSA_SECP256R1_SHA256); + + unsigned char hash[EVP_MAX_MD_SIZE]; + unsigned int hash_len; + calculateDigest(md, message().data(), message().size(), hash, &hash_len); + + priv_key[i] = EC_KEY_get0_private_key(ec_key); + const EC_GROUP* group = EC_KEY_get0_group(ec_key); + const BIGNUM* order = EC_GROUP_get0_order(group); + ctx[i] = bssl::UniquePtr(BN_CTX_new()); + BN_CTX_start(ctx[i].get()); + k[i] = BN_CTX_get(ctx[i].get()); + while (BN_is_zero(k[i])) { + BN_rand_range(k[i], order); + } + + int len = BN_num_bits(order); + size_t buf_len = (len + 7) / 8; + if (8 * hash_len < static_cast(len)) { + in_buf[i] = std::make_unique(buf_len); + memcpy(in_buf[i].get() + buf_len - hash_len, hash, hash_len); + } else { + in_buf[i] = std::make_unique(hash_len); + memcpy(in_buf[i].get(), hash, hash_len); + } + sig_len[i] = ECDSA_size(ec_key); + } + + uint8_t sig_r[8][32]; + uint8_t sig_s[8][32]; + uint8_t* pa_sig_r[8]; + uint8_t* pa_sig_s[8]; + const uint8_t* digest[8]; + for (int i = 0; i < 8; i++) { + pa_sig_r[i] = sig_r[i]; + pa_sig_s[i] = sig_s[i]; + digest[i] = in_buf[i].get(); + } + mbx_nistp256_ecdsa_sign_ssl_mb8(pa_sig_r, pa_sig_s, digest, k, priv_key, nullptr); + + for (int i = 0; i < 8; i++) { + ECDSA_SIG* sig = ECDSA_SIG_new(); + BIGNUM* cur_sig_r = BN_bin2bn(sig_r[i], 32, nullptr); + BIGNUM* cur_sig_s = BN_bin2bn(sig_s[i], 32, nullptr); + ECDSA_SIG_set0(sig, cur_sig_r, cur_sig_s); + + CBB cbb; + CBB_init_fixed(&cbb, out[i], sig_len[i]); + ECDSA_SIG_marshal(&cbb, sig); + CBB_finish(&cbb, nullptr, &out_len[i]); + ECDSA_SIG_free(sig); + } + } + + EC_KEY* ec_key = EVP_PKEY_get0_EC_KEY(pkey.get()); + for (int i = 0; i < 8; i++) { + verifyEcdsa(ec_key, out[i], out_len[i]); + } + + state.counters["Requests"] = + benchmark::Counter(state.iterations() * 8, benchmark::Counter::kIsRate); +} +BENCHMARK(BM_ECDSA_Signing_CryptoMB); +#endif + +// NOLINTNEXTLINE(readability-identifier-naming) +static void BM_RSA_Signing(benchmark::State& state) { + bssl::UniquePtr pkey = makeRsaKey(); + uint8_t out[512]; + size_t out_len; + for (auto _ : state) { // NOLINT + RSA* rsa = EVP_PKEY_get0_RSA(pkey.get()); + const EVP_MD* md = SSL_get_signature_algorithm_digest(SSL_SIGN_RSA_PSS_SHA256); + + unsigned char hash[EVP_MAX_MD_SIZE]; + unsigned int hash_len; + calculateDigest(md, message().data(), message().size(), hash, &hash_len); + + RSA_sign_pss_mgf1(rsa, &out_len, out, 256, hash, hash_len, md, nullptr, -1); + } + + RSA* rsa = EVP_PKEY_get0_RSA(pkey.get()); + verifyRsa(rsa, out, out_len); + + state.counters["Requests"] = benchmark::Counter(state.iterations(), benchmark::Counter::kIsRate); +} +BENCHMARK(BM_RSA_Signing); + +#ifndef IPP_CRYPTO_DISABLED +// NOLINTNEXTLINE(readability-identifier-naming) +static void BM_RSA_Signing_CryptoMB(benchmark::State& state) { + bssl::UniquePtr pkey = makeRsaKey(); + uint8_t out[8][512]; + uint32_t out_len[8]; + for (auto _ : state) { // NOLINT + std::unique_ptr in_buf[8]; + uint32_t out_buf_len[8]; + const BIGNUM* p[8]; + const BIGNUM* q[8]; + const BIGNUM* dmp1[8]; + const BIGNUM* dmq1[8]; + const BIGNUM* iqmp[8]; + for (int i = 0; i < 8; i++) { + RSA* rsa = EVP_PKEY_get0_RSA(pkey.get()); + const EVP_MD* md = SSL_get_signature_algorithm_digest(SSL_SIGN_RSA_PSS_SHA256); + + unsigned char hash[EVP_MAX_MD_SIZE]; + unsigned int hash_len; + calculateDigest(md, message().data(), message().size(), hash, &hash_len); + + size_t msg_len = RSA_size(rsa); + uint8_t* msg = static_cast(OPENSSL_malloc(msg_len)); + RSA_padding_add_PKCS1_PSS_mgf1(rsa, msg, hash, md, nullptr, -1); + + RSA_get0_factors(rsa, &p[i], &q[i]); + RSA_get0_crt_params(rsa, &dmp1[i], &dmq1[i], &iqmp[i]); + + out_buf_len[i] = msg_len; + in_buf[i] = std::make_unique(msg_len); + memcpy(in_buf[i].get(), msg, msg_len); + OPENSSL_free(msg); + } + + uint8_t out_buf[8][512]; + const uint8_t* from[8]; + uint8_t* to[8]; + for (int i = 0; i < 8; i++) { + from[i] = in_buf[i].get(); + to[i] = out_buf[i]; + } + mbx_rsa_private_crt_ssl_mb8(from, to, p, q, dmp1, dmq1, iqmp, out_buf_len[0] * 8); + + for (int i = 0; i < 8; i++) { + out_len[i] = out_buf_len[i]; + memcpy(out[i], out_buf[i], out_buf_len[i]); + } + } + + RSA* rsa = EVP_PKEY_get0_RSA(pkey.get()); + for (int i = 0; i < 8; i++) { + verifyRsa(rsa, out[i], out_len[i]); + } + + state.counters["Requests"] = + benchmark::Counter(state.iterations() * 8, benchmark::Counter::kIsRate); +} +BENCHMARK(BM_RSA_Signing_CryptoMB); +#endif + +const std::vector& x25519Key() { + CONSTRUCT_ON_FIRST_USE(std::vector, + {143, 108, 246, 59, 152, 5, 67, 152, 220, 11, 144, + 198, 61, 43, 240, 209, 94, 190, 231, 111, 57, 42, + 141, 225, 230, 220, 231, 252, 50, 205, 236, 181}); +} + +const std::vector& x25519PeerKey() { + CONSTRUCT_ON_FIRST_USE(std::vector, + {64, 109, 230, 49, 46, 217, 20, 68, 22, 16, 129, + 224, 53, 100, 61, 184, 204, 65, 60, 10, 60, 73, + 62, 45, 192, 238, 74, 116, 237, 230, 155, 63}); +} + +const std::vector& p256Key() { + CONSTRUCT_ON_FIRST_USE(std::vector, + {154, 198, 171, 184, 138, 154, 154, 228, 142, 151, 103, + 249, 233, 0, 68, 110, 166, 26, 232, 232, 71, 127, + 53, 107, 249, 233, 71, 125, 136, 239, 141, 143}); +} + +const std::vector& p256PeerKey() { + CONSTRUCT_ON_FIRST_USE(std::vector, + {4, 0, 125, 68, 149, 141, 169, 88, 123, 178, 63, 48, 93, + 53, 234, 36, 240, 255, 93, 0, 165, 216, 140, 3, 12, 220, + 201, 27, 126, 171, 36, 172, 205, 175, 174, 17, 128, 214, 28, + 189, 58, 138, 133, 149, 148, 84, 2, 46, 144, 172, 236, 7, + 226, 234, 110, 168, 52, 119, 85, 146, 77, 157, 59, 39, 122}); +} + +void verifyX25519(uint8_t* ciphertext, uint8_t* secret) { + uint8_t peer_secret[32]; + X25519(peer_secret, x25519Key().data(), ciphertext); + + EXPECT_EQ(CRYPTO_memcmp(secret, peer_secret, 32), 0); +} + +void verifyP256(uint8_t* ciphertext, uint8_t* secret) { + bssl::UniquePtr key(BN_new()); + BN_bin2bn(p256Key().data(), p256Key().size(), key.get()); + + const EC_GROUP* group = EC_group_p256(); + bssl::UniquePtr point(EC_POINT_new(group)); + EC_POINT_oct2point(group, point.get(), ciphertext, 65, nullptr); + bssl::UniquePtr result(EC_POINT_new(group)); + bssl::UniquePtr x(BN_new()); + EC_POINT_mul(group, result.get(), nullptr, point.get(), key.get(), nullptr); + EC_POINT_get_affine_coordinates_GFp(group, result.get(), x.get(), nullptr, nullptr); + + uint8_t peer_secret[32]; + BN_bn2bin_padded(peer_secret, 32, x.get()); + + EXPECT_EQ(CRYPTO_memcmp(secret, peer_secret, 32), 0); +} + +// NOLINTNEXTLINE(readability-identifier-naming) +static void BM_X25519_Computing(benchmark::State& state) { + uint8_t ciphertext[32]; + uint8_t secret[32]; + for (auto _ : state) { // NOLINT + uint8_t priv_key[32]; + uint8_t public_key[32]; + X25519_keypair(public_key, priv_key); + memcpy(ciphertext, public_key, 32); + + X25519(secret, priv_key, x25519PeerKey().data()); + } + + verifyX25519(ciphertext, secret); + + state.counters["Requests"] = benchmark::Counter(state.iterations(), benchmark::Counter::kIsRate); +} +BENCHMARK(BM_X25519_Computing); + +#ifndef IPP_CRYPTO_DISABLED +// NOLINTNEXTLINE(readability-identifier-naming) +static void BM_X25519_Computing_CryptoMB(benchmark::State& state) { + uint8_t ciphertext[8][32]; + uint8_t secret[8][32]; + for (auto _ : state) { // NOLINT + uint8_t priv_key[8][32]; + // NOLINTNEXTLINE(modernize-loop-convert) + for (int i = 0; i < 8; i++) { + RAND_bytes(priv_key[i], 32); + priv_key[i][0] |= ~248; + priv_key[i][31] &= ~64; + priv_key[i][31] |= ~127; + } + + uint8_t pub_key[8][32]; + const uint8_t* pa_priv_key[8]; + uint8_t* pa_pub_key[8]; + for (int i = 0; i < 8; i++) { + pa_priv_key[i] = priv_key[i]; + pa_pub_key[i] = pub_key[i]; + } + mbx_x25519_public_key_mb8(pa_pub_key, pa_priv_key); + + uint8_t shared_key[8][32]; + uint8_t* pa_shared_key[8]; + const uint8_t* pa_peer_key[8]; + for (int i = 0; i < 8; i++) { + pa_shared_key[i] = shared_key[i]; + pa_peer_key[i] = x25519PeerKey().data(); + } + mbx_x25519_mb8(pa_shared_key, pa_priv_key, pa_peer_key); + + for (int i = 0; i < 8; i++) { + memcpy(ciphertext[i], pub_key[i], 32); + memcpy(secret[i], pa_shared_key[i], 32); + } + } + + for (int i = 0; i < 8; i++) { + verifyX25519(ciphertext[i], secret[i]); + } + + state.counters["Requests"] = + benchmark::Counter(state.iterations() * 8, benchmark::Counter::kIsRate); +} +BENCHMARK(BM_X25519_Computing_CryptoMB); +#endif + +// NOLINTNEXTLINE(readability-identifier-naming) +static void BM_P256_Computing(benchmark::State& state) { + uint8_t ciphertext[65]; + uint8_t secret[32]; + for (auto _ : state) { // NOLINT + const EC_GROUP* group = EC_group_p256(); + bssl::UniquePtr priv_key(BN_new()); + BN_rand_range_ex(priv_key.get(), 1, EC_GROUP_get0_order(group)); + bssl::UniquePtr public_key(EC_POINT_new(group)); + EC_POINT_mul(group, public_key.get(), priv_key.get(), nullptr, nullptr, nullptr); + EC_POINT_point2oct(group, public_key.get(), POINT_CONVERSION_UNCOMPRESSED, ciphertext, 65, + nullptr); + + bssl::UniquePtr peer_point(EC_POINT_new(group)); + EC_POINT_oct2point(group, peer_point.get(), p256PeerKey().data(), p256PeerKey().size(), + nullptr); + bssl::UniquePtr result(EC_POINT_new(group)); + bssl::UniquePtr x(BN_new()); + EC_POINT_mul(group, result.get(), nullptr, peer_point.get(), priv_key.get(), nullptr); + EC_POINT_get_affine_coordinates_GFp(group, result.get(), x.get(), nullptr, nullptr); + + BN_bn2bin_padded(secret, 32, x.get()); + } + + verifyP256(ciphertext, secret); + + state.counters["Requests"] = benchmark::Counter(state.iterations(), benchmark::Counter::kIsRate); +} +BENCHMARK(BM_P256_Computing); + +#ifndef IPP_CRYPTO_DISABLED +// NOLINTNEXTLINE(readability-identifier-naming) +static void BM_P256_Computing_CryptoMB(benchmark::State& state) { + const EC_GROUP* group = EC_group_p256(); + uint8_t ciphertext[8][65]; + uint8_t secret[8][32]; + for (auto _ : state) { // NOLINT + bssl::UniquePtr priv_key[8]; + // NOLINTNEXTLINE(modernize-loop-convert) + for (int i = 0; i < 8; i++) { + priv_key[i].reset(BN_new()); + BN_rand_range_ex(priv_key[i].get(), 1, EC_GROUP_get0_order(group)); + } + + bssl::UniquePtr pub_x[8]; + bssl::UniquePtr pub_y[8]; + BIGNUM* pa_pub_x[8]; + BIGNUM* pa_pub_y[8]; + const BIGNUM* pa_priv_key[8]; + for (int i = 0; i < 8; i++) { + pub_x[i].reset(BN_new()); + pub_y[i].reset(BN_new()); + pa_pub_x[i] = pub_x[i].get(); + pa_pub_y[i] = pub_y[i].get(); + pa_priv_key[i] = priv_key[i].get(); + } + mbx_nistp256_ecpublic_key_ssl_mb8(pa_pub_x, pa_pub_y, nullptr, pa_priv_key, nullptr); + + uint8_t out_ciphertext[8][65]; + bssl::UniquePtr public_key[8]; + for (int i = 0; i < 8; i++) { + public_key[i].reset(EC_POINT_new(group)); + EC_POINT_set_affine_coordinates_GFp(group, public_key[i].get(), pub_x[i].get(), + pub_y[i].get(), nullptr); + EC_POINT_point2oct(group, public_key[i].get(), POINT_CONVERSION_UNCOMPRESSED, + out_ciphertext[i], 65, nullptr); + } + + bssl::UniquePtr peer_x[8]; + bssl::UniquePtr peer_y[8]; + for (int i = 0; i < 8; i++) { + peer_x[i].reset(BN_new()); + peer_y[i].reset(BN_new()); + bssl::UniquePtr peer_key(EC_POINT_new(group)); + EC_POINT_oct2point(group, peer_key.get(), p256PeerKey().data(), p256PeerKey().size(), + nullptr); + EC_POINT_get_affine_coordinates_GFp(group, peer_key.get(), peer_x[i].get(), peer_y[i].get(), + nullptr); + } + + uint8_t shared_key[8][32] = {}; + uint8_t* pa_shared_key[8]; + BIGNUM* pa_peer_x[8]; + BIGNUM* pa_peer_y[8]; + for (int i = 0; i < 8; i++) { + pa_shared_key[i] = shared_key[i]; + pa_peer_x[i] = peer_x[i].get(); + pa_peer_y[i] = peer_y[i].get(); + } + mbx_nistp256_ecdh_ssl_mb8(pa_shared_key, pa_priv_key, pa_peer_x, pa_peer_y, nullptr, nullptr); + + for (int i = 0; i < 8; i++) { + memcpy(ciphertext[i], out_ciphertext[i], 65); + memcpy(secret[i], pa_shared_key[i], 32); + } + } + + for (int i = 0; i < 8; i++) { + verifyP256(ciphertext[i], secret[i]); + } + + state.counters["Requests"] = + benchmark::Counter(state.iterations() * 8, benchmark::Counter::kIsRate); +} +BENCHMARK(BM_P256_Computing_CryptoMB); +#endif + +} // namespace Envoy