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