dtls_server.c 11.8 KB
Newer Older
1 2 3
/*
 *  Simple DTLS server demonstration program
 *
4
 *  Copyright (C) 2006-2015, ARM Limited, All Rights Reserved
5
 *  SPDX-License-Identifier: Apache-2.0
6
 *
7 8 9
 *  Licensed under the Apache License, Version 2.0 (the "License"); you may
 *  not use this file except in compliance with the License.
 *  You may obtain a copy of the License at
10
 *
11
 *  http://www.apache.org/licenses/LICENSE-2.0
12
 *
13 14 15 16 17
 *  Unless required by applicable law or agreed to in writing, software
 *  distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
 *  WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 *  See the License for the specific language governing permissions and
 *  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 27
#endif

28
#if defined(MBEDTLS_PLATFORM_C)
29
#include "mbedtls/platform.h"
30
#else
31
#include <stdio.h>
32 33
#define mbedtls_printf     printf
#define mbedtls_fprintf    fprintf
34
#define mbedtls_time_t     time_t
35 36
#endif

37 38 39 40
#if !defined(MBEDTLS_SSL_SRV_C) || !defined(MBEDTLS_SSL_PROTO_DTLS) ||    \
    !defined(MBEDTLS_SSL_COOKIE_C) || !defined(MBEDTLS_NET_C) ||          \
    !defined(MBEDTLS_ENTROPY_C) || !defined(MBEDTLS_CTR_DRBG_C) ||        \
    !defined(MBEDTLS_X509_CRT_PARSE_C) || !defined(MBEDTLS_RSA_C) ||      \
41 42
    !defined(MBEDTLS_CERTS_C) || !defined(MBEDTLS_PEM_PARSE_C) ||         \
    !defined(MBEDTLS_TIMING_C)
43 44 45

int main( void )
{
46 47 48 49
    printf( "MBEDTLS_SSL_SRV_C and/or MBEDTLS_SSL_PROTO_DTLS and/or "
            "MBEDTLS_SSL_COOKIE_C and/or MBEDTLS_NET_C and/or "
            "MBEDTLS_ENTROPY_C and/or MBEDTLS_CTR_DRBG_C and/or "
            "MBEDTLS_X509_CRT_PARSE_C and/or MBEDTLS_RSA_C and/or "
50 51
            "MBEDTLS_CERTS_C and/or MBEDTLS_PEM_PARSE_C and/or "
            "MBEDTLS_TIMING_C not defined.\n" );
52 53 54 55 56 57 58 59 60 61 62 63
    return( 0 );
}
#else

#if defined(_WIN32)
#include <windows.h>
#endif

#include <string.h>
#include <stdlib.h>
#include <stdio.h>

64 65 66 67 68 69
#include "mbedtls/entropy.h"
#include "mbedtls/ctr_drbg.h"
#include "mbedtls/certs.h"
#include "mbedtls/x509.h"
#include "mbedtls/ssl.h"
#include "mbedtls/ssl_cookie.h"
70
#include "mbedtls/net_sockets.h"
71 72
#include "mbedtls/error.h"
#include "mbedtls/debug.h"
73
#include "mbedtls/timing.h"
74

75
#if defined(MBEDTLS_SSL_CACHE_C)
76
#include "mbedtls/ssl_cache.h"
77 78 79 80 81
#endif

#define READ_TIMEOUT_MS 10000   /* 5 seconds */
#define DEBUG_LEVEL 0

82 83 84
static void my_debug( void *ctx, int level,
                      const char *file, int line,
                      const char *str )
85 86 87
{
    ((void) level);

88
    mbedtls_fprintf( (FILE *) ctx, "%s:%04d: %s", file, line, str );
89 90 91 92 93 94
    fflush(  (FILE *) ctx  );
}

