Adapting the ssl Function

Change-Id: Id545424443408fd91c793aba605aebd0a2fb84e0
diff --git a/mbtk/libmbtk_lib/net/mbtk_openssl.c b/mbtk/libmbtk_lib/net/mbtk_openssl.c
new file mode 100755
index 0000000..ba1d932
--- /dev/null
+++ b/mbtk/libmbtk_lib/net/mbtk_openssl.c
@@ -0,0 +1,312 @@
+/*-----------------------------------------------------------------------------------------------*/

+/**

+  @file mbtk_openssl.c

+  @brief OPENSSL API

+*/

+/*-----------------------------------------------------------------------------------------------*/

+

+/*-------------------------------------------------------------------------------------------------

+  Copyright (c) 2024 mobiletek Wireless Solution, Co., Ltd. All Rights Reserved.

+  mobiletek Wireless Solution Proprietary and Confidential.

+-------------------------------------------------------------------------------------------------*/

+

+/*-------------------------------------------------------------------------------------------------

+  EDIT HISTORY

+  This section contains comments describing changes made to the file.

+  Notice that changes are listed in reverse chronological order.

+  $Header: $

+  when       who          what, where, why

+  --------   ---------    -----------------------------------------------------------------

+  20250410    yq.wang      Created .

+-------------------------------------------------------------------------------------------------*/

+#ifdef MBTK_OPENSSL_V3_0_0_SUPPORT

+#include <stdio.h>

+#include <stdlib.h>

+#include <string.h>

+#include <unistd.h>

+#include <sys/socket.h>

+

+#include <sys/select.h>

+#include <sys/time.h> 

+

+#include "mbtk_openssl.h"

+#include "mbtk_log.h"

+

+#define MBTK_SSL_INFO_FD_DEFAULT -1

+

+X509 * SSL_get1_peer_certificate(SSL *ssl);

+

+static mbtk_openssl_result_e mbtk_openssl_wait_for_socket(int sockfd, bool is_read)

+{

+    int ret = -1;

+    fd_set fds;

+    struct timeval tv = {.tv_sec = 5, .tv_usec = 0}; // 5s timeout

+    

+    FD_ZERO(&fds);

+    FD_SET(sockfd, &fds);

+    ret = select(sockfd + 1, is_read ? &fds : NULL, is_read ? NULL : &fds, NULL, &tv);

+    if (0 >= ret)

+    {

+        LOGE("[%s] select() fail.[%d]", __func__, ret);

+        return MBTK_OPENSSL_RESULT_FAIL;

+    }

+    return MBTK_OPENSSL_RESULT_SUCCESS;

+}

+

+mbtk_openssl_result_e mbtk_openssl_options_default(mbtk_openssl_options_s *opt)

+{

+    if(NULL == opt)

+    {

+        LOGE("[%s] opt [NULL]", __func__);

+        return MBTK_OPENSSL_RESULT_FAIL;

+    }

+

+    opt->load_cert = false;

+    opt->ca_file = NULL;

+    opt->crt_file = NULL;

+    opt->key_file = NULL;

+    opt->ssl_filetype = MBTK_OPENSSL_FILETYPE_PEM;

+    opt->verify_mode = MBTK_OPENSSL_VERIFY_PEER;

+    opt->verify_cb = NULL;

+    opt->init_opts = MBTK_OPENSSL_INIT_LOAD_SSL_STRINGS | MBTK_OPENSSL_INIT_LOAD_CRYPTO_STRINGS \

+                     | MBTK_OPENSSL_INIT_ADD_ALL_CIPHERS | MBTK_OPENSSL_INIT_ADD_ALL_DIGESTS;

+    opt->safety_level = MBTK_OPENSSL_SAFETY_LEVEL_2;

+    

+    return MBTK_OPENSSL_RESULT_SUCCESS;

+}

+

+int mbtk_openssl_write(SSL *ssl, const void *buf, int len)

+{

+    return SSL_write(ssl, buf, len);

+}

+

+int mbtk_openssl_read(SSL *ssl, void *buf, int len)

+{

+    return SSL_read(ssl, buf, len);

+}

+

+mbtk_openssl_result_e mbtk_openssl_init(int fd, mbtk_openssl_options_s *opt, mbtk_openssl_info_s *inter_info)

