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