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 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 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 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 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 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 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