Loading...
Searching...
No Matches
sock_tls.h
1/*
2 * Copyright (C) 2019 Daniele Lacamera
3 *
4 *
5 * This file is subject to the terms and conditions of the GNU Lesser
6 * General Public License v2.1. See the file LICENSE in the top level
7 * directory for more details.
8 */
9
10#pragma once
11
12/* @defgroup module sock_tls
13 * @ingroup pkg_wolfssl
14 * @brief Sock submodule for TLS/DTLS sessions
15 *
16 * How To Use
17 * ----------
18 * First you need to [include][include-link]
19 * a module that implements this API in your application's Makefile.
20 *
21 * The `sock_tls` module requires the `wolfssl` package.
22 *
23 * The application's Makefile should at lease contain the following:
24 *
25 * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ {Makefile}
26 *
27 * USEPKG += wolfssl
28 * USEMODULE+=sock_tls
29 *
30 * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
31 *
32 *
33 * ### A Simple DTLS Server
34 *
35 * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ {.c}
36 * #include <wolfssl/ssl.h>
37 * #include <sock_tls.h>
38 *
39 * #include <stdio.h>
40 * #include <inttypes.h>
41 *
42 * #include <net/sock/udp.h>
43 *
44 * #include <stdio.h>
45 * #include <stdlib.h>
46 * #include <string.h>
47 *
48 * #define SERVER_PORT 11111
49 * #define DEBUG 1
50 * extern const unsigned char server_cert[788];
51 * extern const unsigned char server_key[121];
52 * extern unsigned int server_cert_len;
53 * extern unsigned int server_key_len;
54 *
55 * static sock_tls_t skv;
56 * static sock_tls_t *sk = &skv;
57 * static const char Test_dtls_string[] = "DTLS OK!";
58 *
59 * int main(void)
60 * {
61 * char buf[64];
62 * int ret;
63 * sock_udp_ep_t local = SOCK_IPV6_EP_ANY;
64 * local.port = SERVER_PORT;
65 *
66 * if (sock_dtls_create(sk, &local, NULL, 0, wolfDTLSv1_2_server_method()) != 0) {
67 * printf("Failed to create DTLS socket context\r\n");
68 * return -1;
69 * }
70 * if (wolfSSL_CTX_use_certificate_buffer(sk->ctx, server_cert,
71 * server_cert_len, SSL_FILETYPE_ASN1 ) != SSL_SUCCESS)
72 * {
73 * printf("Failed to load certificate from memory.\r\n");
74 * return -1;
75 * }
76 *
77 * if (wolfSSL_CTX_use_PrivateKey_buffer(sk->ctx, server_key,
78 * server_key_len, SSL_FILETYPE_ASN1 ) != SSL_SUCCESS)
79 * {
80 * printf("Failed to load private key from memory.\r\n");
81 * return -1;
82 * }
83 * ret = sock_dtls_session_create(sk);
84 * if (ret < 0)
85 * {
86 * printf("Failed to create DTLS session (err: %s)\r\n", strerror(-ret));
87 * return -1;
88 * }
89 * printf("Listening on %d\n", SERVER_PORT);
90 * while(1) {
91 * ret = wolfSSL_accept(sk->ssl);
92 * if (ret != SSL_SUCCESS) {
93 * continue;
94 * }
95 * printf("Connection accepted\r\n");
96 * ret = wolfSSL_read(sk->ssl, buf, 64);
97 * if (ret > 0) {
98 * buf[ret] = (char)0;
99 * printf("Received '%s'\r\n", buf);
100 * }
101 * printf("Sending 'DTLS OK'...\r\n");
102 * wolfSSL_write(sk->ssl, Test_dtls_string, sizeof(Test_dtls_string));
103 * printf("Closing connection.\r\n");
104 * sock_dtls_session_destroy(sk);
105 * sock_dtls_close(sk);
106 * break;
107 * }
108 * return 0;
109 * }
110 * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
111 *
112 * Above you see a simple DTLS echo server. It is important to at least
113 * [include][include-link] the IPv6 module of your networking
114 * implementation (e.g. `gnrc_ipv6_default` for @ref net_gnrc GNRC) and at least
115 * one network device.
116 * A separate file should define the buffers used as certificate and private key,
117 * in the variables `server_cert`, `private_key` respectively.
118 *
119 * After including all the needed header files, we use a global object to store
120 * the context for incoming DTLS communication. The object contains the reference
121 * to the wolfSSL context, the SSL session and the underlying transport socket.
122 *
123 * For simplicity, we will refer to the address of the object in the static memory,
124 * through the pointer `sk`.
125 *
126 * A constant test string is used later as a reply to incoming connections.
127 *
128 * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ {.c}
129 * static sock_tls_t skv;
130 * static sock_tls_t *sk = &skv;
131 *
132 * static const char Test_dtls_string[] = "DTLS OK!";
133 * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
134 *
135 * In the same way as a normal @ref net_sock_udp "UDP socket", in order to be able to
136 * listen for incoming packets, we bind the `sock` by setting a local endpoint with
137 * a port (`11111` in this case).
138 *
139 * We then proceed to create the `sock`. It is bound to `local` and thus listens
140 * for UDP packets with @ref udp_hdr_t::dst_port "destination port" `12345`.
141 * Since we don't need any further configuration we set the flags to 0.
142 * The method argument determines which kind of wolfSSL context is associated to
143 * the socket.
144*
145 * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ {.c}
146 * sock_udp_ep_t local = SOCK_IPV6_EP_ANY;
147 * local.port = SERVER_PORT;
148 *
149 * if (sock_dtls_create(sk, &local, NULL, 0, wolfDTLSv1_2_server_method()) != 0) {
150 * printf("ERROR: Unable to create DTLS sock\r\n");
151 * return -1;
152 * }
153 * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
154 *
155 * By default, all sock_tls operations in a DTLS context are blocking for a
156 * limited amount of time, which depends on the DTLS session timeout. To modify
157 * the timeout, use `wolfSSL_dtls_set_timeout_init(sk->ssl)`.
158 *
159 * Certificate and private key for the server context are loaded from a previously
160 * initialized section in memory:
161 *
162 * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ {.c}
163 * if (wolfSSL_CTX_use_certificate_buffer(sk->ctx, server_cert,
164 * server_cert_len, SSL_FILETYPE_ASN1 ) != SSL_SUCCESS)
165 * {
166 * printf("Failed to load certificate from memory.\r\n");
167 * return -1;
168 * }
169 *
170 * if (wolfSSL_CTX_use_PrivateKey_buffer(sk->ctx, server_key,
171 * server_key_len, SSL_FILETYPE_ASN1 ) != SSL_SUCCESS)
172 * {
173 * printf("Failed to load private key from memory.\r\n");
174 * return -1;
175 * }
176 * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
177 *
178 * Once the context is configured, the SSL session can be initialized.
179 *
180 * The listening sock automatically takes care of the DTLS handshake.
181 * When the session is established, `wolfSSL_accept()` will finally return
182 * `SSL_SUCCESS`.
183 *
184 *
185 * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ {.c}
186 * ret = sock_dtls_session_create(sk);
187 * if (ret < 0)
188 * {
189 * printf("Failed to create DTLS session (err: %s)\r\n", strerror(-ret));
190 * return -1;
191 * }
192 * printf("Listening on %d\n", SERVER_PORT);
193 * while(1) {
194 * ret = wolfSSL_accept(sk->ssl);
195 * if (ret != SSL_SUCCESS) {
196 * continue;
197 * }
198 * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
199 *
200 * At this point, the session is established, and encrypted data can be exchanged
201 * using `wolfSSL_read()` and `wolfSSL_write()`:
202 *
203 * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ {.c}
204 * ret = wolfSSL_read(sk->ssl, buf, 64);
205 * if (ret > 0) {
206 * buf[ret] = (char)0;
207 * printf("Received '%s'\r\n", buf);
208 * }
209 * printf("Sending 'DTLS OK'...\r\n");
210 * wolfSSL_write(sk->ssl, Test_dtls_string, sizeof(Test_dtls_string));
211 * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
212 *
213 * The session is terminated, and the associated socket is closed.
214 *
215 * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ {.c}
216 * sock_dtls_session_destroy(sk);
217 * sock_dtls_close(sk);
218 * break;
219 * }
220 * return 0;
221 * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
222 *
223 * [include-link]: https://guide.riot-os.org/advanced_tutorials/creating_application/#including-modules
224 */
225
226#include <string.h>
227#include <stdlib.h>
228#include <stdio.h>
229
230#include <net/sock.h>
231#include <wolfssl/ssl.h>
232
233#ifdef __cplusplus
234extern "C" {
235#endif
236
286int sock_dtls_create(sock_tls_t *sock, const sock_udp_ep_t *local, const sock_udp_ep_t *remote, uint16_t flags, WOLFSSL_METHOD *method);
287
298void sock_dtls_set_endpoint(sock_tls_t *sk, const sock_udp_ep_t *addr);
299
312int sock_dtls_session_create(sock_tls_t *sk);
313
322void sock_dtls_session_destroy(sock_tls_t *sk);
323
332void sock_dtls_close(sock_tls_t *sk);
333
334#ifdef MODULE_SOCK_TCP
335# error Only support for UDP/IP provided via GNRC stack.
336#endif
337
338#ifdef __cplusplus
339}
340#endif
struct _sock_tl_ep sock_udp_ep_t
An end point for a UDP sock object.
Definition udp.h:295
Common sock API definitions.