/* Minimal TLS server. * * Copyright (C) 2006-2015, ARM Limited, All Rights Reserved * * SPDX-License-Identifier: Apache-2.0 * * This file is part of mbed TLS (https://tls.mbed.org) */ #include #include #include #include #if !defined(CONFIG_MBEDTLS_CFG_FILE) #include "mbedtls/config.h" #else #include CONFIG_MBEDTLS_CFG_FILE #endif #if defined(MBEDTLS_PLATFORM_C) #include "mbedtls/platform.h" #else #include #define mbedtls_time_t time_t #define MBEDTLS_EXIT_SUCCESS EXIT_SUCCESS #define MBEDTLS_EXIT_FAILURE EXIT_FAILURE #endif #include #include #include #include "config.h" #include "ssl_utils.h" #include "test_certs.h" #include "mbedtls/ssl_cookie.h" #include "mbedtls/entropy.h" #include "mbedtls/ctr_drbg.h" #include "mbedtls/net_sockets.h" #include "mbedtls/x509.h" #include "mbedtls/ssl.h" #include "mbedtls/error.h" #include "mbedtls/debug.h" #if defined(MBEDTLS_DEBUG_C) #include "mbedtls/debug.h" #define DEBUG_THRESHOLD 0 #endif #if defined(MBEDTLS_MEMORY_BUFFER_ALLOC_C) #include "mbedtls/memory_buffer_alloc.h" static unsigned char heap[12000]; #endif /* * Hardcoded values for server host and port */ static const char *pers = "tls_server"; #if defined(CONFIG_NET_IPV6) static struct in6_addr server_addr; #else static struct in_addr server_addr; #endif struct parsed_url { const char *url; uint16_t url_len; }; #define HTTP_RESPONSE \ "HTTP/1.0 200 OK\r\nContent-Type: text/html\r\n\r\n" \ "

Zephyr TLS Test Server

\r\n" \ "

Successful connection

\r\n" #define HTTP_NOT_FOUND \ "HTTP/1.0 404 NOT FOUND\r\nContent-Type: text/html\r\n\r\n" \ "

Zephyr TLS page not found

\r\n" \ "

Successful connection

