diff --git a/.gitmodules b/.gitmodules
index 6a00a93..8dc737e 100644
--- a/.gitmodules
+++ b/.gitmodules
@@ -1,7 +1,6 @@
 [submodule "lwip/lwip"]
 	path = lwip/lwip
 	url = https://github.com/SuperHouse/esp-lwip.git
-[submodule "axtls/axtls"]
-	path = axtls/axtls
-	url = https://github.com/SuperHouse/axtls.git
-
+[submodule "extras/mbedtls/mbedtls"]
+	path = extras/mbedtls/mbedtls
+	url = https://github.com/ARMmbed/mbedtls.git
diff --git a/README.md b/README.md
index c825277..144ea33 100644
--- a/README.md
+++ b/README.md
@@ -69,18 +69,18 @@ Current status is alpha quality, actively developed. AP STATION mode (ie wifi cl
 * `include` contains header files from Espressif RTOS SDK, relating to the binary libraries & Xtensa core.
 * `core` contains source & headers for low-level ESP8266 functions & peripherals. `core/include/esp` contains useful headers for peripheral access, etc. Minimal to no FreeRTOS dependencies.
 * `extras` is a directory that contains optional components that can be added to your project. Most 'extras' components will have a corresponding example in the `examples` directory. Extras include:
+   - mbedtls - [mbedTLS](https://tls.mbed.org/) is a TLS/SSL library providing up to date secure connectivity and encryption support.
    - i2c - software i2c driver ([upstream project](https://github.com/kanflo/esp-open-rtos-driver-i2c))
    - rboot-ota - OTA support (over-the-air updates) including a TFTP server for receiving updates ([for rboot by @raburton](http://richard.burtons.org/2015/05/18/rboot-a-new-boot-loader-for-esp8266/))
    - bmp180 driver for digital pressure sensor ([upstream project](https://github.com/Angus71/esp-open-rtos-driver-bmp180))
 * `FreeRTOS` contains FreeRTOS implementation, subdirectory structure is the standard FreeRTOS structure. `FreeRTOS/source/portable/esp8266/` contains the ESP8266 port.
-* `lwip` and `axtls` contain the lwIP TCP/IP library and the axTLS TLS library ('libssl' in the esp8266 SDKs), respectively. See [Third Party Libraries](https://github.com/SuperHouse/esp-open-rtos/wiki/Third-Party-Libraries) wiki page for details.
+* `lwip` contains the lwIP TCP/IP library. See [Third Party Libraries](https://github.com/SuperHouse/esp-open-rtos/wiki/Third-Party-Libraries) wiki page for details.
 * `libc` contains the newlib libc. [Libc details here](https://github.com/SuperHouse/esp-open-rtos/wiki/libc-configuration).
 
 ## Open Source Components
 
 * [FreeRTOS](http://freertos.org) V7.5.2
 * [lwIP](http://lwip.wikia.com/wiki/LwIP_Wiki) v1.4.1, modified via the [esp-lwip project](https://github.com/kadamski/esp-lwip) by @kadamski.
-* [axTLS](http://axtls.sourceforge.net/) compiled from development version v1.5.3, plus modifications for low memory devices.
 * [newlib](https://github.com/projectgus/newlib-xtensa) v2.2.0, with patches for xtensa support and locking stubs for thread-safe operation on FreeRTOS.
 
 For details of how third party libraries are integrated, [see the wiki page](https://github.com/SuperHouse/esp-open-rtos/wiki/Third-Party-Libraries).
@@ -91,6 +91,8 @@ Binary libraries (inside the `lib` dir) are all supplied by Espressif as part of
 
 As part of the esp-open-rtos build process, all binary SDK symbols are prefixed with `sdk_`. This makes it easier to differentiate binary & open source code, and also prevents namespace conflicts.
 
+Espressif's RTOS SDK provided a "libssl" based on axTLS. This has been replaced with the more up to date mbedTLS library (see below).
+
 Some binary libraries appear to contain unattributed open source code:
 
 * libnet80211.a & libwpa.a appear to be based on FreeBSD net80211/wpa, or forks of them. ([See this issue](https://github.com/SuperHouse/esp-open-rtos/issues/4)).
@@ -98,7 +100,7 @@ Some binary libraries appear to contain unattributed open source code:
 
 ## Licensing
 
-* BSD license (as described in LICENSE) applies to original source files, [lwIP](http://lwip.wikia.com/wiki/LwIP_Wiki), and [axTLS](http://axtls.sourceforge.net/). lwIP is Copyright (C) Swedish Institute of Computer Science. axTLS is Copyright (C) Cameron Rich.
+* BSD license (as described in LICENSE) applies to original source files, [lwIP](http://lwip.wikia.com/wiki/LwIP_Wiki). lwIP is Copyright (C) Swedish Institute of Computer Science.
 
 * FreeRTOS is provided under the GPL with the FreeRTOS linking exception, allowing non-GPL firmwares to be produced using FreeRTOS as the RTOS core. License details in files under FreeRTOS dir. FreeRTOS is Copyright (C) Real Time Engineers Ltd.
 
@@ -106,6 +108,8 @@ Some binary libraries appear to contain unattributed open source code:
 
 * Newlib is covered by several copyrights and licenses, as per the files in the `libc` directory.
 
+* [mbedTLS](https://tls.mbed.org/) is provided under the Apache 2.0 license as described in the file extras/mbedtls/mbedtls/apache-2.0.txt. mbedTLS is Copyright (C) ARM Limited.
+
 Components under `extras/` may contain different licenses, please see those directories for details.
 
 ## Contributions
diff --git a/axtls/axtls b/axtls/axtls
deleted file mode 160000
index a4860ef..0000000
--- a/axtls/axtls
+++ /dev/null
@@ -1 +0,0 @@
-Subproject commit a4860ef68d7f5d98a8731f99787d51cc44c433c9
diff --git a/axtls/axtls_esp_stubs.c b/axtls/axtls_esp_stubs.c
deleted file mode 100644
index 3182594..0000000
--- a/axtls/axtls_esp_stubs.c
+++ /dev/null
@@ -1,33 +0,0 @@
-/*
- * Stub time-related functions for TLS time-related operations
- *
- * ESPTODO: Revisit these ASAP as gettimeofday() is used for entropy
- *
- * Part of esp-open-rtos
- * Copyright (C) 2015 Superhouse Automation Pty Ltd
- * BSD Licensed as described in the file LICENSE
- */
-#include <time.h>
-#include <sys/time.h>
-#include <stdio.h>
-
-time_t time(time_t *t)
-{
-    return 0;
-}
-
-time_t mktime(struct tm *tm)
-{
-    return 0;
-}
-
-int gettimeofday(struct timeval *tv, void *tz)
-{
-    return 0;
-}
-
-void abort(void)
-{
-    printf("abort() was called.\r\n");
-    while(1) {}
-}
diff --git a/axtls/component.mk b/axtls/component.mk
deleted file mode 100644
index 73859a2..0000000
--- a/axtls/component.mk
+++ /dev/null
@@ -1,22 +0,0 @@
-# Component makefile for axTLS
-
-# axTLS has its own configure and build system, but it's not particularly
-# designed for embedded systems. For now we're just imposing the ESP Open RTOS
-# build system over the top.
-
-# We supply our own hand tweaked config.h in the external 'include' dir.
-
-AXTLS_DIR = $(axtls_ROOT)axtls/
-INC_DIRS += $(axtls_ROOT)include $(AXTLS_DIR)ssl $(AXTLS_DIR)crypto
-
-# args for passing into compile rule generation
-axtls_INC_DIR =  $(AXTLS_DIR)include $(AXTLS_DIR)
-axtls_SRC_DIR = $(AXTLS_DIR)crypto $(AXTLS_DIR)ssl $(axtls_ROOT)
-
-#axtls_CFLAGS = $(CFLAGS) -Wno-address
-
-$(eval $(call component_compile_rules,axtls))
-
-# Helpful error if git submodule not initialised
-$(axtls_SRC_DIR):
-	$(error "axtls git submodule not installed. Please run 'git submodule init' then 'git submodule update'")
diff --git a/axtls/include/config.h b/axtls/include/config.h
deleted file mode 100644
index 175d083..0000000
--- a/axtls/include/config.h
+++ /dev/null
@@ -1,128 +0,0 @@
-/*
- * Automatically generated header file: don't edit
- */
-#define HAVE_DOT_CONFIG 0
-#undef CONFIG_PLATFORM_LINUX
-#undef CONFIG_PLATFORM_CYGWIN
-#undef CONFIG_PLATFORM_WIN32
-
-/*
- * General Configuration
- */
-#define PREFIX "/usr/local"
-#define CROSS "xtensa-lx106-elf-"
-#undef CONFIG_DEBUG
-#define CONFIG_STRIP_UNWANTED_SECTIONS 1
-#undef CONFIG_VISUAL_STUDIO_7_0
-#undef CONFIG_VISUAL_STUDIO_8_0
-#undef CONFIG_VISUAL_STUDIO_10_0
-#define CONFIG_VISUAL_STUDIO_7_0_BASE ""
-#define CONFIG_VISUAL_STUDIO_8_0_BASE ""
-#define CONFIG_VISUAL_STUDIO_10_0_BASE ""
-#define CONFIG_EXTRA_CFLAGS_OPTIONS ""
-#define CONFIG_EXTRA_LDFLAGS_OPTIONS ""
-
-/*
- * Embedded System Options (added for ESP RTOS SDK, don't have config entries yetr)
- */
-#define CONFIG_NO_FILESYSTEM 1
-#define CONFIG_USE_RAND 1
-#define CONFIG_MAX_PLAIN_LENGTH 1024
-#define CONFIG_MAX_KEY_BYTE_SIZE 256 /* for max 2048 bit keys (untested with >1024 bit keys) */
-
-/*
- * SSL Library
- */
-#undef CONFIG_SSL_SERVER_ONLY
-#undef CONFIG_SSL_CERT_VERIFICATION
-#define CONFIG_SSL_ENABLE_CLIENT 1
-#undef CONFIG_SSL_FULL_MODE
-#undef CONFIG_SSL_SKELETON_MODE
-#undef CONFIG_SSL_PROT_LOW
-#define CONFIG_SSL_PROT_MEDIUM 1
-#undef CONFIG_SSL_PROT_HIGH
-#undef CONFIG_SSL_USE_DEFAULT_KEY
-#define CONFIG_SSL_PRIVATE_KEY_LOCATION ""
-#define CONFIG_SSL_PRIVATE_KEY_PASSWORD ""
-#define CONFIG_SSL_X509_CERT_LOCATION ""
-#undef CONFIG_SSL_GENERATE_X509_CERT
-#define CONFIG_SSL_X509_COMMON_NAME ""
-#define CONFIG_SSL_X509_ORGANIZATION_NAME ""
-#define CONFIG_SSL_X509_ORGANIZATION_UNIT_NAME ""
-#undef CONFIG_SSL_ENABLE_V23_HANDSHAKE
-#undef CONFIG_SSL_HAS_PEM
-#undef CONFIG_SSL_USE_PKCS12
-#define CONFIG_SSL_EXPIRY_TIME 24
-#define CONFIG_X509_MAX_CA_CERTS 1
-#define CONFIG_SSL_MAX_CERTS 3
-#undef CONFIG_SSL_CTX_MUTEXING
-#undef CONFIG_USE_DEV_URANDOM
-#undef CONFIG_WIN32_USE_CRYPTO_LIB
-#undef CONFIG_OPENSSL_COMPATIBLE
-#undef CONFIG_PERFORMANCE_TESTING
-#undef CONFIG_SSL_TEST
-#undef CONFIG_AXTLSWRAP
-#undef CONFIG_AXHTTPD
-#undef CONFIG_HTTP_STATIC_BUILD
-#define CONFIG_HTTP_PORT 
-#define CONFIG_HTTP_HTTPS_PORT 
-#define CONFIG_HTTP_SESSION_CACHE_SIZE 
-#define CONFIG_HTTP_WEBROOT ""
-#define CONFIG_HTTP_TIMEOUT 
-#undef CONFIG_HTTP_HAS_CGI
-#define CONFIG_HTTP_CGI_EXTENSIONS ""
-#undef CONFIG_HTTP_ENABLE_LUA
-#define CONFIG_HTTP_LUA_PREFIX ""
-#undef CONFIG_HTTP_BUILD_LUA
-#define CONFIG_HTTP_CGI_LAUNCHER ""
-#undef CONFIG_HTTP_DIRECTORIES
-#undef CONFIG_HTTP_HAS_AUTHORIZATION
-#undef CONFIG_HTTP_HAS_IPV6
-#undef CONFIG_HTTP_ENABLE_DIFFERENT_USER
-#define CONFIG_HTTP_USER ""
-#undef CONFIG_HTTP_VERBOSE
-#undef CONFIG_HTTP_IS_DAEMON
-
-/*
- * Language Bindings
- */
-#undef CONFIG_BINDINGS
-#undef CONFIG_CSHARP_BINDINGS
-#undef CONFIG_VBNET_BINDINGS
-#define CONFIG_DOT_NET_FRAMEWORK_BASE ""
-#undef CONFIG_JAVA_BINDINGS
-#define CONFIG_JAVA_HOME ""
-#undef CONFIG_PERL_BINDINGS
-#define CONFIG_PERL_CORE ""
-#define CONFIG_PERL_LIB ""
-#undef CONFIG_LUA_BINDINGS
-#define CONFIG_LUA_CORE ""
-
-/*
- * Samples
- */
-#undef CONFIG_SAMPLES
-#undef CONFIG_C_SAMPLES
-#undef CONFIG_CSHARP_SAMPLES
-#undef CONFIG_VBNET_SAMPLES
-#undef CONFIG_JAVA_SAMPLES
-#undef CONFIG_PERL_SAMPLES
-#undef CONFIG_LUA_SAMPLES
-
-/*
- * BigInt Options
- */
-#undef CONFIG_BIGINT_CLASSICAL
-#undef CONFIG_BIGINT_MONTGOMERY
-#define CONFIG_BIGINT_BARRETT 1
-#define CONFIG_BIGINT_CRT 1
-#undef CONFIG_BIGINT_KARATSUBA
-#define MUL_KARATSUBA_THRESH
-#define SQU_KARATSUBA_THRESH
-#define CONFIG_BIGINT_SLIDING_WINDOW 1
-#define CONFIG_BIGINT_SQUARE 1
-#define CONFIG_BIGINT_CHECK_ON 1
-#define CONFIG_INTEGER_32BIT 1
-#undef CONFIG_INTEGER_16BIT
-#undef CONFIG_INTEGER_8BIT
-
diff --git a/axtls/include/os_int.h b/axtls/include/os_int.h
deleted file mode 100644
index 3fc09cd..0000000
--- a/axtls/include/os_int.h
+++ /dev/null
@@ -1,6 +0,0 @@
-#ifndef _OS_INT_H
-#define _OS_INT_H
-
-#include <stdint.h>
-
-#endif
diff --git a/axtls/include/os_port.h b/axtls/include/os_port.h
deleted file mode 100644
index 67fc3db..0000000
--- a/axtls/include/os_port.h
+++ /dev/null
@@ -1,95 +0,0 @@
-/*
- * Copyright (c) 2007-2015, Cameron Rich
- * Modifications Copyright (c) 2015 Superhouse Automation Pty Ltd
- * 
- * All rights reserved.
- * 
- * Redistribution and use in source and binary forms, with or without 
- * modification, are permitted provided that the following conditions are met:
- *
- * * Redistributions of source code must retain the above copyright notice, 
- *   this list of conditions and the following disclaimer.
- * * Redistributions in binary form must reproduce the above copyright notice, 
- *   this list of conditions and the following disclaimer in the documentation 
- *   and/or other materials provided with the distribution.
- * * Neither the name of the axTLS project nor the names of its contributors 
- *   may be used to endorse or promote products derived from this software 
- *   without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
- * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
- * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
- * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
- * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
- * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
- * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
- * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
- * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-/**
- * @file os_port.h
- *
- * Some stuff to minimise the differences between windows and linux/unix
- */
-
-#ifndef _HEADER_OS_PORT_H
-#define _HEADER_OS_PORT_H
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-#include "FreeRTOS.h"
-#include "os_int.h"
-#include "config.h"
-#include <stdio.h>
-#include <pwd.h>
-#include <netdb.h>
-//#include <fcntl.h>
-#include <errno.h>
-#include <sys/stat.h>
-#include <sys/time.h>
-#include <posix/sys/socket.h>
-#include <sys/wait.h>
-#include <ipv4/lwip/inet.h>
-#if defined(CONFIG_SSL_CTX_MUTEXING)
-#include "semphr.h"
-#endif
-
-#define SOCKET_READ(A,B,C)      read(A,B,C)
-#define SOCKET_WRITE(A,B,C)     write(A,B,C)
-#define SOCKET_CLOSE(A)         if (A >= 0) close(A)
-#define TTY_FLUSH()
-
-static inline uint64_t be64toh(uint64_t x) {
-  return ntohl(x>>32) | ((uint64_t)(ntohl(x)) << 32);
-}
-
-void exit_now(const char *format, ...) __attribute((noreturn));
-
-#define EXP_FUNC
-#define STDCALL
-
-/* Mutex definitions */
-#if defined(CONFIG_SSL_CTX_MUTEXING)
-#define SSL_CTX_MUTEX_TYPE           xSemaphoreHandle
-#define SSL_CTX_MUTEX_INIT(A)       vSemaphoreCreateBinaryCreateMutex(A)
-#define SSL_CTX_MUTEX_DESTROY(A)    vSemaphoreDelete(A)
-#define SSL_CTX_LOCK(A)             xSemaphoreTakeRecursive(A, portMAX_DELAY)
-#define SSL_CTX_UNLOCK(A)           xSemaphoreGiveRecursive(A)
-#else
-#define SSL_CTX_MUTEX_TYPE
-#define SSL_CTX_MUTEX_INIT(A)
-#define SSL_CTX_MUTEX_DESTROY(A)
-#define SSL_CTX_LOCK(A)
-#define SSL_CTX_UNLOCK(A)
-#endif
-
-#ifdef __cplusplus
-}
-#endif
-
-#endif 
diff --git a/axtls/include/version.h b/axtls/include/version.h
deleted file mode 100644
index 8fee21b..0000000
--- a/axtls/include/version.h
+++ /dev/null
@@ -1,10 +0,0 @@
-/* axTLS version header
-
-   We need this because we're using axTLS from source repo, not from a release.
-*/
-
-#ifndef _VERSION_H
-
-#define AXTLS_VERSION "esp-open-rtos axTLS " GITSHORTREV
-
-#endif
diff --git a/common.mk b/common.mk
index 8a2ed8e..7b236fb 100644
--- a/common.mk
+++ b/common.mk
@@ -80,7 +80,7 @@ OBJDUMP = $(CROSS)objdump
 
 # Source components to compile and link. Each of these are subdirectories
 # of the root, with a 'component.mk' file.
-COMPONENTS     ?= $(EXTRA_COMPONENTS) FreeRTOS lwip axtls core
+COMPONENTS     ?= $(EXTRA_COMPONENTS) FreeRTOS lwip core
 
 # binary esp-iot-rtos SDK libraries to link. These are pre-processed prior to linking.
 SDK_LIBS		?= main net80211 phy pp wpa
@@ -94,14 +94,25 @@ OWN_LIBC ?= 1
 # Note: you will need a recent esp
 ENTRY_SYMBOL ?= call_user_start
 
+# Set this to zero if you don't want individual function & data sections
+# (some code may be slightly slower, linking will be slighty slower,
+# but compiled code size will come down a small amount.)
+SPLIT_SECTIONS ?= 1
+
 # Common flags for both C & C++_
 C_CXX_FLAGS     = -Wall -Werror -Wl,-EL -nostdlib -mlongcalls -mtext-section-literals $(CPPFLAGS)
 # Flags for C only
 CFLAGS		= $(C_CXX_FLAGS) -std=gnu99
 # Flags for C++ only
 CXXFLAGS	= $(C_CXX_FLAGS) -fno-exceptions -fno-rtti
+
 LDFLAGS		= -nostdlib -Wl,--no-check-sections -Wl,-L$(BUILD_DIR)sdklib -Wl,-L$(ROOT)lib -u $(ENTRY_SYMBOL) -Wl,-static -Wl,-Map=build/${PROGRAM}.map $(EXTRA_LDFLAGS)
 
+ifeq ($(SPLIT_SECTIONS),1)
+  C_CXX_FLAGS += -ffunction-sections -fdata-sections
+  LDFLAGS += -Wl,-gc-sections
+endif
+
 ifeq ($(FLAVOR),debug)
     C_CXX_FLAGS += -g -O0
     LDFLAGS += -g -O0
@@ -159,7 +170,7 @@ ifeq ($(OTA),0)
 # for non-OTA, we create two different files for uploading into the flash
 # these are the names and options to generate them
 FW_ADDR_1	= 0x00000
-FW_ADDR_2	= 0x40000
+FW_ADDR_2	= 0x20000
 FW_FILE_1    = $(addprefix $(FW_BASE),$(FW_ADDR_1).bin)
 FW_FILE_2    = $(addprefix $(FW_BASE),$(FW_ADDR_2).bin)
 else
@@ -263,6 +274,7 @@ $$($(1)_OBJ_DIR)%.o: $$($(1)_REAL_ROOT)%.S $$($(1)_MAKEFILE) $(wildcard $(ROOT)*
 	$(vecho) "AS $$<"
 	$(Q) mkdir -p $$(dir $$@)
 	$$($(1)_CC_ARGS) -c $$< -o $$@
+	$$($(1)_CC_ARGS) -MM -MT $$@ -MF $$(@:.o=.d) $$<
 
 # the component is shown to depend on both obj and source files so we get a meaningful error message
 # for missing explicitly named source files
diff --git a/core/esp_hwrand.c b/core/esp_hwrand.c
new file mode 100644
index 0000000..7a591eb
--- /dev/null
+++ b/core/esp_hwrand.c
@@ -0,0 +1,27 @@
+/* Hardware Random Number Generator Functions
+ *
+ * For documentation, see http://esp8266-re.foogod.com/wiki/Random_Number_Generator
+ *
+ * Part of esp-open-rtos
+ * Copyright (C) 2015 Angus Gratton
+ * BSD Licensed as described in the file LICENSE
+ */
+#include <esp/hwrand.h>
+#include <esp/wdev_regs.h>
+#include <string.h>
+
+/* Return a random 32-bit number */
+uint32_t hwrand(void)
+{
+    return WDEV.HWRNG;
+}
+
+/* Fill a variable size buffer with data from the Hardware RNG */
+void hwrand_fill(uint8_t *buf, size_t len)
+{
+    for(size_t i = 0; i < len; i+=4) {
+        uint32_t random = WDEV.HWRNG;
+        /* using memcpy here in case 'buf' is unaligned */
+        memcpy(buf + i, &random, (i+4 <= len) ? 4 : (len % 4));
+    }
+}
diff --git a/core/exception_vectors.S b/core/exception_vectors.S
index 9085ca2..5e7f20e 100644
--- a/core/exception_vectors.S
+++ b/core/exception_vectors.S
@@ -1,256 +1,541 @@
 /* Xtensa Exception (ie interrupt) Vectors & low-level handler code
+ *
+ * Core exception handler code is placed in the .vecbase section, which gets
+ * picked up specially in the linker script and placed at beginning of IRAM.
+ *
+ * The actual VecBase symbol should be the first thing in .vecbase (this is not
+ * strictly important as it gets set by symbol lookup not by hardcoded address,
+ * but having it at 0x40100000 means that the exception vectors have memorable
+ * offsets, which match the default Boot ROM vector offsets. So convenient for
+ * human understanding.
+ *
+ * Part of esp-open-rtos
+ * Original vector contents Copyright (C) 2014-2015 Espressif Systems
+ * Additions Copyright (C) Superhouse Automation Pty Ltd and Angus Gratton
+ * BSD Licensed as described in the file LICENSE
+ */
 
-   Core exception handler code is placed in the .vecbase section,
-   which gets picked up specially in the linker script and placed
-   at beginning of IRAM.
+#include "led_debug.s"
 
-   The actual VecBase symbol should be the first thing in .vecbase
-   (this is not strictly important as it gets set by symbol lookup not
-   by hardcoded address, but having it at 0x40100000 means that the
-   exception vectors have memorable offsets, which match the default
-   Boot ROM vector offsets. So convenient for human understanding.
+/* Some UserException causes, see table Table 4–64 in ISA reference */
 
-   Part of esp-open-rtos
-   Original vector contents Copyright (C) 2014-2015 Espressif Systems
-   Additions Copyright (C) Superhouse Automation Pty Ltd
-   BSD Licensed as described in the file LICENSE
-*/
-	.text
-	.section .vecbase.text, "x"
-        .align  256
-        .global VecBase
-        .type   VecBase, @function /* it's not really a function, but treat it like one */
+#define CAUSE_SYSCALL 1
+#define CAUSE_LOADSTORE 3
+#define CAUSE_LVL1INT 4
+
+        .section .bss
+
+NMIHandlerStack:                # stack space for NMI handler
+        .skip   4*0x100
+.LNMIHandlerStackTop:
+NMIRegisterSaved:               # register space for saving NMI registers
+        .skip   4*(16 + 6)
+
+LoadStoreErrorHandlerStack:
+        .word   0       # a0
+        .word   0       # (unused)
+        .word   0       # a2
+        .word   0       # a3
+        .word   0       # a4
+
+/***************************** Exception Vectors *****************************/
+
+        .section .vecbase.text, "x"
+
+/* Note: Exception vectors must be aligned on a 256-byte (0x100) boundary or
+ * they will not function properly.  (This is taken care of in the linker
+ * script by ensuring .vecbase.text is aligned properly, and putting VecBase
+ * right at the beginning of .vecbase.text) */
+        .org    0
 VecBase:
-	/* IMPORTANT: exception vector literals will go here, but we
-	  can't have more than 4 otherwise we push DebugExceptionVector past
-	  offset 0x10 relative to VecBase. There should be ways to avoid this,
-	  and also keep the VecBase offsets easy to read, but this works for now.
-	*/
-	.literal_position
-	.align 16
+        .global VecBase
+        /* IMPORTANT: exception vector literals will go here, but we
+         * can't have more than 4 otherwise we push DebugExceptionVector past
+         * offset 0x10 relative to VecBase. There should be ways to avoid this,
+         * and also keep the VecBase offsets easy to read, but this works for
+         * now. */
+        .literal_position
+
+        .org    VecBase + 0x10
 DebugExceptionVector:
-	wsr.excsave2 a0
-	call0 sdk_user_fatal_exception_handler
-	rfi 2
-	.align 16
+        .type   DebugExceptionVector, @function
+
+        wsr     a0, excsave2
+        call0   sdk_user_fatal_exception_handler
+        rfi     2
+
+        .org    VecBase + 0x20
 NMIExceptionVector:
-	wsr.excsave3 a0
-	call0 CallNMIExceptionHandler
-	rfi 3 /* CallNMIExceptionHandler should call rfi itself */
-	.align 16
+        .type   NMIExceptionVector, @function
+
+        wsr     a0, excsave3
+        call0   CallNMIExceptionHandler
+        rfi     3  # Should never be reached
+
+        .org    VecBase + 0x30
 KernelExceptionVector:
-	break 1, 0
-	call0 sdk_user_fatal_exception_handler
-	rfe
-	.align 16
-.L_EmptyVectorEntry:
-	nop
-	.align 16
+        .type   KernelExceptionVector, @function
+
+        break   1, 0
+        call0   sdk_user_fatal_exception_handler
+        rfe
+
+        .org    VecBase + 0x50
 UserExceptionVector:
-	wsr.excsave1 a0
-	call0 CallUserExceptionHandler
-	rfe /* CallUserExceptionHandler should call rfe itself */
-	.align 16
-.L_EmptyVectorEntry2:
-	nop
-	.align 16
+        .type   UserExceptionVector, @function
+
+        wsr     a1, excsave1
+        rsr     a1, exccause
+        beqi    a1, CAUSE_LOADSTORE, LoadStoreErrorHandler
+        j       UserExceptionHandler
+
+        .org    VecBase + 0x70
 DoubleExceptionVector:
-	break 1, 4
-	call0 sdk_user_fatal_exception_handler
-	.align 16
-.L_UnusedResetVector:
-	/* reset vector slot doesn't get used, as vecbase goes back to mask ROM on reset */
-	nop
+        .type   DoubleExceptionVector, @function
 
-	.section .bss
-NMIHandlerStack: /* stack space for NMI handler */
-	.skip 4*0x100
-NMIRegisterSaved: /* register space for saving NMI registers */
-	.skip 4*(0x16 + 6)
+        break   1, 4
+        call0   sdk_user_fatal_exception_handler
 
-/* this symbol is _Pri_3_HandlerAddress in the RTOS SDK, appears totally
-	unused (stays zero at all times) */
-	.global NMIHandlerAddress
-NMIHandlerAddress:
-	.long 0
+/* Reset vector at offset 0x80 is unused, as vecbase gets reset to mask ROM
+ * vectors on chip reset. */
+
+/*************************** LoadStoreError Handler **************************/
+
+        .section .vecbase.text, "x"
+
+/* Xtensa "Load/Store Exception" handler:
+ * Completes L8/L16 load instructions from Instruction address space, for which
+ * the architecture only supports 32-bit reads.
+ *
+ * Called from UserExceptionVector if EXCCAUSE is LoadStoreErrorCause
+ *
+ * (Fast path (no branches) is for L8UI)
+ */
+        .literal_position
+
+        .balign 4
+LoadStoreErrorHandler:
+        .type   LoadStoreErrorHandler, @function
+
+        /* Registers are saved in the address corresponding to their register
+         * number times 4.  This allows a quick and easy mapping later on when
+         * needing to store the value to a particular register number. */
+        movi    sp, LoadStoreErrorHandlerStack
+        s32i    a0, sp, 0
+        s32i    a2, sp, 0x08
+        s32i    a3, sp, 0x0c
+        s32i    a4, sp, 0x10
+        rsr     a0, sar         # Save SAR in a0 to restore later
+
+        /* Examine the opcode which generated the exception */
+        /* Note: Instructions are in this order to avoid pipeline stalls. */
+        rsr     a2, epc1
+        movi    a3, ~3
+        ssa8l   a2              # sar is now correct shift for aligned read
+        and     a2, a2, a3      # a2 now 4-byte aligned address of instruction
+        l32i    a4, a2, 0
+        l32i    a2, a2, 4
+        movi    a3, 0x00700F    # opcode mask for l8ui/l16si/l16ui
+        src     a2, a2, a4      # a2 now instruction that failed
+        and     a3, a2, a3      # a3 is masked instruction
+        bnei    a3, 0x000002, .LSE_check_l16
+
+        /* Note: At this point, opcode could technically be one of two things:
+         *   xx0xx2 (L8UI)
+         *   xx8xx2 (Reserved (invalid) opcode)
+         * It is assumed that we'll never get to this point from an illegal
+         * opcode, so we don't bother to check for that case and presume this
+         * is always an L8UI. */
+
+        movi    a4, ~3
+        rsr     a3, excvaddr    # read faulting address
+        and     a4, a3, a4      # a4 now word aligned read address
+
+        l32i    a4, a4, 0       # perform the actual read
+        ssa8l   a3              # sar is now shift to extract a3's byte
+        srl     a3, a4          # shift right correct distance
+        extui   a4, a3, 0, 8    # mask off bits we need for an l8
+
+.LSE_post_fetch:
+        /* We jump back here after either the L8UI or the L16*I routines do the
+         * necessary work to read the value from memory.
+         * At this point, a2 holds the faulting instruction and a4 holds the
+         * correctly read value.
+
+         * Restore original SAR value (saved in a0) and update EPC so we'll
+         * return back to the instruction following the one we just emulated */
+
+        /* Note: Instructions are in this order to avoid pipeline stalls */
+        rsr     a3, epc1
+        wsr     a0, sar
+        addi    a3, a3, 0x3
+        wsr     a3, epc1
+
+        /* Stupid opcode tricks: The jumptable we use later on needs 16 bytes
+         * per entry (so we can avoid a second jump by just doing a RFE inside
+         * each entry).  Unfortunately, however, Xtensa doesn't have an addx16
+         * operation to make that easy for us.  Luckily, all of the faulting
+         * opcodes we're processing are guaranteed to have bit 3 be zero, which
+         * means if we just shift the register bits of the opcode down by 3
+         * instead of 4, we will get the register number multiplied by 2.  This
+         * combined with an addx8 will give us an effective addx16 without
+         * needing any extra shift operations. */
+        extui   a2, a2, 3, 5    # a2 is now destination register 0-15 times 2
+
+        bgei    a2, 10, .LSE_assign_reg     # a5..a15 use jumptable
+        beqi    a2, 2, .LSE_assign_a1       # a1 uses a special routine
+
+        /* We're storing into a0 or a2..a4, which are all saved in our "stack"
+         * area.  Calculate the correct address and stick the value in there,
+         * then just do our normal restore and RFE (no jumps required, which
+         * actually makes a0..a4 substantially faster). */
+        addx2   a2, a2, sp
+        s32i    a4, a2, 0
+
+        /* Restore all regs and return */
+        l32i    a0, sp, 0
+        l32i    a2, sp, 0x08
+        l32i    a3, sp, 0x0c
+        l32i    a4, sp, 0x10
+        rsr     a1, excsave1    # restore a1 saved by UserExceptionVector
+        rfe
+
+.LSE_assign_reg:
+        /* At this point, a2 contains the register number times 2, a4 is the
+         * read value. */
+
+        /* Calculate the jumptable address, and restore all regs except a2 and
+         * a4 so we have less to do after jumping. */
+        /* Note: Instructions are in this order to avoid pipeline stalls. */
+        movi    a3, .LSE_jumptable_base
+        l32i    a0, sp, 0
+        addx8   a2, a2, a3      # a2 is now the address to jump to
+        l32i    a3, sp, 0x0c
+
+        jx      a2
+
+        .balign 4
+.LSE_check_l16:
+        /* At this point, a2 contains the opcode, a3 is masked opcode */
+        movi    a4, 0x001002    # l16si or l16ui opcode after masking
+        bne     a3, a4, .LSE_wrong_opcode
+
+        /* Note: At this point, the opcode could be one of two things:
+         *   xx1xx2 (L16UI)
+         *   xx9xx2 (L16SI)
+         * Both of these we can handle. */
+
+        movi    a4, ~3
+        rsr     a3, excvaddr    # read faulting address
+        and     a4, a3, a4      # a4 now word aligned read address
+
+        l32i    a4, a4, 0       # perform the actual read
+        ssa8l   a3              # sar is now shift to extract a3's bytes
+        srl     a3, a4          # shift right correct distance
+        extui   a4, a3, 0, 16   # mask off bits we need for an l16
+
+        bbci    a2, 15, .LSE_post_fetch  # Not a signed op
+        bbci    a4, 15, .LSE_post_fetch  # Value does not need sign-extension
+
+        movi    a3, 0xFFFF0000
+        or      a4, a3, a4      # set 32-bit sign bits
+        j       .LSE_post_fetch
+
+.LSE_wrong_opcode:
+        /* If we got here it's not an opcode we can try to fix, so bomb out.
+         * Restore registers so any dump the fatal exception routine produces
+         * will have correct values */
+        wsr     a0, sar
+        l32i    a0, sp, 0
+        l32i    a2, sp, 0x08
+        l32i    a3, sp, 0x0c
+        l32i    a4, sp, 0x10
+        rsr     a1, excsave1
+        call0   sdk_user_fatal_exception_handler
+
+        .balign 4
+.LSE_assign_a1:
+        /* a1 is saved in excsave1, so just update that with the value, */
+        wsr     a4, excsave1
+        /* Then restore all regs and return */
+        l32i    a0, sp, 0
+        l32i    a2, sp, 0x08
+        l32i    a3, sp, 0x0c
+        l32i    a4, sp, 0x10
+        rsr     a1, excsave1
+        rfe
+
+        .balign 4
+.LSE_jumptable:
+        /* The first 5 entries (80 bytes) of this table are unused (registers
+         * a0..a4 are handled separately above).  Rather than have a whole bunch
+         * of wasted space, we just pretend that the table starts 80 bytes
+         * earlier in memory. */
+        .set    .LSE_jumptable_base, .LSE_jumptable - (16 * 5)
+
+        .org    .LSE_jumptable_base + (16 * 5)
+        mov     a5, a4
+        l32i    a2, sp, 0x08
+        l32i    a4, sp, 0x10
+        rsr     a1, excsave1
+        rfe
+
+        .org    .LSE_jumptable_base + (16 * 6)
+        mov     a6, a4
+        l32i    a2, sp, 0x08
+        l32i    a4, sp, 0x10
+        rsr     a1, excsave1
+        rfe
+
+        .org    .LSE_jumptable_base + (16 * 7)
+        mov     a7, a4
+        l32i    a2, sp, 0x08
+        l32i    a4, sp, 0x10
+        rsr     a1, excsave1
+        rfe
+
+        .org    .LSE_jumptable_base + (16 * 8)
+        mov     a8, a4
+        l32i    a2, sp, 0x08
+        l32i    a4, sp, 0x10
+        rsr     a1, excsave1
+        rfe
+
+        .org    .LSE_jumptable_base + (16 * 9)
+        mov     a9, a4
+        l32i    a2, sp, 0x08
+        l32i    a4, sp, 0x10
+        rsr     a1, excsave1
+        rfe
+
+        .org    .LSE_jumptable_base + (16 * 10)
+        mov     a10, a4
+        l32i    a2, sp, 0x08
+        l32i    a4, sp, 0x10
+        rsr     a1, excsave1
+        rfe
+
+        .org    .LSE_jumptable_base + (16 * 11)
+        mov     a11, a4
+        l32i    a2, sp, 0x08
+        l32i    a4, sp, 0x10
+        rsr     a1, excsave1
+        rfe
+
+        .org    .LSE_jumptable_base + (16 * 12)
+        mov     a12, a4
+        l32i    a2, sp, 0x08
+        l32i    a4, sp, 0x10
+        rsr     a1, excsave1
+        rfe
+
+        .org    .LSE_jumptable_base + (16 * 13)
+        mov     a13, a4
+        l32i    a2, sp, 0x08
+        l32i    a4, sp, 0x10
+        rsr     a1, excsave1
+        rfe
+
+        .org    .LSE_jumptable_base + (16 * 14)
+        mov     a14, a4
+        l32i    a2, sp, 0x08
+        l32i    a4, sp, 0x10
+        rsr     a1, excsave1
+        rfe
+
+        .org    .LSE_jumptable_base + (16 * 15)
+        mov     a15, a4
+        l32i    a2, sp, 0x08
+        l32i    a4, sp, 0x10
+        rsr     a1, excsave1
+        rfe
+
+/****************************** call_user_start ******************************/
+
+        .section .vecbase.text, "x"
+
+/* This is the first entrypoint called from the ROM after loading the image
+ * into IRAM.  It just sets up the VECBASE register to point at our own
+ * exception vectors and then calls sdk_user_start() */
+
+        .literal_position
+
+        .balign 4
+call_user_start:
+        .global call_user_start
+        .type   call_user_start, @function
+
+        movi    a2, VecBase
+        wsr     a2, vecbase
+        call0   sdk_user_start
+
+/*************************** NMI Exception Handler ***************************/
+
+        .section .vecbase.text, "x"
 
 /* Save register relative to a0 */
 .macro SAVE_REG register, regnum
-	s32i \register, a0, (0x20 + 4 * \regnum)
+        s32i \register, a0, (4 * (\regnum + 6))
 .endm
 
 /* Load register relative to sp */
 .macro LOAD_REG register, regnum
-	l32i \register, sp, (0x20 + 4 * \regnum)
+        l32i \register, sp, (4 * (\regnum + 6))
 .endm
 
-	.text
-	.section .vecbase.text
-	.literal_position
-        .align  4
-	.global call_user_start
-        .type   call_user_start, @function
-call_user_start:
-	movi a2, VecBase
-	wsr.vecbase a2
-	call0 sdk_user_start
+        .literal_position
 
-	.literal_position
-        .align  16
-        .type   CallNMIExceptionHandler, @function
+        .balign  16
 CallNMIExceptionHandler:
-	movi a0, NMIRegisterSaved
-	SAVE_REG a2, 2
-	movi a2, NMIHandlerAddress
-	l32i a2, a2, 0
-	SAVE_REG sp, 1
-	SAVE_REG a3, 3
-	xsr.excsave3 a2 /* excsave3 is now NMIHandlerAddress, a2 is former a0 */
-	SAVE_REG a4, 4
-	SAVE_REG a2, 0
-	rsr.epc1 a3
-	rsr.exccause a4
-	SAVE_REG a3, -5
-	SAVE_REG a4, -4
-	rsr.excvaddr a3
-	SAVE_REG a3, -3
-	rsr.excsave1 a3
-	SAVE_REG a3, -2
-	SAVE_REG a5, 5
-	SAVE_REG a6, 6
-	SAVE_REG a7, 7
-	SAVE_REG a8, 8
-	SAVE_REG a9, 9
-	SAVE_REG a10, 10
-	SAVE_REG a11, 11
-	SAVE_REG a12, 12
-	SAVE_REG a13, 13
-	SAVE_REG a14, 14
-	SAVE_REG a15, 15
-	movi sp, NMIRegisterSaved /* also top of NMIHandlerStack */
-	movi a0, 0
-	movi a2, 0x23 /* argument for handler */
-	wsr.ps a2
-	rsync
-	rsr.sar a14
-	s32i a14, sp, 0 /* this is also NMIRegisterSaved+0 */
-	call0 sdk_wDev_ProcessFiq
-	l32i a15, sp, 0
-	wsr.sar a15
-	movi a2, 0x33
-	wsr.ps a2
-	rsync
-	LOAD_REG a4, 4
-	LOAD_REG a5, 5
-	LOAD_REG a6, 6
-	LOAD_REG a7, 7
-	LOAD_REG a8, 8
-	LOAD_REG a9, 9
-	LOAD_REG a10, 10
-	LOAD_REG a11, 11
-	LOAD_REG a12, 12
-	LOAD_REG a13, 13
-	LOAD_REG a14, 14
-	LOAD_REG a15, 15
-	LOAD_REG a2, -5
-	LOAD_REG a3, -4
-	wsr.epc1 a2
-	wsr.exccause a3
-	LOAD_REG a2, -3
-	LOAD_REG a3, -2
-	wsr.excvaddr a2
-	wsr.excsave1 a3
-	LOAD_REG a0, 0
-	/* set dport nmi status bit 0 (wDev_ProcessFiq clears & verifies this bit stays cleared,
-	   see http://esp8266-re.foogod.com/wiki/WDev_ProcessFiq_%28IoT_RTOS_SDK_0.9.9%29)  */
-	movi a2, 0x3ff00000
-	movi a3, 0x1
-	s32i a3, a2, 0
-	LOAD_REG a2, 2
-	LOAD_REG a3, 3
-	LOAD_REG a1, 1
-	rfi 0x3
+        .type   CallNMIExceptionHandler, @function
 
-/* Some UserException causes, see table Table 4–64 in ISA reference */
-#define CAUSE_SYSCALL 1
-#define CAUSE_LVL1INT 4
+        movi    a0, NMIRegisterSaved
+        SAVE_REG a2, 2
+        SAVE_REG sp, 1
+        SAVE_REG a3, 3
+        rsr     a2, excsave3    # a2 is now former a0
+        SAVE_REG a4, 4
+        SAVE_REG a2, 0
+        rsr     a3, epc1
+        rsr     a4, exccause
+        SAVE_REG a3, -5
+        SAVE_REG a4, -4
+        rsr     a3, excvaddr
+        SAVE_REG a3, -3
+        rsr     a3, excsave1
+        SAVE_REG a3, -2
+        SAVE_REG a5, 5
+        SAVE_REG a6, 6
+        SAVE_REG a7, 7
+        SAVE_REG a8, 8
+        SAVE_REG a9, 9
+        SAVE_REG a10, 10
+        SAVE_REG a11, 11
+        SAVE_REG a12, 12
+        SAVE_REG a13, 13
+        SAVE_REG a14, 14
+        SAVE_REG a15, 15
+        movi    sp, .LNMIHandlerStackTop
+        movi    a0, 0
+        movi    a2, 0x23        # argument for handler
+        wsr     a2, ps
+        rsync
+        rsr     a14, sar
+        s32i    a14, sp, 0      # this is also NMIRegisterSaved+0
+        call0   sdk_wDev_ProcessFiq
+        l32i    a15, sp, 0
+        wsr     a15, sar
+        movi    a2, 0x33
+        wsr     a2, ps
+        rsync
+        LOAD_REG a4, 4
+        LOAD_REG a5, 5
+        LOAD_REG a6, 6
+        LOAD_REG a7, 7
+        LOAD_REG a8, 8
+        LOAD_REG a9, 9
+        LOAD_REG a10, 10
+        LOAD_REG a11, 11
+        LOAD_REG a12, 12
+        LOAD_REG a13, 13
+        LOAD_REG a14, 14
+        LOAD_REG a15, 15
+        LOAD_REG a2, -5
+        LOAD_REG a3, -4
+        wsr     a2, epc1
+        wsr     a3, exccause
+        LOAD_REG a2, -3
+        LOAD_REG a3, -2
+        wsr     a2, excvaddr
+        wsr     a3, excsave1
+        LOAD_REG a0, 0
+        /* set dport nmi status bit 0 (wDev_ProcessFiq clears & verifies this
+         * bit stays cleared, see
+         * http://esp8266-re.foogod.com/wiki/WDev_ProcessFiq_%28IoT_RTOS_SDK_0.9.9%29)
+         */
+        movi    a2, 0x3ff00000
+        movi    a3, 0x1
+        s32i    a3, a2, 0
+        LOAD_REG a2, 2
+        LOAD_REG a3, 3
+        LOAD_REG a1, 1
+        rfi     3
 
-        .type   CallUserExceptionHandler, @function
-CallUserExceptionHandler:
-	rsr.exccause a0
-	beqi a0, CAUSE_SYSCALL, UserSyscallHandler
-	mov a0, sp
-	addi sp, sp, -0x50
-	s32i a0, sp, 0x10
-	rsr.ps a0
-	s32i a0, sp, 0x08
-	rsr.epc1 a0
-	s32i a0, sp, 0x04
-	rsr.excsave1 a0 /* a0 was saved in UserExceptionVector */
-	s32i a0, sp, 0x0c
-	movi a0, _xt_user_exit
-	s32i a0, sp, 0x0
-	call0 sdk__xt_int_enter
-	movi a0, 0x23
-	wsr.ps a0
-	rsync
-	rsr.exccause a2
-	beqi a2, CAUSE_LVL1INT, UserHandleInterrupt
-	/* Any UserException cause other than level 1 interrupt triggers a panic */
+/*********************** General UserException Handler ***********************/
+
+        .section .vecbase.text, "x"
+
+/* Called by UserExceptionVector if EXCCAUSE is anything other than
+ * LoadStoreCause. */
+
+        .literal_position
+
+        .balign  4
+UserExceptionHandler:
+        .type   UserExceptionHandler, @function
+        xsr     a0, excsave1    # a0 now contains sp
+        mov     sp, a0
+        addi    sp, sp, -0x50
+        s32i    a0, sp, 0x10
+        rsr     a0, ps
+        s32i    a0, sp, 0x08
+        rsr     a0, epc1
+        s32i    a0, sp, 0x04
+        rsr     a0, excsave1
+        s32i    a0, sp, 0x0c
+        movi    a0, _xt_user_exit
+        s32i    a0, sp, 0x0
+        call0   sdk__xt_int_enter
+        movi    a0, 0x23
+        wsr     a0, ps
+        rsync
+        rsr     a2, exccause
+        beqi    a2, CAUSE_LVL1INT, UserHandleInterrupt
+        /* Any UserException cause other than level 1 interrupt should panic */
 UserFailOtherExceptionCause:
-	break 1, 1
-	call0 sdk_user_fatal_exception_handler
+        break   1, 1
+        call0   sdk_user_fatal_exception_handler
 UserHandleInterrupt:
-	rsil a0, 1
-	rsr.intenable a2
-	rsr.interrupt a3
-	movi a4, 0x3fff
-	and a2, a2, a3
-	and a2, a2, a4 /* a2 = 0x3FFF & INTENABLE & INTERRUPT */
+        rsil    a0, 1
+        rsr     a2, intenable
+        rsr     a3, interrupt
+        movi    a4, 0x3fff
+        and     a2, a2, a3
+        and     a2, a2, a4      # a2 = 0x3FFF & INTENABLE & INTERRUPT
 UserHandleTimer:
-	movi a3, 0xffbf
-	and a3, a2, a3 /* a3 = a2 & 0xFFBF, ie remove 0x40 from a2 if set */
-	bnez a3, UserTimerDone /* bits other than 0x40 are set */
-	movi a3, 0x40
-	sub a12, a2, a3 /* a12 - a2 - 0x40 - I think a12 _must_ be zero here? */
-	call0 sdk__xt_timer_int /* tick timer interrupt */
-	mov a2, a12 /* restore a2 from a12, ie zero */
-	beqz a2, UserIntDone
+        movi    a3, 0xffbf
+        and     a3, a2, a3      # a3 = a2 with bit 6 cleared
+        bnez    a3, UserTimerDone   # If any non-timer interrupt bits set
+        movi    a3, 0x40
+        sub     a12, a2, a3     # a12 = a2 - 0x40 -- Will be zero if bit 6 set
+        call0   sdk__xt_timer_int  # tick timer interrupt
+        mov     a2, a12         # restore a2 from a12, ie zero
+        beqz    a2, UserIntDone
 UserTimerDone:
-	call0 _xt_isr_handler
-	bnez a2, UserHandleTimer
+        call0   _xt_isr_handler
+        bnez    a2, UserHandleTimer
 UserIntDone:
-	beqz a2, UserIntExit
-	break 1, 1 /* non-zero remnant in a2 means fail */
-	call0 sdk_user_fatal_exception_handler
+        beqz    a2, UserIntExit
+        /* FIXME: this code will never be reached */
+        break   1, 1
+        call0   sdk_user_fatal_exception_handler
 UserIntExit:
-	call0 sdk__xt_int_exit /* calls rfi */
+        call0   sdk__xt_int_exit  # jumps to _xt_user_exit. Never returns here
 
-/* As far as I can tell, the syscall handler is basically a no-op */
-UserSyscallHandler:
-	addi sp, sp, -0x10
-	s32i a2, sp, 0x08
-	s32i a2, sp, 0x0c
-	rsr.epc1 a2
-	addi a3, a2, 0x3
-	wsr.epc1 a3
-	l32i a2, sp, 0x8
-	l32i a3, sp, 0xc
-	addi sp, sp, 0x10
-	movi a0, 0x7f
-	movnez a2, a0, a2
-	rsr.excsave1 a0
-	rfe
+        .section .text
 
-	.global _xt_user_exit
-	.type _xt_user_exit, @function
+/* _xt_user_exit is used to exit interrupt context. */
+/* TODO: Find a better place for this to live. */
 _xt_user_exit:
-	l32i a0, sp, 0x8
-	wsr.ps a0
-	l32i a0, sp, 0x4
-	wsr.epc1 a0
-	l32i a0, sp, 0xc
-	l32i sp, sp, 0x10
-	rsync
-	rfe
+        .global _xt_user_exit
+        .type _xt_user_exit, @function
+
+        l32i    a0, sp, 0x8
+        wsr     a0, ps
+        l32i    a0, sp, 0x4
+        wsr     a0, epc1
+        l32i    a0, sp, 0xc
+        l32i    sp, sp, 0x10
+        rsync
+        rfe
 
diff --git a/core/include/esp/hwrand.h b/core/include/esp/hwrand.h
new file mode 100644
index 0000000..8ec75e1
--- /dev/null
+++ b/core/include/esp/hwrand.h
@@ -0,0 +1,22 @@
+/** esp/hwrand.h
+ *
+ * Hardware Random Number Generator functions.
+ *
+ * For documentation, see http://esp8266-re.foogod.com/wiki/Random_Number_Generator
+ *
+ * Part of esp-open-rtos
+ * Copyright (C) 2015 Angus Gratton
+ * BSD Licensed as described in the file LICENSE
+ */
+#ifndef _ESP_RNG_H
+#define _ESP_RNG_H
+#include <stdint.h>
+#include <sys/types.h>
+
+/* Return a random 32-bit number */
+uint32_t hwrand(void);
+
+/* Fill a variable size buffer with data from the Hardware RNG */
+void hwrand_fill(uint8_t *buf, size_t len);
+
+#endif
diff --git a/core/include/esp/wdev_regs.h b/core/include/esp/wdev_regs.h
index 74788ca..32afca8 100644
--- a/core/include/esp/wdev_regs.h
+++ b/core/include/esp/wdev_regs.h
@@ -2,6 +2,9 @@
  *
  * ESP8266 register definitions for the "wdev" region (0x3FF2xxx)
  *
+ * In the DPORT memory space, alongside DPORT regs. However mostly
+ * concerned with the WiFi hardware interface.
+ *
  * Not compatible with ESP SDK register access code.
  */
 
@@ -21,10 +24,19 @@
  */
 
 struct WDEV_REGS {
-    uint32_t volatile _unknown[768];  // 0x0000 - 0x0bfc
-    uint32_t volatile SYS_TIME;       // 0x0c00
+    uint32_t volatile _unknown0[768];  // 0x0000 - 0x0bfc
+    uint32_t volatile SYS_TIME;        // 0x0c00
+    uint32_t volatile _unknown1[144];  // 0x0c04 - 0x0e40
+    uint32_t volatile HWRNG;           // 0xe44 HW RNG, see http://esp8266-re.foogod.com/wiki/Random_Number_Generator
 } __attribute__ (( packed ));
 
-_Static_assert(sizeof(struct WDEV_REGS) == 0xc04, "WDEV_REGS is the wrong size");
+_Static_assert(sizeof(struct WDEV_REGS) == 0xe48, "WDEV_REGS is the wrong size");
+
+/* Extra paranoid check about the HWRNG address, as if this becomes
+   wrong there will be no obvious symptoms apart from a lack of
+   entropy.
+*/
+_Static_assert(&WDEV.HWRNG == (void*)0x3FF20E44, "HWRNG register is at wrong address");
 
 #endif /* _ESP_WDEV_REGS_H */
+
diff --git a/core/led_debug.s b/core/led_debug.s
index 8196c9e..28caf65 100644
--- a/core/led_debug.s
+++ b/core/led_debug.s
@@ -4,6 +4,8 @@
  *
  * To have this work from initial reset, without needing an iomux call
  * first, choose a pin where iomux defaults to GPIO (ie 0,2,4,5)
+ *
+ * Current sets on=LOW, as the GPIO2 pin is active low
  */
 LED_GPIO=2
 GPIO_DIR_SET = 0x6000030c
@@ -19,11 +21,11 @@ GPIO_OUT_CLEAR = 0x60000308
 .endm
 
 // Turn LED on. rega, regb will be clobbered
-.macro led_on rega, regb
+.macro led_off rega, regb
 	led_op \rega, \regb, GPIO_OUT_SET
 .endm
 
-// Turn LED off. rega, regb will be clobbered
-.macro led_off rega, regb
+// Turn LED on. rega, regb will be clobbered
+.macro led_on rega, regb
 	led_op \rega, \regb, GPIO_OUT_CLEAR
 .endm
diff --git a/examples/cpp_01_tasks/cpp_tasks.cpp b/examples/cpp_01_tasks/cpp_tasks.cpp
index e1ff89f..9e381b9 100644
--- a/examples/cpp_01_tasks/cpp_tasks.cpp
+++ b/examples/cpp_01_tasks/cpp_tasks.cpp
@@ -103,4 +103,4 @@ extern "C" void user_init(void)
     
     task_1.task_create("tsk1");
     task_2.task_create("tsk2");
-}
\ No newline at end of file
+}
diff --git a/examples/experiments/unaligned_load/Makefile b/examples/experiments/unaligned_load/Makefile
new file mode 100644
index 0000000..158bfb3
--- /dev/null
+++ b/examples/experiments/unaligned_load/Makefile
@@ -0,0 +1,2 @@
+PROGRAM=unaligned_load
+include ../../../common.mk
diff --git a/examples/experiments/unaligned_load/unaligned_load.c b/examples/experiments/unaligned_load/unaligned_load.c
new file mode 100644
index 0000000..1574172
--- /dev/null
+++ b/examples/experiments/unaligned_load/unaligned_load.c
@@ -0,0 +1,432 @@
+/* Very basic example that just demonstrates we can run at all!
+ */
+#include "esp/rom.h"
+#include "esp/timer.h"
+#include "espressif/esp_common.h"
+#include "espressif/sdk_private.h"
+#include "FreeRTOS.h"
+#include "task.h"
+#include "queue.h"
+
+#include "string.h"
+#include "strings.h"
+
+#define TESTSTRING "O hai there! %d %d %d"
+
+const char *dramtest = TESTSTRING;
+const __attribute__((section(".iram1.notrodata"))) char iramtest[] = TESTSTRING;
+const __attribute__((section(".text.notrodata"))) char iromtest[] = TESTSTRING;
+
+INLINED uint32_t get_ccount (void)
+{
+    uint32_t ccount;
+    asm volatile ("rsr.ccount %0" : "=a" (ccount));
+    return ccount;
+}
+
+typedef void (* test_with_fn_t)(const char *string);
+
+char buf[64];
+
+void test_memcpy_aligned(const char *string)
+{
+    memcpy(buf, string, 16);
+}
+
+void test_memcpy_unaligned(const char *string)
+{
+    memcpy(buf, string, 15);
+}
+
+void test_memcpy_unaligned2(const char *string)
+{
+    memcpy(buf, string+1, 15);
+}
+
+void test_strcpy(const char *string)
+{
+    strcpy(buf, string);
+}
+
+void test_sprintf(const char *string)
+{
+    sprintf(buf, string, 1, 2, 3);
+}
+
+void test_sprintf_arg(const char *string)
+{
+    sprintf(buf, "%s", string);
+}
+
+void test_naive_strcpy(const char *string)
+{
+    char *to = buf;
+    while((*to++ = *string++))
+        ;
+}
+
+void test_naive_strcpy_a0(const char *string)
+{
+    asm volatile (
+"            mov          a8, %0    \n"
+"            mov          a9, %1    \n"
+"tns_loop%=: l8ui         a0, a9, 0 \n"
+"            addi.n       a9, a9, 1 \n"
+"            s8i          a0, a8, 0 \n"
+"            addi.n       a8, a8, 1 \n"
+"            bnez         a0, tns_loop%=\n"
+        : : "r" (buf), "r" (string) : "a0", "a8", "a9");
+}
+
+void test_naive_strcpy_a2(const char *string)
+{
+    asm volatile (
+"            mov          a8, %0    \n"
+"            mov          a9, %1    \n"
+"tns_loop%=: l8ui         a2, a9, 0 \n"
+"            addi.n       a9, a9, 1 \n"
+"            s8i          a2, a8, 0 \n"
+"            addi.n       a8, a8, 1 \n"
+"            bnez         a2, tns_loop%=\n"
+        : : "r" (buf), "r" (string) : "a2", "a8", "a9");
+}
+
+void test_naive_strcpy_a3(const char *string)
+{
+    asm volatile (
+"            mov          a8, %0    \n"
+"            mov          a9, %1    \n"
+"tns_loop%=: l8ui         a3, a9, 0 \n"
+"            addi.n       a9, a9, 1 \n"
+"            s8i          a3, a8, 0 \n"
+"            addi.n       a8, a8, 1 \n"
+"            bnez         a3, tns_loop%=\n"
+        : : "r" (buf), "r" (string) : "a3", "a8", "a9");
+}
+
+void test_naive_strcpy_a4(const char *string)
+{
+    asm volatile (
+"            mov          a8, %0    \n"
+"            mov          a9, %1    \n"
+"tns_loop%=: l8ui         a4, a9, 0 \n"
+"            addi.n       a9, a9, 1 \n"
+"            s8i          a4, a8, 0 \n"
+"            addi.n       a8, a8, 1 \n"
+"            bnez         a4, tns_loop%=\n"
+        : : "r" (buf), "r" (string) : "a4", "a8", "a9");
+}
+
+void test_naive_strcpy_a5(const char *string)
+{
+    asm volatile (
+"            mov          a8, %0    \n"
+"            mov          a9, %1    \n"
+"tns_loop%=: l8ui         a5, a9, 0 \n"
+"            addi.n       a9, a9, 1 \n"
+"            s8i          a5, a8, 0 \n"
+"            addi.n       a8, a8, 1 \n"
+"            bnez         a5, tns_loop%=\n"
+        : : "r" (buf), "r" (string) : "a5", "a8", "a9");
+}
+
+void test_naive_strcpy_a6(const char *string)
+{
+    asm volatile (
+"            mov          a8, %0    \n"
+"            mov          a9, %1    \n"
+"tns_loop%=: l8ui         a6, a9, 0 \n"
+"            addi.n       a9, a9, 1 \n"
+"            s8i          a6, a8, 0 \n"
+"            addi.n       a8, a8, 1 \n"
+"            bnez         a6, tns_loop%=\n"
+        : : "r" (buf), "r" (string) : "a6", "a8", "a9");
+}
+
+void test_l16si(const char *string)
+{
+    /* This follows most of the l16si path, but as the
+     values in the string are all 7 bit none of them get sign extended.
+
+    See separate test_sign_extension function which validates
+    sign extension works as expected.
+    */
+    int16_t *src_int16 = (int16_t *)string;
+    int32_t *dst_int32 = (int32_t *)buf;
+    dst_int32[0] = src_int16[0];
+    dst_int32[1] = src_int16[1];
+    dst_int32[2] = src_int16[2];
+}
+
+#define TEST_REPEATS 1000
+
+void test_noop(const char *string)
+{
+
+}
+
+uint32_t IRAM run_test(const char *string, test_with_fn_t testfn, const char *testfn_label, uint32_t nullvalue, bool evict_cache)
+{
+    printf(" .. against %30s: ", testfn_label);
+    vPortEnterCritical();
+    uint32_t before = get_ccount();
+    for(int i = 0; i < TEST_REPEATS; i++) {
+        testfn(string);
+        if(evict_cache) {
+            Cache_Read_Disable();
+            Cache_Read_Enable(0,0,1);
+        }
+    }
+    uint32_t after = get_ccount();
+    vPortExitCritical();
+    uint32_t instructions = (after-before)/TEST_REPEATS - nullvalue;
+    printf("%5d instructions\r\n", instructions);
+    return instructions;
+}
+
+void test_string(const char *string, char *label, bool evict_cache)
+{
+    printf("Testing %s (%p) '%s'\r\n", label, string, string);
+    printf("Formats as: '");
+    printf(string, 1, 2, 3);
+    printf("'\r\n");
+    uint32_t nullvalue = run_test(string, test_noop, "null op", 0, evict_cache);
+    run_test(string, test_memcpy_aligned, "memcpy - aligned len", nullvalue, evict_cache);
+    run_test(string, test_memcpy_unaligned, "memcpy - unaligned len", nullvalue, evict_cache);
+    run_test(string, test_memcpy_unaligned2, "memcpy - unaligned start&len", nullvalue, evict_cache);
+    run_test(string, test_strcpy, "strcpy", nullvalue, evict_cache);
+    run_test(string, test_naive_strcpy, "naive strcpy", nullvalue, evict_cache);
+    run_test(string, test_naive_strcpy_a0, "naive strcpy (a0)", nullvalue, evict_cache);
+    run_test(string, test_naive_strcpy_a2, "naive strcpy (a2)", nullvalue, evict_cache);
+    run_test(string, test_naive_strcpy_a3, "naive strcpy (a3)", nullvalue, evict_cache);
+    run_test(string, test_naive_strcpy_a4, "naive strcpy (a4)", nullvalue, evict_cache);
+    run_test(string, test_naive_strcpy_a5, "naive strcpy (a5)", nullvalue, evict_cache);
+    run_test(string, test_naive_strcpy_a6, "naive strcpy (a6)", nullvalue, evict_cache);
+    run_test(string, test_sprintf, "sprintf", nullvalue, evict_cache);
+    run_test(string, test_sprintf_arg, "sprintf format arg", nullvalue, evict_cache);
+    run_test(string, test_l16si, "load as l16si", nullvalue, evict_cache);
+}
+
+static void test_isr();
+static void test_sign_extension();
+static void test_system_interaction();
+void sanity_tests(void);
+
+void user_init(void)
+{
+    sdk_uart_div_modify(0, UART_CLK_FREQ / 115200);
+
+    gpio_enable(2, GPIO_OUTPUT); /* used for LED debug */
+    gpio_write(2, 1); /* active low */
+
+    printf("\r\n\r\nSDK version:%s\r\n", sdk_system_get_sdk_version());
+    sanity_tests();
+    test_string(dramtest, "DRAM", 0);
+    test_string(iramtest, "IRAM", 0);
+    test_string(iromtest, "Cached flash", 0);
+    test_string(iromtest, "'Uncached' flash", 1);
+
+    test_isr();
+    test_sign_extension();
+
+    xTaskHandle taskHandle;
+    xTaskCreate(test_system_interaction, (signed char *)"interactionTask", 256, &taskHandle, 2, NULL);
+}
+
+static volatile bool frc1_ran;
+static volatile bool frc1_finished;
+static volatile char frc1_buf[80];
+
+static void frc1_interrupt_handler(void)
+{
+    frc1_ran = true;
+    timer_set_run(FRC1, false);
+    strcpy((char *)frc1_buf, iramtest);
+    frc1_finished = true;
+}
+
+static void test_isr()
+{
+    printf("Testing behaviour inside ISRs...\r\n");
+    timer_set_interrupts(FRC1, false);
+    timer_set_run(FRC1, false);
+    _xt_isr_attach(INUM_TIMER_FRC1, frc1_interrupt_handler);
+    timer_set_frequency(FRC1, 1000);
+    timer_set_interrupts(FRC1, true);
+    timer_set_run(FRC1, true);
+    sdk_os_delay_us(2000);
+
+    if(!frc1_ran)
+        printf("ERROR: FRC1 timer exception never fired.\r\n");
+    else if(!frc1_finished)
+        printf("ERROR: FRC1 timer exception never finished.\r\n");
+    else if(strcmp((char *)frc1_buf, iramtest))
+        printf("ERROR: FRC1 strcpy from IRAM failed.\r\n");
+    else
+        printf("PASSED\r\n");
+}
+
+const volatile __attribute__((section(".iram1.notliterals"))) int16_t unsigned_shorts[] = { -3, -4, -5, -32767, 44 };
+
+static void test_sign_extension()
+{
+    /* this step seems to be necessary so the compiler will actually generate l16si */
+    int16_t *shorts_p = (int16_t *)unsigned_shorts;
+    if(shorts_p[0] == -3 && shorts_p[1] == -4 && shorts_p[2] == -5 && shorts_p[3] == -32767 && shorts_p[4] == 44)
+    {
+        printf("l16si sign extension PASSED.\r\n");
+    } else {
+        printf("ERROR: l16si sign extension failed. Got values %d %d %d %d %d\r\n", shorts_p[0], shorts_p[1], shorts_p[2], shorts_p[3], shorts_p[4]);
+    }
+}
+
+
+/* test that running unaligned loads in a running FreeRTOS system doesn't break things
+
+   The following tests run inside a FreeRTOS task, after everything else.
+*/
+static void test_system_interaction()
+{
+    uint32_t start = xTaskGetTickCount();
+    printf("Starting system/timer interaction test (takes approx 30 seconds)...\n");
+    for(int i = 0; i < 200*1000; i++) {
+        test_naive_strcpy_a0(iromtest);
+        test_naive_strcpy_a2(iromtest);
+        test_naive_strcpy_a3(iromtest);
+        test_naive_strcpy_a4(iromtest);
+        test_naive_strcpy_a5(iromtest);
+        test_naive_strcpy_a6(iromtest);
+        /*
+        const volatile char *string = iromtest;
+        volatile char *to = dest;
+        while((*to++ = *string++))
+            ;
+        */
+    }
+    uint32_t ticks = xTaskGetTickCount() - start;
+    printf("Timer interaction test PASSED after %dms.\n", ticks*portTICK_RATE_MS);
+    while(1) {}
+}
+
+/* The following "sanity tests" are designed to try to execute every code path
+ * of the LoadStoreError handler, with a variety of offsets and data values
+ * designed to catch any mask/shift errors, sign-extension bugs, etc */
+
+/* (Contrary to expectations, 'mov a15, a15' in Xtensa is not technically a
+ * no-op, but is officially "undefined and reserved for future use", so we need
+ * a special case in the case where reg == "a15" so we don't end up generating
+ * those opcodes.  GCC is smart enough to optimize away the whole conditional
+ * and just insert the correct asm block, since `reg` is a static argument.) */
+#define LOAD_VIA_REG(op, reg, addr, var) \
+    if (strcmp(reg, "a15")) { \
+        asm volatile ( \
+        "mov a15, " reg "\n\t" \
+        op " " reg ", %1, 0\n\t" \
+        "mov %0, " reg "\n\t" \
+        "mov " reg ", a15\n\t" \
+        : "=r" (var) : "r" (addr) : "a15" ); \
+    } else { \
+        asm volatile ( \
+        op " " reg ", %1, 0\n\t" \
+        "mov %0, " reg "\n\t" \
+        : "=r" (var) : "r" (addr) : "a15" ); \
+    }
+
+#define TEST_LOAD(op, reg, addr, value) \
+    { \
+        int32_t result; \
+        LOAD_VIA_REG(op, reg, addr, result); \
+        if (result != value) sanity_test_failed(op, reg, addr, value, result); \
+    }
+
+void sanity_test_failed(const char *testname, const char *reg, const void *addr, int32_t value, int32_t result) {
+    uint32_t actual_data = *(uint32_t *)((uint32_t)addr & 0xfffffffc);
+
+    printf("*** SANITY TEST FAILED: '%s %s' from %p (underlying 32-bit value: 0x%x): Expected 0x%08x (%d), got 0x%08x (%d)\n", testname, reg, addr, actual_data, value, value, result, result);
+}
+
+const __attribute__((section(".iram1.notrodata"))) char sanity_test_data[] = {
+    0x01, 0x55, 0x7e, 0x2a, 0x81, 0xd5, 0xfe, 0xaa
+};
+
+void sanity_test_l8ui(const void *addr, int32_t value) {
+    TEST_LOAD("l8ui", "a0", addr, value);
+    TEST_LOAD("l8ui", "a1", addr, value);
+    TEST_LOAD("l8ui", "a2", addr, value);
+    TEST_LOAD("l8ui", "a3", addr, value);
+    TEST_LOAD("l8ui", "a4", addr, value);
+    TEST_LOAD("l8ui", "a5", addr, value);
+    TEST_LOAD("l8ui", "a6", addr, value);
+    TEST_LOAD("l8ui", "a7", addr, value);
+    TEST_LOAD("l8ui", "a8", addr, value);
+    TEST_LOAD("l8ui", "a9", addr, value);
+    TEST_LOAD("l8ui", "a10", addr, value);
+    TEST_LOAD("l8ui", "a11", addr, value);
+    TEST_LOAD("l8ui", "a12", addr, value);
+    TEST_LOAD("l8ui", "a13", addr, value);
+    TEST_LOAD("l8ui", "a14", addr, value);
+    TEST_LOAD("l8ui", "a15", addr, value);
+}
+
+void sanity_test_l16ui(const void *addr, int32_t value) {
+    TEST_LOAD("l16ui", "a0", addr, value);
+    TEST_LOAD("l16ui", "a1", addr, value);
+    TEST_LOAD("l16ui", "a2", addr, value);
+    TEST_LOAD("l16ui", "a3", addr, value);
+    TEST_LOAD("l16ui", "a4", addr, value);
+    TEST_LOAD("l16ui", "a5", addr, value);
+    TEST_LOAD("l16ui", "a6", addr, value);
+    TEST_LOAD("l16ui", "a7", addr, value);
+    TEST_LOAD("l16ui", "a8", addr, value);
+    TEST_LOAD("l16ui", "a9", addr, value);
+    TEST_LOAD("l16ui", "a10", addr, value);
+    TEST_LOAD("l16ui", "a11", addr, value);
+    TEST_LOAD("l16ui", "a12", addr, value);
+    TEST_LOAD("l16ui", "a13", addr, value);
+    TEST_LOAD("l16ui", "a14", addr, value);
+    TEST_LOAD("l16ui", "a15", addr, value);
+}
+
+void sanity_test_l16si(const void *addr, int32_t value) {
+    TEST_LOAD("l16si", "a0", addr, value);
+    TEST_LOAD("l16si", "a1", addr, value);
+    TEST_LOAD("l16si", "a2", addr, value);
+    TEST_LOAD("l16si", "a3", addr, value);
+    TEST_LOAD("l16si", "a4", addr, value);
+    TEST_LOAD("l16si", "a5", addr, value);
+    TEST_LOAD("l16si", "a6", addr, value);
+    TEST_LOAD("l16si", "a7", addr, value);
+    TEST_LOAD("l16si", "a8", addr, value);
+    TEST_LOAD("l16si", "a9", addr, value);
+    TEST_LOAD("l16si", "a10", addr, value);
+    TEST_LOAD("l16si", "a11", addr, value);
+    TEST_LOAD("l16si", "a12", addr, value);
+    TEST_LOAD("l16si", "a13", addr, value);
+    TEST_LOAD("l16si", "a14", addr, value);
+    TEST_LOAD("l16si", "a15", addr, value);
+}
+
+void sanity_tests(void) {
+    printf("== Performing sanity tests (sanity_test_data @ %p)...\n", sanity_test_data);
+
+    sanity_test_l8ui(sanity_test_data + 0, 0x01);
+    sanity_test_l8ui(sanity_test_data + 1, 0x55);
+    sanity_test_l8ui(sanity_test_data + 2, 0x7e);
+    sanity_test_l8ui(sanity_test_data + 3, 0x2a);
+    sanity_test_l8ui(sanity_test_data + 4, 0x81);
+    sanity_test_l8ui(sanity_test_data + 5, 0xd5);
+    sanity_test_l8ui(sanity_test_data + 6, 0xfe);
+    sanity_test_l8ui(sanity_test_data + 7, 0xaa);
+
+    sanity_test_l16ui(sanity_test_data + 0, 0x5501);
+    sanity_test_l16ui(sanity_test_data + 2, 0x2a7e);
+    sanity_test_l16ui(sanity_test_data + 4, 0xd581);
+    sanity_test_l16ui(sanity_test_data + 6, 0xaafe);
+
+    sanity_test_l16si(sanity_test_data + 0, 0x5501);
+    sanity_test_l16si(sanity_test_data + 2, 0x2a7e);
+    sanity_test_l16si(sanity_test_data + 4, -10879);
+    sanity_test_l16si(sanity_test_data + 6, -21762);
+
+    printf("== Sanity tests completed.\n");
+}
diff --git a/examples/http_get_mbedtls/Makefile b/examples/http_get_mbedtls/Makefile
new file mode 100644
index 0000000..fc9a4fa
--- /dev/null
+++ b/examples/http_get_mbedtls/Makefile
@@ -0,0 +1,4 @@
+PROGRAM=http_get_mbedtls
+COMPONENTS = FreeRTOS lwip core extras/mbedtls
+
+include ../../common.mk
diff --git a/examples/http_get_mbedtls/cert.c b/examples/http_get_mbedtls/cert.c
new file mode 100644
index 0000000..a0050a6
--- /dev/null
+++ b/examples/http_get_mbedtls/cert.c
@@ -0,0 +1,39 @@
+/* This is the root certificate for the CA trust chain of
+   www.howsmyssl.com in PEM format, as dumped via:
+
+   openssl s_client -showcerts -connect www.howsmyssl.com:443 </dev/null
+
+   The root cert is the last cert in the chain output by the server.
+*/
+#include <stdio.h>
+#include <stdint.h>
+#include <string.h>
+
+const char *server_root_cert = "-----BEGIN CERTIFICATE-----\r\n"
+"MIIEWTCCA0GgAwIBAgIDAjpjMA0GCSqGSIb3DQEBBQUAMEIxCzAJBgNVBAYTAlVT\r\n"
+"MRYwFAYDVQQKEw1HZW9UcnVzdCBJbmMuMRswGQYDVQQDExJHZW9UcnVzdCBHbG9i\r\n"
+"YWwgQ0EwHhcNMTIwODI3MjA0MDQwWhcNMjIwNTIwMjA0MDQwWjBEMQswCQYDVQQG\r\n"
+"EwJVUzEWMBQGA1UEChMNR2VvVHJ1c3QgSW5jLjEdMBsGA1UEAxMUR2VvVHJ1c3Qg\r\n"
+"U1NMIENBIC0gRzIwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQC5J/lP\r\n"
+"2Pa3FT+Pzc7WjRxr/X/aVCFOA9jK0HJSFbjJgltYeYT/JHJv8ml/vJbZmnrDPqnP\r\n"
+"UCITDoYZ2+hJ74vm1kfy/XNFCK6PrF62+J589xD/kkNm7xzU7qFGiBGJSXl6Jc5L\r\n"
+"avDXHHYaKTzJ5P0ehdzgMWUFRxasCgdLLnBeawanazpsrwUSxLIRJdY+lynwg2xX\r\n"
+"HNil78zs/dYS8T/bQLSuDxjTxa9Akl0HXk7+Yhc3iemLdCai7bgK52wVWzWQct3Y\r\n"
+"TSHUQCNcj+6AMRaraFX0DjtU6QRN8MxOgV7pb1JpTr6mFm1C9VH/4AtWPJhPc48O\r\n"
+"bxoj8cnI2d+87FLXAgMBAAGjggFUMIIBUDAfBgNVHSMEGDAWgBTAephojYn7qwVk\r\n"
+"DBF9qn1luMrMTjAdBgNVHQ4EFgQUEUrQcznVW2kIXLo9v2SaqIscVbwwEgYDVR0T\r\n"
+"AQH/BAgwBgEB/wIBADAOBgNVHQ8BAf8EBAMCAQYwOgYDVR0fBDMwMTAvoC2gK4Yp\r\n"
+"aHR0cDovL2NybC5nZW90cnVzdC5jb20vY3Jscy9ndGdsb2JhbC5jcmwwNAYIKwYB\r\n"
+"BQUHAQEEKDAmMCQGCCsGAQUFBzABhhhodHRwOi8vb2NzcC5nZW90cnVzdC5jb20w\r\n"
+"TAYDVR0gBEUwQzBBBgpghkgBhvhFAQc2MDMwMQYIKwYBBQUHAgEWJWh0dHA6Ly93\r\n"
+"d3cuZ2VvdHJ1c3QuY29tL3Jlc291cmNlcy9jcHMwKgYDVR0RBCMwIaQfMB0xGzAZ\r\n"
+"BgNVBAMTElZlcmlTaWduTVBLSS0yLTI1NDANBgkqhkiG9w0BAQUFAAOCAQEAPOU9\r\n"
+"WhuiNyrjRs82lhg8e/GExVeGd0CdNfAS8HgY+yKk3phLeIHmTYbjkQ9C47ncoNb/\r\n"
+"qfixeZeZ0cNsQqWSlOBdDDMYJckrlVPg5akMfUf+f1ExRF73Kh41opQy98nuwLbG\r\n"
+"mqzemSFqI6A4ZO6jxIhzMjtQzr+t03UepvTp+UJrYLLdRf1dVwjOLVDmEjIWE4ry\r\n"
+"lKKbR6iGf9mY5ffldnRk2JG8hBYo2CVEMH6C2Kyx5MDkFWzbtiQnAioBEoW6MYhY\r\n"
+"R3TjuNJkpsMyWS4pS0XxW4lJLoKaxhgVRNAuZAEVaDj59vlmAwxVG52/AECu8Egn\r\n"
+"TOCAXi25KhV6vGb4NQ==\r\n"
+"-----END CERTIFICATE-----\r\n";
+
+
diff --git a/examples/http_get_mbedtls/http_get_mbedtls.c b/examples/http_get_mbedtls/http_get_mbedtls.c
new file mode 100644
index 0000000..d1fbf0d
--- /dev/null
+++ b/examples/http_get_mbedtls/http_get_mbedtls.c
@@ -0,0 +1,347 @@
+/* http_get_mbedtls - HTTPS version of the http_get example, using mbed TLS.
+ *
+ * Retrieves a JSON response from the howsmyssl.com API via HTTPS over TLS v1.2.
+ *
+ * Validates the server's certificate using the root CA loaded (in PEM format) in cert.c.
+ *
+ * Adapted from the ssl_client1 example in mbedtls.
+ *
+ * Original Copyright (C) 2006-2015, ARM Limited, All Rights Reserved, Apache 2.0 License.
+ * Additions Copyright (C) 2015 Angus Gratton, Apache 2.0 License.
+ */
+#include "espressif/esp_common.h"
+#include "espressif/sdk_private.h"
+
+#include <string.h>
+
+#include "FreeRTOS.h"
+#include "task.h"
+
+#include "lwip/err.h"
+#include "lwip/sockets.h"
+#include "lwip/sys.h"
+#include "lwip/netdb.h"
+#include "lwip/dns.h"
+#include "lwip/api.h"
+
+#include "ssid_config.h"
+
+/* mbedtls/config.h MUST appear before all other mbedtls headers, or
+   you'll get the default config.
+
+   (Although mostly that isn't a big problem, you just might get
+   errors at link time if functions don't exist.) */
+#include "mbedtls/config.h"
+
+#include "mbedtls/net.h"
+#include "mbedtls/debug.h"
+#include "mbedtls/ssl.h"
+#include "mbedtls/entropy.h"
+#include "mbedtls/ctr_drbg.h"
+#include "mbedtls/error.h"
+#include "mbedtls/certs.h"
+
+#define WEB_SERVER "howsmyssl.com"
+#define WEB_PORT "443"
+#define WEB_URL "https://www.howsmyssl.com/a/check"
+
+#define GET_REQUEST "GET "WEB_URL" HTTP/1.1\n\n"
+
+/* Root cert for howsmyssl.com, stored in cert.c */
+extern const char *server_root_cert;
+
+/* MBEDTLS_DEBUG_C disabled by default to save substantial bloating of
+ * firmware, define it in
+ * examples/http_get_mbedtls/include/mbedtls/config.h if you'd like
+ * debugging output.
+ */
+#ifdef MBEDTLS_DEBUG_C
+
+
+/* Increase this value to see more TLS debug details,
+   0 prints nothing, 1 will print any errors, 4 will print _everything_
+*/
+#define DEBUG_LEVEL 4
+
+static void my_debug(void *ctx, int level,
+                     const char *file, int line,
+                     const char *str)
+{
+    ((void) level);
+
+    /* Shorten 'file' from the whole file path to just the filename
+
+       This is a bit wasteful because the macros are compiled in with
+       the full _FILE_ path in each case, so the firmware is bloated out
+       by a few kb. But there's not a lot we can do about it...
+    */
+    char *file_sep = rindex(file, '/');
+    if(file_sep)
+        file = file_sep+1;
+
+    printf("%s:%04d: %s", file, line, str);
+    fflush(stdout);
+}
+#endif
+
+void http_get_task(void *pvParameters)
+{
+    int successes = 0, failures = 0, ret;
+    printf("HTTP get task starting...\n");
+
+    uint32_t flags;
+    unsigned char buf[1024];
+    const char *pers = "ssl_client1";
+
+    mbedtls_entropy_context entropy;
+    mbedtls_ctr_drbg_context ctr_drbg;
+    mbedtls_ssl_context ssl;
+    mbedtls_x509_crt cacert;
+    mbedtls_ssl_config conf;
+    mbedtls_net_context server_fd;
+
+    /*
+     * 0. Initialize the RNG and the session data
+     */
+    mbedtls_ssl_init(&ssl);
+    mbedtls_x509_crt_init(&cacert);
+    mbedtls_ctr_drbg_init(&ctr_drbg);
+    printf("\n  . Seeding the random number generator...");
+    fflush(stdout);
+
+    mbedtls_ssl_config_init(&conf);
+
+    mbedtls_entropy_init(&entropy);
+    if((ret = mbedtls_ctr_drbg_seed(&ctr_drbg, mbedtls_entropy_func, &entropy,
+                                    (const unsigned char *) pers,
+                                    strlen(pers))) != 0)
+    {
+        printf(" failed\n  ! mbedtls_ctr_drbg_seed returned %d\n", ret);
+        while(1) {} /* todo: replace with abort() */
+    }
+
+    printf(" ok\n");
+
+    /*
+     * 0. Initialize certificates
+     */
+    printf("  . Loading the CA root certificate ...");
+    fflush(stdout);
+
+    ret = mbedtls_x509_crt_parse(&cacert, (uint8_t*)server_root_cert, strlen(server_root_cert)+1);
+    if(ret < 0)
+    {
+        printf(" failed\n  !  mbedtls_x509_crt_parse returned -0x%x\n\n", -ret);
+        while(1) {} /* todo: replace with abort() */
+    }
+
+    printf(" ok (%d skipped)\n", ret);
+
+    /* Hostname set here should match CN in server certificate */
+    if((ret = mbedtls_ssl_set_hostname(&ssl, WEB_SERVER)) != 0)
+    {
+        printf(" failed\n  ! mbedtls_ssl_set_hostname returned %d\n\n", ret);
+        while(1) {} /* todo: replace with abort() */
+    }
+
+    /*
+     * 2. Setup stuff
+     */
+    printf("  . Setting up the SSL/TLS structure...");
+    fflush(stdout);
+
+    if((ret = mbedtls_ssl_config_defaults(&conf,
+                                          MBEDTLS_SSL_IS_CLIENT,
+                                          MBEDTLS_SSL_TRANSPORT_STREAM,
+                                          MBEDTLS_SSL_PRESET_DEFAULT)) != 0)
+    {
+        printf(" failed\n  ! mbedtls_ssl_config_defaults returned %d\n\n", ret);
+        goto exit;
+    }
+
+    printf(" ok\n");
+
+    /* OPTIONAL is not optimal for security, in this example it will print
+       a warning if CA verification fails but it will continue to connect.
+    */
+    mbedtls_ssl_conf_authmode(&conf, MBEDTLS_SSL_VERIFY_OPTIONAL);
+    mbedtls_ssl_conf_ca_chain(&conf, &cacert, NULL);
+    mbedtls_ssl_conf_rng(&conf, mbedtls_ctr_drbg_random, &ctr_drbg);
+#ifdef MBEDTLS_DEBUG_C
+    mbedtls_debug_set_threshold(DEBUG_LEVEL);
+    mbedtls_ssl_conf_dbg(&conf, my_debug, stdout);
+#endif
+
+    if((ret = mbedtls_ssl_setup(&ssl, &conf)) != 0)
+    {
+        printf(" failed\n  ! mbedtls_ssl_setup returned %d\n\n", ret);
+        goto exit;
+    }
+
+    /* Wait until we can resolve the DNS for the server, as an indication
+       our network is probably working...
+    */
+    printf("Waiting for server DNS to resolve... ");
+    fflush(stdout);
+    err_t dns_err;
+    ip_addr_t host_ip;
+    do {
+        vTaskDelay(500 / portTICK_RATE_MS);
+        dns_err = netconn_gethostbyname(WEB_SERVER, &host_ip);
+    } while(dns_err != ERR_OK);
+    printf("done.\n");
+
+    while(1) {
+        mbedtls_net_init(&server_fd);
+        printf("top of loop, free heap = %u\n", xPortGetFreeHeapSize());
+        /*
+         * 1. Start the connection
+         */
+        printf("  . Connecting to %s:%s...", WEB_SERVER, WEB_PORT);
+        fflush(stdout);
+
+        if((ret = mbedtls_net_connect(&server_fd, WEB_SERVER,
+                                      WEB_PORT, MBEDTLS_NET_PROTO_TCP)) != 0)
+        {
+            printf(" failed\n  ! mbedtls_net_connect returned %d\n\n", ret);
+            goto exit;
+        }
+
+        printf(" ok\n");
+
+        mbedtls_ssl_set_bio(&ssl, &server_fd, mbedtls_net_send, mbedtls_net_recv, NULL);
+
+        /*
+         * 4. Handshake
+         */
+        printf("  . Performing the SSL/TLS handshake...");
+        fflush(stdout);
+
+        while((ret = mbedtls_ssl_handshake(&ssl)) != 0)
+        {
+            if(ret != MBEDTLS_ERR_SSL_WANT_READ && ret != MBEDTLS_ERR_SSL_WANT_WRITE)
+            {
+                printf(" failed\n  ! mbedtls_ssl_handshake returned -0x%x\n\n", -ret);
+                goto exit;
+            }
+        }
+
+        printf(" ok\n");
+
+        /*
+         * 5. Verify the server certificate
+         */
+        printf("  . Verifying peer X.509 certificate...");
+
+        /* In real life, we probably want to bail out when ret != 0 */
+        if((flags = mbedtls_ssl_get_verify_result(&ssl)) != 0)
+        {
+            char vrfy_buf[512];
+
+            printf(" failed\n");
+
+            mbedtls_x509_crt_verify_info(vrfy_buf, sizeof(vrfy_buf), "  ! ", flags);
+
+            printf("%s\n", vrfy_buf);
+        }
+        else
+            printf(" ok\n");
+
+        /*
+         * 3. Write the GET request
+         */
+        printf("  > Write to server:");
+        fflush(stdout);
+
+        int len = sprintf((char *) buf, GET_REQUEST);
+
+        while((ret = mbedtls_ssl_write(&ssl, buf, len)) <= 0)
+        {
+            if(ret != MBEDTLS_ERR_SSL_WANT_READ && ret != MBEDTLS_ERR_SSL_WANT_WRITE)
+            {
+                printf(" failed\n  ! mbedtls_ssl_write returned %d\n\n", ret);
+                goto exit;
+            }
+        }
+
+        len = ret;
+        printf(" %d bytes written\n\n%s", len, (char *) buf);
+
+        /*
+         * 7. Read the HTTP response
+         */
+        printf("  < Read from server:");
+        fflush(stdout);
+
+        do
+        {
+            len = sizeof(buf) - 1;
+            memset(buf, 0, sizeof(buf));
+            ret = mbedtls_ssl_read(&ssl, buf, len);
+
+            if(ret == MBEDTLS_ERR_SSL_WANT_READ || ret == MBEDTLS_ERR_SSL_WANT_WRITE)
+                continue;
+
+            if(ret == MBEDTLS_ERR_SSL_PEER_CLOSE_NOTIFY) {
+                ret = 0;
+                break;
+            }
+
+            if(ret < 0)
+            {
+                printf("failed\n  ! mbedtls_ssl_read returned %d\n\n", ret);
+                break;
+            }
+
+            if(ret == 0)
+            {
+                printf("\n\nEOF\n\n");
+                break;
+            }
+
+            len = ret;
+            printf(" %d bytes read\n\n%s", len, (char *) buf);
+        } while(1);
+
+        mbedtls_ssl_close_notify(&ssl);
+
+    exit:
+        mbedtls_ssl_session_reset(&ssl);
+        mbedtls_net_free(&server_fd);
+
+        if(ret != 0)
+        {
+            char error_buf[100];
+            mbedtls_strerror(ret, error_buf, 100);
+            printf("\n\nLast error was: %d - %s\n\n", ret, error_buf);
+            failures++;
+        } else {
+            successes++;
+        }
+
+        printf("\n\nsuccesses = %d failures = %d\n", successes, failures);
+        for(int countdown = successes ? 10 : 5; countdown >= 0; countdown--) {
+            printf("%d... ", countdown);
+            fflush(stdout);
+            vTaskDelay(1000 / portTICK_RATE_MS);
+        }
+        printf("\nStarting again!\n");
+    }
+}
+
+void user_init(void)
+{
+    sdk_uart_div_modify(0, UART_CLK_FREQ / 115200);
+    printf("SDK version:%s\n", sdk_system_get_sdk_version());
+
+    struct sdk_station_config config = {
+        .ssid = WIFI_SSID,
+        .password = WIFI_PASS,
+    };
+
+    /* required to call wifi_set_opmode before station_set_config */
+    sdk_wifi_set_opmode(STATION_MODE);
+    sdk_wifi_station_set_config(&config);
+
+    xTaskCreate(&http_get_task, (signed char *)"get_task", 2048, NULL, 2, NULL);
+}
diff --git a/examples/http_get_mbedtls/include/mbedtls/config.h b/examples/http_get_mbedtls/include/mbedtls/config.h
new file mode 100644
index 0000000..2674292
--- /dev/null
+++ b/examples/http_get_mbedtls/include/mbedtls/config.h
@@ -0,0 +1,27 @@
+/* Special mbedTLS config file for http_get_mbedtls example,
+   overrides supported cipher suite list.
+
+   Overriding the set of cipher suites saves small amounts of ROM and
+   RAM, and is a good practice in general if you know what server(s)
+   you want to connect to.
+
+  However it's extra important here because the howsmyssl API sends
+  back the list of ciphers we send it as a JSON list in the, and we
+  only have a 4096kB receive buffer. If the server supported maximum
+  fragment length option then we wouldn't have this problem either,
+  but we do so this is a good workaround.
+
+  The ciphers chosen below are common ECDHE ciphers, the same ones
+  Firefox uses when connecting to a TLSv1.2 server.
+*/
+#ifndef MBEDTLS_CONFIG_H
+
+/* include_next picks up default config from extras/mbedtls/include/mbedtls/config.h */
+#include_next<mbedtls/config.h>
+
+#define MBEDTLS_SSL_CIPHERSUITES MBEDTLS_TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256,MBEDTLS_TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256,MBEDTLS_TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA,MBEDTLS_TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA,MBEDTLS_TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA,MBEDTLS_TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA
+
+/* uncomment next line to include debug output from example */
+//#define MBEDTLS_DEBUG_C
+
+#endif
diff --git a/examples/http_get_ssl/Makefile b/examples/http_get_ssl/Makefile
deleted file mode 100644
index fe64c2c..0000000
--- a/examples/http_get_ssl/Makefile
+++ /dev/null
@@ -1,2 +0,0 @@
-PROGRAM=http_get_ssl
-include ../../common.mk
diff --git a/examples/http_get_ssl/http_get_ssl.c b/examples/http_get_ssl/http_get_ssl.c
deleted file mode 100644
index 22351b9..0000000
--- a/examples/http_get_ssl/http_get_ssl.c
+++ /dev/null
@@ -1,223 +0,0 @@
-/* http_get_ssl - HTTPS version of the http_get example.
- *
- * Retrieves a web page over HTTPS (TLS) using GET.
- *
- * Does not validate server certificate.
- *
- * This sample code is in the public domain.,
- */
-#include "espressif/esp_common.h"
-#include "espressif/sdk_private.h"
-
-#include <string.h>
-
-#include "FreeRTOS.h"
-#include "task.h"
-
-#include "lwip/err.h"
-#include "lwip/sockets.h"
-#include "lwip/sys.h"
-#include "lwip/netdb.h"
-#include "lwip/dns.h"
-
-#include "ssl.h"
-
-#include "ssid_config.h"
-
-#define WEB_SERVER "192.168.0.18"
-#define WEB_PORT "8000"
-#define WEB_URL "/test"
-
-static void display_cipher(SSL *ssl);
-static void display_session_id(SSL *ssl);
-
-void http_get_task(void *pvParameters)
-{
-    int successes = 0, failures = 0;
-    SSL_CTX *ssl_ctx;
-    uint32_t options = SSL_SERVER_VERIFY_LATER|SSL_DISPLAY_CERTS;
-    printf("HTTP get task starting...\r\n");
-
-    printf("free heap = %u\r\n", xPortGetFreeHeapSize());
-    if ((ssl_ctx = ssl_ctx_new(options, SSL_DEFAULT_CLNT_SESS)) == NULL)
-    {
-        printf("Error: SSL Client context is invalid\n");
-        while(1) {}
-    }
-    printf("Got SSL context.");
-
-    while(1) {
-        const struct addrinfo hints = {
-            .ai_family = AF_INET,
-            .ai_socktype = SOCK_STREAM,
-        };
-        struct addrinfo *res;
-
-        printf("top of loop, free heap = %u\r\n", xPortGetFreeHeapSize());
-
-        printf("Running DNS lookup for %s...\r\n", WEB_SERVER);
-        int err = getaddrinfo(WEB_SERVER, WEB_PORT, &hints, &res);
-
-        if(err != 0 || res == NULL) {
-            printf("DNS lookup failed err=%d res=%p\r\n", err, res);
-            if(res)
-                freeaddrinfo(res);
-            vTaskDelay(1000 / portTICK_RATE_MS);
-            failures++;
-            continue;
-        }
-        /* Note: inet_ntoa is non-reentrant, look at ipaddr_ntoa_r for "real" code */
-        struct in_addr *addr = &((struct sockaddr_in *)res->ai_addr)->sin_addr;
-        printf("DNS lookup succeeded. IP=%s\r\n", inet_ntoa(*addr));
-
-        int s = socket(res->ai_family, res->ai_socktype, 0);
-        if(s < 0) {
-            printf("... Failed to allocate socket.\r\n");
-            freeaddrinfo(res);
-            vTaskDelay(1000 / portTICK_RATE_MS);
-            failures++;
-            continue;
-        }
-
-        printf("... allocated socket\r\n");
-
-        if(connect(s, res->ai_addr, res->ai_addrlen) != 0) {
-            close(s);
-            freeaddrinfo(res);
-            printf("... socket connect failed.\r\n");
-            vTaskDelay(4000 / portTICK_RATE_MS);
-            failures++;
-            continue;
-        }
-
-        printf("... connected. starting TLS session...\r\n");
-        freeaddrinfo(res);
-
-        SSL *ssl = ssl_client_new(ssl_ctx, s, NULL, 0);
-        printf("initial status %p %d\r\n", ssl, ssl_handshake_status(ssl));
-        if((err = ssl_handshake_status(ssl)) != SSL_OK) {
-            ssl_free(ssl);
-            close(s);
-            printf("SSL handshake failed. :( %d\r\n", err);
-            vTaskDelay(4000 / portTICK_RATE_MS);
-            failures++;
-            continue;
-        }
-
-        const char *common_name = ssl_get_cert_dn(ssl,
-                                                  SSL_X509_CERT_COMMON_NAME);
-        if (common_name)
-        {
-            printf("Common Name:\t\t\t%s\n", common_name);
-        }
-
-        display_session_id(ssl);
-        display_cipher(ssl);
-
-        const char *req =
-            "GET "WEB_URL"\r\n"
-            "User-Agent: esp-open-rtos/0.1 esp8266\r\n"
-            "\r\n";
-        if (ssl_write(ssl, (uint8_t *)req, strlen(req)) < 0) {
-            printf("... socket send failed\r\n");
-            ssl_free(ssl);
-            close(s);
-            vTaskDelay(4000 / portTICK_RATE_MS);
-            failures++;
-            continue;
-        }
-        printf("... socket send success\r\n");
-
-        uint8_t *recv_buf;
-        int r;
-        do {
-            r = ssl_read(ssl, &recv_buf);
-            for(int i = 0; i < r; i++)
-                printf("%c", recv_buf[i]);
-        } while(r > 0);
-
-        printf("... done reading from socket. Last read return=%d errno=%d\r\n", r, errno);
-        if(r != 0)
-            failures++;
-        else
-            successes++;
-        ssl_free(ssl);
-        close(s);
-        printf("successes = %d failures = %d\r\n", successes, failures);
-        for(int countdown = 10; countdown >= 0; countdown--) {
-            printf("%d... ", countdown);
-            vTaskDelay(1000 / portTICK_RATE_MS);
-        }
-        printf("\r\nStarting again!\r\n");
-    }
-}
-
-void user_init(void)
-{
-    sdk_uart_div_modify(0, UART_CLK_FREQ / 115200);
-    printf("SDK version:%s\n", sdk_system_get_sdk_version());
-
-    struct sdk_station_config config = {
-        .ssid = WIFI_SSID,
-        .password = WIFI_PASS,
-    };
-
-    /* required to call wifi_set_opmode before station_set_config */
-    sdk_wifi_set_opmode(STATION_MODE);
-    sdk_wifi_station_set_config(&config);
-
-    xTaskCreate(&http_get_task, (signed char *)"get_task", 2048, NULL, 2, NULL);
-}
-
-/**
- * Display what session id we have.
- */
-static void display_session_id(SSL *ssl)
-{
-    int i;
-    const uint8_t *session_id = ssl_get_session_id(ssl);
-    int sess_id_size = ssl_get_session_id_size(ssl);
-
-    if (sess_id_size > 0)
-    {
-        printf("-----BEGIN SSL SESSION PARAMETERS-----\n");
-        for (i = 0; i < sess_id_size; i++)
-        {
-            printf("%02x", session_id[i]);
-        }
-
-        printf("\n-----END SSL SESSION PARAMETERS-----\n");
-    }
-}
-
-/**
- * Display what cipher we are using
- */
-static void display_cipher(SSL *ssl)
-{
-    printf("CIPHER is ");
-    switch (ssl_get_cipher_id(ssl))
-    {
-    case SSL_AES128_SHA:
-        printf("AES128-SHA");
-        break;
-
-    case SSL_AES256_SHA:
-        printf("AES256-SHA");
-        break;
-
-    case SSL_RC4_128_SHA:
-        printf("RC4-SHA");
-        break;
-
-    case SSL_RC4_128_MD5:
-        printf("RC4-MD5");
-        break;
-
-    default:
-        printf("Unknown - %d", ssl_get_cipher_id(ssl));
-        break;
-    }
-
-    printf("\n");
-}
diff --git a/examples/tests/hmac_test_vectors/Makefile b/examples/tests/hmac_test_vectors/Makefile
index ea2761a..f314ff7 100644
--- a/examples/tests/hmac_test_vectors/Makefile
+++ b/examples/tests/hmac_test_vectors/Makefile
@@ -1,2 +1,3 @@
 PROGRAM=hmac_test
+EXTRA_COMPONENTS=extras/mbedtls
 include ../../../common.mk
diff --git a/examples/tests/hmac_test_vectors/hmac_test_vectors.c b/examples/tests/hmac_test_vectors/hmac_test_vectors.c
index 426f217..a6a20f9 100644
--- a/examples/tests/hmac_test_vectors/hmac_test_vectors.c
+++ b/examples/tests/hmac_test_vectors/hmac_test_vectors.c
@@ -10,7 +10,7 @@
 #include "espressif/esp_common.h"
 #include "espressif/sdk_private.h"
 #include "FreeRTOS.h"
-#include "ssl.h"
+#include "mbedtls/md.h"
 
 #include <string.h>
 
@@ -31,9 +31,7 @@ static const uint8_t aa_80_times[] = {0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0x
 				      0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,
 				      0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa};
 
-/* NOTE: Vectors 6 & 7 currently cause a fault as the axTLS
-   routines don't support keys longer than the block size. */
-const uint8_t NUM_MD5_VECTORS = 5;
+const uint8_t NUM_MD5_VECTORS = 7;
 
 static const struct test_vector md5_vectors[] = {
     { /* vector 1*/
@@ -88,15 +86,30 @@ static const struct test_vector md5_vectors[] = {
     },
 };
 
+static void print_blob(const char *label, const uint8_t *data, const uint32_t len)
+{
+    printf("%s:", label);
+    for(int i = 0; i < len; i++) {
+        if(i % 16 == 0)
+            printf("\n%02x:", i);
+        printf(" %02x", data[i]);
+    }
+}
+
 static void test_md5(void)
 {
     printf("\r\nTesting MD5 vectors...\r\n");
-    uint8_t test_digest[16];
+
+    const mbedtls_md_info_t *md5_hmac = mbedtls_md_info_from_type(MBEDTLS_MD_MD5);
+
     for(int i = 0; i < NUM_MD5_VECTORS; i++) {
 	const struct test_vector *vector = &md5_vectors[i];
 	printf("Test case %d: ", i+1);
-	hmac_md5(vector->data, vector->data_len, vector->key, vector->key_len, test_digest);
-	if(memcmp(test_digest, vector->digest, 16)) {
+
+        uint8_t test_digest[16];
+        mbedtls_md_hmac(md5_hmac, vector->key, vector->key_len, vector->data, vector->data_len, test_digest);
+
+	if(memcmp(vector->digest, test_digest, 16)) {
 	    uint8_t first = 0;
 	    for(first = 0; first < 16; first++) {
 		if(test_digest[first] != vector->digest[first]) {
diff --git a/extras/mbedtls/component.mk b/extras/mbedtls/component.mk
new file mode 100644
index 0000000..c392471
--- /dev/null
+++ b/extras/mbedtls/component.mk
@@ -0,0 +1,56 @@
+# Component makefile for mbedtls
+
+# mbedtls by default builds into 3 libraries not one. We just use one for now (doesn't make a huge difference when static linking)
+
+# Config:
+# We supply our own hand tweaked mbedtls/config.h in our 'include' dir, the rest of upstream mbedtls is not changed.
+
+MBEDTLS_DIR = $(mbedtls_ROOT)mbedtls/
+INC_DIRS += $(mbedtls_ROOT)include $(MBEDTLS_DIR)include
+
+# these OBJS_xxx variables  are copied directly from mbedtls/mbedtls/Makefile,
+# minus a few values (noted in comments)
+#
+# If updating to a future mbedtls version you can just copy these in.
+OBJS_CRYPTO=	aes.o		aesni.o		arc4.o		\
+		asn1parse.o	asn1write.o	base64.o	\
+		bignum.o	blowfish.o	camellia.o	\
+		ccm.o		cipher.o	cipher_wrap.o	\
+		ctr_drbg.o	des.o		dhm.o		\
+		ecdh.o		ecdsa.o		ecp.o		\
+		ecp_curves.o	entropy.o	entropy_poll.o	\
+		error.o		gcm.o		havege.o	\
+		hmac_drbg.o	md.o		md2.o		\
+		md4.o		md5.o		md_wrap.o	\
+		memory_buffer_alloc.o		oid.o		\
+		padlock.o	pem.o		pk.o		\
+		pk_wrap.o	pkcs12.o	pkcs5.o		\
+		pkparse.o	pkwrite.o	platform.o	\
+		ripemd160.o	rsa.o		sha1.o		\
+		sha256.o	sha512.o	threading.o	\
+		timing.o	version.o			\
+		version_features.o		xtea.o
+# minus net.o
+
+OBJS_X509=	certs.o		pkcs11.o	x509.o		\
+		x509_create.o	x509_crl.o	x509_crt.o	\
+		x509_csr.o	x509write_crt.o	x509write_csr.o
+
+OBJS_TLS=	debug.o				ssl_cache.o	\
+		ssl_ciphersuites.o		ssl_cli.o	\
+		ssl_cookie.o	ssl_srv.o	ssl_ticket.o	\
+		ssl_tls.o
+
+# args for passing into compile rule generation
+mbedtls_INC_DIR =
+mbedtls_SRC_DIR = $(mbedtls_ROOT)
+mbedtls_EXTRA_SRC_FILES = $(patsubst %.o,$(MBEDTLS_DIR)library/%.c,$(OBJS_CRYPTO) $(OBJS_X509) $(OBJS_TLS))
+
+# depending on cipher configuration, some mbedTLS variables are unused
+mbedtls_CFLAGS = -Wno-error=unused-but-set-variable -Wno-error=unused-variable $(CFLAGS) 
+
+$(eval $(call component_compile_rules,mbedtls))
+
+# Helpful error if git submodule not initialised
+$(MBEDTLS_DIR):
+	$(error "mbedtls git submodule not installed. Please run 'git submodule update --init'")
diff --git a/extras/mbedtls/hardware_entropy.c b/extras/mbedtls/hardware_entropy.c
new file mode 100644
index 0000000..0d197cd
--- /dev/null
+++ b/extras/mbedtls/hardware_entropy.c
@@ -0,0 +1,22 @@
+/* ESP8266 "Hardware RNG" (validity still being confirmed) support for ESP8266
+ *
+ * Based on research done by @foogod.
+ *
+ * Please don't rely on this too much as an entropy source, quite yet...
+ *
+ * Part of esp-open-rtos
+ * Copyright (C) 2015 Angus Gratton
+ * BSD Licensed as described in the file LICENSE
+ */
+#include <mbedtls/entropy_poll.h>
+#include <esp/hwrand.h>
+
+int mbedtls_hardware_poll( void *data,
+                           unsigned char *output, size_t len, size_t *olen )
+{
+    (void)(data);
+    hwrand_fill(output, len);
+    if(olen)
+        *olen = len;
+    return 0;
+}
diff --git a/extras/mbedtls/include/mbedtls/config.h b/extras/mbedtls/include/mbedtls/config.h
new file mode 100644
index 0000000..54ce5be
--- /dev/null
+++ b/extras/mbedtls/include/mbedtls/config.h
@@ -0,0 +1,2446 @@
+/**
+ * \file config.h
+ *
+ * \brief Configuration options (set of defines)
+ *
+ *  Copyright (C) 2006-2015, ARM Limited, All Rights Reserved
+ *  SPDX-License-Identifier: Apache-2.0
+ *
+ *  Licensed under the Apache License, Version 2.0 (the "License"); you may
+ *  not use this file except in compliance with the License.
+ *  You may obtain a copy of the License at
+ *
+ *  http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *  Unless required by applicable law or agreed to in writing, software
+ *  distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ *  WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ *  See the License for the specific language governing permissions and
+ *  limitations under the License.
+ *
+ *  This file is part of mbed TLS (https://tls.mbed.org)
+ */
+
+/*
+ * This set of compile-time options may be used to enable
+ * or disable features selectively, and reduce the global
+ * memory footprint.
+ */
+#ifndef MBEDTLS_CONFIG_H
+#define MBEDTLS_CONFIG_H
+
+#if defined(_MSC_VER) && !defined(_CRT_SECURE_NO_DEPRECATE)
+#define _CRT_SECURE_NO_DEPRECATE 1
+#endif
+
+/**
+ * \name SECTION: System support
+ *
+ * This section sets system specific settings.
+ * \{
+ */
+
+/**
+ * \def MBEDTLS_HAVE_ASM
+ *
+ * The compiler has support for asm().
+ *
+ * Requires support for asm() in compiler.
+ *
+ * Used in:
+ *      library/timing.c
+ *      library/padlock.c
+ *      include/mbedtls/bn_mul.h
+ *
+ * Comment to disable the use of assembly code.
+ */
+#define MBEDTLS_HAVE_ASM
+
+/**
+ * \def MBEDTLS_HAVE_SSE2
+ *
+ * CPU supports SSE2 instruction set.
+ *
+ * Uncomment if the CPU supports SSE2 (IA-32 specific).
+ */
+//#define MBEDTLS_HAVE_SSE2
+
+/**
+ * \def MBEDTLS_HAVE_TIME
+ *
+ * System has time.h and time().
+ * The time does not need to be correct, only time differences are used,
+ * by contrast with MBEDTLS_HAVE_TIME_DATE
+ *
+ * Comment if your system does not support time functions
+ */
+//#define MBEDTLS_HAVE_TIME
+
+/**
+ * \def MBEDTLS_HAVE_TIME_DATE
+ *
+ * System has time.h and time(), gmtime() and the clock is correct.
+ * The time needs to be correct (not necesarily very accurate, but at least
+ * the date should be correct). This is used to verify the validity period of
+ * X.509 certificates.
+ *
+ * Comment if your system does not have a correct clock.
+ */
+//#define MBEDTLS_HAVE_TIME_DATE
+
+/**
+ * \def MBEDTLS_PLATFORM_MEMORY
+ *
+ * Enable the memory allocation layer.
+ *
+ * By default mbed TLS uses the system-provided calloc() and free().
+ * This allows different allocators (self-implemented or provided) to be
+ * provided to the platform abstraction layer.
+ *
+ * Enabling MBEDTLS_PLATFORM_MEMORY without the
+ * MBEDTLS_PLATFORM_{FREE,CALLOC}_MACROs will provide
+ * "mbedtls_platform_set_calloc_free()" allowing you to set an alternative calloc() and
+ * free() function pointer at runtime.
+ *
+ * Enabling MBEDTLS_PLATFORM_MEMORY and specifying
+ * MBEDTLS_PLATFORM_{CALLOC,FREE}_MACROs will allow you to specify the
+ * alternate function at compile time.
+ *
+ * Requires: MBEDTLS_PLATFORM_C
+ *
+ * Enable this layer to allow use of alternative memory allocators.
+ */
+//#define MBEDTLS_PLATFORM_MEMORY
+
+/**
+ * \def MBEDTLS_PLATFORM_NO_STD_FUNCTIONS
+ *
+ * Do not assign standard functions in the platform layer (e.g. calloc() to
+ * MBEDTLS_PLATFORM_STD_CALLOC and printf() to MBEDTLS_PLATFORM_STD_PRINTF)
+ *
+ * This makes sure there are no linking errors on platforms that do not support
+ * these functions. You will HAVE to provide alternatives, either at runtime
+ * via the platform_set_xxx() functions or at compile time by setting
+ * the MBEDTLS_PLATFORM_STD_XXX defines, or enabling a
+ * MBEDTLS_PLATFORM_XXX_MACRO.
+ *
+ * Requires: MBEDTLS_PLATFORM_C
+ *
+ * Uncomment to prevent default assignment of standard functions in the
+ * platform layer.
+ */
+//#define MBEDTLS_PLATFORM_NO_STD_FUNCTIONS
+
+/**
+ * \def MBEDTLS_PLATFORM_XXX_ALT
+ *
+ * Uncomment a macro to let mbed TLS support the function in the platform
+ * abstraction layer.
+ *
+ * Example: In case you uncomment MBEDTLS_PLATFORM_PRINTF_ALT, mbed TLS will
+ * provide a function "mbedtls_platform_set_printf()" that allows you to set an
+ * alternative printf function pointer.
+ *
+ * All these define require MBEDTLS_PLATFORM_C to be defined!
+ *
+ * \note MBEDTLS_PLATFORM_SNPRINTF_ALT is required on Windows;
+ * it will be enabled automatically by check_config.h
+ *
+ * \warning MBEDTLS_PLATFORM_XXX_ALT cannot be defined at the same time as
+ * MBEDTLS_PLATFORM_XXX_MACRO!
+ *
+ * Uncomment a macro to enable alternate implementation of specific base
+ * platform function
+ */
+//#define MBEDTLS_PLATFORM_EXIT_ALT
+//#define MBEDTLS_PLATFORM_FPRINTF_ALT
+//#define MBEDTLS_PLATFORM_PRINTF_ALT
+//#define MBEDTLS_PLATFORM_SNPRINTF_ALT
+
+/**
+ * \def MBEDTLS_DEPRECATED_WARNING
+ *
+ * Mark deprecated functions so that they generate a warning if used.
+ * Functions deprecated in one version will usually be removed in the next
+ * version. You can enable this to help you prepare the transition to a new
+ * major version by making sure your code is not using these functions.
+ *
+ * This only works with GCC and Clang. With other compilers, you may want to
+ * use MBEDTLS_DEPRECATED_REMOVED
+ *
+ * Uncomment to get warnings on using deprecated functions.
+ */
+#define MBEDTLS_DEPRECATED_WARNING
+
+/**
+ * \def MBEDTLS_DEPRECATED_REMOVED
+ *
+ * Remove deprecated functions so that they generate an error if used.
+ * Functions deprecated in one version will usually be removed in the next
+ * version. You can enable this to help you prepare the transition to a new
+ * major version by making sure your code is not using these functions.
+ *
+ * Uncomment to get errors on using deprecated functions.
+ */
+//#define MBEDTLS_DEPRECATED_REMOVED
+
+/* \} name SECTION: System support */
+
+/**
+ * \name SECTION: mbed TLS feature support
+ *
+ * This section sets support for features that are or are not needed
+ * within the modules that are enabled.
+ * \{
+ */
+
+/**
+ * \def MBEDTLS_TIMING_ALT
+ *
+ * Uncomment to provide your own alternate implementation for mbedtls_timing_hardclock(),
+ * mbedtls_timing_get_timer(), mbedtls_set_alarm(), mbedtls_set/get_delay()
+ *
+ * Only works if you have MBEDTLS_TIMING_C enabled.
+ *
+ * You will need to provide a header "timing_alt.h" and an implementation at
+ * compile time.
+ */
+//#define MBEDTLS_TIMING_ALT
+
+/**
+ * \def MBEDTLS__MODULE_NAME__ALT
+ *
+ * Uncomment a macro to let mbed TLS use your alternate core implementation of
+ * a symmetric crypto or hash module (e.g. platform specific assembly
+ * optimized implementations). Keep in mind that the function prototypes
+ * should remain the same.
+ *
+ * This replaces the whole module. If you only want to replace one of the
+ * functions, use one of the MBEDTLS__FUNCTION_NAME__ALT flags.
+ *
+ * Example: In case you uncomment MBEDTLS_AES_ALT, mbed TLS will no longer
+ * provide the "struct mbedtls_aes_context" definition and omit the base function
+ * declarations and implementations. "aes_alt.h" will be included from
+ * "aes.h" to include the new function definitions.
+ *
+ * Uncomment a macro to enable alternate implementation of the corresponding
+ * module.
+ */
+//#define MBEDTLS_AES_ALT
+//#define MBEDTLS_ARC4_ALT
+//#define MBEDTLS_BLOWFISH_ALT
+//#define MBEDTLS_CAMELLIA_ALT
+//#define MBEDTLS_DES_ALT
+//#define MBEDTLS_XTEA_ALT
+//#define MBEDTLS_MD2_ALT
+//#define MBEDTLS_MD4_ALT
+//#define MBEDTLS_MD5_ALT
+//#define MBEDTLS_RIPEMD160_ALT
+//#define MBEDTLS_SHA1_ALT
+//#define MBEDTLS_SHA256_ALT
+//#define MBEDTLS_SHA512_ALT
+
+/**
+ * \def MBEDTLS__FUNCTION_NAME__ALT
+ *
+ * Uncomment a macro to let mbed TLS use you alternate core implementation of
+ * symmetric crypto or hash function. Keep in mind that function prototypes
+ * should remain the same.
+ *
+ * This replaces only one function. The header file from mbed TLS is still
+ * used, in contrast to the MBEDTLS__MODULE_NAME__ALT flags.
+ *
+ * Example: In case you uncomment MBEDTLS_SHA256_PROCESS_ALT, mbed TLS will
+ * no longer provide the mbedtls_sha1_process() function, but it will still provide
+ * the other function (using your mbedtls_sha1_process() function) and the definition
+ * of mbedtls_sha1_context, so your implementation of mbedtls_sha1_process must be compatible
+ * with this definition.
+ *
+ * Note: if you use the AES_xxx_ALT macros, then is is recommended to also set
+ * MBEDTLS_AES_ROM_TABLES in order to help the linker garbage-collect the AES
+ * tables.
+ *
+ * Uncomment a macro to enable alternate implementation of the corresponding
+ * function.
+ */
+//#define MBEDTLS_MD2_PROCESS_ALT
+//#define MBEDTLS_MD4_PROCESS_ALT
+//#define MBEDTLS_MD5_PROCESS_ALT
+//#define MBEDTLS_RIPEMD160_PROCESS_ALT
+//#define MBEDTLS_SHA1_PROCESS_ALT
+//#define MBEDTLS_SHA256_PROCESS_ALT
+//#define MBEDTLS_SHA512_PROCESS_ALT
+//#define MBEDTLS_DES_SETKEY_ALT
+//#define MBEDTLS_DES_CRYPT_ECB_ALT
+//#define MBEDTLS_DES3_CRYPT_ECB_ALT
+//#define MBEDTLS_AES_SETKEY_ENC_ALT
+//#define MBEDTLS_AES_SETKEY_DEC_ALT
+//#define MBEDTLS_AES_ENCRYPT_ALT
+//#define MBEDTLS_AES_DECRYPT_ALT
+
+/**
+ * \def MBEDTLS_ENTROPY_HARDWARE_ALT
+ *
+ * Uncomment this macro to let mbed TLS use your own implementation of a
+ * hardware entropy collector.
+ *
+ * Your function must be called \c mbedtls_hardware_poll(), have the same
+ * prototype as declared in entropy_poll.h, and accept NULL as first argument.
+ *
+ * Uncomment to use your own hardware entropy collector.
+ */
+/* hardware RNG interface provided in hardware_entropy.c */
+#define MBEDTLS_ENTROPY_HARDWARE_ALT
+
+/**
+ * \def MBEDTLS_AES_ROM_TABLES
+ *
+ * Store the AES tables in ROM.
+ *
+ * Uncomment this macro to store the AES tables in ROM.
+ */
+#define MBEDTLS_AES_ROM_TABLES
+
+/**
+ * \def MBEDTLS_CAMELLIA_SMALL_MEMORY
+ *
+ * Use less ROM for the Camellia implementation (saves about 768 bytes).
+ *
+ * Uncomment this macro to use less memory for Camellia.
+ */
+//#define MBEDTLS_CAMELLIA_SMALL_MEMORY
+
+/**
+ * \def MBEDTLS_CIPHER_MODE_CBC
+ *
+ * Enable Cipher Block Chaining mode (CBC) for symmetric ciphers.
+ */
+#define MBEDTLS_CIPHER_MODE_CBC
+
+/**
+ * \def MBEDTLS_CIPHER_MODE_CFB
+ *
+ * Enable Cipher Feedback mode (CFB) for symmetric ciphers.
+ */
+#define MBEDTLS_CIPHER_MODE_CFB
+
+/**
+ * \def MBEDTLS_CIPHER_MODE_CTR
+ *
+ * Enable Counter Block Cipher mode (CTR) for symmetric ciphers.
+ */
+#define MBEDTLS_CIPHER_MODE_CTR
+
+/**
+ * \def MBEDTLS_CIPHER_NULL_CIPHER
+ *
+ * Enable NULL cipher.
+ * Warning: Only do so when you know what you are doing. This allows for
+ * encryption or channels without any security!
+ *
+ * Requires MBEDTLS_ENABLE_WEAK_CIPHERSUITES as well to enable
+ * the following ciphersuites:
+ *      MBEDTLS_TLS_ECDH_ECDSA_WITH_NULL_SHA
+ *      MBEDTLS_TLS_ECDH_RSA_WITH_NULL_SHA
+ *      MBEDTLS_TLS_ECDHE_ECDSA_WITH_NULL_SHA
+ *      MBEDTLS_TLS_ECDHE_RSA_WITH_NULL_SHA
+ *      MBEDTLS_TLS_ECDHE_PSK_WITH_NULL_SHA384
+ *      MBEDTLS_TLS_ECDHE_PSK_WITH_NULL_SHA256
+ *      MBEDTLS_TLS_ECDHE_PSK_WITH_NULL_SHA
+ *      MBEDTLS_TLS_DHE_PSK_WITH_NULL_SHA384
+ *      MBEDTLS_TLS_DHE_PSK_WITH_NULL_SHA256
+ *      MBEDTLS_TLS_DHE_PSK_WITH_NULL_SHA
+ *      MBEDTLS_TLS_RSA_WITH_NULL_SHA256
+ *      MBEDTLS_TLS_RSA_WITH_NULL_SHA
+ *      MBEDTLS_TLS_RSA_WITH_NULL_MD5
+ *      MBEDTLS_TLS_RSA_PSK_WITH_NULL_SHA384
+ *      MBEDTLS_TLS_RSA_PSK_WITH_NULL_SHA256
+ *      MBEDTLS_TLS_RSA_PSK_WITH_NULL_SHA
+ *      MBEDTLS_TLS_PSK_WITH_NULL_SHA384
+ *      MBEDTLS_TLS_PSK_WITH_NULL_SHA256
+ *      MBEDTLS_TLS_PSK_WITH_NULL_SHA
+ *
+ * Uncomment this macro to enable the NULL cipher and ciphersuites
+ */
+//#define MBEDTLS_CIPHER_NULL_CIPHER
+
+/**
+ * \def MBEDTLS_CIPHER_PADDING_XXX
+ *
+ * Uncomment or comment macros to add support for specific padding modes
+ * in the cipher layer with cipher modes that support padding (e.g. CBC)
+ *
+ * If you disable all padding modes, only full blocks can be used with CBC.
+ *
+ * Enable padding modes in the cipher layer.
+ */
+#define MBEDTLS_CIPHER_PADDING_PKCS7
+#define MBEDTLS_CIPHER_PADDING_ONE_AND_ZEROS
+#define MBEDTLS_CIPHER_PADDING_ZEROS_AND_LEN
+#define MBEDTLS_CIPHER_PADDING_ZEROS
+
+/**
+ * \def MBEDTLS_ENABLE_WEAK_CIPHERSUITES
+ *
+ * Enable weak ciphersuites in SSL / TLS.
+ * Warning: Only do so when you know what you are doing. This allows for
+ * channels with virtually no security at all!
+ *
+ * This enables the following ciphersuites:
+ *      MBEDTLS_TLS_RSA_WITH_DES_CBC_SHA
+ *      MBEDTLS_TLS_DHE_RSA_WITH_DES_CBC_SHA
+ *
+ * Uncomment this macro to enable weak ciphersuites
+ */
+//#define MBEDTLS_ENABLE_WEAK_CIPHERSUITES
+
+/**
+ * \def MBEDTLS_REMOVE_ARC4_CIPHERSUITES
+ *
+ * Remove RC4 ciphersuites by default in SSL / TLS.
+ * This flag removes the ciphersuites based on RC4 from the default list as
+ * returned by mbedtls_ssl_list_ciphersuites(). However, it is still possible to
+ * enable (some of) them with mbedtls_ssl_conf_ciphersuites() by including them
+ * explicitly.
+ *
+ * Uncomment this macro to remove RC4 ciphersuites by default.
+ */
+#define MBEDTLS_REMOVE_ARC4_CIPHERSUITES
+
+/**
+ * \def MBEDTLS_ECP_XXXX_ENABLED
+ *
+ * Enables specific curves within the Elliptic Curve module.
+ * By default all supported curves are enabled.
+ *
+ * Comment macros to disable the curve and functions for it
+ */
+#define MBEDTLS_ECP_DP_SECP192R1_ENABLED
+#define MBEDTLS_ECP_DP_SECP224R1_ENABLED
+#define MBEDTLS_ECP_DP_SECP256R1_ENABLED
+#define MBEDTLS_ECP_DP_SECP384R1_ENABLED
+#define MBEDTLS_ECP_DP_SECP521R1_ENABLED
+#define MBEDTLS_ECP_DP_SECP192K1_ENABLED
+#define MBEDTLS_ECP_DP_SECP224K1_ENABLED
+#define MBEDTLS_ECP_DP_SECP256K1_ENABLED
+#define MBEDTLS_ECP_DP_BP256R1_ENABLED
+#define MBEDTLS_ECP_DP_BP384R1_ENABLED
+#define MBEDTLS_ECP_DP_BP512R1_ENABLED
+#define MBEDTLS_ECP_DP_CURVE25519_ENABLED
+
+/**
+ * \def MBEDTLS_ECP_NIST_OPTIM
+ *
+ * Enable specific 'modulo p' routines for each NIST prime.
+ * Depending on the prime and architecture, makes operations 4 to 8 times
+ * faster on the corresponding curve.
+ *
+ * Comment this macro to disable NIST curves optimisation.
+ */
+#define MBEDTLS_ECP_NIST_OPTIM
+
+/**
+ * \def MBEDTLS_ECDSA_DETERMINISTIC
+ *
+ * Enable deterministic ECDSA (RFC 6979).
+ * Standard ECDSA is "fragile" in the sense that lack of entropy when signing
+ * may result in a compromise of the long-term signing key. This is avoided by
+ * the deterministic variant.
+ *
+ * Requires: MBEDTLS_HMAC_DRBG_C
+ *
+ * Comment this macro to disable deterministic ECDSA.
+ */
+#define MBEDTLS_ECDSA_DETERMINISTIC
+
+/**
+ * \def MBEDTLS_KEY_EXCHANGE_PSK_ENABLED
+ *
+ * Enable the PSK based ciphersuite modes in SSL / TLS.
+ *
+ * This enables the following ciphersuites (if other requisites are
+ * enabled as well):
+ *      MBEDTLS_TLS_PSK_WITH_AES_256_GCM_SHA384
+ *      MBEDTLS_TLS_PSK_WITH_AES_256_CBC_SHA384
+ *      MBEDTLS_TLS_PSK_WITH_AES_256_CBC_SHA
+ *      MBEDTLS_TLS_PSK_WITH_CAMELLIA_256_GCM_SHA384
+ *      MBEDTLS_TLS_PSK_WITH_CAMELLIA_256_CBC_SHA384
+ *      MBEDTLS_TLS_PSK_WITH_AES_128_GCM_SHA256
+ *      MBEDTLS_TLS_PSK_WITH_AES_128_CBC_SHA256
+ *      MBEDTLS_TLS_PSK_WITH_AES_128_CBC_SHA
+ *      MBEDTLS_TLS_PSK_WITH_CAMELLIA_128_GCM_SHA256
+ *      MBEDTLS_TLS_PSK_WITH_CAMELLIA_128_CBC_SHA256
+ *      MBEDTLS_TLS_PSK_WITH_3DES_EDE_CBC_SHA
+ *      MBEDTLS_TLS_PSK_WITH_RC4_128_SHA
+ */
+#define MBEDTLS_KEY_EXCHANGE_PSK_ENABLED
+
+/**
+ * \def MBEDTLS_KEY_EXCHANGE_DHE_PSK_ENABLED
+ *
+ * Enable the DHE-PSK based ciphersuite modes in SSL / TLS.
+ *
+ * Requires: MBEDTLS_DHM_C
+ *
+ * This enables the following ciphersuites (if other requisites are
+ * enabled as well):
+ *      MBEDTLS_TLS_DHE_PSK_WITH_AES_256_GCM_SHA384
+ *      MBEDTLS_TLS_DHE_PSK_WITH_AES_256_CBC_SHA384
+ *      MBEDTLS_TLS_DHE_PSK_WITH_AES_256_CBC_SHA
+ *      MBEDTLS_TLS_DHE_PSK_WITH_CAMELLIA_256_GCM_SHA384
+ *      MBEDTLS_TLS_DHE_PSK_WITH_CAMELLIA_256_CBC_SHA384
+ *      MBEDTLS_TLS_DHE_PSK_WITH_AES_128_GCM_SHA256
+ *      MBEDTLS_TLS_DHE_PSK_WITH_AES_128_CBC_SHA256
+ *      MBEDTLS_TLS_DHE_PSK_WITH_AES_128_CBC_SHA
+ *      MBEDTLS_TLS_DHE_PSK_WITH_CAMELLIA_128_GCM_SHA256
+ *      MBEDTLS_TLS_DHE_PSK_WITH_CAMELLIA_128_CBC_SHA256
+ *      MBEDTLS_TLS_DHE_PSK_WITH_3DES_EDE_CBC_SHA
+ *      MBEDTLS_TLS_DHE_PSK_WITH_RC4_128_SHA
+ */
+#define MBEDTLS_KEY_EXCHANGE_DHE_PSK_ENABLED
+
+/**
+ * \def MBEDTLS_KEY_EXCHANGE_ECDHE_PSK_ENABLED
+ *
+ * Enable the ECDHE-PSK based ciphersuite modes in SSL / TLS.
+ *
+ * Requires: MBEDTLS_ECDH_C
+ *
+ * This enables the following ciphersuites (if other requisites are
+ * enabled as well):
+ *      MBEDTLS_TLS_ECDHE_PSK_WITH_AES_256_CBC_SHA384
+ *      MBEDTLS_TLS_ECDHE_PSK_WITH_AES_256_CBC_SHA
+ *      MBEDTLS_TLS_ECDHE_PSK_WITH_CAMELLIA_256_CBC_SHA384
+ *      MBEDTLS_TLS_ECDHE_PSK_WITH_AES_128_CBC_SHA256
+ *      MBEDTLS_TLS_ECDHE_PSK_WITH_AES_128_CBC_SHA
+ *      MBEDTLS_TLS_ECDHE_PSK_WITH_CAMELLIA_128_CBC_SHA256
+ *      MBEDTLS_TLS_ECDHE_PSK_WITH_3DES_EDE_CBC_SHA
+ *      MBEDTLS_TLS_ECDHE_PSK_WITH_RC4_128_SHA
+ */
+#define MBEDTLS_KEY_EXCHANGE_ECDHE_PSK_ENABLED
+
+/**
+ * \def MBEDTLS_KEY_EXCHANGE_RSA_PSK_ENABLED
+ *
+ * Enable the RSA-PSK based ciphersuite modes in SSL / TLS.
+ *
+ * Requires: MBEDTLS_RSA_C, MBEDTLS_PKCS1_V15,
+ *           MBEDTLS_X509_CRT_PARSE_C
+ *
+ * This enables the following ciphersuites (if other requisites are
+ * enabled as well):
+ *      MBEDTLS_TLS_RSA_PSK_WITH_AES_256_GCM_SHA384
+ *      MBEDTLS_TLS_RSA_PSK_WITH_AES_256_CBC_SHA384
+ *      MBEDTLS_TLS_RSA_PSK_WITH_AES_256_CBC_SHA
+ *      MBEDTLS_TLS_RSA_PSK_WITH_CAMELLIA_256_GCM_SHA384
+ *      MBEDTLS_TLS_RSA_PSK_WITH_CAMELLIA_256_CBC_SHA384
+ *      MBEDTLS_TLS_RSA_PSK_WITH_AES_128_GCM_SHA256
+ *      MBEDTLS_TLS_RSA_PSK_WITH_AES_128_CBC_SHA256
+ *      MBEDTLS_TLS_RSA_PSK_WITH_AES_128_CBC_SHA
+ *      MBEDTLS_TLS_RSA_PSK_WITH_CAMELLIA_128_GCM_SHA256
+ *      MBEDTLS_TLS_RSA_PSK_WITH_CAMELLIA_128_CBC_SHA256
+ *      MBEDTLS_TLS_RSA_PSK_WITH_3DES_EDE_CBC_SHA
+ *      MBEDTLS_TLS_RSA_PSK_WITH_RC4_128_SHA
+ */
+#define MBEDTLS_KEY_EXCHANGE_RSA_PSK_ENABLED
+
+/**
+ * \def MBEDTLS_KEY_EXCHANGE_RSA_ENABLED
+ *
+ * Enable the RSA-only based ciphersuite modes in SSL / TLS.
+ *
+ * Requires: MBEDTLS_RSA_C, MBEDTLS_PKCS1_V15,
+ *           MBEDTLS_X509_CRT_PARSE_C
+ *
+ * This enables the following ciphersuites (if other requisites are
+ * enabled as well):
+ *      MBEDTLS_TLS_RSA_WITH_AES_256_GCM_SHA384
+ *      MBEDTLS_TLS_RSA_WITH_AES_256_CBC_SHA256
+ *      MBEDTLS_TLS_RSA_WITH_AES_256_CBC_SHA
+ *      MBEDTLS_TLS_RSA_WITH_CAMELLIA_256_GCM_SHA384
+ *      MBEDTLS_TLS_RSA_WITH_CAMELLIA_256_CBC_SHA256
+ *      MBEDTLS_TLS_RSA_WITH_CAMELLIA_256_CBC_SHA
+ *      MBEDTLS_TLS_RSA_WITH_AES_128_GCM_SHA256
+ *      MBEDTLS_TLS_RSA_WITH_AES_128_CBC_SHA256
+ *      MBEDTLS_TLS_RSA_WITH_AES_128_CBC_SHA
+ *      MBEDTLS_TLS_RSA_WITH_CAMELLIA_128_GCM_SHA256
+ *      MBEDTLS_TLS_RSA_WITH_CAMELLIA_128_CBC_SHA256
+ *      MBEDTLS_TLS_RSA_WITH_CAMELLIA_128_CBC_SHA
+ *      MBEDTLS_TLS_RSA_WITH_3DES_EDE_CBC_SHA
+ *      MBEDTLS_TLS_RSA_WITH_RC4_128_SHA
+ *      MBEDTLS_TLS_RSA_WITH_RC4_128_MD5
+ */
+#define MBEDTLS_KEY_EXCHANGE_RSA_ENABLED
+
+/**
+ * \def MBEDTLS_KEY_EXCHANGE_DHE_RSA_ENABLED
+ *
+ * Enable the DHE-RSA based ciphersuite modes in SSL / TLS.
+ *
+ * Requires: MBEDTLS_DHM_C, MBEDTLS_RSA_C, MBEDTLS_PKCS1_V15,
+ *           MBEDTLS_X509_CRT_PARSE_C
+ *
+ * This enables the following ciphersuites (if other requisites are
+ * enabled as well):
+ *      MBEDTLS_TLS_DHE_RSA_WITH_AES_256_GCM_SHA384
+ *      MBEDTLS_TLS_DHE_RSA_WITH_AES_256_CBC_SHA256
+ *      MBEDTLS_TLS_DHE_RSA_WITH_AES_256_CBC_SHA
+ *      MBEDTLS_TLS_DHE_RSA_WITH_CAMELLIA_256_GCM_SHA384
+ *      MBEDTLS_TLS_DHE_RSA_WITH_CAMELLIA_256_CBC_SHA256
+ *      MBEDTLS_TLS_DHE_RSA_WITH_CAMELLIA_256_CBC_SHA
+ *      MBEDTLS_TLS_DHE_RSA_WITH_AES_128_GCM_SHA256
+ *      MBEDTLS_TLS_DHE_RSA_WITH_AES_128_CBC_SHA256
+ *      MBEDTLS_TLS_DHE_RSA_WITH_AES_128_CBC_SHA
+ *      MBEDTLS_TLS_DHE_RSA_WITH_CAMELLIA_128_GCM_SHA256
+ *      MBEDTLS_TLS_DHE_RSA_WITH_CAMELLIA_128_CBC_SHA256
+ *      MBEDTLS_TLS_DHE_RSA_WITH_CAMELLIA_128_CBC_SHA
+ *      MBEDTLS_TLS_DHE_RSA_WITH_3DES_EDE_CBC_SHA
+ */
+#define MBEDTLS_KEY_EXCHANGE_DHE_RSA_ENABLED
+
+/**
+ * \def MBEDTLS_KEY_EXCHANGE_ECDHE_RSA_ENABLED
+ *
+ * Enable the ECDHE-RSA based ciphersuite modes in SSL / TLS.
+ *
+ * Requires: MBEDTLS_ECDH_C, MBEDTLS_RSA_C, MBEDTLS_PKCS1_V15,
+ *           MBEDTLS_X509_CRT_PARSE_C
+ *
+ * This enables the following ciphersuites (if other requisites are
+ * enabled as well):
+ *      MBEDTLS_TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384
+ *      MBEDTLS_TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA384
+ *      MBEDTLS_TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA
+ *      MBEDTLS_TLS_ECDHE_RSA_WITH_CAMELLIA_256_GCM_SHA384
+ *      MBEDTLS_TLS_ECDHE_RSA_WITH_CAMELLIA_256_CBC_SHA384
+ *      MBEDTLS_TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256
+ *      MBEDTLS_TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256
+ *      MBEDTLS_TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA
+ *      MBEDTLS_TLS_ECDHE_RSA_WITH_CAMELLIA_128_GCM_SHA256
+ *      MBEDTLS_TLS_ECDHE_RSA_WITH_CAMELLIA_128_CBC_SHA256
+ *      MBEDTLS_TLS_ECDHE_RSA_WITH_3DES_EDE_CBC_SHA
+ *      MBEDTLS_TLS_ECDHE_RSA_WITH_RC4_128_SHA
+ */
+#define MBEDTLS_KEY_EXCHANGE_ECDHE_RSA_ENABLED
+
+/**
+ * \def MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA_ENABLED
+ *
+ * Enable the ECDHE-ECDSA based ciphersuite modes in SSL / TLS.
+ *
+ * Requires: MBEDTLS_ECDH_C, MBEDTLS_ECDSA_C, MBEDTLS_X509_CRT_PARSE_C,
+ *
+ * This enables the following ciphersuites (if other requisites are
+ * enabled as well):
+ *      MBEDTLS_TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384
+ *      MBEDTLS_TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA384
+ *      MBEDTLS_TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA
+ *      MBEDTLS_TLS_ECDHE_ECDSA_WITH_CAMELLIA_256_GCM_SHA384
+ *      MBEDTLS_TLS_ECDHE_ECDSA_WITH_CAMELLIA_256_CBC_SHA384
+ *      MBEDTLS_TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256
+ *      MBEDTLS_TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256
+ *      MBEDTLS_TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA
+ *      MBEDTLS_TLS_ECDHE_ECDSA_WITH_CAMELLIA_128_GCM_SHA256
+ *      MBEDTLS_TLS_ECDHE_ECDSA_WITH_CAMELLIA_128_CBC_SHA256
+ *      MBEDTLS_TLS_ECDHE_ECDSA_WITH_3DES_EDE_CBC_SHA
+ *      MBEDTLS_TLS_ECDHE_ECDSA_WITH_RC4_128_SHA
+ */
+#define MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA_ENABLED
+
+/**
+ * \def MBEDTLS_KEY_EXCHANGE_ECDH_ECDSA_ENABLED
+ *
+ * Enable the ECDH-ECDSA based ciphersuite modes in SSL / TLS.
+ *
+ * Requires: MBEDTLS_ECDH_C, MBEDTLS_X509_CRT_PARSE_C
+ *
+ * This enables the following ciphersuites (if other requisites are
+ * enabled as well):
+ *      MBEDTLS_TLS_ECDH_ECDSA_WITH_RC4_128_SHA
+ *      MBEDTLS_TLS_ECDH_ECDSA_WITH_3DES_EDE_CBC_SHA
+ *      MBEDTLS_TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA
+ *      MBEDTLS_TLS_ECDH_ECDSA_WITH_AES_256_CBC_SHA
+ *      MBEDTLS_TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA256
+ *      MBEDTLS_TLS_ECDH_ECDSA_WITH_AES_256_CBC_SHA384
+ *      MBEDTLS_TLS_ECDH_ECDSA_WITH_AES_128_GCM_SHA256
+ *      MBEDTLS_TLS_ECDH_ECDSA_WITH_AES_256_GCM_SHA384
+ *      MBEDTLS_TLS_ECDH_ECDSA_WITH_CAMELLIA_128_CBC_SHA256
+ *      MBEDTLS_TLS_ECDH_ECDSA_WITH_CAMELLIA_256_CBC_SHA384
+ *      MBEDTLS_TLS_ECDH_ECDSA_WITH_CAMELLIA_128_GCM_SHA256
+ *      MBEDTLS_TLS_ECDH_ECDSA_WITH_CAMELLIA_256_GCM_SHA384
+ */
+#define MBEDTLS_KEY_EXCHANGE_ECDH_ECDSA_ENABLED
+
+/**
+ * \def MBEDTLS_KEY_EXCHANGE_ECDH_RSA_ENABLED
+ *
+ * Enable the ECDH-RSA based ciphersuite modes in SSL / TLS.
+ *
+ * Requires: MBEDTLS_ECDH_C, MBEDTLS_X509_CRT_PARSE_C
+ *
+ * This enables the following ciphersuites (if other requisites are
+ * enabled as well):
+ *      MBEDTLS_TLS_ECDH_RSA_WITH_RC4_128_SHA
+ *      MBEDTLS_TLS_ECDH_RSA_WITH_3DES_EDE_CBC_SHA
+ *      MBEDTLS_TLS_ECDH_RSA_WITH_AES_128_CBC_SHA
+ *      MBEDTLS_TLS_ECDH_RSA_WITH_AES_256_CBC_SHA
+ *      MBEDTLS_TLS_ECDH_RSA_WITH_AES_128_CBC_SHA256
+ *      MBEDTLS_TLS_ECDH_RSA_WITH_AES_256_CBC_SHA384
+ *      MBEDTLS_TLS_ECDH_RSA_WITH_AES_128_GCM_SHA256
+ *      MBEDTLS_TLS_ECDH_RSA_WITH_AES_256_GCM_SHA384
+ *      MBEDTLS_TLS_ECDH_RSA_WITH_CAMELLIA_128_CBC_SHA256
+ *      MBEDTLS_TLS_ECDH_RSA_WITH_CAMELLIA_256_CBC_SHA384
+ *      MBEDTLS_TLS_ECDH_RSA_WITH_CAMELLIA_128_GCM_SHA256
+ *      MBEDTLS_TLS_ECDH_RSA_WITH_CAMELLIA_256_GCM_SHA384
+ */
+#define MBEDTLS_KEY_EXCHANGE_ECDH_RSA_ENABLED
+
+/**
+ * \def MBEDTLS_PK_PARSE_EC_EXTENDED
+ *
+ * Enhance support for reading EC keys using variants of SEC1 not allowed by
+ * RFC 5915 and RFC 5480.
+ *
+ * Currently this means parsing the SpecifiedECDomain choice of EC
+ * parameters (only known groups are supported, not arbitrary domains, to
+ * avoid validation issues).
+ *
+ * Disable if you only need to support RFC 5915 + 5480 key formats.
+ */
+#define MBEDTLS_PK_PARSE_EC_EXTENDED
+
+/**
+ * \def MBEDTLS_ERROR_STRERROR_DUMMY
+ *
+ * Enable a dummy error function to make use of mbedtls_strerror() in
+ * third party libraries easier when MBEDTLS_ERROR_C is disabled
+ * (no effect when MBEDTLS_ERROR_C is enabled).
+ *
+ * You can safely disable this if MBEDTLS_ERROR_C is enabled, or if you're
+ * not using mbedtls_strerror() or error_strerror() in your application.
+ *
+ * Disable if you run into name conflicts and want to really remove the
+ * mbedtls_strerror()
+ */
+#define MBEDTLS_ERROR_STRERROR_DUMMY
+
+/**
+ * \def MBEDTLS_GENPRIME
+ *
+ * Enable the prime-number generation code.
+ *
+ * Requires: MBEDTLS_BIGNUM_C
+ */
+#define MBEDTLS_GENPRIME
+
+/**
+ * \def MBEDTLS_FS_IO
+ *
+ * Enable functions that use the filesystem.
+ */
+//#define MBEDTLS_FS_IO
+
+/**
+ * \def MBEDTLS_NO_DEFAULT_ENTROPY_SOURCES
+ *
+ * Do not add default entropy sources. These are the platform specific,
+ * mbedtls_timing_hardclock and HAVEGE based poll functions.
+ *
+ * This is useful to have more control over the added entropy sources in an
+ * application.
+ *
+ * Uncomment this macro to prevent loading of default entropy functions.
+ */
+//#define MBEDTLS_NO_DEFAULT_ENTROPY_SOURCES
+
+/**
+ * \def MBEDTLS_NO_PLATFORM_ENTROPY
+ *
+ * Do not use built-in platform entropy functions.
+ * This is useful if your platform does not support
+ * standards like the /dev/urandom or Windows CryptoAPI.
+ *
+ * Uncomment this macro to disable the built-in platform entropy functions.
+ */
+#define MBEDTLS_NO_PLATFORM_ENTROPY
+
+/**
+ * \def MBEDTLS_ENTROPY_FORCE_SHA256
+ *
+ * Force the entropy accumulator to use a SHA-256 accumulator instead of the
+ * default SHA-512 based one (if both are available).
+ *
+ * Requires: MBEDTLS_SHA256_C
+ *
+ * On 32-bit systems SHA-256 can be much faster than SHA-512. Use this option
+ * if you have performance concerns.
+ *
+ * This option is only useful if both MBEDTLS_SHA256_C and
+ * MBEDTLS_SHA512_C are defined. Otherwise the available hash module is used.
+ */
+#define MBEDTLS_ENTROPY_FORCE_SHA256
+
+/**
+ * \def MBEDTLS_MEMORY_DEBUG
+ *
+ * Enable debugging of buffer allocator memory issues. Automatically prints
+ * (to stderr) all (fatal) messages on memory allocation issues. Enables
+ * function for 'debug output' of allocated memory.
+ *
+ * Requires: MBEDTLS_MEMORY_BUFFER_ALLOC_C
+ *
+ * Uncomment this macro to let the buffer allocator print out error messages.
+ */
+//#define MBEDTLS_MEMORY_DEBUG
+
+/**
+ * \def MBEDTLS_MEMORY_BACKTRACE
+ *
+ * Include backtrace information with each allocated block.
+ *
+ * Requires: MBEDTLS_MEMORY_BUFFER_ALLOC_C
+ *           GLIBC-compatible backtrace() an backtrace_symbols() support
+ *
+ * Uncomment this macro to include backtrace information
+ */
+//#define MBEDTLS_MEMORY_BACKTRACE
+
+/**
+ * \def MBEDTLS_PK_RSA_ALT_SUPPORT
+ *
+ * Support external private RSA keys (eg from a HSM) in the PK layer.
+ *
+ * Comment this macro to disable support for external private RSA keys.
+ */
+#define MBEDTLS_PK_RSA_ALT_SUPPORT
+
+/**
+ * \def MBEDTLS_PKCS1_V15
+ *
+ * Enable support for PKCS#1 v1.5 encoding.
+ *
+ * Requires: MBEDTLS_RSA_C
+ *
+ * This enables support for PKCS#1 v1.5 operations.
+ */
+#define MBEDTLS_PKCS1_V15
+
+/**
+ * \def MBEDTLS_PKCS1_V21
+ *
+ * Enable support for PKCS#1 v2.1 encoding.
+ *
+ * Requires: MBEDTLS_MD_C, MBEDTLS_RSA_C
+ *
+ * This enables support for RSAES-OAEP and RSASSA-PSS operations.
+ */
+#define MBEDTLS_PKCS1_V21
+
+/**
+ * \def MBEDTLS_RSA_NO_CRT
+ *
+ * Do not use the Chinese Remainder Theorem for the RSA private operation.
+ *
+ * Uncomment this macro to disable the use of CRT in RSA.
+ *
+ */
+//#define MBEDTLS_RSA_NO_CRT
+
+/**
+ * \def MBEDTLS_SELF_TEST
+ *
+ * Enable the checkup functions (*_self_test).
+ */
+#define MBEDTLS_SELF_TEST
+
+/**
+ * \def MBEDTLS_SHA256_SMALLER
+ *
+ * Enable an implementation of SHA-256 that has lower ROM footprint but also
+ * lower performance.
+ *
+ * The default implementation is meant to be a reasonnable compromise between
+ * performance and size. This version optimizes more aggressively for size at
+ * the expense of performance. Eg on Cortex-M4 it reduces the size of
+ * mbedtls_sha256_process() from ~2KB to ~0.5KB for a performance hit of about
+ * 30%.
+ *
+ * Uncomment to enable the smaller implementation of SHA256.
+ */
+#define MBEDTLS_SHA256_SMALLER
+
+/**
+ * \def MBEDTLS_SSL_AEAD_RANDOM_IV
+ *
+ * Generate a random IV rather than using the record sequence number as a
+ * nonce for ciphersuites using and AEAD algorithm (GCM or CCM).
+ *
+ * Using the sequence number is generally recommended.
+ *
+ * Uncomment this macro to always use random IVs with AEAD ciphersuites.
+ */
+//#define MBEDTLS_SSL_AEAD_RANDOM_IV
+
+/**
+ * \def MBEDTLS_SSL_ALL_ALERT_MESSAGES
+ *
+ * Enable sending of alert messages in case of encountered errors as per RFC.
+ * If you choose not to send the alert messages, mbed TLS can still communicate
+ * with other servers, only debugging of failures is harder.
+ *
+ * The advantage of not sending alert messages, is that no information is given
+ * about reasons for failures thus preventing adversaries of gaining intel.
+ *
+ * Enable sending of all alert messages
+ */
+#define MBEDTLS_SSL_ALL_ALERT_MESSAGES
+
+/**
+ * \def MBEDTLS_SSL_DEBUG_ALL
+ *
+ * Enable the debug messages in SSL module for all issues.
+ * Debug messages have been disabled in some places to prevent timing
+ * attacks due to (unbalanced) debugging function calls.
+ *
+ * If you need all error reporting you should enable this during debugging,
+ * but remove this for production servers that should log as well.
+ *
+ * Uncomment this macro to report all debug messages on errors introducing
+ * a timing side-channel.
+ *
+ */
+//#define MBEDTLS_SSL_DEBUG_ALL
+
+/** \def MBEDTLS_SSL_ENCRYPT_THEN_MAC
+ *
+ * Enable support for Encrypt-then-MAC, RFC 7366.
+ *
+ * This allows peers that both support it to use a more robust protection for
+ * ciphersuites using CBC, providing deep resistance against timing attacks
+ * on the padding or underlying cipher.
+ *
+ * This only affects CBC ciphersuites, and is useless if none is defined.
+ *
+ * Requires: MBEDTLS_SSL_PROTO_TLS1    or
+ *           MBEDTLS_SSL_PROTO_TLS1_1  or
+ *           MBEDTLS_SSL_PROTO_TLS1_2
+ *
+ * Comment this macro to disable support for Encrypt-then-MAC
+ */
+#define MBEDTLS_SSL_ENCRYPT_THEN_MAC
+
+/** \def MBEDTLS_SSL_EXTENDED_MASTER_SECRET
+ *
+ * Enable support for Extended Master Secret, aka Session Hash
+ * (draft-ietf-tls-session-hash-02).
+ *
+ * This was introduced as "the proper fix" to the Triple Handshake familiy of
+ * attacks, but it is recommended to always use it (even if you disable
+ * renegotiation), since it actually fixes a more fundamental issue in the
+ * original SSL/TLS design, and has implications beyond Triple Handshake.
+ *
+ * Requires: MBEDTLS_SSL_PROTO_TLS1    or
+ *           MBEDTLS_SSL_PROTO_TLS1_1  or
+ *           MBEDTLS_SSL_PROTO_TLS1_2
+ *
+ * Comment this macro to disable support for Extended Master Secret.
+ */
+#define MBEDTLS_SSL_EXTENDED_MASTER_SECRET
+
+/**
+ * \def MBEDTLS_SSL_FALLBACK_SCSV
+ *
+ * Enable support for FALLBACK_SCSV (draft-ietf-tls-downgrade-scsv-00).
+ *
+ * For servers, it is recommended to always enable this, unless you support
+ * only one version of TLS, or know for sure that none of your clients
+ * implements a fallback strategy.
+ *
+ * For clients, you only need this if you're using a fallback strategy, which
+ * is not recommended in the first place, unless you absolutely need it to
+ * interoperate with buggy (version-intolerant) servers.
+ *
+ * Comment this macro to disable support for FALLBACK_SCSV
+ */
+#define MBEDTLS_SSL_FALLBACK_SCSV
+
+/**
+ * \def MBEDTLS_SSL_HW_RECORD_ACCEL
+ *
+ * Enable hooking functions in SSL module for hardware acceleration of
+ * individual records.
+ *
+ * Uncomment this macro to enable hooking functions.
+ */
+//#define MBEDTLS_SSL_HW_RECORD_ACCEL
+
+/**
+ * \def MBEDTLS_SSL_CBC_RECORD_SPLITTING
+ *
+ * Enable 1/n-1 record splitting for CBC mode in SSLv3 and TLS 1.0.
+ *
+ * This is a countermeasure to the BEAST attack, which also minimizes the risk
+ * of interoperability issues compared to sending 0-length records.
+ *
+ * Comment this macro to disable 1/n-1 record splitting.
+ */
+#define MBEDTLS_SSL_CBC_RECORD_SPLITTING
+
+/**
+ * \def MBEDTLS_SSL_RENEGOTIATION
+ *
+ * Disable support for TLS renegotiation.
+ *
+ * The two main uses of renegotiation are (1) refresh keys on long-lived
+ * connections and (2) client authentication after the initial handshake.
+ * If you don't need renegotiation, it's probably better to disable it, since
+ * it has been associated with security issues in the past and is easy to
+ * misuse/misunderstand.
+ *
+ * Comment this to disable support for renegotiation.
+ */
+#define MBEDTLS_SSL_RENEGOTIATION
+
+/**
+ * \def MBEDTLS_SSL_SRV_SUPPORT_SSLV2_CLIENT_HELLO
+ *
+ * Enable support for receiving and parsing SSLv2 Client Hello messages for the
+ * SSL Server module (MBEDTLS_SSL_SRV_C).
+ *
+ * Uncomment this macro to enable support for SSLv2 Client Hello messages.
+ */
+//#define MBEDTLS_SSL_SRV_SUPPORT_SSLV2_CLIENT_HELLO
+
+/**
+ * \def MBEDTLS_SSL_SRV_RESPECT_CLIENT_PREFERENCE
+ *
+ * Pick the ciphersuite according to the client's preferences rather than ours
+ * in the SSL Server module (MBEDTLS_SSL_SRV_C).
+ *
+ * Uncomment this macro to respect client's ciphersuite order
+ */
+//#define MBEDTLS_SSL_SRV_RESPECT_CLIENT_PREFERENCE
+
+/**
+ * \def MBEDTLS_SSL_MAX_FRAGMENT_LENGTH
+ *
+ * Enable support for RFC 6066 max_fragment_length extension in SSL.
+ *
+ * Comment this macro to disable support for the max_fragment_length extension
+ */
+#define MBEDTLS_SSL_MAX_FRAGMENT_LENGTH
+
+/**
+ * \def MBEDTLS_SSL_PROTO_SSL3
+ *
+ * Enable support for SSL 3.0.
+ *
+ * Requires: MBEDTLS_MD5_C
+ *           MBEDTLS_SHA1_C
+ *
+ * Comment this macro to disable support for SSL 3.0
+ */
+#define MBEDTLS_SSL_PROTO_SSL3
+
+/**
+ * \def MBEDTLS_SSL_PROTO_TLS1
+ *
+ * Enable support for TLS 1.0.
+ *
+ * Requires: MBEDTLS_MD5_C
+ *           MBEDTLS_SHA1_C
+ *
+ * Comment this macro to disable support for TLS 1.0
+ */
+#define MBEDTLS_SSL_PROTO_TLS1
+
+/**
+ * \def MBEDTLS_SSL_PROTO_TLS1_1
+ *
+ * Enable support for TLS 1.1 (and DTLS 1.0 if DTLS is enabled).
+ *
+ * Requires: MBEDTLS_MD5_C
+ *           MBEDTLS_SHA1_C
+ *
+ * Comment this macro to disable support for TLS 1.1 / DTLS 1.0
+ */
+#define MBEDTLS_SSL_PROTO_TLS1_1
+
+/**
+ * \def MBEDTLS_SSL_PROTO_TLS1_2
+ *
+ * Enable support for TLS 1.2 (and DTLS 1.2 if DTLS is enabled).
+ *
+ * Requires: MBEDTLS_SHA1_C or MBEDTLS_SHA256_C or MBEDTLS_SHA512_C
+ *           (Depends on ciphersuites)
+ *
+ * Comment this macro to disable support for TLS 1.2 / DTLS 1.2
+ */
+#define MBEDTLS_SSL_PROTO_TLS1_2
+
+/**
+ * \def MBEDTLS_SSL_PROTO_DTLS
+ *
+ * Enable support for DTLS (all available versions).
+ *
+ * Enable this and MBEDTLS_SSL_PROTO_TLS1_1 to enable DTLS 1.0,
+ * and/or this and MBEDTLS_SSL_PROTO_TLS1_2 to enable DTLS 1.2.
+ *
+ * Requires: MBEDTLS_SSL_PROTO_TLS1_1
+ *        or MBEDTLS_SSL_PROTO_TLS1_2
+ *
+ * Comment this macro to disable support for DTLS
+ */
+#define MBEDTLS_SSL_PROTO_DTLS
+
+/**
+ * \def MBEDTLS_SSL_ALPN
+ *
+ * Enable support for RFC 7301 Application Layer Protocol Negotiation.
+ *
+ * Comment this macro to disable support for ALPN.
+ */
+#define MBEDTLS_SSL_ALPN
+
+/**
+ * \def MBEDTLS_SSL_DTLS_ANTI_REPLAY
+ *
+ * Enable support for the anti-replay mechanism in DTLS.
+ *
+ * Requires: MBEDTLS_SSL_TLS_C
+ *           MBEDTLS_SSL_PROTO_DTLS
+ *
+ * \warning Disabling this is often a security risk!
+ * See mbedtls_ssl_conf_dtls_anti_replay() for details.
+ *
+ * Comment this to disable anti-replay in DTLS.
+ */
+#define MBEDTLS_SSL_DTLS_ANTI_REPLAY
+
+/**
+ * \def MBEDTLS_SSL_DTLS_HELLO_VERIFY
+ *
+ * Enable support for HelloVerifyRequest on DTLS servers.
+ *
+ * This feature is highly recommended to prevent DTLS servers being used as
+ * amplifiers in DoS attacks against other hosts. It should always be enabled
+ * unless you know for sure amplification cannot be a problem in the
+ * environment in which your server operates.
+ *
+ * \warning Disabling this can ba a security risk! (see above)
+ *
+ * Requires: MBEDTLS_SSL_PROTO_DTLS
+ *
+ * Comment this to disable support for HelloVerifyRequest.
+ */
+#define MBEDTLS_SSL_DTLS_HELLO_VERIFY
+
+/**
+ * \def MBEDTLS_SSL_DTLS_BADMAC_LIMIT
+ *
+ * Enable support for a limit of records with bad MAC.
+ *
+ * See mbedtls_ssl_conf_dtls_badmac_limit().
+ *
+ * Requires: MBEDTLS_SSL_PROTO_DTLS
+ */
+#define MBEDTLS_SSL_DTLS_BADMAC_LIMIT
+
+/**
+ * \def MBEDTLS_SSL_SESSION_TICKETS
+ *
+ * Enable support for RFC 5077 session tickets in SSL.
+ * Client-side, provides full support for session tickets (maintainance of a
+ * session store remains the responsibility of the application, though).
+ * Server-side, you also need to provide callbacks for writing and parsing
+ * tickets, including authenticated encryption and key management. Example
+ * callbacks are provided by MBEDTLS_SSL_TICKET_C.
+ *
+ * Comment this macro to disable support for SSL session tickets
+ */
+#define MBEDTLS_SSL_SESSION_TICKETS
+
+/**
+ * \def MBEDTLS_SSL_SERVER_NAME_INDICATION
+ *
+ * Enable support for RFC 6066 server name indication (SNI) in SSL.
+ *
+ * Requires: MBEDTLS_X509_CRT_PARSE_C
+ *
+ * Comment this macro to disable support for server name indication in SSL
+ */
+#define MBEDTLS_SSL_SERVER_NAME_INDICATION
+
+/**
+ * \def MBEDTLS_SSL_TRUNCATED_HMAC
+ *
+ * Enable support for RFC 6066 truncated HMAC in SSL.
+ *
+ * Comment this macro to disable support for truncated HMAC in SSL
+ */
+#define MBEDTLS_SSL_TRUNCATED_HMAC
+
+/**
+ * \def MBEDTLS_THREADING_ALT
+ *
+ * Provide your own alternate threading implementation.
+ *
+ * Requires: MBEDTLS_THREADING_C
+ *
+ * Uncomment this to allow your own alternate threading implementation.
+ */
+//#define MBEDTLS_THREADING_ALT
+
+/**
+ * \def MBEDTLS_THREADING_PTHREAD
+ *
+ * Enable the pthread wrapper layer for the threading layer.
+ *
+ * Requires: MBEDTLS_THREADING_C
+ *
+ * Uncomment this to enable pthread mutexes.
+ */
+//#define MBEDTLS_THREADING_PTHREAD
+
+/**
+ * \def MBEDTLS_VERSION_FEATURES
+ *
+ * Allow run-time checking of compile-time enabled features. Thus allowing users
+ * to check at run-time if the library is for instance compiled with threading
+ * support via mbedtls_version_check_feature().
+ *
+ * Requires: MBEDTLS_VERSION_C
+ *
+ * Comment this to disable run-time checking and save ROM space
+ */
+#define MBEDTLS_VERSION_FEATURES
+
+/**
+ * \def MBEDTLS_X509_ALLOW_EXTENSIONS_NON_V3
+ *
+ * If set, the X509 parser will not break-off when parsing an X509 certificate
+ * and encountering an extension in a v1 or v2 certificate.
+ *
+ * Uncomment to prevent an error.
+ */
+//#define MBEDTLS_X509_ALLOW_EXTENSIONS_NON_V3
+
+/**
+ * \def MBEDTLS_X509_ALLOW_UNSUPPORTED_CRITICAL_EXTENSION
+ *
+ * If set, the X509 parser will not break-off when parsing an X509 certificate
+ * and encountering an unknown critical extension.
+ *
+ * Uncomment to prevent an error.
+ */
+//#define MBEDTLS_X509_ALLOW_UNSUPPORTED_CRITICAL_EXTENSION
+
+/**
+ * \def MBEDTLS_X509_CHECK_KEY_USAGE
+ *
+ * Enable verification of the keyUsage extension (CA and leaf certificates).
+ *
+ * Disabling this avoids problems with mis-issued and/or misused
+ * (intermediate) CA and leaf certificates.
+ *
+ * \warning Depending on your PKI use, disabling this can be a security risk!
+ *
+ * Comment to skip keyUsage checking for both CA and leaf certificates.
+ */
+#define MBEDTLS_X509_CHECK_KEY_USAGE
+
+/**
+ * \def MBEDTLS_X509_CHECK_EXTENDED_KEY_USAGE
+ *
+ * Enable verification of the extendedKeyUsage extension (leaf certificates).
+ *
+ * Disabling this avoids problems with mis-issued and/or misused certificates.
+ *
+ * \warning Depending on your PKI use, disabling this can be a security risk!
+ *
+ * Comment to skip extendedKeyUsage checking for certificates.
+ */
+#define MBEDTLS_X509_CHECK_EXTENDED_KEY_USAGE
+
+/**
+ * \def MBEDTLS_X509_RSASSA_PSS_SUPPORT
+ *
+ * Enable parsing and verification of X.509 certificates, CRLs and CSRS
+ * signed with RSASSA-PSS (aka PKCS#1 v2.1).
+ *
+ * Comment this macro to disallow using RSASSA-PSS in certificates.
+ */
+#define MBEDTLS_X509_RSASSA_PSS_SUPPORT
+
+/**
+ * \def MBEDTLS_ZLIB_SUPPORT
+ *
+ * If set, the SSL/TLS module uses ZLIB to support compression and
+ * decompression of packet data.
+ *
+ * \warning TLS-level compression MAY REDUCE SECURITY! See for example the
+ * CRIME attack. Before enabling this option, you should examine with care if
+ * CRIME or similar exploits may be a applicable to your use case.
+ *
+ * \note Currently compression can't be used with DTLS.
+ *
+ * Used in: library/ssl_tls.c
+ *          library/ssl_cli.c
+ *          library/ssl_srv.c
+ *
+ * This feature requires zlib library and headers to be present.
+ *
+ * Uncomment to enable use of ZLIB
+ */
+//#define MBEDTLS_ZLIB_SUPPORT
+/* \} name SECTION: mbed TLS feature support */
+
+/**
+ * \name SECTION: mbed TLS modules
+ *
+ * This section enables or disables entire modules in mbed TLS
+ * \{
+ */
+
+/**
+ * \def MBEDTLS_AESNI_C
+ *
+ * Enable AES-NI support on x86-64.
+ *
+ * Module:  library/aesni.c
+ * Caller:  library/aes.c
+ *
+ * Requires: MBEDTLS_HAVE_ASM
+ *
+ * This modules adds support for the AES-NI instructions on x86-64
+ */
+#define MBEDTLS_AESNI_C
+
+/**
+ * \def MBEDTLS_AES_C
+ *
+ * Enable the AES block cipher.
+ *
+ * Module:  library/aes.c
+ * Caller:  library/ssl_tls.c
+ *          library/pem.c
+ *          library/ctr_drbg.c
+ *
+ * This module enables the following ciphersuites (if other requisites are
+ * enabled as well):
+ *      MBEDTLS_TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA
+ *      MBEDTLS_TLS_ECDH_ECDSA_WITH_AES_256_CBC_SHA
+ *      MBEDTLS_TLS_ECDH_RSA_WITH_AES_128_CBC_SHA
+ *      MBEDTLS_TLS_ECDH_RSA_WITH_AES_256_CBC_SHA
+ *      MBEDTLS_TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA256
+ *      MBEDTLS_TLS_ECDH_ECDSA_WITH_AES_256_CBC_SHA384
+ *      MBEDTLS_TLS_ECDH_RSA_WITH_AES_128_CBC_SHA256
+ *      MBEDTLS_TLS_ECDH_RSA_WITH_AES_256_CBC_SHA384
+ *      MBEDTLS_TLS_ECDH_ECDSA_WITH_AES_128_GCM_SHA256
+ *      MBEDTLS_TLS_ECDH_ECDSA_WITH_AES_256_GCM_SHA384
+ *      MBEDTLS_TLS_ECDH_RSA_WITH_AES_128_GCM_SHA256
+ *      MBEDTLS_TLS_ECDH_RSA_WITH_AES_256_GCM_SHA384
+ *      MBEDTLS_TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384
+ *      MBEDTLS_TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384
+ *      MBEDTLS_TLS_DHE_RSA_WITH_AES_256_GCM_SHA384
+ *      MBEDTLS_TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA384
+ *      MBEDTLS_TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA384
+ *      MBEDTLS_TLS_DHE_RSA_WITH_AES_256_CBC_SHA256
+ *      MBEDTLS_TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA
+ *      MBEDTLS_TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA
+ *      MBEDTLS_TLS_DHE_RSA_WITH_AES_256_CBC_SHA
+ *      MBEDTLS_TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256
+ *      MBEDTLS_TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256
+ *      MBEDTLS_TLS_DHE_RSA_WITH_AES_128_GCM_SHA256
+ *      MBEDTLS_TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256
+ *      MBEDTLS_TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256
+ *      MBEDTLS_TLS_DHE_RSA_WITH_AES_128_CBC_SHA256
+ *      MBEDTLS_TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA
+ *      MBEDTLS_TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA
+ *      MBEDTLS_TLS_DHE_RSA_WITH_AES_128_CBC_SHA
+ *      MBEDTLS_TLS_DHE_PSK_WITH_AES_256_GCM_SHA384
+ *      MBEDTLS_TLS_ECDHE_PSK_WITH_AES_256_CBC_SHA384
+ *      MBEDTLS_TLS_DHE_PSK_WITH_AES_256_CBC_SHA384
+ *      MBEDTLS_TLS_ECDHE_PSK_WITH_AES_256_CBC_SHA
+ *      MBEDTLS_TLS_DHE_PSK_WITH_AES_256_CBC_SHA
+ *      MBEDTLS_TLS_DHE_PSK_WITH_AES_128_GCM_SHA256
+ *      MBEDTLS_TLS_ECDHE_PSK_WITH_AES_128_CBC_SHA256
+ *      MBEDTLS_TLS_DHE_PSK_WITH_AES_128_CBC_SHA256
+ *      MBEDTLS_TLS_ECDHE_PSK_WITH_AES_128_CBC_SHA
+ *      MBEDTLS_TLS_DHE_PSK_WITH_AES_128_CBC_SHA
+ *      MBEDTLS_TLS_RSA_WITH_AES_256_GCM_SHA384
+ *      MBEDTLS_TLS_RSA_WITH_AES_256_CBC_SHA256
+ *      MBEDTLS_TLS_RSA_WITH_AES_256_CBC_SHA
+ *      MBEDTLS_TLS_RSA_WITH_AES_128_GCM_SHA256
+ *      MBEDTLS_TLS_RSA_WITH_AES_128_CBC_SHA256
+ *      MBEDTLS_TLS_RSA_WITH_AES_128_CBC_SHA
+ *      MBEDTLS_TLS_RSA_PSK_WITH_AES_256_GCM_SHA384
+ *      MBEDTLS_TLS_RSA_PSK_WITH_AES_256_CBC_SHA384
+ *      MBEDTLS_TLS_RSA_PSK_WITH_AES_256_CBC_SHA
+ *      MBEDTLS_TLS_RSA_PSK_WITH_AES_128_GCM_SHA256
+ *      MBEDTLS_TLS_RSA_PSK_WITH_AES_128_CBC_SHA256
+ *      MBEDTLS_TLS_RSA_PSK_WITH_AES_128_CBC_SHA
+ *      MBEDTLS_TLS_PSK_WITH_AES_256_GCM_SHA384
+ *      MBEDTLS_TLS_PSK_WITH_AES_256_CBC_SHA384
+ *      MBEDTLS_TLS_PSK_WITH_AES_256_CBC_SHA
+ *      MBEDTLS_TLS_PSK_WITH_AES_128_GCM_SHA256
+ *      MBEDTLS_TLS_PSK_WITH_AES_128_CBC_SHA256
+ *      MBEDTLS_TLS_PSK_WITH_AES_128_CBC_SHA
+ *
+ * PEM_PARSE uses AES for decrypting encrypted keys.
+ */
+#define MBEDTLS_AES_C
+
+/**
+ * \def MBEDTLS_ARC4_C
+ *
+ * Enable the ARCFOUR stream cipher.
+ *
+ * Module:  library/arc4.c
+ * Caller:  library/ssl_tls.c
+ *
+ * This module enables the following ciphersuites (if other requisites are
+ * enabled as well):
+ *      MBEDTLS_TLS_ECDH_ECDSA_WITH_RC4_128_SHA
+ *      MBEDTLS_TLS_ECDH_RSA_WITH_RC4_128_SHA
+ *      MBEDTLS_TLS_ECDHE_ECDSA_WITH_RC4_128_SHA
+ *      MBEDTLS_TLS_ECDHE_RSA_WITH_RC4_128_SHA
+ *      MBEDTLS_TLS_ECDHE_PSK_WITH_RC4_128_SHA
+ *      MBEDTLS_TLS_DHE_PSK_WITH_RC4_128_SHA
+ *      MBEDTLS_TLS_RSA_WITH_RC4_128_SHA
+ *      MBEDTLS_TLS_RSA_WITH_RC4_128_MD5
+ *      MBEDTLS_TLS_RSA_PSK_WITH_RC4_128_SHA
+ *      MBEDTLS_TLS_PSK_WITH_RC4_128_SHA
+ */
+#define MBEDTLS_ARC4_C
+
+/**
+ * \def MBEDTLS_ASN1_PARSE_C
+ *
+ * Enable the generic ASN1 parser.
+ *
+ * Module:  library/asn1.c
+ * Caller:  library/x509.c
+ *          library/dhm.c
+ *          library/pkcs12.c
+ *          library/pkcs5.c
+ *          library/pkparse.c
+ */
+#define MBEDTLS_ASN1_PARSE_C
+
+/**
+ * \def MBEDTLS_ASN1_WRITE_C
+ *
+ * Enable the generic ASN1 writer.
+ *
+ * Module:  library/asn1write.c
+ * Caller:  library/ecdsa.c
+ *          library/pkwrite.c
+ *          library/x509_create.c
+ *          library/x509write_crt.c
+ *          library/mbedtls_x509write_csr.c
+ */
+#define MBEDTLS_ASN1_WRITE_C
+
+/**
+ * \def MBEDTLS_BASE64_C
+ *
+ * Enable the Base64 module.
+ *
+ * Module:  library/base64.c
+ * Caller:  library/pem.c
+ *
+ * This module is required for PEM support (required by X.509).
+ */
+#define MBEDTLS_BASE64_C
+
+/**
+ * \def MBEDTLS_BIGNUM_C
+ *
+ * Enable the multi-precision integer library.
+ *
+ * Module:  library/bignum.c
+ * Caller:  library/dhm.c
+ *          library/ecp.c
+ *          library/ecdsa.c
+ *          library/rsa.c
+ *          library/ssl_tls.c
+ *
+ * This module is required for RSA, DHM and ECC (ECDH, ECDSA) support.
+ */
+#define MBEDTLS_BIGNUM_C
+
+/**
+ * \def MBEDTLS_BLOWFISH_C
+ *
+ * Enable the Blowfish block cipher.
+ *
+ * Module:  library/blowfish.c
+ */
+#define MBEDTLS_BLOWFISH_C
+
+/**
+ * \def MBEDTLS_CAMELLIA_C
+ *
+ * Enable the Camellia block cipher.
+ *
+ * Module:  library/camellia.c
+ * Caller:  library/ssl_tls.c
+ *
+ * This module enables the following ciphersuites (if other requisites are
+ * enabled as well):
+ *      MBEDTLS_TLS_ECDH_ECDSA_WITH_CAMELLIA_128_CBC_SHA256
+ *      MBEDTLS_TLS_ECDH_ECDSA_WITH_CAMELLIA_256_CBC_SHA384
+ *      MBEDTLS_TLS_ECDH_RSA_WITH_CAMELLIA_128_CBC_SHA256
+ *      MBEDTLS_TLS_ECDH_RSA_WITH_CAMELLIA_256_CBC_SHA384
+ *      MBEDTLS_TLS_ECDH_ECDSA_WITH_CAMELLIA_128_GCM_SHA256
+ *      MBEDTLS_TLS_ECDH_ECDSA_WITH_CAMELLIA_256_GCM_SHA384
+ *      MBEDTLS_TLS_ECDH_RSA_WITH_CAMELLIA_128_GCM_SHA256
+ *      MBEDTLS_TLS_ECDH_RSA_WITH_CAMELLIA_256_GCM_SHA384
+ *      MBEDTLS_TLS_ECDHE_ECDSA_WITH_CAMELLIA_256_GCM_SHA384
+ *      MBEDTLS_TLS_ECDHE_RSA_WITH_CAMELLIA_256_GCM_SHA384
+ *      MBEDTLS_TLS_DHE_RSA_WITH_CAMELLIA_256_GCM_SHA384
+ *      MBEDTLS_TLS_ECDHE_ECDSA_WITH_CAMELLIA_256_CBC_SHA384
+ *      MBEDTLS_TLS_ECDHE_RSA_WITH_CAMELLIA_256_CBC_SHA384
+ *      MBEDTLS_TLS_DHE_RSA_WITH_CAMELLIA_256_CBC_SHA256
+ *      MBEDTLS_TLS_DHE_RSA_WITH_CAMELLIA_256_CBC_SHA
+ *      MBEDTLS_TLS_ECDHE_ECDSA_WITH_CAMELLIA_128_GCM_SHA256
+ *      MBEDTLS_TLS_ECDHE_RSA_WITH_CAMELLIA_128_GCM_SHA256
+ *      MBEDTLS_TLS_DHE_RSA_WITH_CAMELLIA_128_GCM_SHA256
+ *      MBEDTLS_TLS_ECDHE_ECDSA_WITH_CAMELLIA_128_CBC_SHA256
+ *      MBEDTLS_TLS_ECDHE_RSA_WITH_CAMELLIA_128_CBC_SHA256
+ *      MBEDTLS_TLS_DHE_RSA_WITH_CAMELLIA_128_CBC_SHA256
+ *      MBEDTLS_TLS_DHE_RSA_WITH_CAMELLIA_128_CBC_SHA
+ *      MBEDTLS_TLS_DHE_PSK_WITH_CAMELLIA_256_GCM_SHA384
+ *      MBEDTLS_TLS_ECDHE_PSK_WITH_CAMELLIA_256_CBC_SHA384
+ *      MBEDTLS_TLS_DHE_PSK_WITH_CAMELLIA_256_CBC_SHA384
+ *      MBEDTLS_TLS_DHE_PSK_WITH_CAMELLIA_128_GCM_SHA256
+ *      MBEDTLS_TLS_DHE_PSK_WITH_CAMELLIA_128_CBC_SHA256
+ *      MBEDTLS_TLS_ECDHE_PSK_WITH_CAMELLIA_128_CBC_SHA256
+ *      MBEDTLS_TLS_RSA_WITH_CAMELLIA_256_GCM_SHA384
+ *      MBEDTLS_TLS_RSA_WITH_CAMELLIA_256_CBC_SHA256
+ *      MBEDTLS_TLS_RSA_WITH_CAMELLIA_256_CBC_SHA
+ *      MBEDTLS_TLS_RSA_WITH_CAMELLIA_128_GCM_SHA256
+ *      MBEDTLS_TLS_RSA_WITH_CAMELLIA_128_CBC_SHA256
+ *      MBEDTLS_TLS_RSA_WITH_CAMELLIA_128_CBC_SHA
+ *      MBEDTLS_TLS_RSA_PSK_WITH_CAMELLIA_256_GCM_SHA384
+ *      MBEDTLS_TLS_RSA_PSK_WITH_CAMELLIA_256_CBC_SHA384
+ *      MBEDTLS_TLS_RSA_PSK_WITH_CAMELLIA_128_GCM_SHA256
+ *      MBEDTLS_TLS_RSA_PSK_WITH_CAMELLIA_128_CBC_SHA256
+ *      MBEDTLS_TLS_PSK_WITH_CAMELLIA_256_GCM_SHA384
+ *      MBEDTLS_TLS_PSK_WITH_CAMELLIA_256_CBC_SHA384
+ *      MBEDTLS_TLS_PSK_WITH_CAMELLIA_128_GCM_SHA256
+ *      MBEDTLS_TLS_PSK_WITH_CAMELLIA_128_CBC_SHA256
+ */
+#define MBEDTLS_CAMELLIA_C
+
+/**
+ * \def MBEDTLS_CCM_C
+ *
+ * Enable the Counter with CBC-MAC (CCM) mode for 128-bit block cipher.
+ *
+ * Module:  library/ccm.c
+ *
+ * Requires: MBEDTLS_AES_C or MBEDTLS_CAMELLIA_C
+ *
+ * This module enables the AES-CCM ciphersuites, if other requisites are
+ * enabled as well.
+ */
+#define MBEDTLS_CCM_C
+
+/**
+ * \def MBEDTLS_CERTS_C
+ *
+ * Enable the test certificates.
+ *
+ * Module:  library/certs.c
+ * Caller:
+ *
+ * This module is used for testing (ssl_client/server).
+ */
+#define MBEDTLS_CERTS_C
+
+/**
+ * \def MBEDTLS_CIPHER_C
+ *
+ * Enable the generic cipher layer.
+ *
+ * Module:  library/cipher.c
+ * Caller:  library/ssl_tls.c
+ *
+ * Uncomment to enable generic cipher wrappers.
+ */
+#define MBEDTLS_CIPHER_C
+
+/**
+ * \def MBEDTLS_CTR_DRBG_C
+ *
+ * Enable the CTR_DRBG AES-256-based random generator.
+ *
+ * Module:  library/ctr_drbg.c
+ * Caller:
+ *
+ * Requires: MBEDTLS_AES_C
+ *
+ * This module provides the CTR_DRBG AES-256 random number generator.
+ */
+#define MBEDTLS_CTR_DRBG_C
+
+/**
+ * \def MBEDTLS_DEBUG_C
+ *
+ * Enable the debug functions.
+ *
+ * Module:  library/debug.c
+ * Caller:  library/ssl_cli.c
+ *          library/ssl_srv.c
+ *          library/ssl_tls.c
+ *
+ * This module provides debugging functions.
+ */
+//#define MBEDTLS_DEBUG_C
+
+/**
+ * \def MBEDTLS_DES_C
+ *
+ * Enable the DES block cipher.
+ *
+ * Module:  library/des.c
+ * Caller:  library/pem.c
+ *          library/ssl_tls.c
+ *
+ * This module enables the following ciphersuites (if other requisites are
+ * enabled as well):
+ *      MBEDTLS_TLS_ECDH_ECDSA_WITH_3DES_EDE_CBC_SHA
+ *      MBEDTLS_TLS_ECDH_RSA_WITH_3DES_EDE_CBC_SHA
+ *      MBEDTLS_TLS_ECDHE_ECDSA_WITH_3DES_EDE_CBC_SHA
+ *      MBEDTLS_TLS_ECDHE_RSA_WITH_3DES_EDE_CBC_SHA
+ *      MBEDTLS_TLS_DHE_RSA_WITH_3DES_EDE_CBC_SHA
+ *      MBEDTLS_TLS_ECDHE_PSK_WITH_3DES_EDE_CBC_SHA
+ *      MBEDTLS_TLS_DHE_PSK_WITH_3DES_EDE_CBC_SHA
+ *      MBEDTLS_TLS_RSA_WITH_3DES_EDE_CBC_SHA
+ *      MBEDTLS_TLS_RSA_PSK_WITH_3DES_EDE_CBC_SHA
+ *      MBEDTLS_TLS_PSK_WITH_3DES_EDE_CBC_SHA
+ *
+ * PEM_PARSE uses DES/3DES for decrypting encrypted keys.
+ */
+#define MBEDTLS_DES_C
+
+/**
+ * \def MBEDTLS_DHM_C
+ *
+ * Enable the Diffie-Hellman-Merkle module.
+ *
+ * Module:  library/dhm.c
+ * Caller:  library/ssl_cli.c
+ *          library/ssl_srv.c
+ *
+ * This module is used by the following key exchanges:
+ *      DHE-RSA, DHE-PSK
+ */
+#define MBEDTLS_DHM_C
+
+/**
+ * \def MBEDTLS_ECDH_C
+ *
+ * Enable the elliptic curve Diffie-Hellman library.
+ *
+ * Module:  library/ecdh.c
+ * Caller:  library/ssl_cli.c
+ *          library/ssl_srv.c
+ *
+ * This module is used by the following key exchanges:
+ *      ECDHE-ECDSA, ECDHE-RSA, DHE-PSK
+ *
+ * Requires: MBEDTLS_ECP_C
+ */
+#define MBEDTLS_ECDH_C
+
+/**
+ * \def MBEDTLS_ECDSA_C
+ *
+ * Enable the elliptic curve DSA library.
+ *
+ * Module:  library/ecdsa.c
+ * Caller:
+ *
+ * This module is used by the following key exchanges:
+ *      ECDHE-ECDSA
+ *
+ * Requires: MBEDTLS_ECP_C, MBEDTLS_ASN1_WRITE_C, MBEDTLS_ASN1_PARSE_C
+ */
+#define MBEDTLS_ECDSA_C
+
+/**
+ * \def MBEDTLS_ECP_C
+ *
+ * Enable the elliptic curve over GF(p) library.
+ *
+ * Module:  library/ecp.c
+ * Caller:  library/ecdh.c
+ *          library/ecdsa.c
+ *
+ * Requires: MBEDTLS_BIGNUM_C and at least one MBEDTLS_ECP_DP_XXX_ENABLED
+ */
+#define MBEDTLS_ECP_C
+
+/**
+ * \def MBEDTLS_ENTROPY_C
+ *
+ * Enable the platform-specific entropy code.
+ *
+ * Module:  library/entropy.c
+ * Caller:
+ *
+ * Requires: MBEDTLS_SHA512_C or MBEDTLS_SHA256_C
+ *
+ * This module provides a generic entropy pool
+ */
+#define MBEDTLS_ENTROPY_C
+
+/**
+ * \def MBEDTLS_ERROR_C
+ *
+ * Enable error code to error string conversion.
+ *
+ * Module:  library/error.c
+ * Caller:
+ *
+ * This module enables mbedtls_strerror().
+ */
+#define MBEDTLS_ERROR_C
+
+/**
+ * \def MBEDTLS_GCM_C
+ *
+ * Enable the Galois/Counter Mode (GCM) for AES.
+ *
+ * Module:  library/gcm.c
+ *
+ * Requires: MBEDTLS_AES_C or MBEDTLS_CAMELLIA_C
+ *
+ * This module enables the AES-GCM and CAMELLIA-GCM ciphersuites, if other
+ * requisites are enabled as well.
+ */
+#define MBEDTLS_GCM_C
+
+/**
+ * \def MBEDTLS_HAVEGE_C
+ *
+ * Enable the HAVEGE random generator.
+ *
+ * Warning: the HAVEGE random generator is not suitable for virtualized
+ *          environments
+ *
+ * Warning: the HAVEGE random generator is dependent on timing and specific
+ *          processor traits. It is therefore not advised to use HAVEGE as
+ *          your applications primary random generator or primary entropy pool
+ *          input. As a secondary input to your entropy pool, it IS able add
+ *          the (limited) extra entropy it provides.
+ *
+ * Module:  library/havege.c
+ * Caller:
+ *
+ * Requires: MBEDTLS_TIMING_C
+ *
+ * Uncomment to enable the HAVEGE random generator.
+ */
+//#define MBEDTLS_HAVEGE_C
+
+/**
+ * \def MBEDTLS_HMAC_DRBG_C
+ *
+ * Enable the HMAC_DRBG random generator.
+ *
+ * Module:  library/hmac_drbg.c
+ * Caller:
+ *
+ * Requires: MBEDTLS_MD_C
+ *
+ * Uncomment to enable the HMAC_DRBG random number geerator.
+ */
+#define MBEDTLS_HMAC_DRBG_C
+
+/**
+ * \def MBEDTLS_MD_C
+ *
+ * Enable the generic message digest layer.
+ *
+ * Module:  library/mbedtls_md.c
+ * Caller:
+ *
+ * Uncomment to enable generic message digest wrappers.
+ */
+#define MBEDTLS_MD_C
+
+/**
+ * \def MBEDTLS_MD2_C
+ *
+ * Enable the MD2 hash algorithm.
+ *
+ * Module:  library/mbedtls_md2.c
+ * Caller:
+ *
+ * Uncomment to enable support for (rare) MD2-signed X.509 certs.
+ */
+//#define MBEDTLS_MD2_C
+
+/**
+ * \def MBEDTLS_MD4_C
+ *
+ * Enable the MD4 hash algorithm.
+ *
+ * Module:  library/mbedtls_md4.c
+ * Caller:
+ *
+ * Uncomment to enable support for (rare) MD4-signed X.509 certs.
+ */
+//#define MBEDTLS_MD4_C
+
+/**
+ * \def MBEDTLS_MD5_C
+ *
+ * Enable the MD5 hash algorithm.
+ *
+ * Module:  library/mbedtls_md5.c
+ * Caller:  library/mbedtls_md.c
+ *          library/pem.c
+ *          library/ssl_tls.c
+ *
+ * This module is required for SSL/TLS and X.509.
+ * PEM_PARSE uses MD5 for decrypting encrypted keys.
+ */
+#define MBEDTLS_MD5_C
+
+/**
+ * \def MBEDTLS_MEMORY_BUFFER_ALLOC_C
+ *
+ * Enable the buffer allocator implementation that makes use of a (stack)
+ * based buffer to 'allocate' dynamic memory. (replaces calloc() and free()
+ * calls)
+ *
+ * Module:  library/memory_buffer_alloc.c
+ *
+ * Requires: MBEDTLS_PLATFORM_C
+ *           MBEDTLS_PLATFORM_MEMORY (to use it within mbed TLS)
+ *
+ * Enable this module to enable the buffer memory allocator.
+ */
+//#define MBEDTLS_MEMORY_BUFFER_ALLOC_C
+
+/**
+ * \def MBEDTLS_NET_C
+ *
+ * Enable the TCP/IP networking routines.
+ *
+ * Module:  library/net.c
+ *
+ * This module provides TCP/IP networking routines.
+ */
+#define MBEDTLS_NET_C
+
+/**
+ * \def MBEDTLS_OID_C
+ *
+ * Enable the OID database.
+ *
+ * Module:  library/oid.c
+ * Caller:  library/asn1write.c
+ *          library/pkcs5.c
+ *          library/pkparse.c
+ *          library/pkwrite.c
+ *          library/rsa.c
+ *          library/x509.c
+ *          library/x509_create.c
+ *          library/mbedtls_x509_crl.c
+ *          library/mbedtls_x509_crt.c
+ *          library/mbedtls_x509_csr.c
+ *          library/x509write_crt.c
+ *          library/mbedtls_x509write_csr.c
+ *
+ * This modules translates between OIDs and internal values.
+ */
+#define MBEDTLS_OID_C
+
+/**
+ * \def MBEDTLS_PADLOCK_C
+ *
+ * Enable VIA Padlock support on x86.
+ *
+ * Module:  library/padlock.c
+ * Caller:  library/aes.c
+ *
+ * Requires: MBEDTLS_HAVE_ASM
+ *
+ * This modules adds support for the VIA PadLock on x86.
+ */
+#define MBEDTLS_PADLOCK_C
+
+/**
+ * \def MBEDTLS_PEM_PARSE_C
+ *
+ * Enable PEM decoding / parsing.
+ *
+ * Module:  library/pem.c
+ * Caller:  library/dhm.c
+ *          library/pkparse.c
+ *          library/mbedtls_x509_crl.c
+ *          library/mbedtls_x509_crt.c
+ *          library/mbedtls_x509_csr.c
+ *
+ * Requires: MBEDTLS_BASE64_C
+ *
+ * This modules adds support for decoding / parsing PEM files.
+ */
+#define MBEDTLS_PEM_PARSE_C
+
+/**
+ * \def MBEDTLS_PEM_WRITE_C
+ *
+ * Enable PEM encoding / writing.
+ *
+ * Module:  library/pem.c
+ * Caller:  library/pkwrite.c
+ *          library/x509write_crt.c
+ *          library/mbedtls_x509write_csr.c
+ *
+ * Requires: MBEDTLS_BASE64_C
+ *
+ * This modules adds support for encoding / writing PEM files.
+ */
+#define MBEDTLS_PEM_WRITE_C
+
+/**
+ * \def MBEDTLS_PK_C
+ *
+ * Enable the generic public (asymetric) key layer.
+ *
+ * Module:  library/pk.c
+ * Caller:  library/ssl_tls.c
+ *          library/ssl_cli.c
+ *          library/ssl_srv.c
+ *
+ * Requires: MBEDTLS_RSA_C or MBEDTLS_ECP_C
+ *
+ * Uncomment to enable generic public key wrappers.
+ */
+#define MBEDTLS_PK_C
+
+/**
+ * \def MBEDTLS_PK_PARSE_C
+ *
+ * Enable the generic public (asymetric) key parser.
+ *
+ * Module:  library/pkparse.c
+ * Caller:  library/mbedtls_x509_crt.c
+ *          library/mbedtls_x509_csr.c
+ *
+ * Requires: MBEDTLS_PK_C
+ *
+ * Uncomment to enable generic public key parse functions.
+ */
+#define MBEDTLS_PK_PARSE_C
+
+/**
+ * \def MBEDTLS_PK_WRITE_C
+ *
+ * Enable the generic public (asymetric) key writer.
+ *
+ * Module:  library/pkwrite.c
+ * Caller:  library/x509write.c
+ *
+ * Requires: MBEDTLS_PK_C
+ *
+ * Uncomment to enable generic public key write functions.
+ */
+#define MBEDTLS_PK_WRITE_C
+
+/**
+ * \def MBEDTLS_PKCS5_C
+ *
+ * Enable PKCS#5 functions.
+ *
+ * Module:  library/pkcs5.c
+ *
+ * Requires: MBEDTLS_MD_C
+ *
+ * This module adds support for the PKCS#5 functions.
+ */
+#define MBEDTLS_PKCS5_C
+
+/**
+ * \def MBEDTLS_PKCS11_C
+ *
+ * Enable wrapper for PKCS#11 smartcard support.
+ *
+ * Module:  library/pkcs11.c
+ * Caller:  library/pk.c
+ *
+ * Requires: MBEDTLS_PK_C
+ *
+ * This module enables SSL/TLS PKCS #11 smartcard support.
+ * Requires the presence of the PKCS#11 helper library (libpkcs11-helper)
+ */
+//#define MBEDTLS_PKCS11_C
+
+/**
+ * \def MBEDTLS_PKCS12_C
+ *
+ * Enable PKCS#12 PBE functions.
+ * Adds algorithms for parsing PKCS#8 encrypted private keys
+ *
+ * Module:  library/pkcs12.c
+ * Caller:  library/pkparse.c
+ *
+ * Requires: MBEDTLS_ASN1_PARSE_C, MBEDTLS_CIPHER_C, MBEDTLS_MD_C
+ * Can use:  MBEDTLS_ARC4_C
+ *
+ * This module enables PKCS#12 functions.
+ */
+#define MBEDTLS_PKCS12_C
+
+/**
+ * \def MBEDTLS_PLATFORM_C
+ *
+ * Enable the platform abstraction layer that allows you to re-assign
+ * functions like calloc(), free(), snprintf(), printf(), fprintf(), exit().
+ *
+ * Enabling MBEDTLS_PLATFORM_C enables to use of MBEDTLS_PLATFORM_XXX_ALT
+ * or MBEDTLS_PLATFORM_XXX_MACRO directives, allowing the functions mentioned
+ * above to be specified at runtime or compile time respectively.
+ *
+ * \note This abstraction layer must be enabled on Windows (including MSYS2)
+ * as other module rely on it for a fixed snprintf implementation.
+ *
+ * Module:  library/platform.c
+ * Caller:  Most other .c files
+ *
+ * This module enables abstraction of common (libc) functions.
+ */
+#define MBEDTLS_PLATFORM_C
+
+/**
+ * \def MBEDTLS_RIPEMD160_C
+ *
+ * Enable the RIPEMD-160 hash algorithm.
+ *
+ * Module:  library/mbedtls_ripemd160.c
+ * Caller:  library/mbedtls_md.c
+ *
+ */
+#define MBEDTLS_RIPEMD160_C
+
+/**
+ * \def MBEDTLS_RSA_C
+ *
+ * Enable the RSA public-key cryptosystem.
+ *
+ * Module:  library/rsa.c
+ * Caller:  library/ssl_cli.c
+ *          library/ssl_srv.c
+ *          library/ssl_tls.c
+ *          library/x509.c
+ *
+ * This module is used by the following key exchanges:
+ *      RSA, DHE-RSA, ECDHE-RSA, RSA-PSK
+ *
+ * Requires: MBEDTLS_BIGNUM_C, MBEDTLS_OID_C
+ */
+#define MBEDTLS_RSA_C
+
+/**
+ * \def MBEDTLS_SHA1_C
+ *
+ * Enable the SHA1 cryptographic hash algorithm.
+ *
+ * Module:  library/mbedtls_sha1.c
+ * Caller:  library/mbedtls_md.c
+ *          library/ssl_cli.c
+ *          library/ssl_srv.c
+ *          library/ssl_tls.c
+ *          library/x509write_crt.c
+ *
+ * This module is required for SSL/TLS and SHA1-signed certificates.
+ */
+#define MBEDTLS_SHA1_C
+
+/**
+ * \def MBEDTLS_SHA256_C
+ *
+ * Enable the SHA-224 and SHA-256 cryptographic hash algorithms.
+ *
+ * Module:  library/mbedtls_sha256.c
+ * Caller:  library/entropy.c
+ *          library/mbedtls_md.c
+ *          library/ssl_cli.c
+ *          library/ssl_srv.c
+ *          library/ssl_tls.c
+ *
+ * This module adds support for SHA-224 and SHA-256.
+ * This module is required for the SSL/TLS 1.2 PRF function.
+ */
+#define MBEDTLS_SHA256_C
+
+/**
+ * \def MBEDTLS_SHA512_C
+ *
+ * Enable the SHA-384 and SHA-512 cryptographic hash algorithms.
+ *
+ * Module:  library/mbedtls_sha512.c
+ * Caller:  library/entropy.c
+ *          library/mbedtls_md.c
+ *          library/ssl_cli.c
+ *          library/ssl_srv.c
+ *
+ * This module adds support for SHA-384 and SHA-512.
+ */
+#define MBEDTLS_SHA512_C
+
+/**
+ * \def MBEDTLS_SSL_CACHE_C
+ *
+ * Enable simple SSL cache implementation.
+ *
+ * Module:  library/ssl_cache.c
+ * Caller:
+ *
+ * Requires: MBEDTLS_SSL_CACHE_C
+ */
+#define MBEDTLS_SSL_CACHE_C
+
+/**
+ * \def MBEDTLS_SSL_COOKIE_C
+ *
+ * Enable basic implementation of DTLS cookies for hello verification.
+ *
+ * Module:  library/ssl_cookie.c
+ * Caller:
+ */
+#define MBEDTLS_SSL_COOKIE_C
+
+/**
+ * \def MBEDTLS_SSL_TICKET_C
+ *
+ * Enable an implementation of TLS server-side callbacks for session tickets.
+ *
+ * Module:  library/ssl_ticket.c
+ * Caller:
+ *
+ * Requires: MBEDTLS_CIPHER_C
+ */
+#define MBEDTLS_SSL_TICKET_C
+
+/**
+ * \def MBEDTLS_SSL_CLI_C
+ *
+ * Enable the SSL/TLS client code.
+ *
+ * Module:  library/ssl_cli.c
+ * Caller:
+ *
+ * Requires: MBEDTLS_SSL_TLS_C
+ *
+ * This module is required for SSL/TLS client support.
+ */
+#define MBEDTLS_SSL_CLI_C
+
+/**
+ * \def MBEDTLS_SSL_SRV_C
+ *
+ * Enable the SSL/TLS server code.
+ *
+ * Module:  library/ssl_srv.c
+ * Caller:
+ *
+ * Requires: MBEDTLS_SSL_TLS_C
+ *
+ * This module is required for SSL/TLS server support.
+ */
+#define MBEDTLS_SSL_SRV_C
+
+/**
+ * \def MBEDTLS_SSL_TLS_C
+ *
+ * Enable the generic SSL/TLS code.
+ *
+ * Module:  library/ssl_tls.c
+ * Caller:  library/ssl_cli.c
+ *          library/ssl_srv.c
+ *
+ * Requires: MBEDTLS_CIPHER_C, MBEDTLS_MD_C
+ *           and at least one of the MBEDTLS_SSL_PROTO_XXX defines
+ *
+ * This module is required for SSL/TLS.
+ */
+#define MBEDTLS_SSL_TLS_C
+
+/**
+ * \def MBEDTLS_THREADING_C
+ *
+ * Enable the threading abstraction layer.
+ * By default mbed TLS assumes it is used in a non-threaded environment or that
+ * contexts are not shared between threads. If you do intend to use contexts
+ * between threads, you will need to enable this layer to prevent race
+ * conditions.
+ *
+ * Module:  library/threading.c
+ *
+ * This allows different threading implementations (self-implemented or
+ * provided).
+ *
+ * You will have to enable either MBEDTLS_THREADING_ALT or
+ * MBEDTLS_THREADING_PTHREAD.
+ *
+ * Enable this layer to allow use of mutexes within mbed TLS
+ */
+//#define MBEDTLS_THREADING_C
+
+/**
+ * \def MBEDTLS_TIMING_C
+ *
+ * Enable the portable timing interface.
+ *
+ * Module:  library/timing.c
+ * Caller:  library/havege.c
+ *
+ * This module is used by the HAVEGE random number generator.
+ */
+//#define MBEDTLS_TIMING_C
+
+/**
+ * \def MBEDTLS_VERSION_C
+ *
+ * Enable run-time version information.
+ *
+ * Module:  library/version.c
+ *
+ * This module provides run-time version information.
+ */
+#define MBEDTLS_VERSION_C
+
+/**
+ * \def MBEDTLS_X509_USE_C
+ *
+ * Enable X.509 core for using certificates.
+ *
+ * Module:  library/x509.c
+ * Caller:  library/mbedtls_x509_crl.c
+ *          library/mbedtls_x509_crt.c
+ *          library/mbedtls_x509_csr.c
+ *
+ * Requires: MBEDTLS_ASN1_PARSE_C, MBEDTLS_BIGNUM_C, MBEDTLS_OID_C,
+ *           MBEDTLS_PK_PARSE_C
+ *
+ * This module is required for the X.509 parsing modules.
+ */
+#define MBEDTLS_X509_USE_C
+
+/**
+ * \def MBEDTLS_X509_CRT_PARSE_C
+ *
+ * Enable X.509 certificate parsing.
+ *
+ * Module:  library/mbedtls_x509_crt.c
+ * Caller:  library/ssl_cli.c
+ *          library/ssl_srv.c
+ *          library/ssl_tls.c
+ *
+ * Requires: MBEDTLS_X509_USE_C
+ *
+ * This module is required for X.509 certificate parsing.
+ */
+#define MBEDTLS_X509_CRT_PARSE_C
+
+/**
+ * \def MBEDTLS_X509_CRL_PARSE_C
+ *
+ * Enable X.509 CRL parsing.
+ *
+ * Module:  library/mbedtls_x509_crl.c
+ * Caller:  library/mbedtls_x509_crt.c
+ *
+ * Requires: MBEDTLS_X509_USE_C
+ *
+ * This module is required for X.509 CRL parsing.
+ */
+#define MBEDTLS_X509_CRL_PARSE_C
+
+/**
+ * \def MBEDTLS_X509_CSR_PARSE_C
+ *
+ * Enable X.509 Certificate Signing Request (CSR) parsing.
+ *
+ * Module:  library/mbedtls_x509_csr.c
+ * Caller:  library/x509_crt_write.c
+ *
+ * Requires: MBEDTLS_X509_USE_C
+ *
+ * This module is used for reading X.509 certificate request.
+ */
+#define MBEDTLS_X509_CSR_PARSE_C
+
+/**
+ * \def MBEDTLS_X509_CREATE_C
+ *
+ * Enable X.509 core for creating certificates.
+ *
+ * Module:  library/x509_create.c
+ *
+ * Requires: MBEDTLS_BIGNUM_C, MBEDTLS_OID_C, MBEDTLS_PK_WRITE_C
+ *
+ * This module is the basis for creating X.509 certificates and CSRs.
+ */
+#define MBEDTLS_X509_CREATE_C
+
+/**
+ * \def MBEDTLS_X509_CRT_WRITE_C
+ *
+ * Enable creating X.509 certificates.
+ *
+ * Module:  library/x509_crt_write.c
+ *
+ * Requires: MBEDTLS_X509_CREATE_C
+ *
+ * This module is required for X.509 certificate creation.
+ */
+#define MBEDTLS_X509_CRT_WRITE_C
+
+/**
+ * \def MBEDTLS_X509_CSR_WRITE_C
+ *
+ * Enable creating X.509 Certificate Signing Requests (CSR).
+ *
+ * Module:  library/x509_csr_write.c
+ *
+ * Requires: MBEDTLS_X509_CREATE_C
+ *
+ * This module is required for X.509 certificate request writing.
+ */
+#define MBEDTLS_X509_CSR_WRITE_C
+
+/**
+ * \def MBEDTLS_XTEA_C
+ *
+ * Enable the XTEA block cipher.
+ *
+ * Module:  library/xtea.c
+ * Caller:
+ */
+#define MBEDTLS_XTEA_C
+
+/* \} name SECTION: mbed TLS modules */
+
+/**
+ * \name SECTION: Module configuration options
+ *
+ * This section allows for the setting of module specific sizes and
+ * configuration options. The default values are already present in the
+ * relevant header files and should suffice for the regular use cases.
+ *
+ * Our advice is to enable options and change their values here
+ * only if you have a good reason and know the consequences.
+ *
+ * Please check the respective header file for documentation on these
+ * parameters (to prevent duplicate documentation).
+ * \{
+ */
+
+/* MPI / BIGNUM options */
+#define MBEDTLS_MPI_WINDOW_SIZE            1 /**< Maximum windows size used. */
+#define MBEDTLS_MPI_MAX_SIZE            512 /**< Maximum number of bytes for usable MPIs. */
+
+/* CTR_DRBG options */
+//#define MBEDTLS_CTR_DRBG_ENTROPY_LEN               48 /**< Amount of entropy used per seed by default (48 with SHA-512, 32 with SHA-256) */
+/* this is normally 10x higher, but reseeding seems quite inexpensive on esp8266 */
+#define MBEDTLS_CTR_DRBG_RESEED_INTERVAL        1000 /**< Interval before reseed is performed by default */
+//#define MBEDTLS_CTR_DRBG_MAX_INPUT                256 /**< Maximum number of additional input bytes */
+//#define MBEDTLS_CTR_DRBG_MAX_REQUEST             1024 /**< Maximum number of requested bytes per call */
+//#define MBEDTLS_CTR_DRBG_MAX_SEED_INPUT           384 /**< Maximum size of (re)seed buffer */
+
+/* HMAC_DRBG options */
+//#define MBEDTLS_HMAC_DRBG_RESEED_INTERVAL   10000 /**< Interval before reseed is performed by default */
+//#define MBEDTLS_HMAC_DRBG_MAX_INPUT           256 /**< Maximum number of additional input bytes */
+//#define MBEDTLS_HMAC_DRBG_MAX_REQUEST        1024 /**< Maximum number of requested bytes per call */
+//#define MBEDTLS_HMAC_DRBG_MAX_SEED_INPUT      384 /**< Maximum size of (re)seed buffer */
+
+/* ECP options */
+//#define MBEDTLS_ECP_MAX_BITS             521 /**< Maximum bit size of groups */
+#define MBEDTLS_ECP_WINDOW_SIZE            2 /**< Maximum window size used */
+#define MBEDTLS_ECP_FIXED_POINT_OPTIM      0 /**< Enable fixed-point speed-up */
+
+/* Entropy options */
+//#define MBEDTLS_ENTROPY_MAX_SOURCES                20 /**< Maximum number of sources supported */
+//#define MBEDTLS_ENTROPY_MAX_GATHER                128 /**< Maximum amount requested from entropy sources */
+
+/* Memory buffer allocator options */
+//#define MBEDTLS_MEMORY_ALIGN_MULTIPLE      4 /**< Align on multiples of this value */
+
+/* Platform options */
+//#define MBEDTLS_PLATFORM_STD_MEM_HDR   <stdlib.h> /**< Header to include if MBEDTLS_PLATFORM_NO_STD_FUNCTIONS is defined. Don't define if no header is needed. */
+//#define MBEDTLS_PLATFORM_STD_CALLOC        calloc /**< Default allocator to use, can be undefined */
+//#define MBEDTLS_PLATFORM_STD_FREE            free /**< Default free to use, can be undefined */
+//#define MBEDTLS_PLATFORM_STD_EXIT            exit /**< Default exit to use, can be undefined */
+//#define MBEDTLS_PLATFORM_STD_FPRINTF      fprintf /**< Default fprintf to use, can be undefined */
+//#define MBEDTLS_PLATFORM_STD_PRINTF        printf /**< Default printf to use, can be undefined */
+/* Note: your snprintf must correclty zero-terminate the buffer! */
+//#define MBEDTLS_PLATFORM_STD_SNPRINTF    snprintf /**< Default snprintf to use, can be undefined */
+
+/* To Use Function Macros MBEDTLS_PLATFORM_C must be enabled */
+/* MBEDTLS_PLATFORM_XXX_MACRO and MBEDTLS_PLATFORM_XXX_ALT cannot both be defined */
+//#define MBEDTLS_PLATFORM_CALLOC_MACRO        calloc /**< Default allocator macro to use, can be undefined */
+//#define MBEDTLS_PLATFORM_FREE_MACRO            free /**< Default free macro to use, can be undefined */
+//#define MBEDTLS_PLATFORM_EXIT_MACRO            exit /**< Default exit macro to use, can be undefined */
+//#define MBEDTLS_PLATFORM_FPRINTF_MACRO      fprintf /**< Default fprintf macro to use, can be undefined */
+//#define MBEDTLS_PLATFORM_PRINTF_MACRO        printf /**< Default printf macro to use, can be undefined */
+/* Note: your snprintf must correclty zero-terminate the buffer! */
+//#define MBEDTLS_PLATFORM_SNPRINTF_MACRO    snprintf /**< Default snprintf macro to use, can be undefined */
+
+/* SSL Cache options */
+//#define MBEDTLS_SSL_CACHE_DEFAULT_TIMEOUT       86400 /**< 1 day  */
+//#define MBEDTLS_SSL_CACHE_DEFAULT_MAX_ENTRIES      50 /**< Maximum entries in cache */
+
+/* SSL options */
+#define MBEDTLS_SSL_MAX_CONTENT_LEN             4096 /**< Maxium fragment length in bytes, determines the size of each of the two internal I/O buffers */
+//#define MBEDTLS_SSL_DEFAULT_TICKET_LIFETIME     86400 /**< Lifetime of session tickets (if enabled) */
+//#define MBEDTLS_PSK_MAX_LEN               32 /**< Max size of TLS pre-shared keys, in bytes (default 256 bits) */
+//#define MBEDTLS_SSL_COOKIE_TIMEOUT        60 /**< Default expiration delay of DTLS cookies, in seconds if HAVE_TIME, or in number of cookies issued */
+
+/**
+ * Complete list of ciphersuites to use, in order of preference.
+ *
+ * \warning No dependency checking is done on that field! This option can only
+ * be used to restrict the set of available ciphersuites. It is your
+ * responsibility to make sure the needed modules are active.
+ *
+ * Use this to save a few hundred bytes of ROM (default ordering of all
+ * available ciphersuites) and a few to a few hundred bytes of RAM.
+ *
+ * The value below is only an example, not the default.
+ */
+//#define MBEDTLS_SSL_CIPHERSUITES MBEDTLS_TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384,MBEDTLS_TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256
+
+/* X509 options */
+//#define MBEDTLS_X509_MAX_INTERMEDIATE_CA   8   /**< Maximum number of intermediate CAs in a verification chain. */
+
+/* \} name SECTION: Module configuration options */
+
+#if defined(TARGET_LIKE_MBED)
+#include "mbedtls/target_config.h"
+#endif
+
+/*
+ * Allow user to override any previous default.
+ *
+ * Use two macro names for that, as:
+ * - with yotta the prefix YOTTA_CFG_ is forced
+ * - without yotta is looks weird to have a YOTTA prefix.
+ */
+#if defined(YOTTA_CFG_MBEDTLS_USER_CONFIG_FILE)
+#include YOTTA_CFG_MBEDTLS_USER_CONFIG_FILE
+#elif defined(MBEDTLS_USER_CONFIG_FILE)
+#include MBEDTLS_USER_CONFIG_FILE
+#endif
+
+#include "mbedtls/check_config.h"
+
+#endif /* MBEDTLS_CONFIG_H */
diff --git a/extras/mbedtls/mbedtls b/extras/mbedtls/mbedtls
new file mode 160000
index 0000000..0a0c22e
--- /dev/null
+++ b/extras/mbedtls/mbedtls
@@ -0,0 +1 @@
+Subproject commit 0a0c22e0efcf2f8f71d7e16712f80b8f77326f72
diff --git a/extras/mbedtls/net_lwip.c b/extras/mbedtls/net_lwip.c
new file mode 100644
index 0000000..10dba89
--- /dev/null
+++ b/extras/mbedtls/net_lwip.c
@@ -0,0 +1,510 @@
+/*
+ *  TCP/IP or UDP/IP networking functions
+ *  modified for LWIP support on ESP8266
+ *
+ *  Copyright (C) 2006-2015, ARM Limited, All Rights Reserved
+ *  Additions Copyright (C) 2015 Angus Gratton
+ *  SPDX-License-Identifier: Apache-2.0
+ *
+ *  Licensed under the Apache License, Version 2.0 (the "License"); you may
+ *  not use this file except in compliance with the License.
+ *  You may obtain a copy of the License at
+ *
+ *  http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *  Unless required by applicable law or agreed to in writing, software
+ *  distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ *  WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ *  See the License for the specific language governing permissions and
+ *  limitations under the License.
+ *
+ *  This file is part of mbed TLS (https://tls.mbed.org)
+ */
+
+#if !defined(MBEDTLS_CONFIG_FILE)
+#include "mbedtls/config.h"
+#else
+#include MBEDTLS_CONFIG_FILE
+#endif
+
+#if defined(MBEDTLS_NET_C)
+
+#include "mbedtls/net.h"
+
+#include <string.h>
+
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <sys/time.h>
+#include <unistd.h>
+#include <netdb.h>
+#include <errno.h>
+
+#include <stdlib.h>
+#include <stdio.h>
+
+#include <time.h>
+
+#include <stdint.h>
+
+/*
+ * Prepare for using the sockets interface
+ */
+static int net_prepare( void )
+{
+#if ( defined(_WIN32) || defined(_WIN32_WCE) ) && !defined(EFIX64) && \
+    !defined(EFI32)
+    WSADATA wsaData;
+
+    if( wsa_init_done == 0 )
+    {
+        if( WSAStartup( MAKEWORD(2,0), &wsaData ) != 0 )
+            return( MBEDTLS_ERR_NET_SOCKET_FAILED );
+
+        wsa_init_done = 1;
+    }
+#else
+#endif
+    return( 0 );
+}
+
+/*
+ * Initialize a context
+ */
+void mbedtls_net_init( mbedtls_net_context *ctx )
+{
+    ctx->fd = -1;
+}
+
+/*
+ * Initiate a TCP connection with host:port and the given protocol
+ */
+int mbedtls_net_connect( mbedtls_net_context *ctx, const char *host, const char *port, int proto )
+{
+    int ret;
+    struct addrinfo hints, *addr_list, *cur;
+
+    if( ( ret = net_prepare() ) != 0 )
+        return( ret );
+
+    /* Do name resolution with both IPv6 and IPv4 */
+    memset( &hints, 0, sizeof( hints ) );
+    hints.ai_family = AF_UNSPEC;
+    hints.ai_socktype = proto == MBEDTLS_NET_PROTO_UDP ? SOCK_DGRAM : SOCK_STREAM;
+    hints.ai_protocol = proto == MBEDTLS_NET_PROTO_UDP ? IPPROTO_UDP : IPPROTO_TCP;
+
+    if( getaddrinfo( host, port, &hints, &addr_list ) != 0 )
+        return( MBEDTLS_ERR_NET_UNKNOWN_HOST );
+
+    /* Try the sockaddrs until a connection succeeds */
+    ret = MBEDTLS_ERR_NET_UNKNOWN_HOST;
+    for( cur = addr_list; cur != NULL; cur = cur->ai_next )
+    {
+        ctx->fd = (int) socket( cur->ai_family, cur->ai_socktype,
+                            cur->ai_protocol );
+        if( ctx->fd < 0 )
+        {
+            ret = MBEDTLS_ERR_NET_SOCKET_FAILED;
+            continue;
+        }
+
+        if( connect( ctx->fd, cur->ai_addr, cur->ai_addrlen ) == 0 )
+        {
+            ret = 0;
+            break;
+        }
+
+        close( ctx->fd );
+        ret = MBEDTLS_ERR_NET_CONNECT_FAILED;
+    }
+
+    freeaddrinfo( addr_list );
+
+    return( ret );
+}
+
+/*
+ * Create a listening socket on bind_ip:port
+ */
+int mbedtls_net_bind( mbedtls_net_context *ctx, const char *bind_ip, const char *port, int proto )
+{
+    int n, ret;
+    struct addrinfo hints, *addr_list, *cur;
+
+    if( ( ret = net_prepare() ) != 0 )
+        return( ret );
+
+    /* Bind to IPv6 and/or IPv4, but only in the desired protocol */
+    memset( &hints, 0, sizeof( hints ) );
+    hints.ai_family = AF_UNSPEC;
+    hints.ai_socktype = proto == MBEDTLS_NET_PROTO_UDP ? SOCK_DGRAM : SOCK_STREAM;
+    hints.ai_protocol = proto == MBEDTLS_NET_PROTO_UDP ? IPPROTO_UDP : IPPROTO_TCP;
+
+    if( getaddrinfo( bind_ip, port, &hints, &addr_list ) != 0 )
+        return( MBEDTLS_ERR_NET_UNKNOWN_HOST );
+
+    /* Try the sockaddrs until a binding succeeds */
+    ret = MBEDTLS_ERR_NET_UNKNOWN_HOST;
+    for( cur = addr_list; cur != NULL; cur = cur->ai_next )
+    {
+        ctx->fd = (int) socket( cur->ai_family, cur->ai_socktype,
+                            cur->ai_protocol );
+        if( ctx->fd < 0 )
+        {
+            ret = MBEDTLS_ERR_NET_SOCKET_FAILED;
+            continue;
+        }
+
+        n = 1;
+        if( setsockopt( ctx->fd, SOL_SOCKET, SO_REUSEADDR,
+                        (const char *) &n, sizeof( n ) ) != 0 )
+        {
+            close( ctx->fd );
+            ret = MBEDTLS_ERR_NET_SOCKET_FAILED;
+            continue;
+        }
+
+        if( bind( ctx->fd, cur->ai_addr, cur->ai_addrlen ) != 0 )
+        {
+            close( ctx->fd );
+            ret = MBEDTLS_ERR_NET_BIND_FAILED;
+            continue;
+        }
+
+        /* Listen only makes sense for TCP */
+        if( proto == MBEDTLS_NET_PROTO_TCP )
+        {
+            if( listen( ctx->fd, MBEDTLS_NET_LISTEN_BACKLOG ) != 0 )
+            {
+                close( ctx->fd );
+                ret = MBEDTLS_ERR_NET_LISTEN_FAILED;
+                continue;
+            }
+        }
+
+        /* I we ever get there, it's a success */
+        ret = 0;
+        break;
+    }
+
+    freeaddrinfo( addr_list );
+
+    return( ret );
+
+}
+
+#if ( defined(_WIN32) || defined(_WIN32_WCE) ) && !defined(EFIX64) && \
+    !defined(EFI32)
+/*
+ * Check if the requested operation would be blocking on a non-blocking socket
+ * and thus 'failed' with a negative return value.
+ */
+static int net_would_block( const mbedtls_net_context *ctx )
+{
+    ((void) ctx);
+    return( WSAGetLastError() == WSAEWOULDBLOCK );
+}
+#else
+/*
+ * Check if the requested operation would be blocking on a non-blocking socket
+ * and thus 'failed' with a negative return value.
+ *
+ * Note: on a blocking socket this function always returns 0!
+ */
+static int net_would_block( const mbedtls_net_context *ctx )
+{
+    /*
+     * Never return 'WOULD BLOCK' on a non-blocking socket
+     */
+    if( ( fcntl( ctx->fd, F_GETFL, 0) & O_NONBLOCK ) != O_NONBLOCK )
+        return( 0 );
+
+    switch( errno )
+    {
+#if defined EAGAIN
+        case EAGAIN:
+#endif
+#if defined EWOULDBLOCK && EWOULDBLOCK != EAGAIN
+        case EWOULDBLOCK:
+#endif
+            return( 1 );
+    }
+    return( 0 );
+}
+#endif /* ( _WIN32 || _WIN32_WCE ) && !EFIX64 && !EFI32 */
+
+/*
+ * Accept a connection from a remote client
+ */
+int mbedtls_net_accept( mbedtls_net_context *bind_ctx,
+                        mbedtls_net_context *client_ctx,
+                        void *client_ip, size_t buf_size, size_t *ip_len )
+{
+    int ret;
+    int type;
+
+    struct sockaddr_in client_addr;
+
+    socklen_t n = (socklen_t) sizeof( client_addr );
+    socklen_t type_len = (socklen_t) sizeof( type );
+
+    /* Is this a TCP or UDP socket? */
+    if( getsockopt( bind_ctx->fd, SOL_SOCKET, SO_TYPE,
+                    (void *) &type, (socklen_t *) &type_len ) != 0 ||
+        ( type != SOCK_STREAM && type != SOCK_DGRAM ) )
+    {
+        return( MBEDTLS_ERR_NET_ACCEPT_FAILED );
+    }
+
+    if( type == SOCK_STREAM )
+    {
+        /* TCP: actual accept() */
+        ret = client_ctx->fd = (int) accept( bind_ctx->fd,
+                                             (struct sockaddr *) &client_addr, &n );
+    }
+    else
+    {
+        /* UDP: wait for a message, but keep it in the queue */
+        char buf[1] = { 0 };
+
+        ret = recvfrom( bind_ctx->fd, buf, sizeof( buf ), MSG_PEEK,
+                        (struct sockaddr *) &client_addr, &n );
+
+#if defined(_WIN32)
+        if( ret == SOCKET_ERROR &&
+            WSAGetLastError() == WSAEMSGSIZE )
+        {
+            /* We know buf is too small, thanks, just peeking here */
+            ret = 0;
+        }
+#endif
+    }
+
+    if( ret < 0 )
+    {
+        if( net_would_block( bind_ctx ) != 0 )
+            return( MBEDTLS_ERR_SSL_WANT_READ );
+
+        return( MBEDTLS_ERR_NET_ACCEPT_FAILED );
+    }
+
+    /* UDP: hijack the listening socket to communicate with the client,
+     * then bind a new socket to accept new connections */
+    if( type != SOCK_STREAM )
+    {
+        struct sockaddr_in local_addr;
+        int one = 1;
+
+        if( connect( bind_ctx->fd, (struct sockaddr *) &client_addr, n ) != 0 )
+            return( MBEDTLS_ERR_NET_ACCEPT_FAILED );
+
+        client_ctx->fd = bind_ctx->fd;
+        bind_ctx->fd   = -1; /* In case we exit early */
+
+        n = sizeof( struct sockaddr_in );
+        if( getsockname( client_ctx->fd,
+                         (struct sockaddr *) &local_addr, &n ) != 0 ||
+            ( bind_ctx->fd = (int) socket( AF_INET,
+                                           SOCK_DGRAM, IPPROTO_UDP ) ) < 0 ||
+            setsockopt( bind_ctx->fd, SOL_SOCKET, SO_REUSEADDR,
+                        (const char *) &one, sizeof( one ) ) != 0 )
+        {
+            return( MBEDTLS_ERR_NET_SOCKET_FAILED );
+        }
+
+        if( bind( bind_ctx->fd, (struct sockaddr *) &local_addr, n ) != 0 )
+        {
+            return( MBEDTLS_ERR_NET_BIND_FAILED );
+        }
+    }
+
+    if( client_ip != NULL )
+    {
+            struct sockaddr_in *addr4 = (struct sockaddr_in *) &client_addr;
+            *ip_len = sizeof( addr4->sin_addr.s_addr );
+
+            if( buf_size < *ip_len )
+                return( MBEDTLS_ERR_NET_BUFFER_TOO_SMALL );
+
+            memcpy( client_ip, &addr4->sin_addr.s_addr, *ip_len );
+    }
+
+    return( 0 );
+}
+
+/*
+ * Set the socket blocking or non-blocking
+ */
+int mbedtls_net_set_block( mbedtls_net_context *ctx )
+{
+#if ( defined(_WIN32) || defined(_WIN32_WCE) ) && !defined(EFIX64) && \
+    !defined(EFI32)
+    u_long n = 0;
+    return( ioctlsocket( ctx->fd, FIONBIO, &n ) );
+#else
+    return( fcntl( ctx->fd, F_SETFL, fcntl( ctx->fd, F_GETFL, 0 ) & ~O_NONBLOCK ) );
+#endif
+}
+
+int mbedtls_net_set_nonblock( mbedtls_net_context *ctx )
+{
+#if ( defined(_WIN32) || defined(_WIN32_WCE) ) && !defined(EFIX64) && \
+    !defined(EFI32)
+    u_long n = 1;
+    return( ioctlsocket( ctx->fd, FIONBIO, &n ) );
+#else
+    return( fcntl( ctx->fd, F_SETFL, fcntl( ctx->fd, F_GETFL, 0 ) | O_NONBLOCK ) );
+#endif
+}
+
+/*
+ * Portable usleep helper
+ */
+void mbedtls_net_usleep( unsigned long usec )
+{
+#if defined(_WIN32)
+    Sleep( ( usec + 999 ) / 1000 );
+#else
+    struct timeval tv;
+    tv.tv_sec  = usec / 1000000;
+#if defined(__unix__) || defined(__unix) || \
+    ( defined(__APPLE__) && defined(__MACH__) )
+    tv.tv_usec = (suseconds_t) usec % 1000000;
+#else
+    tv.tv_usec = usec % 1000000;
+#endif
+    select( 0, NULL, NULL, NULL, &tv );
+#endif
+}
+
+/*
+ * Read at most 'len' characters
+ */
+int mbedtls_net_recv( void *ctx, unsigned char *buf, size_t len )
+{
+    int ret;
+    int fd = ((mbedtls_net_context *) ctx)->fd;
+
+    if( fd < 0 )
+        return( MBEDTLS_ERR_NET_INVALID_CONTEXT );
+
+    ret = (int) read( fd, buf, len );
+
+    if( ret < 0 )
+    {
+        if( net_would_block( ctx ) != 0 )
+            return( MBEDTLS_ERR_SSL_WANT_READ );
+
+#if ( defined(_WIN32) || defined(_WIN32_WCE) ) && !defined(EFIX64) && \
+    !defined(EFI32)
+        if( WSAGetLastError() == WSAECONNRESET )
+            return( MBEDTLS_ERR_NET_CONN_RESET );
+#else
+        if( errno == EPIPE || errno == ECONNRESET )
+            return( MBEDTLS_ERR_NET_CONN_RESET );
+
+        if( errno == EINTR )
+            return( MBEDTLS_ERR_SSL_WANT_READ );
+#endif
+
+        return( MBEDTLS_ERR_NET_RECV_FAILED );
+    }
+
+    return( ret );
+}
+
+/*
+ * Read at most 'len' characters, blocking for at most 'timeout' ms
+ */
+int mbedtls_net_recv_timeout( void *ctx, unsigned char *buf, size_t len,
+                      uint32_t timeout )
+{
+    int ret;
+    struct timeval tv;
+    fd_set read_fds;
+    int fd = ((mbedtls_net_context *) ctx)->fd;
+
+    if( fd < 0 )
+        return( MBEDTLS_ERR_NET_INVALID_CONTEXT );
+
+    FD_ZERO( &read_fds );
+    FD_SET( fd, &read_fds );
+
+    tv.tv_sec  = timeout / 1000;
+    tv.tv_usec = ( timeout % 1000 ) * 1000;
+
+    ret = select( fd + 1, &read_fds, NULL, NULL, timeout == 0 ? NULL : &tv );
+
+    /* Zero fds ready means we timed out */
+    if( ret == 0 )
+        return( MBEDTLS_ERR_SSL_TIMEOUT );
+
+    if( ret < 0 )
+    {
+#if ( defined(_WIN32) || defined(_WIN32_WCE) ) && !defined(EFIX64) && \
+    !defined(EFI32)
+        if( WSAGetLastError() == WSAEINTR )
+            return( MBEDTLS_ERR_SSL_WANT_READ );
+#else
+        if( errno == EINTR )
+            return( MBEDTLS_ERR_SSL_WANT_READ );
+#endif
+
+        return( MBEDTLS_ERR_NET_RECV_FAILED );
+    }
+
+    /* This call will not block */
+    return( mbedtls_net_recv( ctx, buf, len ) );
+}
+
+/*
+ * Write at most 'len' characters
+ */
+int mbedtls_net_send( void *ctx, const unsigned char *buf, size_t len )
+{
+    int ret;
+    int fd = ((mbedtls_net_context *) ctx)->fd;
+
+    if( fd < 0 )
+        return( MBEDTLS_ERR_NET_INVALID_CONTEXT );
+
+    ret = (int) write( fd, buf, len );
+
+    if( ret < 0 )
+    {
+        if( net_would_block( ctx ) != 0 )
+            return( MBEDTLS_ERR_SSL_WANT_WRITE );
+
+#if ( defined(_WIN32) || defined(_WIN32_WCE) ) && !defined(EFIX64) && \
+    !defined(EFI32)
+        if( WSAGetLastError() == WSAECONNRESET )
+            return( MBEDTLS_ERR_NET_CONN_RESET );
+#else
+        if( errno == EPIPE || errno == ECONNRESET )
+            return( MBEDTLS_ERR_NET_CONN_RESET );
+
+        if( errno == EINTR )
+            return( MBEDTLS_ERR_SSL_WANT_WRITE );
+#endif
+
+        return( MBEDTLS_ERR_NET_SEND_FAILED );
+    }
+
+    return( ret );
+}
+
+/*
+ * Gracefully close the connection
+ */
+void mbedtls_net_free( mbedtls_net_context *ctx )
+{
+    if( ctx->fd == -1 )
+        return;
+
+    shutdown( ctx->fd, 2 );
+    close( ctx->fd );
+
+    ctx->fd = -1;
+}
+
+#endif /* MBEDTLS_NET_C */
diff --git a/ld/eagle.app.v6.ld b/ld/eagle.app.v6.ld
index 67b211d..3a52fed 100644
--- a/ld/eagle.app.v6.ld
+++ b/ld/eagle.app.v6.ld
@@ -32,7 +32,7 @@ ets_printf = printf;
 */
 #ifndef OTA
 
-#define IROM0_START 0x40240000
+#define IROM0_START 0x40220000
 
 /* Non-OTA sizes */
 #if FLASH_SIZE == 2 /* 256kB */
@@ -136,6 +136,68 @@ SECTIONS
     _dport0_data_end = ABSOLUTE(.);
   } >dport0_0_seg :dport0_0_phdr
 
+  .text : ALIGN(4) /* IRAM */
+  {
+    _stext = .;
+    _text_start = ABSOLUTE(.);
+    . = ALIGN (16);
+    *(.vecbase.text)
+    *(.entry.text)
+    *(.init.literal)
+    *(.init)
+    /* esp-open-rtos compiled source files use the .iram1.* section names for IRAM
+       functions, etc. */
+    *(.iram1.*)
+    /* SDK libraries expect their .text sections to link to iram, not irom */
+    *sdklib*:*(.literal .text .literal.* .text.*)
+    /* libgcc integer functions also need to be in .text, as some are called before
+       flash is mapped (also performance)
+    */
+    *libgcc.a:*i3.o(.literal .text .literal.* .text.*)
+
+    /* libc also in IRAM */
+    *libc.a:*malloc.o(.literal .text .literal.* .text.*)
+    *libc.a:*mallocr.o(.literal .text .literal.* .text.*)
+    *libc.a:*freer.o(.literal .text .literal.* .text.*)
+    *libc.a:*memcpy.o(.literal .text .literal.* .text.*)
+    *libc.a:*memset.o(.literal .text .literal.* .text.*)
+    *libc.a:*memcmp.o(.literal .text .literal.* .text.*)
+    *libc.a:*memmove.o(.literal .text .literal.* .text.*)
+    *libc.a:*rand.o(.literal .text .literal.* .text.*)
+    *libc.a:*bzero.o(.literal .text .literal.* .text.*)
+    *libc.a:*lock.o(.literal .text .literal.* .text.*)
+
+    *libc.a:*printf.o(.literal .text .literal.* .text.*)
+    *libc.a:*findfp.o(.literal .text .literal.* .text.*)
+    *libc.a:*fputwc.o(.literal .text .literal.* .text.*)
+
+    /* xthal_set_intset() called from PendSV in NMI context */
+    *libhal.a:*set_intset.o(.literal .text .literal.* .text.*)
+
+    *(.stub .gnu.warning .gnu.linkonce.literal.* .gnu.linkonce.t.*.literal .gnu.linkonce.t.*)
+    *(.fini.literal)
+    *(.fini)
+    *(.gnu.version)
+    _text_end = ABSOLUTE(.);
+    _etext = .;
+  } >iram1_0_seg :iram1_0_phdr
+
+  .irom0.text : ALIGN(4)
+  {
+    _irom0_text_start = ABSOLUTE(.);
+    /* esp-open-rtos compiled code goes into IROM by default
+       (except for libgcc which is matched above.)
+    */
+    *(.literal .text .literal.* .text.*)
+    /* mbedtls rodata */
+    *mbedtls.a:*.o(.rodata.* .rodata)
+    /* actual certificate in example (TEMPORARY HACK) */
+    *:cert.o(.rodata.* .rodata)
+    /* Anything explicitly marked as "irom" or "irom0" should go here */
+    *(.irom.* .irom.*.* .irom0.*)
+    _irom0_text_end = ABSOLUTE(.);
+  } >irom0_0_seg :irom0_0_phdr
+
   .data : ALIGN(4)
   {
     _data_start = ABSOLUTE(.);
@@ -218,62 +280,6 @@ SECTIONS
   } >dram0_0_seg :dram0_0_bss_phdr
 /* __stack = 0x3ffc8000; */
 
-  .text : ALIGN(4) /* IRAM */
-  {
-    _stext = .;
-    _text_start = ABSOLUTE(.);
-    . = ALIGN (16);
-    *(.vecbase.text)
-    *(.entry.text)
-    *(.init.literal)
-    *(.init)
-    /* esp-open-rtos compiled source files use the .iram1.* section names for IRAM
-       functions, etc. */
-    *(.iram1.*)
-    /* SDK libraries expect their .text sections to link to iram, not irom */
-    *sdklib*:*(.literal .text .literal.* .text.*)
-    /* libgcc integer functions also need to be in .text, as some are called before
-       flash is mapped (also performance)
-    */
-    *libgcc.a:*i3.o(.literal .text .literal.* .text.*)
-
-    /* libc also in IRAM */
-    *libc.a:*malloc.o(.literal .text .literal.* .text.*)
-    *libc.a:*mallocr.o(.literal .text .literal.* .text.*)
-    *libc.a:*freer.o(.literal .text .literal.* .text.*)
-    *libc.a:*memcpy.o(.literal .text .literal.* .text.*)
-    *libc.a:*memset.o(.literal .text .literal.* .text.*)
-    *libc.a:*memcmp.o(.literal .text .literal.* .text.*)
-    *libc.a:*rand.o(.literal .text .literal.* .text.*)
-    *libc.a:*bzero.o(.literal .text .literal.* .text.*)
-    *libc.a:*lock.o(.literal .text .literal.* .text.*)
-
-    *libc.a:*printf.o(.literal .text .literal.* .text.*)
-    *libc.a:*findfp.o(.literal .text .literal.* .text.*)
-    *libc.a:*fputwc.o(.literal .text .literal.* .text.*)
-
-    /* xthal_set_intset() called from PendSV in NMI context */
-    *libhal.a:*set_intset.o(.literal .text .literal.* .text.*)
-
-    *(.stub .gnu.warning .gnu.linkonce.literal.* .gnu.linkonce.t.*.literal .gnu.linkonce.t.*)
-    *(.fini.literal)
-    *(.fini)
-    *(.gnu.version)
-    _text_end = ABSOLUTE(.);
-    _etext = .;
-  } >iram1_0_seg :iram1_0_phdr
-
-  .irom0.text : ALIGN(4)
-  {
-    _irom0_text_start = ABSOLUTE(.);
-    /* esp-open-rtos compiled code goes into IROM by default
-       (except for libgcc which is matched above.)
-    */
-    *(.literal .text .literal.* .text.*)
-    /* Anything explicitly marked as "irom" or "irom0" should go here */
-    *(.irom.* .irom.*.* .irom0.*)
-    _irom0_text_end = ABSOLUTE(.);
-  } >irom0_0_seg :irom0_0_phdr
 
   .lit4 : ALIGN(4)
   {
diff --git a/lwip/component.mk b/lwip/component.mk
index e16baa0..1bbe21c 100644
--- a/lwip/component.mk
+++ b/lwip/component.mk
@@ -1,7 +1,7 @@
 # Component makefile for LWIP
 
 LWIP_DIR = $(lwip_ROOT)lwip/src/
-INC_DIRS += $(LWIP_DIR)include $(ROOT)lwip/include $(lwip_ROOT)include $(LWIP_DIR)include/ipv4 $(LWIP_DIR)include/ipv4/lwip $(LWIP_DIR)include/lwip
+INC_DIRS += $(LWIP_DIR)include $(ROOT)lwip/include $(lwip_ROOT)include $(LWIP_DIR)include/posix $(LWIP_DIR)include/ipv4 $(LWIP_DIR)include/ipv4/lwip $(LWIP_DIR)include/lwip
 
 # args for passing into compile rule generation
 lwip_INC_DIR =  # all in INC_DIRS, needed for normal operation