13af4c543SShuo Chen#include <openssl/aes.h>
23af4c543SShuo Chen#include <openssl/conf.h>
33af4c543SShuo Chen#include <openssl/err.h>
43af4c543SShuo Chen#include <openssl/ssl.h>
53af4c543SShuo Chen
63af4c543SShuo Chen#include <malloc.h>
73af4c543SShuo Chen#include <mcheck.h>
83af4c543SShuo Chen#include <stdio.h>
93af4c543SShuo Chen#include <sys/socket.h>
103af4c543SShuo Chen
113af4c543SShuo Chen#include "timer.h"
123af4c543SShuo Chen
133af4c543SShuo Chen#include <string>
143af4c543SShuo Chen#include <vector>
153af4c543SShuo Chen
163af4c543SShuo Chenusing std::string;
173af4c543SShuo Chenstring readStatus()
183af4c543SShuo Chen{
193af4c543SShuo Chen  string result;
203af4c543SShuo Chen  FILE* fp = fopen("/proc/self/status", "r");
213af4c543SShuo Chen  char buf[8192];
223af4c543SShuo Chen  int nr = fread(buf, 1, sizeof buf, fp);
233af4c543SShuo Chen  result.append(buf, nr);
243af4c543SShuo Chen  return result;
253af4c543SShuo Chen}
263af4c543SShuo Chen
273af4c543SShuo Chenint main(int argc, char* argv[])
283af4c543SShuo Chen{
293af4c543SShuo Chen  SSL_load_error_strings();
303af4c543SShuo Chen  ERR_load_BIO_strings();
313af4c543SShuo Chen  SSL_library_init();
323af4c543SShuo Chen  OPENSSL_config(NULL);
333af4c543SShuo Chen
343af4c543SShuo Chen  SSL_CTX* ctx = SSL_CTX_new(TLSv1_2_server_method());
353af4c543SShuo Chen  SSL_CTX_set_options(ctx, SSL_OP_NO_COMPRESSION);
363af4c543SShuo Chen
373af4c543SShuo Chen  EC_KEY* ecdh = EC_KEY_new_by_curve_name(NID_X9_62_prime256v1);
383af4c543SShuo Chen  SSL_CTX_set_options(ctx, SSL_OP_SINGLE_ECDH_USE);
393af4c543SShuo Chen  SSL_CTX_set_tmp_ecdh(ctx, ecdh);
403af4c543SShuo Chen  EC_KEY_free(ecdh);
413af4c543SShuo Chen
423af4c543SShuo Chen  const char* CertFile = "server.pem";  // argv[1];
433af4c543SShuo Chen  const char* KeyFile = "server.pem";  // argv[2];
443af4c543SShuo Chen  SSL_CTX_use_certificate_file(ctx, CertFile, SSL_FILETYPE_PEM);
453af4c543SShuo Chen  SSL_CTX_use_PrivateKey_file(ctx, KeyFile, SSL_FILETYPE_PEM);
463af4c543SShuo Chen  if (!SSL_CTX_check_private_key(ctx))
473af4c543SShuo Chen    abort();
483af4c543SShuo Chen
493af4c543SShuo Chen  SSL_CTX* ctx_client = SSL_CTX_new(TLSv1_2_client_method());
503af4c543SShuo Chen
513af4c543SShuo Chen  string st0 = readStatus();
523af4c543SShuo Chen  double start = now();
533af4c543SShuo Chen  const int N = 1000;
543af4c543SShuo Chen  struct mallinfo mi0 = mallinfo();
553af4c543SShuo Chen  std::vector<SSL*> ssls;
563af4c543SShuo Chen
573af4c543SShuo Chen  for (int i = 0; i < N; ++i)
583af4c543SShuo Chen  {
593af4c543SShuo Chen    int fds[2];
603af4c543SShuo Chen    if (socketpair(AF_UNIX, SOCK_STREAM | SOCK_NONBLOCK, 0, fds) != 0)
613af4c543SShuo Chen      abort();
623af4c543SShuo Chen
633af4c543SShuo Chen    SSL* ssl = SSL_new (ctx);
643af4c543SShuo Chen    SSL* ssl_client = SSL_new (ctx_client);
653af4c543SShuo Chen    SSL_set_fd(ssl, fds[0]);
663af4c543SShuo Chen    SSL_set_fd(ssl_client, fds[1]);
673af4c543SShuo Chen
683af4c543SShuo Chen    int ret = SSL_connect(ssl_client);
693af4c543SShuo Chen    int ret2 = SSL_accept(ssl);
703af4c543SShuo Chen
713af4c543SShuo Chen    while (true)
723af4c543SShuo Chen    {
733af4c543SShuo Chen      ret = SSL_do_handshake(ssl_client);
743af4c543SShuo Chen      ret2 = SSL_do_handshake(ssl);
753af4c543SShuo Chen      if (ret == 1 && ret2 == 1)
763af4c543SShuo Chen        break;
773af4c543SShuo Chen    }
783af4c543SShuo Chen
793af4c543SShuo Chen    if (i == 0)
803af4c543SShuo Chen      printf ("SSL connection using %s %s\n", SSL_get_version(ssl_client), SSL_get_cipher (ssl_client));
813af4c543SShuo Chen    ssls.push_back(ssl);
823af4c543SShuo Chen    ssls.push_back(ssl_client);
833af4c543SShuo Chen  }
843af4c543SShuo Chen  double elapsed = now() - start;
853af4c543SShuo Chen  printf("%.2fs %.1f handshakes/s\n", elapsed, N / elapsed);
863af4c543SShuo Chen  struct mallinfo mi1 = mallinfo();
873af4c543SShuo Chen  string st1 = readStatus();
883af4c543SShuo Chen  printf("%s\n", st0.c_str());
893af4c543SShuo Chen  printf("%s\n", st1.c_str());
903af4c543SShuo Chen  for (int i = 0; i < ssls.size(); ++i)
913af4c543SShuo Chen    SSL_free(ssls[i]);
923af4c543SShuo Chen
933af4c543SShuo Chen  // string st2 = readStatus();
943af4c543SShuo Chen  struct mallinfo mi2 = mallinfo();
953af4c543SShuo Chen  SSL_CTX_free (ctx);
963af4c543SShuo Chen  SSL_CTX_free (ctx_client);
973af4c543SShuo Chen  // string st3 = readStatus();
983af4c543SShuo Chen  struct mallinfo mi3 = mallinfo();
993af4c543SShuo Chen  // printf("after SSL_free\n%s\n", st2.c_str());
1003af4c543SShuo Chen  // printf("after SSL_CTX_free\n%s\n", st3.c_str());
1013af4c543SShuo Chen  // OPENSSL_cleanup();  // only in 1.1.0
1023af4c543SShuo Chen  printf("\n");
1033af4c543SShuo Chen}
104