19acb42f4SShuo Chen/*
29acb42f4SShuo Chen * Remember to turn off CPU frequency scaling before testing.
39acb42f4SShuo Chen */
49acb42f4SShuo Chen
59acb42f4SShuo Chen
6a98d478eSShuo Chen#include <polarssl/ctr_drbg.h>
7a98d478eSShuo Chen#include <polarssl/error.h>
8a98d478eSShuo Chen#include <polarssl/entropy.h>
9a98d478eSShuo Chen#include <polarssl/ssl.h>
10a98d478eSShuo Chen
11a98d478eSShuo Chen#include <polarssl/certs.h>
12a98d478eSShuo Chen
13a98d478eSShuo Chen#include <muduo/base/Thread.h>
14a98d478eSShuo Chen
15a98d478eSShuo Chen#include <boost/bind.hpp>
16a98d478eSShuo Chen
17a98d478eSShuo Chen#include <stdio.h>
18a98d478eSShuo Chen#include <sys/socket.h>
199acb42f4SShuo Chen#include <sys/time.h>
20a98d478eSShuo Chen
21a98d478eSShuo Chenbool useRSA = false;
229acb42f4SShuo Chenbool useECDHE = false;
23a98d478eSShuo Chenconst int N = 500;
24a98d478eSShuo Chen
259acb42f4SShuo Chendouble now()
269acb42f4SShuo Chen{
279acb42f4SShuo Chen  struct timeval tv;
289acb42f4SShuo Chen  gettimeofday(&tv, NULL);
299acb42f4SShuo Chen  return tv.tv_sec + tv.tv_usec / 1000000.0;
309acb42f4SShuo Chen}
319acb42f4SShuo Chen
32a98d478eSShuo Chen// FIXME: net_recv with buffer
33a98d478eSShuo Chen
34a98d478eSShuo Chenvoid clientThread(entropy_context* entropy, int* clientFd)
35a98d478eSShuo Chen{
36a98d478eSShuo Chen  ctr_drbg_context ctr_drbg;
37a98d478eSShuo Chen  ctr_drbg_init(&ctr_drbg, entropy_func, entropy, NULL, 0);
38a98d478eSShuo Chen
39a98d478eSShuo Chen  ssl_context ssl;
40a98d478eSShuo Chen  bzero(&ssl, sizeof ssl);
41a98d478eSShuo Chen  ssl_init(&ssl);
42a98d478eSShuo Chen  ssl_set_rng(&ssl, ctr_drbg_random, &ctr_drbg);
43a98d478eSShuo Chen  ssl_set_bio(&ssl, &net_recv, clientFd, &net_send, clientFd);
44a98d478eSShuo Chen  ssl_set_endpoint(&ssl, SSL_IS_CLIENT);
45a98d478eSShuo Chen  ssl_set_authmode(&ssl, SSL_VERIFY_NONE);
46a98d478eSShuo Chen
47a98d478eSShuo Chen  for (int i = 0; i < N; ++i)
48a98d478eSShuo Chen  {
49a98d478eSShuo Chen    ssl_session_reset( &ssl );
50a98d478eSShuo Chen    int ret = 0;
51a98d478eSShuo Chen    while ( (ret = ssl_handshake(&ssl)) != 0)
52a98d478eSShuo Chen    {
53a98d478eSShuo Chen      if (ret != POLARSSL_ERR_NET_WANT_READ && ret != POLARSSL_ERR_NET_WANT_WRITE)
54a98d478eSShuo Chen      {
55a98d478eSShuo Chen        printf("client handshake failed %d\n", ret);
56a98d478eSShuo Chen        break;
57a98d478eSShuo Chen      }
58a98d478eSShuo Chen    }
59a98d478eSShuo Chen    if (i == 0)
60a98d478eSShuo Chen      printf("client done %s %s\n", ssl_get_version(&ssl), ssl_get_ciphersuite(&ssl));
61a98d478eSShuo Chen  }
62a98d478eSShuo Chen
63a98d478eSShuo Chen  ssl_free(&ssl);
64a98d478eSShuo Chen}
65a98d478eSShuo Chen
66a98d478eSShuo Chenvoid serverThread(entropy_context* entropy, int* serverFd)
67a98d478eSShuo Chen{
68a98d478eSShuo Chen  const char* srv_cert = test_srv_crt_ec;
69a98d478eSShuo Chen  const char* srv_key = test_srv_key_ec;
70a98d478eSShuo Chen  if (useRSA)
71a98d478eSShuo Chen  {
72a98d478eSShuo Chen    srv_cert = test_srv_crt;
73a98d478eSShuo Chen    srv_key = test_srv_key;
74a98d478eSShuo Chen  }
75a98d478eSShuo Chen  x509_crt cert;
76a98d478eSShuo Chen  x509_crt_init(&cert);
77a98d478eSShuo Chen  x509_crt_parse(&cert, reinterpret_cast<const unsigned char*>(srv_cert), strlen(srv_cert));
78a98d478eSShuo Chen  x509_crt_parse(&cert, reinterpret_cast<const unsigned char*>(test_ca_list), strlen(test_ca_list));
79a98d478eSShuo Chen
80a98d478eSShuo Chen  pk_context pkey;
81a98d478eSShuo Chen  pk_init(&pkey);
82a98d478eSShuo Chen  pk_parse_key(&pkey, reinterpret_cast<const unsigned char*>(srv_key), strlen(srv_key), NULL, 0);
83a98d478eSShuo Chen
84a98d478eSShuo Chen  ctr_drbg_context ctr_drbg;
85a98d478eSShuo Chen  ctr_drbg_init(&ctr_drbg, entropy_func, entropy, NULL, 0);
86a98d478eSShuo Chen
87a98d478eSShuo Chen  ssl_context ssl_server;
88a98d478eSShuo Chen  bzero(&ssl_server, sizeof ssl_server);
89a98d478eSShuo Chen  ssl_init(&ssl_server);
90a98d478eSShuo Chen  ssl_set_rng(&ssl_server, ctr_drbg_random, &ctr_drbg);
91a98d478eSShuo Chen  ssl_set_bio(&ssl_server, &net_recv, serverFd, &net_send, serverFd);
92a98d478eSShuo Chen  ssl_set_endpoint(&ssl_server, SSL_IS_SERVER);
93a98d478eSShuo Chen  ssl_set_authmode(&ssl_server, SSL_VERIFY_NONE);
94a98d478eSShuo Chen  ssl_set_ca_chain(&ssl_server, cert.next, NULL, NULL);
95a98d478eSShuo Chen  ssl_set_own_cert(&ssl_server, &cert, &pkey);
96a98d478eSShuo Chen  // ssl_set_dbg(&ssl_server, my_debug, (void*)"server");
97a98d478eSShuo Chen  ecp_group_id curves[] = { POLARSSL_ECP_DP_SECP256R1, POLARSSL_ECP_DP_NONE };
98a98d478eSShuo Chen  ssl_set_curves(&ssl_server, curves);
999acb42f4SShuo Chen  int ciphersuites[] = { TLS_ECDH_ECDSA_WITH_AES_256_CBC_SHA, TLS_RSA_WITH_AES_256_CBC_SHA, 0 };
1009acb42f4SShuo Chen  if (!useECDHE)
1019acb42f4SShuo Chen    ssl_set_ciphersuites(&ssl_server, ciphersuites);
102a98d478eSShuo Chen
103a98d478eSShuo Chen  for (int i = 0; i < N; ++i)
104a98d478eSShuo Chen  {
105a98d478eSShuo Chen    ssl_session_reset(&ssl_server);
106a98d478eSShuo Chen    int ret = 0;
107a98d478eSShuo Chen    while ( (ret = ssl_handshake(&ssl_server)) != 0)
108a98d478eSShuo Chen    {
109a98d478eSShuo Chen      if (ret != POLARSSL_ERR_NET_WANT_READ && ret != POLARSSL_ERR_NET_WANT_WRITE)
110a98d478eSShuo Chen      {
111a98d478eSShuo Chen        printf("server handshake failed %d\n", ret);
112a98d478eSShuo Chen        break;
113a98d478eSShuo Chen      }
114a98d478eSShuo Chen    }
115a98d478eSShuo Chen    if (i == 0)
116a98d478eSShuo Chen      printf("server done %s %s\n", ssl_get_version(&ssl_server), ssl_get_ciphersuite(&ssl_server));
117a98d478eSShuo Chen  }
118a98d478eSShuo Chen
119a98d478eSShuo Chen  ssl_free(&ssl_server);
120a98d478eSShuo Chen  pk_free(&pkey);
121a98d478eSShuo Chen  x509_crt_free(&cert);
122a98d478eSShuo Chen}
123a98d478eSShuo Chen
124a98d478eSShuo Chenint main(int argc, char* argv[])
125a98d478eSShuo Chen{
126a98d478eSShuo Chen  unsigned char buf[16384] = { 0 };
127a98d478eSShuo Chen  entropy_context entropy;
128a98d478eSShuo Chen  entropy_init(&entropy);
129a98d478eSShuo Chen
130a98d478eSShuo Chen  if (argc > 1)
131a98d478eSShuo Chen    useRSA = true;
132a98d478eSShuo Chen
1339acb42f4SShuo Chen  useECDHE = argc > 2;
1349acb42f4SShuo Chen
135a98d478eSShuo Chen  int fds[2];
136a98d478eSShuo Chen  if (::socketpair(AF_UNIX, SOCK_STREAM, 0, fds))
137a98d478eSShuo Chen    abort();
138a98d478eSShuo Chen
1399acb42f4SShuo Chen  double start = now();
140a98d478eSShuo Chen  muduo::Thread client(boost::bind(&clientThread, &entropy, &fds[0]), "ssl client");
141a98d478eSShuo Chen  muduo::Thread server(boost::bind(&serverThread, &entropy, &fds[1]), "ssl server");
142a98d478eSShuo Chen  client.start();
143a98d478eSShuo Chen  server.start();
144a98d478eSShuo Chen
145a98d478eSShuo Chen  client.join();
146a98d478eSShuo Chen  server.join();
1479acb42f4SShuo Chen  double elapsed = now() - start;
1489acb42f4SShuo Chen  printf("%.2fs %.1f handshakes/s\n", elapsed, N / elapsed);
149a98d478eSShuo Chen  entropy_free(&entropy);
150a98d478eSShuo Chen}
151