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