Add bssl speed support for hashtocurve and trusttoken.
Change-Id: I74bee1855c593131bf1451553de6a56b4e0e8a54
Reviewed-on: https://boringssl-review.googlesource.com/c/boringssl/+/40804
Commit-Queue: David Benjamin <davidben@google.com>
Reviewed-by: David Benjamin <davidben@google.com>
diff --git a/crypto/trust_token/internal.h b/crypto/trust_token/internal.h
index 6edd111..3154077 100644
--- a/crypto/trust_token/internal.h
+++ b/crypto/trust_token/internal.h
@@ -25,6 +25,11 @@
#include <openssl/trust_token.h>
+#if defined(__cplusplus)
+extern "C" {
+#endif
+
+
// PMBTokens is described in https://eprint.iacr.org/2020/072/20200324:214215
// and provides anonymous tokens with private metadata. We implement the
// construction with validity verification, described in appendix H,
@@ -67,7 +72,7 @@
} PMBTOKEN_PRETOKEN;
// PMBTOKEN_PRETOKEN_free releases the memory associated with |token|.
-void PMBTOKEN_PRETOKEN_free(PMBTOKEN_PRETOKEN *token);
+OPENSSL_EXPORT void PMBTOKEN_PRETOKEN_free(PMBTOKEN_PRETOKEN *token);
DEFINE_STACK_OF(PMBTOKEN_PRETOKEN)
@@ -162,4 +167,19 @@
size_t metadata_key_len;
};
+
+#if defined(__cplusplus)
+} // extern C
+
+extern "C++" {
+
+BSSL_NAMESPACE_BEGIN
+
+BORINGSSL_MAKE_DELETER(PMBTOKEN_PRETOKEN, PMBTOKEN_PRETOKEN_free)
+
+BSSL_NAMESPACE_END
+
+} // extern C++
+#endif
+
#endif // OPENSSL_HEADER_TRUST_TOKEN_INTERNAL_H
diff --git a/tool/speed.cc b/tool/speed.cc
index 224a72b..b87afb9 100644
--- a/tool/speed.cc
+++ b/tool/speed.cc
@@ -35,9 +35,11 @@
#include <openssl/ec_key.h>
#include <openssl/evp.h>
#include <openssl/hrss.h>
+#include <openssl/mem.h>
#include <openssl/nid.h>
#include <openssl/rand.h>
#include <openssl/rsa.h>
+#include <openssl/trust_token.h>
#if defined(OPENSSL_WINDOWS)
OPENSSL_MSVC_PRAGMA(warning(push, 3))
@@ -49,7 +51,10 @@
#include <time.h>
#endif
+#include "../crypto/ec_extra/internal.h"
+#include "../crypto/fipsmodule/ec/internal.h"
#include "../crypto/internal.h"
+#include "../crypto/trust_token/internal.h"
#include "internal.h"
// g_print_json is true if printed output is JSON formatted.
@@ -942,6 +947,279 @@
return true;
}
+static bool SpeedHashToCurve(const std::string &selected) {
+ if (!selected.empty() && selected.find("hashtocurve") == std::string::npos) {
+ return true;
+ }
+
+ EC_GROUP *group = EC_GROUP_new_by_curve_name(NID_secp521r1);
+ if (group == NULL) {
+ return false;
+ }
+ uint8_t input[64];
+ RAND_bytes(input, sizeof(input));
+
+ static const uint8_t kLabel[] = "label";
+
+ TimeResults results;
+ if (!TimeFunction(&results, [&]() -> bool {
+ EC_RAW_POINT out;
+ return ec_hash_to_curve_p521_xmd_sha512_sswu(
+ group, &out, kLabel, sizeof(kLabel), input, sizeof(input));
+ })) {
+ fprintf(stderr, "hash-to-curve failed.\n");
+ return false;
+ }
+ results.Print("hash-to-curve P521_XMD:SHA-512_SSWU_RO_");
+
+ if (!TimeFunction(&results, [&]() -> bool {
+ EC_SCALAR out;
+ return ec_hash_to_scalar_p521_xmd_sha512(
+ group, &out, kLabel, sizeof(kLabel), input, sizeof(input));
+ })) {
+ fprintf(stderr, "hash-to-scalar failed.\n");
+ return false;
+ }
+ results.Print("hash-to-scalar P521_XMD:SHA-512");
+
+ return true;
+}
+
+static PMBTOKEN_PRETOKEN *pmbtoken_pretoken_dup(PMBTOKEN_PRETOKEN *in) {
+ PMBTOKEN_PRETOKEN *out =
+ (PMBTOKEN_PRETOKEN *)OPENSSL_malloc(sizeof(PMBTOKEN_PRETOKEN));
+ if (out) {
+ OPENSSL_memcpy(out, in, sizeof(PMBTOKEN_PRETOKEN));
+ }
+ return out;
+}
+
+static bool SpeedTrustToken(std::string name, size_t batchsize,
+ const std::string &selected) {
+ if (!selected.empty() && selected.find("trusttoken") == std::string::npos) {
+ return true;
+ }
+
+ TimeResults results;
+ if (!TimeFunction(&results, [&]() -> bool {
+ uint8_t priv_key[TRUST_TOKEN_MAX_PRIVATE_KEY_SIZE];
+ uint8_t pub_key[TRUST_TOKEN_MAX_PUBLIC_KEY_SIZE];
+ size_t priv_key_len, pub_key_len;
+ return TRUST_TOKEN_generate_key(
+ priv_key, &priv_key_len, TRUST_TOKEN_MAX_PRIVATE_KEY_SIZE, pub_key,
+ &pub_key_len, TRUST_TOKEN_MAX_PUBLIC_KEY_SIZE, 0);
+ })) {
+ fprintf(stderr, "TRUST_TOKEN_generate_key failed.\n");
+ return false;
+ }
+ results.Print(name + " generate_key");
+
+ bssl::UniquePtr<TRUST_TOKEN_CLIENT> client(TRUST_TOKEN_CLIENT_new(batchsize));
+ bssl::UniquePtr<TRUST_TOKEN_ISSUER> issuer(TRUST_TOKEN_ISSUER_new(batchsize));
+ uint8_t priv_key[TRUST_TOKEN_MAX_PRIVATE_KEY_SIZE];
+ uint8_t pub_key[TRUST_TOKEN_MAX_PUBLIC_KEY_SIZE];
+ size_t priv_key_len, pub_key_len, key_index;
+ if (!client ||
+ !issuer ||
+ !TRUST_TOKEN_generate_key(
+ priv_key, &priv_key_len, TRUST_TOKEN_MAX_PRIVATE_KEY_SIZE, pub_key,
+ &pub_key_len, TRUST_TOKEN_MAX_PUBLIC_KEY_SIZE, 0) ||
+ !TRUST_TOKEN_CLIENT_add_key(client.get(), &key_index, pub_key,
+ pub_key_len) ||
+ !TRUST_TOKEN_ISSUER_add_key(issuer.get(), priv_key, priv_key_len)) {
+ fprintf(stderr, "failed to generate trust token key.\n");
+ return false;
+ }
+
+ uint8_t public_key[32], private_key[64];
+ ED25519_keypair(public_key, private_key);
+ bssl::UniquePtr<EVP_PKEY> priv(
+ EVP_PKEY_new_raw_private_key(EVP_PKEY_ED25519, nullptr, private_key, 32));
+ bssl::UniquePtr<EVP_PKEY> pub(
+ EVP_PKEY_new_raw_public_key(EVP_PKEY_ED25519, nullptr, public_key, 32));
+ if (!priv || !pub) {
+ fprintf(stderr, "failed to generate trust token SRR key.\n");
+ return false;
+ }
+
+ TRUST_TOKEN_CLIENT_set_srr_key(client.get(), pub.get());
+ TRUST_TOKEN_ISSUER_set_srr_key(issuer.get(), priv.get());
+ uint8_t metadata_key[32];
+ RAND_bytes(metadata_key, sizeof(metadata_key));
+ if (!TRUST_TOKEN_ISSUER_set_metadata_key(issuer.get(), metadata_key,
+ sizeof(metadata_key))) {
+ fprintf(stderr, "failed to generate trust token metadata key.\n");
+ return false;
+ }
+
+ if (!TimeFunction(&results, [&]() -> bool {
+ uint8_t *issue_msg = NULL;
+ size_t msg_len;
+ int ok = TRUST_TOKEN_CLIENT_begin_issuance(client.get(), &issue_msg,
+ &msg_len, batchsize);
+ OPENSSL_free(issue_msg);
+ // Clear pretokens.
+ sk_PMBTOKEN_PRETOKEN_pop_free(client->pretokens,
+ PMBTOKEN_PRETOKEN_free);
+ client->pretokens = sk_PMBTOKEN_PRETOKEN_new_null();
+ return ok;
+ })) {
+ fprintf(stderr, "TRUST_TOKEN_CLIENT_begin_issuance failed.\n");
+ return false;
+ }
+ results.Print(name + " begin_issuance");
+
+ uint8_t *issue_msg = NULL;
+ size_t msg_len;
+ if (!TRUST_TOKEN_CLIENT_begin_issuance(client.get(), &issue_msg, &msg_len,
+ batchsize)) {
+ fprintf(stderr, "TRUST_TOKEN_CLIENT_begin_issuance failed.\n");
+ return false;
+ }
+ bssl::UniquePtr<uint8_t> free_issue_msg(issue_msg);
+
+ bssl::UniquePtr<STACK_OF(PMBTOKEN_PRETOKEN)> pretokens(
+ sk_PMBTOKEN_PRETOKEN_deep_copy(client->pretokens, pmbtoken_pretoken_dup,
+ PMBTOKEN_PRETOKEN_free));
+
+ if (!TimeFunction(&results, [&]() -> bool {
+ uint8_t *issue_resp = NULL;
+ size_t resp_len;
+ uint8_t tokens_issued;
+ int ok = TRUST_TOKEN_ISSUER_issue(issuer.get(), &issue_resp, &resp_len,
+ &tokens_issued, issue_msg, msg_len,
+ /*public_metadata=*/0,
+ /*private_metadata=*/0,
+ /*max_issuance=*/batchsize);
+ OPENSSL_free(issue_resp);
+ return ok;
+ })) {
+ fprintf(stderr, "TRUST_TOKEN_ISSUER_issue failed.\n");
+ return false;
+ }
+ results.Print(name + " issue");
+
+ uint8_t *issue_resp = NULL;
+ size_t resp_len;
+ uint8_t tokens_issued;
+ if (!TRUST_TOKEN_ISSUER_issue(issuer.get(), &issue_resp, &resp_len,
+ &tokens_issued, issue_msg, msg_len,
+ /*public_metadata=*/0, /*private_metadata=*/0,
+ /*max_issuance=*/batchsize)) {
+ fprintf(stderr, "TRUST_TOKEN_ISSUER_issue failed.\n");
+ return false;
+ }
+ bssl::UniquePtr<uint8_t> free_issue_resp(issue_resp);
+
+ if (!TimeFunction(&results, [&]() -> bool {
+ size_t key_index2;
+ bssl::UniquePtr<STACK_OF(TRUST_TOKEN)> tokens(
+ TRUST_TOKEN_CLIENT_finish_issuance(client.get(), &key_index2,
+ issue_resp, resp_len));
+
+ // Reset pretokens.
+ client->pretokens = sk_PMBTOKEN_PRETOKEN_deep_copy(
+ pretokens.get(), pmbtoken_pretoken_dup, PMBTOKEN_PRETOKEN_free);
+ return !!tokens;
+ })) {
+ fprintf(stderr, "TRUST_TOKEN_CLIENT_finish_issuance failed.\n");
+ return false;
+ }
+ results.Print(name + " finish_issuance");
+
+ bssl::UniquePtr<STACK_OF(TRUST_TOKEN)> tokens(
+ TRUST_TOKEN_CLIENT_finish_issuance(client.get(), &key_index, issue_resp,
+ resp_len));
+ if (!tokens || sk_TRUST_TOKEN_num(tokens.get()) < 1) {
+ fprintf(stderr, "TRUST_TOKEN_CLIENT_finish_issuance failed.\n");
+ return false;
+ }
+
+ const TRUST_TOKEN *token = sk_TRUST_TOKEN_value(tokens.get(), 0);
+
+ const uint8_t kClientData[] = "\x70TEST CLIENT DATA";
+ uint64_t kRedemptionTime = 13374242;
+
+ if (!TimeFunction(&results, [&]() -> bool {
+ uint8_t *redeem_msg = NULL;
+ size_t redeem_msg_len;
+ int ok = TRUST_TOKEN_CLIENT_begin_redemption(
+ client.get(), &redeem_msg, &redeem_msg_len, token, kClientData,
+ sizeof(kClientData) - 1, kRedemptionTime);
+ OPENSSL_free(redeem_msg);
+ return ok;
+ })) {
+ fprintf(stderr, "TRUST_TOKEN_CLIENT_begin_redemption failed.\n");
+ return false;
+ }
+ results.Print(name + " begin_redemption");
+
+ uint8_t *redeem_msg = NULL;
+ size_t redeem_msg_len;
+ if (!TRUST_TOKEN_CLIENT_begin_redemption(
+ client.get(), &redeem_msg, &redeem_msg_len, token, kClientData,
+ sizeof(kClientData) - 1, kRedemptionTime)) {
+ fprintf(stderr, "TRUST_TOKEN_CLIENT_begin_redemption failed.\n");
+ return false;
+ }
+ bssl::UniquePtr<uint8_t> free_redeem_msg(redeem_msg);
+
+ if (!TimeFunction(&results, [&]() -> bool {
+ uint8_t *redeem_resp = NULL;
+ size_t redeem_resp_len;
+ TRUST_TOKEN *rtoken = NULL;
+ uint8_t *client_data = NULL;
+ size_t client_data_len;
+ uint64_t redemption_time;
+ int ok = TRUST_TOKEN_ISSUER_redeem(
+ issuer.get(), &redeem_resp, &redeem_resp_len, &rtoken, &client_data,
+ &client_data_len, &redemption_time, redeem_msg, redeem_msg_len,
+ /*lifetime=*/600);
+ OPENSSL_free(redeem_resp);
+ OPENSSL_free(client_data);
+ TRUST_TOKEN_free(rtoken);
+ return ok;
+ })) {
+ fprintf(stderr, "TRUST_TOKEN_ISSUER_redeem failed.\n");
+ return false;
+ }
+ results.Print(name + " redeem");
+
+ uint8_t *redeem_resp = NULL;
+ size_t redeem_resp_len;
+ TRUST_TOKEN *rtoken = NULL;
+ uint8_t *client_data = NULL;
+ size_t client_data_len;
+ uint64_t redemption_time;
+ if (!TRUST_TOKEN_ISSUER_redeem(issuer.get(), &redeem_resp, &redeem_resp_len,
+ &rtoken, &client_data, &client_data_len,
+ &redemption_time, redeem_msg, redeem_msg_len,
+ /*lifetime=*/600)) {
+ fprintf(stderr, "TRUST_TOKEN_ISSUER_redeem failed.\n");
+ return false;
+ }
+ bssl::UniquePtr<uint8_t> free_redeem_resp(redeem_resp);
+ bssl::UniquePtr<uint8_t> free_client_data(client_data);
+ bssl::UniquePtr<TRUST_TOKEN> free_rtoken(rtoken);
+
+ if (!TimeFunction(&results, [&]() -> bool {
+ uint8_t *srr = NULL, *sig = NULL;
+ size_t srr_len, sig_len;
+ int ok = TRUST_TOKEN_CLIENT_finish_redemption(client.get(), &srr,
+ &srr_len, &sig, &sig_len,
+ redeem_resp, resp_len);
+ OPENSSL_free(srr);
+ OPENSSL_free(sig);
+ return ok;
+ })) {
+ fprintf(stderr, "TRUST_TOKEN_CLIENT_finish_redemption failed.\n");
+ return false;
+ }
+ results.Print(name + " finish_redemption");
+
+ return true;
+}
+
static const struct argument kArguments[] = {
{
"-filter",
@@ -1071,7 +1349,10 @@
!SpeedSPAKE2(selected) ||
!SpeedScrypt(selected) ||
!SpeedRSAKeyGen(selected) ||
- !SpeedHRSS(selected)) {
+ !SpeedHRSS(selected) ||
+ !SpeedHashToCurve(selected) ||
+ !SpeedTrustToken("TrustToken-Batch1", 1, selected) ||
+ !SpeedTrustToken("TrustToken-Batch10", 10, selected)) {
return false;
}
if (g_print_json) {