int main( void )
{
    int ret, len;
95
    mbedtls_net_context listen_fd, client_fd;
96 97 98
    unsigned char buf[1024];
    const char *pers = "dtls_server";
    unsigned char client_ip[16] = { 0 };
99
    size_t cliip_len;
100 101 102 103 104
    mbedtls_ssl_cookie_ctx cookie_ctx;

    mbedtls_entropy_context entropy;
    mbedtls_ctr_drbg_context ctr_drbg;
    mbedtls_ssl_context ssl;
105
    mbedtls_ssl_config conf;
106 107
    mbedtls_x509_crt srvcert;
    mbedtls_pk_context pkey;
108
    mbedtls_timing_delay_context timer;
109 110
#if defined(MBEDTLS_SSL_CACHE_C)
    mbedtls_ssl_cache_context cache;
111 112
#endif

113 114
    mbedtls_net_init( &listen_fd );
    mbedtls_net_init( &client_fd );
115
    mbedtls_ssl_init( &ssl );
116
    mbedtls_ssl_config_init( &conf );
117 118 119
    mbedtls_ssl_cookie_init( &cookie_ctx );
#if defined(MBEDTLS_SSL_CACHE_C)
    mbedtls_ssl_cache_init( &cache );
120
#endif
121 122 123
    mbedtls_x509_crt_init( &srvcert );
    mbedtls_pk_init( &pkey );
    mbedtls_entropy_init( &entropy );
124
    mbedtls_ctr_drbg_init( &ctr_drbg );
125

126 127
#if defined(MBEDTLS_DEBUG_C)
    mbedtls_debug_set_threshold( DEBUG_LEVEL );
128 129 130 131 132 133 134 135 136 137
#endif

    /*
     * 1. Load the certificates and private RSA key
     */
    printf( "\n  . Loading the server cert. and key..." );
    fflush( stdout );

    /*
     * This demonstration program uses embedded test certificates.
138 139
     * Instead, you may want to use mbedtls_x509_crt_parse_file() to read the
     * server and CA certificates, as well as mbedtls_pk_parse_keyfile().
140
     */
141 142
    ret = mbedtls_x509_crt_parse( &srvcert, (const unsigned char *) mbedtls_test_srv_crt,
                          mbedtls_test_srv_crt_len );
143 144
    if( ret != 0 )
    {
145
        printf( " failed\n  !  mbedtls_x509_crt_parse returned %d\n\n", ret );
146 147 148
        goto exit;
    }

149 150
    ret = mbedtls_x509_crt_parse( &srvcert, (const unsigned char *) mbedtls_test_cas_pem,
                          mbedtls_test_cas_pem_len );
151 152
    if( ret != 0 )
    {
153
        printf( " failed\n  !  mbedtls_x509_crt_parse returned %d\n\n", ret );
154 155 156
        goto exit;
    }

157 158
    ret =  mbedtls_pk_parse_key( &pkey, (const unsigned char *) mbedtls_test_srv_key,
                         mbedtls_test_srv_key_len, NULL, 0 );
159 160
    if( ret != 0 )
    {
161
        printf( " failed\n  !  mbedtls_pk_parse_key returned %d\n\n", ret );
162 163 164 165 166 167 168 169 170 171 172
        goto exit;
    }

    printf( " ok\n" );

    /*
     * 2. Setup the "listening" UDP socket
     */
    printf( "  . Bind on udp/*/4433 ..." );
    fflush( stdout );

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 177 178 179 180 181 182 183 184 185 186
        goto exit;
    }

    printf( " ok\n" );

    /*
     * 3. Seed the RNG
     */
    printf( "  . Seeding the random number generator..." );
    fflush( stdout );

187
    if( ( ret = mbedtls_ctr_drbg_seed( &ctr_drbg, mbedtls_entropy_func, &entropy,
188 189 190
                               (const unsigned char *) pers,
                               strlen( pers ) ) ) != 0 )
    {
191
        printf( " failed\n  ! mbedtls_ctr_drbg_seed returned %d\n", ret );
192 193 194 195 196 197 198 199 200 201 202
        goto exit;
    }

    printf( " ok\n" );

    /*
     * 4. Setup stuff
     */
    printf( "  . Setting up the DTLS data..." );
    fflush( stdout );

