1 /**
2 * Copyright (c) 2020 Huawei Device Co., Ltd.
3 * Licensed under the Apache License, Version 2.0 (the "License");
4 * you may not use this file except in compliance with the License.
5 * You may obtain a copy of the License at
6 *
7 * http://www.apache.org/licenses/LICENSE-2.0
8 *
9 * Unless required by applicable law or agreed to in writing, software
10 * distributed under the License is distributed on an "AS IS" BASIS,
11 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 * See the License for the specific language governing permissions and
13 * limitations under the License.
14 */
15
16 #include "tls_client.h"
17
18 #include <stdio.h>
19 #include <string.h>
20 #include "securec.h"
21 //#include "securec.h"
22 #include "tls_certificate.h"
23 #include "mbedtls_log.h"
24
25 #include "mbedtls/build_info.h"
26
SslDebug(void * ctx,int level,const char * file,int line,const char * str)27 static void SslDebug(void *ctx, int level, const char *file, int line, const char *str)
28 {
29 LOGD("%s:%04d: %s.", file, line, str);
30 }
31
MbedtlsSslCertificateVerify(MbedTLSSession * session)32 static int MbedtlsSslCertificateVerify(MbedTLSSession *session)
33 {
34 if (session == NULL) {
35 return -RET_ERROR;
36 }
37 int ret = mbedtls_ssl_get_verify_result(&session->ssl);
38 if (ret != 0) {
39 LOGD("verify peer certificate fail...");
40 (void)memset_s(session->buffer, session->buffer_len, 0x00, session->buffer_len);
41 mbedtls_x509_crt_verify_info((char *)session->buffer, session->buffer_len, " ! ", ret);
42 LOGD("verification info: %s.", session->buffer);
43 return -RET_ERROR;
44 }
45 return RET_EOK;
46 }
47
MbedtlsClientInit(MbedTLSSession * session,void * entropy,size_t entropyLen)48 int MbedtlsClientInit(MbedTLSSession *session, void *entropy, size_t entropyLen)
49 {
50 if (session == NULL || entropy == NULL) {
51 return -RET_ERROR;
52 }
53 mbedtls_net_init(&session->server_fd);
54 mbedtls_ssl_init(&session->ssl);
55 mbedtls_ssl_config_init(&session->conf);
56 mbedtls_ctr_drbg_init(&session->ctr_drbg);
57 mbedtls_entropy_init(&session->entropy);
58 mbedtls_x509_crt_init(&session->cacert);
59 int ret = mbedtls_ctr_drbg_seed(&session->ctr_drbg, mbedtls_entropy_func, &session->entropy,
60 (unsigned char *)entropy, entropyLen);
61 if (ret != 0) {
62 LOGD("mbedtls_ctr_drbg_seed error, return -0x%x.", -ret);
63 return ret;
64 }
65 LOGD("mbedtls client struct init success...");
66 return RET_EOK;
67 }
68
MbedtlsClientClose(MbedTLSSession * session)69 int MbedtlsClientClose(MbedTLSSession *session)
70 {
71 if (session == NULL) {
72 return -RET_ERROR;
73 }
74 mbedtls_ssl_close_notify(&session->ssl);
75 mbedtls_net_free(&session->server_fd);
76 mbedtls_x509_crt_free(&session->cacert);
77 mbedtls_entropy_free(&session->entropy);
78 mbedtls_ctr_drbg_free(&session->ctr_drbg);
79 mbedtls_ssl_config_free(&session->conf);
80 mbedtls_ssl_free(&session->ssl);
81 LOGD("MbedTLS connection close success.");
82 return RET_EOK;
83 }
84
MbedtlsClientContext(MbedTLSSession * session)85 int MbedtlsClientContext(MbedTLSSession *session)
86 {
87 if (session == NULL) {
88 return -RET_ERROR;
89 }
90 int ret = mbedtls_x509_crt_parse(&session->cacert, (const unsigned char *)G_MBEDTLS_ROOT_CERTIFICATE,
91 G_MBEDTLS_ROOT_CERTIFICATE_LEN);
92 if (ret < 0) {
93 LOGE("mbedtls_x509_crt_parse error, return -0x%x.", -ret);
94 return ret;
95 }
96
97 LOGD("Loading the CA root certificate success...");
98
99 // Hostname set here should match CN in server certificate
100 if (session->host != NULL) {
101 ret = mbedtls_ssl_set_hostname(&session->ssl, session->host);
102 if (ret != 0) {
103 LOGD("mbedtls_ssl_set_hostname error, return -0x%x", -ret);
104 return ret;
105 }
106 }
107
108 ret = mbedtls_ssl_config_defaults(&session->conf,
109 MBEDTLS_SSL_IS_CLIENT,
110 MBEDTLS_SSL_TRANSPORT_STREAM,
111 MBEDTLS_SSL_PRESET_DEFAULT);
112 if (ret != 0) {
113 LOGD("mbedtls_ssl_config_defaults error, return -0x%x.", -ret);
114 return ret;
115 }
116
117 // If you want to verify the validity of the server certificate,
118 // you need to replace MBEDTLS_SSL_VERIFY_NONE with MBEDTLS_SSL_VERIFY_REQUIRED
119 mbedtls_ssl_conf_authmode(&session->conf, MBEDTLS_SSL_VERIFY_NONE);
120 mbedtls_ssl_conf_ca_chain(&session->conf, &session->cacert, NULL);
121 mbedtls_ssl_conf_rng(&session->conf, mbedtls_ctr_drbg_random, &session->ctr_drbg);
122 mbedtls_ssl_conf_dbg(&session->conf, SslDebug, NULL);
123 ret = mbedtls_ssl_setup(&session->ssl, &session->conf);
124 if (ret != 0) {
125 LOGD("mbedtls_ssl_setup error, return -0x%x.", -ret);
126 return ret;
127 }
128 LOGD("mbedtls client context init success...");
129
130 return RET_EOK;
131 }
132
MbedtlsClientConnect(MbedTLSSession * session)133 int MbedtlsClientConnect(MbedTLSSession *session)
134 {
135 if (session == NULL) {
136 return -RET_ERROR;
137 }
138 LOGI("connect: host:%s, port: %s", session->host, session->port);
139
140 int ret = mbedtls_net_connect(&session->server_fd, session->host, session->port, MBEDTLS_NET_PROTO_TCP);
141 if (ret != 0) {
142 LOGD("mbedtls_net_connect error, return -0x%x.", -ret);
143 return ret;
144 }
145 LOGD("Connected %s:%s fd:%d, success...", session->host, session->port, session->server_fd.fd);
146
147 mbedtls_ssl_set_bio(&session->ssl, &session->server_fd, mbedtls_net_send, mbedtls_net_recv, NULL);
148 LOGD("ssl state=%d", session->ssl.state);
149
150 while ((ret = mbedtls_ssl_handshake(&session->ssl)) != 0) {
151 LOGD("mbedtls_ssl_handshake ret=0x%x.", -ret);
152 if (RET_EOK != MbedtlsSslCertificateVerify(session)) {
153 return -RET_ERROR;
154 }
155 if (ret != MBEDTLS_ERR_SSL_WANT_READ && ret != MBEDTLS_ERR_SSL_WANT_WRITE) {
156 LOGD("mbedtls_ssl_handshake error, return -0x%x.", -ret);
157 return ret;
158 }
159 }
160
161 if (RET_EOK != MbedtlsSslCertificateVerify(session)) {
162 LOGD("Certificate verified err...");
163 return -RET_ERROR;
164 }
165
166 LOGD("Certificate verified success...");
167
168 return RET_EOK;
169 }
170
MbedtlsClientRead(MbedTLSSession * session,unsigned char * buf,size_t len)171 int MbedtlsClientRead(MbedTLSSession *session, unsigned char *buf, size_t len)
172 {
173 if (session == NULL || buf == NULL) {
174 return -RET_ERROR;
175 }
176 int ret = mbedtls_ssl_read(&session->ssl, (unsigned char *)buf, len);
177 if (ret < 0 && ret != MBEDTLS_ERR_SSL_WANT_READ && ret != MBEDTLS_ERR_SSL_WANT_WRITE) {
178 LOGD("MbedtlsClientRead data error, return -0x%x.", -ret);
179 }
180 return ret;
181 }
182
MbedtlsClientWrite(MbedTLSSession * session,const unsigned char * buf,size_t len)183 int MbedtlsClientWrite(MbedTLSSession *session, const unsigned char *buf, size_t len)
184 {
185 if (session == NULL || buf == NULL) {
186 return -RET_ERROR;
187 }
188 int ret = mbedtls_ssl_write(&session->ssl, (unsigned char *)buf, len);
189 if (ret < 0 && ret != MBEDTLS_ERR_SSL_WANT_READ && ret != MBEDTLS_ERR_SSL_WANT_WRITE) {
190 LOGD("MbedtlsClientWrite data error, return -0x%x.", -ret);
191 }
192 return ret;
193 }