+{

+    int ret = -1;

+    int ssl_error = -1;

+    long verify_res = -1;

+    char *line = NULL;

+    X509 *cert = NULL;

+    mbtk_openssl_result_e mbtk_ssl_ret = MBTK_OPENSSL_RESULT_SUCCESS;

+    const SSL_METHOD *method = NULL;

+    mbtk_openssl_info_s temp_inter_info = {0};

+    mbtk_openssl_options_s temp_opt = {0};

+

+    if(NULL == inter_info)

+    {

+        LOGE("[%s] inter_info [NULL]", __func__);

+        return MBTK_OPENSSL_RESULT_FAIL;

+    }

+

+    if(NULL == opt)

+    {

+        mbtk_openssl_options_default(&temp_opt);

+    }

+    else

+    {

+        memset(&temp_opt, 0x00, sizeof(mbtk_openssl_options_s));

+        memcpy(&temp_opt, opt, sizeof(mbtk_openssl_options_s));

+    }

+    

+    //1.Initializes the OPENSSL library

+    OPENSSL_init_ssl(temp_opt.init_opts, NULL);

+

+    memset(&temp_inter_info, 0x00, sizeof(mbtk_openssl_info_s));

+    //2.Create an SSL/TLS context object

+    method = TLS_client_method();

+    temp_inter_info.ctx = SSL_CTX_new(method);

+    if(NULL == temp_inter_info.ctx)

+    {

+        LOGE("[%s] SSL_CTX_new() fail", __func__);

+        goto error;

+    }

+

+    //3.Load certificate

+    if(temp_opt.load_cert)

+    {

+        //3.1-Set the certificate security level

+        SSL_CTX_set_security_level(temp_inter_info.ctx, temp_opt.safety_level);

+        

+        //3.2-Loading a CA Certificate

+        if(NULL != temp_opt.ca_file)

+        {

+            ret = SSL_CTX_load_verify_locations(temp_inter_info.ctx, temp_opt.ca_file, NULL);

+            if(1 != ret)

+            {

+                LOGE("[%s] SSL_CTX_load_verify_locations() fail.[%d]", __func__, ret);

+                goto error;

+            }

+        }

+

+        //3.3-Load the client public key

+        if(NULL != temp_opt.crt_file)

+        {

+            ret = SSL_CTX_use_certificate_file(temp_inter_info.ctx, temp_opt.crt_file, temp_opt.ssl_filetype);

+            if(1 != ret)

+            {

+                LOGE("[%s] SSL_CTX_use_certificate_file() fail.[%d]", __func__, ret);

+                goto error;

+            }

+        }

+

+        //3.4-Load the client private key

+        if(NULL != temp_opt.key_file)

+        {

+            ret = SSL_CTX_use_PrivateKey_file(temp_inter_info.ctx, temp_opt.key_file, temp_opt.ssl_filetype);

+            if(1 != ret)

+            {

+                LOGE("[%s] SSL_CTX_use_PrivateKey_file() fail.[%d]", __func__, ret);

+                goto error;

+            }

+        }

+

+        //3.5-Verify the private key matching certificate

+        ret = SSL_CTX_check_private_key(temp_inter_info.ctx);

+        if (1 != ret)

+        {

+            LOGE("[%s] SSL_CTX_check_private_key() fail.[%d]", __func__, ret);

+            goto error;

+        }

+

+        //3.6-Set verification mode

+        SSL_CTX_set_verify(temp_inter_info.ctx, temp_opt.verify_mode, temp_opt.verify_cb);

+    }

+

+    //4.Creates and initializes a new SSL/TLS session object

+    temp_inter_info.ssl = SSL_new(temp_inter_info.ctx);

+    if(NULL == temp_inter_info.ssl)

+    {

+        LOGE("[%s] SSL_new() fail", __func__);

+        goto error;

+    }

+    SSL_set_fd(temp_inter_info.ssl, fd);

+

+    LOGD("[%s] Performing the SSL/TLS handshake...", __func__);

+    //5.Executive handshake

+    //SSL_set_connect_state(temp_inter_info.ssl);

+    while((ret = SSL_connect(temp_inter_info.ssl)) <= 0)

+    {

+        ssl_error = SSL_get_error(temp_inter_info.ssl, ret);  

+        if(ssl_error == SSL_ERROR_WANT_READ)

+        {    

+            mbtk_ssl_ret = mbtk_openssl_wait_for_socket(fd, true);

+            if(MBTK_OPENSSL_RESULT_SUCCESS != mbtk_ssl_ret)

+            {

+                LOGE("[%s] mbtk_openssl_wait_for_socket() fail", __func__);

+                goto error;

+            }

+        }

+        else if(ssl_error == SSL_ERROR_WANT_WRITE)

+        {

+            mbtk_ssl_ret = mbtk_openssl_wait_for_socket(fd, false);

+            if(MBTK_OPENSSL_RESULT_SUCCESS != mbtk_ssl_ret)

+            {

+                LOGE("[%s] mbtk_openssl_wait_for_socket() fail", __func__);

+                goto error;

+            }

+        }

+        else

+        {

+            LOGE("[%s] SSL_connect() fail.[%d]", __func__, ssl_error);

+            goto error;

+        }

+    }

+

+    LOGD("[%s] SSL connect ok: Protocol[%s], Ciphersuite[%s]", __func__, SSL_get_version(temp_inter_info.ssl), SSL_get_cipher_name(temp_inter_info.ssl));

+

+    //6.Verification certificate

+    if(temp_opt.load_cert)

+    {

+        cert = SSL_get1_peer_certificate(temp_inter_info.ssl);

+        if(NULL != cert)

+        {

+            verify_res = SSL_get_verify_result(temp_inter_info.ssl);

+            if(X509_V_OK != verify_res)

+            {

+                LOGE("[%s] SSL_get_verify_result() fail.[%s]", __func__, X509_verify_cert_error_string(verify_res));

+                goto error;

+            }

+

+            LOGD("[%s] Digital certificate information:", __func__);

+            

+            line = X509_NAME_oneline(X509_get_subject_name(cert), 0, 0);

+            LOGD("[%s] certificate: [%s]", __func__, line);

+            free(line);

+            line = NULL;

+            

+            line = X509_NAME_oneline(X509_get_issuer_name(cert), 0, 0);

+            LOGD("[%s] issuer: [%s]", __func__, line);

+            free(line);

+            line = NULL;

+            

+            X509_free(cert);

+            cert = NULL;

+        }

+        else

+        {

+            LOGD("[%s] No server certificate received", __func__);

+            if(temp_opt.verify_mode != MBTK_OPENSSL_VERIFY_NONE)

+            {

+                LOGE("[%s] Verification fail", __func__);

+                goto error;

+            }

+        }

+    }

+

+    temp_inter_info.fd = fd;

+    memcpy(inter_info, &temp_inter_info, sizeof(mbtk_openssl_info_s));

+    

+    return MBTK_OPENSSL_RESULT_SUCCESS;

+error:

+    if(NULL != cert)

+    {

+        X509_free(cert);

+        cert = NULL;

+    }

+    if(NULL != temp_inter_info.ssl)

+    {

+        SSL_shutdown(temp_inter_info.ssl);

+        SSL_free(temp_inter_info.ssl);

+        temp_inter_info.ssl = NULL;

+    }

+

+    if(NULL != temp_inter_info.ctx)

+    {

+        SSL_CTX_free(temp_inter_info.ctx);

+        temp_inter_info.ctx = NULL;

+    }

+

+    return MBTK_OPENSSL_RESULT_FAIL;

+}

+

+mbtk_openssl_result_e mbtk_openssl_deinit(mbtk_openssl_info_s *inter_info)

+{

+    if(NULL == inter_info)

+    {

+        LOGE("[%s] inter_info [NULL]", __func__);

+        return MBTK_OPENSSL_RESULT_FAIL;

+    }

+

+    if(NULL != inter_info->ssl)

+    {

+        SSL_shutdown(inter_info->ssl);

+        SSL_free(inter_info->ssl);

+        inter_info->ssl = NULL;

+    }

+

+    if(NULL != inter_info->ctx)

+    {

+        SSL_CTX_free(inter_info->ctx);

+        inter_info->ctx = NULL;

+    }

+

+    inter_info->fd = MBTK_SSL_INFO_FD_DEFAULT;

+    return MBTK_OPENSSL_RESULT_SUCCESS;

+}

+

+#endif