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