1d9e397b599b13d642138480a28c14db7a136bf0Adam Langley/* Copyright (c) 2014, Google Inc.
2d9e397b599b13d642138480a28c14db7a136bf0Adam Langley *
3d9e397b599b13d642138480a28c14db7a136bf0Adam Langley * Permission to use, copy, modify, and/or distribute this software for any
4d9e397b599b13d642138480a28c14db7a136bf0Adam Langley * purpose with or without fee is hereby granted, provided that the above
5d9e397b599b13d642138480a28c14db7a136bf0Adam Langley * copyright notice and this permission notice appear in all copies.
6d9e397b599b13d642138480a28c14db7a136bf0Adam Langley *
7d9e397b599b13d642138480a28c14db7a136bf0Adam Langley * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
8d9e397b599b13d642138480a28c14db7a136bf0Adam Langley * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
9d9e397b599b13d642138480a28c14db7a136bf0Adam Langley * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
10d9e397b599b13d642138480a28c14db7a136bf0Adam Langley * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
11d9e397b599b13d642138480a28c14db7a136bf0Adam Langley * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
12d9e397b599b13d642138480a28c14db7a136bf0Adam Langley * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
13d9e397b599b13d642138480a28c14db7a136bf0Adam Langley * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */
14d9e397b599b13d642138480a28c14db7a136bf0Adam Langley
15d9e397b599b13d642138480a28c14db7a136bf0Adam Langley#include <string>
16d9e397b599b13d642138480a28c14db7a136bf0Adam Langley#include <functional>
17d9e397b599b13d642138480a28c14db7a136bf0Adam Langley#include <memory>
18d9e397b599b13d642138480a28c14db7a136bf0Adam Langley#include <vector>
19d9e397b599b13d642138480a28c14db7a136bf0Adam Langley
20d9e397b599b13d642138480a28c14db7a136bf0Adam Langley#include <stdint.h>
21d9e397b599b13d642138480a28c14db7a136bf0Adam Langley#include <string.h>
22d9e397b599b13d642138480a28c14db7a136bf0Adam Langley
23d9e397b599b13d642138480a28c14db7a136bf0Adam Langley#include <openssl/aead.h>
24d9e397b599b13d642138480a28c14db7a136bf0Adam Langley#include <openssl/digest.h>
25e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley#include <openssl/err.h>
26d9e397b599b13d642138480a28c14db7a136bf0Adam Langley#include <openssl/obj.h>
27e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley#include <openssl/rand.h>
28d9e397b599b13d642138480a28c14db7a136bf0Adam Langley#include <openssl/rsa.h>
29d9e397b599b13d642138480a28c14db7a136bf0Adam Langley
30d9e397b599b13d642138480a28c14db7a136bf0Adam Langley#if defined(OPENSSL_WINDOWS)
31d9e397b599b13d642138480a28c14db7a136bf0Adam Langley#pragma warning(push, 3)
32ac6c5371f5e5beafc345f312a097c3ebd4766afaKenny Root#include <windows.h>
33d9e397b599b13d642138480a28c14db7a136bf0Adam Langley#pragma warning(pop)
34d9e397b599b13d642138480a28c14db7a136bf0Adam Langley#elif defined(OPENSSL_APPLE)
35d9e397b599b13d642138480a28c14db7a136bf0Adam Langley#include <sys/time.h>
36d9e397b599b13d642138480a28c14db7a136bf0Adam Langley#endif
37d9e397b599b13d642138480a28c14db7a136bf0Adam Langley
38e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley#include "../crypto/test/scoped_types.h"
39e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley
40d9e397b599b13d642138480a28c14db7a136bf0Adam Langley
41d9e397b599b13d642138480a28c14db7a136bf0Adam Langleyextern "C" {
42d9e397b599b13d642138480a28c14db7a136bf0Adam Langley// These values are DER encoded, RSA private keys.
43d9e397b599b13d642138480a28c14db7a136bf0Adam Langleyextern const uint8_t kDERRSAPrivate2048[];
44d9e397b599b13d642138480a28c14db7a136bf0Adam Langleyextern size_t kDERRSAPrivate2048Len;
45d9e397b599b13d642138480a28c14db7a136bf0Adam Langleyextern const uint8_t kDERRSAPrivate4096[];
46d9e397b599b13d642138480a28c14db7a136bf0Adam Langleyextern size_t kDERRSAPrivate4096Len;
47d9e397b599b13d642138480a28c14db7a136bf0Adam Langley}
48d9e397b599b13d642138480a28c14db7a136bf0Adam Langley
49d9e397b599b13d642138480a28c14db7a136bf0Adam Langley// TimeResults represents the results of benchmarking a function.
50d9e397b599b13d642138480a28c14db7a136bf0Adam Langleystruct TimeResults {
51d9e397b599b13d642138480a28c14db7a136bf0Adam Langley  // num_calls is the number of function calls done in the time period.
52d9e397b599b13d642138480a28c14db7a136bf0Adam Langley  unsigned num_calls;
53d9e397b599b13d642138480a28c14db7a136bf0Adam Langley  // us is the number of microseconds that elapsed in the time period.
54d9e397b599b13d642138480a28c14db7a136bf0Adam Langley  unsigned us;
55d9e397b599b13d642138480a28c14db7a136bf0Adam Langley
56d9e397b599b13d642138480a28c14db7a136bf0Adam Langley  void Print(const std::string &description) {
57d9e397b599b13d642138480a28c14db7a136bf0Adam Langley    printf("Did %u %s operations in %uus (%.1f ops/sec)\n", num_calls,
58d9e397b599b13d642138480a28c14db7a136bf0Adam Langley           description.c_str(), us,
59d9e397b599b13d642138480a28c14db7a136bf0Adam Langley           (static_cast<double>(num_calls) / us) * 1000000);
60d9e397b599b13d642138480a28c14db7a136bf0Adam Langley  }
61d9e397b599b13d642138480a28c14db7a136bf0Adam Langley
62d9e397b599b13d642138480a28c14db7a136bf0Adam Langley  void PrintWithBytes(const std::string &description, size_t bytes_per_call) {
63d9e397b599b13d642138480a28c14db7a136bf0Adam Langley    printf("Did %u %s operations in %uus (%.1f ops/sec): %.1f MB/s\n",
64d9e397b599b13d642138480a28c14db7a136bf0Adam Langley           num_calls, description.c_str(), us,
65d9e397b599b13d642138480a28c14db7a136bf0Adam Langley           (static_cast<double>(num_calls) / us) * 1000000,
66d9e397b599b13d642138480a28c14db7a136bf0Adam Langley           static_cast<double>(bytes_per_call * num_calls) / us);
67d9e397b599b13d642138480a28c14db7a136bf0Adam Langley  }
68d9e397b599b13d642138480a28c14db7a136bf0Adam Langley};
69d9e397b599b13d642138480a28c14db7a136bf0Adam Langley
70d9e397b599b13d642138480a28c14db7a136bf0Adam Langley#if defined(OPENSSL_WINDOWS)
71d9e397b599b13d642138480a28c14db7a136bf0Adam Langleystatic uint64_t time_now() { return GetTickCount64() * 1000; }
72d9e397b599b13d642138480a28c14db7a136bf0Adam Langley#elif defined(OPENSSL_APPLE)
73d9e397b599b13d642138480a28c14db7a136bf0Adam Langleystatic uint64_t time_now() {
74d9e397b599b13d642138480a28c14db7a136bf0Adam Langley  struct timeval tv;
75d9e397b599b13d642138480a28c14db7a136bf0Adam Langley  uint64_t ret;
76d9e397b599b13d642138480a28c14db7a136bf0Adam Langley
77d9e397b599b13d642138480a28c14db7a136bf0Adam Langley  gettimeofday(&tv, NULL);
78d9e397b599b13d642138480a28c14db7a136bf0Adam Langley  ret = tv.tv_sec;
79d9e397b599b13d642138480a28c14db7a136bf0Adam Langley  ret *= 1000000;
80d9e397b599b13d642138480a28c14db7a136bf0Adam Langley  ret += tv.tv_usec;
81d9e397b599b13d642138480a28c14db7a136bf0Adam Langley  return ret;
82d9e397b599b13d642138480a28c14db7a136bf0Adam Langley}
83d9e397b599b13d642138480a28c14db7a136bf0Adam Langley#else
84d9e397b599b13d642138480a28c14db7a136bf0Adam Langleystatic uint64_t time_now() {
85d9e397b599b13d642138480a28c14db7a136bf0Adam Langley  struct timespec ts;
86d9e397b599b13d642138480a28c14db7a136bf0Adam Langley  clock_gettime(CLOCK_MONOTONIC, &ts);
87d9e397b599b13d642138480a28c14db7a136bf0Adam Langley
88d9e397b599b13d642138480a28c14db7a136bf0Adam Langley  uint64_t ret = ts.tv_sec;
89d9e397b599b13d642138480a28c14db7a136bf0Adam Langley  ret *= 1000000;
90d9e397b599b13d642138480a28c14db7a136bf0Adam Langley  ret += ts.tv_nsec / 1000;
91d9e397b599b13d642138480a28c14db7a136bf0Adam Langley  return ret;
92d9e397b599b13d642138480a28c14db7a136bf0Adam Langley}
93d9e397b599b13d642138480a28c14db7a136bf0Adam Langley#endif
94d9e397b599b13d642138480a28c14db7a136bf0Adam Langley
95d9e397b599b13d642138480a28c14db7a136bf0Adam Langleystatic bool TimeFunction(TimeResults *results, std::function<bool()> func) {
96d9e397b599b13d642138480a28c14db7a136bf0Adam Langley  // kTotalMS is the total amount of time that we'll aim to measure a function
97d9e397b599b13d642138480a28c14db7a136bf0Adam Langley  // for.
98e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley  static const uint64_t kTotalUS = 1000000;
99d9e397b599b13d642138480a28c14db7a136bf0Adam Langley  uint64_t start = time_now(), now, delta;
100d9e397b599b13d642138480a28c14db7a136bf0Adam Langley  unsigned done = 0, iterations_between_time_checks;
101d9e397b599b13d642138480a28c14db7a136bf0Adam Langley
102d9e397b599b13d642138480a28c14db7a136bf0Adam Langley  if (!func()) {
103d9e397b599b13d642138480a28c14db7a136bf0Adam Langley    return false;
104d9e397b599b13d642138480a28c14db7a136bf0Adam Langley  }
105d9e397b599b13d642138480a28c14db7a136bf0Adam Langley  now = time_now();
106d9e397b599b13d642138480a28c14db7a136bf0Adam Langley  delta = now - start;
107d9e397b599b13d642138480a28c14db7a136bf0Adam Langley  if (delta == 0) {
108d9e397b599b13d642138480a28c14db7a136bf0Adam Langley    iterations_between_time_checks = 250;
109d9e397b599b13d642138480a28c14db7a136bf0Adam Langley  } else {
110d9e397b599b13d642138480a28c14db7a136bf0Adam Langley    // Aim for about 100ms between time checks.
111d9e397b599b13d642138480a28c14db7a136bf0Adam Langley    iterations_between_time_checks =
112d9e397b599b13d642138480a28c14db7a136bf0Adam Langley        static_cast<double>(100000) / static_cast<double>(delta);
113d9e397b599b13d642138480a28c14db7a136bf0Adam Langley    if (iterations_between_time_checks > 1000) {
114d9e397b599b13d642138480a28c14db7a136bf0Adam Langley      iterations_between_time_checks = 1000;
115d9e397b599b13d642138480a28c14db7a136bf0Adam Langley    } else if (iterations_between_time_checks < 1) {
116d9e397b599b13d642138480a28c14db7a136bf0Adam Langley      iterations_between_time_checks = 1;
117d9e397b599b13d642138480a28c14db7a136bf0Adam Langley    }
118d9e397b599b13d642138480a28c14db7a136bf0Adam Langley  }
119d9e397b599b13d642138480a28c14db7a136bf0Adam Langley
120d9e397b599b13d642138480a28c14db7a136bf0Adam Langley  for (;;) {
121d9e397b599b13d642138480a28c14db7a136bf0Adam Langley    for (unsigned i = 0; i < iterations_between_time_checks; i++) {
122d9e397b599b13d642138480a28c14db7a136bf0Adam Langley      if (!func()) {
123d9e397b599b13d642138480a28c14db7a136bf0Adam Langley        return false;
124d9e397b599b13d642138480a28c14db7a136bf0Adam Langley      }
125d9e397b599b13d642138480a28c14db7a136bf0Adam Langley      done++;
126d9e397b599b13d642138480a28c14db7a136bf0Adam Langley    }
127d9e397b599b13d642138480a28c14db7a136bf0Adam Langley
128d9e397b599b13d642138480a28c14db7a136bf0Adam Langley    now = time_now();
129d9e397b599b13d642138480a28c14db7a136bf0Adam Langley    if (now - start > kTotalUS) {
130d9e397b599b13d642138480a28c14db7a136bf0Adam Langley      break;
131d9e397b599b13d642138480a28c14db7a136bf0Adam Langley    }
132d9e397b599b13d642138480a28c14db7a136bf0Adam Langley  }
133d9e397b599b13d642138480a28c14db7a136bf0Adam Langley
134d9e397b599b13d642138480a28c14db7a136bf0Adam Langley  results->us = now - start;
135d9e397b599b13d642138480a28c14db7a136bf0Adam Langley  results->num_calls = done;
136d9e397b599b13d642138480a28c14db7a136bf0Adam Langley  return true;
137d9e397b599b13d642138480a28c14db7a136bf0Adam Langley}
138d9e397b599b13d642138480a28c14db7a136bf0Adam Langley
139e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langleystatic bool SpeedRSA(const std::string &key_name, RSA *key,
140e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley                     const std::string &selected) {
141e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley  if (!selected.empty() && key_name.find(selected) == std::string::npos) {
142e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley    return true;
143e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley  }
144d9e397b599b13d642138480a28c14db7a136bf0Adam Langley
145d9e397b599b13d642138480a28c14db7a136bf0Adam Langley  std::unique_ptr<uint8_t[]> sig(new uint8_t[RSA_size(key)]);
146d9e397b599b13d642138480a28c14db7a136bf0Adam Langley  const uint8_t fake_sha256_hash[32] = {0};
147d9e397b599b13d642138480a28c14db7a136bf0Adam Langley  unsigned sig_len;
148d9e397b599b13d642138480a28c14db7a136bf0Adam Langley
149e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley  TimeResults results;
150d9e397b599b13d642138480a28c14db7a136bf0Adam Langley  if (!TimeFunction(&results,
151d9e397b599b13d642138480a28c14db7a136bf0Adam Langley                    [key, &sig, &fake_sha256_hash, &sig_len]() -> bool {
152d9e397b599b13d642138480a28c14db7a136bf0Adam Langley        return RSA_sign(NID_sha256, fake_sha256_hash, sizeof(fake_sha256_hash),
153d9e397b599b13d642138480a28c14db7a136bf0Adam Langley                        sig.get(), &sig_len, key);
154d9e397b599b13d642138480a28c14db7a136bf0Adam Langley      })) {
155d9e397b599b13d642138480a28c14db7a136bf0Adam Langley    fprintf(stderr, "RSA_sign failed.\n");
156e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley    ERR_print_errors_fp(stderr);
157d9e397b599b13d642138480a28c14db7a136bf0Adam Langley    return false;
158d9e397b599b13d642138480a28c14db7a136bf0Adam Langley  }
159d9e397b599b13d642138480a28c14db7a136bf0Adam Langley  results.Print(key_name + " signing");
160d9e397b599b13d642138480a28c14db7a136bf0Adam Langley
161d9e397b599b13d642138480a28c14db7a136bf0Adam Langley  if (!TimeFunction(&results,
162d9e397b599b13d642138480a28c14db7a136bf0Adam Langley                    [key, &fake_sha256_hash, &sig, sig_len]() -> bool {
163d9e397b599b13d642138480a28c14db7a136bf0Adam Langley        return RSA_verify(NID_sha256, fake_sha256_hash,
164d9e397b599b13d642138480a28c14db7a136bf0Adam Langley                          sizeof(fake_sha256_hash), sig.get(), sig_len, key);
165d9e397b599b13d642138480a28c14db7a136bf0Adam Langley      })) {
166d9e397b599b13d642138480a28c14db7a136bf0Adam Langley    fprintf(stderr, "RSA_verify failed.\n");
167e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley    ERR_print_errors_fp(stderr);
168d9e397b599b13d642138480a28c14db7a136bf0Adam Langley    return false;
169d9e397b599b13d642138480a28c14db7a136bf0Adam Langley  }
170d9e397b599b13d642138480a28c14db7a136bf0Adam Langley  results.Print(key_name + " verify");
171d9e397b599b13d642138480a28c14db7a136bf0Adam Langley
172d9e397b599b13d642138480a28c14db7a136bf0Adam Langley  return true;
173d9e397b599b13d642138480a28c14db7a136bf0Adam Langley}
174d9e397b599b13d642138480a28c14db7a136bf0Adam Langley
175d9e397b599b13d642138480a28c14db7a136bf0Adam Langleystatic uint8_t *align(uint8_t *in, unsigned alignment) {
176d9e397b599b13d642138480a28c14db7a136bf0Adam Langley  return reinterpret_cast<uint8_t *>(
177e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley      (reinterpret_cast<uintptr_t>(in) + alignment) &
178e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley      ~static_cast<size_t>(alignment - 1));
179d9e397b599b13d642138480a28c14db7a136bf0Adam Langley}
180d9e397b599b13d642138480a28c14db7a136bf0Adam Langley
181d9e397b599b13d642138480a28c14db7a136bf0Adam Langleystatic bool SpeedAEADChunk(const EVP_AEAD *aead, const std::string &name,
182d9e397b599b13d642138480a28c14db7a136bf0Adam Langley                           size_t chunk_len, size_t ad_len) {
183d9e397b599b13d642138480a28c14db7a136bf0Adam Langley  static const unsigned kAlignment = 16;
184d9e397b599b13d642138480a28c14db7a136bf0Adam Langley
185d9e397b599b13d642138480a28c14db7a136bf0Adam Langley  EVP_AEAD_CTX ctx;
186d9e397b599b13d642138480a28c14db7a136bf0Adam Langley  const size_t key_len = EVP_AEAD_key_length(aead);
187d9e397b599b13d642138480a28c14db7a136bf0Adam Langley  const size_t nonce_len = EVP_AEAD_nonce_length(aead);
188d9e397b599b13d642138480a28c14db7a136bf0Adam Langley  const size_t overhead_len = EVP_AEAD_max_overhead(aead);
189d9e397b599b13d642138480a28c14db7a136bf0Adam Langley
190d9e397b599b13d642138480a28c14db7a136bf0Adam Langley  std::unique_ptr<uint8_t[]> key(new uint8_t[key_len]);
191d9e397b599b13d642138480a28c14db7a136bf0Adam Langley  memset(key.get(), 0, key_len);
192d9e397b599b13d642138480a28c14db7a136bf0Adam Langley  std::unique_ptr<uint8_t[]> nonce(new uint8_t[nonce_len]);
193d9e397b599b13d642138480a28c14db7a136bf0Adam Langley  memset(nonce.get(), 0, nonce_len);
194e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley  std::unique_ptr<uint8_t[]> in_storage(new uint8_t[chunk_len + kAlignment]);
195e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley  std::unique_ptr<uint8_t[]> out_storage(new uint8_t[chunk_len + overhead_len + kAlignment]);
196d9e397b599b13d642138480a28c14db7a136bf0Adam Langley  std::unique_ptr<uint8_t[]> ad(new uint8_t[ad_len]);
197d9e397b599b13d642138480a28c14db7a136bf0Adam Langley  memset(ad.get(), 0, ad_len);
198d9e397b599b13d642138480a28c14db7a136bf0Adam Langley
199d9e397b599b13d642138480a28c14db7a136bf0Adam Langley  uint8_t *const in = align(in_storage.get(), kAlignment);
200d9e397b599b13d642138480a28c14db7a136bf0Adam Langley  memset(in, 0, chunk_len);
201d9e397b599b13d642138480a28c14db7a136bf0Adam Langley  uint8_t *const out = align(out_storage.get(), kAlignment);
202d9e397b599b13d642138480a28c14db7a136bf0Adam Langley  memset(out, 0, chunk_len + overhead_len);
203d9e397b599b13d642138480a28c14db7a136bf0Adam Langley
204e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley  if (!EVP_AEAD_CTX_init_with_direction(&ctx, aead, key.get(), key_len,
205e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley                                        EVP_AEAD_DEFAULT_TAG_LENGTH,
206e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley                                        evp_aead_seal)) {
207d9e397b599b13d642138480a28c14db7a136bf0Adam Langley    fprintf(stderr, "Failed to create EVP_AEAD_CTX.\n");
208e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley    ERR_print_errors_fp(stderr);
209d9e397b599b13d642138480a28c14db7a136bf0Adam Langley    return false;
210d9e397b599b13d642138480a28c14db7a136bf0Adam Langley  }
211d9e397b599b13d642138480a28c14db7a136bf0Adam Langley
212d9e397b599b13d642138480a28c14db7a136bf0Adam Langley  TimeResults results;
213d9e397b599b13d642138480a28c14db7a136bf0Adam Langley  if (!TimeFunction(&results, [chunk_len, overhead_len, nonce_len, ad_len, in,
214d9e397b599b13d642138480a28c14db7a136bf0Adam Langley                               out, &ctx, &nonce, &ad]() -> bool {
215d9e397b599b13d642138480a28c14db7a136bf0Adam Langley        size_t out_len;
216d9e397b599b13d642138480a28c14db7a136bf0Adam Langley
217d9e397b599b13d642138480a28c14db7a136bf0Adam Langley        return EVP_AEAD_CTX_seal(
218d9e397b599b13d642138480a28c14db7a136bf0Adam Langley            &ctx, out, &out_len, chunk_len + overhead_len, nonce.get(),
219d9e397b599b13d642138480a28c14db7a136bf0Adam Langley            nonce_len, in, chunk_len, ad.get(), ad_len);
220d9e397b599b13d642138480a28c14db7a136bf0Adam Langley      })) {
221d9e397b599b13d642138480a28c14db7a136bf0Adam Langley    fprintf(stderr, "EVP_AEAD_CTX_seal failed.\n");
222e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley    ERR_print_errors_fp(stderr);
223d9e397b599b13d642138480a28c14db7a136bf0Adam Langley    return false;
224d9e397b599b13d642138480a28c14db7a136bf0Adam Langley  }
225d9e397b599b13d642138480a28c14db7a136bf0Adam Langley
226d9e397b599b13d642138480a28c14db7a136bf0Adam Langley  results.PrintWithBytes(name + " seal", chunk_len);
227d9e397b599b13d642138480a28c14db7a136bf0Adam Langley
228d9e397b599b13d642138480a28c14db7a136bf0Adam Langley  EVP_AEAD_CTX_cleanup(&ctx);
229d9e397b599b13d642138480a28c14db7a136bf0Adam Langley
230d9e397b599b13d642138480a28c14db7a136bf0Adam Langley  return true;
231d9e397b599b13d642138480a28c14db7a136bf0Adam Langley}
232d9e397b599b13d642138480a28c14db7a136bf0Adam Langley
233d9e397b599b13d642138480a28c14db7a136bf0Adam Langleystatic bool SpeedAEAD(const EVP_AEAD *aead, const std::string &name,
234e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley                      size_t ad_len, const std::string &selected) {
235e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley  if (!selected.empty() && name.find(selected) == std::string::npos) {
236e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley    return true;
237e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley  }
238e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley
239d9e397b599b13d642138480a28c14db7a136bf0Adam Langley  return SpeedAEADChunk(aead, name + " (16 bytes)", 16, ad_len) &&
240d9e397b599b13d642138480a28c14db7a136bf0Adam Langley         SpeedAEADChunk(aead, name + " (1350 bytes)", 1350, ad_len) &&
241d9e397b599b13d642138480a28c14db7a136bf0Adam Langley         SpeedAEADChunk(aead, name + " (8192 bytes)", 8192, ad_len);
242d9e397b599b13d642138480a28c14db7a136bf0Adam Langley}
243d9e397b599b13d642138480a28c14db7a136bf0Adam Langley
244d9e397b599b13d642138480a28c14db7a136bf0Adam Langleystatic bool SpeedHashChunk(const EVP_MD *md, const std::string &name,
245d9e397b599b13d642138480a28c14db7a136bf0Adam Langley                           size_t chunk_len) {
246d9e397b599b13d642138480a28c14db7a136bf0Adam Langley  EVP_MD_CTX *ctx = EVP_MD_CTX_create();
247d9e397b599b13d642138480a28c14db7a136bf0Adam Langley  uint8_t scratch[8192];
248d9e397b599b13d642138480a28c14db7a136bf0Adam Langley
249d9e397b599b13d642138480a28c14db7a136bf0Adam Langley  if (chunk_len > sizeof(scratch)) {
250d9e397b599b13d642138480a28c14db7a136bf0Adam Langley    return false;
251d9e397b599b13d642138480a28c14db7a136bf0Adam Langley  }
252d9e397b599b13d642138480a28c14db7a136bf0Adam Langley
253d9e397b599b13d642138480a28c14db7a136bf0Adam Langley  TimeResults results;
254d9e397b599b13d642138480a28c14db7a136bf0Adam Langley  if (!TimeFunction(&results, [ctx, md, chunk_len, &scratch]() -> bool {
255d9e397b599b13d642138480a28c14db7a136bf0Adam Langley        uint8_t digest[EVP_MAX_MD_SIZE];
256d9e397b599b13d642138480a28c14db7a136bf0Adam Langley        unsigned int md_len;
257d9e397b599b13d642138480a28c14db7a136bf0Adam Langley
258d9e397b599b13d642138480a28c14db7a136bf0Adam Langley        return EVP_DigestInit_ex(ctx, md, NULL /* ENGINE */) &&
259d9e397b599b13d642138480a28c14db7a136bf0Adam Langley               EVP_DigestUpdate(ctx, scratch, chunk_len) &&
260d9e397b599b13d642138480a28c14db7a136bf0Adam Langley               EVP_DigestFinal_ex(ctx, digest, &md_len);
261d9e397b599b13d642138480a28c14db7a136bf0Adam Langley      })) {
262d9e397b599b13d642138480a28c14db7a136bf0Adam Langley    fprintf(stderr, "EVP_DigestInit_ex failed.\n");
263e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley    ERR_print_errors_fp(stderr);
264d9e397b599b13d642138480a28c14db7a136bf0Adam Langley    return false;
265d9e397b599b13d642138480a28c14db7a136bf0Adam Langley  }
266d9e397b599b13d642138480a28c14db7a136bf0Adam Langley
267d9e397b599b13d642138480a28c14db7a136bf0Adam Langley  results.PrintWithBytes(name, chunk_len);
268d9e397b599b13d642138480a28c14db7a136bf0Adam Langley
269d9e397b599b13d642138480a28c14db7a136bf0Adam Langley  EVP_MD_CTX_destroy(ctx);
270d9e397b599b13d642138480a28c14db7a136bf0Adam Langley
271d9e397b599b13d642138480a28c14db7a136bf0Adam Langley  return true;
272d9e397b599b13d642138480a28c14db7a136bf0Adam Langley}
273e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langleystatic bool SpeedHash(const EVP_MD *md, const std::string &name,
274e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley                      const std::string &selected) {
275e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley  if (!selected.empty() && name.find(selected) == std::string::npos) {
276e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley    return true;
277e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley  }
278e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley
279d9e397b599b13d642138480a28c14db7a136bf0Adam Langley  return SpeedHashChunk(md, name + " (16 bytes)", 16) &&
280d9e397b599b13d642138480a28c14db7a136bf0Adam Langley         SpeedHashChunk(md, name + " (256 bytes)", 256) &&
281d9e397b599b13d642138480a28c14db7a136bf0Adam Langley         SpeedHashChunk(md, name + " (8192 bytes)", 8192);
282d9e397b599b13d642138480a28c14db7a136bf0Adam Langley}
283d9e397b599b13d642138480a28c14db7a136bf0Adam Langley
284e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langleystatic bool SpeedRandomChunk(const std::string name, size_t chunk_len) {
285e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley  uint8_t scratch[8192];
286e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley
287e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley  if (chunk_len > sizeof(scratch)) {
288e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley    return false;
289e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley  }
290e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley
291e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley  TimeResults results;
292e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley  if (!TimeFunction(&results, [chunk_len, &scratch]() -> bool {
293e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley        RAND_bytes(scratch, chunk_len);
294e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley        return true;
295e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley      })) {
296e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley    return false;
297e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley  }
298e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley
299e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley  results.PrintWithBytes(name, chunk_len);
300e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley  return true;
301e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley}
302e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley
303e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langleystatic bool SpeedRandom(const std::string &selected) {
304e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley  if (!selected.empty() && selected != "RNG") {
305e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley    return true;
306e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley  }
307e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley
308e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley  return SpeedRandomChunk("RNG (16 bytes)", 16) &&
309e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley         SpeedRandomChunk("RNG (256 bytes)", 256) &&
310e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley         SpeedRandomChunk("RNG (8192 bytes)", 8192);
311e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley}
312e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley
313e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langleystatic bool SpeedECDHCurve(const std::string &name, int nid,
314e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley                           const std::string &selected) {
315e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley  if (!selected.empty() && name.find(selected) == std::string::npos) {
316e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley    return true;
317e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley  }
318e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley
319e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley  TimeResults results;
320e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley  if (!TimeFunction(&results, [nid]() -> bool {
321e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley        ScopedEC_KEY key(EC_KEY_new_by_curve_name(nid));
322e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley        if (!key ||
323e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley            !EC_KEY_generate_key(key.get())) {
324e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley          return false;
325e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley        }
326e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley        const EC_GROUP *const group = EC_KEY_get0_group(key.get());
327e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley        ScopedEC_POINT point(EC_POINT_new(group));
328e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley        ScopedBN_CTX ctx(BN_CTX_new());
329e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley
330e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley        ScopedBIGNUM x(BN_new());
331e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley        ScopedBIGNUM y(BN_new());
332e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley
333e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley        if (!point || !ctx || !x || !y ||
334e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley            !EC_POINT_mul(group, point.get(), NULL,
335e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley                          EC_KEY_get0_public_key(key.get()),
336e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley                          EC_KEY_get0_private_key(key.get()), ctx.get()) ||
337e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley            !EC_POINT_get_affine_coordinates_GFp(group, point.get(), x.get(),
338e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley                                                 y.get(), ctx.get())) {
339e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley          return false;
340e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley        }
341e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley
342e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley        return true;
343e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley      })) {
344e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley    return false;
345e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley  }
346e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley
347e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley  results.Print(name);
348e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley  return true;
349e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley}
350e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley
351e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langleystatic bool SpeedECDSACurve(const std::string &name, int nid,
352e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley                            const std::string &selected) {
353e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley  if (!selected.empty() && name.find(selected) == std::string::npos) {
354e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley    return true;
355e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley  }
356e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley
357e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley  ScopedEC_KEY key(EC_KEY_new_by_curve_name(nid));
358e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley  if (!key ||
359e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley      !EC_KEY_generate_key(key.get())) {
360e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley    return false;
361e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley  }
362e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley
363e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley  uint8_t signature[256];
364e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley  if (ECDSA_size(key.get()) > sizeof(signature)) {
365e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley    return false;
366e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley  }
367e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley  uint8_t digest[20];
368e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley  memset(digest, 42, sizeof(digest));
369e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley  unsigned sig_len;
370e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley
371e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley  TimeResults results;
372e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley  if (!TimeFunction(&results, [&key, &signature, &digest, &sig_len]() -> bool {
373e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley        return ECDSA_sign(0, digest, sizeof(digest), signature, &sig_len,
374e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley                          key.get()) == 1;
375e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley      })) {
376e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley    return false;
377e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley  }
378e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley
379e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley  results.Print(name + " signing");
380e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley
381e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley  if (!TimeFunction(&results, [&key, &signature, &digest, sig_len]() -> bool {
382e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley        return ECDSA_verify(0, digest, sizeof(digest), signature, sig_len,
383e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley                            key.get()) == 1;
384e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley      })) {
385e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley    return false;
386e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley  }
387e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley
388e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley  results.Print(name + " verify");
389e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley
390e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley  return true;
391e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley}
392e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley
393e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langleystatic bool SpeedECDH(const std::string &selected) {
394e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley  return SpeedECDHCurve("ECDH P-224", NID_secp224r1, selected) &&
395e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley         SpeedECDHCurve("ECDH P-256", NID_X9_62_prime256v1, selected) &&
396e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley         SpeedECDHCurve("ECDH P-384", NID_secp384r1, selected) &&
397e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley         SpeedECDHCurve("ECDH P-521", NID_secp521r1, selected);
398e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley}
399e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley
400e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langleystatic bool SpeedECDSA(const std::string &selected) {
401e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley  return SpeedECDSACurve("ECDSA P-224", NID_secp224r1, selected) &&
402e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley         SpeedECDSACurve("ECDSA P-256", NID_X9_62_prime256v1, selected) &&
403e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley         SpeedECDSACurve("ECDSA P-384", NID_secp384r1, selected) &&
404e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley         SpeedECDSACurve("ECDSA P-521", NID_secp521r1, selected);
405e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley}
406e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley
407e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langleybool Speed(const std::vector<std::string> &args) {
408e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley  std::string selected;
409e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley  if (args.size() > 1) {
410e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley    fprintf(stderr, "Usage: bssl speed [speed test selector, i.e. 'RNG']\n");
411e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley    return false;
412e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley  }
413e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley  if (args.size() > 0) {
414e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley    selected = args[0];
415e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley  }
416d9e397b599b13d642138480a28c14db7a136bf0Adam Langley
417d9e397b599b13d642138480a28c14db7a136bf0Adam Langley  RSA *key = NULL;
418e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley  const uint8_t *inp = kDERRSAPrivate2048;
419d9e397b599b13d642138480a28c14db7a136bf0Adam Langley  if (NULL == d2i_RSAPrivateKey(&key, &inp, kDERRSAPrivate2048Len)) {
420d9e397b599b13d642138480a28c14db7a136bf0Adam Langley    fprintf(stderr, "Failed to parse RSA key.\n");
421e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley    ERR_print_errors_fp(stderr);
422d9e397b599b13d642138480a28c14db7a136bf0Adam Langley    return false;
423d9e397b599b13d642138480a28c14db7a136bf0Adam Langley  }
424d9e397b599b13d642138480a28c14db7a136bf0Adam Langley
425e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley  if (!SpeedRSA("RSA 2048", key, selected)) {
426d9e397b599b13d642138480a28c14db7a136bf0Adam Langley    return false;
427d9e397b599b13d642138480a28c14db7a136bf0Adam Langley  }
428d9e397b599b13d642138480a28c14db7a136bf0Adam Langley
429d9e397b599b13d642138480a28c14db7a136bf0Adam Langley  RSA_free(key);
430d9e397b599b13d642138480a28c14db7a136bf0Adam Langley  key = NULL;
431d9e397b599b13d642138480a28c14db7a136bf0Adam Langley
432d9e397b599b13d642138480a28c14db7a136bf0Adam Langley  inp = kDERRSAPrivate4096;
433d9e397b599b13d642138480a28c14db7a136bf0Adam Langley  if (NULL == d2i_RSAPrivateKey(&key, &inp, kDERRSAPrivate4096Len)) {
434d9e397b599b13d642138480a28c14db7a136bf0Adam Langley    fprintf(stderr, "Failed to parse 4096-bit RSA key.\n");
435e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley    ERR_print_errors_fp(stderr);
436d9e397b599b13d642138480a28c14db7a136bf0Adam Langley    return 1;
437d9e397b599b13d642138480a28c14db7a136bf0Adam Langley  }
438d9e397b599b13d642138480a28c14db7a136bf0Adam Langley
439e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley  if (!SpeedRSA("RSA 4096", key, selected)) {
440d9e397b599b13d642138480a28c14db7a136bf0Adam Langley    return false;
441d9e397b599b13d642138480a28c14db7a136bf0Adam Langley  }
442d9e397b599b13d642138480a28c14db7a136bf0Adam Langley
443d9e397b599b13d642138480a28c14db7a136bf0Adam Langley  RSA_free(key);
444d9e397b599b13d642138480a28c14db7a136bf0Adam Langley
445d9e397b599b13d642138480a28c14db7a136bf0Adam Langley  // kTLSADLen is the number of bytes of additional data that TLS passes to
446d9e397b599b13d642138480a28c14db7a136bf0Adam Langley  // AEADs.
447d9e397b599b13d642138480a28c14db7a136bf0Adam Langley  static const size_t kTLSADLen = 13;
448d9e397b599b13d642138480a28c14db7a136bf0Adam Langley  // kLegacyADLen is the number of bytes that TLS passes to the "legacy" AEADs.
449d9e397b599b13d642138480a28c14db7a136bf0Adam Langley  // These are AEADs that weren't originally defined as AEADs, but which we use
450d9e397b599b13d642138480a28c14db7a136bf0Adam Langley  // via the AEAD interface. In order for that to work, they have some TLS
451d9e397b599b13d642138480a28c14db7a136bf0Adam Langley  // knowledge in them and construct a couple of the AD bytes internally.
452d9e397b599b13d642138480a28c14db7a136bf0Adam Langley  static const size_t kLegacyADLen = kTLSADLen - 2;
453d9e397b599b13d642138480a28c14db7a136bf0Adam Langley
454e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley  if (!SpeedAEAD(EVP_aead_aes_128_gcm(), "AES-128-GCM", kTLSADLen, selected) ||
455e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley      !SpeedAEAD(EVP_aead_aes_256_gcm(), "AES-256-GCM", kTLSADLen, selected) ||
456e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley      !SpeedAEAD(EVP_aead_chacha20_poly1305(), "ChaCha20-Poly1305", kTLSADLen,
457e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley                 selected) ||
458e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley      !SpeedAEAD(EVP_aead_rc4_md5_tls(), "RC4-MD5", kLegacyADLen, selected) ||
459e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley      !SpeedAEAD(EVP_aead_aes_128_cbc_sha1_tls(), "AES-128-CBC-SHA1",
460e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley                 kLegacyADLen, selected) ||
461e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley      !SpeedAEAD(EVP_aead_aes_256_cbc_sha1_tls(), "AES-256-CBC-SHA1",
462e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley                 kLegacyADLen, selected) ||
463e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley      !SpeedHash(EVP_sha1(), "SHA-1", selected) ||
464e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley      !SpeedHash(EVP_sha256(), "SHA-256", selected) ||
465e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley      !SpeedHash(EVP_sha512(), "SHA-512", selected) ||
466e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley      !SpeedRandom(selected) ||
467e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley      !SpeedECDH(selected) ||
468e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley      !SpeedECDSA(selected)) {
469d9e397b599b13d642138480a28c14db7a136bf0Adam Langley    return false;
470d9e397b599b13d642138480a28c14db7a136bf0Adam Langley  }
471d9e397b599b13d642138480a28c14db7a136bf0Adam Langley
472e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley  return true;
473d9e397b599b13d642138480a28c14db7a136bf0Adam Langley}
474