Nie możesz wybrać więcej, niż 25 tematów Tematy muszą się zaczynać od litery lub cyfry, mogą zawierać myślniki ('-') i mogą mieć do 35 znaków.
 
 
 
 
 
 

712 wiersze
22 KiB

  1. /* Copyright (c) 2014, Google Inc.
  2. *
  3. * Permission to use, copy, modify, and/or distribute this software for any
  4. * purpose with or without fee is hereby granted, provided that the above
  5. * copyright notice and this permission notice appear in all copies.
  6. *
  7. * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
  8. * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
  9. * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
  10. * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
  11. * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
  12. * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
  13. * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */
  14. #include <string>
  15. #include <functional>
  16. #include <memory>
  17. #include <vector>
  18. #include <stdint.h>
  19. #include <stdlib.h>
  20. #include <string.h>
  21. #include <openssl/aead.h>
  22. #include <openssl/bn.h>
  23. #include <openssl/curve25519.h>
  24. #include <openssl/digest.h>
  25. #include <openssl/err.h>
  26. #include <openssl/ec.h>
  27. #include <openssl/ecdsa.h>
  28. #include <openssl/ec_key.h>
  29. #include <openssl/evp.h>
  30. #include <openssl/nid.h>
  31. #include <openssl/rand.h>
  32. #include <openssl/rsa.h>
  33. #if defined(OPENSSL_WINDOWS)
  34. OPENSSL_MSVC_PRAGMA(warning(push, 3))
  35. #include <windows.h>
  36. OPENSSL_MSVC_PRAGMA(warning(pop))
  37. #elif defined(OPENSSL_APPLE)
  38. #include <sys/time.h>
  39. #else
  40. #include <time.h>
  41. #endif
  42. #include "../crypto/internal.h"
  43. #include "internal.h"
  44. // TimeResults represents the results of benchmarking a function.
  45. struct TimeResults {
  46. // num_calls is the number of function calls done in the time period.
  47. unsigned num_calls;
  48. // us is the number of microseconds that elapsed in the time period.
  49. unsigned us;
  50. void Print(const std::string &description) {
  51. printf("Did %u %s operations in %uus (%.1f ops/sec)\n", num_calls,
  52. description.c_str(), us,
  53. (static_cast<double>(num_calls) / us) * 1000000);
  54. }
  55. void PrintWithBytes(const std::string &description, size_t bytes_per_call) {
  56. printf("Did %u %s operations in %uus (%.1f ops/sec): %.1f MB/s\n",
  57. num_calls, description.c_str(), us,
  58. (static_cast<double>(num_calls) / us) * 1000000,
  59. static_cast<double>(bytes_per_call * num_calls) / us);
  60. }
  61. };
  62. #if defined(OPENSSL_WINDOWS)
  63. static uint64_t time_now() { return GetTickCount64() * 1000; }
  64. #elif defined(OPENSSL_APPLE)
  65. static uint64_t time_now() {
  66. struct timeval tv;
  67. uint64_t ret;
  68. gettimeofday(&tv, NULL);
  69. ret = tv.tv_sec;
  70. ret *= 1000000;
  71. ret += tv.tv_usec;
  72. return ret;
  73. }
  74. #else
  75. static uint64_t time_now() {
  76. struct timespec ts;
  77. clock_gettime(CLOCK_MONOTONIC, &ts);
  78. uint64_t ret = ts.tv_sec;
  79. ret *= 1000000;
  80. ret += ts.tv_nsec / 1000;
  81. return ret;
  82. }
  83. #endif
  84. static uint64_t g_timeout_seconds = 1;
  85. static bool TimeFunction(TimeResults *results, std::function<bool()> func) {
  86. // total_us is the total amount of time that we'll aim to measure a function
  87. // for.
  88. const uint64_t total_us = g_timeout_seconds * 1000000;
  89. uint64_t start = time_now(), now, delta;
  90. unsigned done = 0, iterations_between_time_checks;
  91. if (!func()) {
  92. return false;
  93. }
  94. now = time_now();
  95. delta = now - start;
  96. if (delta == 0) {
  97. iterations_between_time_checks = 250;
  98. } else {
  99. // Aim for about 100ms between time checks.
  100. iterations_between_time_checks =
  101. static_cast<double>(100000) / static_cast<double>(delta);
  102. if (iterations_between_time_checks > 1000) {
  103. iterations_between_time_checks = 1000;
  104. } else if (iterations_between_time_checks < 1) {
  105. iterations_between_time_checks = 1;
  106. }
  107. }
  108. for (;;) {
  109. for (unsigned i = 0; i < iterations_between_time_checks; i++) {
  110. if (!func()) {
  111. return false;
  112. }
  113. done++;
  114. }
  115. now = time_now();
  116. if (now - start > total_us) {
  117. break;
  118. }
  119. }
  120. results->us = now - start;
  121. results->num_calls = done;
  122. return true;
  123. }
  124. static bool SpeedRSA(const std::string &key_name, RSA *key,
  125. const std::string &selected) {
  126. if (!selected.empty() && key_name.find(selected) == std::string::npos) {
  127. return true;
  128. }
  129. std::unique_ptr<uint8_t[]> sig(new uint8_t[RSA_size(key)]);
  130. const uint8_t fake_sha256_hash[32] = {0};
  131. unsigned sig_len;
  132. TimeResults results;
  133. if (!TimeFunction(&results,
  134. [key, &sig, &fake_sha256_hash, &sig_len]() -> bool {
  135. /* Usually during RSA signing we're using a long-lived |RSA| that has
  136. * already had all of its |BN_MONT_CTX|s constructed, so it makes
  137. * sense to use |key| directly here. */
  138. return RSA_sign(NID_sha256, fake_sha256_hash, sizeof(fake_sha256_hash),
  139. sig.get(), &sig_len, key);
  140. })) {
  141. fprintf(stderr, "RSA_sign failed.\n");
  142. ERR_print_errors_fp(stderr);
  143. return false;
  144. }
  145. results.Print(key_name + " signing");
  146. if (!TimeFunction(&results,
  147. [key, &fake_sha256_hash, &sig, sig_len]() -> bool {
  148. /* Usually during RSA verification we have to parse an RSA key from a
  149. * certificate or similar, in which case we'd need to construct a new
  150. * RSA key, with a new |BN_MONT_CTX| for the public modulus. If we were
  151. * to use |key| directly instead, then these costs wouldn't be
  152. * accounted for. */
  153. bssl::UniquePtr<RSA> verify_key(RSA_new());
  154. if (!verify_key) {
  155. return false;
  156. }
  157. verify_key->n = BN_dup(key->n);
  158. verify_key->e = BN_dup(key->e);
  159. if (!verify_key->n ||
  160. !verify_key->e) {
  161. return false;
  162. }
  163. return RSA_verify(NID_sha256, fake_sha256_hash,
  164. sizeof(fake_sha256_hash), sig.get(), sig_len, key);
  165. })) {
  166. fprintf(stderr, "RSA_verify failed.\n");
  167. ERR_print_errors_fp(stderr);
  168. return false;
  169. }
  170. results.Print(key_name + " verify");
  171. return true;
  172. }
  173. static uint8_t *align(uint8_t *in, unsigned alignment) {
  174. return reinterpret_cast<uint8_t *>(
  175. (reinterpret_cast<uintptr_t>(in) + alignment) &
  176. ~static_cast<size_t>(alignment - 1));
  177. }
  178. static bool SpeedAEADChunk(const EVP_AEAD *aead, const std::string &name,
  179. size_t chunk_len, size_t ad_len,
  180. evp_aead_direction_t direction) {
  181. static const unsigned kAlignment = 16;
  182. bssl::ScopedEVP_AEAD_CTX ctx;
  183. const size_t key_len = EVP_AEAD_key_length(aead);
  184. const size_t nonce_len = EVP_AEAD_nonce_length(aead);
  185. const size_t overhead_len = EVP_AEAD_max_overhead(aead);
  186. std::unique_ptr<uint8_t[]> key(new uint8_t[key_len]);
  187. OPENSSL_memset(key.get(), 0, key_len);
  188. std::unique_ptr<uint8_t[]> nonce(new uint8_t[nonce_len]);
  189. OPENSSL_memset(nonce.get(), 0, nonce_len);
  190. std::unique_ptr<uint8_t[]> in_storage(new uint8_t[chunk_len + kAlignment]);
  191. std::unique_ptr<uint8_t[]> out_storage(new uint8_t[chunk_len + overhead_len + kAlignment]);
  192. std::unique_ptr<uint8_t[]> in2_storage(new uint8_t[chunk_len + kAlignment]);
  193. std::unique_ptr<uint8_t[]> ad(new uint8_t[ad_len]);
  194. OPENSSL_memset(ad.get(), 0, ad_len);
  195. uint8_t *const in = align(in_storage.get(), kAlignment);
  196. OPENSSL_memset(in, 0, chunk_len);
  197. uint8_t *const out = align(out_storage.get(), kAlignment);
  198. OPENSSL_memset(out, 0, chunk_len + overhead_len);
  199. uint8_t *const in2 = align(in2_storage.get(), kAlignment);
  200. if (!EVP_AEAD_CTX_init_with_direction(ctx.get(), aead, key.get(), key_len,
  201. EVP_AEAD_DEFAULT_TAG_LENGTH,
  202. evp_aead_seal)) {
  203. fprintf(stderr, "Failed to create EVP_AEAD_CTX.\n");
  204. ERR_print_errors_fp(stderr);
  205. return false;
  206. }
  207. TimeResults results;
  208. if (direction == evp_aead_seal) {
  209. if (!TimeFunction(&results, [chunk_len, overhead_len, nonce_len, ad_len, in,
  210. out, &ctx, &nonce, &ad]() -> bool {
  211. size_t out_len;
  212. return EVP_AEAD_CTX_seal(ctx.get(), out, &out_len,
  213. chunk_len + overhead_len, nonce.get(),
  214. nonce_len, in, chunk_len, ad.get(), ad_len);
  215. })) {
  216. fprintf(stderr, "EVP_AEAD_CTX_seal failed.\n");
  217. ERR_print_errors_fp(stderr);
  218. return false;
  219. }
  220. } else {
  221. size_t out_len;
  222. EVP_AEAD_CTX_seal(ctx.get(), out, &out_len, chunk_len + overhead_len,
  223. nonce.get(), nonce_len, in, chunk_len, ad.get(), ad_len);
  224. if (!TimeFunction(&results, [chunk_len, nonce_len, ad_len, in2, out, &ctx,
  225. &nonce, &ad, out_len]() -> bool {
  226. size_t in2_len;
  227. return EVP_AEAD_CTX_open(ctx.get(), in2, &in2_len, chunk_len,
  228. nonce.get(), nonce_len, out, out_len,
  229. ad.get(), ad_len);
  230. })) {
  231. fprintf(stderr, "EVP_AEAD_CTX_open failed.\n");
  232. ERR_print_errors_fp(stderr);
  233. return false;
  234. }
  235. }
  236. results.PrintWithBytes(
  237. name + (direction == evp_aead_seal ? " seal" : " open"), chunk_len);
  238. return true;
  239. }
  240. static bool SpeedAEAD(const EVP_AEAD *aead, const std::string &name,
  241. size_t ad_len, const std::string &selected) {
  242. if (!selected.empty() && name.find(selected) == std::string::npos) {
  243. return true;
  244. }
  245. return SpeedAEADChunk(aead, name + " (16 bytes)", 16, ad_len,
  246. evp_aead_seal) &&
  247. SpeedAEADChunk(aead, name + " (1350 bytes)", 1350, ad_len,
  248. evp_aead_seal) &&
  249. SpeedAEADChunk(aead, name + " (8192 bytes)", 8192, ad_len,
  250. evp_aead_seal);
  251. }
  252. static bool SpeedAEADOpen(const EVP_AEAD *aead, const std::string &name,
  253. size_t ad_len, const std::string &selected) {
  254. if (!selected.empty() && name.find(selected) == std::string::npos) {
  255. return true;
  256. }
  257. return SpeedAEADChunk(aead, name + " (16 bytes)", 16, ad_len,
  258. evp_aead_open) &&
  259. SpeedAEADChunk(aead, name + " (1350 bytes)", 1350, ad_len,
  260. evp_aead_open) &&
  261. SpeedAEADChunk(aead, name + " (8192 bytes)", 8192, ad_len,
  262. evp_aead_open);
  263. }
  264. static bool SpeedHashChunk(const EVP_MD *md, const std::string &name,
  265. size_t chunk_len) {
  266. EVP_MD_CTX *ctx = EVP_MD_CTX_create();
  267. uint8_t scratch[8192];
  268. if (chunk_len > sizeof(scratch)) {
  269. return false;
  270. }
  271. TimeResults results;
  272. if (!TimeFunction(&results, [ctx, md, chunk_len, &scratch]() -> bool {
  273. uint8_t digest[EVP_MAX_MD_SIZE];
  274. unsigned int md_len;
  275. return EVP_DigestInit_ex(ctx, md, NULL /* ENGINE */) &&
  276. EVP_DigestUpdate(ctx, scratch, chunk_len) &&
  277. EVP_DigestFinal_ex(ctx, digest, &md_len);
  278. })) {
  279. fprintf(stderr, "EVP_DigestInit_ex failed.\n");
  280. ERR_print_errors_fp(stderr);
  281. return false;
  282. }
  283. results.PrintWithBytes(name, chunk_len);
  284. EVP_MD_CTX_destroy(ctx);
  285. return true;
  286. }
  287. static bool SpeedHash(const EVP_MD *md, const std::string &name,
  288. const std::string &selected) {
  289. if (!selected.empty() && name.find(selected) == std::string::npos) {
  290. return true;
  291. }
  292. return SpeedHashChunk(md, name + " (16 bytes)", 16) &&
  293. SpeedHashChunk(md, name + " (256 bytes)", 256) &&
  294. SpeedHashChunk(md, name + " (8192 bytes)", 8192);
  295. }
  296. static bool SpeedRandomChunk(const std::string &name, size_t chunk_len) {
  297. uint8_t scratch[8192];
  298. if (chunk_len > sizeof(scratch)) {
  299. return false;
  300. }
  301. TimeResults results;
  302. if (!TimeFunction(&results, [chunk_len, &scratch]() -> bool {
  303. RAND_bytes(scratch, chunk_len);
  304. return true;
  305. })) {
  306. return false;
  307. }
  308. results.PrintWithBytes(name, chunk_len);
  309. return true;
  310. }
  311. static bool SpeedRandom(const std::string &selected) {
  312. if (!selected.empty() && selected != "RNG") {
  313. return true;
  314. }
  315. return SpeedRandomChunk("RNG (16 bytes)", 16) &&
  316. SpeedRandomChunk("RNG (256 bytes)", 256) &&
  317. SpeedRandomChunk("RNG (8192 bytes)", 8192);
  318. }
  319. static bool SpeedECDHCurve(const std::string &name, int nid,
  320. const std::string &selected) {
  321. if (!selected.empty() && name.find(selected) == std::string::npos) {
  322. return true;
  323. }
  324. TimeResults results;
  325. if (!TimeFunction(&results, [nid]() -> bool {
  326. bssl::UniquePtr<EC_KEY> key(EC_KEY_new_by_curve_name(nid));
  327. if (!key ||
  328. !EC_KEY_generate_key(key.get())) {
  329. return false;
  330. }
  331. const EC_GROUP *const group = EC_KEY_get0_group(key.get());
  332. bssl::UniquePtr<EC_POINT> point(EC_POINT_new(group));
  333. bssl::UniquePtr<BN_CTX> ctx(BN_CTX_new());
  334. bssl::UniquePtr<BIGNUM> x(BN_new());
  335. bssl::UniquePtr<BIGNUM> y(BN_new());
  336. if (!point || !ctx || !x || !y ||
  337. !EC_POINT_mul(group, point.get(), NULL,
  338. EC_KEY_get0_public_key(key.get()),
  339. EC_KEY_get0_private_key(key.get()), ctx.get()) ||
  340. !EC_POINT_get_affine_coordinates_GFp(group, point.get(), x.get(),
  341. y.get(), ctx.get())) {
  342. return false;
  343. }
  344. return true;
  345. })) {
  346. return false;
  347. }
  348. results.Print(name);
  349. return true;
  350. }
  351. static bool SpeedECDSACurve(const std::string &name, int nid,
  352. const std::string &selected) {
  353. if (!selected.empty() && name.find(selected) == std::string::npos) {
  354. return true;
  355. }
  356. bssl::UniquePtr<EC_KEY> key(EC_KEY_new_by_curve_name(nid));
  357. if (!key ||
  358. !EC_KEY_generate_key(key.get())) {
  359. return false;
  360. }
  361. uint8_t signature[256];
  362. if (ECDSA_size(key.get()) > sizeof(signature)) {
  363. return false;
  364. }
  365. uint8_t digest[20];
  366. OPENSSL_memset(digest, 42, sizeof(digest));
  367. unsigned sig_len;
  368. TimeResults results;
  369. if (!TimeFunction(&results, [&key, &signature, &digest, &sig_len]() -> bool {
  370. return ECDSA_sign(0, digest, sizeof(digest), signature, &sig_len,
  371. key.get()) == 1;
  372. })) {
  373. return false;
  374. }
  375. results.Print(name + " signing");
  376. if (!TimeFunction(&results, [&key, &signature, &digest, sig_len]() -> bool {
  377. return ECDSA_verify(0, digest, sizeof(digest), signature, sig_len,
  378. key.get()) == 1;
  379. })) {
  380. return false;
  381. }
  382. results.Print(name + " verify");
  383. return true;
  384. }
  385. static bool SpeedECDH(const std::string &selected) {
  386. return SpeedECDHCurve("ECDH P-224", NID_secp224r1, selected) &&
  387. SpeedECDHCurve("ECDH P-256", NID_X9_62_prime256v1, selected) &&
  388. SpeedECDHCurve("ECDH P-384", NID_secp384r1, selected) &&
  389. SpeedECDHCurve("ECDH P-521", NID_secp521r1, selected);
  390. }
  391. static bool SpeedECDSA(const std::string &selected) {
  392. return SpeedECDSACurve("ECDSA P-224", NID_secp224r1, selected) &&
  393. SpeedECDSACurve("ECDSA P-256", NID_X9_62_prime256v1, selected) &&
  394. SpeedECDSACurve("ECDSA P-384", NID_secp384r1, selected) &&
  395. SpeedECDSACurve("ECDSA P-521", NID_secp521r1, selected);
  396. }
  397. static bool Speed25519(const std::string &selected) {
  398. if (!selected.empty() && selected.find("25519") == std::string::npos) {
  399. return true;
  400. }
  401. TimeResults results;
  402. uint8_t public_key[32], private_key[64];
  403. if (!TimeFunction(&results, [&public_key, &private_key]() -> bool {
  404. ED25519_keypair(public_key, private_key);
  405. return true;
  406. })) {
  407. return false;
  408. }
  409. results.Print("Ed25519 key generation");
  410. static const uint8_t kMessage[] = {0, 1, 2, 3, 4, 5};
  411. uint8_t signature[64];
  412. if (!TimeFunction(&results, [&private_key, &signature]() -> bool {
  413. return ED25519_sign(signature, kMessage, sizeof(kMessage),
  414. private_key) == 1;
  415. })) {
  416. return false;
  417. }
  418. results.Print("Ed25519 signing");
  419. if (!TimeFunction(&results, [&public_key, &signature]() -> bool {
  420. return ED25519_verify(kMessage, sizeof(kMessage), signature,
  421. public_key) == 1;
  422. })) {
  423. fprintf(stderr, "Ed25519 verify failed.\n");
  424. return false;
  425. }
  426. results.Print("Ed25519 verify");
  427. if (!TimeFunction(&results, []() -> bool {
  428. uint8_t out[32], in[32];
  429. OPENSSL_memset(in, 0, sizeof(in));
  430. X25519_public_from_private(out, in);
  431. return true;
  432. })) {
  433. fprintf(stderr, "Curve25519 base-point multiplication failed.\n");
  434. return false;
  435. }
  436. results.Print("Curve25519 base-point multiplication");
  437. if (!TimeFunction(&results, []() -> bool {
  438. uint8_t out[32], in1[32], in2[32];
  439. OPENSSL_memset(in1, 0, sizeof(in1));
  440. OPENSSL_memset(in2, 0, sizeof(in2));
  441. in1[0] = 1;
  442. in2[0] = 9;
  443. return X25519(out, in1, in2) == 1;
  444. })) {
  445. fprintf(stderr, "Curve25519 arbitrary point multiplication failed.\n");
  446. return false;
  447. }
  448. results.Print("Curve25519 arbitrary point multiplication");
  449. return true;
  450. }
  451. static bool SpeedSPAKE2(const std::string &selected) {
  452. if (!selected.empty() && selected.find("SPAKE2") == std::string::npos) {
  453. return true;
  454. }
  455. TimeResults results;
  456. static const uint8_t kAliceName[] = {'A'};
  457. static const uint8_t kBobName[] = {'B'};
  458. static const uint8_t kPassword[] = "password";
  459. bssl::UniquePtr<SPAKE2_CTX> alice(SPAKE2_CTX_new(spake2_role_alice,
  460. kAliceName, sizeof(kAliceName), kBobName,
  461. sizeof(kBobName)));
  462. uint8_t alice_msg[SPAKE2_MAX_MSG_SIZE];
  463. size_t alice_msg_len;
  464. if (!SPAKE2_generate_msg(alice.get(), alice_msg, &alice_msg_len,
  465. sizeof(alice_msg),
  466. kPassword, sizeof(kPassword))) {
  467. fprintf(stderr, "SPAKE2_generate_msg failed.\n");
  468. return false;
  469. }
  470. if (!TimeFunction(&results, [&alice_msg, alice_msg_len]() -> bool {
  471. bssl::UniquePtr<SPAKE2_CTX> bob(SPAKE2_CTX_new(spake2_role_bob,
  472. kBobName, sizeof(kBobName), kAliceName,
  473. sizeof(kAliceName)));
  474. uint8_t bob_msg[SPAKE2_MAX_MSG_SIZE], bob_key[64];
  475. size_t bob_msg_len, bob_key_len;
  476. if (!SPAKE2_generate_msg(bob.get(), bob_msg, &bob_msg_len,
  477. sizeof(bob_msg), kPassword,
  478. sizeof(kPassword)) ||
  479. !SPAKE2_process_msg(bob.get(), bob_key, &bob_key_len,
  480. sizeof(bob_key), alice_msg, alice_msg_len)) {
  481. return false;
  482. }
  483. return true;
  484. })) {
  485. fprintf(stderr, "SPAKE2 failed.\n");
  486. }
  487. results.Print("SPAKE2 over Ed25519");
  488. return true;
  489. }
  490. static bool SpeedScrypt(const std::string &selected) {
  491. if (!selected.empty() && selected.find("scrypt") == std::string::npos) {
  492. return true;
  493. }
  494. TimeResults results;
  495. static const char kPassword[] = "password";
  496. static const uint8_t kSalt[] = "NaCl";
  497. if (!TimeFunction(&results, [&]() -> bool {
  498. uint8_t out[64];
  499. return !!EVP_PBE_scrypt(kPassword, sizeof(kPassword) - 1, kSalt,
  500. sizeof(kSalt) - 1, 1024, 8, 16, 0 /* max_mem */,
  501. out, sizeof(out));
  502. })) {
  503. fprintf(stderr, "scrypt failed.\n");
  504. return false;
  505. }
  506. results.Print("scrypt (N = 1024, r = 8, p = 16)");
  507. if (!TimeFunction(&results, [&]() -> bool {
  508. uint8_t out[64];
  509. return !!EVP_PBE_scrypt(kPassword, sizeof(kPassword) - 1, kSalt,
  510. sizeof(kSalt) - 1, 16384, 8, 1, 0 /* max_mem */,
  511. out, sizeof(out));
  512. })) {
  513. fprintf(stderr, "scrypt failed.\n");
  514. return false;
  515. }
  516. results.Print("scrypt (N = 16384, r = 8, p = 1)");
  517. return true;
  518. }
  519. static const struct argument kArguments[] = {
  520. {
  521. "-filter", kOptionalArgument,
  522. "A filter on the speed tests to run",
  523. },
  524. {
  525. "-timeout", kOptionalArgument,
  526. "The number of seconds to run each test for (default is 1)",
  527. },
  528. {
  529. "", kOptionalArgument, "",
  530. },
  531. };
  532. bool Speed(const std::vector<std::string> &args) {
  533. std::map<std::string, std::string> args_map;
  534. if (!ParseKeyValueArguments(&args_map, args, kArguments)) {
  535. PrintUsage(kArguments);
  536. return false;
  537. }
  538. std::string selected;
  539. if (args_map.count("-filter") != 0) {
  540. selected = args_map["-filter"];
  541. }
  542. if (args_map.count("-timeout") != 0) {
  543. g_timeout_seconds = atoi(args_map["-timeout"].c_str());
  544. }
  545. bssl::UniquePtr<RSA> key(
  546. RSA_private_key_from_bytes(kDERRSAPrivate2048, kDERRSAPrivate2048Len));
  547. if (key == nullptr) {
  548. fprintf(stderr, "Failed to parse RSA key.\n");
  549. ERR_print_errors_fp(stderr);
  550. return false;
  551. }
  552. if (!SpeedRSA("RSA 2048", key.get(), selected)) {
  553. return false;
  554. }
  555. key.reset(
  556. RSA_private_key_from_bytes(kDERRSAPrivate4096, kDERRSAPrivate4096Len));
  557. if (key == nullptr) {
  558. fprintf(stderr, "Failed to parse 4096-bit RSA key.\n");
  559. ERR_print_errors_fp(stderr);
  560. return 1;
  561. }
  562. if (!SpeedRSA("RSA 4096", key.get(), selected)) {
  563. return false;
  564. }
  565. key.reset();
  566. // kTLSADLen is the number of bytes of additional data that TLS passes to
  567. // AEADs.
  568. static const size_t kTLSADLen = 13;
  569. // kLegacyADLen is the number of bytes that TLS passes to the "legacy" AEADs.
  570. // These are AEADs that weren't originally defined as AEADs, but which we use
  571. // via the AEAD interface. In order for that to work, they have some TLS
  572. // knowledge in them and construct a couple of the AD bytes internally.
  573. static const size_t kLegacyADLen = kTLSADLen - 2;
  574. if (!SpeedAEAD(EVP_aead_aes_128_gcm(), "AES-128-GCM", kTLSADLen, selected) ||
  575. !SpeedAEAD(EVP_aead_aes_256_gcm(), "AES-256-GCM", kTLSADLen, selected) ||
  576. !SpeedAEAD(EVP_aead_chacha20_poly1305(), "ChaCha20-Poly1305", kTLSADLen,
  577. selected) ||
  578. !SpeedAEAD(EVP_aead_des_ede3_cbc_sha1_tls(), "DES-EDE3-CBC-SHA1",
  579. kLegacyADLen, selected) ||
  580. !SpeedAEAD(EVP_aead_aes_128_cbc_sha1_tls(), "AES-128-CBC-SHA1",
  581. kLegacyADLen, selected) ||
  582. !SpeedAEAD(EVP_aead_aes_256_cbc_sha1_tls(), "AES-256-CBC-SHA1",
  583. kLegacyADLen, selected) ||
  584. !SpeedAEAD(EVP_aead_aes_128_gcm_siv(), "AES-128-GCM-SIV", kTLSADLen,
  585. selected) ||
  586. !SpeedAEAD(EVP_aead_aes_256_gcm_siv(), "AES-256-GCM-SIV", kTLSADLen,
  587. selected) ||
  588. !SpeedAEADOpen(EVP_aead_aes_128_gcm_siv(), "AES-128-GCM-SIV", kTLSADLen,
  589. selected) ||
  590. !SpeedAEADOpen(EVP_aead_aes_256_gcm_siv(), "AES-256-GCM-SIV", kTLSADLen,
  591. selected) ||
  592. !SpeedHash(EVP_sha1(), "SHA-1", selected) ||
  593. !SpeedHash(EVP_sha256(), "SHA-256", selected) ||
  594. !SpeedHash(EVP_sha512(), "SHA-512", selected) ||
  595. !SpeedRandom(selected) ||
  596. !SpeedECDH(selected) ||
  597. !SpeedECDSA(selected) ||
  598. !Speed25519(selected) ||
  599. !SpeedSPAKE2(selected) ||
  600. !SpeedScrypt(selected)) {
  601. return false;
  602. }
  603. return true;
  604. }