benchmark-openssl.cc revision 9acb42f4
1a98d478eSShuo Chen#include <openssl/aes.h> 2a98d478eSShuo Chen#include <openssl/conf.h> 3a98d478eSShuo Chen#include <openssl/err.h> 4a98d478eSShuo Chen#include <openssl/ssl.h> 5a98d478eSShuo Chen 6a98d478eSShuo Chen#include <muduo/net/Buffer.h> 7a98d478eSShuo Chen 8a98d478eSShuo Chen#include <stdio.h> 9a98d478eSShuo Chen 109acb42f4SShuo Chen#include "timer.h" 119acb42f4SShuo Chen 12a98d478eSShuo Chenmuduo::net::Buffer clientOut, serverOut; 13a98d478eSShuo Chen 14a98d478eSShuo Chendouble now() 15a98d478eSShuo Chen{ 16a98d478eSShuo Chen struct timeval tv; 17a98d478eSShuo Chen gettimeofday(&tv, NULL); 18a98d478eSShuo Chen return tv.tv_sec + tv.tv_usec / 1000000.0; 19a98d478eSShuo Chen} 20a98d478eSShuo Chen 21a98d478eSShuo Chenint bread(BIO *b, char *buf, int len) 22a98d478eSShuo Chen{ 23a98d478eSShuo Chen BIO_clear_retry_flags(b); 24a98d478eSShuo Chen muduo::net::Buffer* in = static_cast<muduo::net::Buffer*>(b->ptr); 25a98d478eSShuo Chen // printf("%s recv %d\n", in == &clientOut ? "server" : "client", len); 26a98d478eSShuo Chen if (in->readableBytes() > 0) 27a98d478eSShuo Chen { 28a98d478eSShuo Chen size_t n = std::min(in->readableBytes(), static_cast<size_t>(len)); 29a98d478eSShuo Chen memcpy(buf, in->peek(), n); 30a98d478eSShuo Chen in->retrieve(n); 31a98d478eSShuo Chen 32a98d478eSShuo Chen /* 33a98d478eSShuo Chen if (n < len) 34a98d478eSShuo Chen printf("got %zd\n", n); 35a98d478eSShuo Chen else 36a98d478eSShuo Chen printf("\n"); 37a98d478eSShuo Chen */ 38a98d478eSShuo Chen return n; 39a98d478eSShuo Chen } 40a98d478eSShuo Chen else 41a98d478eSShuo Chen { 42a98d478eSShuo Chen //printf("got 0\n"); 43a98d478eSShuo Chen BIO_set_retry_read(b); 44a98d478eSShuo Chen return -1; 45a98d478eSShuo Chen } 46a98d478eSShuo Chen} 47a98d478eSShuo Chen 48a98d478eSShuo Chenint bwrite(BIO *b, const char *buf, int len) 49a98d478eSShuo Chen{ 50a98d478eSShuo Chen BIO_clear_retry_flags(b); 51a98d478eSShuo Chen muduo::net::Buffer* out = static_cast<muduo::net::Buffer*>(b->ptr); 52a98d478eSShuo Chen // printf("%s send %d\n", out == &clientOut ? "client" : "server", len); 53a98d478eSShuo Chen out->append(buf, len); 54a98d478eSShuo Chen return len; 55a98d478eSShuo Chen} 56a98d478eSShuo Chen 57a98d478eSShuo Chenlong bctrl(BIO *, int cmd, long num, void *) 58a98d478eSShuo Chen{ 59a98d478eSShuo Chen //printf("ctrl %d\n", cmd); 60a98d478eSShuo Chen switch (cmd) { 61a98d478eSShuo Chen case BIO_CTRL_FLUSH: 62a98d478eSShuo Chen return 1; 63a98d478eSShuo Chen default: 64a98d478eSShuo Chen return 0; 65a98d478eSShuo Chen } 66a98d478eSShuo Chen} 67a98d478eSShuo Chen 68a98d478eSShuo Chenint main(int argc, char* argv[]) 69a98d478eSShuo Chen{ 70a98d478eSShuo Chen SSL_load_error_strings(); 71a98d478eSShuo Chen // ERR_load_BIO_strings(); 72a98d478eSShuo Chen SSL_library_init(); 73a98d478eSShuo Chen OPENSSL_config(NULL); 74a98d478eSShuo Chen 75a98d478eSShuo Chen SSL_CTX* ctx = SSL_CTX_new(TLSv1_1_server_method()); 76a98d478eSShuo Chen 77a98d478eSShuo Chen EC_KEY* ecdh = EC_KEY_new_by_curve_name(NID_X9_62_prime256v1); 78a98d478eSShuo Chen SSL_CTX_set_options(ctx, SSL_OP_SINGLE_ECDH_USE); 799acb42f4SShuo Chen if (argc > 3) 809acb42f4SShuo Chen SSL_CTX_set_tmp_ecdh(ctx, ecdh); 81a98d478eSShuo Chen EC_KEY_free(ecdh); 82a98d478eSShuo Chen 83a98d478eSShuo Chen const char* CertFile = argv[1]; 84a98d478eSShuo Chen const char* KeyFile = argv[2]; 85a98d478eSShuo Chen SSL_CTX_use_certificate_file(ctx, CertFile, SSL_FILETYPE_PEM); 86a98d478eSShuo Chen SSL_CTX_use_PrivateKey_file(ctx, KeyFile, SSL_FILETYPE_PEM); 87a98d478eSShuo Chen if (!SSL_CTX_check_private_key(ctx)) 88a98d478eSShuo Chen abort(); 89a98d478eSShuo Chen 90a98d478eSShuo Chen SSL_CTX* ctx_client = SSL_CTX_new(TLSv1_1_client_method()); 91a98d478eSShuo Chen 92a98d478eSShuo Chen BIO_METHOD method; 93a98d478eSShuo Chen bzero(&method, sizeof method); 94a98d478eSShuo Chen method.bread = bread; 95a98d478eSShuo Chen method.bwrite = bwrite; 96a98d478eSShuo Chen method.ctrl = bctrl; 97a98d478eSShuo Chen BIO client, server; 98a98d478eSShuo Chen bzero(&client, sizeof client); 99a98d478eSShuo Chen bzero(&server, sizeof server); 100a98d478eSShuo Chen BIO_set(&client, &method); 101a98d478eSShuo Chen BIO_set(&server, &method); 102a98d478eSShuo Chen client.ptr = &clientOut; 103a98d478eSShuo Chen client.init = 1; 104a98d478eSShuo Chen server.ptr = &serverOut; 105a98d478eSShuo Chen server.init = 1; 106a98d478eSShuo Chen 107a98d478eSShuo Chen 108a98d478eSShuo Chen double start = now(); 109a98d478eSShuo Chen const int N = 1000; 110a98d478eSShuo Chen SSL *ssl, *ssl_client; 1119acb42f4SShuo Chen Timer tc, ts; 112a98d478eSShuo Chen for (int i = 0; i < N; ++i) 113a98d478eSShuo Chen { 114a98d478eSShuo Chen ssl = SSL_new (ctx); 115a98d478eSShuo Chen ssl_client = SSL_new (ctx_client); 116a98d478eSShuo Chen SSL_set_bio(ssl, &client, &server); 117a98d478eSShuo Chen SSL_set_bio(ssl_client, &server, &client); 118a98d478eSShuo Chen 1199acb42f4SShuo Chen tc.start(); 120a98d478eSShuo Chen int ret = SSL_connect(ssl_client); 1219acb42f4SShuo Chen tc.stop(); 122a98d478eSShuo Chen //printf("%d %d\n", ret, BIO_retry_type(&server)); 1239acb42f4SShuo Chen ts.start(); 124a98d478eSShuo Chen int ret2 = SSL_accept(ssl); 1259acb42f4SShuo Chen ts.stop(); 126a98d478eSShuo Chen //printf("%d %d\n", ret2, BIO_retry_type(&client)); 127a98d478eSShuo Chen 128a98d478eSShuo Chen while (true) 129a98d478eSShuo Chen { 1309acb42f4SShuo Chen tc.start(); 1319acb42f4SShuo Chen ret = SSL_do_handshake(ssl_client); 1329acb42f4SShuo Chen tc.stop(); 133a98d478eSShuo Chen //printf("client handshake %d %d\n", ret, BIO_retry_type(&server)); 1349acb42f4SShuo Chen ts.start(); 1359acb42f4SShuo Chen ret2 = SSL_do_handshake(ssl); 1369acb42f4SShuo Chen ts.stop(); 137a98d478eSShuo Chen //printf("server handshake %d %d\n", ret2, BIO_retry_type(&client)); 138a98d478eSShuo Chen //if (ret == -1 && BIO_retry_type(&server) == 0) 139a98d478eSShuo Chen // break; 140a98d478eSShuo Chen //if (ret2 == -1 && BIO_retry_type(&client) == 0) 141a98d478eSShuo Chen // break; 142a98d478eSShuo Chen if (ret == 1 && ret2 == 1) 143a98d478eSShuo Chen break; 144a98d478eSShuo Chen } 145a98d478eSShuo Chen 146a98d478eSShuo Chen //printf ("SSL connection using %s %s\n", SSL_get_version(ssl), SSL_get_cipher (ssl)); 147a98d478eSShuo Chen if (i == 0) 148a98d478eSShuo Chen printf ("SSL connection using %s %s\n", SSL_get_version(ssl_client), SSL_get_cipher (ssl_client)); 149a98d478eSShuo Chen //SSL_clear(ssl); 150a98d478eSShuo Chen //SSL_clear(ssl_client); 151a98d478eSShuo Chen if (i != N-1) 152a98d478eSShuo Chen { 153a98d478eSShuo Chen SSL_free (ssl); 154a98d478eSShuo Chen SSL_free (ssl_client); 155a98d478eSShuo Chen } 156a98d478eSShuo Chen } 157a98d478eSShuo Chen double elapsed = now() - start; 158a98d478eSShuo Chen printf("%.2fs %.1f handshakes/s\n", elapsed, N / elapsed); 1599acb42f4SShuo Chen printf("client %.3f %.1f\n", tc.seconds(), N / tc.seconds()); 1609acb42f4SShuo Chen printf("server %.3f %.1f\n", ts.seconds(), N / ts.seconds()); 1619acb42f4SShuo Chen printf("server/client %.2f\n", ts.seconds() / tc.seconds()); 1629acb42f4SShuo Chen 163a98d478eSShuo Chen 164a98d478eSShuo Chen double start2 = now(); 165a98d478eSShuo Chen const int M = 300; 166a98d478eSShuo Chen char buf[1024] = { 0 }; 167a98d478eSShuo Chen for (int i = 0; i < M*1024; ++i) 168a98d478eSShuo Chen { 169a98d478eSShuo Chen int n = SSL_write(ssl_client, buf, sizeof buf); 170a98d478eSShuo Chen if (n < 0) 171a98d478eSShuo Chen { 1729acb42f4SShuo Chen printf("%d\n", n); 173a98d478eSShuo Chen } 174a98d478eSShuo Chen clientOut.retrieveAll(); 175a98d478eSShuo Chen } 176a98d478eSShuo Chen elapsed = now() - start2; 177a98d478eSShuo Chen printf("%.2f %.1f MiB/s\n", elapsed, M / elapsed); 178a98d478eSShuo Chen SSL_free (ssl); 179a98d478eSShuo Chen SSL_free (ssl_client); 180a98d478eSShuo Chen 181a98d478eSShuo Chen SSL_CTX_free (ctx); 182a98d478eSShuo Chen SSL_CTX_free (ctx_client); 183a98d478eSShuo Chen} 184