blob: 2272080f44d65a326ee358964665d74138ca346d [file] [log] [blame]
yq.wang39b54a22025-04-11 15:25:50 +08001/*-----------------------------------------------------------------------------------------------*/
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.liub7a1b1d2025-04-18 10:42:56 +080037// X509 * SSL_get1_peer_certificate(SSL *ssl);
yq.wang39b54a22025-04-11 15:25:50 +080038
39static 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
56mbtk_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
78int mbtk_openssl_write(SSL *ssl, const void *buf, int len)
79{
80 return SSL_write(ssl, buf, len);
81}
82
83int mbtk_openssl_read(SSL *ssl, void *buf, int len)
84{
85 return SSL_read(ssl, buf, len);
86}
87
88mbtk_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;
265error:
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
287mbtk_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