1c5c0c7e85325820eafe78d6d5793a441ce40ec78Adam Langley/* Copyright (c) 2014, Google Inc. 2c5c0c7e85325820eafe78d6d5793a441ce40ec78Adam Langley * 3c5c0c7e85325820eafe78d6d5793a441ce40ec78Adam Langley * Permission to use, copy, modify, and/or distribute this software for any 4c5c0c7e85325820eafe78d6d5793a441ce40ec78Adam Langley * purpose with or without fee is hereby granted, provided that the above 5c5c0c7e85325820eafe78d6d5793a441ce40ec78Adam Langley * copyright notice and this permission notice appear in all copies. 6c5c0c7e85325820eafe78d6d5793a441ce40ec78Adam Langley * 7c5c0c7e85325820eafe78d6d5793a441ce40ec78Adam Langley * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES 8c5c0c7e85325820eafe78d6d5793a441ce40ec78Adam Langley * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 9c5c0c7e85325820eafe78d6d5793a441ce40ec78Adam Langley * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY 10c5c0c7e85325820eafe78d6d5793a441ce40ec78Adam Langley * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 11c5c0c7e85325820eafe78d6d5793a441ce40ec78Adam Langley * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION 12c5c0c7e85325820eafe78d6d5793a441ce40ec78Adam Langley * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN 13c5c0c7e85325820eafe78d6d5793a441ce40ec78Adam Langley * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ 14c5c0c7e85325820eafe78d6d5793a441ce40ec78Adam Langley 15c5c0c7e85325820eafe78d6d5793a441ce40ec78Adam Langley#include <string> 16c5c0c7e85325820eafe78d6d5793a441ce40ec78Adam Langley#include <functional> 17c5c0c7e85325820eafe78d6d5793a441ce40ec78Adam Langley#include <memory> 18c5c0c7e85325820eafe78d6d5793a441ce40ec78Adam Langley#include <vector> 19c5c0c7e85325820eafe78d6d5793a441ce40ec78Adam Langley 20c5c0c7e85325820eafe78d6d5793a441ce40ec78Adam Langley#include <stdint.h> 21c5c0c7e85325820eafe78d6d5793a441ce40ec78Adam Langley#include <time.h> 22c5c0c7e85325820eafe78d6d5793a441ce40ec78Adam Langley 23c5c0c7e85325820eafe78d6d5793a441ce40ec78Adam Langley#include <openssl/aead.h> 24c5c0c7e85325820eafe78d6d5793a441ce40ec78Adam Langley#include <openssl/bio.h> 25006779a02c515e5e6c8406c4aea26950b37676e0Adam Langley#include <openssl/digest.h> 26c5c0c7e85325820eafe78d6d5793a441ce40ec78Adam Langley#include <openssl/obj.h> 27c5c0c7e85325820eafe78d6d5793a441ce40ec78Adam Langley#include <openssl/rsa.h> 28c5c0c7e85325820eafe78d6d5793a441ce40ec78Adam Langley 29c5c0c7e85325820eafe78d6d5793a441ce40ec78Adam Langley#if defined(OPENSSL_WINDOWS) 30c5c0c7e85325820eafe78d6d5793a441ce40ec78Adam Langley#include <Windows.h> 3130eda1d2b80b8a943d3fb792f623a232646b0dbcAdam Langley#elif defined(OPENSSL_APPLE) 3230eda1d2b80b8a943d3fb792f623a232646b0dbcAdam Langley#include <sys/time.h> 33c5c0c7e85325820eafe78d6d5793a441ce40ec78Adam Langley#endif 34c5c0c7e85325820eafe78d6d5793a441ce40ec78Adam Langley 35c5c0c7e85325820eafe78d6d5793a441ce40ec78Adam Langleyextern "C" { 36c5c0c7e85325820eafe78d6d5793a441ce40ec78Adam Langley// These values are DER encoded, RSA private keys. 37c5c0c7e85325820eafe78d6d5793a441ce40ec78Adam Langleyextern const uint8_t kDERRSAPrivate2048[]; 38c5c0c7e85325820eafe78d6d5793a441ce40ec78Adam Langleyextern size_t kDERRSAPrivate2048Len; 39c5c0c7e85325820eafe78d6d5793a441ce40ec78Adam Langleyextern const uint8_t kDERRSAPrivate4096[]; 40c5c0c7e85325820eafe78d6d5793a441ce40ec78Adam Langleyextern size_t kDERRSAPrivate4096Len; 41c5c0c7e85325820eafe78d6d5793a441ce40ec78Adam Langley} 42c5c0c7e85325820eafe78d6d5793a441ce40ec78Adam Langley 43c5c0c7e85325820eafe78d6d5793a441ce40ec78Adam Langley// TimeResults represents the results of benchmarking a function. 44c5c0c7e85325820eafe78d6d5793a441ce40ec78Adam Langleystruct TimeResults { 45c5c0c7e85325820eafe78d6d5793a441ce40ec78Adam Langley // num_calls is the number of function calls done in the time period. 46c5c0c7e85325820eafe78d6d5793a441ce40ec78Adam Langley unsigned num_calls; 47c5c0c7e85325820eafe78d6d5793a441ce40ec78Adam Langley // us is the number of microseconds that elapsed in the time period. 48c5c0c7e85325820eafe78d6d5793a441ce40ec78Adam Langley unsigned us; 49c5c0c7e85325820eafe78d6d5793a441ce40ec78Adam Langley 50c5c0c7e85325820eafe78d6d5793a441ce40ec78Adam Langley void Print(const std::string &description) { 51c5c0c7e85325820eafe78d6d5793a441ce40ec78Adam Langley printf("Did %u %s operations in %uus (%.1f ops/sec)\n", num_calls, 52c5c0c7e85325820eafe78d6d5793a441ce40ec78Adam Langley description.c_str(), us, 53c5c0c7e85325820eafe78d6d5793a441ce40ec78Adam Langley (static_cast<double>(num_calls) / us) * 1000000); 54c5c0c7e85325820eafe78d6d5793a441ce40ec78Adam Langley } 55c5c0c7e85325820eafe78d6d5793a441ce40ec78Adam Langley 56c5c0c7e85325820eafe78d6d5793a441ce40ec78Adam Langley void PrintWithBytes(const std::string &description, size_t bytes_per_call) { 57c5c0c7e85325820eafe78d6d5793a441ce40ec78Adam Langley printf("Did %u %s operations in %uus (%.1f ops/sec): %.1f MB/s\n", 58c5c0c7e85325820eafe78d6d5793a441ce40ec78Adam Langley num_calls, description.c_str(), us, 59c5c0c7e85325820eafe78d6d5793a441ce40ec78Adam Langley (static_cast<double>(num_calls) / us) * 1000000, 60c5c0c7e85325820eafe78d6d5793a441ce40ec78Adam Langley static_cast<double>(bytes_per_call * num_calls) / us); 61c5c0c7e85325820eafe78d6d5793a441ce40ec78Adam Langley } 62c5c0c7e85325820eafe78d6d5793a441ce40ec78Adam Langley}; 63c5c0c7e85325820eafe78d6d5793a441ce40ec78Adam Langley 64c5c0c7e85325820eafe78d6d5793a441ce40ec78Adam Langley#if defined(OPENSSL_WINDOWS) 65c5c0c7e85325820eafe78d6d5793a441ce40ec78Adam Langleystatic uint64_t time_now() { return GetTickCount64() * 1000; } 6630eda1d2b80b8a943d3fb792f623a232646b0dbcAdam Langley#elif defined(OPENSSL_APPLE) 6730eda1d2b80b8a943d3fb792f623a232646b0dbcAdam Langleystatic uint64_t time_now() { 6830eda1d2b80b8a943d3fb792f623a232646b0dbcAdam Langley struct timeval tv; 6930eda1d2b80b8a943d3fb792f623a232646b0dbcAdam Langley uint64_t ret; 7030eda1d2b80b8a943d3fb792f623a232646b0dbcAdam Langley 7130eda1d2b80b8a943d3fb792f623a232646b0dbcAdam Langley gettimeofday(&tv, NULL); 7230eda1d2b80b8a943d3fb792f623a232646b0dbcAdam Langley ret = tv.tv_sec; 7330eda1d2b80b8a943d3fb792f623a232646b0dbcAdam Langley ret *= 1000000; 7430eda1d2b80b8a943d3fb792f623a232646b0dbcAdam Langley ret += tv.tv_usec; 7530eda1d2b80b8a943d3fb792f623a232646b0dbcAdam Langley return ret; 7630eda1d2b80b8a943d3fb792f623a232646b0dbcAdam Langley} 77c5c0c7e85325820eafe78d6d5793a441ce40ec78Adam Langley#else 78c5c0c7e85325820eafe78d6d5793a441ce40ec78Adam Langleystatic uint64_t time_now() { 79c5c0c7e85325820eafe78d6d5793a441ce40ec78Adam Langley struct timespec ts; 80c5c0c7e85325820eafe78d6d5793a441ce40ec78Adam Langley clock_gettime(CLOCK_MONOTONIC, &ts); 81c5c0c7e85325820eafe78d6d5793a441ce40ec78Adam Langley 82c5c0c7e85325820eafe78d6d5793a441ce40ec78Adam Langley uint64_t ret = ts.tv_sec; 83c5c0c7e85325820eafe78d6d5793a441ce40ec78Adam Langley ret *= 1000000; 84c5c0c7e85325820eafe78d6d5793a441ce40ec78Adam Langley ret += ts.tv_nsec / 1000; 85c5c0c7e85325820eafe78d6d5793a441ce40ec78Adam Langley return ret; 86c5c0c7e85325820eafe78d6d5793a441ce40ec78Adam Langley} 87c5c0c7e85325820eafe78d6d5793a441ce40ec78Adam Langley#endif 88c5c0c7e85325820eafe78d6d5793a441ce40ec78Adam Langley 89c5c0c7e85325820eafe78d6d5793a441ce40ec78Adam Langleystatic bool TimeFunction(TimeResults *results, std::function<bool()> func) { 90c5c0c7e85325820eafe78d6d5793a441ce40ec78Adam Langley // kTotalMS is the total amount of time that we'll aim to measure a function 91c5c0c7e85325820eafe78d6d5793a441ce40ec78Adam Langley // for. 92c5c0c7e85325820eafe78d6d5793a441ce40ec78Adam Langley static const uint64_t kTotalUS = 3000000; 93c5c0c7e85325820eafe78d6d5793a441ce40ec78Adam Langley uint64_t start = time_now(), now, delta; 94c5c0c7e85325820eafe78d6d5793a441ce40ec78Adam Langley unsigned done = 0, iterations_between_time_checks; 95c5c0c7e85325820eafe78d6d5793a441ce40ec78Adam Langley 96c5c0c7e85325820eafe78d6d5793a441ce40ec78Adam Langley if (!func()) { 97c5c0c7e85325820eafe78d6d5793a441ce40ec78Adam Langley return false; 98c5c0c7e85325820eafe78d6d5793a441ce40ec78Adam Langley } 99c5c0c7e85325820eafe78d6d5793a441ce40ec78Adam Langley now = time_now(); 100c5c0c7e85325820eafe78d6d5793a441ce40ec78Adam Langley delta = now - start; 101c5c0c7e85325820eafe78d6d5793a441ce40ec78Adam Langley if (delta == 0) { 102c5c0c7e85325820eafe78d6d5793a441ce40ec78Adam Langley iterations_between_time_checks = 250; 103c5c0c7e85325820eafe78d6d5793a441ce40ec78Adam Langley } else { 104c5c0c7e85325820eafe78d6d5793a441ce40ec78Adam Langley // Aim for about 100ms between time checks. 105c5c0c7e85325820eafe78d6d5793a441ce40ec78Adam Langley iterations_between_time_checks = 106c5c0c7e85325820eafe78d6d5793a441ce40ec78Adam Langley static_cast<double>(100000) / static_cast<double>(delta); 107c5c0c7e85325820eafe78d6d5793a441ce40ec78Adam Langley if (iterations_between_time_checks > 1000) { 108c5c0c7e85325820eafe78d6d5793a441ce40ec78Adam Langley iterations_between_time_checks = 1000; 109c5c0c7e85325820eafe78d6d5793a441ce40ec78Adam Langley } else if (iterations_between_time_checks < 1) { 110c5c0c7e85325820eafe78d6d5793a441ce40ec78Adam Langley iterations_between_time_checks = 1; 111c5c0c7e85325820eafe78d6d5793a441ce40ec78Adam Langley } 112c5c0c7e85325820eafe78d6d5793a441ce40ec78Adam Langley } 113c5c0c7e85325820eafe78d6d5793a441ce40ec78Adam Langley 114c5c0c7e85325820eafe78d6d5793a441ce40ec78Adam Langley for (;;) { 115c5c0c7e85325820eafe78d6d5793a441ce40ec78Adam Langley for (unsigned i = 0; i < iterations_between_time_checks; i++) { 116c5c0c7e85325820eafe78d6d5793a441ce40ec78Adam Langley if (!func()) { 117c5c0c7e85325820eafe78d6d5793a441ce40ec78Adam Langley return false; 118c5c0c7e85325820eafe78d6d5793a441ce40ec78Adam Langley } 119c5c0c7e85325820eafe78d6d5793a441ce40ec78Adam Langley done++; 120c5c0c7e85325820eafe78d6d5793a441ce40ec78Adam Langley } 121c5c0c7e85325820eafe78d6d5793a441ce40ec78Adam Langley 122c5c0c7e85325820eafe78d6d5793a441ce40ec78Adam Langley now = time_now(); 123c5c0c7e85325820eafe78d6d5793a441ce40ec78Adam Langley if (now - start > kTotalUS) { 124c5c0c7e85325820eafe78d6d5793a441ce40ec78Adam Langley break; 125c5c0c7e85325820eafe78d6d5793a441ce40ec78Adam Langley } 126c5c0c7e85325820eafe78d6d5793a441ce40ec78Adam Langley } 127c5c0c7e85325820eafe78d6d5793a441ce40ec78Adam Langley 128c5c0c7e85325820eafe78d6d5793a441ce40ec78Adam Langley results->us = now - start; 129c5c0c7e85325820eafe78d6d5793a441ce40ec78Adam Langley results->num_calls = done; 130c5c0c7e85325820eafe78d6d5793a441ce40ec78Adam Langley return true; 131c5c0c7e85325820eafe78d6d5793a441ce40ec78Adam Langley} 132c5c0c7e85325820eafe78d6d5793a441ce40ec78Adam Langley 133c5c0c7e85325820eafe78d6d5793a441ce40ec78Adam Langleystatic bool SpeedRSA(const std::string& key_name, RSA *key) { 134c5c0c7e85325820eafe78d6d5793a441ce40ec78Adam Langley TimeResults results; 135c5c0c7e85325820eafe78d6d5793a441ce40ec78Adam Langley 136c5c0c7e85325820eafe78d6d5793a441ce40ec78Adam Langley std::unique_ptr<uint8_t[]> sig(new uint8_t[RSA_size(key)]); 137c5c0c7e85325820eafe78d6d5793a441ce40ec78Adam Langley const uint8_t fake_sha256_hash[32] = {0}; 138c5c0c7e85325820eafe78d6d5793a441ce40ec78Adam Langley unsigned sig_len; 139c5c0c7e85325820eafe78d6d5793a441ce40ec78Adam Langley 140c5c0c7e85325820eafe78d6d5793a441ce40ec78Adam Langley if (!TimeFunction(&results, 141c5c0c7e85325820eafe78d6d5793a441ce40ec78Adam Langley [key, &sig, &fake_sha256_hash, &sig_len]() -> bool { 142c5c0c7e85325820eafe78d6d5793a441ce40ec78Adam Langley return RSA_sign(NID_sha256, fake_sha256_hash, sizeof(fake_sha256_hash), 143c5c0c7e85325820eafe78d6d5793a441ce40ec78Adam Langley sig.get(), &sig_len, key); 144c5c0c7e85325820eafe78d6d5793a441ce40ec78Adam Langley })) { 145c5c0c7e85325820eafe78d6d5793a441ce40ec78Adam Langley fprintf(stderr, "RSA_sign failed.\n"); 146c5c0c7e85325820eafe78d6d5793a441ce40ec78Adam Langley BIO_print_errors_fp(stderr); 147c5c0c7e85325820eafe78d6d5793a441ce40ec78Adam Langley return false; 148c5c0c7e85325820eafe78d6d5793a441ce40ec78Adam Langley } 149c5c0c7e85325820eafe78d6d5793a441ce40ec78Adam Langley results.Print(key_name + " signing"); 150c5c0c7e85325820eafe78d6d5793a441ce40ec78Adam Langley 151c5c0c7e85325820eafe78d6d5793a441ce40ec78Adam Langley if (!TimeFunction(&results, 152c5c0c7e85325820eafe78d6d5793a441ce40ec78Adam Langley [key, &fake_sha256_hash, &sig, sig_len]() -> bool { 153c5c0c7e85325820eafe78d6d5793a441ce40ec78Adam Langley return RSA_verify(NID_sha256, fake_sha256_hash, 154c5c0c7e85325820eafe78d6d5793a441ce40ec78Adam Langley sizeof(fake_sha256_hash), sig.get(), sig_len, key); 155c5c0c7e85325820eafe78d6d5793a441ce40ec78Adam Langley })) { 156c5c0c7e85325820eafe78d6d5793a441ce40ec78Adam Langley fprintf(stderr, "RSA_verify failed.\n"); 157c5c0c7e85325820eafe78d6d5793a441ce40ec78Adam Langley BIO_print_errors_fp(stderr); 158c5c0c7e85325820eafe78d6d5793a441ce40ec78Adam Langley return false; 159c5c0c7e85325820eafe78d6d5793a441ce40ec78Adam Langley } 160c5c0c7e85325820eafe78d6d5793a441ce40ec78Adam Langley results.Print(key_name + " verify"); 161c5c0c7e85325820eafe78d6d5793a441ce40ec78Adam Langley 162c5c0c7e85325820eafe78d6d5793a441ce40ec78Adam Langley return true; 163c5c0c7e85325820eafe78d6d5793a441ce40ec78Adam Langley} 164c5c0c7e85325820eafe78d6d5793a441ce40ec78Adam Langley 165c5c0c7e85325820eafe78d6d5793a441ce40ec78Adam Langleystatic bool SpeedAEADChunk(const EVP_AEAD *aead, const std::string &name, 166c5c0c7e85325820eafe78d6d5793a441ce40ec78Adam Langley size_t chunk_len) { 167c5c0c7e85325820eafe78d6d5793a441ce40ec78Adam Langley EVP_AEAD_CTX ctx; 168c5c0c7e85325820eafe78d6d5793a441ce40ec78Adam Langley const size_t key_len = EVP_AEAD_key_length(aead); 169c5c0c7e85325820eafe78d6d5793a441ce40ec78Adam Langley const size_t nonce_len = EVP_AEAD_nonce_length(aead); 170c5c0c7e85325820eafe78d6d5793a441ce40ec78Adam Langley const size_t overhead_len = EVP_AEAD_max_overhead(aead); 171c5c0c7e85325820eafe78d6d5793a441ce40ec78Adam Langley 172c5c0c7e85325820eafe78d6d5793a441ce40ec78Adam Langley std::unique_ptr<uint8_t[]> key(new uint8_t[key_len]); 173c5c0c7e85325820eafe78d6d5793a441ce40ec78Adam Langley memset(key.get(), 0, key_len); 174c5c0c7e85325820eafe78d6d5793a441ce40ec78Adam Langley std::unique_ptr<uint8_t[]> nonce(new uint8_t[nonce_len]); 175c5c0c7e85325820eafe78d6d5793a441ce40ec78Adam Langley memset(nonce.get(), 0, nonce_len); 176c5c0c7e85325820eafe78d6d5793a441ce40ec78Adam Langley std::unique_ptr<uint8_t[]> in(new uint8_t[chunk_len]); 177c5c0c7e85325820eafe78d6d5793a441ce40ec78Adam Langley memset(in.get(), 0, chunk_len); 178c5c0c7e85325820eafe78d6d5793a441ce40ec78Adam Langley std::unique_ptr<uint8_t[]> out(new uint8_t[chunk_len + overhead_len]); 179c5c0c7e85325820eafe78d6d5793a441ce40ec78Adam Langley memset(out.get(), 0, chunk_len + overhead_len); 180c5c0c7e85325820eafe78d6d5793a441ce40ec78Adam Langley 181c5c0c7e85325820eafe78d6d5793a441ce40ec78Adam Langley if (!EVP_AEAD_CTX_init(&ctx, aead, key.get(), key_len, 182c5c0c7e85325820eafe78d6d5793a441ce40ec78Adam Langley EVP_AEAD_DEFAULT_TAG_LENGTH, NULL)) { 183c5c0c7e85325820eafe78d6d5793a441ce40ec78Adam Langley fprintf(stderr, "Failed to create EVP_AEAD_CTX.\n"); 184c5c0c7e85325820eafe78d6d5793a441ce40ec78Adam Langley BIO_print_errors_fp(stderr); 185c5c0c7e85325820eafe78d6d5793a441ce40ec78Adam Langley return false; 186c5c0c7e85325820eafe78d6d5793a441ce40ec78Adam Langley } 187c5c0c7e85325820eafe78d6d5793a441ce40ec78Adam Langley 188c5c0c7e85325820eafe78d6d5793a441ce40ec78Adam Langley TimeResults results; 189c5c0c7e85325820eafe78d6d5793a441ce40ec78Adam Langley if (!TimeFunction(&results, [chunk_len, overhead_len, nonce_len, &in, &out, 190c5c0c7e85325820eafe78d6d5793a441ce40ec78Adam Langley &ctx, &nonce]() -> bool { 191c5c0c7e85325820eafe78d6d5793a441ce40ec78Adam Langley size_t out_len; 192c5c0c7e85325820eafe78d6d5793a441ce40ec78Adam Langley 193c5c0c7e85325820eafe78d6d5793a441ce40ec78Adam Langley return EVP_AEAD_CTX_seal(&ctx, out.get(), &out_len, 194c5c0c7e85325820eafe78d6d5793a441ce40ec78Adam Langley chunk_len + overhead_len, nonce.get(), 195c5c0c7e85325820eafe78d6d5793a441ce40ec78Adam Langley nonce_len, in.get(), chunk_len, NULL, 0); 196c5c0c7e85325820eafe78d6d5793a441ce40ec78Adam Langley })) { 197c5c0c7e85325820eafe78d6d5793a441ce40ec78Adam Langley fprintf(stderr, "EVP_AEAD_CTX_seal failed.\n"); 198c5c0c7e85325820eafe78d6d5793a441ce40ec78Adam Langley BIO_print_errors_fp(stderr); 199c5c0c7e85325820eafe78d6d5793a441ce40ec78Adam Langley return false; 200c5c0c7e85325820eafe78d6d5793a441ce40ec78Adam Langley } 201c5c0c7e85325820eafe78d6d5793a441ce40ec78Adam Langley 202c5c0c7e85325820eafe78d6d5793a441ce40ec78Adam Langley results.PrintWithBytes(name + " seal", chunk_len); 203c5c0c7e85325820eafe78d6d5793a441ce40ec78Adam Langley 204c5c0c7e85325820eafe78d6d5793a441ce40ec78Adam Langley EVP_AEAD_CTX_cleanup(&ctx); 205c5c0c7e85325820eafe78d6d5793a441ce40ec78Adam Langley 206c5c0c7e85325820eafe78d6d5793a441ce40ec78Adam Langley return true; 207c5c0c7e85325820eafe78d6d5793a441ce40ec78Adam Langley} 208c5c0c7e85325820eafe78d6d5793a441ce40ec78Adam Langley 209c5c0c7e85325820eafe78d6d5793a441ce40ec78Adam Langleystatic bool SpeedAEAD(const EVP_AEAD *aead, const std::string &name) { 210c5c0c7e85325820eafe78d6d5793a441ce40ec78Adam Langley return SpeedAEADChunk(aead, name + " (16 bytes)", 16) && 211c5c0c7e85325820eafe78d6d5793a441ce40ec78Adam Langley SpeedAEADChunk(aead, name + " (1350 bytes)", 1350) && 212c5c0c7e85325820eafe78d6d5793a441ce40ec78Adam Langley SpeedAEADChunk(aead, name + " (8192 bytes)", 8192); 213c5c0c7e85325820eafe78d6d5793a441ce40ec78Adam Langley} 214c5c0c7e85325820eafe78d6d5793a441ce40ec78Adam Langley 215006779a02c515e5e6c8406c4aea26950b37676e0Adam Langleystatic bool SpeedHashChunk(const EVP_MD *md, const std::string &name, 216006779a02c515e5e6c8406c4aea26950b37676e0Adam Langley size_t chunk_len) { 217006779a02c515e5e6c8406c4aea26950b37676e0Adam Langley EVP_MD_CTX *ctx = EVP_MD_CTX_create(); 218006779a02c515e5e6c8406c4aea26950b37676e0Adam Langley uint8_t scratch[8192]; 219006779a02c515e5e6c8406c4aea26950b37676e0Adam Langley 220006779a02c515e5e6c8406c4aea26950b37676e0Adam Langley if (chunk_len > sizeof(scratch)) { 221006779a02c515e5e6c8406c4aea26950b37676e0Adam Langley return false; 222006779a02c515e5e6c8406c4aea26950b37676e0Adam Langley } 223006779a02c515e5e6c8406c4aea26950b37676e0Adam Langley 224006779a02c515e5e6c8406c4aea26950b37676e0Adam Langley TimeResults results; 225006779a02c515e5e6c8406c4aea26950b37676e0Adam Langley if (!TimeFunction(&results, [ctx, md, chunk_len, &scratch]() -> bool { 226006779a02c515e5e6c8406c4aea26950b37676e0Adam Langley uint8_t digest[EVP_MAX_MD_SIZE]; 227006779a02c515e5e6c8406c4aea26950b37676e0Adam Langley unsigned int md_len; 228006779a02c515e5e6c8406c4aea26950b37676e0Adam Langley 229006779a02c515e5e6c8406c4aea26950b37676e0Adam Langley return EVP_DigestInit_ex(ctx, md, NULL /* ENGINE */) && 230006779a02c515e5e6c8406c4aea26950b37676e0Adam Langley EVP_DigestUpdate(ctx, scratch, chunk_len) && 231006779a02c515e5e6c8406c4aea26950b37676e0Adam Langley EVP_DigestFinal_ex(ctx, digest, &md_len); 232006779a02c515e5e6c8406c4aea26950b37676e0Adam Langley })) { 233006779a02c515e5e6c8406c4aea26950b37676e0Adam Langley fprintf(stderr, "EVP_DigestInit_ex failed.\n"); 234006779a02c515e5e6c8406c4aea26950b37676e0Adam Langley BIO_print_errors_fp(stderr); 235006779a02c515e5e6c8406c4aea26950b37676e0Adam Langley return false; 236006779a02c515e5e6c8406c4aea26950b37676e0Adam Langley } 237006779a02c515e5e6c8406c4aea26950b37676e0Adam Langley 238006779a02c515e5e6c8406c4aea26950b37676e0Adam Langley results.PrintWithBytes(name, chunk_len); 239006779a02c515e5e6c8406c4aea26950b37676e0Adam Langley 240006779a02c515e5e6c8406c4aea26950b37676e0Adam Langley EVP_MD_CTX_destroy(ctx); 241006779a02c515e5e6c8406c4aea26950b37676e0Adam Langley 242006779a02c515e5e6c8406c4aea26950b37676e0Adam Langley return true; 243006779a02c515e5e6c8406c4aea26950b37676e0Adam Langley} 244006779a02c515e5e6c8406c4aea26950b37676e0Adam Langleystatic bool SpeedHash(const EVP_MD *md, const std::string &name) { 245006779a02c515e5e6c8406c4aea26950b37676e0Adam Langley return SpeedHashChunk(md, name + " (16 bytes)", 16) && 246006779a02c515e5e6c8406c4aea26950b37676e0Adam Langley SpeedHashChunk(md, name + " (256 bytes)", 256) && 247006779a02c515e5e6c8406c4aea26950b37676e0Adam Langley SpeedHashChunk(md, name + " (8192 bytes)", 8192); 248006779a02c515e5e6c8406c4aea26950b37676e0Adam Langley} 249006779a02c515e5e6c8406c4aea26950b37676e0Adam Langley 250c5c0c7e85325820eafe78d6d5793a441ce40ec78Adam Langleybool Speed(const std::vector<std::string> &args) { 251c5c0c7e85325820eafe78d6d5793a441ce40ec78Adam Langley const uint8_t *inp; 252c5c0c7e85325820eafe78d6d5793a441ce40ec78Adam Langley 253c5c0c7e85325820eafe78d6d5793a441ce40ec78Adam Langley RSA *key = NULL; 254c5c0c7e85325820eafe78d6d5793a441ce40ec78Adam Langley inp = kDERRSAPrivate2048; 255c5c0c7e85325820eafe78d6d5793a441ce40ec78Adam Langley if (NULL == d2i_RSAPrivateKey(&key, &inp, kDERRSAPrivate2048Len)) { 256c5c0c7e85325820eafe78d6d5793a441ce40ec78Adam Langley fprintf(stderr, "Failed to parse RSA key.\n"); 257c5c0c7e85325820eafe78d6d5793a441ce40ec78Adam Langley BIO_print_errors_fp(stderr); 258c5c0c7e85325820eafe78d6d5793a441ce40ec78Adam Langley return false; 259c5c0c7e85325820eafe78d6d5793a441ce40ec78Adam Langley } 260c5c0c7e85325820eafe78d6d5793a441ce40ec78Adam Langley 261c5c0c7e85325820eafe78d6d5793a441ce40ec78Adam Langley if (!SpeedRSA("RSA 2048", key)) { 262c5c0c7e85325820eafe78d6d5793a441ce40ec78Adam Langley return false; 263c5c0c7e85325820eafe78d6d5793a441ce40ec78Adam Langley } 264c5c0c7e85325820eafe78d6d5793a441ce40ec78Adam Langley 265c5c0c7e85325820eafe78d6d5793a441ce40ec78Adam Langley RSA_free(key); 266c5c0c7e85325820eafe78d6d5793a441ce40ec78Adam Langley key = NULL; 267c5c0c7e85325820eafe78d6d5793a441ce40ec78Adam Langley 268c5c0c7e85325820eafe78d6d5793a441ce40ec78Adam Langley inp = kDERRSAPrivate4096; 269c5c0c7e85325820eafe78d6d5793a441ce40ec78Adam Langley if (NULL == d2i_RSAPrivateKey(&key, &inp, kDERRSAPrivate4096Len)) { 270c5c0c7e85325820eafe78d6d5793a441ce40ec78Adam Langley fprintf(stderr, "Failed to parse 4096-bit RSA key.\n"); 271c5c0c7e85325820eafe78d6d5793a441ce40ec78Adam Langley BIO_print_errors_fp(stderr); 272c5c0c7e85325820eafe78d6d5793a441ce40ec78Adam Langley return 1; 273c5c0c7e85325820eafe78d6d5793a441ce40ec78Adam Langley } 274c5c0c7e85325820eafe78d6d5793a441ce40ec78Adam Langley 275c5c0c7e85325820eafe78d6d5793a441ce40ec78Adam Langley if (!SpeedRSA("RSA 4096", key)) { 276c5c0c7e85325820eafe78d6d5793a441ce40ec78Adam Langley return false; 277c5c0c7e85325820eafe78d6d5793a441ce40ec78Adam Langley } 278c5c0c7e85325820eafe78d6d5793a441ce40ec78Adam Langley 279c5c0c7e85325820eafe78d6d5793a441ce40ec78Adam Langley RSA_free(key); 280c5c0c7e85325820eafe78d6d5793a441ce40ec78Adam Langley 281c5c0c7e85325820eafe78d6d5793a441ce40ec78Adam Langley if (!SpeedAEAD(EVP_aead_aes_128_gcm(), "AES-128-GCM") || 282c5c0c7e85325820eafe78d6d5793a441ce40ec78Adam Langley !SpeedAEAD(EVP_aead_aes_256_gcm(), "AES-256-GCM") || 283006779a02c515e5e6c8406c4aea26950b37676e0Adam Langley !SpeedAEAD(EVP_aead_chacha20_poly1305(), "ChaCha20-Poly1305") || 28445ec21b99c144643dec9e953a3b8ba44870f5cacAdam Langley !SpeedAEAD(EVP_aead_rc4_md5_tls(), "RC4-MD5") || 285006779a02c515e5e6c8406c4aea26950b37676e0Adam Langley !SpeedHash(EVP_sha1(), "SHA-1") || 286006779a02c515e5e6c8406c4aea26950b37676e0Adam Langley !SpeedHash(EVP_sha256(), "SHA-256") || 287006779a02c515e5e6c8406c4aea26950b37676e0Adam Langley !SpeedHash(EVP_sha512(), "SHA-512")) { 288c5c0c7e85325820eafe78d6d5793a441ce40ec78Adam Langley return false; 289c5c0c7e85325820eafe78d6d5793a441ce40ec78Adam Langley } 290c5c0c7e85325820eafe78d6d5793a441ce40ec78Adam Langley 291c5c0c7e85325820eafe78d6d5793a441ce40ec78Adam Langley return 0; 292c5c0c7e85325820eafe78d6d5793a441ce40ec78Adam Langley} 293