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