xref: /nrf52832-nimble/rt-thread/components/net/sal_socket/impl/proto_mbedtls.c (revision 104654410c56c573564690304ae786df310c91fc)
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