203 204
    if( ( ret = mbedtls_ssl_config_defaults( &conf,
                    MBEDTLS_SSL_IS_SERVER,
205 206
                    MBEDTLS_SSL_TRANSPORT_DATAGRAM,
                    MBEDTLS_SSL_PRESET_DEFAULT ) ) != 0 )
207 208 209 210 211
    {
        mbedtls_printf( " failed\n  ! mbedtls_ssl_config_defaults returned %d\n\n", ret );
        goto exit;
    }

212 213
    mbedtls_ssl_conf_rng( &conf, mbedtls_ctr_drbg_random, &ctr_drbg );
    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 218
                                   mbedtls_ssl_cache_get,
                                   mbedtls_ssl_cache_set );
219 220
#endif

221 222
    mbedtls_ssl_conf_ca_chain( &conf, srvcert.next, NULL );
   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 226 227
        goto exit;
    }

228 229
    if( ( ret = mbedtls_ssl_cookie_setup( &cookie_ctx,
                                  mbedtls_ctr_drbg_random, &ctr_drbg ) ) != 0 )
230
    {
231
        printf( " failed\n  ! mbedtls_ssl_cookie_setup returned %d\n\n", ret );
232 233 234
        goto exit;
    }

235
    mbedtls_ssl_conf_dtls_cookies( &conf, mbedtls_ssl_cookie_write, mbedtls_ssl_cookie_check,
236 237
                               &cookie_ctx );

238 239 240 241 242 243
    if( ( ret = mbedtls_ssl_setup( &ssl, &conf ) ) != 0 )
    {
        printf( " failed\n  ! mbedtls_ssl_setup returned %d\n\n", ret );
        goto exit;
    }

244 245 246
    mbedtls_ssl_set_timer_cb( &ssl, &timer, mbedtls_timing_set_delay,
                                            mbedtls_timing_get_delay );

247 248 249
    printf( " ok\n" );

reset:
250
#ifdef MBEDTLS_ERROR_C
251 252 253
    if( ret != 0 )
    {
        char error_buf[100];
254
        mbedtls_strerror( ret, error_buf, 100 );
255 256 257 258
        printf("Last error was: %d - %s\n\n", ret, error_buf );
    }
#endif

259
    mbedtls_net_free( &client_fd );
260

261
    mbedtls_ssl_session_reset( &ssl );
262 263 264 265 266 267 268

    /*
     * 3. Wait until a client connects
     */
    printf( "  . Waiting for a remote connection ..." );
    fflush( stdout );

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 274 275 276
        goto exit;
    }

    /* For HelloVerifyRequest cookies */
277 278
    if( ( ret = mbedtls_ssl_set_client_transport_id( &ssl,
                    client_ip, cliip_len ) ) != 0 )
279 280
    {
        printf( " failed\n  ! "
281
                "mbedtls_ssl_set_client_transport_id() returned -0x%x\n\n", -ret );
282 283 284
        goto exit;
    }

285
    mbedtls_ssl_set_bio( &ssl, &client_fd,
286
                         mbedtls_net_send, mbedtls_net_recv, mbedtls_net_recv_timeout );
287 288 289 290 291 292 293 294 295

    printf( " ok\n" );

    /*
     * 5. Handshake
     */
    printf( "  . Performing the DTLS handshake..." );
    fflush( stdout );

296
    do ret = mbedtls_ssl_handshake( &ssl );
297 298
    while( ret == MBEDTLS_ERR_SSL_WANT_READ ||
           ret == MBEDTLS_ERR_SSL_WANT_WRITE );
299

300
    if( ret == MBEDTLS_ERR_SSL_HELLO_VERIFY_REQUIRED )
301 302 303 304 305 306 307
    {
        printf( " hello verification requested\n" );
        ret = 0;
        goto reset;
    }
    else if( ret != 0 )
    {
308
        printf( " failed\n  ! mbedtls_ssl_handshake returned -0x%x\n\n", -ret );
309 310 311 312 313 314 315 316 317 318 319 320 321 322
        goto reset;
    }

    printf( " ok\n" );

    /*
     * 6. Read the echo Request
     */
    printf( "  < Read from client:" );
    fflush( stdout );

    len = sizeof( buf ) - 1;
    memset( buf, 0, sizeof( buf ) );

