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