1 /*
2  *  Simple DTLS server demonstration program
3  *
4  *  Copyright The Mbed TLS Contributors
5  *  SPDX-License-Identifier: Apache-2.0
6  *
7  *  Licensed under the Apache License, Version 2.0 (the "License"); you may
8  *  not use this file except in compliance with the License.
9  *  You may obtain a copy of the License at
10  *
11  *  http://www.apache.org/licenses/LICENSE-2.0
12  *
13  *  Unless required by applicable law or agreed to in writing, software
14  *  distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
15  *  WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16  *  See the License for the specific language governing permissions and
17  *  limitations under the License.
18  */
19 
20 #include "mbedtls/build_info.h"
21 
22 #if defined(MBEDTLS_PLATFORM_C)
23 #include "mbedtls/platform.h"
24 #else
25 #include <stdio.h>
26 #include <stdlib.h>
27 #define mbedtls_printf     printf
28 #define mbedtls_fprintf    fprintf
29 #define mbedtls_time_t     time_t
30 #define mbedtls_exit            exit
31 #define MBEDTLS_EXIT_SUCCESS    EXIT_SUCCESS
32 #define MBEDTLS_EXIT_FAILURE    EXIT_FAILURE
33 #endif
34 
35 /* Uncomment out the following line to default to IPv4 and disable IPv6 */
36 //#define FORCE_IPV4
37 
38 #ifdef FORCE_IPV4
39 #define BIND_IP     "0.0.0.0"     /* Forces IPv4 */
40 #else
41 #define BIND_IP     "::"
42 #endif
43 
44 #if !defined(MBEDTLS_SSL_SRV_C) || !defined(MBEDTLS_SSL_PROTO_DTLS) ||    \
45     !defined(MBEDTLS_SSL_COOKIE_C) || !defined(MBEDTLS_NET_C) ||          \
46     !defined(MBEDTLS_ENTROPY_C) || !defined(MBEDTLS_CTR_DRBG_C) ||        \
47     !defined(MBEDTLS_X509_CRT_PARSE_C) || !defined(MBEDTLS_RSA_C) ||      \
48     !defined(MBEDTLS_PEM_PARSE_C) || !defined(MBEDTLS_TIMING_C)
49 
main(void)50 int main( void )
51 {
52     printf( "MBEDTLS_SSL_SRV_C and/or MBEDTLS_SSL_PROTO_DTLS and/or "
53             "MBEDTLS_SSL_COOKIE_C and/or MBEDTLS_NET_C and/or "
54             "MBEDTLS_ENTROPY_C and/or MBEDTLS_CTR_DRBG_C and/or "
55             "MBEDTLS_X509_CRT_PARSE_C and/or MBEDTLS_RSA_C and/or "
56             "MBEDTLS_PEM_PARSE_C and/or MBEDTLS_TIMING_C not defined.\n" );
57     mbedtls_exit( 0 );
58 }
59 #else
60 
61 #if defined(_WIN32)
62 #include <windows.h>
63 #endif
64 
65 #include <string.h>
66 #include <stdlib.h>
67 #include <stdio.h>
68 
69 #include "mbedtls/entropy.h"
70 #include "mbedtls/ctr_drbg.h"
71 #include "mbedtls/x509.h"
72 #include "mbedtls/ssl.h"
73 #include "mbedtls/ssl_cookie.h"
74 #include "mbedtls/net_sockets.h"
75 #include "mbedtls/error.h"
76 #include "mbedtls/debug.h"
77 #include "mbedtls/timing.h"
78 
79 #include "test/certs.h"
80 
81 #if defined(MBEDTLS_SSL_CACHE_C)
82 #include "mbedtls/ssl_cache.h"
83 #endif
84 
85 #define READ_TIMEOUT_MS 10000   /* 10 seconds */
86 #define DEBUG_LEVEL 0
87 
88 
my_debug(void * ctx,int level,const char * file,int line,const char * str)89 static void my_debug( void *ctx, int level,
90                       const char *file, int line,
91                       const char *str )
92 {
93     ((void) level);
94 
95     mbedtls_fprintf( (FILE *) ctx, "%s:%04d: %s", file, line, str );
96     fflush(  (FILE *) ctx  );
97 }
98 
main(void)99 int main( void )
100 {
101     int ret, len;
102     mbedtls_net_context listen_fd, client_fd;
103     unsigned char buf[1024];
104     const char *pers = "dtls_server";
105     unsigned char client_ip[16] = { 0 };
106     size_t cliip_len;
107     mbedtls_ssl_cookie_ctx cookie_ctx;
108 
109     mbedtls_entropy_context entropy;
110     mbedtls_ctr_drbg_context ctr_drbg;
111     mbedtls_ssl_context ssl;
112     mbedtls_ssl_config conf;
113     mbedtls_x509_crt srvcert;
114     mbedtls_pk_context pkey;
115     mbedtls_timing_delay_context timer;
116 #if defined(MBEDTLS_SSL_CACHE_C)
117     mbedtls_ssl_cache_context cache;
118 #endif
119 
120     mbedtls_net_init( &listen_fd );
121     mbedtls_net_init( &client_fd );
122     mbedtls_ssl_init( &ssl );
123     mbedtls_ssl_config_init( &conf );
124     mbedtls_ssl_cookie_init( &cookie_ctx );
125 #if defined(MBEDTLS_SSL_CACHE_C)
126     mbedtls_ssl_cache_init( &cache );
127 #endif
128     mbedtls_x509_crt_init( &srvcert );
129     mbedtls_pk_init( &pkey );
130     mbedtls_entropy_init( &entropy );
131     mbedtls_ctr_drbg_init( &ctr_drbg );
132 
133 #if defined(MBEDTLS_DEBUG_C)
134     mbedtls_debug_set_threshold( DEBUG_LEVEL );
135 #endif
136 
137     /*
138      * 1. Seed the RNG
139      */
140     printf( "  . Seeding the random number generator..." );
141     fflush( stdout );
142 
143     if( ( ret = mbedtls_ctr_drbg_seed( &ctr_drbg, mbedtls_entropy_func, &entropy,
144                                (const unsigned char *) pers,
145                                strlen( pers ) ) ) != 0 )
146     {
147         printf( " failed\n  ! mbedtls_ctr_drbg_seed returned %d\n", ret );
148         goto exit;
149     }
150 
151     printf( " ok\n" );
152 
153     /*
154      * 2. Load the certificates and private RSA key
155      */
156     printf( "\n  . Loading the server cert. and key..." );
157     fflush( stdout );
158 
159     /*
160      * This demonstration program uses embedded test certificates.
161      * Instead, you may want to use mbedtls_x509_crt_parse_file() to read the
162      * server and CA certificates, as well as mbedtls_pk_parse_keyfile().
163      */
164     ret = mbedtls_x509_crt_parse( &srvcert, (const unsigned char *) mbedtls_test_srv_crt,
165                           mbedtls_test_srv_crt_len );
166     if( ret != 0 )
167     {
168         printf( " failed\n  !  mbedtls_x509_crt_parse returned %d\n\n", ret );
169         goto exit;
170     }
171 
172     ret = mbedtls_x509_crt_parse( &srvcert, (const unsigned char *) mbedtls_test_cas_pem,
173                           mbedtls_test_cas_pem_len );
174     if( ret != 0 )
175     {
176         printf( " failed\n  !  mbedtls_x509_crt_parse returned %d\n\n", ret );
177         goto exit;
178     }
179 
180     ret =  mbedtls_pk_parse_key( &pkey, (const unsigned char *) mbedtls_test_srv_key,
181                          mbedtls_test_srv_key_len, NULL, 0, mbedtls_ctr_drbg_random, &ctr_drbg );
182     if( ret != 0 )
183     {
184         printf( " failed\n  !  mbedtls_pk_parse_key returned %d\n\n", ret );
185         goto exit;
186     }
187 
188     printf( " ok\n" );
189 
190     /*
191      * 3. Setup the "listening" UDP socket
192      */
193     printf( "  . Bind on udp/*/4433 ..." );
194     fflush( stdout );
195 
196     if( ( ret = mbedtls_net_bind( &listen_fd, BIND_IP, "4433", MBEDTLS_NET_PROTO_UDP ) ) != 0 )
197     {
198         printf( " failed\n  ! mbedtls_net_bind returned %d\n\n", ret );
199         goto exit;
200     }
201 
202     printf( " ok\n" );
203 
204     /*
205      * 4. Setup stuff
206      */
207     printf( "  . Setting up the DTLS data..." );
208     fflush( stdout );
209 
210     if( ( ret = mbedtls_ssl_config_defaults( &conf,
211                     MBEDTLS_SSL_IS_SERVER,
212                     MBEDTLS_SSL_TRANSPORT_DATAGRAM,
213                     MBEDTLS_SSL_PRESET_DEFAULT ) ) != 0 )
214     {
215         mbedtls_printf( " failed\n  ! mbedtls_ssl_config_defaults returned %d\n\n", ret );
216         goto exit;
217     }
218 
219     mbedtls_ssl_conf_rng( &conf, mbedtls_ctr_drbg_random, &ctr_drbg );
220     mbedtls_ssl_conf_dbg( &conf, my_debug, stdout );
221     mbedtls_ssl_conf_read_timeout( &conf, READ_TIMEOUT_MS );
222 
223 #if defined(MBEDTLS_SSL_CACHE_C)
224     mbedtls_ssl_conf_session_cache( &conf, &cache,
225                                    mbedtls_ssl_cache_get,
226                                    mbedtls_ssl_cache_set );
227 #endif
228 
229     mbedtls_ssl_conf_ca_chain( &conf, srvcert.next, NULL );
230    if( ( ret = mbedtls_ssl_conf_own_cert( &conf, &srvcert, &pkey ) ) != 0 )
231     {
232         printf( " failed\n  ! mbedtls_ssl_conf_own_cert returned %d\n\n", ret );
233         goto exit;
234     }
235 
236     if( ( ret = mbedtls_ssl_cookie_setup( &cookie_ctx,
237                                   mbedtls_ctr_drbg_random, &ctr_drbg ) ) != 0 )
238     {
239         printf( " failed\n  ! mbedtls_ssl_cookie_setup returned %d\n\n", ret );
240         goto exit;
241     }
242 
243     mbedtls_ssl_conf_dtls_cookies( &conf, mbedtls_ssl_cookie_write, mbedtls_ssl_cookie_check,
244                                &cookie_ctx );
245 
246     if( ( ret = mbedtls_ssl_setup( &ssl, &conf ) ) != 0 )
247     {
248         printf( " failed\n  ! mbedtls_ssl_setup returned %d\n\n", ret );
249         goto exit;
250     }
251 
252     mbedtls_ssl_set_timer_cb( &ssl, &timer, mbedtls_timing_set_delay,
253                                             mbedtls_timing_get_delay );
254 
255     printf( " ok\n" );
256 
257 reset:
258 #ifdef MBEDTLS_ERROR_C
259     if( ret != 0 )
260     {
261         char error_buf[100];
262         mbedtls_strerror( ret, error_buf, 100 );
263         printf("Last error was: %d - %s\n\n", ret, error_buf );
264     }
265 #endif
266 
267     mbedtls_net_free( &client_fd );
268 
269     mbedtls_ssl_session_reset( &ssl );
270 
271     /*
272      * 3. Wait until a client connects
273      */
274     printf( "  . Waiting for a remote connection ..." );
275     fflush( stdout );
276 
277     if( ( ret = mbedtls_net_accept( &listen_fd, &client_fd,
278                     client_ip, sizeof( client_ip ), &cliip_len ) ) != 0 )
279     {
280         printf( " failed\n  ! mbedtls_net_accept returned %d\n\n", ret );
281         goto exit;
282     }
283 
284     /* For HelloVerifyRequest cookies */
285     if( ( ret = mbedtls_ssl_set_client_transport_id( &ssl,
286                     client_ip, cliip_len ) ) != 0 )
287     {
288         printf( " failed\n  ! "
289                 "mbedtls_ssl_set_client_transport_id() returned -0x%x\n\n", (unsigned int) -ret );
290         goto exit;
291     }
292 
293     mbedtls_ssl_set_bio( &ssl, &client_fd,
294                          mbedtls_net_send, mbedtls_net_recv, mbedtls_net_recv_timeout );
295 
296     printf( " ok\n" );
297 
298     /*
299      * 5. Handshake
300      */
301     printf( "  . Performing the DTLS handshake..." );
302     fflush( stdout );
303 
304     do ret = mbedtls_ssl_handshake( &ssl );
305     while( ret == MBEDTLS_ERR_SSL_WANT_READ ||
306            ret == MBEDTLS_ERR_SSL_WANT_WRITE );
307 
308     if( ret == MBEDTLS_ERR_SSL_HELLO_VERIFY_REQUIRED )
309     {
310         printf( " hello verification requested\n" );
311         ret = 0;
312         goto reset;
313     }
314     else if( ret != 0 )
315     {
316         printf( " failed\n  ! mbedtls_ssl_handshake returned -0x%x\n\n", (unsigned int) -ret );
317         goto reset;
318     }
319 
320     printf( " ok\n" );
321 
322     /*
323      * 6. Read the echo Request
324      */
325     printf( "  < Read from client:" );
326     fflush( stdout );
327 
328     len = sizeof( buf ) - 1;
329     memset( buf, 0, sizeof( buf ) );
330 
331     do ret = mbedtls_ssl_read( &ssl, buf, len );
332     while( ret == MBEDTLS_ERR_SSL_WANT_READ ||
333            ret == MBEDTLS_ERR_SSL_WANT_WRITE );
334 
335     if( ret <= 0 )
336     {
337         switch( ret )
338         {
339             case MBEDTLS_ERR_SSL_TIMEOUT:
340                 printf( " timeout\n\n" );
341                 goto reset;
342 
343             case MBEDTLS_ERR_SSL_PEER_CLOSE_NOTIFY:
344                 printf( " connection was closed gracefully\n" );
345                 ret = 0;
346                 goto close_notify;
347 
348             default:
349                 printf( " mbedtls_ssl_read returned -0x%x\n\n", (unsigned int) -ret );
350                 goto reset;
351         }
352     }
353 
354     len = ret;
355     printf( " %d bytes read\n\n%s\n\n", len, buf );
356 
357     /*
358      * 7. Write the 200 Response
359      */
360     printf( "  > Write to client:" );
361     fflush( stdout );
362 
363     do ret = mbedtls_ssl_write( &ssl, buf, len );
364     while( ret == MBEDTLS_ERR_SSL_WANT_READ ||
365            ret == MBEDTLS_ERR_SSL_WANT_WRITE );
366 
367     if( ret < 0 )
368     {
369         printf( " failed\n  ! mbedtls_ssl_write returned %d\n\n", ret );
370         goto exit;
371     }
372 
373     len = ret;
374     printf( " %d bytes written\n\n%s\n\n", len, buf );
375 
376     /*
377      * 8. Done, cleanly close the connection
378      */
379 close_notify:
380     printf( "  . Closing the connection..." );
381 
382     /* No error checking, the connection might be closed already */
383     do ret = mbedtls_ssl_close_notify( &ssl );
384     while( ret == MBEDTLS_ERR_SSL_WANT_WRITE );
385     ret = 0;
386 
387     printf( " done\n" );
388 
389     goto reset;
390 
391     /*
392      * Final clean-ups and exit
393      */
394 exit:
395 
396 #ifdef MBEDTLS_ERROR_C
397     if( ret != 0 )
398     {
399         char error_buf[100];
400         mbedtls_strerror( ret, error_buf, 100 );
401         printf( "Last error was: %d - %s\n\n", ret, error_buf );
402     }
403 #endif
404 
405     mbedtls_net_free( &client_fd );
406     mbedtls_net_free( &listen_fd );
407 
408     mbedtls_x509_crt_free( &srvcert );
409     mbedtls_pk_free( &pkey );
410     mbedtls_ssl_free( &ssl );
411     mbedtls_ssl_config_free( &conf );
412     mbedtls_ssl_cookie_free( &cookie_ctx );
413 #if defined(MBEDTLS_SSL_CACHE_C)
414     mbedtls_ssl_cache_free( &cache );
415 #endif
416     mbedtls_ctr_drbg_free( &ctr_drbg );
417     mbedtls_entropy_free( &entropy );
418 
419 #if defined(_WIN32)
420     printf( "  Press Enter to exit this program.\n" );
421     fflush( stdout ); getchar();
422 #endif
423 
424     /* Shell can not handle large exit numbers -> 1 for errors */
425     if( ret < 0 )
426         ret = 1;
427 
428     mbedtls_exit( ret );
429 }
430 #endif /* MBEDTLS_SSL_SRV_C && MBEDTLS_SSL_PROTO_DTLS &&
431           MBEDTLS_SSL_COOKIE_C && MBEDTLS_NET_C && MBEDTLS_ENTROPY_C &&
432           MBEDTLS_CTR_DRBG_C && MBEDTLS_X509_CRT_PARSE_C && MBEDTLS_RSA_C
433           && MBEDTLS_PEM_PARSE_C && MBEDTLS_TIMING_C */
434