1#include <openssl/aes.h>
2#include <openssl/conf.h>
3#include <openssl/err.h>
4#include <openssl/ssl.h>
5
6#include <stdio.h>
7
8#include "timer.h"
9
10int main(int argc, char* argv[])
11{
12  printf("Compiled with " OPENSSL_VERSION_TEXT "\n");
13  SSL_load_error_strings();
14  // ERR_load_BIO_strings();
15  SSL_library_init();
16  OPENSSL_config(NULL);
17
18  SSL_CTX* ctx = SSL_CTX_new(TLSv1_2_server_method());
19  SSL_CTX_set_options(ctx, SSL_OP_NO_COMPRESSION);
20
21  EC_KEY* ecdh = EC_KEY_new_by_curve_name(NID_X9_62_prime256v1);
22  SSL_CTX_set_options(ctx, SSL_OP_SINGLE_ECDH_USE);
23  // if (argc > 3)
24  SSL_CTX_set_tmp_ecdh(ctx, ecdh);
25  EC_KEY_free(ecdh);
26
27  const char* CertFile = "server.pem";  // argv[1];
28  const char* KeyFile = "server.pem";  // argv[2];
29  SSL_CTX_use_certificate_file(ctx, CertFile, SSL_FILETYPE_PEM);
30  SSL_CTX_use_PrivateKey_file(ctx, KeyFile, SSL_FILETYPE_PEM);
31  if (!SSL_CTX_check_private_key(ctx))
32    abort();
33
34  SSL_CTX* ctx_client = SSL_CTX_new(TLSv1_2_client_method());
35
36  double start = now();
37  const int N = 1000;
38  SSL *ssl, *ssl_client;
39  Timer tc, ts;
40  for (int i = 0; i < N; ++i)
41  {
42    BIO *client, *server;
43    BIO_new_bio_pair(&client, 0, &server, 0);
44
45    ssl = SSL_new (ctx);
46    ssl_client = SSL_new (ctx_client);
47    SSL_set_bio(ssl, server, server);
48    SSL_set_bio(ssl_client, client, client);
49
50    tc.start();
51    int ret = SSL_connect(ssl_client);
52    tc.stop();
53    //printf("%d %d\n", ret, BIO_retry_type(&server));
54    ts.start();
55    int ret2 = SSL_accept(ssl);
56    ts.stop();
57    //printf("%d %d\n", ret2, BIO_retry_type(&client));
58
59    while (true)
60    {
61      tc.start();
62      ret = SSL_do_handshake(ssl_client);
63      tc.stop();
64      //printf("client handshake %d %d\n", ret, BIO_retry_type(&server));
65      ts.start();
66      ret2 = SSL_do_handshake(ssl);
67      ts.stop();
68      //printf("server handshake %d %d\n", ret2, BIO_retry_type(&client));
69      //if (ret == -1 && BIO_retry_type(&server) == 0)
70      //  break;
71      //if (ret2 == -1 && BIO_retry_type(&client) == 0)
72      //  break;
73      if (ret == 1 && ret2 == 1)
74        break;
75    }
76
77    if (i == 0)
78    {
79      printf("SSL connection using %s %s\n", SSL_get_version(ssl_client), SSL_get_cipher (ssl_client));
80#ifdef OPENSSL_IS_BORINGSSL
81      printf("Curve: %s\n", SSL_get_curve_name(SSL_get_curve_id(ssl_client)));
82#elif OPENSSL_VERSION_NUMBER >= 0x10002000L
83      EVP_PKEY *key;
84      if (SSL_get_server_tmp_key(ssl_client, &key))
85      {
86        if (EVP_PKEY_id(key) == EVP_PKEY_EC)
87        {
88          EC_KEY *ec = EVP_PKEY_get1_EC_KEY(key);
89          int nid = EC_GROUP_get_curve_name(EC_KEY_get0_group(ec));
90          EC_KEY_free(ec);
91          const char *cname = EC_curve_nid2nist(nid);
92          if (!cname)
93            cname = OBJ_nid2sn(nid);
94          printf("Curve: %s, %d bits\n", cname, EVP_PKEY_bits(key));
95        }
96      }
97#endif
98    }
99    if (i != N-1)
100    {
101      SSL_free (ssl);
102      SSL_free (ssl_client);
103    }
104  }
105  double elapsed = now() - start;
106  printf("%.2fs %.1f handshakes/s\n", elapsed, N / elapsed);
107  printf("client %.3f %.1f\n", tc.seconds(), N / tc.seconds());
108  printf("server %.3f %.1f\n", ts.seconds(), N / ts.seconds());
109  printf("server/client %.2f\n", ts.seconds() / tc.seconds());
110
111
112  double start2 = now();
113  const int M = 1000;
114  char buf[1024] = { 0 };
115  for (int i = 0; i < M*1024; ++i)
116  {
117    int nw = SSL_write(ssl_client, buf, sizeof buf);
118    if (nw != sizeof buf)
119    {
120      printf("nw = %d\n", nw);
121    }
122    int nr = SSL_read(ssl, buf, sizeof buf);
123    if (nr != sizeof buf)
124    {
125      printf("nr = %d\n", nr);
126    }
127  }
128  elapsed = now() - start2;
129  printf("%.2f %.1f MiB/s\n", elapsed, M / elapsed);
130  SSL_free (ssl);
131  SSL_free (ssl_client);
132
133  SSL_CTX_free (ctx);
134  SSL_CTX_free (ctx_client);
135}
136