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