\r\n" static void my_debug(void *ctx, int level, const char *file, int line, const char *str) { const char *p, *basename; ARG_UNUSED(ctx); /* Extract basename from file */ for (p = basename = file; *p != '\0'; p++) { if (*p == '/' || *p == '\\') { basename = p + 1; } } mbedtls_printf("%s:%04d: |%d| %s", basename, line, level, str); } static int entropy_source(void *data, unsigned char *output, size_t len, size_t *olen) { uint32_t seed; ARG_UNUSED(data); seed = sys_rand32_get(); if (len > sizeof(seed)) { len = sizeof(seed); } memcpy(output, &seed, len); *olen = len; return 0; } static int on_url(struct http_parser *parser, const char *at, size_t length) { struct parsed_url *req = (struct parsed_url *)parser->data; req->url = at; req->url_len = length; return 0; } static unsigned char payload[256]; void https_server(void) { struct ssl_context ctx; struct parsed_url request; int ret, len = 0; mbedtls_entropy_context entropy; mbedtls_ctr_drbg_context ctr_drbg; mbedtls_ssl_context ssl; mbedtls_ssl_config conf; mbedtls_x509_crt srvcert; mbedtls_pk_context pkey; mbedtls_platform_set_printf(printk); #if defined(MBEDTLS_MEMORY_BUFFER_ALLOC_C) mbedtls_memory_buffer_alloc_init(heap, sizeof(heap)); #endif #if defined(MBEDTLS_DEBUG_C) mbedtls_debug_set_threshold(DEBUG_THRESHOLD); mbedtls_ssl_conf_dbg(&conf, my_debug, NULL); #endif mbedtls_x509_crt_init(&srvcert); mbedtls_pk_init(&pkey); mbedtls_ssl_init(&ssl); mbedtls_ssl_config_init(&conf); mbedtls_entropy_init(&entropy); mbedtls_ctr_drbg_init(&ctr_drbg); /* * 1. Load the certificates and private RSA key */ ret = mbedtls_x509_crt_parse(&srvcert, rsa_example_cert_der, rsa_example_cert_der_len); if (ret != 0) { mbedtls_printf(" failed\n !" " mbedtls_x509_crt_parse returned %d\n\n", ret); goto exit; } ret = mbedtls_pk_parse_key(&pkey, rsa_example_keypair_der, rsa_example_keypair_der_len, NULL, 0); if (ret != 0) { mbedtls_printf(" failed\n !" " mbedtls_pk_parse_key returned %d\n\n", ret); goto exit; } /* * 3. Seed the RNG */ mbedtls_entropy_add_source(&entropy, entropy_source, NULL, MBEDTLS_ENTROPY_MAX_GATHER, MBEDTLS_ENTROPY_SOURCE_STRONG); ret = mbedtls_ctr_drbg_seed(&ctr_drbg, mbedtls_entropy_func, &entropy, (const unsigned char *)pers, strlen(pers)); if (ret != 0) { mbedtls_printf(" failed\n !" " mbedtls_ctr_drbg_seed returned %d\n", ret); goto exit; } /* * 4. Setup stuff */ ret = mbedtls_ssl_config_defaults(&conf, MBEDTLS_SSL_IS_SERVER, MBEDTLS_SSL_TRANSPORT_STREAM, MBEDTLS_SSL_PRESET_DEFAULT); if (ret != 0) { mbedtls_printf(" failed\n !" " mbedtls_ssl_config_defaults returned %d\n\n", ret); goto exit; } mbedtls_ssl_conf_rng(&conf, mbedtls_ctr_drbg_random, &ctr_drbg); mbedtls_ssl_conf_dbg(&conf, my_debug, NULL); mbedtls_ssl_conf_ca_chain(&conf, srvcert.next, NULL); ret = mbedtls_ssl_conf_own_cert(&conf, &srvcert, &pkey); if (ret != 0) { mbedtls_printf(" failed\n !" " mbedtls_ssl_conf_own_cert returned %d\n\n", ret); goto exit; } ret = mbedtls_ssl_setup(&ssl, &conf); if (ret != 0) { mbedtls_printf(" failed\n !" " mbedtls_ssl_setup returned %d\n\n", ret); goto exit; } /* * 3. Wait until a client connects */ ret = ssl_init(&ctx, &server_addr); if (ret != 0) { mbedtls_printf(" failed\n ! ssl_init returned %d\n\n", ret); goto exit; } /* * 4. Prepare http parser */ http_parser_init(&ctx.parser, HTTP_REQUEST); http_parser_settings_init(&ctx.parser_settings); ctx.parser.data = &request; ctx.parser_settings.on_url = on_url; mbedtls_printf("Zephyr HTTPS Server\n"); mbedtls_printf("Address: %s, port: %d\n", ZEPHYR_ADDR, SERVER_PORT); reset: mbedtls_ssl_session_reset(&ssl); mbedtls_ssl_set_bio(&ssl, &ctx, ssl_tx, ssl_rx, NULL); /* * 5. Handshake */ do { ret = mbedtls_ssl_handshake(&ssl); if (ret != MBEDTLS_ERR_SSL_WANT_READ && ret != MBEDTLS_ERR_SSL_WANT_WRITE) { if (ret < 0) { mbedtls_printf(" failed\n !" " mbedtls_ssl_handshake returned %d\n\n", ret); goto reset; } } } while (ret != 0); /* * 6. Read the HTTPS Request */ mbedtls_printf("Read HTTPS request\n"); do { len = sizeof(payload) - 1; memset(payload, 0, sizeof(payload)); ret = mbedtls_ssl_read(&ssl, payload, len); if (ret == MBEDTLS_ERR_SSL_WANT_READ || ret == MBEDTLS_ERR_SSL_WANT_WRITE) { continue; } if (ret <= 0) { switch (ret) { case MBEDTLS_ERR_SSL_PEER_CLOSE_NOTIFY: mbedtls_printf(" connection was" " closed gracefully\n"); goto close; case MBEDTLS_ERR_NET_CONN_RESET: mbedtls_printf(" connection was" " reset by peer\n"); break; default: mbedtls_printf (" mbedtls_ssl_read returned -0x%x\n", -ret); break; } break; } len = ret; ret = http_parser_execute(&ctx.parser, &ctx.parser_settings, payload, len); if (ret < 0) { } } while (ret < 0); /* * 7. Write the Response */ mbedtls_printf("Write HTTPS response\n"); if (!strncmp("/index.html", request.url, request.url_len)) { len = snprintf((char *)payload, sizeof(payload), HTTP_RESPONSE); } else { len = snprintf((char *)payload, sizeof(payload), HTTP_NOT_FOUND); } do { ret = mbedtls_ssl_write(&ssl, payload, len); if (ret == MBEDTLS_ERR_NET_CONN_RESET) { mbedtls_printf(" failed\n !" " peer closed the connection\n"); goto reset; } if (ret != MBEDTLS_ERR_SSL_WANT_READ && ret != MBEDTLS_ERR_SSL_WANT_WRITE) { if (ret < 0) { mbedtls_printf(" failed\n !" " mbedtls_ssl_write" " returned %d\n", ret); goto exit; } } } while (ret <= 0); close: mbedtls_ssl_close_notify(&ssl); ret = 0; goto reset; exit: #ifdef MBEDTLS_ERROR_C if (ret != 0) { mbedtls_strerror(ret, payload, 100); mbedtls_printf("Last error was: %d - %s\n", ret, payload); } #endif mbedtls_ssl_free(&ssl); mbedtls_ssl_config_free(&conf); mbedtls_ctr_drbg_free(&ctr_drbg); mbedtls_entropy_free(&entropy); } #define STACK_SIZE 8192 uint8_t stack[STACK_SIZE]; static inline int init_app(void) { #if defined(CONFIG_NET_IPV6) if (net_addr_pton(AF_INET6, ZEPHYR_ADDR, &server_addr) < 0) { mbedtls_printf("Invalid IPv6 address %s", ZEPHYR_ADDR); } if (!net_if_ipv6_addr_add(net_if_get_default(), &server_addr, NET_ADDR_MANUAL, 0)) { return -EIO; } #else if (net_addr_pton(AF_INET, ZEPHYR_ADDR, &server_addr) < 0) { mbedtls_printf("Invalid IPv4 address %s", ZEPHYR_ADDR); } if (!net_if_ipv4_addr_add(net_if_get_default(), &server_addr, NET_ADDR_MANUAL, 0)) { return -EIO; } #endif return 0; } void https_server_start(void) { if (init_app() != 0) { printk("Cannot initialize network\n"); return; } k_thread_spawn(stack, STACK_SIZE, (k_thread_entry_t) https_server, NULL, NULL, NULL, K_PRIO_COOP(7), 0, 0); }