summaryrefslogtreecommitdiff
path: root/samples
diff options
context:
space:
mode:
authorSergio Rodriguez <sergio.sf.rodriguez@intel.com>2017-02-10 11:29:58 -0800
committerJukka Rissanen <jukka.rissanen@linux.intel.com>2017-02-14 08:30:35 +0200
commitde60e4c8cd4bf7ee27e720b874502626c10ea23e (patch)
treebea4fdbdb94cc82538e1d918ff8d551cfed02f51 /samples
parentf054d3e897db4aa92a0f4ee78afeba715961d0b5 (diff)
samples/net/http: Add HTTP over TLS sample application
Add the HTTPS (HTTP over TLS) server sample application on top of the current HTTP Parser Library and mbedTLS. This code uses TLS to stablish a secure connection and HTTP parser to identify the request and the proper response. Jira: ZEP-799 Change-Id: Ifbbcd0347bec47d12158440e50a82dc2966334d3 Signed-off-by: Sergio Rodriguez <sergio.sf.rodriguez@intel.com> Signed-off-by: Flavio Santes <flavio.santes@intel.com>
Diffstat (limited to 'samples')
-rw-r--r--samples/net/http_server/README.rst57
-rw-r--r--samples/net/http_server/prj_qemu_x86.conf4
-rw-r--r--samples/net/http_server/src/Makefile5
-rw-r--r--samples/net/http_server/src/config.h4
-rw-r--r--samples/net/http_server/src/https_server.c406
-rw-r--r--samples/net/http_server/src/main.c7
-rw-r--r--samples/net/http_server/src/ssl_utils.c295
-rw-r--r--samples/net/http_server/src/ssl_utils.h37
-rw-r--r--samples/net/http_server/src/test_certs.h92
9 files changed, 906 insertions, 1 deletions
diff --git a/samples/net/http_server/README.rst b/samples/net/http_server/README.rst
index 27b77829c..792bbdaa1 100644
--- a/samples/net/http_server/README.rst
+++ b/samples/net/http_server/README.rst
@@ -109,7 +109,6 @@ Refer to the board documentation in Zephyr, :ref:`frdm_k64f`,
for more information about this board and how to access the FRDM
serial console under other operating systems.
-
Sample Output
=============
@@ -223,6 +222,60 @@ and this is the HTML message that wget will save:
<body><h1><center>404 Not Found</center></h1></body>
</html>
+HTTPS Server
+============
+
+The sample code also includes a HTTPS (HTTP over TLS) server example
+running side by side with the HTTP server, this server runs on qemu.
+In order to compile and run the code execute:
+
+.. code-block:: console
+
+ make BOARD=qemu_x86 run
+
+The sample code supports only one hard-coded valid URL (index.html) and
+will return 404 code for other requests.
+
+Sample Output
+=============
+
+The app will show the following on the screen:
+
+.. code-block:: console
+
+ Zephyr HTTP Server
+ Address: 192.0.2.1, port: 80
+ Zephyr HTTPS Server
+ Address: 192.0.2.1, port: 443
+ failed
+ ! mbedtls_ssl_handshake returned -29312
+
+Now execute the following command on a different terminal window
+
+.. code-block:: console
+
+ wget https://192.0.2.1 --no-check-certificate
+
+This will be shown on the screen
+
+.. code-block:: console
+
+ Connecting to 192.0.2.1:443... connected.
+ WARNING: cannot verify 192.0.2.1's certificate
+ Unable to locally verify the issuer's authority.
+ HTTP request sent, awaiting response... 200 OK
+ Length: unspecified [text/html]
+ Saving to: ‘index.html’
+
+ index.html [ <=> ]
+
+The inspection of the file index.html will show
+
+.. code-block:: console
+
+ <h2>Zephyr TLS Test Server</h2>
+ <p>Successful connection</p>
+
Known Issues and Limitations
============================
@@ -230,3 +283,5 @@ Known Issues and Limitations
chunk transfer mode.
- Clients must close the connection to allow the HTTP server to release
the network context and accept another connection.
+- The use of mbedTLS and IPv6 takes more than the available ram for the
+ emulation platform, so only IPv4 works for now in QEMU.
diff --git a/samples/net/http_server/prj_qemu_x86.conf b/samples/net/http_server/prj_qemu_x86.conf
index 8e869d43e..88ba68d55 100644
--- a/samples/net/http_server/prj_qemu_x86.conf
+++ b/samples/net/http_server/prj_qemu_x86.conf
@@ -28,3 +28,7 @@ CONFIG_NET_SAMPLES_MY_IPV6_ADDR="2001:db8::1"
CONFIG_NET_SAMPLES_MY_IPV4_ADDR="192.0.2.1"
CONFIG_NET_MAX_CONTEXTS=16
+
+CONFIG_MBEDTLS=y
+CONFIG_MBEDTLS_BUILTIN=y
+CONFIG_MBEDTLS_CFG_FILE="config-mini-tls1_2.h"
diff --git a/samples/net/http_server/src/Makefile b/samples/net/http_server/src/Makefile
index 11d9be117..5219783b9 100644
--- a/samples/net/http_server/src/Makefile
+++ b/samples/net/http_server/src/Makefile
@@ -8,3 +8,8 @@ obj-y += main.o
obj-y += http_utils.o
obj-y += http_server.o
obj-y += http_write_utils.o
+ifdef CONFIG_MBEDTLS
+obj-y += https_server.o ssl_utils.o
+endif
+
+
diff --git a/samples/net/http_server/src/config.h b/samples/net/http_server/src/config.h
index 672b66363..054a4c4e3 100644
--- a/samples/net/http_server/src/config.h
+++ b/samples/net/http_server/src/config.h
@@ -25,4 +25,8 @@
#define APP_SLEEP_MSECS 500
+#ifdef CONFIG_MBEDTLS
+#define SERVER_PORT 443
+#endif
+
#endif
diff --git a/samples/net/http_server/src/https_server.c b/samples/net/http_server/src/https_server.c
new file mode 100644
index 000000000..6173c7ec2
--- /dev/null
+++ b/samples/net/http_server/src/https_server.c
@@ -0,0 +1,406 @@
+/* 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 <zephyr.h>
+#include <stdio.h>
+
+#include <errno.h>
+#include <misc/printk.h>
+
+#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 <stdlib.h>
+#define mbedtls_time_t time_t
+#define MBEDTLS_EXIT_SUCCESS EXIT_SUCCESS
+#define MBEDTLS_EXIT_FAILURE EXIT_FAILURE
+#endif
+
+#include <string.h>
+#include <net/net_context.h>
+#include <net/net_if.h>
+#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" \
+ "<h2>Zephyr TLS Test Server</h2>\r\n" \
+ "<p>Successful connection</p>\r\n"
+
+#define HTTP_NOT_FOUND \
+ "HTTP/1.0 404 NOT FOUND\r\nContent-Type: text/html\r\n\r\n" \
+ "<h2>Zephyr TLS page not found </h2>\r\n" \
+ "<p>Successful connection</p>\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);
+
+}
diff --git a/samples/net/http_server/src/main.c b/samples/net/http_server/src/main.c
index e5ebd16e8..d71f897ad 100644
--- a/samples/net/http_server/src/main.c
+++ b/samples/net/http_server/src/main.c
@@ -20,6 +20,10 @@ static
int network_setup(struct net_context **net_ctx, net_tcp_accept_cb_t accept_cb,
const char *addr, uint16_t port);
+#if defined(CONFIG_MBEDTLS)
+#include "ssl_utils.h"
+#endif
+
void main(void)
{
struct net_context *net_ctx = NULL;
@@ -101,6 +105,9 @@ int network_setup(struct net_context **net_ctx, net_tcp_accept_cb_t accept_cb,
print_server_banner(&local_sock);
+#if defined(CONFIG_MBEDTLS)
+ https_server_start();
+#endif
return 0;
lb_error:
diff --git a/samples/net/http_server/src/ssl_utils.c b/samples/net/http_server/src/ssl_utils.c
new file mode 100644
index 000000000..ac75aadd0
--- /dev/null
+++ b/samples/net/http_server/src/ssl_utils.c
@@ -0,0 +1,295 @@
+/*
+ * Copyright (c) 2017 Intel Corporation
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ */
+
+#include <zephyr.h>
+#include <net/net_core.h>
+#include <net/net_context.h>
+#include <net/nbuf.h>
+#include <net/net_if.h>
+#include <string.h>
+#include <errno.h>
+#include <misc/printk.h>
+
+#if !defined(CONFIG_MBEDTLS_CFG_FILE)
+#include "mbedtls/config.h"
+#else
+#include CONFIG_MBEDTLS_CFG_FILE
+#endif
+
+#include "mbedtls/ssl.h"
+
+#include "config.h"
+#include "ssl_utils.h"
+
+#define RX_FIFO_DEPTH 4
+
+K_MEM_POOL_DEFINE(rx_pkts, 4, 64, RX_FIFO_DEPTH, 4);
+
+static void ssl_received(struct net_context *context,
+ struct net_buf *buf, int status, void *user_data)
+{
+ struct ssl_context *ctx = user_data;
+ struct rx_fifo_block *rx_data = NULL;
+ struct k_mem_block block;
+
+ ARG_UNUSED(context);
+ ARG_UNUSED(status);
+
+ if (!net_nbuf_appdatalen(buf)) {
+ net_nbuf_unref(buf);
+ return;
+ }
+
+ k_mem_pool_alloc(&rx_pkts, &block,
+ sizeof(struct rx_fifo_block), K_FOREVER);
+ rx_data = block.data;
+ rx_data->buf = buf;
+
+ /* For freeing memory later */
+ memcpy(&rx_data->block, &block, sizeof(struct k_mem_block));
+ k_fifo_put(&ctx->rx_fifo, (void *)rx_data);
+}
+
+static inline void ssl_sent(struct net_context *context,
+ int status, void *token, void *user_data)
+{
+ struct ssl_context *ctx = user_data;
+
+ k_sem_give(&ctx->tx_sem);
+}
+
+int ssl_tx(void *context, const unsigned char *buf, size_t size)
+{
+ struct ssl_context *ctx = context;
+ struct net_context *net_ctx;
+ struct net_buf *send_buf;
+
+ int rc, len;
+
+ net_ctx = ctx->net_ctx;
+
+ send_buf = net_nbuf_get_tx(net_ctx, K_NO_WAIT);
+ if (!send_buf) {
+ return MBEDTLS_ERR_SSL_ALLOC_FAILED;
+ }
+
+ rc = net_nbuf_append(send_buf, size, (uint8_t *) buf, K_FOREVER);
+ if (!rc) {
+ net_nbuf_unref(send_buf);
+ return MBEDTLS_ERR_SSL_INTERNAL_ERROR;
+ }
+
+ len = net_buf_frags_len(send_buf);
+
+ rc = net_context_send(send_buf, ssl_sent, K_NO_WAIT, NULL, ctx);
+
+ if (rc < 0) {
+ net_nbuf_unref(send_buf);
+ return MBEDTLS_ERR_SSL_INTERNAL_ERROR;
+ }
+
+ k_sem_take(&ctx->tx_sem, K_FOREVER);
+ return len;
+}
+
+int ssl_rx(void *context, unsigned char *buf, size_t size)
+{
+ struct ssl_context *ctx = context;
+ uint16_t read_bytes;
+ struct rx_fifo_block *rx_data;
+ uint8_t *ptr;
+ int pos;
+ int len;
+ int rc = 0;
+
+ if (ctx->frag == NULL) {
+ rx_data = k_fifo_get(&ctx->rx_fifo, K_FOREVER);
+ ctx->rx_nbuf = rx_data->buf;
+ k_mem_pool_free(&rx_data->block);
+
+ read_bytes = net_nbuf_appdatalen(ctx->rx_nbuf);
+
+ ctx->remaining = read_bytes;
+ ctx->frag = ctx->rx_nbuf->frags;
+ ptr = net_nbuf_appdata(ctx->rx_nbuf);
+
+ len = ptr - ctx->frag->data;
+ net_buf_pull(ctx->frag, len);
+ } else {
+ read_bytes = ctx->remaining;
+ ptr = ctx->frag->data;
+ }
+
+ len = ctx->frag->len;
+ pos = 0;
+ if (read_bytes > size) {
+ while (ctx->frag) {
+ read_bytes = len < (size - pos) ? len : (size - pos);
+ memcpy(buf + pos, ptr, read_bytes);
+ pos += read_bytes;
+ if (pos < size) {
+ ctx->frag = ctx->frag->frags;
+ ptr = ctx->frag->data;
+ len = ctx->frag->len;
+ } else {
+ if (read_bytes == len) {
+ ctx->frag = ctx->frag->frags;
+ } else {
+ net_buf_pull(ctx->frag, read_bytes);
+ }
+
+ ctx->remaining -= size;
+ return size;
+ }
+ }
+ } else {
+ while (ctx->frag) {
+ memcpy(buf + pos, ptr, len);
+ pos += len;
+ ctx->frag = ctx->frag->frags;
+ if (!ctx->frag) {
+ break;
+ }
+
+ ptr = ctx->frag->data;
+ len = ctx->frag->len;
+ }
+
+ net_nbuf_unref(ctx->rx_nbuf);
+ ctx->rx_nbuf = NULL;
+ ctx->frag = NULL;
+ ctx->remaining = 0;
+
+ if (read_bytes != pos) {
+ return -EIO;
+ }
+
+ rc = read_bytes;
+ }
+
+ return rc;
+}
+
+static void ssl_accepted(struct net_context *context,
+ struct sockaddr *addr,
+ socklen_t addrlen, int error, void *user_data)
+{
+ int ret;
+ struct ssl_context *ctx = user_data;
+
+ ctx->net_ctx = context;
+ ret = net_context_recv(context, ssl_received, 0, user_data);
+ if (ret < 0) {
+ printk("Cannot receive TCP packet (family %d)",
+ net_context_get_family(context));
+ }
+
+}
+
+#if defined(CONFIG_NET_IPV6)
+int ssl_init(struct ssl_context *ctx, void *addr)
+{
+ struct net_context *tcp_ctx = { 0 };
+ struct sockaddr_in6 my_addr = { 0 };
+ struct in6_addr *server_addr = addr;
+ int rc;
+
+ k_sem_init(&ctx->tx_sem, 0, UINT_MAX);
+ k_fifo_init(&ctx->rx_fifo);
+
+ my_mcast_addr.sin6_family = AF_INET6;
+
+ net_ipaddr_copy(&my_addr.sin6_addr, server_addr);
+ my_addr.sin6_family = AF_INET6;
+ my_addr.sin6_port = htons(SERVER_PORT);
+
+ rc = net_context_get(AF_INET6, SOCK_STREAM, IPPROTO_TCP, &tcp_ctx);
+ if (rc < 0) {
+ printk("Cannot get network context for IPv6 TCP (%d)", rc);
+ return -EIO;
+ }
+
+ rc = net_context_bind(tcp_ctx, (struct sockaddr *)&my_addr,
+ sizeof(struct sockaddr_in6));
+ if (rc < 0) {
+ printk("Cannot bind IPv6 TCP port %d (%d)", SERVER_PORT, rc);
+ goto error;
+ }
+
+ ctx->rx_nbuf = NULL;
+ ctx->remaining = 0;
+ ctx->net_ctx = tcp_ctx;
+
+ rc = net_context_listen(ctx->net_ctx, 0);
+ if (rc < 0) {
+ printk("Cannot listen IPv6 TCP (%d)", rc);
+ return -EIO;
+ }
+
+ rc = net_context_accept(ctx->net_ctx, ssl_accepted, 0, ctx);
+ if (rc < 0) {
+ printk("Cannot accept IPv4 (%d)", rc);
+ return -EIO;
+ }
+
+ return 0;
+
+error:
+ net_context_put(tcp_ctx);
+ return -EINVAL;
+}
+
+#else
+int ssl_init(struct ssl_context *ctx, void *addr)
+{
+ struct net_context *tcp_ctx = { 0 };
+ struct sockaddr_in my_addr4 = { 0 };
+ struct in_addr *server_addr = addr;
+ int rc;
+
+ k_sem_init(&ctx->tx_sem, 0, UINT_MAX);
+ k_fifo_init(&ctx->rx_fifo);
+
+ net_ipaddr_copy(&my_addr4.sin_addr, server_addr);
+ my_addr4.sin_family = AF_INET;
+ my_addr4.sin_port = htons(SERVER_PORT);
+
+ rc = net_context_get(AF_INET, SOCK_STREAM, IPPROTO_TCP, &tcp_ctx);
+ if (rc < 0) {
+ printk("Cannot get network context for IPv4 TCP (%d)", rc);
+ return -EIO;
+ }
+
+ rc = net_context_bind(tcp_ctx, (struct sockaddr *)&my_addr4,
+ sizeof(struct sockaddr_in));
+ if (rc < 0) {
+ printk("Cannot bind IPv4 TCP port %d (%d)", SERVER_PORT, rc);
+ goto error;
+ }
+
+ ctx->rx_nbuf = NULL;
+ ctx->remaining = 0;
+ ctx->net_ctx = tcp_ctx;
+
+ rc = net_context_listen(ctx->net_ctx, 0);
+ if (rc < 0) {
+ printk("Cannot listen IPv4 (%d)", rc);
+ return -EIO;
+ }
+
+ rc = net_context_accept(ctx->net_ctx, ssl_accepted, 0, ctx);
+ if (rc < 0) {
+ printk("Cannot accept IPv4 (%d)", rc);
+ return -EIO;
+ }
+
+ return 0;
+
+error:
+ net_context_put(tcp_ctx);
+ return -EINVAL;
+}
+#endif
diff --git a/samples/net/http_server/src/ssl_utils.h b/samples/net/http_server/src/ssl_utils.h
new file mode 100644
index 000000000..a0ef50eff
--- /dev/null
+++ b/samples/net/http_server/src/ssl_utils.h
@@ -0,0 +1,37 @@
+/*
+ * Copyright (c) 2017 Intel Corporation
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ */
+
+#ifndef _SSL_UTILS_H_
+#define _SSL_UTILS_H_
+
+#include <net/net_core.h>
+#include <net/http_parser.h>
+
+struct rx_fifo_block {
+ sys_snode_t snode;
+ struct k_mem_block block;
+ struct net_buf *buf;
+};
+
+struct ssl_context {
+ struct net_context *net_ctx;
+ struct net_buf *rx_nbuf;
+ struct net_buf *frag;
+ struct k_sem tx_sem;
+ struct k_fifo rx_fifo;
+ struct http_parser_settings parser_settings;
+ struct http_parser parser;
+
+ int remaining;
+};
+
+int ssl_init(struct ssl_context *ctx, void *addr);
+int ssl_tx(void *ctx, const unsigned char *buf, size_t size);
+int ssl_rx(void *ctx, unsigned char *buf, size_t size);
+
+void https_server_start(void);
+
+#endif
diff --git a/samples/net/http_server/src/test_certs.h b/samples/net/http_server/src/test_certs.h
new file mode 100644
index 000000000..5b6326110
--- /dev/null
+++ b/samples/net/http_server/src/test_certs.h
@@ -0,0 +1,92 @@
+/*
+ * Copyright (c) 2016 Intel Corporation
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ */
+
+#ifndef __TEST_CERTS_H__
+#define __TEST_CERTS_H__
+
+static const unsigned char rsa_example_keypair_der[] = {
+ 0x30, 0x82, 0x01, 0x3b, 0x02, 0x01, 0x00, 0x02, 0x41, 0x00, 0x9b, 0xfc,
+ 0x66, 0x90, 0x79, 0x84, 0x42, 0xbb, 0xab, 0x13, 0xfd, 0x2b, 0x7b, 0xf8,
+ 0xde, 0x15, 0x12, 0xe5, 0xf1, 0x93, 0xe3, 0x06, 0x8a, 0x7b, 0xb8, 0xb1,
+ 0xe1, 0x9e, 0x26, 0xbb, 0x95, 0x01, 0xbf, 0xe7, 0x30, 0xed, 0x64, 0x85,
+ 0x02, 0xdd, 0x15, 0x69, 0xa8, 0x34, 0xb0, 0x06, 0xec, 0x3f, 0x35, 0x3c,
+ 0x1e, 0x1b, 0x2b, 0x8f, 0xfa, 0x8f, 0x00, 0x1b, 0xdf, 0x07, 0xc6, 0xac,
+ 0x53, 0x07, 0x02, 0x03, 0x01, 0x00, 0x01, 0x02, 0x40, 0x1b, 0x4a, 0xf7,
+ 0x7b, 0x31, 0xf7, 0xe5, 0x61, 0x46, 0xd6, 0xd1, 0x86, 0x69, 0x43, 0xab,
+ 0x40, 0x0e, 0xb5, 0x73, 0x26, 0x88, 0x23, 0x9d, 0xd9, 0x76, 0x00, 0x91,
+ 0xd4, 0x85, 0x3c, 0x6f, 0x1e, 0xc0, 0x51, 0xeb, 0xe6, 0x90, 0x5b, 0x41,
+ 0x7f, 0xe6, 0xaa, 0x31, 0x6b, 0xac, 0x59, 0x53, 0x96, 0x26, 0xf1, 0xae,
+ 0xda, 0xbe, 0x55, 0xa4, 0x75, 0x40, 0x22, 0x5f, 0x27, 0x17, 0xa0, 0xd2,
+ 0x91, 0x02, 0x21, 0x00, 0xc8, 0xc4, 0x27, 0x7c, 0xd5, 0x61, 0xad, 0xbf,
+ 0x32, 0x8e, 0x1e, 0xcb, 0xe8, 0x94, 0xf4, 0x9f, 0x55, 0x77, 0xe5, 0xa8,
+ 0xc9, 0x70, 0xd0, 0x0f, 0x81, 0x04, 0xb7, 0x09, 0xb2, 0x1b, 0x53, 0xe9,
+ 0x02, 0x21, 0x00, 0xc6, 0xe6, 0x65, 0xbe, 0x10, 0xc8, 0x6d, 0xb7, 0x1e,
+ 0xee, 0x8e, 0x41, 0xbc, 0xe8, 0x67, 0x09, 0x9d, 0x8d, 0xee, 0x46, 0x1b,
+ 0xd5, 0x90, 0xb9, 0xee, 0x0d, 0xc5, 0xf9, 0xc6, 0xc9, 0xc9, 0x6f, 0x02,
+ 0x21, 0x00, 0x9b, 0xb0, 0x31, 0x87, 0x06, 0xda, 0x36, 0xa8, 0x9c, 0x85,
+ 0xc5, 0xb0, 0x0e, 0xee, 0xe4, 0x3c, 0x63, 0x45, 0x15, 0x1d, 0xad, 0x09,
+ 0x04, 0xef, 0xe0, 0xf7, 0x4d, 0x12, 0x01, 0xc2, 0x5b, 0x71, 0x02, 0x20,
+ 0x46, 0xd1, 0x25, 0x8c, 0x84, 0xa1, 0x38, 0x1f, 0x29, 0x0e, 0x3a, 0xec,
+ 0x40, 0xfc, 0x66, 0x23, 0x50, 0x4b, 0x86, 0x78, 0xc3, 0xd4, 0x48, 0x51,
+ 0x4a, 0xe6, 0xf0, 0x84, 0x3c, 0x39, 0x00, 0x55, 0x02, 0x21, 0x00, 0x8d,
+ 0x03, 0x6e, 0x29, 0x0e, 0xd7, 0x4e, 0x1f, 0x27, 0x70, 0xb5, 0x20, 0x79,
+ 0xfb, 0x31, 0x6a, 0x14, 0xb7, 0xe6, 0x55, 0x9a, 0x65, 0x40, 0xcf, 0xe0,
+ 0xe6, 0x46, 0xf8, 0xb2, 0x8e, 0xf4, 0x63, 0x0a
+};
+
+static const unsigned int rsa_example_keypair_der_len = 320;
+
+static const unsigned char rsa_example_cert_der[] = {
+ 0x30, 0x82, 0x02, 0x12, 0x30, 0x82, 0x01, 0x7b, 0x02, 0x02, 0x0d, 0xfa,
+ 0x30, 0x0d, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01,
+ 0x05, 0x05, 0x00, 0x30, 0x81, 0x9b, 0x31, 0x0b, 0x30, 0x09, 0x06, 0x03,
+ 0x55, 0x04, 0x06, 0x13, 0x02, 0x4a, 0x50, 0x31, 0x0e, 0x30, 0x0c, 0x06,
+ 0x03, 0x55, 0x04, 0x08, 0x13, 0x05, 0x54, 0x6f, 0x6b, 0x79, 0x6f, 0x31,
+ 0x10, 0x30, 0x0e, 0x06, 0x03, 0x55, 0x04, 0x07, 0x13, 0x07, 0x43, 0x68,
+ 0x75, 0x6f, 0x2d, 0x6b, 0x75, 0x31, 0x11, 0x30, 0x0f, 0x06, 0x03, 0x55,
+ 0x04, 0x0a, 0x13, 0x08, 0x46, 0x72, 0x61, 0x6e, 0x6b, 0x34, 0x44, 0x44,
+ 0x31, 0x18, 0x30, 0x16, 0x06, 0x03, 0x55, 0x04, 0x0b, 0x13, 0x0f, 0x57,
+ 0x65, 0x62, 0x43, 0x65, 0x72, 0x74, 0x20, 0x53, 0x75, 0x70, 0x70, 0x6f,
+ 0x72, 0x74, 0x31, 0x18, 0x30, 0x16, 0x06, 0x03, 0x55, 0x04, 0x03, 0x13,
+ 0x0f, 0x46, 0x72, 0x61, 0x6e, 0x6b, 0x34, 0x44, 0x44, 0x20, 0x57, 0x65,
+ 0x62, 0x20, 0x43, 0x41, 0x31, 0x23, 0x30, 0x21, 0x06, 0x09, 0x2a, 0x86,
+ 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x09, 0x01, 0x16, 0x14, 0x73, 0x75, 0x70,
+ 0x70, 0x6f, 0x72, 0x74, 0x40, 0x66, 0x72, 0x61, 0x6e, 0x6b, 0x34, 0x64,
+ 0x64, 0x2e, 0x63, 0x6f, 0x6d, 0x30, 0x1e, 0x17, 0x0d, 0x31, 0x32, 0x30,
+ 0x38, 0x32, 0x32, 0x30, 0x35, 0x32, 0x36, 0x35, 0x34, 0x5a, 0x17, 0x0d,
+ 0x31, 0x37, 0x30, 0x38, 0x32, 0x31, 0x30, 0x35, 0x32, 0x36, 0x35, 0x34,
+ 0x5a, 0x30, 0x4a, 0x31, 0x0b, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06,
+ 0x13, 0x02, 0x4a, 0x50, 0x31, 0x0e, 0x30, 0x0c, 0x06, 0x03, 0x55, 0x04,
+ 0x08, 0x0c, 0x05, 0x54, 0x6f, 0x6b, 0x79, 0x6f, 0x31, 0x11, 0x30, 0x0f,
+ 0x06, 0x03, 0x55, 0x04, 0x0a, 0x0c, 0x08, 0x46, 0x72, 0x61, 0x6e, 0x6b,
+ 0x34, 0x44, 0x44, 0x31, 0x18, 0x30, 0x16, 0x06, 0x03, 0x55, 0x04, 0x03,
+ 0x0c, 0x0f, 0x77, 0x77, 0x77, 0x2e, 0x65, 0x78, 0x61, 0x6d, 0x70, 0x6c,
+ 0x65, 0x2e, 0x63, 0x6f, 0x6d, 0x30, 0x5c, 0x30, 0x0d, 0x06, 0x09, 0x2a,
+ 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x01, 0x05, 0x00, 0x03, 0x4b,
+ 0x00, 0x30, 0x48, 0x02, 0x41, 0x00, 0x9b, 0xfc, 0x66, 0x90, 0x79, 0x84,
+ 0x42, 0xbb, 0xab, 0x13, 0xfd, 0x2b, 0x7b, 0xf8, 0xde, 0x15, 0x12, 0xe5,
+ 0xf1, 0x93, 0xe3, 0x06, 0x8a, 0x7b, 0xb8, 0xb1, 0xe1, 0x9e, 0x26, 0xbb,
+ 0x95, 0x01, 0xbf, 0xe7, 0x30, 0xed, 0x64, 0x85, 0x02, 0xdd, 0x15, 0x69,
+ 0xa8, 0x34, 0xb0, 0x06, 0xec, 0x3f, 0x35, 0x3c, 0x1e, 0x1b, 0x2b, 0x8f,
+ 0xfa, 0x8f, 0x00, 0x1b, 0xdf, 0x07, 0xc6, 0xac, 0x53, 0x07, 0x02, 0x03,
+ 0x01, 0x00, 0x01, 0x30, 0x0d, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7,
+ 0x0d, 0x01, 0x01, 0x05, 0x05, 0x00, 0x03, 0x81, 0x81, 0x00, 0x14, 0xb6,
+ 0x4c, 0xbb, 0x81, 0x79, 0x33, 0xe6, 0x71, 0xa4, 0xda, 0x51, 0x6f, 0xcb,
+ 0x08, 0x1d, 0x8d, 0x60, 0xec, 0xbc, 0x18, 0xc7, 0x73, 0x47, 0x59, 0xb1,
+ 0xf2, 0x20, 0x48, 0xbb, 0x61, 0xfa, 0xfc, 0x4d, 0xad, 0x89, 0x8d, 0xd1,
+ 0x21, 0xeb, 0xd5, 0xd8, 0xe5, 0xba, 0xd6, 0xa6, 0x36, 0xfd, 0x74, 0x50,
+ 0x83, 0xb6, 0x0f, 0xc7, 0x1d, 0xdf, 0x7d, 0xe5, 0x2e, 0x81, 0x7f, 0x45,
+ 0xe0, 0x9f, 0xe2, 0x3e, 0x79, 0xee, 0xd7, 0x30, 0x31, 0xc7, 0x20, 0x72,
+ 0xd9, 0x58, 0x2e, 0x2a, 0xfe, 0x12, 0x5a, 0x34, 0x45, 0xa1, 0x19, 0x08,
+ 0x7c, 0x89, 0x47, 0x5f, 0x4a, 0x95, 0xbe, 0x23, 0x21, 0x4a, 0x53, 0x72,
+ 0xda, 0x2a, 0x05, 0x2f, 0x2e, 0xc9, 0x70, 0xf6, 0x5b, 0xfa, 0xfd, 0xdf,
+ 0xb4, 0x31, 0xb2, 0xc1, 0x4a, 0x9c, 0x06, 0x25, 0x43, 0xa1, 0xe6, 0xb4,
+ 0x1e, 0x7f, 0x86, 0x9b, 0x16, 0x40, 0x0a
+};
+
+static const unsigned int rsa_example_cert_der_len = 535;
+
+#endif