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