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