1 /*
2 * Copyright (c) 2006-2021, RT-Thread Development Team
3 *
4 * SPDX-License-Identifier: Apache-2.0
5 *
6 * Change Logs:
7 * Date Author Notes
8 * 2018-11-12 ChenYong First version
9 */
10
11 #include <rtthread.h>
12
13 #ifdef RT_USING_DFS
14 #include <unistd.h>
15 #include <sys/stat.h>
16 #include <sys/statfs.h>
17 #endif
18
19 #ifdef SAL_USING_TLS
20 #include <sal_tls.h>
21 #endif
22 #include <netdb.h>
23 #include <sal_low_lvl.h>
24
25 #include <netdev.h>
26
27 #ifdef SAL_USING_TLS
28
29 #if !defined(MBEDTLS_CONFIG_FILE)
30 #include <mbedtls/config.h>
31 #else
32 #include MBEDTLS_CONFIG_FILE
33 #endif
34
35 #include <tls_certificate.h>
36 #include <tls_client.h>
37
38 #ifndef SAL_MEBDTLS_BUFFER_LEN
39 #define SAL_MEBDTLS_BUFFER_LEN 1024
40 #endif
41
mebdtls_socket(int socket)42 static void *mebdtls_socket(int socket)
43 {
44 MbedTLSSession *session = RT_NULL;
45 char *pers = "mbedtls";
46
47 if (socket < 0)
48 {
49 return RT_NULL;
50 }
51
52 session = (MbedTLSSession *) tls_calloc(1, sizeof(MbedTLSSession));
53 if (session == RT_NULL)
54 {
55 return RT_NULL;
56 }
57
58 session->buffer_len = SAL_MEBDTLS_BUFFER_LEN;
59 session->buffer = tls_calloc(1, session->buffer_len);
60 if (session->buffer == RT_NULL)
61 {
62 tls_free(session);
63 session = RT_NULL;
64
65 return RT_NULL;
66 }
67
68 /* initialize TLS Client sesison */
69 if (mbedtls_client_init(session, (void *) pers, rt_strlen(pers)) != RT_EOK)
70 {
71 mbedtls_client_close(session);
72 return RT_NULL;
73 }
74 session->server_fd.fd = socket;
75
76 return (void *)session;
77 }
78
mbedtls_net_send_cb(void * ctx,const unsigned char * buf,size_t len)79 int mbedtls_net_send_cb(void *ctx, const unsigned char *buf, size_t len)
80 {
81 struct sal_socket *sock;
82 int socket, ret;
83 struct sal_proto_family *pf;
84
85 RT_ASSERT(ctx);
86 RT_ASSERT(buf);
87
88 socket = ((mbedtls_net_context *) ctx)->fd;
89 sock = sal_get_socket(socket);
90 if (sock == RT_NULL)
91 {
92 return -1;
93 }
94
95 pf = (struct sal_proto_family *)sock->netdev->sal_user_data;
96
97 /* Register scoket sendto option to TLS send data callback */
98 ret = pf->skt_ops->sendto((int) sock->user_data, (void *)buf, len, 0, RT_NULL, RT_NULL);
99 if (ret < 0)
100 {
101 #ifdef RT_USING_DFS
102 if ((fcntl(socket, F_GETFL) & O_NONBLOCK) == O_NONBLOCK)
103 return MBEDTLS_ERR_SSL_WANT_WRITE;
104 #endif
105 if (errno == ECONNRESET)
106 return MBEDTLS_ERR_NET_CONN_RESET;
107 if ( errno == EINTR)
108 return MBEDTLS_ERR_SSL_WANT_READ;
109
110 return MBEDTLS_ERR_NET_SEND_FAILED ;
111 }
112
113 return ret;
114 }
115
mbedtls_net_recv_cb(void * ctx,unsigned char * buf,size_t len)116 int mbedtls_net_recv_cb( void *ctx, unsigned char *buf, size_t len)
117 {
118 struct sal_socket *sock;
119 struct sal_proto_family *pf;
120 int socket, ret;
121
122 RT_ASSERT(ctx);
123 RT_ASSERT(buf);
124
125 socket = ((mbedtls_net_context *) ctx)->fd;
126 sock = sal_get_socket(socket);
127 if (sock == RT_NULL)
128 {
129 return -1;
130 }
131
132 pf = (struct sal_proto_family *)sock->netdev->sal_user_data;
133
134 /* Register scoket recvfrom option to TLS recv data callback */
135 ret = pf->skt_ops->recvfrom((int) sock->user_data, (void *)buf, len, 0, RT_NULL, RT_NULL);
136 if (ret < 0)
137 {
138 #ifdef RT_USING_DFS
139 if ((fcntl(socket, F_GETFL) & O_NONBLOCK) == O_NONBLOCK)
140 return MBEDTLS_ERR_SSL_WANT_WRITE;
141 #endif
142 if (errno == ECONNRESET)
143 return MBEDTLS_ERR_NET_CONN_RESET;
144 if ( errno == EINTR)
145 return MBEDTLS_ERR_SSL_WANT_READ;
146
147 return MBEDTLS_ERR_NET_RECV_FAILED ;
148 }
149
150 return ret;
151 }
152
mbedtls_connect(void * sock)153 static int mbedtls_connect(void *sock)
154 {
155 MbedTLSSession *session = RT_NULL;
156 int ret = 0;
157
158 RT_ASSERT(sock);
159
160 session = (MbedTLSSession *) sock;
161
162 /* Set the SSL Configure infromation */
163 ret = mbedtls_client_context(session);
164 if (ret < 0)
165 {
166 goto __exit;
167 }
168
169 /* Set the underlying BIO callbacks for write, read and read-with-timeout. */
170 mbedtls_ssl_set_bio(&session->ssl, &session->server_fd, mbedtls_net_send_cb, mbedtls_net_recv_cb, RT_NULL);
171
172 while ((ret = mbedtls_ssl_handshake(&session->ssl)) != 0)
173 {
174 if (ret != MBEDTLS_ERR_SSL_WANT_READ && ret != MBEDTLS_ERR_SSL_WANT_WRITE)
175 {
176 goto __exit;
177 }
178 }
179
180 /* Return the result of the certificate verification */
181 ret = mbedtls_ssl_get_verify_result(&session->ssl);
182 if (ret != 0)
183 {
184 rt_memset(session->buffer, 0x00, session->buffer_len);
185 mbedtls_x509_crt_verify_info((char *)session->buffer, session->buffer_len, " ! ", ret);
186 goto __exit;
187 }
188
189 return ret;
190
191 __exit:
192 if (session)
193 {
194 mbedtls_client_close(session);
195 }
196
197 return ret;
198 }
199
mbedtls_closesocket(void * sock)200 static int mbedtls_closesocket(void *sock)
201 {
202 struct sal_socket *ssock;
203 int socket;
204
205 if (sock == RT_NULL)
206 {
207 return 0;
208 }
209
210 socket = ((MbedTLSSession *) sock)->server_fd.fd;
211 ssock = sal_get_socket(socket);
212 if (ssock == RT_NULL)
213 {
214 return -1;
215 }
216
217 /* Close TLS client session, and clean user-data in SAL socket */
218 mbedtls_client_close((MbedTLSSession *) sock);
219 ssock->user_data_tls = RT_NULL;
220
221 return 0;
222 }
223
224 static const struct sal_proto_tls_ops mbedtls_proto_ops=
225 {
226 RT_NULL,
227 mebdtls_socket,
228 mbedtls_connect,
229 (int (*)(void *sock, const void *data, size_t size)) mbedtls_client_write,
230 (int (*)(void *sock, void *mem, size_t len)) mbedtls_client_read,
231 mbedtls_closesocket,
232 };
233
234 static const struct sal_proto_tls mbedtls_proto =
235 {
236 "mbedtls",
237 &mbedtls_proto_ops,
238 };
239
sal_mbedtls_proto_init(void)240 int sal_mbedtls_proto_init(void)
241 {
242 /* register MbedTLS protocol options to SAL */
243 sal_proto_tls_register(&mbedtls_proto);
244
245 return 0;
246 }
247 INIT_COMPONENT_EXPORT(sal_mbedtls_proto_init);
248
249 #endif /* SAL_USING_TLS */
250