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