blob: 3929cf63151c050140ef1d1ee8dabda94236db65 [file] [log] [blame]
Adam Langleyd9e397b2015-01-22 14:27:53 -08001/* Copyright (c) 2014, Google Inc.
2 *
3 * Permission to use, copy, modify, and/or distribute this software for any
4 * purpose with or without fee is hereby granted, provided that the above
5 * copyright notice and this permission notice appear in all copies.
6 *
7 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
8 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
9 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
10 * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
11 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
12 * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
13 * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */
14
Robert Sloan49d063b2018-04-03 11:30:38 -070015#include <algorithm>
Adam Langleyd9e397b2015-01-22 14:27:53 -080016#include <string>
17#include <functional>
18#include <memory>
19#include <vector>
20
Robert Sloan49d063b2018-04-03 11:30:38 -070021#include <assert.h>
Robert Sloan4c22c5f2019-03-01 15:53:37 -080022#include <errno.h>
Adam Langleyd9e397b2015-01-22 14:27:53 -080023#include <stdint.h>
David Benjaminf0c4a6c2016-08-11 13:26:41 -040024#include <stdlib.h>
Adam Langleyd9e397b2015-01-22 14:27:53 -080025#include <string.h>
Adam Langleyd9e397b2015-01-22 14:27:53 -080026
27#include <openssl/aead.h>
David Benjaminf0c4a6c2016-08-11 13:26:41 -040028#include <openssl/bn.h>
Adam Langley4139edb2016-01-13 15:00:54 -080029#include <openssl/curve25519.h>
Adam Langleyd9e397b2015-01-22 14:27:53 -080030#include <openssl/digest.h>
Adam Langleye9ada862015-05-11 17:20:37 -070031#include <openssl/err.h>
David Benjaminf0c4a6c2016-08-11 13:26:41 -040032#include <openssl/ec.h>
33#include <openssl/ecdsa.h>
34#include <openssl/ec_key.h>
Robert Sloan8ff03552017-06-14 12:40:58 -070035#include <openssl/evp.h>
Robert Sloan11c28bd2018-12-17 12:09:20 -080036#include <openssl/hrss.h>
David Benjamin4969cc92016-04-22 15:02:23 -040037#include <openssl/nid.h>
Adam Langleye9ada862015-05-11 17:20:37 -070038#include <openssl/rand.h>
Adam Langleyd9e397b2015-01-22 14:27:53 -080039#include <openssl/rsa.h>
40
41#if defined(OPENSSL_WINDOWS)
David Benjamin6e899c72016-06-09 18:02:18 -040042OPENSSL_MSVC_PRAGMA(warning(push, 3))
Kenny Rootac6c5372015-03-04 12:52:47 -080043#include <windows.h>
David Benjamin6e899c72016-06-09 18:02:18 -040044OPENSSL_MSVC_PRAGMA(warning(pop))
Adam Langleyd9e397b2015-01-22 14:27:53 -080045#elif defined(OPENSSL_APPLE)
46#include <sys/time.h>
David Benjaminf0c4a6c2016-08-11 13:26:41 -040047#else
48#include <time.h>
Adam Langleyd9e397b2015-01-22 14:27:53 -080049#endif
50
Robert Sloan69939df2017-01-09 10:53:07 -080051#include "../crypto/internal.h"
Kenny Rootb8494592015-09-25 02:29:14 +000052#include "internal.h"
Adam Langleye9ada862015-05-11 17:20:37 -070053
Pete Bentley0c61efe2019-08-13 09:32:23 +010054#include "../third_party/sike/sike.h"
55
Adam Langleyd9e397b2015-01-22 14:27:53 -080056
Adam Langleyd9e397b2015-01-22 14:27:53 -080057// TimeResults represents the results of benchmarking a function.
58struct TimeResults {
59 // num_calls is the number of function calls done in the time period.
60 unsigned num_calls;
61 // us is the number of microseconds that elapsed in the time period.
62 unsigned us;
63
64 void Print(const std::string &description) {
65 printf("Did %u %s operations in %uus (%.1f ops/sec)\n", num_calls,
66 description.c_str(), us,
67 (static_cast<double>(num_calls) / us) * 1000000);
68 }
69
70 void PrintWithBytes(const std::string &description, size_t bytes_per_call) {
71 printf("Did %u %s operations in %uus (%.1f ops/sec): %.1f MB/s\n",
72 num_calls, description.c_str(), us,
73 (static_cast<double>(num_calls) / us) * 1000000,
74 static_cast<double>(bytes_per_call * num_calls) / us);
75 }
76};
77
78#if defined(OPENSSL_WINDOWS)
79static uint64_t time_now() { return GetTickCount64() * 1000; }
80#elif defined(OPENSSL_APPLE)
81static uint64_t time_now() {
82 struct timeval tv;
83 uint64_t ret;
84
85 gettimeofday(&tv, NULL);
86 ret = tv.tv_sec;
87 ret *= 1000000;
88 ret += tv.tv_usec;
89 return ret;
90}
91#else
92static uint64_t time_now() {
93 struct timespec ts;
94 clock_gettime(CLOCK_MONOTONIC, &ts);
95
96 uint64_t ret = ts.tv_sec;
97 ret *= 1000000;
98 ret += ts.tv_nsec / 1000;
99 return ret;
100}
101#endif
102
David Benjaminf0c4a6c2016-08-11 13:26:41 -0400103static uint64_t g_timeout_seconds = 1;
Robert Sloan59e99502019-03-25 12:33:16 -0700104static std::vector<size_t> g_chunk_lengths = {16, 256, 1350, 8192, 16384};
David Benjaminf0c4a6c2016-08-11 13:26:41 -0400105
Adam Langleyd9e397b2015-01-22 14:27:53 -0800106static bool TimeFunction(TimeResults *results, std::function<bool()> func) {
David Benjaminf0c4a6c2016-08-11 13:26:41 -0400107 // total_us is the total amount of time that we'll aim to measure a function
Adam Langleyd9e397b2015-01-22 14:27:53 -0800108 // for.
David Benjaminf0c4a6c2016-08-11 13:26:41 -0400109 const uint64_t total_us = g_timeout_seconds * 1000000;
Adam Langleyd9e397b2015-01-22 14:27:53 -0800110 uint64_t start = time_now(), now, delta;
111 unsigned done = 0, iterations_between_time_checks;
112
113 if (!func()) {
114 return false;
115 }
116 now = time_now();
117 delta = now - start;
118 if (delta == 0) {
119 iterations_between_time_checks = 250;
120 } else {
121 // Aim for about 100ms between time checks.
122 iterations_between_time_checks =
123 static_cast<double>(100000) / static_cast<double>(delta);
124 if (iterations_between_time_checks > 1000) {
125 iterations_between_time_checks = 1000;
126 } else if (iterations_between_time_checks < 1) {
127 iterations_between_time_checks = 1;
128 }
129 }
130
131 for (;;) {
132 for (unsigned i = 0; i < iterations_between_time_checks; i++) {
133 if (!func()) {
134 return false;
135 }
136 done++;
137 }
138
139 now = time_now();
David Benjaminf0c4a6c2016-08-11 13:26:41 -0400140 if (now - start > total_us) {
Adam Langleyd9e397b2015-01-22 14:27:53 -0800141 break;
142 }
143 }
144
145 results->us = now - start;
146 results->num_calls = done;
147 return true;
148}
149
Robert Sloan15c0b352018-04-16 08:36:46 -0700150static bool SpeedRSA(const std::string &selected) {
151 if (!selected.empty() && selected.find("RSA") == std::string::npos) {
Adam Langleye9ada862015-05-11 17:20:37 -0700152 return true;
153 }
Adam Langleyd9e397b2015-01-22 14:27:53 -0800154
Robert Sloan15c0b352018-04-16 08:36:46 -0700155 static const struct {
156 const char *name;
157 const uint8_t *key;
158 const size_t key_len;
159 } kRSAKeys[] = {
160 {"RSA 2048", kDERRSAPrivate2048, kDERRSAPrivate2048Len},
161 {"RSA 4096", kDERRSAPrivate4096, kDERRSAPrivate4096Len},
162 };
Adam Langleyd9e397b2015-01-22 14:27:53 -0800163
Robert Sloan15c0b352018-04-16 08:36:46 -0700164 for (unsigned i = 0; i < OPENSSL_ARRAY_SIZE(kRSAKeys); i++) {
165 const std::string name = kRSAKeys[i].name;
Adam Langleyd9e397b2015-01-22 14:27:53 -0800166
Robert Sloan15c0b352018-04-16 08:36:46 -0700167 bssl::UniquePtr<RSA> key(
168 RSA_private_key_from_bytes(kRSAKeys[i].key, kRSAKeys[i].key_len));
169 if (key == nullptr) {
170 fprintf(stderr, "Failed to parse %s key.\n", name.c_str());
171 ERR_print_errors_fp(stderr);
172 return false;
173 }
Robert Sloandc2f6092018-04-10 10:22:33 -0700174
Robert Sloan15c0b352018-04-16 08:36:46 -0700175 std::unique_ptr<uint8_t[]> sig(new uint8_t[RSA_size(key.get())]);
176 const uint8_t fake_sha256_hash[32] = {0};
177 unsigned sig_len;
178
179 TimeResults results;
180 if (!TimeFunction(&results,
181 [&key, &sig, &fake_sha256_hash, &sig_len]() -> bool {
182 // Usually during RSA signing we're using a long-lived |RSA| that has
183 // already had all of its |BN_MONT_CTX|s constructed, so it makes
184 // sense to use |key| directly here.
185 return RSA_sign(NID_sha256, fake_sha256_hash, sizeof(fake_sha256_hash),
186 sig.get(), &sig_len, key.get());
187 })) {
188 fprintf(stderr, "RSA_sign failed.\n");
189 ERR_print_errors_fp(stderr);
190 return false;
191 }
192 results.Print(name + " signing");
193
194 if (!TimeFunction(&results,
195 [&key, &fake_sha256_hash, &sig, sig_len]() -> bool {
196 return RSA_verify(
197 NID_sha256, fake_sha256_hash, sizeof(fake_sha256_hash),
198 sig.get(), sig_len, key.get());
199 })) {
200 fprintf(stderr, "RSA_verify failed.\n");
201 ERR_print_errors_fp(stderr);
202 return false;
203 }
204 results.Print(name + " verify (same key)");
205
206 if (!TimeFunction(&results,
207 [&key, &fake_sha256_hash, &sig, sig_len]() -> bool {
208 // Usually during RSA verification we have to parse an RSA key from a
209 // certificate or similar, in which case we'd need to construct a new
210 // RSA key, with a new |BN_MONT_CTX| for the public modulus. If we
211 // were to use |key| directly instead, then these costs wouldn't be
212 // accounted for.
213 bssl::UniquePtr<RSA> verify_key(RSA_new());
214 if (!verify_key) {
215 return false;
216 }
217 verify_key->n = BN_dup(key->n);
218 verify_key->e = BN_dup(key->e);
219 if (!verify_key->n ||
220 !verify_key->e) {
221 return false;
222 }
223 return RSA_verify(NID_sha256, fake_sha256_hash,
224 sizeof(fake_sha256_hash), sig.get(), sig_len,
225 verify_key.get());
226 })) {
227 fprintf(stderr, "RSA_verify failed.\n");
228 ERR_print_errors_fp(stderr);
229 return false;
230 }
231 results.Print(name + " verify (fresh key)");
Adam Langleyd9e397b2015-01-22 14:27:53 -0800232 }
Adam Langleyd9e397b2015-01-22 14:27:53 -0800233
234 return true;
235}
236
Robert Sloan49d063b2018-04-03 11:30:38 -0700237static bool SpeedRSAKeyGen(const std::string &selected) {
238 // Don't run this by default because it's so slow.
239 if (selected != "RSAKeyGen") {
240 return true;
241 }
242
243 bssl::UniquePtr<BIGNUM> e(BN_new());
244 if (!BN_set_word(e.get(), 65537)) {
245 return false;
246 }
247
248 const std::vector<int> kSizes = {2048, 3072, 4096};
249 for (int size : kSizes) {
250 const uint64_t start = time_now();
251 unsigned num_calls = 0;
252 unsigned us;
253 std::vector<unsigned> durations;
254
255 for (;;) {
256 bssl::UniquePtr<RSA> rsa(RSA_new());
257
258 const uint64_t iteration_start = time_now();
259 if (!RSA_generate_key_ex(rsa.get(), size, e.get(), nullptr)) {
260 fprintf(stderr, "RSA_generate_key_ex failed.\n");
261 ERR_print_errors_fp(stderr);
262 return false;
263 }
264 const uint64_t iteration_end = time_now();
265
266 num_calls++;
267 durations.push_back(iteration_end - iteration_start);
268
269 us = iteration_end - start;
270 if (us > 30 * 1000000 /* 30 secs */) {
271 break;
272 }
273 }
274
275 std::sort(durations.begin(), durations.end());
276 printf("Did %u RSA %d key-gen operations in %uus (%.1f ops/sec)\n",
277 num_calls, size, us,
278 (static_cast<double>(num_calls) / us) * 1000000);
279 const size_t n = durations.size();
280 assert(n > 0);
Robert Sloan4c22c5f2019-03-01 15:53:37 -0800281
282 // |min| and |max| must be stored in temporary variables to avoid an MSVC
283 // bug on x86. There, size_t is a typedef for unsigned, but MSVC's printf
284 // warning tries to retain the distinction and suggest %zu for size_t
285 // instead of %u. It gets confused if std::vector<unsigned> and
286 // std::vector<size_t> are both instantiated. Being typedefs, the two
287 // instantiations are identical, which somehow breaks the size_t vs unsigned
288 // metadata.
289 unsigned min = durations[0];
Robert Sloan49d063b2018-04-03 11:30:38 -0700290 unsigned median = n & 1 ? durations[n / 2]
291 : (durations[n / 2 - 1] + durations[n / 2]) / 2;
Robert Sloan4c22c5f2019-03-01 15:53:37 -0800292 unsigned max = durations[n - 1];
293 printf(" min: %uus, median: %uus, max: %uus\n", min, median, max);
Robert Sloan49d063b2018-04-03 11:30:38 -0700294 }
295
296 return true;
297}
298
Pete Bentley0c61efe2019-08-13 09:32:23 +0100299static bool SpeedSIKEP434(const std::string &selected) {
300 if (!selected.empty() && selected.find("SIKE") == std::string::npos) {
301 return true;
302 }
303 // speed generation
304 uint8_t public_SIKE[SIKE_PUB_BYTESZ];
305 uint8_t private_SIKE[SIKE_PRV_BYTESZ];
306 uint8_t ct[SIKE_CT_BYTESZ];
307 bool res;
308
309 {
310 TimeResults results;
311 res = TimeFunction(&results,
312 [&private_SIKE, &public_SIKE]() -> bool {
313 return (SIKE_keypair(private_SIKE, public_SIKE) == 1);
314 });
315 results.Print("SIKE/P434 generate");
316 }
317
318 if (!res) {
319 fprintf(stderr, "Failed to time SIKE_keypair.\n");
320 return false;
321 }
322
323 {
324 TimeResults results;
325 TimeFunction(&results,
326 [&ct, &public_SIKE]() -> bool {
327 uint8_t ss[SIKE_SS_BYTESZ];
328 SIKE_encaps(ss, ct, public_SIKE);
329 return true;
330 });
331 results.Print("SIKE/P434 encap");
332 }
333
334 if (!res) {
335 fprintf(stderr, "Failed to time SIKE_encaps.\n");
336 return false;
337 }
338
339 {
340 TimeResults results;
341 TimeFunction(&results,
342 [&ct, &public_SIKE, &private_SIKE]() -> bool {
343 uint8_t ss[SIKE_SS_BYTESZ];
344 SIKE_decaps(ss, ct, public_SIKE, private_SIKE);
345 return true;
346 });
347 results.Print("SIKE/P434 decap");
348 }
349
350 if (!res) {
351 fprintf(stderr, "Failed to time SIKE_decaps.\n");
352 return false;
353 }
354 return true;
355}
356
Adam Langleyd9e397b2015-01-22 14:27:53 -0800357static uint8_t *align(uint8_t *in, unsigned alignment) {
358 return reinterpret_cast<uint8_t *>(
Adam Langleye9ada862015-05-11 17:20:37 -0700359 (reinterpret_cast<uintptr_t>(in) + alignment) &
360 ~static_cast<size_t>(alignment - 1));
Adam Langleyd9e397b2015-01-22 14:27:53 -0800361}
362
Robert Sloan4c22c5f2019-03-01 15:53:37 -0800363static std::string ChunkLenSuffix(size_t chunk_len) {
364 char buf[32];
365 snprintf(buf, sizeof(buf), " (%zu byte%s)", chunk_len,
366 chunk_len != 1 ? "s" : "");
367 return buf;
368}
369
370static bool SpeedAEADChunk(const EVP_AEAD *aead, std::string name,
Robert Sloan7d422bc2017-03-06 10:04:29 -0800371 size_t chunk_len, size_t ad_len,
372 evp_aead_direction_t direction) {
Adam Langleyd9e397b2015-01-22 14:27:53 -0800373 static const unsigned kAlignment = 16;
374
Robert Sloan4c22c5f2019-03-01 15:53:37 -0800375 name += ChunkLenSuffix(chunk_len);
Steven Valdez909b19f2016-11-21 15:35:44 -0500376 bssl::ScopedEVP_AEAD_CTX ctx;
Adam Langleyd9e397b2015-01-22 14:27:53 -0800377 const size_t key_len = EVP_AEAD_key_length(aead);
378 const size_t nonce_len = EVP_AEAD_nonce_length(aead);
379 const size_t overhead_len = EVP_AEAD_max_overhead(aead);
380
381 std::unique_ptr<uint8_t[]> key(new uint8_t[key_len]);
Robert Sloan69939df2017-01-09 10:53:07 -0800382 OPENSSL_memset(key.get(), 0, key_len);
Adam Langleyd9e397b2015-01-22 14:27:53 -0800383 std::unique_ptr<uint8_t[]> nonce(new uint8_t[nonce_len]);
Robert Sloan69939df2017-01-09 10:53:07 -0800384 OPENSSL_memset(nonce.get(), 0, nonce_len);
Adam Langleye9ada862015-05-11 17:20:37 -0700385 std::unique_ptr<uint8_t[]> in_storage(new uint8_t[chunk_len + kAlignment]);
Robert Sloanfe7cd212017-08-07 09:03:39 -0700386 // N.B. for EVP_AEAD_CTX_seal_scatter the input and output buffers may be the
387 // same size. However, in the direction == evp_aead_open case we still use
388 // non-scattering seal, hence we add overhead_len to the size of this buffer.
389 std::unique_ptr<uint8_t[]> out_storage(
390 new uint8_t[chunk_len + overhead_len + kAlignment]);
Adam Vartanianbfcf3a72018-08-10 14:55:24 +0100391 std::unique_ptr<uint8_t[]> in2_storage(
392 new uint8_t[chunk_len + overhead_len + kAlignment]);
Adam Langleyd9e397b2015-01-22 14:27:53 -0800393 std::unique_ptr<uint8_t[]> ad(new uint8_t[ad_len]);
Robert Sloan69939df2017-01-09 10:53:07 -0800394 OPENSSL_memset(ad.get(), 0, ad_len);
Robert Sloanfe7cd212017-08-07 09:03:39 -0700395 std::unique_ptr<uint8_t[]> tag_storage(
396 new uint8_t[overhead_len + kAlignment]);
397
Adam Langleyd9e397b2015-01-22 14:27:53 -0800398
399 uint8_t *const in = align(in_storage.get(), kAlignment);
Robert Sloan69939df2017-01-09 10:53:07 -0800400 OPENSSL_memset(in, 0, chunk_len);
Adam Langleyd9e397b2015-01-22 14:27:53 -0800401 uint8_t *const out = align(out_storage.get(), kAlignment);
Robert Sloan69939df2017-01-09 10:53:07 -0800402 OPENSSL_memset(out, 0, chunk_len + overhead_len);
Robert Sloanfe7cd212017-08-07 09:03:39 -0700403 uint8_t *const tag = align(tag_storage.get(), kAlignment);
404 OPENSSL_memset(tag, 0, overhead_len);
Robert Sloan7d422bc2017-03-06 10:04:29 -0800405 uint8_t *const in2 = align(in2_storage.get(), kAlignment);
Adam Langleyd9e397b2015-01-22 14:27:53 -0800406
Steven Valdez909b19f2016-11-21 15:35:44 -0500407 if (!EVP_AEAD_CTX_init_with_direction(ctx.get(), aead, key.get(), key_len,
Adam Langleye9ada862015-05-11 17:20:37 -0700408 EVP_AEAD_DEFAULT_TAG_LENGTH,
409 evp_aead_seal)) {
Adam Langleyd9e397b2015-01-22 14:27:53 -0800410 fprintf(stderr, "Failed to create EVP_AEAD_CTX.\n");
Adam Langleye9ada862015-05-11 17:20:37 -0700411 ERR_print_errors_fp(stderr);
Adam Langleyd9e397b2015-01-22 14:27:53 -0800412 return false;
413 }
414
415 TimeResults results;
Robert Sloan7d422bc2017-03-06 10:04:29 -0800416 if (direction == evp_aead_seal) {
Robert Sloanfe7cd212017-08-07 09:03:39 -0700417 if (!TimeFunction(&results,
418 [chunk_len, nonce_len, ad_len, overhead_len, in, out, tag,
419 &ctx, &nonce, &ad]() -> bool {
420 size_t tag_len;
421 return EVP_AEAD_CTX_seal_scatter(
422 ctx.get(), out, tag, &tag_len, overhead_len,
423 nonce.get(), nonce_len, in, chunk_len, nullptr, 0,
424 ad.get(), ad_len);
425 })) {
Robert Sloan7d422bc2017-03-06 10:04:29 -0800426 fprintf(stderr, "EVP_AEAD_CTX_seal failed.\n");
427 ERR_print_errors_fp(stderr);
428 return false;
429 }
430 } else {
431 size_t out_len;
432 EVP_AEAD_CTX_seal(ctx.get(), out, &out_len, chunk_len + overhead_len,
433 nonce.get(), nonce_len, in, chunk_len, ad.get(), ad_len);
434
Adam Vartanianbfcf3a72018-08-10 14:55:24 +0100435 ctx.Reset();
436 if (!EVP_AEAD_CTX_init_with_direction(ctx.get(), aead, key.get(), key_len,
437 EVP_AEAD_DEFAULT_TAG_LENGTH,
438 evp_aead_open)) {
439 fprintf(stderr, "Failed to create EVP_AEAD_CTX.\n");
440 ERR_print_errors_fp(stderr);
441 return false;
442 }
443
Robert Sloanfe7cd212017-08-07 09:03:39 -0700444 if (!TimeFunction(&results,
Adam Vartanianbfcf3a72018-08-10 14:55:24 +0100445 [chunk_len, overhead_len, nonce_len, ad_len, in2, out,
446 out_len, &ctx, &nonce, &ad]() -> bool {
Robert Sloanfe7cd212017-08-07 09:03:39 -0700447 size_t in2_len;
448 // N.B. EVP_AEAD_CTX_open_gather is not implemented for
449 // all AEADs.
Adam Vartanianbfcf3a72018-08-10 14:55:24 +0100450 return EVP_AEAD_CTX_open(ctx.get(), in2, &in2_len,
451 chunk_len + overhead_len,
452 nonce.get(), nonce_len, out,
453 out_len, ad.get(), ad_len);
Robert Sloanfe7cd212017-08-07 09:03:39 -0700454 })) {
Robert Sloan7d422bc2017-03-06 10:04:29 -0800455 fprintf(stderr, "EVP_AEAD_CTX_open failed.\n");
456 ERR_print_errors_fp(stderr);
457 return false;
458 }
Adam Langleyd9e397b2015-01-22 14:27:53 -0800459 }
460
Robert Sloan7d422bc2017-03-06 10:04:29 -0800461 results.PrintWithBytes(
462 name + (direction == evp_aead_seal ? " seal" : " open"), chunk_len);
Adam Langleyd9e397b2015-01-22 14:27:53 -0800463 return true;
464}
465
466static bool SpeedAEAD(const EVP_AEAD *aead, const std::string &name,
Adam Langleye9ada862015-05-11 17:20:37 -0700467 size_t ad_len, const std::string &selected) {
468 if (!selected.empty() && name.find(selected) == std::string::npos) {
469 return true;
470 }
471
Robert Sloan4c22c5f2019-03-01 15:53:37 -0800472 for (size_t chunk_len : g_chunk_lengths) {
473 if (!SpeedAEADChunk(aead, name, chunk_len, ad_len, evp_aead_seal)) {
474 return false;
475 }
476 }
477 return true;
Adam Langleyd9e397b2015-01-22 14:27:53 -0800478}
479
Robert Sloan7d422bc2017-03-06 10:04:29 -0800480static bool SpeedAEADOpen(const EVP_AEAD *aead, const std::string &name,
481 size_t ad_len, const std::string &selected) {
482 if (!selected.empty() && name.find(selected) == std::string::npos) {
483 return true;
484 }
485
Robert Sloan4c22c5f2019-03-01 15:53:37 -0800486 for (size_t chunk_len : g_chunk_lengths) {
487 if (!SpeedAEADChunk(aead, name, chunk_len, ad_len, evp_aead_open)) {
488 return false;
489 }
490 }
491
492 return true;
Robert Sloan7d422bc2017-03-06 10:04:29 -0800493}
Robert Sloan7d422bc2017-03-06 10:04:29 -0800494
Robert Sloan4c22c5f2019-03-01 15:53:37 -0800495static bool SpeedHashChunk(const EVP_MD *md, std::string name,
Adam Langleyd9e397b2015-01-22 14:27:53 -0800496 size_t chunk_len) {
Robert Sloan15c0b352018-04-16 08:36:46 -0700497 bssl::ScopedEVP_MD_CTX ctx;
Pete Bentley0c61efe2019-08-13 09:32:23 +0100498 uint8_t scratch[16384];
Adam Langleyd9e397b2015-01-22 14:27:53 -0800499
500 if (chunk_len > sizeof(scratch)) {
501 return false;
502 }
503
Robert Sloan4c22c5f2019-03-01 15:53:37 -0800504 name += ChunkLenSuffix(chunk_len);
Adam Langleyd9e397b2015-01-22 14:27:53 -0800505 TimeResults results;
Robert Sloan15c0b352018-04-16 08:36:46 -0700506 if (!TimeFunction(&results, [&ctx, md, chunk_len, &scratch]() -> bool {
Adam Langleyd9e397b2015-01-22 14:27:53 -0800507 uint8_t digest[EVP_MAX_MD_SIZE];
508 unsigned int md_len;
509
Robert Sloan15c0b352018-04-16 08:36:46 -0700510 return EVP_DigestInit_ex(ctx.get(), md, NULL /* ENGINE */) &&
511 EVP_DigestUpdate(ctx.get(), scratch, chunk_len) &&
512 EVP_DigestFinal_ex(ctx.get(), digest, &md_len);
Adam Langleyd9e397b2015-01-22 14:27:53 -0800513 })) {
514 fprintf(stderr, "EVP_DigestInit_ex failed.\n");
Adam Langleye9ada862015-05-11 17:20:37 -0700515 ERR_print_errors_fp(stderr);
Adam Langleyd9e397b2015-01-22 14:27:53 -0800516 return false;
517 }
518
519 results.PrintWithBytes(name, chunk_len);
Adam Langleyd9e397b2015-01-22 14:27:53 -0800520 return true;
521}
Robert Sloan4c22c5f2019-03-01 15:53:37 -0800522
Adam Langleye9ada862015-05-11 17:20:37 -0700523static bool SpeedHash(const EVP_MD *md, const std::string &name,
524 const std::string &selected) {
525 if (!selected.empty() && name.find(selected) == std::string::npos) {
526 return true;
527 }
528
Robert Sloan4c22c5f2019-03-01 15:53:37 -0800529 for (size_t chunk_len : g_chunk_lengths) {
530 if (!SpeedHashChunk(md, name, chunk_len)) {
531 return false;
532 }
533 }
534
535 return true;
Adam Langleyd9e397b2015-01-22 14:27:53 -0800536}
537
Robert Sloan4c22c5f2019-03-01 15:53:37 -0800538static bool SpeedRandomChunk(std::string name, size_t chunk_len) {
Pete Bentley0c61efe2019-08-13 09:32:23 +0100539 uint8_t scratch[16384];
Adam Langleyd9e397b2015-01-22 14:27:53 -0800540
Adam Langleye9ada862015-05-11 17:20:37 -0700541 if (chunk_len > sizeof(scratch)) {
Adam Langleyd9e397b2015-01-22 14:27:53 -0800542 return false;
543 }
544
Robert Sloan4c22c5f2019-03-01 15:53:37 -0800545 name += ChunkLenSuffix(chunk_len);
Adam Langleye9ada862015-05-11 17:20:37 -0700546 TimeResults results;
547 if (!TimeFunction(&results, [chunk_len, &scratch]() -> bool {
548 RAND_bytes(scratch, chunk_len);
549 return true;
550 })) {
551 return false;
552 }
553
554 results.PrintWithBytes(name, chunk_len);
555 return true;
556}
557
558static bool SpeedRandom(const std::string &selected) {
559 if (!selected.empty() && selected != "RNG") {
560 return true;
561 }
562
Robert Sloan4c22c5f2019-03-01 15:53:37 -0800563 for (size_t chunk_len : g_chunk_lengths) {
564 if (!SpeedRandomChunk("RNG", chunk_len)) {
565 return false;
566 }
567 }
568
569 return true;
Adam Langleye9ada862015-05-11 17:20:37 -0700570}
571
572static bool SpeedECDHCurve(const std::string &name, int nid,
573 const std::string &selected) {
574 if (!selected.empty() && name.find(selected) == std::string::npos) {
575 return true;
576 }
577
Robert Sloan49d063b2018-04-03 11:30:38 -0700578 bssl::UniquePtr<EC_KEY> peer_key(EC_KEY_new_by_curve_name(nid));
579 if (!peer_key ||
580 !EC_KEY_generate_key(peer_key.get())) {
581 return false;
582 }
583
584 size_t peer_value_len = EC_POINT_point2oct(
585 EC_KEY_get0_group(peer_key.get()), EC_KEY_get0_public_key(peer_key.get()),
586 POINT_CONVERSION_UNCOMPRESSED, nullptr, 0, nullptr);
587 if (peer_value_len == 0) {
588 return false;
589 }
590 std::unique_ptr<uint8_t[]> peer_value(new uint8_t[peer_value_len]);
591 peer_value_len = EC_POINT_point2oct(
592 EC_KEY_get0_group(peer_key.get()), EC_KEY_get0_public_key(peer_key.get()),
593 POINT_CONVERSION_UNCOMPRESSED, peer_value.get(), peer_value_len, nullptr);
594 if (peer_value_len == 0) {
595 return false;
596 }
597
Adam Langleye9ada862015-05-11 17:20:37 -0700598 TimeResults results;
Robert Sloan49d063b2018-04-03 11:30:38 -0700599 if (!TimeFunction(&results, [nid, peer_value_len, &peer_value]() -> bool {
David Benjaminf0c4a6c2016-08-11 13:26:41 -0400600 bssl::UniquePtr<EC_KEY> key(EC_KEY_new_by_curve_name(nid));
Adam Langleye9ada862015-05-11 17:20:37 -0700601 if (!key ||
602 !EC_KEY_generate_key(key.get())) {
603 return false;
604 }
605 const EC_GROUP *const group = EC_KEY_get0_group(key.get());
David Benjaminf0c4a6c2016-08-11 13:26:41 -0400606 bssl::UniquePtr<EC_POINT> point(EC_POINT_new(group));
Robert Sloan49d063b2018-04-03 11:30:38 -0700607 bssl::UniquePtr<EC_POINT> peer_point(EC_POINT_new(group));
David Benjaminf0c4a6c2016-08-11 13:26:41 -0400608 bssl::UniquePtr<BN_CTX> ctx(BN_CTX_new());
Adam Langleye9ada862015-05-11 17:20:37 -0700609
David Benjaminf0c4a6c2016-08-11 13:26:41 -0400610 bssl::UniquePtr<BIGNUM> x(BN_new());
611 bssl::UniquePtr<BIGNUM> y(BN_new());
Adam Langleye9ada862015-05-11 17:20:37 -0700612
Robert Sloan49d063b2018-04-03 11:30:38 -0700613 if (!point || !peer_point || !ctx || !x || !y ||
614 !EC_POINT_oct2point(group, peer_point.get(), peer_value.get(),
615 peer_value_len, ctx.get()) ||
616 !EC_POINT_mul(group, point.get(), NULL, peer_point.get(),
Adam Langleye9ada862015-05-11 17:20:37 -0700617 EC_KEY_get0_private_key(key.get()), ctx.get()) ||
618 !EC_POINT_get_affine_coordinates_GFp(group, point.get(), x.get(),
619 y.get(), ctx.get())) {
620 return false;
621 }
622
623 return true;
624 })) {
625 return false;
626 }
627
628 results.Print(name);
629 return true;
630}
631
632static bool SpeedECDSACurve(const std::string &name, int nid,
633 const std::string &selected) {
634 if (!selected.empty() && name.find(selected) == std::string::npos) {
635 return true;
636 }
637
David Benjaminf0c4a6c2016-08-11 13:26:41 -0400638 bssl::UniquePtr<EC_KEY> key(EC_KEY_new_by_curve_name(nid));
Adam Langleye9ada862015-05-11 17:20:37 -0700639 if (!key ||
640 !EC_KEY_generate_key(key.get())) {
641 return false;
642 }
643
644 uint8_t signature[256];
645 if (ECDSA_size(key.get()) > sizeof(signature)) {
646 return false;
647 }
648 uint8_t digest[20];
Robert Sloan69939df2017-01-09 10:53:07 -0800649 OPENSSL_memset(digest, 42, sizeof(digest));
Adam Langleye9ada862015-05-11 17:20:37 -0700650 unsigned sig_len;
651
652 TimeResults results;
653 if (!TimeFunction(&results, [&key, &signature, &digest, &sig_len]() -> bool {
654 return ECDSA_sign(0, digest, sizeof(digest), signature, &sig_len,
655 key.get()) == 1;
656 })) {
657 return false;
658 }
659
660 results.Print(name + " signing");
661
662 if (!TimeFunction(&results, [&key, &signature, &digest, sig_len]() -> bool {
663 return ECDSA_verify(0, digest, sizeof(digest), signature, sig_len,
664 key.get()) == 1;
665 })) {
666 return false;
667 }
668
669 results.Print(name + " verify");
670
671 return true;
672}
673
674static bool SpeedECDH(const std::string &selected) {
675 return SpeedECDHCurve("ECDH P-224", NID_secp224r1, selected) &&
676 SpeedECDHCurve("ECDH P-256", NID_X9_62_prime256v1, selected) &&
677 SpeedECDHCurve("ECDH P-384", NID_secp384r1, selected) &&
678 SpeedECDHCurve("ECDH P-521", NID_secp521r1, selected);
679}
680
681static bool SpeedECDSA(const std::string &selected) {
682 return SpeedECDSACurve("ECDSA P-224", NID_secp224r1, selected) &&
683 SpeedECDSACurve("ECDSA P-256", NID_X9_62_prime256v1, selected) &&
684 SpeedECDSACurve("ECDSA P-384", NID_secp384r1, selected) &&
685 SpeedECDSACurve("ECDSA P-521", NID_secp521r1, selected);
686}
687
Adam Langley4139edb2016-01-13 15:00:54 -0800688static bool Speed25519(const std::string &selected) {
689 if (!selected.empty() && selected.find("25519") == std::string::npos) {
690 return true;
691 }
692
693 TimeResults results;
694
695 uint8_t public_key[32], private_key[64];
696
697 if (!TimeFunction(&results, [&public_key, &private_key]() -> bool {
698 ED25519_keypair(public_key, private_key);
699 return true;
700 })) {
701 return false;
702 }
703
704 results.Print("Ed25519 key generation");
705
706 static const uint8_t kMessage[] = {0, 1, 2, 3, 4, 5};
707 uint8_t signature[64];
708
709 if (!TimeFunction(&results, [&private_key, &signature]() -> bool {
710 return ED25519_sign(signature, kMessage, sizeof(kMessage),
711 private_key) == 1;
712 })) {
713 return false;
714 }
715
716 results.Print("Ed25519 signing");
717
718 if (!TimeFunction(&results, [&public_key, &signature]() -> bool {
719 return ED25519_verify(kMessage, sizeof(kMessage), signature,
720 public_key) == 1;
721 })) {
722 fprintf(stderr, "Ed25519 verify failed.\n");
723 return false;
724 }
725
726 results.Print("Ed25519 verify");
727
728 if (!TimeFunction(&results, []() -> bool {
729 uint8_t out[32], in[32];
Robert Sloan69939df2017-01-09 10:53:07 -0800730 OPENSSL_memset(in, 0, sizeof(in));
Adam Langley4139edb2016-01-13 15:00:54 -0800731 X25519_public_from_private(out, in);
732 return true;
733 })) {
734 fprintf(stderr, "Curve25519 base-point multiplication failed.\n");
735 return false;
736 }
737
738 results.Print("Curve25519 base-point multiplication");
739
740 if (!TimeFunction(&results, []() -> bool {
741 uint8_t out[32], in1[32], in2[32];
Robert Sloan69939df2017-01-09 10:53:07 -0800742 OPENSSL_memset(in1, 0, sizeof(in1));
743 OPENSSL_memset(in2, 0, sizeof(in2));
Adam Langley4139edb2016-01-13 15:00:54 -0800744 in1[0] = 1;
745 in2[0] = 9;
746 return X25519(out, in1, in2) == 1;
747 })) {
748 fprintf(stderr, "Curve25519 arbitrary point multiplication failed.\n");
749 return false;
750 }
751
752 results.Print("Curve25519 arbitrary point multiplication");
753
754 return true;
755}
756
David Benjamin4969cc92016-04-22 15:02:23 -0400757static bool SpeedSPAKE2(const std::string &selected) {
758 if (!selected.empty() && selected.find("SPAKE2") == std::string::npos) {
759 return true;
760 }
761
762 TimeResults results;
763
764 static const uint8_t kAliceName[] = {'A'};
765 static const uint8_t kBobName[] = {'B'};
766 static const uint8_t kPassword[] = "password";
David Benjaminf0c4a6c2016-08-11 13:26:41 -0400767 bssl::UniquePtr<SPAKE2_CTX> alice(SPAKE2_CTX_new(spake2_role_alice,
768 kAliceName, sizeof(kAliceName), kBobName,
769 sizeof(kBobName)));
David Benjamin4969cc92016-04-22 15:02:23 -0400770 uint8_t alice_msg[SPAKE2_MAX_MSG_SIZE];
771 size_t alice_msg_len;
772
773 if (!SPAKE2_generate_msg(alice.get(), alice_msg, &alice_msg_len,
774 sizeof(alice_msg),
775 kPassword, sizeof(kPassword))) {
776 fprintf(stderr, "SPAKE2_generate_msg failed.\n");
777 return false;
778 }
779
780 if (!TimeFunction(&results, [&alice_msg, alice_msg_len]() -> bool {
David Benjaminf0c4a6c2016-08-11 13:26:41 -0400781 bssl::UniquePtr<SPAKE2_CTX> bob(SPAKE2_CTX_new(spake2_role_bob,
782 kBobName, sizeof(kBobName), kAliceName,
783 sizeof(kAliceName)));
David Benjamin4969cc92016-04-22 15:02:23 -0400784 uint8_t bob_msg[SPAKE2_MAX_MSG_SIZE], bob_key[64];
785 size_t bob_msg_len, bob_key_len;
786 if (!SPAKE2_generate_msg(bob.get(), bob_msg, &bob_msg_len,
787 sizeof(bob_msg), kPassword,
788 sizeof(kPassword)) ||
789 !SPAKE2_process_msg(bob.get(), bob_key, &bob_key_len,
790 sizeof(bob_key), alice_msg, alice_msg_len)) {
791 return false;
792 }
793
794 return true;
795 })) {
796 fprintf(stderr, "SPAKE2 failed.\n");
797 }
798
799 results.Print("SPAKE2 over Ed25519");
800
801 return true;
802}
803
Robert Sloan8ff03552017-06-14 12:40:58 -0700804static bool SpeedScrypt(const std::string &selected) {
805 if (!selected.empty() && selected.find("scrypt") == std::string::npos) {
806 return true;
807 }
808
809 TimeResults results;
810
811 static const char kPassword[] = "password";
812 static const uint8_t kSalt[] = "NaCl";
813
814 if (!TimeFunction(&results, [&]() -> bool {
815 uint8_t out[64];
816 return !!EVP_PBE_scrypt(kPassword, sizeof(kPassword) - 1, kSalt,
817 sizeof(kSalt) - 1, 1024, 8, 16, 0 /* max_mem */,
818 out, sizeof(out));
819 })) {
820 fprintf(stderr, "scrypt failed.\n");
821 return false;
822 }
823 results.Print("scrypt (N = 1024, r = 8, p = 16)");
824
825 if (!TimeFunction(&results, [&]() -> bool {
826 uint8_t out[64];
827 return !!EVP_PBE_scrypt(kPassword, sizeof(kPassword) - 1, kSalt,
828 sizeof(kSalt) - 1, 16384, 8, 1, 0 /* max_mem */,
829 out, sizeof(out));
830 })) {
831 fprintf(stderr, "scrypt failed.\n");
832 return false;
833 }
834 results.Print("scrypt (N = 16384, r = 8, p = 1)");
835
836 return true;
837}
838
Robert Sloan11c28bd2018-12-17 12:09:20 -0800839static bool SpeedHRSS(const std::string &selected) {
840 if (!selected.empty() && selected != "HRSS") {
841 return true;
842 }
843
844 TimeResults results;
845
846 if (!TimeFunction(&results, []() -> bool {
847 struct HRSS_public_key pub;
848 struct HRSS_private_key priv;
849 uint8_t entropy[HRSS_GENERATE_KEY_BYTES];
850 RAND_bytes(entropy, sizeof(entropy));
851 HRSS_generate_key(&pub, &priv, entropy);
852 return true;
853 })) {
854 fprintf(stderr, "Failed to time HRSS_generate_key.\n");
855 return false;
856 }
857
858 results.Print("HRSS generate");
859
860 struct HRSS_public_key pub;
861 struct HRSS_private_key priv;
862 uint8_t key_entropy[HRSS_GENERATE_KEY_BYTES];
863 RAND_bytes(key_entropy, sizeof(key_entropy));
864 HRSS_generate_key(&pub, &priv, key_entropy);
865
866 uint8_t ciphertext[HRSS_CIPHERTEXT_BYTES];
867 if (!TimeFunction(&results, [&pub, &ciphertext]() -> bool {
868 uint8_t entropy[HRSS_ENCAP_BYTES];
869 uint8_t shared_key[HRSS_KEY_BYTES];
870 RAND_bytes(entropy, sizeof(entropy));
871 HRSS_encap(ciphertext, shared_key, &pub, entropy);
872 return true;
873 })) {
874 fprintf(stderr, "Failed to time HRSS_encap.\n");
875 return false;
876 }
877
878 results.Print("HRSS encap");
879
Robert Sloan4c22c5f2019-03-01 15:53:37 -0800880 if (!TimeFunction(&results, [&priv, &ciphertext]() -> bool {
Robert Sloan11c28bd2018-12-17 12:09:20 -0800881 uint8_t shared_key[HRSS_KEY_BYTES];
Robert Sloan4c22c5f2019-03-01 15:53:37 -0800882 HRSS_decap(shared_key, &priv, ciphertext, sizeof(ciphertext));
Robert Sloan11c28bd2018-12-17 12:09:20 -0800883 return true;
884 })) {
885 fprintf(stderr, "Failed to time HRSS_encap.\n");
886 return false;
887 }
888
889 results.Print("HRSS decap");
890
891 return true;
892}
893
David Benjaminf0c4a6c2016-08-11 13:26:41 -0400894static const struct argument kArguments[] = {
895 {
Robert Sloan4c22c5f2019-03-01 15:53:37 -0800896 "-filter",
897 kOptionalArgument,
898 "A filter on the speed tests to run",
David Benjaminf0c4a6c2016-08-11 13:26:41 -0400899 },
900 {
Robert Sloan4c22c5f2019-03-01 15:53:37 -0800901 "-timeout",
902 kOptionalArgument,
903 "The number of seconds to run each test for (default is 1)",
David Benjaminf0c4a6c2016-08-11 13:26:41 -0400904 },
905 {
Robert Sloan4c22c5f2019-03-01 15:53:37 -0800906 "-chunks",
907 kOptionalArgument,
908 "A comma-separated list of input sizes to run tests at (default is "
Robert Sloan59e99502019-03-25 12:33:16 -0700909 "16,256,1350,8192,16384)",
Robert Sloan4c22c5f2019-03-01 15:53:37 -0800910 },
911 {
912 "",
913 kOptionalArgument,
914 "",
David Benjaminf0c4a6c2016-08-11 13:26:41 -0400915 },
916};
917
Adam Langleye9ada862015-05-11 17:20:37 -0700918bool Speed(const std::vector<std::string> &args) {
David Benjaminf0c4a6c2016-08-11 13:26:41 -0400919 std::map<std::string, std::string> args_map;
920 if (!ParseKeyValueArguments(&args_map, args, kArguments)) {
921 PrintUsage(kArguments);
Adam Langleye9ada862015-05-11 17:20:37 -0700922 return false;
923 }
David Benjaminf0c4a6c2016-08-11 13:26:41 -0400924
925 std::string selected;
926 if (args_map.count("-filter") != 0) {
927 selected = args_map["-filter"];
928 }
929
930 if (args_map.count("-timeout") != 0) {
931 g_timeout_seconds = atoi(args_map["-timeout"].c_str());
Adam Langleye9ada862015-05-11 17:20:37 -0700932 }
933
Robert Sloan4c22c5f2019-03-01 15:53:37 -0800934 if (args_map.count("-chunks") != 0) {
935 g_chunk_lengths.clear();
936 const char *start = args_map["-chunks"].data();
937 const char *end = start + args_map["-chunks"].size();
938 while (start != end) {
939 errno = 0;
940 char *ptr;
941 unsigned long long val = strtoull(start, &ptr, 10);
942 if (ptr == start /* no numeric characters found */ ||
943 errno == ERANGE /* overflow */ ||
944 static_cast<size_t>(val) != val) {
945 fprintf(stderr, "Error parsing -chunks argument\n");
946 return false;
947 }
948 g_chunk_lengths.push_back(static_cast<size_t>(val));
949 start = ptr;
950 if (start != end) {
951 if (*start != ',') {
952 fprintf(stderr, "Error parsing -chunks argument\n");
953 return false;
954 }
955 start++;
956 }
957 }
958 }
959
Adam Langleyd9e397b2015-01-22 14:27:53 -0800960 // kTLSADLen is the number of bytes of additional data that TLS passes to
961 // AEADs.
962 static const size_t kTLSADLen = 13;
963 // kLegacyADLen is the number of bytes that TLS passes to the "legacy" AEADs.
964 // These are AEADs that weren't originally defined as AEADs, but which we use
965 // via the AEAD interface. In order for that to work, they have some TLS
966 // knowledge in them and construct a couple of the AD bytes internally.
967 static const size_t kLegacyADLen = kTLSADLen - 2;
968
Robert Sloan15c0b352018-04-16 08:36:46 -0700969 if (!SpeedRSA(selected) ||
970 !SpeedAEAD(EVP_aead_aes_128_gcm(), "AES-128-GCM", kTLSADLen, selected) ||
Adam Langleye9ada862015-05-11 17:20:37 -0700971 !SpeedAEAD(EVP_aead_aes_256_gcm(), "AES-256-GCM", kTLSADLen, selected) ||
Adam Langley4139edb2016-01-13 15:00:54 -0800972 !SpeedAEAD(EVP_aead_chacha20_poly1305(), "ChaCha20-Poly1305", kTLSADLen,
973 selected) ||
Adam Langley4139edb2016-01-13 15:00:54 -0800974 !SpeedAEAD(EVP_aead_des_ede3_cbc_sha1_tls(), "DES-EDE3-CBC-SHA1",
975 kLegacyADLen, selected) ||
Adam Langleye9ada862015-05-11 17:20:37 -0700976 !SpeedAEAD(EVP_aead_aes_128_cbc_sha1_tls(), "AES-128-CBC-SHA1",
977 kLegacyADLen, selected) ||
978 !SpeedAEAD(EVP_aead_aes_256_cbc_sha1_tls(), "AES-256-CBC-SHA1",
979 kLegacyADLen, selected) ||
Adam Vartanianbfcf3a72018-08-10 14:55:24 +0100980 !SpeedAEADOpen(EVP_aead_aes_128_cbc_sha1_tls(), "AES-128-CBC-SHA1",
981 kLegacyADLen, selected) ||
982 !SpeedAEADOpen(EVP_aead_aes_256_cbc_sha1_tls(), "AES-256-CBC-SHA1",
983 kLegacyADLen, selected) ||
David Benjamin1b249672016-12-06 18:25:50 -0500984 !SpeedAEAD(EVP_aead_aes_128_gcm_siv(), "AES-128-GCM-SIV", kTLSADLen,
985 selected) ||
986 !SpeedAEAD(EVP_aead_aes_256_gcm_siv(), "AES-256-GCM-SIV", kTLSADLen,
987 selected) ||
Robert Sloan7d422bc2017-03-06 10:04:29 -0800988 !SpeedAEADOpen(EVP_aead_aes_128_gcm_siv(), "AES-128-GCM-SIV", kTLSADLen,
989 selected) ||
990 !SpeedAEADOpen(EVP_aead_aes_256_gcm_siv(), "AES-256-GCM-SIV", kTLSADLen,
991 selected) ||
Robert Sloanab8b8882018-03-26 11:39:51 -0700992 !SpeedAEAD(EVP_aead_aes_128_ccm_bluetooth(), "AES-128-CCM-Bluetooth",
993 kTLSADLen, selected) ||
Adam Langleye9ada862015-05-11 17:20:37 -0700994 !SpeedHash(EVP_sha1(), "SHA-1", selected) ||
995 !SpeedHash(EVP_sha256(), "SHA-256", selected) ||
996 !SpeedHash(EVP_sha512(), "SHA-512", selected) ||
997 !SpeedRandom(selected) ||
998 !SpeedECDH(selected) ||
Adam Langley4139edb2016-01-13 15:00:54 -0800999 !SpeedECDSA(selected) ||
David Benjamin4969cc92016-04-22 15:02:23 -04001000 !Speed25519(selected) ||
Pete Bentley0c61efe2019-08-13 09:32:23 +01001001 !SpeedSIKEP434(selected) ||
Robert Sloan8ff03552017-06-14 12:40:58 -07001002 !SpeedSPAKE2(selected) ||
Robert Sloan49d063b2018-04-03 11:30:38 -07001003 !SpeedScrypt(selected) ||
Robert Sloan11c28bd2018-12-17 12:09:20 -08001004 !SpeedRSAKeyGen(selected) ||
1005 !SpeedHRSS(selected)) {
Adam Langleyd9e397b2015-01-22 14:27:53 -08001006 return false;
1007 }
1008
Adam Langleye9ada862015-05-11 17:20:37 -07001009 return true;
Adam Langleyd9e397b2015-01-22 14:27:53 -08001010}