gvalkov

g_tls_t OpenSSL

Aug 19th, 2021 (edited)
1,259
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C++ 9.99 KB | None | 0 0
  1. errno_t g_tls_t::init_ctx(G_TLS_MODE_E mode)
  2. {
  3. #if !defined(WIN32) && !defined(_WIN64) && !USE_TLS_OPENSSL_MEM
  4.     signal(SIGPIPE, SIG_IGN);
  5. #endif
  6.  
  7.     // load & register all cryptos, etc.
  8.     // not needed since OpenSSL 1.1.0
  9.     //-OpenSSL_add_all_algorithms();
  10.  
  11.     // load all error messages
  12.     tls_load_error_strings();
  13.  
  14.     if (mode & G_TLS_SERVER)
  15.     {
  16.         wprintf(L"%" _HS_ L"\n", TLS_VERSION);
  17.         server_valid = false;
  18.  
  19.         // create new server context from method
  20.         ctx_server = SSL_CTX_new(tls_server_method());
  21.  
  22.         if (ctx_server == NULL)
  23.         {
  24.             //- tls_err_print_errors_fp(stderr);
  25.             wprintf(L"cannot create server SSL context\n\n");
  26.             return FAIL;
  27.         }
  28.     }
  29.  
  30.     if (mode & G_TLS_CLIENT)
  31.     {
  32.         wprintf(L"%" _HS_ L"\n", TLS_VERSION);
  33.         client_valid = false;
  34.  
  35.         // create new client context from method
  36.         ctx_client = SSL_CTX_new(tls_client_method());
  37.  
  38.         if (ctx_client == NULL)
  39.         {
  40.             //- tls_err_print_errors_fp(stderr);
  41.             wprintf(L"cannot create client SSL context\n\n");
  42.             return FAIL;
  43.         }
  44.  
  45.         client_valid = true;
  46.     }
  47.  
  48.     return OK;
  49. }
  50.  
  51. errno_t g_tls_t::load_cer(G_TLS_MODE_E mode)
  52. {
  53.     if (mode == G_TLS_SERVER)
  54.     {
  55.         server_valid = false;
  56.     }
  57.  
  58.     TLS_CTX_T ctx = (mode == G_TLS_CLIENT) ? ctx_client : ctx_server;
  59.  
  60.     if (!ctx)
  61.     {
  62.         return FAIL;
  63.     }
  64.  
  65. #if defined(WIN32) || defined(_WIN64)
  66.     char * p_cer = c_cer;
  67.     char * p_key = c_key;
  68.  
  69.     // openssl does not support wchar_t
  70.     // convert wchar_t to char
  71.     if (OK != key_to_c_key())
  72.     {
  73.         return FAIL;
  74.     }
  75. #else
  76.     char * p_cer = cer;
  77.     char * p_key = key;
  78. #endif
  79.  
  80.     // set the local certificate from cer
  81.     if (SSL_CTX_use_certificate_file(ctx, p_cer, SSL_FILETYPE_PEM) <= 0)
  82.     {
  83.         if (show_errors)
  84.         {
  85.             wprintf(L"invalid or missing certificate file\n%" _HS_ L"\n\n", p_cer);
  86.         }
  87.  
  88.         return FAIL;
  89.     }
  90.  
  91.     // set the private key from key (may be the same as cer)
  92.     if (SSL_CTX_use_PrivateKey_file(ctx, p_key, SSL_FILETYPE_PEM) <= 0)
  93.     {
  94.         if (show_errors)
  95.         {
  96.             wprintf(L"invalid or missing key file\n%" _HS_ L"\n\n", p_key);
  97.         }
  98.  
  99.         return FAIL;
  100.     }
  101.  
  102.     // verify private key
  103.     if (!SSL_CTX_check_private_key(ctx))
  104.     {
  105.         if (show_errors)
  106.         {
  107.             fprintf(stderr, "Private key does not match the public certificate\n");
  108.         }
  109.  
  110.         return FAIL;
  111.     }
  112.  
  113.     if (mode == G_TLS_SERVER)
  114.     {
  115.         server_valid = true;
  116.     }
  117.  
  118.     return OK;
  119. }
  120.  
  121. errno_t g_tls_t::new_session(SOCKET so, G_TLS_MODE_E mode)
  122. {
  123.     this->so = so;
  124.     bool valid = (mode == G_TLS_CLIENT) ? client_valid : server_valid;
  125.  
  126.     if (!valid || (so == INVALID_SOCKET))
  127.     {
  128.         return FAIL;
  129.     }
  130.  
  131.     tls = SSL_new((mode == G_TLS_CLIENT) ? ctx_client : ctx_server);
  132.  
  133.     if (!tls)
  134.     {
  135.         return FAIL;
  136.     }
  137.  
  138. #if USE_TLS_OPENSSL_MEM
  139.     b_recv = BIO_new(BIO_s_mem());
  140.     b_send = BIO_new(BIO_s_mem());
  141.  
  142.     if (!(b_recv && b_send))
  143.     {
  144.         if (b_recv)
  145.         {
  146.             BIO_free(b_recv);
  147.             b_recv = NULL;
  148.         }
  149.  
  150.         if (b_send)
  151.         {
  152.             BIO_free(b_send);
  153.             b_send = NULL;
  154.         }
  155.  
  156.         tls_free(tls);
  157.  
  158.         return FAIL;
  159.     }
  160.  
  161.     SSL_set_bio(tls, b_recv, b_send);
  162. #else
  163.     tls_set_fd(tls, (int)so);
  164. #endif
  165.  
  166.     InterlockedExchange(&ref, 1);
  167.     error_code = OK;
  168.  
  169.     return OK;
  170. }
  171.  
  172. errno_t g_tls_t::accept()
  173. {
  174.     TLS_SESSION_T tls_tmp = tls;
  175.  
  176.     if (!tls)
  177.     {
  178.         return FAIL;
  179.     }
  180.  
  181.     if (InterlockedExchangeAdd(&ref, 1) <= 0)
  182.     {
  183.         InterlockedDecrement(&ref);
  184.         error_code = FAIL;
  185.         return FAIL;
  186.     }
  187.  
  188. #if USE_TLS_OPENSSL_MEM
  189.     int b = FAIL;
  190.  
  191.     if (!p_recv || !p_recv_size)
  192.     {
  193.         error_code = FAIL;
  194.         wprintf(L"p_recv or p_recv_size not set\n");
  195.     }
  196.     else
  197.     {
  198.     RECV_MORE:
  199.         if (!SSL_is_init_finished(tls))
  200.         {
  201.             ssize_t size = ::recv(so, p_recv, (int)p_recv_size, 0);
  202.  
  203.             if (size <= 0)
  204.             {
  205.                 error_code = WSAGetLastError();
  206.                 //- wprintf(L"tls.accept::recv  %i\n", error_code);
  207.             }
  208.             else
  209.             {
  210.                 size = tls ? BIO_write(b_recv, p_recv, (int)size) : FAIL;
  211.  
  212.                 if (size <= 0)
  213.                 {
  214.                     error_code = tls ? SSL_get_error(tls_tmp, (int)size) : FAIL;
  215.                     //- wprintf(L"tls.accept::BIO_write  %i\n", error_code);
  216.                 }
  217.                 else
  218.                 {
  219.                     error_code = OK;
  220.                     b = SSL_accept(tls);
  221.  
  222.                     if (b <= 0)
  223.                     {
  224.                         error_code = tls ? SSL_get_error(tls_tmp, b) : FAIL;
  225.                         //- wprintf(L"tls.accept::SSL_accept  %i\n", error_code);
  226.                     }
  227.  
  228.                     if (
  229.                         (error_code == OK) ||
  230.                         (error_code == SSL_ERROR_WANT_READ)
  231.                         )
  232.                     {
  233.                         size = tls ? BIO_read(b_send, p_recv, (int)p_recv_size) : FAIL;
  234.  
  235.                         if (size <= 0)
  236.                         {
  237.                             error_code = tls ? SSL_get_error(tls_tmp, (int)size) : FAIL;
  238.                             //- wprintf(L"tls.accept::BIO_read  %i\n", error_code);
  239.                         }
  240.                         else
  241.                         {
  242.                             size = send_raw(p_recv, size);
  243.  
  244.                             if (size <= 0)
  245.                             {
  246.                                 error_code = WSAGetLastError();
  247.                                 //- wprintf(L"tls.accept::send  %i\n", error_code);
  248.                             }
  249.                         }
  250.  
  251.                         if (error_code == SSL_ERROR_WANT_READ)
  252.                         {
  253.                             // SSL_accept or BIO_read require more data from client
  254.                             goto RECV_MORE;
  255.                         }
  256.                     }
  257.                 }
  258.             }
  259.         }
  260.     }
  261. #else
  262.     int b = SSL_accept(tls_tmp);
  263.  
  264.     if (b <= 0)
  265.     {
  266.         error_code = SSL_get_error(tls_tmp, b);
  267.     }
  268. #endif
  269.  
  270.     if (!InterlockedDecrement(&ref))
  271.     {
  272.         tls_shutdown(tls_tmp);
  273.         tls_free(tls_tmp);
  274.     }
  275.  
  276.     return (1 == b) ? OK : FAIL;
  277. }
  278.  
  279. errno_t g_tls_t::connect()
  280. {
  281.     TLS_SESSION_T tls_tmp = tls;
  282.  
  283.     if (!tls)
  284.     {
  285.         return FAIL;
  286.     }
  287.  
  288.     if (InterlockedExchangeAdd(&ref, 1) <= 0)
  289.     {
  290.         InterlockedDecrement(&ref);
  291.         error_code = FAIL;
  292.         return FAIL;
  293.     }
  294.  
  295. #if USE_TLS_OPENSSL_MEM
  296.     int b = FAIL;
  297.     ssize_t size = 0;
  298.  
  299.     if (!p_recv || !p_recv_size)
  300.     {
  301.         error_code = FAIL;
  302.         wprintf(L"p_recv or p_recv_size not set\n");
  303.     }
  304.     else
  305.     {
  306.     RECV_MORE:
  307.         if (!SSL_is_init_finished(tls))
  308.         {
  309.             error_code = OK;
  310.             b = SSL_connect(tls);
  311.  
  312.             if (b <= 0)
  313.             {
  314.                 error_code = tls ? SSL_get_error(tls_tmp, b) : FAIL;
  315.                 //- wprintf(L"tls.connect::SSL_connect  %i %i\n", b, error_code);
  316.             }
  317.  
  318.             if (
  319.                 (error_code == OK) ||
  320.                 (error_code == SSL_ERROR_WANT_READ)
  321.                 )
  322.             {
  323.                 size = tls ? BIO_read(b_send, p_recv, (int)p_recv_size) : FAIL;
  324.  
  325.                 if (size <= 0)
  326.                 {
  327.                     error_code = tls ? SSL_get_error(tls_tmp, (int)size) : FAIL;
  328.                     //- wprintf(L"tls.connect::BIO_read  %i\n", error_code);
  329.                 }
  330.                 else
  331.                 {
  332.                     size = send_raw(p_recv, size);
  333.  
  334.                     if (size <= 0)
  335.                     {
  336.                         error_code = WSAGetLastError();
  337.                         //- wprintf(L"tls.connect::send  %i\n", error_code);
  338.                     }
  339.                 }
  340.  
  341.                 if (
  342.                     (error_code == OK) ||
  343.                     (error_code == SSL_ERROR_WANT_READ)
  344.                     )
  345.                 {
  346.                     size = ::recv(so, p_recv, (int)p_recv_size, 0);
  347.  
  348.                     if (size <= 0)
  349.                     {
  350.                         error_code = WSAGetLastError();
  351.                         //- wprintf(L"tls.connect::recv  %i\n", error_code);
  352.                     }
  353.                     else
  354.                     {
  355.                         size = tls ? BIO_write(b_recv, p_recv, (int)size) : FAIL;
  356.  
  357.                         if (size <= 0)
  358.                         {
  359.                             error_code = tls ? SSL_get_error(tls_tmp, (int)size) : FAIL;
  360.                             //- wprintf(L"tls.connect::BIO_write  %i\n", error_code);
  361.                         }
  362.                         else
  363.                         {
  364.                             goto RECV_MORE;
  365.                         }
  366.                     }
  367.                 }
  368.             }
  369.         }
  370.     }
  371. #else
  372.     int b = SSL_connect(tls_tmp);
  373.  
  374.     if (b <= 0)
  375.     {
  376.         error_code = tls ? SSL_get_error(tls_tmp, b) : FAIL;
  377.     }
  378. #endif
  379.  
  380.     if (!InterlockedDecrement(&ref))
  381.     {
  382.         tls_shutdown(tls_tmp);
  383.         tls_free(tls_tmp);
  384.     }
  385.  
  386.     return (1 == b) ? OK : FAIL;
  387. }
  388.  
  389. ssize_t g_tls_t::recv(char * msg, size_t count)
  390. {
  391.     TLS_SESSION_T tls_tmp = tls;
  392.  
  393.     if (!tls)
  394.     {
  395.         // fall-back to RAW TCP
  396.         return ::recv(so, msg, (int)count, 0);
  397.     }
  398.  
  399.     if (InterlockedExchangeAdd(&ref, 1) <= 0)
  400.     {
  401.         InterlockedDecrement(&ref);
  402.         error_code = FAIL;
  403.         return FAIL;
  404.     }
  405.  
  406. #if USE_TLS_OPENSSL_MEM
  407.     BIO * b_recv_tmp = b_recv;
  408.     ssize_t size = 0;
  409.  
  410. RECV_MORE:
  411.     size = tls ? SSL_read(tls, msg, (int)count) : FAIL;
  412.  
  413.     if (size <= 0)
  414.     {
  415.         error_code = tls ? SSL_get_error(tls_tmp, (int)size) : FAIL;
  416.  
  417.         if (error_code == SSL_ERROR_WANT_READ)
  418.         {
  419.             ssize_t size_read = ::recv(so, msg, (int)count, 0);
  420.  
  421.             if (size_read <= 0)
  422.             {
  423.                 error_code = WSAGetLastError();
  424.                 //- wprintf(L"tls.recv::recv  %i\n", error_code);
  425.             }
  426.             else
  427.             {
  428.                 if (!tls || (0 >= (size_read = BIO_write(b_recv_tmp, msg, (int)size_read))))
  429.                 {
  430.                     error_code = tls ? SSL_get_error(tls_tmp, (int)size_read) : FAIL;
  431.                     //- wprintf(L"tls.recv::BIO_write  %i\n", error_code);
  432.                 }
  433.                 else
  434.                 {
  435.                     goto RECV_MORE;
  436.                 }
  437.             }
  438.         }
  439.     }
  440. #else
  441.     ssize_t size = tls ? SSL_read(tls_tmp, msg, (int)count) : FAIL;
  442.  
  443.     if (size <= 0)
  444.     {
  445.         error_code = tls ? SSL_get_error(tls_tmp, (int)size) : FAIL;
  446.     }
  447. #endif
  448.  
  449.     if (!InterlockedDecrement(&ref))
  450.     {
  451.         tls_shutdown(tls_tmp);
  452.         tls_free(tls_tmp);
  453.     }
  454.  
  455.     return size;
  456. }
  457.  
  458. ssize_t g_tls_t::send(const char * msg, size_t count)
  459. {
  460.     TLS_SESSION_T tls_tmp = tls;
  461.  
  462.     if (!tls)
  463.     {
  464.         // fall-back to RAW TCP
  465.         return send_raw(msg, count);
  466.     }
  467.  
  468.     if (InterlockedExchangeAdd(&ref, 1) <= 0)
  469.     {
  470.         InterlockedDecrement(&ref);
  471.         error_code = FAIL;
  472.         return FAIL;
  473.     }
  474.  
  475. #if USE_TLS_OPENSSL_MEM
  476.     BIO * b_send_tmp = b_send;
  477.     const char * p = msg;
  478.     size_t remain = count;
  479.  
  480. SEND_MORE:
  481.     ssize_t size = (remain > MAX_TLS_GROUP) ? MAX_TLS_GROUP : remain;
  482.     size = tls ? SSL_write(tls_tmp, p, (int)size) : FAIL;
  483.  
  484.     if (size <= 0)
  485.     {
  486.         error_code = tls ? SSL_get_error(tls_tmp, (int)size) : FAIL;
  487.         //- wprintf(L"tls.send::SSL_write  %i\n", error_code);
  488.     }
  489.     else
  490.     {
  491.         p += size;
  492.         remain -= size;
  493.  
  494.         BUF_MEM * bm = NULL;
  495.         BIO_get_mem_ptr(b_send_tmp, &bm);
  496.  
  497.         if (!bm)
  498.         {
  499.             error_code = tls ? SSL_get_error(tls_tmp, (int)size) : FAIL;
  500.             //- wprintf(L"tls.send::tls_bio_get_mem_ptr  %i\n", error_code);
  501.         }
  502.         else
  503.         {
  504.             size = send_raw(bm->data, bm->length);
  505.  
  506. #if USE_TLS_OPENSSL
  507.             bm->length = 0;
  508.             BIO_set_shutdown(b_send_tmp, BIO_NOCLOSE);
  509.             BIO_set_mem_buf(b_send_tmp, bm, BIO_CLOSE);
  510. #else
  511.             BIO_reset(b_send_tmp);
  512. #endif
  513.  
  514.             if (size > 0)
  515.             {
  516.                 if (remain)
  517.                 {
  518.                     goto SEND_MORE;
  519.                 }
  520.  
  521.                 size = count;
  522.             }
  523.         }
  524.     }
  525. #else
  526.     ssize_t size = tls ? SSL_write(tls_tmp, msg, (int)count) : FAIL;
  527.  
  528.     if (size <= 0)
  529.     {
  530.         error_code = tls ? SSL_get_error(tls_tmp, (int)size) : FAIL;
  531.     }
  532. #endif
  533.  
  534.     if (!InterlockedDecrement(&ref))
  535.     {
  536.         tls_shutdown(tls_tmp);
  537.         tls_free(tls_tmp);
  538.     }
  539.  
  540.     return size;
  541. }
  542.  
Add Comment
Please, Sign In to add comment