323
    do ret = mbedtls_ssl_read( &ssl, buf, len );
324 325
    while( ret == MBEDTLS_ERR_SSL_WANT_READ ||
           ret == MBEDTLS_ERR_SSL_WANT_WRITE );
326 327 328 329 330

    if( ret <= 0 )
    {
        switch( ret )
        {
331
            case MBEDTLS_ERR_SSL_TIMEOUT:
332 333 334
                printf( " timeout\n\n" );
                goto reset;

335
            case MBEDTLS_ERR_SSL_PEER_CLOSE_NOTIFY:
336 337 338 339 340
                printf( " connection was closed gracefully\n" );
                ret = 0;
                goto close_notify;

            default:
341
                printf( " mbedtls_ssl_read returned -0x%x\n\n", -ret );
342 343 344 345 346 347 348 349 350 351 352 353 354
                goto reset;
        }
    }

    len = ret;
    printf( " %d bytes read\n\n%s\n\n", len, buf );

    /*
     * 7. Write the 200 Response
     */
    printf( "  > Write to client:" );
    fflush( stdout );

355
    do ret = mbedtls_ssl_write( &ssl, buf, len );
356 357
    while( ret == MBEDTLS_ERR_SSL_WANT_READ ||
           ret == MBEDTLS_ERR_SSL_WANT_WRITE );
358 359 360

    if( ret < 0 )
    {
361
        printf( " failed\n  ! mbedtls_ssl_write returned %d\n\n", ret );
362 363 364 365 366 367 368 369 370 371 372 373 374
        goto exit;
    }

    len = ret;
    printf( " %d bytes written\n\n%s\n\n", len, buf );

    /*
     * 8. Done, cleanly close the connection
     */
close_notify:
    printf( "  . Closing the connection..." );

    /* 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 378 379 380 381 382 383 384 385 386 387
    ret = 0;

    printf( " done\n" );

    goto reset;

    /*
     * Final clean-ups and exit
     */
exit:

388
#ifdef MBEDTLS_ERROR_C
389 390 391
    if( ret != 0 )
    {
        char error_buf[100];
392
        mbedtls_strerror( ret, error_buf, 100 );
393 394 395 396
        printf( "Last error was: %d - %s\n\n", ret, error_buf );
    }
#endif

397 398
    mbedtls_net_free( &client_fd );
    mbedtls_net_free( &listen_fd );
399 400 401 402

    mbedtls_x509_crt_free( &srvcert );
    mbedtls_pk_free( &pkey );
    mbedtls_ssl_free( &ssl );
403
    mbedtls_ssl_config_free( &conf );
404 405 406
    mbedtls_ssl_cookie_free( &cookie_ctx );
#if defined(MBEDTLS_SSL_CACHE_C)
    mbedtls_ssl_cache_free( &cache );
407
#endif
408 409
    mbedtls_ctr_drbg_free( &ctr_drbg );
    mbedtls_entropy_free( &entropy );
410 411 412 413 414 415 416 417 418 419 420 421

#if defined(_WIN32)
    printf( "  Press Enter to exit this program.\n" );
    fflush( stdout ); getchar();
#endif

    /* Shell can not handle large exit numbers -> 1 for errors */
    if( ret < 0 )
        ret = 1;

    return( ret );
}
422 423 424
#endif /* MBEDTLS_SSL_SRV_C && MBEDTLS_SSL_PROTO_DTLS &&
          MBEDTLS_SSL_COOKIE_C && MBEDTLS_NET_C && MBEDTLS_ENTROPY_C &&
          MBEDTLS_CTR_DRBG_C && MBEDTLS_X509_CRT_PARSE_C && MBEDTLS_RSA_C
425
          && MBEDTLS_CERTS_C && MBEDTLS_PEM_PARSE_C && MBEDTLS_TIMING_C */