1#include <polarssl/ctr_drbg.h>
2#include <polarssl/error.h>
3#include <polarssl/entropy.h>
4#include <polarssl/ssl.h>
5
6#include <polarssl/certs.h>
7
8#include <muduo/net/Buffer.h>
9#include <string>
10#include <stdio.h>
11#include <sys/time.h>
12#include "timer.h"
13
14muduo::net::Buffer clientOut, serverOut;
15
16int net_recv(void* ctx, unsigned char* buf, size_t len)
17{
18  muduo::net::Buffer* in = static_cast<muduo::net::Buffer*>(ctx);
19  //printf("%s recv %zd\n", in == &clientOut ? "server" : "client", len);
20  if (in->readableBytes() > 0)
21  {
22    size_t n = std::min(in->readableBytes(), len);
23    memcpy(buf, in->peek(), n);
24    in->retrieve(n);
25
26    /*
27    if (n < len)
28      printf("got %zd\n", n);
29    else
30      printf("\n");
31      */
32    return n;
33  }
34  else
35  {
36    //printf("got 0\n");
37    return POLARSSL_ERR_NET_WANT_READ;
38  }
39}
40
41int net_send(void* ctx, const unsigned char* buf, size_t len)
42{
43  muduo::net::Buffer* out = static_cast<muduo::net::Buffer*>(ctx);
44  // printf("%s send %zd\n", out == &clientOut ? "client" : "server", len);
45  out->append(buf, len);
46  return len;
47}
48
49int main(int argc, char* argv[])
50{
51  entropy_context entropy;
52  entropy_init(&entropy);
53  ctr_drbg_context ctr_drbg;
54  ctr_drbg_init(&ctr_drbg, entropy_func, &entropy, NULL, 0);
55
56  ssl_context ssl;
57  bzero(&ssl, sizeof ssl);
58  ssl_init(&ssl);
59  ssl_set_rng(&ssl, ctr_drbg_random, &ctr_drbg);
60  ssl_set_bio(&ssl, &net_recv, &serverOut, &net_send, &clientOut);
61  ssl_set_endpoint(&ssl, SSL_IS_CLIENT);
62  ssl_set_authmode(&ssl, SSL_VERIFY_NONE);
63
64  const char* srv_cert = test_srv_crt_ec;
65  const char* srv_key = test_srv_key_ec;
66  std::string arg = argc > 1 ? argv[1] : "r";
67  bool useRSA = arg == "r" || arg == "er";
68  bool useECDHE = arg == "er" || arg == "ee";
69  if (useRSA)
70  {
71    srv_cert = test_srv_crt;
72    srv_key = test_srv_key;
73  }
74  x509_crt cert;
75  x509_crt_init(&cert);
76  // int ret = x509_crt_parse_file(&cert, argv[1]);
77  // printf("cert parse %d\n", ret);
78  x509_crt_parse(&cert, reinterpret_cast<const unsigned char*>(srv_cert), strlen(srv_cert));
79  x509_crt_parse(&cert, reinterpret_cast<const unsigned char*>(test_ca_list), strlen(test_ca_list));
80
81  pk_context pkey;
82  pk_init(&pkey);
83  pk_parse_key(&pkey, reinterpret_cast<const unsigned char*>(srv_key), strlen(srv_key), NULL, 0);
84  // ret = pk_parse_keyfile(&pkey, argv[2], NULL);
85  // printf("key parse %d\n", ret);
86
87  ssl_context ssl_server;
88  bzero(&ssl_server, sizeof ssl_server);
89  ssl_init(&ssl_server);
90  ssl_set_rng(&ssl_server, ctr_drbg_random, &ctr_drbg);
91  ssl_set_bio(&ssl_server, &net_recv, &clientOut, &net_send, &serverOut);
92  ssl_set_endpoint(&ssl_server, SSL_IS_SERVER);
93  ssl_set_authmode(&ssl_server, SSL_VERIFY_NONE);
94  //ssl_set_ca_chain(&ssl_server, cert.next, NULL, NULL);
95  ssl_set_own_cert(&ssl_server, &cert, &pkey);
96  ecp_group_id curves[] = { POLARSSL_ECP_DP_SECP256R1, POLARSSL_ECP_DP_SECP224K1, POLARSSL_ECP_DP_NONE };
97  ssl_set_curves(&ssl_server, curves);
98  if (useECDHE)
99  {
100    int ciphersuites[] = { TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA, TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA, 0 };
101    ssl_set_ciphersuites(&ssl_server, ciphersuites);
102  }
103  else
104  {
105    int ciphersuites[] = { TLS_ECDH_ECDSA_WITH_AES_256_CBC_SHA, TLS_RSA_WITH_AES_256_CBC_SHA, 0 };
106    ssl_set_ciphersuites(&ssl_server, ciphersuites);
107  }
108
109  double start = now();
110  Timer tc, ts;
111  const int N = 500;
112  for (int i = 0; i < N; ++i)
113  {
114    ssl_session_reset(&ssl);
115    ssl_session_reset(&ssl_server);
116    while (true)
117    {
118      tc.start();
119      int ret = ssl_handshake(&ssl);
120      tc.stop();
121      //printf("ssl %d\n", ret);
122      if (ret < 0)
123      {
124        if (ret != POLARSSL_ERR_NET_WANT_READ)
125        {
126          char errbuf[512];
127          polarssl_strerror(ret, errbuf, sizeof errbuf);
128          printf("client error %d %s\n", ret, errbuf);
129          break;
130        }
131      }
132      else if (ret == 0 && i == 0)
133      {
134        printf("client done %s %s\n", ssl_get_version(&ssl), ssl_get_ciphersuite(&ssl));
135      }
136
137      ts.start();
138      int ret2 = ssl_handshake(&ssl_server);
139      ts.stop();
140      // printf("srv %d\n", ret2);
141      if (ret2 < 0)
142      {
143        if (ret != POLARSSL_ERR_NET_WANT_READ)
144        {
145          char errbuf[512];
146          polarssl_strerror(ret2, errbuf, sizeof errbuf);
147          printf("server error %d %s\n", ret2, errbuf);
148          break;
149        }
150      }
151      else if (ret2 == 0)
152      {
153        // printf("server done %s %s\n", ssl_get_version(&ssl_server), ssl_get_ciphersuite(&ssl_server));
154      }
155
156      if (ret == 0 && ret2 == 0)
157        break;
158    }
159  }
160  double elapsed = now() - start;
161  printf("%.2fs %.1f handshakes/s\n", elapsed, N / elapsed);
162  printf("client %.3f %.1f\n", tc.seconds(), N / tc.seconds());
163  printf("server %.3f %.1f\n", ts.seconds(), N / ts.seconds());
164  printf("server/client %.2f\n", ts.seconds() / tc.seconds());
165
166  double start2 = now();
167  const int M = 200;
168  unsigned char buf[16384] = { 0 };
169  for (int i = 0; i < M*1024; ++i)
170  {
171    int n = ssl_write(&ssl, buf, 1024);
172    if (n < 0)
173    {
174      char errbuf[512];
175      polarssl_strerror(n, errbuf, sizeof errbuf);
176      printf("%s\n", errbuf);
177    }
178    /*
179    n = ssl_read(&ssl_server, buf, 8192);
180    if (n != 1024)
181      break;
182    if (n < 0)
183    {
184      char errbuf[512];
185      polarssl_strerror(n, errbuf, sizeof errbuf);
186      printf("%s\n", errbuf);
187    }
188    */
189    clientOut.retrieveAll();
190  }
191  elapsed = now() - start2;
192  printf("%.2f %.1f MiB/s\n", elapsed, M / elapsed);
193
194  ssl_free(&ssl);
195  ssl_free(&ssl_server);
196  pk_free(&pkey);
197  x509_crt_free(&cert);
198  entropy_free(&entropy);
199}
200