yq.wang | 39b54a2 | 2025-04-11 15:25:50 +0800 | [diff] [blame] | 1 | /*-----------------------------------------------------------------------------------------------*/
|
| 2 | /**
|
| 3 | @file mbtk_openssl.c
|
| 4 | @brief OPENSSL API
|
| 5 | */
|
| 6 | /*-----------------------------------------------------------------------------------------------*/
|
| 7 |
|
| 8 | /*-------------------------------------------------------------------------------------------------
|
| 9 | Copyright (c) 2024 mobiletek Wireless Solution, Co., Ltd. All Rights Reserved.
|
| 10 | mobiletek Wireless Solution Proprietary and Confidential.
|
| 11 | -------------------------------------------------------------------------------------------------*/
|
| 12 |
|
| 13 | /*-------------------------------------------------------------------------------------------------
|
| 14 | EDIT HISTORY
|
| 15 | This section contains comments describing changes made to the file.
|
| 16 | Notice that changes are listed in reverse chronological order.
|
| 17 | $Header: $
|
| 18 | when who what, where, why
|
| 19 | -------- --------- -----------------------------------------------------------------
|
| 20 | 20250410 yq.wang Created .
|
| 21 | -------------------------------------------------------------------------------------------------*/
|
| 22 | #ifdef MBTK_OPENSSL_V3_0_0_SUPPORT
|
| 23 | #include <stdio.h>
|
| 24 | #include <stdlib.h>
|
| 25 | #include <string.h>
|
| 26 | #include <unistd.h>
|
| 27 | #include <sys/socket.h>
|
| 28 |
|
| 29 | #include <sys/select.h>
|
| 30 | #include <sys/time.h>
|
| 31 |
|
| 32 | #include "mbtk_openssl.h"
|
| 33 | #include "mbtk_log.h"
|
| 34 |
|
| 35 | #define MBTK_SSL_INFO_FD_DEFAULT -1
|
| 36 |
|
b.liu | b7a1b1d | 2025-04-18 10:42:56 +0800 | [diff] [blame] | 37 | // X509 * SSL_get1_peer_certificate(SSL *ssl);
|
yq.wang | 39b54a2 | 2025-04-11 15:25:50 +0800 | [diff] [blame] | 38 |
|
| 39 | static mbtk_openssl_result_e mbtk_openssl_wait_for_socket(int sockfd, bool is_read)
|
| 40 | {
|
| 41 | int ret = -1;
|
| 42 | fd_set fds;
|
| 43 | struct timeval tv = {.tv_sec = 5, .tv_usec = 0}; // 5s timeout
|
| 44 |
|
| 45 | FD_ZERO(&fds);
|
| 46 | FD_SET(sockfd, &fds);
|
| 47 | ret = select(sockfd + 1, is_read ? &fds : NULL, is_read ? NULL : &fds, NULL, &tv);
|
| 48 | if (0 >= ret)
|
| 49 | {
|
| 50 | LOGE("[%s] select() fail.[%d]", __func__, ret);
|
| 51 | return MBTK_OPENSSL_RESULT_FAIL;
|
| 52 | }
|
| 53 | return MBTK_OPENSSL_RESULT_SUCCESS;
|
| 54 | }
|
| 55 |
|
| 56 | mbtk_openssl_result_e mbtk_openssl_options_default(mbtk_openssl_options_s *opt)
|
| 57 | {
|
| 58 | if(NULL == opt)
|
| 59 | {
|
| 60 | LOGE("[%s] opt [NULL]", __func__);
|
| 61 | return MBTK_OPENSSL_RESULT_FAIL;
|
| 62 | }
|
| 63 |
|
| 64 | opt->load_cert = false;
|
| 65 | opt->ca_file = NULL;
|
| 66 | opt->crt_file = NULL;
|
| 67 | opt->key_file = NULL;
|
| 68 | opt->ssl_filetype = MBTK_OPENSSL_FILETYPE_PEM;
|
| 69 | opt->verify_mode = MBTK_OPENSSL_VERIFY_PEER;
|
| 70 | opt->verify_cb = NULL;
|
| 71 | opt->init_opts = MBTK_OPENSSL_INIT_LOAD_SSL_STRINGS | MBTK_OPENSSL_INIT_LOAD_CRYPTO_STRINGS \
|
| 72 | | MBTK_OPENSSL_INIT_ADD_ALL_CIPHERS | MBTK_OPENSSL_INIT_ADD_ALL_DIGESTS;
|
| 73 | opt->safety_level = MBTK_OPENSSL_SAFETY_LEVEL_2;
|
| 74 |
|
| 75 | return MBTK_OPENSSL_RESULT_SUCCESS;
|
| 76 | }
|
| 77 |
|
| 78 | int mbtk_openssl_write(SSL *ssl, const void *buf, int len)
|
| 79 | {
|
| 80 | return SSL_write(ssl, buf, len);
|
| 81 | }
|
| 82 |
|
| 83 | int mbtk_openssl_read(SSL *ssl, void *buf, int len)
|
| 84 | {
|
| 85 | return SSL_read(ssl, buf, len);
|
| 86 | }
|
| 87 |
|
| 88 | mbtk_openssl_result_e mbtk_openssl_init(int fd, mbtk_openssl_options_s *opt, mbtk_openssl_info_s *inter_info)
|
| 89 | {
|
| 90 | int ret = -1;
|
| 91 | int ssl_error = -1;
|
| 92 | long verify_res = -1;
|
| 93 | char *line = NULL;
|
| 94 | X509 *cert = NULL;
|
| 95 | mbtk_openssl_result_e mbtk_ssl_ret = MBTK_OPENSSL_RESULT_SUCCESS;
|
| 96 | const SSL_METHOD *method = NULL;
|
| 97 | mbtk_openssl_info_s temp_inter_info = {0};
|
| 98 | mbtk_openssl_options_s temp_opt = {0};
|
| 99 |
|
| 100 | if(NULL == inter_info)
|
| 101 | {
|
| 102 | LOGE("[%s] inter_info [NULL]", __func__);
|
| 103 | return MBTK_OPENSSL_RESULT_FAIL;
|
| 104 | }
|
| 105 |
|
| 106 | if(NULL == opt)
|
| 107 | {
|
| 108 | mbtk_openssl_options_default(&temp_opt);
|
| 109 | }
|
| 110 | else
|
| 111 | {
|
| 112 | memset(&temp_opt, 0x00, sizeof(mbtk_openssl_options_s));
|
| 113 | memcpy(&temp_opt, opt, sizeof(mbtk_openssl_options_s));
|
| 114 | }
|
| 115 |
|
| 116 | //1.Initializes the OPENSSL library
|
| 117 | OPENSSL_init_ssl(temp_opt.init_opts, NULL);
|
| 118 |
|
| 119 | memset(&temp_inter_info, 0x00, sizeof(mbtk_openssl_info_s));
|
| 120 | //2.Create an SSL/TLS context object
|
| 121 | method = TLS_client_method();
|
| 122 | temp_inter_info.ctx = SSL_CTX_new(method);
|
| 123 | if(NULL == temp_inter_info.ctx)
|
| 124 | {
|
| 125 | LOGE("[%s] SSL_CTX_new() fail", __func__);
|
| 126 | goto error;
|
| 127 | }
|
| 128 |
|
| 129 | //3.Load certificate
|
| 130 | if(temp_opt.load_cert)
|
| 131 | {
|
| 132 | //3.1-Set the certificate security level
|
| 133 | SSL_CTX_set_security_level(temp_inter_info.ctx, temp_opt.safety_level);
|
| 134 |
|
| 135 | //3.2-Loading a CA Certificate
|
| 136 | if(NULL != temp_opt.ca_file)
|
| 137 | {
|
| 138 | ret = SSL_CTX_load_verify_locations(temp_inter_info.ctx, temp_opt.ca_file, NULL);
|
| 139 | if(1 != ret)
|
| 140 | {
|
| 141 | LOGE("[%s] SSL_CTX_load_verify_locations() fail.[%d]", __func__, ret);
|
| 142 | goto error;
|
| 143 | }
|
| 144 | }
|
| 145 |
|
| 146 | //3.3-Load the client public key
|
| 147 | if(NULL != temp_opt.crt_file)
|
| 148 | {
|
| 149 | ret = SSL_CTX_use_certificate_file(temp_inter_info.ctx, temp_opt.crt_file, temp_opt.ssl_filetype);
|
| 150 | if(1 != ret)
|
| 151 | {
|
| 152 | LOGE("[%s] SSL_CTX_use_certificate_file() fail.[%d]", __func__, ret);
|
| 153 | goto error;
|
| 154 | }
|
| 155 | }
|
| 156 |
|
| 157 | //3.4-Load the client private key
|
| 158 | if(NULL != temp_opt.key_file)
|
| 159 | {
|
| 160 | ret = SSL_CTX_use_PrivateKey_file(temp_inter_info.ctx, temp_opt.key_file, temp_opt.ssl_filetype);
|
| 161 | if(1 != ret)
|
| 162 | {
|
| 163 | LOGE("[%s] SSL_CTX_use_PrivateKey_file() fail.[%d]", __func__, ret);
|
| 164 | goto error;
|
| 165 | }
|
| 166 | }
|
| 167 |
|
| 168 | //3.5-Verify the private key matching certificate
|
| 169 | ret = SSL_CTX_check_private_key(temp_inter_info.ctx);
|
| 170 | if (1 != ret)
|
| 171 | {
|
| 172 | LOGE("[%s] SSL_CTX_check_private_key() fail.[%d]", __func__, ret);
|
| 173 | goto error;
|
| 174 | }
|
| 175 |
|
| 176 | //3.6-Set verification mode
|
| 177 | SSL_CTX_set_verify(temp_inter_info.ctx, temp_opt.verify_mode, temp_opt.verify_cb);
|
| 178 | }
|
| 179 |
|
| 180 | //4.Creates and initializes a new SSL/TLS session object
|
| 181 | temp_inter_info.ssl = SSL_new(temp_inter_info.ctx);
|
| 182 | if(NULL == temp_inter_info.ssl)
|
| 183 | {
|
| 184 | LOGE("[%s] SSL_new() fail", __func__);
|
| 185 | goto error;
|
| 186 | }
|
| 187 | SSL_set_fd(temp_inter_info.ssl, fd);
|
| 188 |
|
| 189 | LOGD("[%s] Performing the SSL/TLS handshake...", __func__);
|
| 190 | //5.Executive handshake
|
| 191 | //SSL_set_connect_state(temp_inter_info.ssl);
|
| 192 | while((ret = SSL_connect(temp_inter_info.ssl)) <= 0)
|
| 193 | {
|
| 194 | ssl_error = SSL_get_error(temp_inter_info.ssl, ret);
|
| 195 | if(ssl_error == SSL_ERROR_WANT_READ)
|
| 196 | {
|
| 197 | mbtk_ssl_ret = mbtk_openssl_wait_for_socket(fd, true);
|
| 198 | if(MBTK_OPENSSL_RESULT_SUCCESS != mbtk_ssl_ret)
|
| 199 | {
|
| 200 | LOGE("[%s] mbtk_openssl_wait_for_socket() fail", __func__);
|
| 201 | goto error;
|
| 202 | }
|
| 203 | }
|
| 204 | else if(ssl_error == SSL_ERROR_WANT_WRITE)
|
| 205 | {
|
| 206 | mbtk_ssl_ret = mbtk_openssl_wait_for_socket(fd, false);
|
| 207 | if(MBTK_OPENSSL_RESULT_SUCCESS != mbtk_ssl_ret)
|
| 208 | {
|
| 209 | LOGE("[%s] mbtk_openssl_wait_for_socket() fail", __func__);
|
| 210 | goto error;
|
| 211 | }
|
| 212 | }
|
| 213 | else
|
| 214 | {
|
| 215 | LOGE("[%s] SSL_connect() fail.[%d]", __func__, ssl_error);
|
| 216 | goto error;
|
| 217 | }
|
| 218 | }
|
| 219 |
|
| 220 | 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));
|
| 221 |
|
| 222 | //6.Verification certificate
|
| 223 | if(temp_opt.load_cert)
|
| 224 | {
|
| 225 | cert = SSL_get1_peer_certificate(temp_inter_info.ssl);
|
| 226 | if(NULL != cert)
|
| 227 | {
|
| 228 | verify_res = SSL_get_verify_result(temp_inter_info.ssl);
|
| 229 | if(X509_V_OK != verify_res)
|
| 230 | {
|
| 231 | LOGE("[%s] SSL_get_verify_result() fail.[%s]", __func__, X509_verify_cert_error_string(verify_res));
|
| 232 | goto error;
|
| 233 | }
|
| 234 |
|
| 235 | LOGD("[%s] Digital certificate information:", __func__);
|
| 236 |
|
| 237 | line = X509_NAME_oneline(X509_get_subject_name(cert), 0, 0);
|
| 238 | LOGD("[%s] certificate: [%s]", __func__, line);
|
| 239 | free(line);
|
| 240 | line = NULL;
|
| 241 |
|
| 242 | line = X509_NAME_oneline(X509_get_issuer_name(cert), 0, 0);
|
| 243 | LOGD("[%s] issuer: [%s]", __func__, line);
|
| 244 | free(line);
|
| 245 | line = NULL;
|
| 246 |
|
| 247 | X509_free(cert);
|
| 248 | cert = NULL;
|
| 249 | }
|
| 250 | else
|
| 251 | {
|
| 252 | LOGD("[%s] No server certificate received", __func__);
|
| 253 | if(temp_opt.verify_mode != MBTK_OPENSSL_VERIFY_NONE)
|
| 254 | {
|
| 255 | LOGE("[%s] Verification fail", __func__);
|
| 256 | goto error;
|
| 257 | }
|
| 258 | }
|
| 259 | }
|
| 260 |
|
| 261 | temp_inter_info.fd = fd;
|
| 262 | memcpy(inter_info, &temp_inter_info, sizeof(mbtk_openssl_info_s));
|
| 263 |
|
| 264 | return MBTK_OPENSSL_RESULT_SUCCESS;
|
| 265 | error:
|
| 266 | if(NULL != cert)
|
| 267 | {
|
| 268 | X509_free(cert);
|
| 269 | cert = NULL;
|
| 270 | }
|
| 271 | if(NULL != temp_inter_info.ssl)
|
| 272 | {
|
| 273 | SSL_shutdown(temp_inter_info.ssl);
|
| 274 | SSL_free(temp_inter_info.ssl);
|
| 275 | temp_inter_info.ssl = NULL;
|
| 276 | }
|
| 277 |
|
| 278 | if(NULL != temp_inter_info.ctx)
|
| 279 | {
|
| 280 | SSL_CTX_free(temp_inter_info.ctx);
|
| 281 | temp_inter_info.ctx = NULL;
|
| 282 | }
|
| 283 |
|
| 284 | return MBTK_OPENSSL_RESULT_FAIL;
|
| 285 | }
|
| 286 |
|
| 287 | mbtk_openssl_result_e mbtk_openssl_deinit(mbtk_openssl_info_s *inter_info)
|
| 288 | {
|
| 289 | if(NULL == inter_info)
|
| 290 | {
|
| 291 | LOGE("[%s] inter_info [NULL]", __func__);
|
| 292 | return MBTK_OPENSSL_RESULT_FAIL;
|
| 293 | }
|
| 294 |
|
| 295 | if(NULL != inter_info->ssl)
|
| 296 | {
|
| 297 | SSL_shutdown(inter_info->ssl);
|
| 298 | SSL_free(inter_info->ssl);
|
| 299 | inter_info->ssl = NULL;
|
| 300 | }
|
| 301 |
|
| 302 | if(NULL != inter_info->ctx)
|
| 303 | {
|
| 304 | SSL_CTX_free(inter_info->ctx);
|
| 305 | inter_info->ctx = NULL;
|
| 306 | }
|
| 307 |
|
| 308 | inter_info->fd = MBTK_SSL_INFO_FD_DEFAULT;
|
| 309 | return MBTK_OPENSSL_RESULT_SUCCESS;
|
| 310 | }
|
| 311 |
|
| 312 | #endif
|