ssl_server.c (10384B)
1 /* 2 * SSL 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 #if !defined(MBEDTLS_ENTROPY_C) || !defined(MBEDTLS_CTR_DRBG_C) || \ 13 !defined(MBEDTLS_NET_C) || !defined(MBEDTLS_SSL_SRV_C) || \ 14 !defined(MBEDTLS_PEM_PARSE_C) || !defined(MBEDTLS_X509_CRT_PARSE_C) 15 int main(void) 16 { 17 mbedtls_printf("MBEDTLS_ENTROPY_C and/or MBEDTLS_CTR_DRBG_C and/or " 18 "MBEDTLS_NET_C and/or MBEDTLS_SSL_SRV_C and/or " 19 "MBEDTLS_PEM_PARSE_C and/or MBEDTLS_X509_CRT_PARSE_C " 20 "not defined.\n"); 21 mbedtls_exit(0); 22 } 23 #else 24 25 #include <stdlib.h> 26 #include <string.h> 27 28 #if defined(_WIN32) 29 #include <windows.h> 30 #endif 31 32 #include "mbedtls/entropy.h" 33 #include "mbedtls/ctr_drbg.h" 34 #include "mbedtls/x509.h" 35 #include "mbedtls/ssl.h" 36 #include "mbedtls/net_sockets.h" 37 #include "mbedtls/error.h" 38 #include "mbedtls/debug.h" 39 #include "test/certs.h" 40 41 #if defined(MBEDTLS_SSL_CACHE_C) 42 #include "mbedtls/ssl_cache.h" 43 #endif 44 45 #define HTTP_RESPONSE \ 46 "HTTP/1.0 200 OK\r\nContent-Type: text/html\r\n\r\n" \ 47 "<h2>Mbed TLS Test Server</h2>\r\n" \ 48 "<p>Successful connection using: %s</p>\r\n" 49 50 #define DEBUG_LEVEL 0 51 52 53 static void my_debug(void *ctx, int level, 54 const char *file, int line, 55 const char *str) 56 { 57 ((void) level); 58 59 mbedtls_fprintf((FILE *) ctx, "%s:%04d: %s", file, line, str); 60 fflush((FILE *) ctx); 61 } 62 63 int main(void) 64 { 65 int ret, len; 66 mbedtls_net_context listen_fd, client_fd; 67 unsigned char buf[1024]; 68 const char *pers = "ssl_server"; 69 70 mbedtls_entropy_context entropy; 71 mbedtls_ctr_drbg_context ctr_drbg; 72 mbedtls_ssl_context ssl; 73 mbedtls_ssl_config conf; 74 mbedtls_x509_crt srvcert; 75 mbedtls_pk_context pkey; 76 #if defined(MBEDTLS_SSL_CACHE_C) 77 mbedtls_ssl_cache_context cache; 78 #endif 79 80 mbedtls_net_init(&listen_fd); 81 mbedtls_net_init(&client_fd); 82 mbedtls_ssl_init(&ssl); 83 mbedtls_ssl_config_init(&conf); 84 #if defined(MBEDTLS_SSL_CACHE_C) 85 mbedtls_ssl_cache_init(&cache); 86 #endif 87 mbedtls_x509_crt_init(&srvcert); 88 mbedtls_pk_init(&pkey); 89 mbedtls_entropy_init(&entropy); 90 mbedtls_ctr_drbg_init(&ctr_drbg); 91 92 #if defined(MBEDTLS_USE_PSA_CRYPTO) 93 psa_status_t status = psa_crypto_init(); 94 if (status != PSA_SUCCESS) { 95 mbedtls_fprintf(stderr, "Failed to initialize PSA Crypto implementation: %d\n", 96 (int) status); 97 ret = MBEDTLS_ERR_SSL_HW_ACCEL_FAILED; 98 goto exit; 99 } 100 #endif /* MBEDTLS_USE_PSA_CRYPTO */ 101 102 #if defined(MBEDTLS_DEBUG_C) 103 mbedtls_debug_set_threshold(DEBUG_LEVEL); 104 #endif 105 106 /* 107 * 1. Seed the RNG 108 */ 109 mbedtls_printf(" . Seeding the random number generator..."); 110 fflush(stdout); 111 112 if ((ret = mbedtls_ctr_drbg_seed(&ctr_drbg, mbedtls_entropy_func, &entropy, 113 (const unsigned char *) pers, 114 strlen(pers))) != 0) { 115 mbedtls_printf(" failed\n ! mbedtls_ctr_drbg_seed returned %d\n", ret); 116 goto exit; 117 } 118 119 mbedtls_printf(" ok\n"); 120 121 /* 122 * 2. Load the certificates and private RSA key 123 */ 124 mbedtls_printf("\n . Loading the server cert. and key..."); 125 fflush(stdout); 126 127 /* 128 * This demonstration program uses embedded test certificates. 129 * Instead, you may want to use mbedtls_x509_crt_parse_file() to read the 130 * server and CA certificates, as well as mbedtls_pk_parse_keyfile(). 131 */ 132 ret = mbedtls_x509_crt_parse(&srvcert, (const unsigned char *) mbedtls_test_srv_crt, 133 mbedtls_test_srv_crt_len); 134 if (ret != 0) { 135 mbedtls_printf(" failed\n ! mbedtls_x509_crt_parse returned %d\n\n", ret); 136 goto exit; 137 } 138 139 ret = mbedtls_x509_crt_parse(&srvcert, (const unsigned char *) mbedtls_test_cas_pem, 140 mbedtls_test_cas_pem_len); 141 if (ret != 0) { 142 mbedtls_printf(" failed\n ! mbedtls_x509_crt_parse returned %d\n\n", ret); 143 goto exit; 144 } 145 146 ret = mbedtls_pk_parse_key(&pkey, (const unsigned char *) mbedtls_test_srv_key, 147 mbedtls_test_srv_key_len, NULL, 0, 148 mbedtls_ctr_drbg_random, &ctr_drbg); 149 if (ret != 0) { 150 mbedtls_printf(" failed\n ! mbedtls_pk_parse_key returned %d\n\n", ret); 151 goto exit; 152 } 153 154 mbedtls_printf(" ok\n"); 155 156 /* 157 * 3. Setup the listening TCP socket 158 */ 159 mbedtls_printf(" . Bind on https://localhost:4433/ ..."); 160 fflush(stdout); 161 162 if ((ret = mbedtls_net_bind(&listen_fd, NULL, "4433", MBEDTLS_NET_PROTO_TCP)) != 0) { 163 mbedtls_printf(" failed\n ! mbedtls_net_bind returned %d\n\n", ret); 164 goto exit; 165 } 166 167 mbedtls_printf(" ok\n"); 168 169 /* 170 * 4. Setup stuff 171 */ 172 mbedtls_printf(" . Setting up the SSL data...."); 173 fflush(stdout); 174 175 if ((ret = mbedtls_ssl_config_defaults(&conf, 176 MBEDTLS_SSL_IS_SERVER, 177 MBEDTLS_SSL_TRANSPORT_STREAM, 178 MBEDTLS_SSL_PRESET_DEFAULT)) != 0) { 179 mbedtls_printf(" failed\n ! mbedtls_ssl_config_defaults returned %d\n\n", ret); 180 goto exit; 181 } 182 183 mbedtls_ssl_conf_rng(&conf, mbedtls_ctr_drbg_random, &ctr_drbg); 184 mbedtls_ssl_conf_dbg(&conf, my_debug, stdout); 185 186 #if defined(MBEDTLS_SSL_CACHE_C) 187 mbedtls_ssl_conf_session_cache(&conf, &cache, 188 mbedtls_ssl_cache_get, 189 mbedtls_ssl_cache_set); 190 #endif 191 192 mbedtls_ssl_conf_ca_chain(&conf, srvcert.next, NULL); 193 if ((ret = mbedtls_ssl_conf_own_cert(&conf, &srvcert, &pkey)) != 0) { 194 mbedtls_printf(" failed\n ! mbedtls_ssl_conf_own_cert returned %d\n\n", ret); 195 goto exit; 196 } 197 198 if ((ret = mbedtls_ssl_setup(&ssl, &conf)) != 0) { 199 mbedtls_printf(" failed\n ! mbedtls_ssl_setup returned %d\n\n", ret); 200 goto exit; 201 } 202 203 mbedtls_printf(" ok\n"); 204 205 reset: 206 #ifdef MBEDTLS_ERROR_C 207 if (ret != 0) { 208 char error_buf[100]; 209 mbedtls_strerror(ret, error_buf, 100); 210 mbedtls_printf("Last error was: %d - %s\n\n", ret, error_buf); 211 } 212 #endif 213 214 mbedtls_net_free(&client_fd); 215 216 mbedtls_ssl_session_reset(&ssl); 217 218 /* 219 * 3. Wait until a client connects 220 */ 221 mbedtls_printf(" . Waiting for a remote connection ..."); 222 fflush(stdout); 223 224 if ((ret = mbedtls_net_accept(&listen_fd, &client_fd, 225 NULL, 0, NULL)) != 0) { 226 mbedtls_printf(" failed\n ! mbedtls_net_accept returned %d\n\n", ret); 227 goto exit; 228 } 229 230 mbedtls_ssl_set_bio(&ssl, &client_fd, mbedtls_net_send, mbedtls_net_recv, NULL); 231 232 mbedtls_printf(" ok\n"); 233 234 /* 235 * 5. Handshake 236 */ 237 mbedtls_printf(" . Performing the SSL/TLS handshake..."); 238 fflush(stdout); 239 240 while ((ret = mbedtls_ssl_handshake(&ssl)) != 0) { 241 if (ret != MBEDTLS_ERR_SSL_WANT_READ && ret != MBEDTLS_ERR_SSL_WANT_WRITE) { 242 mbedtls_printf(" failed\n ! mbedtls_ssl_handshake returned %d\n\n", ret); 243 goto reset; 244 } 245 } 246 247 mbedtls_printf(" ok\n"); 248 249 /* 250 * 6. Read the HTTP Request 251 */ 252 mbedtls_printf(" < Read from client:"); 253 fflush(stdout); 254 255 do { 256 len = sizeof(buf) - 1; 257 memset(buf, 0, sizeof(buf)); 258 ret = mbedtls_ssl_read(&ssl, buf, len); 259 260 if (ret == MBEDTLS_ERR_SSL_WANT_READ || ret == MBEDTLS_ERR_SSL_WANT_WRITE) { 261 continue; 262 } 263 264 if (ret <= 0) { 265 switch (ret) { 266 case MBEDTLS_ERR_SSL_PEER_CLOSE_NOTIFY: 267 mbedtls_printf(" connection was closed gracefully\n"); 268 break; 269 270 case MBEDTLS_ERR_NET_CONN_RESET: 271 mbedtls_printf(" connection was reset by peer\n"); 272 break; 273 274 default: 275 mbedtls_printf(" mbedtls_ssl_read returned -0x%x\n", (unsigned int) -ret); 276 break; 277 } 278 279 break; 280 } 281 282 len = ret; 283 mbedtls_printf(" %d bytes read\n\n%s", len, (char *) buf); 284 285 if (ret > 0) { 286 break; 287 } 288 } while (1); 289 290 /* 291 * 7. Write the 200 Response 292 */ 293 mbedtls_printf(" > Write to client:"); 294 fflush(stdout); 295 296 len = sprintf((char *) buf, HTTP_RESPONSE, 297 mbedtls_ssl_get_ciphersuite(&ssl)); 298 299 while ((ret = mbedtls_ssl_write(&ssl, buf, len)) <= 0) { 300 if (ret == MBEDTLS_ERR_NET_CONN_RESET) { 301 mbedtls_printf(" failed\n ! peer closed the connection\n\n"); 302 goto reset; 303 } 304 305 if (ret != MBEDTLS_ERR_SSL_WANT_READ && ret != MBEDTLS_ERR_SSL_WANT_WRITE) { 306 mbedtls_printf(" failed\n ! mbedtls_ssl_write returned %d\n\n", ret); 307 goto exit; 308 } 309 } 310 311 len = ret; 312 mbedtls_printf(" %d bytes written\n\n%s\n", len, (char *) buf); 313 314 mbedtls_printf(" . Closing the connection..."); 315 fflush(stdout); 316 317 while ((ret = mbedtls_ssl_close_notify(&ssl)) < 0) { 318 if (ret != MBEDTLS_ERR_SSL_WANT_READ && 319 ret != MBEDTLS_ERR_SSL_WANT_WRITE && 320 ret != MBEDTLS_ERR_NET_CONN_RESET) { 321 mbedtls_printf(" failed\n ! mbedtls_ssl_close_notify returned %d\n\n", ret); 322 goto reset; 323 } 324 } 325 326 mbedtls_printf(" ok\n"); 327 fflush(stdout); 328 329 ret = 0; 330 goto reset; 331 332 exit: 333 334 #ifdef MBEDTLS_ERROR_C 335 if (ret != 0) { 336 char error_buf[100]; 337 mbedtls_strerror(ret, error_buf, 100); 338 mbedtls_printf("Last error was: %d - %s\n\n", ret, error_buf); 339 } 340 #endif 341 342 mbedtls_net_free(&client_fd); 343 mbedtls_net_free(&listen_fd); 344 mbedtls_x509_crt_free(&srvcert); 345 mbedtls_pk_free(&pkey); 346 mbedtls_ssl_free(&ssl); 347 mbedtls_ssl_config_free(&conf); 348 #if defined(MBEDTLS_SSL_CACHE_C) 349 mbedtls_ssl_cache_free(&cache); 350 #endif 351 mbedtls_ctr_drbg_free(&ctr_drbg); 352 mbedtls_entropy_free(&entropy); 353 #if defined(MBEDTLS_USE_PSA_CRYPTO) 354 mbedtls_psa_crypto_free(); 355 #endif /* MBEDTLS_USE_PSA_CRYPTO */ 356 357 mbedtls_exit(ret); 358 } 359 360 #endif /* configuration allows running this program */