dtls_server.c (12066B)
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_ENTROPY_C) || !defined(MBEDTLS_CTR_DRBG_C) || \ 22 !defined(MBEDTLS_NET_C) || !defined(MBEDTLS_SSL_SRV_C) || \ 23 !defined(MBEDTLS_TIMING_C) || !defined(MBEDTLS_SSL_PROTO_DTLS) || \ 24 !defined(MBEDTLS_SSL_COOKIE_C) || \ 25 !defined(MBEDTLS_PEM_PARSE_C) || !defined(MBEDTLS_X509_CRT_PARSE_C) 26 int main(void) 27 { 28 mbedtls_printf("MBEDTLS_ENTROPY_C and/or MBEDTLS_CTR_DRBG_C and/or " 29 "MBEDTLS_NET_C and/or MBEDTLS_SSL_SRV_C and/or " 30 "MBEDTLS_TIMING_C and/or MBEDTLS_SSL_PROTO_DTLS and/or " 31 "MBEDTLS_SSL_COOKIE_C and/or " 32 "MBEDTLS_PEM_PARSE_C and/or MBEDTLS_X509_CRT_PARSE_C " 33 "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 66 static 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 76 int 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 240 reset: 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", (unsigned int) -ret); 295 if (ret == MBEDTLS_ERR_SSL_UNEXPECTED_MESSAGE) { 296 printf(" An unexpected message was received from our peer. If this happened at\n"); 297 printf(" the beginning of the handshake, this is likely a duplicated packet or\n"); 298 printf(" a close_notify alert from the previous connection, which is harmless.\n"); 299 ret = 0; 300 } 301 printf("\n"); 302 goto reset; 303 } 304 305 printf(" ok\n"); 306 307 /* 308 * 7. Read the echo Request 309 */ 310 printf(" < Read from client:"); 311 fflush(stdout); 312 313 len = sizeof(buf) - 1; 314 memset(buf, 0, sizeof(buf)); 315 316 do { 317 ret = mbedtls_ssl_read(&ssl, buf, len); 318 } while (ret == MBEDTLS_ERR_SSL_WANT_READ || 319 ret == MBEDTLS_ERR_SSL_WANT_WRITE); 320 321 if (ret <= 0) { 322 switch (ret) { 323 case MBEDTLS_ERR_SSL_TIMEOUT: 324 printf(" timeout\n\n"); 325 goto reset; 326 327 case MBEDTLS_ERR_SSL_PEER_CLOSE_NOTIFY: 328 printf(" connection was closed gracefully\n"); 329 goto close_notify; 330 331 default: 332 printf(" mbedtls_ssl_read returned -0x%x\n\n", (unsigned int) -ret); 333 goto reset; 334 } 335 } 336 337 len = ret; 338 printf(" %d bytes read\n\n%s\n\n", len, buf); 339 340 /* 341 * 8. Write the 200 Response 342 */ 343 printf(" > Write to client:"); 344 fflush(stdout); 345 346 do { 347 ret = mbedtls_ssl_write(&ssl, buf, len); 348 } while (ret == MBEDTLS_ERR_SSL_WANT_READ || 349 ret == MBEDTLS_ERR_SSL_WANT_WRITE); 350 351 if (ret < 0) { 352 printf(" failed\n ! mbedtls_ssl_write returned %d\n\n", ret); 353 goto exit; 354 } 355 356 len = ret; 357 printf(" %d bytes written\n\n%s\n\n", len, buf); 358 359 /* 360 * 9. Done, cleanly close the connection 361 */ 362 close_notify: 363 printf(" . Closing the connection..."); 364 365 /* No error checking, the connection might be closed already */ 366 do { 367 ret = mbedtls_ssl_close_notify(&ssl); 368 } while (ret == MBEDTLS_ERR_SSL_WANT_WRITE); 369 ret = 0; 370 371 printf(" done\n"); 372 373 goto reset; 374 375 /* 376 * Final clean-ups and exit 377 */ 378 exit: 379 380 #ifdef MBEDTLS_ERROR_C 381 if (ret != 0) { 382 char error_buf[100]; 383 mbedtls_strerror(ret, error_buf, 100); 384 printf("Last error was: %d - %s\n\n", ret, error_buf); 385 } 386 #endif 387 388 mbedtls_net_free(&client_fd); 389 mbedtls_net_free(&listen_fd); 390 391 mbedtls_x509_crt_free(&srvcert); 392 mbedtls_pk_free(&pkey); 393 mbedtls_ssl_free(&ssl); 394 mbedtls_ssl_config_free(&conf); 395 mbedtls_ssl_cookie_free(&cookie_ctx); 396 #if defined(MBEDTLS_SSL_CACHE_C) 397 mbedtls_ssl_cache_free(&cache); 398 #endif 399 mbedtls_ctr_drbg_free(&ctr_drbg); 400 mbedtls_entropy_free(&entropy); 401 #if defined(MBEDTLS_USE_PSA_CRYPTO) 402 mbedtls_psa_crypto_free(); 403 #endif /* MBEDTLS_USE_PSA_CRYPTO */ 404 405 /* Shell can not handle large exit numbers -> 1 for errors */ 406 if (ret < 0) { 407 ret = 1; 408 } 409 410 mbedtls_exit(ret); 411 } 412 413 #endif /* configuration allows running this program */