1 /* Copyright (c) 2014, Google Inc.
2 *
3 * Permission to use, copy, modify, and/or distribute this software for any
4 * purpose with or without fee is hereby granted, provided that the above
5 * copyright notice and this permission notice appear in all copies.
6 *
7 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
8 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
9 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
10 * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
11 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
12 * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
13 * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */
14
15 #include <algorithm>
16 #include <functional>
17 #include <memory>
18 #include <string>
19 #include <vector>
20
21 #include <assert.h>
22 #include <errno.h>
23 #include <inttypes.h>
24 #include <stdint.h>
25 #include <stdlib.h>
26 #include <string.h>
27
28 #define OPENSSL_I_UNDERSTAND_EXPERIMENTAL_FUNCTION_RISK
29
30 #include <openssl/aead.h>
31 #include <openssl/aes.h>
32 #include <openssl/base64.h>
33 #include <openssl/bn.h>
34 #include <openssl/bytestring.h>
35 #include <openssl/crypto.h>
36 #include <openssl/curve25519.h>
37 #include <openssl/digest.h>
38 #include <openssl/ec.h>
39 #include <openssl/ec_key.h>
40 #include <openssl/ecdsa.h>
41 #include <openssl/err.h>
42 #include <openssl/evp.h>
43 #define OPENSSL_UNSTABLE_EXPERIMENTAL_DILITHIUM
44 #include <openssl/experimental/dilithium.h>
45 #define OPENSSL_UNSTABLE_EXPERIMENTAL_SPX
46 #include <openssl/experimental/kyber.h>
47 #include <openssl/experimental/spx.h>
48 #include <openssl/hrss.h>
49 #include <openssl/mem.h>
50 #include <openssl/nid.h>
51 #include <openssl/rand.h>
52 #include <openssl/rsa.h>
53 #include <openssl/siphash.h>
54 #include <openssl/trust_token.h>
55
56 #if defined(OPENSSL_WINDOWS)
57 OPENSSL_MSVC_PRAGMA(warning(push, 3))
58 #include <windows.h>
59 OPENSSL_MSVC_PRAGMA(warning(pop))
60 #elif defined(OPENSSL_APPLE)
61 #include <sys/time.h>
62 #else
63 #include <time.h>
64 #endif
65
66 #if defined(OPENSSL_THREADS)
67 #include <condition_variable>
68 #include <mutex>
69 #include <thread>
70 #endif
71
72 #include "../crypto/ec_extra/internal.h"
73 #include "../crypto/fipsmodule/ec/internal.h"
74 #include "../crypto/internal.h"
75 #include "../crypto/trust_token/internal.h"
76 #include "internal.h"
77
78 // g_print_json is true if printed output is JSON formatted.
79 static bool g_print_json = false;
80
81 // TimeResults represents the results of benchmarking a function.
82 struct TimeResults {
83 // num_calls is the number of function calls done in the time period.
84 uint64_t num_calls;
85 // us is the number of microseconds that elapsed in the time period.
86 uint64_t us;
87
PrintTimeResults88 void Print(const std::string &description) const {
89 if (g_print_json) {
90 PrintJSON(description);
91 } else {
92 printf(
93 "Did %" PRIu64 " %s operations in %" PRIu64 "us (%.1f ops/sec)\n",
94 num_calls, description.c_str(), us,
95 (static_cast<double>(num_calls) / static_cast<double>(us)) * 1000000);
96 }
97 }
98
PrintWithBytesTimeResults99 void PrintWithBytes(const std::string &description,
100 size_t bytes_per_call) const {
101 if (g_print_json) {
102 PrintJSON(description, bytes_per_call);
103 } else {
104 printf(
105 "Did %" PRIu64 " %s operations in %" PRIu64
106 "us (%.1f ops/sec): %.1f MB/s\n",
107 num_calls, description.c_str(), us,
108 (static_cast<double>(num_calls) / static_cast<double>(us)) * 1000000,
109 static_cast<double>(bytes_per_call * num_calls) /
110 static_cast<double>(us));
111 }
112 }
113
114 private:
PrintJSONTimeResults115 void PrintJSON(const std::string &description,
116 size_t bytes_per_call = 0) const {
117 if (first_json_printed) {
118 puts(",");
119 }
120
121 printf("{\"description\": \"%s\", \"numCalls\": %" PRIu64
122 ", \"microseconds\": %" PRIu64,
123 description.c_str(), num_calls, us);
124
125 if (bytes_per_call > 0) {
126 printf(", \"bytesPerCall\": %zu", bytes_per_call);
127 }
128
129 printf("}");
130 first_json_printed = true;
131 }
132
133 // first_json_printed is true if |g_print_json| is true and the first item in
134 // the JSON results has been printed already. This is used to handle the
135 // commas between each item in the result list.
136 static bool first_json_printed;
137 };
138
139 bool TimeResults::first_json_printed = false;
140
141 #if defined(OPENSSL_WINDOWS)
time_now()142 static uint64_t time_now() { return GetTickCount64() * 1000; }
143 #elif defined(OPENSSL_APPLE)
time_now()144 static uint64_t time_now() {
145 struct timeval tv;
146 uint64_t ret;
147
148 gettimeofday(&tv, NULL);
149 ret = tv.tv_sec;
150 ret *= 1000000;
151 ret += tv.tv_usec;
152 return ret;
153 }
154 #else
time_now()155 static uint64_t time_now() {
156 struct timespec ts;
157 clock_gettime(CLOCK_MONOTONIC, &ts);
158
159 uint64_t ret = ts.tv_sec;
160 ret *= 1000000;
161 ret += ts.tv_nsec / 1000;
162 return ret;
163 }
164 #endif
165
166 static uint64_t g_timeout_seconds = 1;
167 static std::vector<size_t> g_chunk_lengths = {16, 256, 1350, 8192, 16384};
168
169 // IterationsBetweenTimeChecks returns the number of iterations of |func| to run
170 // in between checking the time, or zero on error.
IterationsBetweenTimeChecks(std::function<bool ()> func)171 static uint32_t IterationsBetweenTimeChecks(std::function<bool()> func) {
172 uint64_t start = time_now();
173 if (!func()) {
174 return 0;
175 }
176 uint64_t delta = time_now() - start;
177 if (delta == 0) {
178 return 250;
179 }
180
181 // Aim for about 100ms between time checks.
182 uint32_t ret = static_cast<double>(100000) / static_cast<double>(delta);
183 if (ret > 1000) {
184 ret = 1000;
185 } else if (ret < 1) {
186 ret = 1;
187 }
188 return ret;
189 }
190
TimeFunctionImpl(TimeResults * results,std::function<bool ()> func,uint32_t iterations_between_time_checks)191 static bool TimeFunctionImpl(TimeResults *results, std::function<bool()> func,
192 uint32_t iterations_between_time_checks) {
193 // total_us is the total amount of time that we'll aim to measure a function
194 // for.
195 const uint64_t total_us = g_timeout_seconds * 1000000;
196 uint64_t start = time_now(), now;
197 uint64_t done = 0;
198 for (;;) {
199 for (uint32_t i = 0; i < iterations_between_time_checks; i++) {
200 if (!func()) {
201 return false;
202 }
203 done++;
204 }
205
206 now = time_now();
207 if (now - start > total_us) {
208 break;
209 }
210 }
211
212 results->us = now - start;
213 results->num_calls = done;
214 return true;
215 }
216
TimeFunction(TimeResults * results,std::function<bool ()> func)217 static bool TimeFunction(TimeResults *results, std::function<bool()> func) {
218 uint32_t iterations_between_time_checks = IterationsBetweenTimeChecks(func);
219 if (iterations_between_time_checks == 0) {
220 return false;
221 }
222
223 return TimeFunctionImpl(results, std::move(func),
224 iterations_between_time_checks);
225 }
226
227 #if defined(OPENSSL_THREADS)
228 // g_threads is the number of threads to run in parallel benchmarks.
229 static int g_threads = 1;
230
231 // Latch behaves like C++20 std::latch.
232 class Latch {
233 public:
Latch(int expected)234 explicit Latch(int expected) : expected_(expected) {}
235 Latch(const Latch &) = delete;
236 Latch &operator=(const Latch &) = delete;
237
ArriveAndWait()238 void ArriveAndWait() {
239 std::unique_lock<std::mutex> lock(lock_);
240 expected_--;
241 if (expected_ > 0) {
242 cond_.wait(lock, [&] { return expected_ == 0; });
243 } else {
244 cond_.notify_all();
245 }
246 }
247
248 private:
249 int expected_;
250 std::mutex lock_;
251 std::condition_variable cond_;
252 };
253
TimeFunctionParallel(TimeResults * results,std::function<bool ()> func)254 static bool TimeFunctionParallel(TimeResults *results,
255 std::function<bool()> func) {
256 if (g_threads <= 1) {
257 return TimeFunction(results, std::move(func));
258 }
259
260 uint32_t iterations_between_time_checks = IterationsBetweenTimeChecks(func);
261 if (iterations_between_time_checks == 0) {
262 return false;
263 }
264
265 struct ThreadResult {
266 TimeResults time_result;
267 bool ok = false;
268 };
269 std::vector<ThreadResult> thread_results(g_threads);
270 Latch latch(g_threads);
271 std::vector<std::thread> threads;
272 for (int i = 0; i < g_threads; i++) {
273 threads.emplace_back([&, i] {
274 // Wait for all the threads to be ready before running the benchmark.
275 latch.ArriveAndWait();
276 thread_results[i].ok = TimeFunctionImpl(
277 &thread_results[i].time_result, func, iterations_between_time_checks);
278 });
279 }
280
281 for (auto &thread : threads) {
282 thread.join();
283 }
284
285 results->num_calls = 0;
286 results->us = 0;
287 for (const auto &pair : thread_results) {
288 if (!pair.ok) {
289 return false;
290 }
291 results->num_calls += pair.time_result.num_calls;
292 results->us += pair.time_result.us;
293 }
294 return true;
295 }
296
297 #else
TimeFunctionParallel(TimeResults * results,std::function<bool ()> func)298 static bool TimeFunctionParallel(TimeResults *results,
299 std::function<bool()> func) {
300 return TimeFunction(results, std::move(func));
301 }
302 #endif
303
SpeedRSA(const std::string & selected)304 static bool SpeedRSA(const std::string &selected) {
305 if (!selected.empty() && selected.find("RSA") == std::string::npos) {
306 return true;
307 }
308
309 static const struct {
310 const char *name;
311 const uint8_t *key;
312 const size_t key_len;
313 } kRSAKeys[] = {
314 {"RSA 2048", kDERRSAPrivate2048, kDERRSAPrivate2048Len},
315 {"RSA 4096", kDERRSAPrivate4096, kDERRSAPrivate4096Len},
316 };
317
318 for (size_t i = 0; i < OPENSSL_ARRAY_SIZE(kRSAKeys); i++) {
319 const std::string name = kRSAKeys[i].name;
320
321 bssl::UniquePtr<RSA> key(
322 RSA_private_key_from_bytes(kRSAKeys[i].key, kRSAKeys[i].key_len));
323 if (key == nullptr) {
324 fprintf(stderr, "Failed to parse %s key.\n", name.c_str());
325 ERR_print_errors_fp(stderr);
326 return false;
327 }
328
329 static constexpr size_t kMaxSignature = 512;
330 if (RSA_size(key.get()) > kMaxSignature) {
331 abort();
332 }
333 const uint8_t fake_sha256_hash[32] = {0};
334
335 TimeResults results;
336 if (!TimeFunctionParallel(&results, [&key, &fake_sha256_hash]() -> bool {
337 // Usually during RSA signing we're using a long-lived |RSA| that
338 // has already had all of its |BN_MONT_CTX|s constructed, so it
339 // makes sense to use |key| directly here.
340 uint8_t out[kMaxSignature];
341 unsigned out_len;
342 return RSA_sign(NID_sha256, fake_sha256_hash,
343 sizeof(fake_sha256_hash), out, &out_len, key.get());
344 })) {
345 fprintf(stderr, "RSA_sign failed.\n");
346 ERR_print_errors_fp(stderr);
347 return false;
348 }
349 results.Print(name + " signing");
350
351 uint8_t sig[kMaxSignature];
352 unsigned sig_len;
353 if (!RSA_sign(NID_sha256, fake_sha256_hash, sizeof(fake_sha256_hash), sig,
354 &sig_len, key.get())) {
355 return false;
356 }
357 if (!TimeFunctionParallel(
358 &results, [&key, &fake_sha256_hash, &sig, sig_len]() -> bool {
359 return RSA_verify(NID_sha256, fake_sha256_hash,
360 sizeof(fake_sha256_hash), sig, sig_len,
361 key.get());
362 })) {
363 fprintf(stderr, "RSA_verify failed.\n");
364 ERR_print_errors_fp(stderr);
365 return false;
366 }
367 results.Print(name + " verify (same key)");
368
369 if (!TimeFunctionParallel(
370 &results, [&key, &fake_sha256_hash, &sig, sig_len]() -> bool {
371 // Usually during RSA verification we have to parse an RSA key
372 // from a certificate or similar, in which case we'd need to
373 // construct a new RSA key, with a new |BN_MONT_CTX| for the
374 // public modulus. If we were to use |key| directly instead, then
375 // these costs wouldn't be accounted for.
376 bssl::UniquePtr<RSA> verify_key(RSA_new_public_key(
377 RSA_get0_n(key.get()), RSA_get0_e(key.get())));
378 if (!verify_key) {
379 return false;
380 }
381 return RSA_verify(NID_sha256, fake_sha256_hash,
382 sizeof(fake_sha256_hash), sig, sig_len,
383 verify_key.get());
384 })) {
385 fprintf(stderr, "RSA_verify failed.\n");
386 ERR_print_errors_fp(stderr);
387 return false;
388 }
389 results.Print(name + " verify (fresh key)");
390
391 if (!TimeFunctionParallel(&results, [&]() -> bool {
392 return bssl::UniquePtr<RSA>(RSA_private_key_from_bytes(
393 kRSAKeys[i].key, kRSAKeys[i].key_len)) != nullptr;
394 })) {
395 fprintf(stderr, "Failed to parse %s key.\n", name.c_str());
396 ERR_print_errors_fp(stderr);
397 return false;
398 }
399 results.Print(name + " private key parse");
400 }
401
402 return true;
403 }
404
SpeedRSAKeyGen(const std::string & selected)405 static bool SpeedRSAKeyGen(const std::string &selected) {
406 // Don't run this by default because it's so slow.
407 if (selected != "RSAKeyGen") {
408 return true;
409 }
410
411 bssl::UniquePtr<BIGNUM> e(BN_new());
412 if (!BN_set_word(e.get(), 65537)) {
413 return false;
414 }
415
416 const std::vector<int> kSizes = {2048, 3072, 4096};
417 for (int size : kSizes) {
418 const uint64_t start = time_now();
419 uint64_t num_calls = 0;
420 uint64_t us;
421 std::vector<uint64_t> durations;
422
423 for (;;) {
424 bssl::UniquePtr<RSA> rsa(RSA_new());
425
426 const uint64_t iteration_start = time_now();
427 if (!RSA_generate_key_ex(rsa.get(), size, e.get(), nullptr)) {
428 fprintf(stderr, "RSA_generate_key_ex failed.\n");
429 ERR_print_errors_fp(stderr);
430 return false;
431 }
432 const uint64_t iteration_end = time_now();
433
434 num_calls++;
435 durations.push_back(iteration_end - iteration_start);
436
437 us = iteration_end - start;
438 if (us > 30 * 1000000 /* 30 secs */) {
439 break;
440 }
441 }
442
443 std::sort(durations.begin(), durations.end());
444 const std::string description =
445 std::string("RSA ") + std::to_string(size) + std::string(" key-gen");
446 const TimeResults results = {num_calls, us};
447 results.Print(description);
448 const size_t n = durations.size();
449 assert(n > 0);
450
451 // Distribution information is useful, but doesn't fit into the standard
452 // format used by |g_print_json|.
453 if (!g_print_json) {
454 uint64_t min = durations[0];
455 uint64_t median = n & 1 ? durations[n / 2]
456 : (durations[n / 2 - 1] + durations[n / 2]) / 2;
457 uint64_t max = durations[n - 1];
458 printf(" min: %" PRIu64 "us, median: %" PRIu64 "us, max: %" PRIu64
459 "us\n",
460 min, median, max);
461 }
462 }
463
464 return true;
465 }
466
ChunkLenSuffix(size_t chunk_len)467 static std::string ChunkLenSuffix(size_t chunk_len) {
468 char buf[32];
469 snprintf(buf, sizeof(buf), " (%zu byte%s)", chunk_len,
470 chunk_len != 1 ? "s" : "");
471 return buf;
472 }
473
SpeedAEADChunk(const EVP_AEAD * aead,std::string name,size_t chunk_len,size_t ad_len,evp_aead_direction_t direction)474 static bool SpeedAEADChunk(const EVP_AEAD *aead, std::string name,
475 size_t chunk_len, size_t ad_len,
476 evp_aead_direction_t direction) {
477 static const unsigned kAlignment = 16;
478
479 name += ChunkLenSuffix(chunk_len);
480 bssl::ScopedEVP_AEAD_CTX ctx;
481 const size_t key_len = EVP_AEAD_key_length(aead);
482 const size_t nonce_len = EVP_AEAD_nonce_length(aead);
483 const size_t overhead_len = EVP_AEAD_max_overhead(aead);
484
485 auto key = std::make_unique<uint8_t[]>(key_len);
486 OPENSSL_memset(key.get(), 0, key_len);
487 auto nonce = std::make_unique<uint8_t[]>(nonce_len);
488 OPENSSL_memset(nonce.get(), 0, nonce_len);
489 auto in_storage = std::make_unique<uint8_t[]>(chunk_len + kAlignment);
490 // N.B. for EVP_AEAD_CTX_seal_scatter the input and output buffers may be the
491 // same size. However, in the direction == evp_aead_open case we still use
492 // non-scattering seal, hence we add overhead_len to the size of this buffer.
493 auto out_storage =
494 std::make_unique<uint8_t[]>(chunk_len + overhead_len + kAlignment);
495 auto in2_storage =
496 std::make_unique<uint8_t[]>(chunk_len + overhead_len + kAlignment);
497 auto ad = std::make_unique<uint8_t[]>(ad_len);
498 OPENSSL_memset(ad.get(), 0, ad_len);
499 auto tag_storage = std::make_unique<uint8_t[]>(overhead_len + kAlignment);
500
501 uint8_t *const in =
502 static_cast<uint8_t *>(align_pointer(in_storage.get(), kAlignment));
503 OPENSSL_memset(in, 0, chunk_len);
504 uint8_t *const out =
505 static_cast<uint8_t *>(align_pointer(out_storage.get(), kAlignment));
506 OPENSSL_memset(out, 0, chunk_len + overhead_len);
507 uint8_t *const tag =
508 static_cast<uint8_t *>(align_pointer(tag_storage.get(), kAlignment));
509 OPENSSL_memset(tag, 0, overhead_len);
510 uint8_t *const in2 =
511 static_cast<uint8_t *>(align_pointer(in2_storage.get(), kAlignment));
512
513 if (!EVP_AEAD_CTX_init_with_direction(ctx.get(), aead, key.get(), key_len,
514 EVP_AEAD_DEFAULT_TAG_LENGTH,
515 evp_aead_seal)) {
516 fprintf(stderr, "Failed to create EVP_AEAD_CTX.\n");
517 ERR_print_errors_fp(stderr);
518 return false;
519 }
520
521 // TODO(davidben): In most cases, this can be |TimeFunctionParallel|, but a
522 // few stateful AEADs must be run serially.
523 TimeResults results;
524 if (direction == evp_aead_seal) {
525 if (!TimeFunction(&results,
526 [chunk_len, nonce_len, ad_len, overhead_len, in, out, tag,
527 &ctx, &nonce, &ad]() -> bool {
528 size_t tag_len;
529 return EVP_AEAD_CTX_seal_scatter(
530 ctx.get(), out, tag, &tag_len, overhead_len,
531 nonce.get(), nonce_len, in, chunk_len, nullptr, 0,
532 ad.get(), ad_len);
533 })) {
534 fprintf(stderr, "EVP_AEAD_CTX_seal failed.\n");
535 ERR_print_errors_fp(stderr);
536 return false;
537 }
538 } else {
539 size_t out_len;
540 EVP_AEAD_CTX_seal(ctx.get(), out, &out_len, chunk_len + overhead_len,
541 nonce.get(), nonce_len, in, chunk_len, ad.get(), ad_len);
542
543 ctx.Reset();
544 if (!EVP_AEAD_CTX_init_with_direction(ctx.get(), aead, key.get(), key_len,
545 EVP_AEAD_DEFAULT_TAG_LENGTH,
546 evp_aead_open)) {
547 fprintf(stderr, "Failed to create EVP_AEAD_CTX.\n");
548 ERR_print_errors_fp(stderr);
549 return false;
550 }
551
552 if (!TimeFunction(&results,
553 [chunk_len, overhead_len, nonce_len, ad_len, in2, out,
554 out_len, &ctx, &nonce, &ad]() -> bool {
555 size_t in2_len;
556 // N.B. EVP_AEAD_CTX_open_gather is not implemented for
557 // all AEADs.
558 return EVP_AEAD_CTX_open(ctx.get(), in2, &in2_len,
559 chunk_len + overhead_len,
560 nonce.get(), nonce_len, out,
561 out_len, ad.get(), ad_len);
562 })) {
563 fprintf(stderr, "EVP_AEAD_CTX_open failed.\n");
564 ERR_print_errors_fp(stderr);
565 return false;
566 }
567 }
568
569 results.PrintWithBytes(
570 name + (direction == evp_aead_seal ? " seal" : " open"), chunk_len);
571 return true;
572 }
573
SpeedAEAD(const EVP_AEAD * aead,const std::string & name,size_t ad_len,const std::string & selected)574 static bool SpeedAEAD(const EVP_AEAD *aead, const std::string &name,
575 size_t ad_len, const std::string &selected) {
576 if (!selected.empty() && name.find(selected) == std::string::npos) {
577 return true;
578 }
579
580 for (size_t chunk_len : g_chunk_lengths) {
581 if (!SpeedAEADChunk(aead, name, chunk_len, ad_len, evp_aead_seal)) {
582 return false;
583 }
584 }
585 return true;
586 }
587
SpeedAEADOpen(const EVP_AEAD * aead,const std::string & name,size_t ad_len,const std::string & selected)588 static bool SpeedAEADOpen(const EVP_AEAD *aead, const std::string &name,
589 size_t ad_len, const std::string &selected) {
590 if (!selected.empty() && name.find(selected) == std::string::npos) {
591 return true;
592 }
593
594 for (size_t chunk_len : g_chunk_lengths) {
595 if (!SpeedAEADChunk(aead, name, chunk_len, ad_len, evp_aead_open)) {
596 return false;
597 }
598 }
599
600 return true;
601 }
602
SpeedAESBlock(const std::string & name,unsigned bits,const std::string & selected)603 static bool SpeedAESBlock(const std::string &name, unsigned bits,
604 const std::string &selected) {
605 if (!selected.empty() && name.find(selected) == std::string::npos) {
606 return true;
607 }
608
609 static const uint8_t kZero[32] = {0};
610
611 {
612 TimeResults results;
613 if (!TimeFunctionParallel(&results, [&]() -> bool {
614 AES_KEY key;
615 return AES_set_encrypt_key(kZero, bits, &key) == 0;
616 })) {
617 fprintf(stderr, "AES_set_encrypt_key failed.\n");
618 return false;
619 }
620 results.Print(name + " encrypt setup");
621 }
622
623 {
624 AES_KEY key;
625 if (AES_set_encrypt_key(kZero, bits, &key) != 0) {
626 return false;
627 }
628 uint8_t block[16] = {0};
629 TimeResults results;
630 if (!TimeFunctionParallel(&results, [&]() -> bool {
631 AES_encrypt(block, block, &key);
632 return true;
633 })) {
634 fprintf(stderr, "AES_encrypt failed.\n");
635 return false;
636 }
637 results.Print(name + " encrypt");
638 }
639
640 {
641 TimeResults results;
642 if (!TimeFunctionParallel(&results, [&]() -> bool {
643 AES_KEY key;
644 return AES_set_decrypt_key(kZero, bits, &key) == 0;
645 })) {
646 fprintf(stderr, "AES_set_decrypt_key failed.\n");
647 return false;
648 }
649 results.Print(name + " decrypt setup");
650 }
651
652 {
653 AES_KEY key;
654 if (AES_set_decrypt_key(kZero, bits, &key) != 0) {
655 return false;
656 }
657 uint8_t block[16] = {0};
658 TimeResults results;
659 if (!TimeFunctionParallel(&results, [&]() -> bool {
660 AES_decrypt(block, block, &key);
661 return true;
662 })) {
663 fprintf(stderr, "AES_decrypt failed.\n");
664 return false;
665 }
666 results.Print(name + " decrypt");
667 }
668
669 return true;
670 }
671
SpeedHashChunk(const EVP_MD * md,std::string name,size_t chunk_len)672 static bool SpeedHashChunk(const EVP_MD *md, std::string name,
673 size_t chunk_len) {
674 uint8_t input[16384] = {0};
675
676 if (chunk_len > sizeof(input)) {
677 return false;
678 }
679
680 name += ChunkLenSuffix(chunk_len);
681 TimeResults results;
682 if (!TimeFunctionParallel(&results, [md, chunk_len, &input]() -> bool {
683 uint8_t digest[EVP_MAX_MD_SIZE];
684 unsigned int md_len;
685
686 bssl::ScopedEVP_MD_CTX ctx;
687 return EVP_DigestInit_ex(ctx.get(), md, NULL /* ENGINE */) &&
688 EVP_DigestUpdate(ctx.get(), input, chunk_len) &&
689 EVP_DigestFinal_ex(ctx.get(), digest, &md_len);
690 })) {
691 fprintf(stderr, "EVP_DigestInit_ex failed.\n");
692 ERR_print_errors_fp(stderr);
693 return false;
694 }
695
696 results.PrintWithBytes(name, chunk_len);
697 return true;
698 }
699
SpeedHash(const EVP_MD * md,const std::string & name,const std::string & selected)700 static bool SpeedHash(const EVP_MD *md, const std::string &name,
701 const std::string &selected) {
702 if (!selected.empty() && name.find(selected) == std::string::npos) {
703 return true;
704 }
705
706 for (size_t chunk_len : g_chunk_lengths) {
707 if (!SpeedHashChunk(md, name, chunk_len)) {
708 return false;
709 }
710 }
711
712 return true;
713 }
714
SpeedRandomChunk(std::string name,size_t chunk_len)715 static bool SpeedRandomChunk(std::string name, size_t chunk_len) {
716 static constexpr size_t kMaxChunk = 16384;
717 if (chunk_len > kMaxChunk) {
718 return false;
719 }
720
721 name += ChunkLenSuffix(chunk_len);
722 TimeResults results;
723 if (!TimeFunctionParallel(&results, [chunk_len]() -> bool {
724 uint8_t scratch[kMaxChunk];
725 RAND_bytes(scratch, chunk_len);
726 return true;
727 })) {
728 return false;
729 }
730
731 results.PrintWithBytes(name, chunk_len);
732 return true;
733 }
734
SpeedRandom(const std::string & selected)735 static bool SpeedRandom(const std::string &selected) {
736 if (!selected.empty() && selected != "RNG") {
737 return true;
738 }
739
740 for (size_t chunk_len : g_chunk_lengths) {
741 if (!SpeedRandomChunk("RNG", chunk_len)) {
742 return false;
743 }
744 }
745
746 return true;
747 }
748
SpeedECDHCurve(const std::string & name,const EC_GROUP * group,const std::string & selected)749 static bool SpeedECDHCurve(const std::string &name, const EC_GROUP *group,
750 const std::string &selected) {
751 if (!selected.empty() && name.find(selected) == std::string::npos) {
752 return true;
753 }
754
755 bssl::UniquePtr<EC_KEY> peer_key(EC_KEY_new());
756 if (!peer_key ||
757 !EC_KEY_set_group(peer_key.get(), group) ||
758 !EC_KEY_generate_key(peer_key.get())) {
759 return false;
760 }
761
762 size_t peer_value_len = EC_POINT_point2oct(
763 EC_KEY_get0_group(peer_key.get()), EC_KEY_get0_public_key(peer_key.get()),
764 POINT_CONVERSION_UNCOMPRESSED, nullptr, 0, nullptr);
765 if (peer_value_len == 0) {
766 return false;
767 }
768 auto peer_value = std::make_unique<uint8_t[]>(peer_value_len);
769 peer_value_len = EC_POINT_point2oct(
770 EC_KEY_get0_group(peer_key.get()), EC_KEY_get0_public_key(peer_key.get()),
771 POINT_CONVERSION_UNCOMPRESSED, peer_value.get(), peer_value_len, nullptr);
772 if (peer_value_len == 0) {
773 return false;
774 }
775
776 TimeResults results;
777 if (!TimeFunctionParallel(
778 &results, [group, peer_value_len, &peer_value]() -> bool {
779 bssl::UniquePtr<EC_KEY> key(EC_KEY_new());
780 if (!key || !EC_KEY_set_group(key.get(), group) ||
781 !EC_KEY_generate_key(key.get())) {
782 return false;
783 }
784 bssl::UniquePtr<EC_POINT> point(EC_POINT_new(group));
785 bssl::UniquePtr<EC_POINT> peer_point(EC_POINT_new(group));
786 bssl::UniquePtr<BN_CTX> ctx(BN_CTX_new());
787 bssl::UniquePtr<BIGNUM> x(BN_new());
788 if (!point || !peer_point || !ctx || !x ||
789 !EC_POINT_oct2point(group, peer_point.get(), peer_value.get(),
790 peer_value_len, ctx.get()) ||
791 !EC_POINT_mul(group, point.get(), nullptr, peer_point.get(),
792 EC_KEY_get0_private_key(key.get()), ctx.get()) ||
793 !EC_POINT_get_affine_coordinates_GFp(
794 group, point.get(), x.get(), nullptr, ctx.get())) {
795 return false;
796 }
797
798 return true;
799 })) {
800 return false;
801 }
802
803 results.Print(name);
804 return true;
805 }
806
SpeedECDSACurve(const std::string & name,const EC_GROUP * group,const std::string & selected)807 static bool SpeedECDSACurve(const std::string &name, const EC_GROUP *group,
808 const std::string &selected) {
809 if (!selected.empty() && name.find(selected) == std::string::npos) {
810 return true;
811 }
812
813 bssl::UniquePtr<EC_KEY> key(EC_KEY_new());
814 if (!key ||
815 !EC_KEY_set_group(key.get(), group) ||
816 !EC_KEY_generate_key(key.get())) {
817 return false;
818 }
819
820 static constexpr size_t kMaxSignature = 256;
821 if (ECDSA_size(key.get()) > kMaxSignature) {
822 abort();
823 }
824 uint8_t digest[20];
825 OPENSSL_memset(digest, 42, sizeof(digest));
826
827 TimeResults results;
828 if (!TimeFunctionParallel(&results, [&key, &digest]() -> bool {
829 uint8_t out[kMaxSignature];
830 unsigned out_len;
831 return ECDSA_sign(0, digest, sizeof(digest), out, &out_len,
832 key.get()) == 1;
833 })) {
834 return false;
835 }
836
837 results.Print(name + " signing");
838
839 uint8_t signature[kMaxSignature];
840 unsigned sig_len;
841 if (!ECDSA_sign(0, digest, sizeof(digest), signature, &sig_len, key.get())) {
842 return false;
843 }
844
845 if (!TimeFunctionParallel(
846 &results, [&key, &signature, &digest, sig_len]() -> bool {
847 return ECDSA_verify(0, digest, sizeof(digest), signature, sig_len,
848 key.get()) == 1;
849 })) {
850 return false;
851 }
852
853 results.Print(name + " verify");
854
855 return true;
856 }
857
SpeedECDH(const std::string & selected)858 static bool SpeedECDH(const std::string &selected) {
859 return SpeedECDHCurve("ECDH P-224", EC_group_p224(), selected) &&
860 SpeedECDHCurve("ECDH P-256", EC_group_p256(), selected) &&
861 SpeedECDHCurve("ECDH P-384", EC_group_p384(), selected) &&
862 SpeedECDHCurve("ECDH P-521", EC_group_p521(), selected);
863 }
864
SpeedECDSA(const std::string & selected)865 static bool SpeedECDSA(const std::string &selected) {
866 return SpeedECDSACurve("ECDSA P-224", EC_group_p224(), selected) &&
867 SpeedECDSACurve("ECDSA P-256", EC_group_p256(), selected) &&
868 SpeedECDSACurve("ECDSA P-384", EC_group_p384(), selected) &&
869 SpeedECDSACurve("ECDSA P-521", EC_group_p521(), selected);
870 }
871
Speed25519(const std::string & selected)872 static bool Speed25519(const std::string &selected) {
873 if (!selected.empty() && selected.find("25519") == std::string::npos) {
874 return true;
875 }
876
877 TimeResults results;
878 if (!TimeFunctionParallel(&results, []() -> bool {
879 uint8_t public_key[32], private_key[64];
880 ED25519_keypair(public_key, private_key);
881 return true;
882 })) {
883 return false;
884 }
885
886 results.Print("Ed25519 key generation");
887
888 uint8_t public_key[32], private_key[64];
889 ED25519_keypair(public_key, private_key);
890 static const uint8_t kMessage[] = {0, 1, 2, 3, 4, 5};
891
892 if (!TimeFunctionParallel(&results, [&private_key]() -> bool {
893 uint8_t out[64];
894 return ED25519_sign(out, kMessage, sizeof(kMessage), private_key) == 1;
895 })) {
896 return false;
897 }
898
899 results.Print("Ed25519 signing");
900
901 uint8_t signature[64];
902 if (!ED25519_sign(signature, kMessage, sizeof(kMessage), private_key)) {
903 return false;
904 }
905
906 if (!TimeFunctionParallel(&results, [&public_key, &signature]() -> bool {
907 return ED25519_verify(kMessage, sizeof(kMessage), signature,
908 public_key) == 1;
909 })) {
910 fprintf(stderr, "Ed25519 verify failed.\n");
911 return false;
912 }
913
914 results.Print("Ed25519 verify");
915
916 if (!TimeFunctionParallel(&results, []() -> bool {
917 uint8_t out[32], in[32];
918 OPENSSL_memset(in, 0, sizeof(in));
919 X25519_public_from_private(out, in);
920 return true;
921 })) {
922 fprintf(stderr, "Curve25519 base-point multiplication failed.\n");
923 return false;
924 }
925
926 results.Print("Curve25519 base-point multiplication");
927
928 if (!TimeFunctionParallel(&results, []() -> bool {
929 uint8_t out[32], in1[32], in2[32];
930 OPENSSL_memset(in1, 0, sizeof(in1));
931 OPENSSL_memset(in2, 0, sizeof(in2));
932 in1[0] = 1;
933 in2[0] = 9;
934 return X25519(out, in1, in2) == 1;
935 })) {
936 fprintf(stderr, "Curve25519 arbitrary point multiplication failed.\n");
937 return false;
938 }
939
940 results.Print("Curve25519 arbitrary point multiplication");
941
942 return true;
943 }
944
SpeedSPAKE2(const std::string & selected)945 static bool SpeedSPAKE2(const std::string &selected) {
946 if (!selected.empty() && selected.find("SPAKE2") == std::string::npos) {
947 return true;
948 }
949
950 TimeResults results;
951
952 static const uint8_t kAliceName[] = {'A'};
953 static const uint8_t kBobName[] = {'B'};
954 static const uint8_t kPassword[] = "password";
955 bssl::UniquePtr<SPAKE2_CTX> alice(
956 SPAKE2_CTX_new(spake2_role_alice, kAliceName, sizeof(kAliceName),
957 kBobName, sizeof(kBobName)));
958 uint8_t alice_msg[SPAKE2_MAX_MSG_SIZE];
959 size_t alice_msg_len;
960
961 if (!SPAKE2_generate_msg(alice.get(), alice_msg, &alice_msg_len,
962 sizeof(alice_msg), kPassword, sizeof(kPassword))) {
963 fprintf(stderr, "SPAKE2_generate_msg failed.\n");
964 return false;
965 }
966
967 if (!TimeFunctionParallel(&results, [&alice_msg, alice_msg_len]() -> bool {
968 bssl::UniquePtr<SPAKE2_CTX> bob(
969 SPAKE2_CTX_new(spake2_role_bob, kBobName, sizeof(kBobName),
970 kAliceName, sizeof(kAliceName)));
971 uint8_t bob_msg[SPAKE2_MAX_MSG_SIZE], bob_key[64];
972 size_t bob_msg_len, bob_key_len;
973 if (!SPAKE2_generate_msg(bob.get(), bob_msg, &bob_msg_len,
974 sizeof(bob_msg), kPassword,
975 sizeof(kPassword)) ||
976 !SPAKE2_process_msg(bob.get(), bob_key, &bob_key_len,
977 sizeof(bob_key), alice_msg, alice_msg_len)) {
978 return false;
979 }
980
981 return true;
982 })) {
983 fprintf(stderr, "SPAKE2 failed.\n");
984 }
985
986 results.Print("SPAKE2 over Ed25519");
987
988 return true;
989 }
990
SpeedScrypt(const std::string & selected)991 static bool SpeedScrypt(const std::string &selected) {
992 if (!selected.empty() && selected.find("scrypt") == std::string::npos) {
993 return true;
994 }
995
996 TimeResults results;
997
998 static const char kPassword[] = "password";
999 static const uint8_t kSalt[] = "NaCl";
1000
1001 if (!TimeFunctionParallel(&results, [&]() -> bool {
1002 uint8_t out[64];
1003 return !!EVP_PBE_scrypt(kPassword, sizeof(kPassword) - 1, kSalt,
1004 sizeof(kSalt) - 1, 1024, 8, 16, 0 /* max_mem */,
1005 out, sizeof(out));
1006 })) {
1007 fprintf(stderr, "scrypt failed.\n");
1008 return false;
1009 }
1010 results.Print("scrypt (N = 1024, r = 8, p = 16)");
1011
1012 if (!TimeFunctionParallel(&results, [&]() -> bool {
1013 uint8_t out[64];
1014 return !!EVP_PBE_scrypt(kPassword, sizeof(kPassword) - 1, kSalt,
1015 sizeof(kSalt) - 1, 16384, 8, 1, 0 /* max_mem */,
1016 out, sizeof(out));
1017 })) {
1018 fprintf(stderr, "scrypt failed.\n");
1019 return false;
1020 }
1021 results.Print("scrypt (N = 16384, r = 8, p = 1)");
1022
1023 return true;
1024 }
1025
SpeedHRSS(const std::string & selected)1026 static bool SpeedHRSS(const std::string &selected) {
1027 if (!selected.empty() && selected != "HRSS") {
1028 return true;
1029 }
1030
1031 TimeResults results;
1032
1033 if (!TimeFunctionParallel(&results, []() -> bool {
1034 struct HRSS_public_key pub;
1035 struct HRSS_private_key priv;
1036 uint8_t entropy[HRSS_GENERATE_KEY_BYTES];
1037 RAND_bytes(entropy, sizeof(entropy));
1038 return HRSS_generate_key(&pub, &priv, entropy);
1039 })) {
1040 fprintf(stderr, "Failed to time HRSS_generate_key.\n");
1041 return false;
1042 }
1043
1044 results.Print("HRSS generate");
1045
1046 struct HRSS_public_key pub;
1047 struct HRSS_private_key priv;
1048 uint8_t key_entropy[HRSS_GENERATE_KEY_BYTES];
1049 RAND_bytes(key_entropy, sizeof(key_entropy));
1050 if (!HRSS_generate_key(&pub, &priv, key_entropy)) {
1051 return false;
1052 }
1053
1054 if (!TimeFunctionParallel(&results, [&pub]() -> bool {
1055 uint8_t entropy[HRSS_ENCAP_BYTES];
1056 uint8_t shared_key[HRSS_KEY_BYTES];
1057 uint8_t ciphertext[HRSS_CIPHERTEXT_BYTES];
1058 RAND_bytes(entropy, sizeof(entropy));
1059 return HRSS_encap(ciphertext, shared_key, &pub, entropy);
1060 })) {
1061 fprintf(stderr, "Failed to time HRSS_encap.\n");
1062 return false;
1063 }
1064 results.Print("HRSS encap");
1065
1066 uint8_t entropy[HRSS_ENCAP_BYTES];
1067 uint8_t shared_key[HRSS_KEY_BYTES];
1068 uint8_t ciphertext[HRSS_CIPHERTEXT_BYTES];
1069 RAND_bytes(entropy, sizeof(entropy));
1070 if (!HRSS_encap(ciphertext, shared_key, &pub, entropy)) {
1071 return false;
1072 }
1073
1074 if (!TimeFunctionParallel(&results, [&priv, &ciphertext]() -> bool {
1075 uint8_t shared_key2[HRSS_KEY_BYTES];
1076 return HRSS_decap(shared_key2, &priv, ciphertext, sizeof(ciphertext));
1077 })) {
1078 fprintf(stderr, "Failed to time HRSS_encap.\n");
1079 return false;
1080 }
1081
1082 results.Print("HRSS decap");
1083
1084 return true;
1085 }
1086
SpeedKyber(const std::string & selected)1087 static bool SpeedKyber(const std::string &selected) {
1088 if (!selected.empty() && selected != "Kyber") {
1089 return true;
1090 }
1091
1092 TimeResults results;
1093
1094 uint8_t ciphertext[KYBER_CIPHERTEXT_BYTES];
1095 // This ciphertext is nonsense, but Kyber decap is constant-time so, for the
1096 // purposes of timing, it's fine.
1097 memset(ciphertext, 42, sizeof(ciphertext));
1098 if (!TimeFunctionParallel(&results, [&]() -> bool {
1099 KYBER_private_key priv;
1100 uint8_t encoded_public_key[KYBER_PUBLIC_KEY_BYTES];
1101 KYBER_generate_key(encoded_public_key, &priv);
1102 uint8_t shared_secret[KYBER_SHARED_SECRET_BYTES];
1103 KYBER_decap(shared_secret, ciphertext, &priv);
1104 return true;
1105 })) {
1106 fprintf(stderr, "Failed to time KYBER_generate_key + KYBER_decap.\n");
1107 return false;
1108 }
1109
1110 results.Print("Kyber generate + decap");
1111
1112 KYBER_private_key priv;
1113 uint8_t encoded_public_key[KYBER_PUBLIC_KEY_BYTES];
1114 KYBER_generate_key(encoded_public_key, &priv);
1115 KYBER_public_key pub;
1116 if (!TimeFunctionParallel(&results, [&]() -> bool {
1117 CBS encoded_public_key_cbs;
1118 CBS_init(&encoded_public_key_cbs, encoded_public_key,
1119 sizeof(encoded_public_key));
1120 if (!KYBER_parse_public_key(&pub, &encoded_public_key_cbs)) {
1121 return false;
1122 }
1123 uint8_t shared_secret[KYBER_SHARED_SECRET_BYTES];
1124 KYBER_encap(ciphertext, shared_secret, &pub);
1125 return true;
1126 })) {
1127 fprintf(stderr, "Failed to time KYBER_encap.\n");
1128 return false;
1129 }
1130
1131 results.Print("Kyber parse + encap");
1132
1133 return true;
1134 }
1135
SpeedDilithium(const std::string & selected)1136 static bool SpeedDilithium(const std::string &selected) {
1137 if (!selected.empty() && selected != "Dilithium") {
1138 return true;
1139 }
1140
1141 TimeResults results;
1142
1143 auto encoded_public_key =
1144 std::make_unique<uint8_t[]>(DILITHIUM_PUBLIC_KEY_BYTES);
1145 auto priv = std::make_unique<DILITHIUM_private_key>();
1146 if (!TimeFunctionParallel(&results, [&]() -> bool {
1147 if (!DILITHIUM_generate_key(encoded_public_key.get(), priv.get())) {
1148 fprintf(stderr, "Failure in DILITHIUM_generate_key.\n");
1149 return false;
1150 }
1151 return true;
1152 })) {
1153 fprintf(stderr, "Failed to time DILITHIUM_generate_key.\n");
1154 return false;
1155 }
1156
1157 results.Print("Dilithium key generation");
1158
1159 auto encoded_private_key =
1160 std::make_unique<uint8_t[]>(DILITHIUM_PRIVATE_KEY_BYTES);
1161 CBB cbb;
1162 CBB_init_fixed(&cbb, encoded_private_key.get(), DILITHIUM_PRIVATE_KEY_BYTES);
1163 DILITHIUM_marshal_private_key(&cbb, priv.get());
1164
1165 if (!TimeFunctionParallel(&results, [&]() -> bool {
1166 CBS cbs;
1167 CBS_init(&cbs, encoded_private_key.get(), DILITHIUM_PRIVATE_KEY_BYTES);
1168 if (!DILITHIUM_parse_private_key(priv.get(), &cbs)) {
1169 fprintf(stderr, "Failure in DILITHIUM_parse_private_key.\n");
1170 return false;
1171 }
1172 return true;
1173 })) {
1174 fprintf(stderr, "Failed to time DILITHIUM_parse_private_key.\n");
1175 return false;
1176 }
1177
1178 results.Print("Dilithium parse (valid) private key");
1179
1180 const char *message = "Hello world";
1181 size_t message_len = strlen(message);
1182 auto out_encoded_signature =
1183 std::make_unique<uint8_t[]>(DILITHIUM_SIGNATURE_BYTES);
1184 if (!TimeFunctionParallel(&results, [&]() -> bool {
1185 if (!DILITHIUM_sign(out_encoded_signature.get(), priv.get(),
1186 (const uint8_t *)message, message_len)) {
1187 fprintf(stderr, "Failure in DILITHIUM_sign.\n");
1188 return false;
1189 }
1190 return true;
1191 })) {
1192 fprintf(stderr, "Failed to time DILITHIUM_sign.\n");
1193 return false;
1194 }
1195
1196 results.Print("Dilithium sign (randomized)");
1197
1198 auto pub = std::make_unique<DILITHIUM_public_key>();
1199
1200 if (!TimeFunctionParallel(&results, [&]() -> bool {
1201 CBS cbs;
1202 CBS_init(&cbs, encoded_public_key.get(), DILITHIUM_PUBLIC_KEY_BYTES);
1203 if (!DILITHIUM_parse_public_key(pub.get(), &cbs)) {
1204 fprintf(stderr, "Failure in DILITHIUM_parse_public_key.\n");
1205 return false;
1206 }
1207 return true;
1208 })) {
1209 fprintf(stderr, "Failed to time DILITHIUM_parse_public_key.\n");
1210 return false;
1211 }
1212
1213 results.Print("Dilithium parse (valid) public key");
1214
1215 if (!TimeFunctionParallel(&results, [&]() -> bool {
1216 if (!DILITHIUM_verify(pub.get(), out_encoded_signature.get(),
1217 (const uint8_t *)message, message_len)) {
1218 fprintf(stderr, "Failed to verify Dilithium signature.\n");
1219 return false;
1220 }
1221 return true;
1222 })) {
1223 fprintf(stderr, "Failed to time DILITHIUM_verify.\n");
1224 return false;
1225 }
1226
1227 results.Print("Dilithium verify (valid signature)");
1228
1229 out_encoded_signature[42] ^= 0x42;
1230 if (!TimeFunctionParallel(&results, [&]() -> bool {
1231 if (DILITHIUM_verify(pub.get(), out_encoded_signature.get(),
1232 (const uint8_t *)message, message_len)) {
1233 fprintf(stderr, "Dilithium signature unexpectedly verified.\n");
1234 return false;
1235 }
1236 return true;
1237 })) {
1238 fprintf(stderr, "Failed to time DILITHIUM_verify.\n");
1239 return false;
1240 }
1241
1242 results.Print("Dilithium verify (invalid signature)");
1243
1244 return true;
1245 }
1246
SpeedSpx(const std::string & selected)1247 static bool SpeedSpx(const std::string &selected) {
1248 if (!selected.empty() && selected.find("spx") == std::string::npos) {
1249 return true;
1250 }
1251
1252 TimeResults results;
1253 if (!TimeFunctionParallel(&results, []() -> bool {
1254 uint8_t public_key[32], private_key[64];
1255 SPX_generate_key(public_key, private_key);
1256 return true;
1257 })) {
1258 return false;
1259 }
1260
1261 results.Print("SPHINCS+-SHA2-128s key generation");
1262
1263 uint8_t public_key[32], private_key[64];
1264 SPX_generate_key(public_key, private_key);
1265 static const uint8_t kMessage[] = {0, 1, 2, 3, 4, 5};
1266
1267 if (!TimeFunctionParallel(&results, [&private_key]() -> bool {
1268 uint8_t out[SPX_SIGNATURE_BYTES];
1269 SPX_sign(out, private_key, kMessage, sizeof(kMessage), true);
1270 return true;
1271 })) {
1272 return false;
1273 }
1274
1275 results.Print("SPHINCS+-SHA2-128s signing");
1276
1277 uint8_t signature[SPX_SIGNATURE_BYTES];
1278 SPX_sign(signature, private_key, kMessage, sizeof(kMessage), true);
1279
1280 if (!TimeFunctionParallel(&results, [&public_key, &signature]() -> bool {
1281 return SPX_verify(signature, public_key, kMessage, sizeof(kMessage)) ==
1282 1;
1283 })) {
1284 fprintf(stderr, "SPHINCS+-SHA2-128s verify failed.\n");
1285 return false;
1286 }
1287
1288 results.Print("SPHINCS+-SHA2-128s verify");
1289
1290 return true;
1291 }
1292
SpeedHashToCurve(const std::string & selected)1293 static bool SpeedHashToCurve(const std::string &selected) {
1294 if (!selected.empty() && selected.find("hashtocurve") == std::string::npos) {
1295 return true;
1296 }
1297
1298 uint8_t input[64];
1299 RAND_bytes(input, sizeof(input));
1300
1301 static const uint8_t kLabel[] = "label";
1302
1303 TimeResults results;
1304 {
1305 if (!TimeFunctionParallel(&results, [&]() -> bool {
1306 EC_JACOBIAN out;
1307 return ec_hash_to_curve_p256_xmd_sha256_sswu(EC_group_p256(), &out,
1308 kLabel, sizeof(kLabel),
1309 input, sizeof(input));
1310 })) {
1311 fprintf(stderr, "hash-to-curve failed.\n");
1312 return false;
1313 }
1314 results.Print("hash-to-curve P256_XMD:SHA-256_SSWU_RO_");
1315
1316 if (!TimeFunctionParallel(&results, [&]() -> bool {
1317 EC_JACOBIAN out;
1318 return ec_hash_to_curve_p384_xmd_sha384_sswu(EC_group_p384(), &out,
1319 kLabel, sizeof(kLabel),
1320 input, sizeof(input));
1321 })) {
1322 fprintf(stderr, "hash-to-curve failed.\n");
1323 return false;
1324 }
1325 results.Print("hash-to-curve P384_XMD:SHA-384_SSWU_RO_");
1326
1327 if (!TimeFunctionParallel(&results, [&]() -> bool {
1328 EC_SCALAR out;
1329 return ec_hash_to_scalar_p384_xmd_sha512_draft07(
1330 EC_group_p384(), &out, kLabel, sizeof(kLabel), input,
1331 sizeof(input));
1332 })) {
1333 fprintf(stderr, "hash-to-scalar failed.\n");
1334 return false;
1335 }
1336 results.Print("hash-to-scalar P384_XMD:SHA-512");
1337 }
1338
1339 return true;
1340 }
1341
SpeedBase64(const std::string & selected)1342 static bool SpeedBase64(const std::string &selected) {
1343 if (!selected.empty() && selected.find("base64") == std::string::npos) {
1344 return true;
1345 }
1346
1347 static const char kInput[] =
1348 "MIIDtTCCAp2gAwIBAgIJALW2IrlaBKUhMA0GCSqGSIb3DQEBCwUAMEUxCzAJBgNV"
1349 "BAYTAkFVMRMwEQYDVQQIEwpTb21lLVN0YXRlMSEwHwYDVQQKExhJbnRlcm5ldCBX"
1350 "aWRnaXRzIFB0eSBMdGQwHhcNMTYwNzA5MDQzODA5WhcNMTYwODA4MDQzODA5WjBF"
1351 "MQswCQYDVQQGEwJBVTETMBEGA1UECBMKU29tZS1TdGF0ZTEhMB8GA1UEChMYSW50"
1352 "ZXJuZXQgV2lkZ2l0cyBQdHkgTHRkMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIB"
1353 "CgKCAQEAugvahBkSAUF1fC49vb1bvlPrcl80kop1iLpiuYoz4Qptwy57+EWssZBc"
1354 "HprZ5BkWf6PeGZ7F5AX1PyJbGHZLqvMCvViP6pd4MFox/igESISEHEixoiXCzepB"
1355 "rhtp5UQSjHD4D4hKtgdMgVxX+LRtwgW3mnu/vBu7rzpr/DS8io99p3lqZ1Aky+aN"
1356 "lcMj6MYy8U+YFEevb/V0lRY9oqwmW7BHnXikm/vi6sjIS350U8zb/mRzYeIs2R65"
1357 "LUduTL50+UMgat9ocewI2dv8aO9Dph+8NdGtg8LFYyTTHcUxJoMr1PTOgnmET19W"
1358 "JH4PrFwk7ZE1QJQQ1L4iKmPeQistuQIDAQABo4GnMIGkMB0GA1UdDgQWBBT5m6Vv"
1359 "zYjVYHG30iBE+j2XDhUE8jB1BgNVHSMEbjBsgBT5m6VvzYjVYHG30iBE+j2XDhUE"
1360 "8qFJpEcwRTELMAkGA1UEBhMCQVUxEzARBgNVBAgTClNvbWUtU3RhdGUxITAfBgNV"
1361 "BAoTGEludGVybmV0IFdpZGdpdHMgUHR5IEx0ZIIJALW2IrlaBKUhMAwGA1UdEwQF"
1362 "MAMBAf8wDQYJKoZIhvcNAQELBQADggEBAD7Jg68SArYWlcoHfZAB90Pmyrt5H6D8"
1363 "LRi+W2Ri1fBNxREELnezWJ2scjl4UMcsKYp4Pi950gVN+62IgrImcCNvtb5I1Cfy"
1364 "/MNNur9ffas6X334D0hYVIQTePyFk3umI+2mJQrtZZyMPIKSY/sYGQHhGGX6wGK+"
1365 "GO/og0PQk/Vu6D+GU2XRnDV0YZg1lsAsHd21XryK6fDmNkEMwbIWrts4xc7scRrG"
1366 "HWy+iMf6/7p/Ak/SIicM4XSwmlQ8pPxAZPr+E2LoVd9pMpWUwpW2UbtO5wsGTrY5"
1367 "sO45tFNN/y+jtUheB1C2ijObG/tXELaiyCdM+S/waeuv0MXtI4xnn1A=";
1368
1369 TimeResults results;
1370 if (!TimeFunctionParallel(&results, [&]() -> bool {
1371 uint8_t out[sizeof(kInput)];
1372 size_t len;
1373 return EVP_DecodeBase64(out, &len, sizeof(out),
1374 reinterpret_cast<const uint8_t *>(kInput),
1375 strlen(kInput));
1376 })) {
1377 fprintf(stderr, "base64 decode failed.\n");
1378 return false;
1379 }
1380 results.PrintWithBytes("base64 decode", strlen(kInput));
1381 return true;
1382 }
1383
SpeedSipHash(const std::string & selected)1384 static bool SpeedSipHash(const std::string &selected) {
1385 if (!selected.empty() && selected.find("siphash") == std::string::npos) {
1386 return true;
1387 }
1388
1389 uint64_t key[2] = {0};
1390 for (size_t len : g_chunk_lengths) {
1391 std::vector<uint8_t> input(len);
1392 TimeResults results;
1393 if (!TimeFunctionParallel(&results, [&]() -> bool {
1394 SIPHASH_24(key, input.data(), input.size());
1395 return true;
1396 })) {
1397 fprintf(stderr, "SIPHASH_24 failed.\n");
1398 ERR_print_errors_fp(stderr);
1399 return false;
1400 }
1401 results.PrintWithBytes("SipHash-2-4" + ChunkLenSuffix(len), len);
1402 }
1403
1404 return true;
1405 }
1406
trust_token_pretoken_dup(const TRUST_TOKEN_PRETOKEN * in)1407 static TRUST_TOKEN_PRETOKEN *trust_token_pretoken_dup(
1408 const TRUST_TOKEN_PRETOKEN *in) {
1409 return static_cast<TRUST_TOKEN_PRETOKEN *>(
1410 OPENSSL_memdup(in, sizeof(TRUST_TOKEN_PRETOKEN)));
1411 }
1412
SpeedTrustToken(std::string name,const TRUST_TOKEN_METHOD * method,size_t batchsize,const std::string & selected)1413 static bool SpeedTrustToken(std::string name, const TRUST_TOKEN_METHOD *method,
1414 size_t batchsize, const std::string &selected) {
1415 if (!selected.empty() && selected.find("trusttoken") == std::string::npos) {
1416 return true;
1417 }
1418
1419 TimeResults results;
1420 if (!TimeFunction(&results, [&]() -> bool {
1421 uint8_t priv_key[TRUST_TOKEN_MAX_PRIVATE_KEY_SIZE];
1422 uint8_t pub_key[TRUST_TOKEN_MAX_PUBLIC_KEY_SIZE];
1423 size_t priv_key_len, pub_key_len;
1424 return TRUST_TOKEN_generate_key(
1425 method, priv_key, &priv_key_len, TRUST_TOKEN_MAX_PRIVATE_KEY_SIZE,
1426 pub_key, &pub_key_len, TRUST_TOKEN_MAX_PUBLIC_KEY_SIZE, 0);
1427 })) {
1428 fprintf(stderr, "TRUST_TOKEN_generate_key failed.\n");
1429 return false;
1430 }
1431 results.Print(name + " generate_key");
1432
1433 bssl::UniquePtr<TRUST_TOKEN_CLIENT> client(
1434 TRUST_TOKEN_CLIENT_new(method, batchsize));
1435 bssl::UniquePtr<TRUST_TOKEN_ISSUER> issuer(
1436 TRUST_TOKEN_ISSUER_new(method, batchsize));
1437 uint8_t priv_key[TRUST_TOKEN_MAX_PRIVATE_KEY_SIZE];
1438 uint8_t pub_key[TRUST_TOKEN_MAX_PUBLIC_KEY_SIZE];
1439 size_t priv_key_len, pub_key_len, key_index;
1440 if (!client || !issuer ||
1441 !TRUST_TOKEN_generate_key(
1442 method, priv_key, &priv_key_len, TRUST_TOKEN_MAX_PRIVATE_KEY_SIZE,
1443 pub_key, &pub_key_len, TRUST_TOKEN_MAX_PUBLIC_KEY_SIZE, 0) ||
1444 !TRUST_TOKEN_CLIENT_add_key(client.get(), &key_index, pub_key,
1445 pub_key_len) ||
1446 !TRUST_TOKEN_ISSUER_add_key(issuer.get(), priv_key, priv_key_len)) {
1447 fprintf(stderr, "failed to generate trust token key.\n");
1448 return false;
1449 }
1450
1451 uint8_t public_key[32], private_key[64];
1452 ED25519_keypair(public_key, private_key);
1453 bssl::UniquePtr<EVP_PKEY> priv(
1454 EVP_PKEY_new_raw_private_key(EVP_PKEY_ED25519, nullptr, private_key, 32));
1455 bssl::UniquePtr<EVP_PKEY> pub(
1456 EVP_PKEY_new_raw_public_key(EVP_PKEY_ED25519, nullptr, public_key, 32));
1457 if (!priv || !pub) {
1458 fprintf(stderr, "failed to generate trust token SRR key.\n");
1459 return false;
1460 }
1461
1462 TRUST_TOKEN_CLIENT_set_srr_key(client.get(), pub.get());
1463 TRUST_TOKEN_ISSUER_set_srr_key(issuer.get(), priv.get());
1464 uint8_t metadata_key[32];
1465 RAND_bytes(metadata_key, sizeof(metadata_key));
1466 if (!TRUST_TOKEN_ISSUER_set_metadata_key(issuer.get(), metadata_key,
1467 sizeof(metadata_key))) {
1468 fprintf(stderr, "failed to generate trust token metadata key.\n");
1469 return false;
1470 }
1471
1472 if (!TimeFunction(&results, [&]() -> bool {
1473 uint8_t *issue_msg = NULL;
1474 size_t msg_len;
1475 int ok = TRUST_TOKEN_CLIENT_begin_issuance(client.get(), &issue_msg,
1476 &msg_len, batchsize);
1477 OPENSSL_free(issue_msg);
1478 // Clear pretokens.
1479 sk_TRUST_TOKEN_PRETOKEN_pop_free(client->pretokens,
1480 TRUST_TOKEN_PRETOKEN_free);
1481 client->pretokens = sk_TRUST_TOKEN_PRETOKEN_new_null();
1482 return ok;
1483 })) {
1484 fprintf(stderr, "TRUST_TOKEN_CLIENT_begin_issuance failed.\n");
1485 return false;
1486 }
1487 results.Print(name + " begin_issuance");
1488
1489 uint8_t *issue_msg = NULL;
1490 size_t msg_len;
1491 if (!TRUST_TOKEN_CLIENT_begin_issuance(client.get(), &issue_msg, &msg_len,
1492 batchsize)) {
1493 fprintf(stderr, "TRUST_TOKEN_CLIENT_begin_issuance failed.\n");
1494 return false;
1495 }
1496 bssl::UniquePtr<uint8_t> free_issue_msg(issue_msg);
1497
1498 bssl::UniquePtr<STACK_OF(TRUST_TOKEN_PRETOKEN)> pretokens(
1499 sk_TRUST_TOKEN_PRETOKEN_deep_copy(client->pretokens,
1500 trust_token_pretoken_dup,
1501 TRUST_TOKEN_PRETOKEN_free));
1502
1503 if (!TimeFunction(&results, [&]() -> bool {
1504 uint8_t *issue_resp = NULL;
1505 size_t resp_len, tokens_issued;
1506 int ok = TRUST_TOKEN_ISSUER_issue(issuer.get(), &issue_resp, &resp_len,
1507 &tokens_issued, issue_msg, msg_len,
1508 /*public_metadata=*/0,
1509 /*private_metadata=*/0,
1510 /*max_issuance=*/batchsize);
1511 OPENSSL_free(issue_resp);
1512 return ok;
1513 })) {
1514 fprintf(stderr, "TRUST_TOKEN_ISSUER_issue failed.\n");
1515 return false;
1516 }
1517 results.Print(name + " issue");
1518
1519 uint8_t *issue_resp = NULL;
1520 size_t resp_len, tokens_issued;
1521 if (!TRUST_TOKEN_ISSUER_issue(issuer.get(), &issue_resp, &resp_len,
1522 &tokens_issued, issue_msg, msg_len,
1523 /*public_metadata=*/0, /*private_metadata=*/0,
1524 /*max_issuance=*/batchsize)) {
1525 fprintf(stderr, "TRUST_TOKEN_ISSUER_issue failed.\n");
1526 return false;
1527 }
1528 bssl::UniquePtr<uint8_t> free_issue_resp(issue_resp);
1529
1530 if (!TimeFunction(&results, [&]() -> bool {
1531 size_t key_index2;
1532 bssl::UniquePtr<STACK_OF(TRUST_TOKEN)> tokens(
1533 TRUST_TOKEN_CLIENT_finish_issuance(client.get(), &key_index2,
1534 issue_resp, resp_len));
1535
1536 // Reset pretokens.
1537 client->pretokens = sk_TRUST_TOKEN_PRETOKEN_deep_copy(
1538 pretokens.get(), trust_token_pretoken_dup,
1539 TRUST_TOKEN_PRETOKEN_free);
1540 return !!tokens;
1541 })) {
1542 fprintf(stderr, "TRUST_TOKEN_CLIENT_finish_issuance failed.\n");
1543 return false;
1544 }
1545 results.Print(name + " finish_issuance");
1546
1547 bssl::UniquePtr<STACK_OF(TRUST_TOKEN)> tokens(
1548 TRUST_TOKEN_CLIENT_finish_issuance(client.get(), &key_index, issue_resp,
1549 resp_len));
1550 if (!tokens || sk_TRUST_TOKEN_num(tokens.get()) < 1) {
1551 fprintf(stderr, "TRUST_TOKEN_CLIENT_finish_issuance failed.\n");
1552 return false;
1553 }
1554
1555 const TRUST_TOKEN *token = sk_TRUST_TOKEN_value(tokens.get(), 0);
1556
1557 const uint8_t kClientData[] = "\x70TEST CLIENT DATA";
1558 uint64_t kRedemptionTime = 13374242;
1559
1560 if (!TimeFunction(&results, [&]() -> bool {
1561 uint8_t *redeem_msg = NULL;
1562 size_t redeem_msg_len;
1563 int ok = TRUST_TOKEN_CLIENT_begin_redemption(
1564 client.get(), &redeem_msg, &redeem_msg_len, token, kClientData,
1565 sizeof(kClientData) - 1, kRedemptionTime);
1566 OPENSSL_free(redeem_msg);
1567 return ok;
1568 })) {
1569 fprintf(stderr, "TRUST_TOKEN_CLIENT_begin_redemption failed.\n");
1570 return false;
1571 }
1572 results.Print(name + " begin_redemption");
1573
1574 uint8_t *redeem_msg = NULL;
1575 size_t redeem_msg_len;
1576 if (!TRUST_TOKEN_CLIENT_begin_redemption(
1577 client.get(), &redeem_msg, &redeem_msg_len, token, kClientData,
1578 sizeof(kClientData) - 1, kRedemptionTime)) {
1579 fprintf(stderr, "TRUST_TOKEN_CLIENT_begin_redemption failed.\n");
1580 return false;
1581 }
1582 bssl::UniquePtr<uint8_t> free_redeem_msg(redeem_msg);
1583
1584 if (!TimeFunction(&results, [&]() -> bool {
1585 uint32_t public_value;
1586 uint8_t private_value;
1587 TRUST_TOKEN *rtoken;
1588 uint8_t *client_data = NULL;
1589 size_t client_data_len;
1590 int ok = TRUST_TOKEN_ISSUER_redeem(
1591 issuer.get(), &public_value, &private_value, &rtoken, &client_data,
1592 &client_data_len, redeem_msg, redeem_msg_len);
1593 OPENSSL_free(client_data);
1594 TRUST_TOKEN_free(rtoken);
1595 return ok;
1596 })) {
1597 fprintf(stderr, "TRUST_TOKEN_ISSUER_redeem failed.\n");
1598 return false;
1599 }
1600 results.Print(name + " redeem");
1601
1602 uint32_t public_value;
1603 uint8_t private_value;
1604 TRUST_TOKEN *rtoken;
1605 uint8_t *client_data = NULL;
1606 size_t client_data_len;
1607 if (!TRUST_TOKEN_ISSUER_redeem(issuer.get(), &public_value, &private_value,
1608 &rtoken, &client_data, &client_data_len,
1609 redeem_msg, redeem_msg_len)) {
1610 fprintf(stderr, "TRUST_TOKEN_ISSUER_redeem failed.\n");
1611 return false;
1612 }
1613 bssl::UniquePtr<uint8_t> free_client_data(client_data);
1614 bssl::UniquePtr<TRUST_TOKEN> free_rtoken(rtoken);
1615
1616 return true;
1617 }
1618
1619 #if defined(BORINGSSL_FIPS)
SpeedSelfTest(const std::string & selected)1620 static bool SpeedSelfTest(const std::string &selected) {
1621 if (!selected.empty() && selected.find("self-test") == std::string::npos) {
1622 return true;
1623 }
1624
1625 TimeResults results;
1626 if (!TimeFunction(&results, []() -> bool { return BORINGSSL_self_test(); })) {
1627 fprintf(stderr, "BORINGSSL_self_test faileid.\n");
1628 ERR_print_errors_fp(stderr);
1629 return false;
1630 }
1631
1632 results.Print("self-test");
1633 return true;
1634 }
1635 #endif
1636
1637 static const struct argument kArguments[] = {
1638 {
1639 "-filter",
1640 kOptionalArgument,
1641 "A filter on the speed tests to run",
1642 },
1643 {
1644 "-timeout",
1645 kOptionalArgument,
1646 "The number of seconds to run each test for (default is 1)",
1647 },
1648 {
1649 "-chunks",
1650 kOptionalArgument,
1651 "A comma-separated list of input sizes to run tests at (default is "
1652 "16,256,1350,8192,16384)",
1653 },
1654 {
1655 "-json",
1656 kBooleanArgument,
1657 "If this flag is set, speed will print the output of each benchmark in "
1658 "JSON format as follows: \"{\"description\": "
1659 "\"descriptionOfOperation\", \"numCalls\": 1234, "
1660 "\"timeInMicroseconds\": 1234567, \"bytesPerCall\": 1234}\". When "
1661 "there is no information about the bytes per call for an operation, "
1662 "the JSON field for bytesPerCall will be omitted.",
1663 },
1664 #if defined(OPENSSL_THREADS)
1665 {
1666 "-threads",
1667 kOptionalArgument,
1668 "The number of threads to benchmark in parallel (default is 1)",
1669 },
1670 #endif
1671 {
1672 "",
1673 kOptionalArgument,
1674 "",
1675 },
1676 };
1677
Speed(const std::vector<std::string> & args)1678 bool Speed(const std::vector<std::string> &args) {
1679 std::map<std::string, std::string> args_map;
1680 if (!ParseKeyValueArguments(&args_map, args, kArguments)) {
1681 PrintUsage(kArguments);
1682 return false;
1683 }
1684
1685 std::string selected;
1686 if (args_map.count("-filter") != 0) {
1687 selected = args_map["-filter"];
1688 }
1689
1690 if (args_map.count("-json") != 0) {
1691 g_print_json = true;
1692 }
1693
1694 if (args_map.count("-timeout") != 0) {
1695 g_timeout_seconds = atoi(args_map["-timeout"].c_str());
1696 }
1697
1698 #if defined(OPENSSL_THREADS)
1699 if (args_map.count("-threads") != 0) {
1700 g_threads = atoi(args_map["-threads"].c_str());
1701 }
1702 #endif
1703
1704 if (args_map.count("-chunks") != 0) {
1705 g_chunk_lengths.clear();
1706 const char *start = args_map["-chunks"].data();
1707 const char *end = start + args_map["-chunks"].size();
1708 while (start != end) {
1709 errno = 0;
1710 char *ptr;
1711 unsigned long long val = strtoull(start, &ptr, 10);
1712 if (ptr == start /* no numeric characters found */ ||
1713 errno == ERANGE /* overflow */ || static_cast<size_t>(val) != val) {
1714 fprintf(stderr, "Error parsing -chunks argument\n");
1715 return false;
1716 }
1717 g_chunk_lengths.push_back(static_cast<size_t>(val));
1718 start = ptr;
1719 if (start != end) {
1720 if (*start != ',') {
1721 fprintf(stderr, "Error parsing -chunks argument\n");
1722 return false;
1723 }
1724 start++;
1725 }
1726 }
1727 }
1728
1729 // kTLSADLen is the number of bytes of additional data that TLS passes to
1730 // AEADs.
1731 static const size_t kTLSADLen = 13;
1732 // kLegacyADLen is the number of bytes that TLS passes to the "legacy" AEADs.
1733 // These are AEADs that weren't originally defined as AEADs, but which we use
1734 // via the AEAD interface. In order for that to work, they have some TLS
1735 // knowledge in them and construct a couple of the AD bytes internally.
1736 static const size_t kLegacyADLen = kTLSADLen - 2;
1737
1738 if (g_print_json) {
1739 puts("[");
1740 }
1741 if (!SpeedRSA(selected) ||
1742 !SpeedAEAD(EVP_aead_aes_128_gcm(), "AES-128-GCM", kTLSADLen, selected) ||
1743 !SpeedAEAD(EVP_aead_aes_256_gcm(), "AES-256-GCM", kTLSADLen, selected) ||
1744 !SpeedAEAD(EVP_aead_chacha20_poly1305(), "ChaCha20-Poly1305", kTLSADLen,
1745 selected) ||
1746 !SpeedAEAD(EVP_aead_des_ede3_cbc_sha1_tls(), "DES-EDE3-CBC-SHA1",
1747 kLegacyADLen, selected) ||
1748 !SpeedAEAD(EVP_aead_aes_128_cbc_sha1_tls(), "AES-128-CBC-SHA1",
1749 kLegacyADLen, selected) ||
1750 !SpeedAEAD(EVP_aead_aes_256_cbc_sha1_tls(), "AES-256-CBC-SHA1",
1751 kLegacyADLen, selected) ||
1752 !SpeedAEADOpen(EVP_aead_aes_128_cbc_sha1_tls(), "AES-128-CBC-SHA1",
1753 kLegacyADLen, selected) ||
1754 !SpeedAEADOpen(EVP_aead_aes_256_cbc_sha1_tls(), "AES-256-CBC-SHA1",
1755 kLegacyADLen, selected) ||
1756 !SpeedAEAD(EVP_aead_aes_128_gcm_siv(), "AES-128-GCM-SIV", kTLSADLen,
1757 selected) ||
1758 !SpeedAEAD(EVP_aead_aes_256_gcm_siv(), "AES-256-GCM-SIV", kTLSADLen,
1759 selected) ||
1760 !SpeedAEADOpen(EVP_aead_aes_128_gcm_siv(), "AES-128-GCM-SIV", kTLSADLen,
1761 selected) ||
1762 !SpeedAEADOpen(EVP_aead_aes_256_gcm_siv(), "AES-256-GCM-SIV", kTLSADLen,
1763 selected) ||
1764 !SpeedAEAD(EVP_aead_aes_128_ccm_bluetooth(), "AES-128-CCM-Bluetooth",
1765 kTLSADLen, selected) ||
1766 !SpeedAESBlock("AES-128", 128, selected) ||
1767 !SpeedAESBlock("AES-256", 256, selected) ||
1768 !SpeedHash(EVP_sha1(), "SHA-1", selected) ||
1769 !SpeedHash(EVP_sha256(), "SHA-256", selected) ||
1770 !SpeedHash(EVP_sha512(), "SHA-512", selected) ||
1771 !SpeedHash(EVP_blake2b256(), "BLAKE2b-256", selected) ||
1772 !SpeedRandom(selected) || //
1773 !SpeedECDH(selected) || //
1774 !SpeedECDSA(selected) || //
1775 !Speed25519(selected) || //
1776 !SpeedSPAKE2(selected) || //
1777 !SpeedScrypt(selected) || //
1778 !SpeedRSAKeyGen(selected) || //
1779 !SpeedHRSS(selected) || //
1780 !SpeedKyber(selected) || //
1781 !SpeedDilithium(selected) || //
1782 !SpeedSpx(selected) || //
1783 !SpeedHashToCurve(selected) || //
1784 !SpeedTrustToken("TrustToken-Exp1-Batch1", TRUST_TOKEN_experiment_v1(), 1,
1785 selected) ||
1786 !SpeedTrustToken("TrustToken-Exp1-Batch10", TRUST_TOKEN_experiment_v1(),
1787 10, selected) ||
1788 !SpeedTrustToken("TrustToken-Exp2VOPRF-Batch1",
1789 TRUST_TOKEN_experiment_v2_voprf(), 1, selected) ||
1790 !SpeedTrustToken("TrustToken-Exp2VOPRF-Batch10",
1791 TRUST_TOKEN_experiment_v2_voprf(), 10, selected) ||
1792 !SpeedTrustToken("TrustToken-Exp2PMB-Batch1",
1793 TRUST_TOKEN_experiment_v2_pmb(), 1, selected) ||
1794 !SpeedTrustToken("TrustToken-Exp2PMB-Batch10",
1795 TRUST_TOKEN_experiment_v2_pmb(), 10, selected) ||
1796 !SpeedBase64(selected) || //
1797 !SpeedSipHash(selected)) {
1798 return false;
1799 }
1800 #if defined(BORINGSSL_FIPS)
1801 if (!SpeedSelfTest(selected)) {
1802 return false;
1803 }
1804 #endif
1805 if (g_print_json) {
1806 puts("\n]");
1807 }
1808
1809 return true;
1810 }
1811