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 <stdio.h>
7a98d478eSShuo Chen
89acb42f4SShuo Chen#include "timer.h"
99acb42f4SShuo Chen
10a98d478eSShuo Chenint main(int argc, char* argv[])
11a98d478eSShuo Chen{
123592419dSShuo Chen  printf("Compiled with " OPENSSL_VERSION_TEXT "\n");
13a98d478eSShuo Chen  SSL_load_error_strings();
14a98d478eSShuo Chen  // ERR_load_BIO_strings();
15a98d478eSShuo Chen  SSL_library_init();
16a98d478eSShuo Chen  OPENSSL_config(NULL);
17a98d478eSShuo Chen
18b140ba61SShuo Chen  SSL_CTX* ctx = SSL_CTX_new(TLSv1_2_server_method());
193af4c543SShuo Chen  SSL_CTX_set_options(ctx, SSL_OP_NO_COMPRESSION);
20a98d478eSShuo Chen
21a98d478eSShuo Chen  EC_KEY* ecdh = EC_KEY_new_by_curve_name(NID_X9_62_prime256v1);
22a98d478eSShuo Chen  SSL_CTX_set_options(ctx, SSL_OP_SINGLE_ECDH_USE);
23132b87adSShuo Chen  // if (argc > 3)
24132b87adSShuo Chen  SSL_CTX_set_tmp_ecdh(ctx, ecdh);
25a98d478eSShuo Chen  EC_KEY_free(ecdh);
26a98d478eSShuo Chen
27b140ba61SShuo Chen  const char* CertFile = "server.pem";  // argv[1];
28b140ba61SShuo Chen  const char* KeyFile = "server.pem";  // argv[2];
29a98d478eSShuo Chen  SSL_CTX_use_certificate_file(ctx, CertFile, SSL_FILETYPE_PEM);
30a98d478eSShuo Chen  SSL_CTX_use_PrivateKey_file(ctx, KeyFile, SSL_FILETYPE_PEM);
31a98d478eSShuo Chen  if (!SSL_CTX_check_private_key(ctx))
32a98d478eSShuo Chen    abort();
33a98d478eSShuo Chen
34b140ba61SShuo Chen  SSL_CTX* ctx_client = SSL_CTX_new(TLSv1_2_client_method());
35a98d478eSShuo Chen
36a98d478eSShuo Chen  double start = now();
37a98d478eSShuo Chen  const int N = 1000;
38a98d478eSShuo Chen  SSL *ssl, *ssl_client;
399acb42f4SShuo Chen  Timer tc, ts;
40a98d478eSShuo Chen  for (int i = 0; i < N; ++i)
41a98d478eSShuo Chen  {
42132b87adSShuo Chen    BIO *client, *server;
43132b87adSShuo Chen    BIO_new_bio_pair(&client, 0, &server, 0);
44132b87adSShuo Chen
45a98d478eSShuo Chen    ssl = SSL_new (ctx);
46a98d478eSShuo Chen    ssl_client = SSL_new (ctx_client);
47132b87adSShuo Chen    SSL_set_bio(ssl, server, server);
48132b87adSShuo Chen    SSL_set_bio(ssl_client, client, client);
49a98d478eSShuo Chen
509acb42f4SShuo Chen    tc.start();
51a98d478eSShuo Chen    int ret = SSL_connect(ssl_client);
529acb42f4SShuo Chen    tc.stop();
53a98d478eSShuo Chen    //printf("%d %d\n", ret, BIO_retry_type(&server));
549acb42f4SShuo Chen    ts.start();
55a98d478eSShuo Chen    int ret2 = SSL_accept(ssl);
569acb42f4SShuo Chen    ts.stop();
57a98d478eSShuo Chen    //printf("%d %d\n", ret2, BIO_retry_type(&client));
58a98d478eSShuo Chen
59a98d478eSShuo Chen    while (true)
60a98d478eSShuo Chen    {
619acb42f4SShuo Chen      tc.start();
629acb42f4SShuo Chen      ret = SSL_do_handshake(ssl_client);
639acb42f4SShuo Chen      tc.stop();
64a98d478eSShuo Chen      //printf("client handshake %d %d\n", ret, BIO_retry_type(&server));
659acb42f4SShuo Chen      ts.start();
669acb42f4SShuo Chen      ret2 = SSL_do_handshake(ssl);
679acb42f4SShuo Chen      ts.stop();
68a98d478eSShuo Chen      //printf("server handshake %d %d\n", ret2, BIO_retry_type(&client));
69a98d478eSShuo Chen      //if (ret == -1 && BIO_retry_type(&server) == 0)
70a98d478eSShuo Chen      //  break;
71a98d478eSShuo Chen      //if (ret2 == -1 && BIO_retry_type(&client) == 0)
72a98d478eSShuo Chen      //  break;
73a98d478eSShuo Chen      if (ret == 1 && ret2 == 1)
74a98d478eSShuo Chen        break;
75a98d478eSShuo Chen    }
76a98d478eSShuo Chen
77a98d478eSShuo Chen    if (i == 0)
783592419dSShuo Chen    {
793592419dSShuo Chen      printf("SSL connection using %s %s\n", SSL_get_version(ssl_client), SSL_get_cipher (ssl_client));
803592419dSShuo Chen#ifdef OPENSSL_IS_BORINGSSL
813592419dSShuo Chen      printf("Curve: %s\n", SSL_get_curve_name(SSL_get_curve_id(ssl_client)));
823592419dSShuo Chen#elif OPENSSL_VERSION_NUMBER >= 0x10002000L
833592419dSShuo Chen      EVP_PKEY *key;
843592419dSShuo Chen      if (SSL_get_server_tmp_key(ssl_client, &key))
853592419dSShuo Chen      {
863592419dSShuo Chen        if (EVP_PKEY_id(key) == EVP_PKEY_EC)
873592419dSShuo Chen        {
883592419dSShuo Chen          EC_KEY *ec = EVP_PKEY_get1_EC_KEY(key);
893592419dSShuo Chen          int nid = EC_GROUP_get_curve_name(EC_KEY_get0_group(ec));
903592419dSShuo Chen          EC_KEY_free(ec);
913592419dSShuo Chen          const char *cname = EC_curve_nid2nist(nid);
923592419dSShuo Chen          if (!cname)
933592419dSShuo Chen            cname = OBJ_nid2sn(nid);
943592419dSShuo Chen          printf("Curve: %s, %d bits\n", cname, EVP_PKEY_bits(key));
953592419dSShuo Chen        }
963592419dSShuo Chen      }
973592419dSShuo Chen#endif
983592419dSShuo Chen    }
99a98d478eSShuo Chen    if (i != N-1)
100a98d478eSShuo Chen    {
101a98d478eSShuo Chen      SSL_free (ssl);
102a98d478eSShuo Chen      SSL_free (ssl_client);
103a98d478eSShuo Chen    }
104a98d478eSShuo Chen  }
105a98d478eSShuo Chen  double elapsed = now() - start;
106a98d478eSShuo Chen  printf("%.2fs %.1f handshakes/s\n", elapsed, N / elapsed);
1079acb42f4SShuo Chen  printf("client %.3f %.1f\n", tc.seconds(), N / tc.seconds());
1089acb42f4SShuo Chen  printf("server %.3f %.1f\n", ts.seconds(), N / ts.seconds());
1099acb42f4SShuo Chen  printf("server/client %.2f\n", ts.seconds() / tc.seconds());
1109acb42f4SShuo Chen
111a98d478eSShuo Chen
112a98d478eSShuo Chen  double start2 = now();
113cc4062ffSShuo Chen  const int M = 1000;
114a98d478eSShuo Chen  char buf[1024] = { 0 };
115a98d478eSShuo Chen  for (int i = 0; i < M*1024; ++i)
116a98d478eSShuo Chen  {
117132b87adSShuo Chen    int nw = SSL_write(ssl_client, buf, sizeof buf);
118132b87adSShuo Chen    if (nw != sizeof buf)
119132b87adSShuo Chen    {
120132b87adSShuo Chen      printf("nw = %d\n", nw);
121132b87adSShuo Chen    }
122132b87adSShuo Chen    int nr = SSL_read(ssl, buf, sizeof buf);
123132b87adSShuo Chen    if (nr != sizeof buf)
124a98d478eSShuo Chen    {
125132b87adSShuo Chen      printf("nr = %d\n", nr);
126a98d478eSShuo Chen    }
127a98d478eSShuo Chen  }
128a98d478eSShuo Chen  elapsed = now() - start2;
129a98d478eSShuo Chen  printf("%.2f %.1f MiB/s\n", elapsed, M / elapsed);
130a98d478eSShuo Chen  SSL_free (ssl);
131a98d478eSShuo Chen  SSL_free (ssl_client);
132a98d478eSShuo Chen
133a98d478eSShuo Chen  SSL_CTX_free (ctx);
134a98d478eSShuo Chen  SSL_CTX_free (ctx_client);
135a98d478eSShuo Chen}
136