diff --git a/components/coap/CMakeLists.txt b/components/coap/CMakeLists.txt index 2c3b57e1a2..77576e0a40 100644 --- a/components/coap/CMakeLists.txt +++ b/components/coap/CMakeLists.txt @@ -6,17 +6,24 @@ if(NOT CONFIG_LWIP_IPV6 AND NOT CMAKE_BUILD_EARLY_EXPANSION) return() endif() -set(include_dirs port/include port/include/coap libcoap/include libcoap/include/coap2) +set(include_dirs port/include port/include libcoap/include) set(srcs "libcoap/src/address.c" "libcoap/src/async.c" "libcoap/src/block.c" + "libcoap/src/coap_asn1.c" + "libcoap/src/coap_cache.c" + "libcoap/src/coap_debug.c" "libcoap/src/coap_event.c" "libcoap/src/coap_hashkey.c" + "libcoap/src/coap_io.c" + "libcoap/src/coap_mbedtls.c" + "libcoap/src/coap_notls.c" + "libcoap/src/coap_prng.c" "libcoap/src/coap_session.c" + "libcoap/src/coap_tcp.c" "libcoap/src/coap_time.c" - "port/coap_debug.c" "libcoap/src/encode.c" "libcoap/src/mem.c" "libcoap/src/net.c" @@ -25,17 +32,14 @@ set(srcs "libcoap/src/resource.c" "libcoap/src/str.c" "libcoap/src/subscribe.c" - "libcoap/src/uri.c" - "libcoap/src/coap_io.c" - "port/coap_notls.c" - "port/coap_mbedtls.c") + "libcoap/src/uri.c") idf_component_register(SRCS "${srcs}" INCLUDE_DIRS "${include_dirs}" REQUIRES lwip mbedtls) # Silence format truncation warning, until it is fixed upstream -set_source_files_properties(port/coap_debug.c PROPERTIES COMPILE_FLAGS -Wno-format-truncation) +# set_source_files_properties(libcoap/src/coap_debug.c PROPERTIES COMPILE_FLAGS -Wno-format-truncation) # Needed for coap headers in public builds, also. # diff --git a/components/coap/Kconfig b/components/coap/Kconfig index a5d613e146..1221523c2b 100644 --- a/components/coap/Kconfig +++ b/components/coap/Kconfig @@ -52,6 +52,8 @@ menu "CoAP Configuration" bool "Info" config COAP_LOG_DEBUG bool "Debug" + config COAP_LOG_MBEDTLS + bool "mbedTLS" endchoice config COAP_LOG_DEFAULT_LEVEL @@ -65,5 +67,6 @@ menu "CoAP Configuration" default 5 if COAP_LOG_NOTICE default 6 if COAP_LOG_INFO default 7 if COAP_LOG_DEBUG + default 9 if COAP_LOG_MBEDTLS endmenu diff --git a/components/coap/component.mk b/components/coap/component.mk index eeec323f0c..19ef7fd50b 100644 --- a/components/coap/component.mk +++ b/components/coap/component.mk @@ -4,15 +4,15 @@ ifdef CONFIG_LWIP_IPV6 -COMPONENT_ADD_INCLUDEDIRS := port/include port/include/coap libcoap/include libcoap/include/coap2 +COMPONENT_ADD_INCLUDEDIRS := port/include port/include libcoap/include -COMPONENT_OBJS = libcoap/src/address.o libcoap/src/async.o libcoap/src/block.o libcoap/src/coap_event.o libcoap/src/coap_hashkey.o libcoap/src/coap_session.o libcoap/src/coap_time.o port/coap_debug.o libcoap/src/encode.o libcoap/src/mem.o libcoap/src/net.o libcoap/src/option.o libcoap/src/pdu.o libcoap/src/resource.o libcoap/src/str.o libcoap/src/subscribe.o libcoap/src/uri.o port/coap_mbedtls.o libcoap/src/coap_io.o port/coap_notls.o +COMPONENT_OBJS = libcoap/src/address.o libcoap/src/async.o libcoap/src/block.o libcoap/src/coap_asn1.o libcoap/src/coap_cache.o libcoap/src/coap_debug.o libcoap/src/coap_event.o libcoap/src/coap_hashkey.o libcoap/src/coap_io.o libcoap/src/coap_mbedtls.o libcoap/src/coap_notls.o libcoap/src/coap_prng.o libcoap/src/coap_session.o libcoap/src/coap_tcp.o libcoap/src/coap_time.o libcoap/src/encode.o libcoap/src/mem.o libcoap/src/net.o libcoap/src/option.o libcoap/src/pdu.o libcoap/src/resource.o libcoap/src/str.o libcoap/src/subscribe.o libcoap/src/uri.o COMPONENT_SRCDIRS := libcoap/src libcoap port COMPONENT_SUBMODULES += libcoap # Silence format truncation warning, until it is fixed upstream -port/coap_debug.o: CFLAGS += -Wno-format-truncation +# libcoap/src/coap_debug.o: CFLAGS += -Wno-format-truncation endif # CONFIG_LWIP_IPV6 diff --git a/components/coap/libcoap b/components/coap/libcoap index 98954eb30a..9b6451c365 160000 --- a/components/coap/libcoap +++ b/components/coap/libcoap @@ -1 +1 @@ -Subproject commit 98954eb30a2e728e172a6cd29430ae5bc999b585 +Subproject commit 9b6451c3654bc1f625e36c87f018c2da34bea5e6 diff --git a/components/coap/port/coap_debug.c b/components/coap/port/coap_debug.c deleted file mode 100644 index 64d6a01800..0000000000 --- a/components/coap/port/coap_debug.c +++ /dev/null @@ -1,888 +0,0 @@ -/* debug.c -- debug utilities - * - * Copyright (C) 2010--2012,2014--2019 Olaf Bergmann and others - * - * This file is part of the CoAP library libcoap. Please see - * README for terms of use. - */ - -#include "coap_config.h" - -#if defined(HAVE_STRNLEN) && defined(__GNUC__) && !defined(_GNU_SOURCE) -#define _GNU_SOURCE 1 -#endif - -#if defined(HAVE_ASSERT_H) && !defined(assert) -# include -#endif - -#include -#include -#include -#include - -#ifdef HAVE_ARPA_INET_H -#include -#endif -#ifdef HAVE_WS2TCPIP_H -#include -#endif - -#ifdef HAVE_TIME_H -#include -#endif - -#include "libcoap.h" -#include "coap_dtls.h" -#include "block.h" -#include "coap_debug.h" -#include "encode.h" -#include "net.h" -#include "coap_mutex.h" - -#ifdef WITH_LWIP -# define fprintf(fd, ...) LWIP_PLATFORM_DIAG((__VA_ARGS__)) -# define fflush(...) -#endif - -#ifdef WITH_CONTIKI -# ifndef DEBUG -# define DEBUG DEBUG_PRINT -# endif /* DEBUG */ -#include "net/ip/uip-debug.h" -#endif - -static coap_log_t maxlog = LOG_WARNING; /* default maximum log level */ - -static int use_fprintf_for_show_pdu = 1; /* non zero to output with fprintf */ - -const char *coap_package_name(void) { - return PACKAGE_NAME; -} - -const char *coap_package_version(void) { - return PACKAGE_STRING; -} - -void -coap_set_show_pdu_output(int use_fprintf) { - use_fprintf_for_show_pdu = use_fprintf; -} - -coap_log_t -coap_get_log_level(void) { - return maxlog; -} - -void -coap_set_log_level(coap_log_t level) { - maxlog = level; -} - -/* this array has the same order as the type log_t */ -static const char *loglevels[] = { - "EMRG", "ALRT", "CRIT", "ERR ", "WARN", "NOTE", "INFO", "DEBG" -}; - -#ifdef HAVE_TIME_H - -COAP_STATIC_INLINE size_t -print_timestamp(char *s, size_t len, coap_tick_t t) { - struct tm *tmp; - time_t now = coap_ticks_to_rt(t); - tmp = localtime(&now); - return strftime(s, len, "%b %d %H:%M:%S", tmp); -} - -#else /* alternative implementation: just print the timestamp */ - -COAP_STATIC_INLINE size_t -print_timestamp(char *s, size_t len, coap_tick_t t) { -#ifdef HAVE_SNPRINTF - return snprintf(s, len, "%u.%03u", - (unsigned int)coap_ticks_to_rt(t), - (unsigned int)(t % COAP_TICKS_PER_SECOND)); -#else /* HAVE_SNPRINTF */ - /* @todo do manual conversion of timestamp */ - return 0; -#endif /* HAVE_SNPRINTF */ -} - -#endif /* HAVE_TIME_H */ - -#ifndef HAVE_STRNLEN -/** - * A length-safe strlen() fake. - * - * @param s The string to count characters != 0. - * @param maxlen The maximum length of @p s. - * - * @return The length of @p s. - */ -static inline size_t -strnlen(const char *s, size_t maxlen) { - size_t n = 0; - while(*s++ && n < maxlen) - ++n; - return n; -} -#endif /* HAVE_STRNLEN */ - -static size_t -print_readable( const uint8_t *data, size_t len, - unsigned char *result, size_t buflen, int encode_always ) { - const uint8_t hex[] = "0123456789ABCDEF"; - size_t cnt = 0; - assert(data || len == 0); - - if (buflen == 0) { /* there is nothing we can do here but return */ - return 0; - } - - while (len) { - if (!encode_always && isprint(*data)) { - if (cnt+1 < buflen) { /* keep one byte for terminating zero */ - *result++ = *data; - ++cnt; - } else { - break; - } - } else { - if (cnt+4 < buflen) { /* keep one byte for terminating zero */ - *result++ = '\\'; - *result++ = 'x'; - *result++ = hex[(*data & 0xf0) >> 4]; - *result++ = hex[*data & 0x0f]; - cnt += 4; - } else - break; - } - - ++data; --len; - } - - *result = '\0'; /* add a terminating zero */ - return cnt; -} - -#ifndef min -#define min(a,b) ((a) < (b) ? (a) : (b)) -#endif - -size_t -coap_print_addr(const struct coap_address_t *addr, unsigned char *buf, size_t len) { -#if defined( HAVE_ARPA_INET_H ) || defined( HAVE_WS2TCPIP_H ) - const void *addrptr = NULL; - in_port_t port; - unsigned char *p = buf; - size_t need_buf; - - switch (addr->addr.sa.sa_family) { - case AF_INET: - addrptr = &addr->addr.sin.sin_addr; - port = ntohs(addr->addr.sin.sin_port); - need_buf = INET_ADDRSTRLEN; - break; - case AF_INET6: - if (len < 7) /* do not proceed if buffer is even too short for [::]:0 */ - return 0; - - *p++ = '['; - - addrptr = &addr->addr.sin6.sin6_addr; - port = ntohs(addr->addr.sin6.sin6_port); - need_buf = INET6_ADDRSTRLEN; - - break; - default: - memcpy(buf, "(unknown address type)", min(22, len)); - return min(22, len); - } - - /* Cast needed for Windows, since it doesn't have the correct API signature. */ - if (inet_ntop(addr->addr.sa.sa_family, addrptr, (char *)p, - min(len, need_buf)) == 0) { - perror("coap_print_addr"); - return 0; - } - - p += strnlen((char *)p, len); - - if (addr->addr.sa.sa_family == AF_INET6) { - if (p < buf + len) { - *p++ = ']'; - } else - return 0; - } - - p += snprintf((char *)p, buf + len - p + 1, ":%d", port); - - return buf + len - p; -#else /* HAVE_ARPA_INET_H */ -# if WITH_CONTIKI - unsigned char *p = buf; - uint8_t i; -# if NETSTACK_CONF_WITH_IPV6 - const uint8_t hex[] = "0123456789ABCDEF"; - - if (len < 41) - return 0; - - *p++ = '['; - - for (i=0; i < 16; i += 2) { - if (i) { - *p++ = ':'; - } - *p++ = hex[(addr->addr.u8[i] & 0xf0) >> 4]; - *p++ = hex[(addr->addr.u8[i] & 0x0f)]; - *p++ = hex[(addr->addr.u8[i+1] & 0xf0) >> 4]; - *p++ = hex[(addr->addr.u8[i+1] & 0x0f)]; - } - *p++ = ']'; -# else /* WITH_UIP6 */ -# warning "IPv4 network addresses will not be included in debug output" - - if (len < 21) - return 0; -# endif /* WITH_UIP6 */ - if (buf + len - p < 6) - return 0; - -#ifdef HAVE_SNPRINTF - p += snprintf((char *)p, buf + len - p + 1, ":%d", uip_htons(addr->port)); -#else /* HAVE_SNPRINTF */ - /* @todo manual conversion of port number */ -#endif /* HAVE_SNPRINTF */ - - return p - buf; -# else /* WITH_CONTIKI */ - /* TODO: output addresses manually */ -# warning "inet_ntop() not available, network addresses will not be included in debug output" -# endif /* WITH_CONTIKI */ - return 0; -#endif -} - -#ifdef WITH_CONTIKI -# define fprintf(fd, ...) PRINTF(__VA_ARGS__) -# define fflush(...) - -# ifdef HAVE_VPRINTF -# define vfprintf(fd, ...) vprintf(__VA_ARGS__) -# else /* HAVE_VPRINTF */ -# define vfprintf(fd, ...) PRINTF(__VA_ARGS__) -# endif /* HAVE_VPRINTF */ -#endif /* WITH_CONTIKI */ - -/** Returns a textual description of the message type @p t. */ -static const char * -msg_type_string(uint16_t t) { - static const char *types[] = { "CON", "NON", "ACK", "RST", "???" }; - - return types[min(t, sizeof(types)/sizeof(char *) - 1)]; -} - -/** Returns a textual description of the method or response code. */ -static const char * -msg_code_string(uint16_t c) { - static const char *methods[] = { "0.00", "GET", "POST", "PUT", "DELETE", - "FETCH", "PATCH", "iPATCH" }; - static const char *signals[] = { "7.00", "CSM", "Ping", "Pong", "Release", - "Abort" }; - static char buf[5]; - - if (c < sizeof(methods)/sizeof(const char *)) { - return methods[c]; - } else if (c >= 224 && c - 224 < (int)(sizeof(signals)/sizeof(const char *))) { - return signals[c-224]; - } else { - snprintf(buf, sizeof(buf), "%u.%02u", (c >> 5) & 0x7, c & 0x1f); - return buf; - } -} - -/** Returns a textual description of the option name. */ -static const char * -msg_option_string(uint8_t code, uint16_t option_type) { - struct option_desc_t { - uint16_t type; - const char *name; - }; - - static struct option_desc_t options[] = { - { COAP_OPTION_IF_MATCH, "If-Match" }, - { COAP_OPTION_URI_HOST, "Uri-Host" }, - { COAP_OPTION_ETAG, "ETag" }, - { COAP_OPTION_IF_NONE_MATCH, "If-None-Match" }, - { COAP_OPTION_OBSERVE, "Observe" }, - { COAP_OPTION_URI_PORT, "Uri-Port" }, - { COAP_OPTION_LOCATION_PATH, "Location-Path" }, - { COAP_OPTION_URI_PATH, "Uri-Path" }, - { COAP_OPTION_CONTENT_FORMAT, "Content-Format" }, - { COAP_OPTION_MAXAGE, "Max-Age" }, - { COAP_OPTION_URI_QUERY, "Uri-Query" }, - { COAP_OPTION_ACCEPT, "Accept" }, - { COAP_OPTION_LOCATION_QUERY, "Location-Query" }, - { COAP_OPTION_BLOCK2, "Block2" }, - { COAP_OPTION_BLOCK1, "Block1" }, - { COAP_OPTION_PROXY_URI, "Proxy-Uri" }, - { COAP_OPTION_PROXY_SCHEME, "Proxy-Scheme" }, - { COAP_OPTION_SIZE1, "Size1" }, - { COAP_OPTION_SIZE2, "Size2" }, - { COAP_OPTION_NORESPONSE, "No-Response" } - }; - - static struct option_desc_t options_csm[] = { - { COAP_SIGNALING_OPTION_MAX_MESSAGE_SIZE, "Max-Message-Size" }, - { COAP_SIGNALING_OPTION_BLOCK_WISE_TRANSFER, "Block-wise-Transfer" } - }; - - static struct option_desc_t options_pingpong[] = { - { COAP_SIGNALING_OPTION_CUSTODY, "Custody" } - }; - - static struct option_desc_t options_release[] = { - { COAP_SIGNALING_OPTION_ALTERNATIVE_ADDRESS, "Alternative-Address" }, - { COAP_SIGNALING_OPTION_HOLD_OFF, "Hold-Off" } - }; - - static struct option_desc_t options_abort[] = { - { COAP_SIGNALING_OPTION_BAD_CSM_OPTION, "Bad-CSM-Option" } - }; - - static char buf[6]; - size_t i; - - if (code == COAP_SIGNALING_CSM) { - for (i = 0; i < sizeof(options_csm)/sizeof(struct option_desc_t); i++) { - if (option_type == options_csm[i].type) { - return options_csm[i].name; - } - } - } else if (code == COAP_SIGNALING_PING || code == COAP_SIGNALING_PONG) { - for (i = 0; i < sizeof(options_pingpong)/sizeof(struct option_desc_t); i++) { - if (option_type == options_pingpong[i].type) { - return options_pingpong[i].name; - } - } - } else if (code == COAP_SIGNALING_RELEASE) { - for (i = 0; i < sizeof(options_release)/sizeof(struct option_desc_t); i++) { - if (option_type == options_release[i].type) { - return options_release[i].name; - } - } - } else if (code == COAP_SIGNALING_ABORT) { - for (i = 0; i < sizeof(options_abort)/sizeof(struct option_desc_t); i++) { - if (option_type == options_abort[i].type) { - return options_abort[i].name; - } - } - } else { - /* search option_type in list of known options */ - for (i = 0; i < sizeof(options)/sizeof(struct option_desc_t); i++) { - if (option_type == options[i].type) { - return options[i].name; - } - } - } - /* unknown option type, just print to buf */ - snprintf(buf, sizeof(buf), "%u", option_type); - return buf; -} - -static unsigned int -print_content_format(unsigned int format_type, - unsigned char *result, unsigned int buflen) { - struct desc_t { - unsigned int type; - const char *name; - }; - - static struct desc_t formats[] = { - { COAP_MEDIATYPE_TEXT_PLAIN, "text/plain" }, - { COAP_MEDIATYPE_APPLICATION_LINK_FORMAT, "application/link-format" }, - { COAP_MEDIATYPE_APPLICATION_XML, "application/xml" }, - { COAP_MEDIATYPE_APPLICATION_OCTET_STREAM, "application/octet-stream" }, - { COAP_MEDIATYPE_APPLICATION_EXI, "application/exi" }, - { COAP_MEDIATYPE_APPLICATION_JSON, "application/json" }, - { COAP_MEDIATYPE_APPLICATION_CBOR, "application/cbor" }, - { COAP_MEDIATYPE_APPLICATION_COSE_SIGN, "application/cose; cose-type=\"cose-sign\"" }, - { COAP_MEDIATYPE_APPLICATION_COSE_SIGN1, "application/cose; cose-type=\"cose-sign1\"" }, - { COAP_MEDIATYPE_APPLICATION_COSE_ENCRYPT, "application/cose; cose-type=\"cose-encrypt\"" }, - { COAP_MEDIATYPE_APPLICATION_COSE_ENCRYPT0, "application/cose; cose-type=\"cose-encrypt0\"" }, - { COAP_MEDIATYPE_APPLICATION_COSE_MAC, "application/cose; cose-type=\"cose-mac\"" }, - { COAP_MEDIATYPE_APPLICATION_COSE_MAC0, "application/cose; cose-type=\"cose-mac0\"" }, - { COAP_MEDIATYPE_APPLICATION_COSE_KEY, "application/cose-key" }, - { COAP_MEDIATYPE_APPLICATION_COSE_KEY_SET, "application/cose-key-set" }, - { COAP_MEDIATYPE_APPLICATION_SENML_JSON, "application/senml+json" }, - { COAP_MEDIATYPE_APPLICATION_SENSML_JSON, "application/sensml+json" }, - { COAP_MEDIATYPE_APPLICATION_SENML_CBOR, "application/senml+cbor" }, - { COAP_MEDIATYPE_APPLICATION_SENSML_CBOR, "application/sensml+cbor" }, - { COAP_MEDIATYPE_APPLICATION_SENML_EXI, "application/senml-exi" }, - { COAP_MEDIATYPE_APPLICATION_SENSML_EXI, "application/sensml-exi" }, - { COAP_MEDIATYPE_APPLICATION_SENML_XML, "application/senml+xml" }, - { COAP_MEDIATYPE_APPLICATION_SENSML_XML, "application/sensml+xml" }, - { 75, "application/dcaf+cbor" } - }; - - size_t i; - - /* search format_type in list of known content formats */ - for (i = 0; i < sizeof(formats)/sizeof(struct desc_t); i++) { - if (format_type == formats[i].type) { - return snprintf((char *)result, buflen, "%s", formats[i].name); - } - } - - /* unknown content format, just print numeric value to buf */ - return snprintf((char *)result, buflen, "%d", format_type); -} - -/** - * Returns 1 if the given @p content_format is either unknown or known - * to carry binary data. The return value @c 0 hence indicates - * printable data which is also assumed if @p content_format is @c 01. - */ -COAP_STATIC_INLINE int -is_binary(int content_format) { - return !(content_format == -1 || - content_format == COAP_MEDIATYPE_TEXT_PLAIN || - content_format == COAP_MEDIATYPE_APPLICATION_LINK_FORMAT || - content_format == COAP_MEDIATYPE_APPLICATION_XML || - content_format == COAP_MEDIATYPE_APPLICATION_JSON); -} - -#define COAP_DO_SHOW_OUTPUT_LINE \ - do { \ - if (use_fprintf_for_show_pdu) { \ - fprintf(COAP_DEBUG_FD, "%s", outbuf); \ - } \ - else { \ - coap_log(level, "%s", outbuf); \ - } \ - } while (0) - -void -coap_show_pdu(coap_log_t level, const coap_pdu_t *pdu) { -#if COAP_CONSTRAINED_STACK - static coap_mutex_t static_show_pdu_mutex = COAP_MUTEX_INITIALIZER; - static unsigned char buf[1024]; /* need some space for output creation */ - static char outbuf[COAP_DEBUG_BUF_SIZE]; -#else /* ! COAP_CONSTRAINED_STACK */ - unsigned char buf[1024]; /* need some space for output creation */ - char outbuf[COAP_DEBUG_BUF_SIZE]; -#endif /* ! COAP_CONSTRAINED_STACK */ - size_t buf_len = 0; /* takes the number of bytes written to buf */ - int encode = 0, have_options = 0, i; - coap_opt_iterator_t opt_iter; - coap_opt_t *option; - int content_format = -1; - size_t data_len; - unsigned char *data; - int outbuflen = 0; - - /* Save time if not needed */ - if (level > coap_get_log_level()) - return; - -#if COAP_CONSTRAINED_STACK - coap_mutex_lock(&static_show_pdu_mutex); -#endif /* COAP_CONSTRAINED_STACK */ - - snprintf(outbuf, sizeof(outbuf), "v:%d t:%s c:%s i:%04x {", - COAP_DEFAULT_VERSION, msg_type_string(pdu->type), - msg_code_string(pdu->code), pdu->tid); - - for (i = 0; i < pdu->token_length; i++) { - outbuflen = strlen(outbuf); - snprintf(&outbuf[outbuflen], sizeof(outbuf)-outbuflen, - "%02x", pdu->token[i]); - } - outbuflen = strlen(outbuf); - snprintf(&outbuf[outbuflen], sizeof(outbuf)-outbuflen, "}"); - - /* show options, if any */ - coap_option_iterator_init(pdu, &opt_iter, COAP_OPT_ALL); - - outbuflen = strlen(outbuf); - snprintf(&outbuf[outbuflen], sizeof(outbuf)-outbuflen, " ["); - while ((option = coap_option_next(&opt_iter))) { - if (!have_options) { - have_options = 1; - } else { - outbuflen = strlen(outbuf); - snprintf(&outbuf[outbuflen], sizeof(outbuf)-outbuflen, ","); - } - - if (pdu->code == COAP_SIGNALING_CSM) switch(opt_iter.type) { - case COAP_SIGNALING_OPTION_MAX_MESSAGE_SIZE: - buf_len = snprintf((char *)buf, sizeof(buf), "%u", - coap_decode_var_bytes(coap_opt_value(option), - coap_opt_length(option))); - break; - default: - buf_len = 0; - break; - } else if (pdu->code == COAP_SIGNALING_PING - || pdu->code == COAP_SIGNALING_PONG) { - buf_len = 0; - } else if (pdu->code == COAP_SIGNALING_RELEASE) switch(opt_iter.type) { - case COAP_SIGNALING_OPTION_ALTERNATIVE_ADDRESS: - buf_len = print_readable(coap_opt_value(option), - coap_opt_length(option), - buf, sizeof(buf), 0); - break; - case COAP_SIGNALING_OPTION_HOLD_OFF: - buf_len = snprintf((char *)buf, sizeof(buf), "%u", - coap_decode_var_bytes(coap_opt_value(option), - coap_opt_length(option))); - break; - default: - buf_len = 0; - break; - } else if (pdu->code == COAP_SIGNALING_ABORT) switch(opt_iter.type) { - case COAP_SIGNALING_OPTION_BAD_CSM_OPTION: - buf_len = snprintf((char *)buf, sizeof(buf), "%u", - coap_decode_var_bytes(coap_opt_value(option), - coap_opt_length(option))); - break; - default: - buf_len = 0; - break; - } else switch (opt_iter.type) { - case COAP_OPTION_CONTENT_FORMAT: - content_format = (int)coap_decode_var_bytes(coap_opt_value(option), - coap_opt_length(option)); - - buf_len = print_content_format(content_format, buf, sizeof(buf)); - break; - - case COAP_OPTION_BLOCK1: - case COAP_OPTION_BLOCK2: - /* split block option into number/more/size where more is the - * letter M if set, the _ otherwise */ - buf_len = snprintf((char *)buf, sizeof(buf), "%u/%c/%u", - coap_opt_block_num(option), /* block number */ - COAP_OPT_BLOCK_MORE(option) ? 'M' : '_', /* M bit */ - (1 << (COAP_OPT_BLOCK_SZX(option) + 4))); /* block size */ - - break; - - case COAP_OPTION_URI_PORT: - case COAP_OPTION_MAXAGE: - case COAP_OPTION_OBSERVE: - case COAP_OPTION_SIZE1: - case COAP_OPTION_SIZE2: - /* show values as unsigned decimal value */ - buf_len = snprintf((char *)buf, sizeof(buf), "%u", - coap_decode_var_bytes(coap_opt_value(option), - coap_opt_length(option))); - break; - - default: - /* generic output function for all other option types */ - if (opt_iter.type == COAP_OPTION_URI_PATH || - opt_iter.type == COAP_OPTION_PROXY_URI || - opt_iter.type == COAP_OPTION_URI_HOST || - opt_iter.type == COAP_OPTION_LOCATION_PATH || - opt_iter.type == COAP_OPTION_LOCATION_QUERY || - opt_iter.type == COAP_OPTION_URI_QUERY) { - encode = 0; - } else { - encode = 1; - } - - buf_len = print_readable(coap_opt_value(option), - coap_opt_length(option), - buf, sizeof(buf), encode); - } - - outbuflen = strlen(outbuf); - snprintf(&outbuf[outbuflen], sizeof(outbuf)-outbuflen, - " %s:%.*s", msg_option_string(pdu->code, opt_iter.type), - (int)buf_len, buf); - } - - outbuflen = strlen(outbuf); - snprintf(&outbuf[outbuflen], sizeof(outbuf)-outbuflen, " ]"); - - if (coap_get_data(pdu, &data_len, &data)) { - - outbuflen = strlen(outbuf); - snprintf(&outbuf[outbuflen], sizeof(outbuf)-outbuflen, " :: "); - - if (is_binary(content_format)) { - int keep_data_len = data_len; - uint8_t *keep_data = data; - - outbuflen = strlen(outbuf); - snprintf(&outbuf[outbuflen], sizeof(outbuf)-outbuflen, - "binary data length %zu\n", data_len); - COAP_DO_SHOW_OUTPUT_LINE; - /* - * Output hex dump of binary data as a continuous entry - */ - outbuf[0] = '\000'; - snprintf(outbuf, sizeof(outbuf), "<<"); - while (data_len--) { - outbuflen = strlen(outbuf); - snprintf(&outbuf[outbuflen], sizeof(outbuf)-outbuflen, - "%02x", *data++); - } - outbuflen = strlen(outbuf); - snprintf(&outbuf[outbuflen], sizeof(outbuf)-outbuflen, ">>"); - data_len = keep_data_len; - data = keep_data; - outbuflen = strlen(outbuf); - snprintf(&outbuf[outbuflen], sizeof(outbuf)-outbuflen, "\n"); - COAP_DO_SHOW_OUTPUT_LINE; - /* - * Output ascii readable (if possible), immediately under the - * hex value of the character output above to help binary debugging - */ - outbuf[0] = '\000'; - snprintf(outbuf, sizeof(outbuf), "<<"); - while (data_len--) { - outbuflen = strlen(outbuf); - snprintf(&outbuf[outbuflen], sizeof(outbuf)-outbuflen, - "%c ", isprint (*data) ? *data : '.'); - data++; - } - outbuflen = strlen(outbuf); - snprintf(&outbuf[outbuflen], sizeof(outbuf)-outbuflen, ">>"); - } else { - if (print_readable(data, data_len, buf, sizeof(buf), 0)) { - outbuflen = strlen(outbuf); - snprintf(&outbuf[outbuflen], sizeof(outbuf)-outbuflen, "'%s'", buf); - } - } - } - - outbuflen = strlen(outbuf); - snprintf(&outbuf[outbuflen], sizeof(outbuf)-outbuflen, "\n"); - COAP_DO_SHOW_OUTPUT_LINE; - -#if COAP_CONSTRAINED_STACK - coap_mutex_unlock(&static_show_pdu_mutex); -#endif /* COAP_CONSTRAINED_STACK */ -} - -void coap_show_tls_version(coap_log_t level) -{ - char buffer[64]; - coap_string_tls_version(buffer, sizeof(buffer)); - coap_log(level, "%s\n", buffer); -} - -char *coap_string_tls_version(char *buffer, size_t bufsize) -{ - coap_tls_version_t *tls_version = coap_get_tls_library_version(); - char beta[8]; - char sub[2]; - char b_beta[8]; - char b_sub[2]; - - switch (tls_version->type) { - case COAP_TLS_LIBRARY_NOTLS: - snprintf(buffer, bufsize, "TLS Library: None"); - break; - case COAP_TLS_LIBRARY_TINYDTLS: - snprintf(buffer, bufsize, "TLS Library: TinyDTLS - runtime %lu.%lu.%lu, " - "libcoap built for %lu.%lu.%lu", - (unsigned long)(tls_version->version >> 16), - (unsigned long)((tls_version->version >> 8) & 0xff), - (unsigned long)(tls_version->version & 0xff), - (unsigned long)(tls_version->built_version >> 16), - (unsigned long)((tls_version->built_version >> 8) & 0xff), - (unsigned long)(tls_version->built_version & 0xff)); - break; - case COAP_TLS_LIBRARY_OPENSSL: - switch (tls_version->version &0xf) { - case 0: - strcpy(beta, "-dev"); - break; - case 0xf: - strcpy(beta, ""); - break; - default: - strcpy(beta, "-beta"); - beta[5] = (tls_version->version &0xf) + '0'; - beta[6] = '\000'; - break; - } - sub[0] = ((tls_version->version >> 4) & 0xff) ? - ((tls_version->version >> 4) & 0xff) + 'a' -1 : '\000'; - sub[1] = '\000'; - switch (tls_version->built_version &0xf) { - case 0: - strcpy(b_beta, "-dev"); - break; - case 0xf: - strcpy(b_beta, ""); - break; - default: - strcpy(b_beta, "-beta"); - b_beta[5] = (tls_version->built_version &0xf) + '0'; - b_beta[6] = '\000'; - break; - } - b_sub[0] = ((tls_version->built_version >> 4) & 0xff) ? - ((tls_version->built_version >> 4) & 0xff) + 'a' -1 : '\000'; - b_sub[1] = '\000'; - snprintf(buffer, bufsize, "TLS Library: OpenSSL - runtime " - "%lu.%lu.%lu%s%s, libcoap built for %lu.%lu.%lu%s%s", - (unsigned long)(tls_version->version >> 28), - (unsigned long)((tls_version->version >> 20) & 0xff), - (unsigned long)((tls_version->version >> 12) & 0xff), sub, beta, - (unsigned long)(tls_version->built_version >> 28), - (unsigned long)((tls_version->built_version >> 20) & 0xff), - (unsigned long)((tls_version->built_version >> 12) & 0xff), - b_sub, b_beta); - break; - case COAP_TLS_LIBRARY_GNUTLS: - snprintf(buffer, bufsize, "TLS Library: GnuTLS - runtime %lu.%lu.%lu, " - "libcoap built for %lu.%lu.%lu", - (unsigned long)(tls_version->version >> 16), - (unsigned long)((tls_version->version >> 8) & 0xff), - (unsigned long)(tls_version->version & 0xff), - (unsigned long)(tls_version->built_version >> 16), - (unsigned long)((tls_version->built_version >> 8) & 0xff), - (unsigned long)(tls_version->built_version & 0xff)); - break; - case COAP_TLS_LIBRARY_MBEDTLS: - snprintf(buffer, bufsize, "TLS Library: MbedTLS - runtime %lu.%lu.%lu, " - "libcoap built for %lu.%lu.%lu", - (unsigned long)(tls_version->version >> 24), - (unsigned long)((tls_version->version >> 16) & 0xff), - (unsigned long)((tls_version->version >> 8) & 0xff), - (unsigned long)(tls_version->built_version >> 24), - (unsigned long)((tls_version->built_version >> 16) & 0xff), - (unsigned long)((tls_version->built_version >> 8) & 0xff)); - break; - default: - snprintf(buffer, bufsize, "Library type %d unknown", tls_version->type); - break; - } - return buffer; -} - -static coap_log_handler_t log_handler = NULL; - -void coap_set_log_handler(coap_log_handler_t handler) { - log_handler = handler; -} - -void -coap_log_impl(coap_log_t level, const char *format, ...) { - - if (maxlog < level) - return; - - if (log_handler) { -#if COAP_CONSTRAINED_STACK - static coap_mutex_t static_log_mutex = COAP_MUTEX_INITIALIZER; - static char message[COAP_DEBUG_BUF_SIZE]; -#else /* ! COAP_CONSTRAINED_STACK */ - char message[COAP_DEBUG_BUF_SIZE]; -#endif /* ! COAP_CONSTRAINED_STACK */ - va_list ap; - va_start(ap, format); -#if COAP_CONSTRAINED_STACK - coap_mutex_lock(&static_log_mutex); -#endif /* COAP_CONSTRAINED_STACK */ - - vsnprintf( message, sizeof(message), format, ap); - va_end(ap); - log_handler(level, message); -#if COAP_CONSTRAINED_STACK - coap_mutex_unlock(&static_log_mutex); -#endif /* COAP_CONSTRAINED_STACK */ - } else { - char timebuf[32]; - coap_tick_t now; - va_list ap; - FILE *log_fd; - - log_fd = level <= LOG_CRIT ? COAP_ERR_FD : COAP_DEBUG_FD; - - coap_ticks(&now); - if (print_timestamp(timebuf,sizeof(timebuf), now)) - fprintf(log_fd, "%s ", timebuf); - - if (level <= LOG_DEBUG) - fprintf(log_fd, "%s ", loglevels[level]); - - va_start(ap, format); - vfprintf(log_fd, format, ap); - va_end(ap); - fflush(log_fd); - } -} - -static struct packet_num_interval { - int start; - int end; -} packet_loss_intervals[10]; -static int num_packet_loss_intervals = 0; -static int packet_loss_level = 0; -static int send_packet_count = 0; - -int coap_debug_set_packet_loss(const char *loss_level) { - const char *p = loss_level; - char *end = NULL; - int n = (int)strtol(p, &end, 10), i = 0; - if (end == p || n < 0) - return 0; - if (*end == '%') { - if (n > 100) - n = 100; - packet_loss_level = n * 65536 / 100; - coap_log(LOG_DEBUG, "packet loss level set to %d%%\n", n); - } else { - if (n <= 0) - return 0; - while (i < 10) { - packet_loss_intervals[i].start = n; - if (*end == '-') { - p = end + 1; - n = (int)strtol(p, &end, 10); - if (end == p || n <= 0) - return 0; - } - packet_loss_intervals[i++].end = n; - if (*end == 0) - break; - if (*end != ',') - return 0; - p = end + 1; - n = (int)strtol(p, &end, 10); - if (end == p || n <= 0) - return 0; - } - if (i == 10) - return 0; - num_packet_loss_intervals = i; - } - send_packet_count = 0; - return 1; -} - -int coap_debug_send_packet(void) { - ++send_packet_count; - if (num_packet_loss_intervals > 0) { - int i; - for (i = 0; i < num_packet_loss_intervals; i++) { - if (send_packet_count >= packet_loss_intervals[i].start - && send_packet_count <= packet_loss_intervals[i].end) - return 0; - } - } - if ( packet_loss_level > 0 ) { - uint16_t r = 0; - prng( (uint8_t*)&r, 2 ); - if ( r < packet_loss_level ) - return 0; - } - return 1; -} diff --git a/components/coap/port/coap_mbedtls.c b/components/coap/port/coap_mbedtls.c deleted file mode 100644 index ef016a125d..0000000000 --- a/components/coap/port/coap_mbedtls.c +++ /dev/null @@ -1,1869 +0,0 @@ -/* -* coap_mbedtls.c -- mbedTLS Datagram Transport Layer Support for libcoap -* -* Copyright (C) 2019 Jon Shallow -* 2019 Jitin George -* -* This file is part of the CoAP library libcoap. Please see README for terms -* of use. -*/ - -/* - * Naming used to prevent confusion between coap sessions, mbedtls sessions etc. - * when reading the code. - * - * c_context A coap_context_t * - * c_session A coap_session_t * - * m_context A coap_mbedtls_context_t * (held in c_context->dtls_context) - * m_env A coap_mbedtls_env_t * (held in c_session->tls) - */ - -#include "coap_config.h" - -#ifdef HAVE_MBEDTLS - -/* - * Once PS #335 has been merged in, then code following a rebase needs to be - * updated removing sections that are "#ifndef PSK2_PR", and then remove all - * references to PSK2_PR. - */ -#undef PSK2_PR - -#include "libcoap.h" -#include "coap_dtls.h" -#include "net.h" -#include "mem.h" -#include "coap_debug.h" -#include "prng.h" -#include "coap_mutex.h" - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#if defined(ESPIDF_VERSION) && defined(CONFIG_MBEDTLS_DEBUG) -#include -#endif /* ESPIDF_VERSION && CONFIG_MBEDTLS_DEBUG */ -#include -#include - -#define mbedtls_malloc(a) malloc(a) -#define mbedtls_realloc(a,b) realloc(a,b) -#define mbedtls_strdup(a) strdup(a) - -#ifdef __GNUC__ -#define UNUSED __attribute__((unused)) -#else /* __GNUC__ */ -#define UNUSED -#endif /* __GNUC__ */ - -#define IS_PSK (1 << 0) -#define IS_PKI (1 << 1) -#define IS_CLIENT (1 << 6) -#define IS_SERVER (1 << 7) - -typedef struct coap_ssl_t { - const uint8_t *pdu; - unsigned pdu_len; - unsigned peekmode; - coap_tick_t timeout; -} coap_ssl_t; - -/* - * This structure encapsulates the mbedTLS session object. - * It handles both TLS and DTLS. - * c_session->tls points to this. - */ -typedef struct coap_mbedtls_env_t { - mbedtls_ssl_context ssl; - mbedtls_entropy_context entropy; - mbedtls_ctr_drbg_context ctr_drbg; - mbedtls_ssl_config conf; - mbedtls_timing_delay_context timer; - mbedtls_x509_crt cacert; - mbedtls_x509_crt public_cert; - mbedtls_pk_context private_key; - mbedtls_ssl_cookie_ctx cookie_ctx; - /* If not set, need to do do_mbedtls_handshake */ - int established; - int seen_client_hello; - coap_ssl_t coap_ssl_data; -} coap_mbedtls_env_t; - -typedef struct pki_sni_entry { - char *sni; - coap_dtls_key_t pki_key; - mbedtls_x509_crt cacert; - mbedtls_x509_crt public_cert; - mbedtls_pk_context private_key; -} pki_sni_entry; - -#ifdef PSK2_PR -typedef struct psk_sni_entry { - coap_string_t sni; - coap_dtls_spsk_info_t psk_info; -} psk_sni_entry; -#endif /* PSK2_PR */ - -typedef struct coap_mbedtls_context_t { - coap_dtls_pki_t setup_data; - size_t pki_sni_count; - pki_sni_entry *pki_sni_entry_list; -#ifdef PSK2_PR - size_t psk_sni_count; - psk_sni_entry *psk_sni_entry_list; -#endif /* PSK2_PR */ - char *root_ca_file; - char *root_ca_path; - int psk_pki_enabled; -} coap_mbedtls_context_t; - -static int coap_dgram_read(void *ctx, unsigned char *out, size_t outl) -{ - ssize_t ret = 0; - coap_session_t *c_session = (struct coap_session_t *)ctx; - coap_ssl_t *data = &((coap_mbedtls_env_t *)c_session->tls)->coap_ssl_data; - - if (!c_session->tls) { - errno = EAGAIN; - return MBEDTLS_ERR_SSL_WANT_READ; - } - - if (out != NULL) { - if (data != NULL && data->pdu_len > 0) { - if (outl < data->pdu_len) { - memcpy(out, data->pdu, outl); - ret = outl; - data->pdu += outl; - data->pdu_len -= outl; - } - else { - memcpy(out, data->pdu, data->pdu_len); - ret = data->pdu_len; - if (!data->peekmode) { - data->pdu_len = 0; - data->pdu = NULL; - } - } - } - else { - ret = MBEDTLS_ERR_SSL_WANT_READ; - errno = EAGAIN; - return ret; - } - } - return ret; -} - -/* - * return +ve data amount - * 0 no more - * -1 error (error in errno) - */ -/* callback function given to mbedtls for sending data over socket */ -static int -coap_dgram_write(void *ctx, const unsigned char *send_buffer, - size_t send_buffer_length) -{ - ssize_t result = -1; - coap_session_t *c_session = (struct coap_session_t *)ctx; - - if (c_session) { - result = coap_session_send(c_session, send_buffer, send_buffer_length); - if (result != (int)send_buffer_length) { - coap_log(LOG_WARNING, "coap_network_send failed (%zd != %zd)\n", - result, send_buffer_length); - result = 0; - } - } else { - result = 0; - } - return result; -} - -#if !defined(ESPIDF_VERSION) || (defined(CONFIG_MBEDTLS_SSL_PROTO_DTLS) && defined(CONFIG_MBEDTLS_TLS_SERVER)) -static char* -get_ip_addr(const struct coap_address_t *addr) -{ - const void *addrptr = NULL; - size_t buf_len; - - if (!addr) { - return NULL; - } - switch (addr->addr.sa.sa_family) { - case AF_INET: - addrptr = &addr->addr.sin.sin_addr; - buf_len = INET_ADDRSTRLEN; - break; - case AF_INET6: - addrptr = &addr->addr.sin6.sin6_addr; - buf_len = INET6_ADDRSTRLEN; - break; - default: - return NULL; - } - char *str = (char *)mbedtls_calloc(1, buf_len); - if (!str) { - coap_log(LOG_ERR, "Memory allocation failed\n"); - return NULL; - } - if (inet_ntop(addr->addr.sa.sa_family, addrptr, str, - buf_len) == 0) { - perror("coap_print_addr"); - return 0; - } - return str; -} -#endif /* !ESPIDF_VERSION || (CONFIG_MBEDTLS_SSL_PROTO_DTLS && CONFIG_MBEDTLS_TLS_SERVER) */ - -#if !defined(ESPIDF_VERSION) || (defined(CONFIG_MBEDTLS_SSL_PROTO_DTLS) && defined(CONFIG_MBEDTLS_PSK_MODES) && defined(CONFIG_MBEDTLS_TLS_SERVER)) -/* - * Server side PSK callback - */ -static int psk_server_callback(void *p_info, mbedtls_ssl_context *ssl, - const unsigned char *name, size_t name_len ) -{ - coap_session_t *c_session = - (coap_session_t *)p_info; - uint8_t buf[128]; - size_t psk_len; -#ifdef PSK2_PR - coap_dtls_spsk_t *setup_data; -#endif /* PSK2_PR */ - coap_mbedtls_env_t *m_env; - - coap_log(LOG_DEBUG, "got psk_identity: '%.*s'\n", - (int)name_len, name); - - if (c_session == NULL || c_session->context == NULL || - c_session->context->get_server_psk == NULL) { - return -1; - } - m_env = (coap_mbedtls_env_t *)c_session->tls; -#ifdef PSK2_PR - setup_data = &c_session->context->spsk_setup_data; - - if (setup_data->validate_id_call_back) { - coap_bin_const_t lidentity; - lidentity.length = name_len; - lidentity.s = (const uint8_t*)name; - const coap_bin_const_t *psk_key = - setup_data->validate_id_call_back(&lidentity, - c_session, - setup_data->id_call_back_arg); - - if (psk_key == NULL) - return -1; - mbedtls_ssl_set_hs_psk(ssl, psk_key->s, psk_key->length); - coap_session_refresh_psk_key(c_session, psk_key); - m_env->seen_client_hello = 1; - return 0; - } -#endif /* PSK2_PR */ - - psk_len = c_session->context->get_server_psk(c_session, - (const uint8_t*)name, - name_len, - (uint8_t*)buf, sizeof(buf)); - m_env->seen_client_hello = 1; - mbedtls_ssl_set_hs_psk(ssl, buf, psk_len); - return 0; -} -#endif /* !ESPIDF_VERSION || (CONFIG_MBEDTLS_SSL_PROTO_DTLS && CONFIG_MBEDTLS_PSK_MODES && CONFIG_MBEDTLS_TLS_SERVER) */ - -static char* -get_san_or_cn_from_cert(mbedtls_x509_crt *crt) -{ - if (crt) { -#if COAP_CONSTRAINED_STACK - static coap_mutex_t a_static_mutex = COAP_MUTEX_INITIALIZER; - static char buf[1024]; -#else /* ! COAP_CONSTRAINED_STACK */ - char buf[1024]; -#endif /* ! COAP_CONSTRAINED_STACK */ - char *cn; - char *cp; - char *tcp; - int n; - -#if COAP_CONSTRAINED_STACK - coap_mutex_lock(&a_static_mutex); -#endif /* COAP_CONSTRAINED_STACK */ - - mbedtls_x509_crt_info(buf, sizeof(buf) - 1, "", crt ); - - /* Look first to see if Subject Alt Name is defined */ - cp = strstr(buf, "subject alt name"); - if (cp) { - cp = strchr(cp, ':'); - if (cp) { - cp++; - while (*cp == ' ') cp++; - tcp = strchr(cp, '\n'); - if (tcp) - *tcp = '\000'; - /* Take only the first entry */ - tcp = strchr(cp, ','); - if (tcp) - *tcp = '\000'; - /* Return the Subject Alt Name */ -#if COAP_CONSTRAINED_STACK - coap_mutex_unlock(&a_static_mutex); -#endif /* COAP_CONSTRAINED_STACK */ - return mbedtls_strdup(cp); - } - } - - /* Pull CN= out of subject name */ - cp = strstr(buf, "subject name"); - if (cp) { - cp = strchr(cp, ':'); - if (cp) { - cp++; - while (*cp == ' ') cp++; - tcp = strchr(cp, '\n'); - if (tcp) - *tcp = '\000'; - - /* Need to emulate strcasestr() here. Looking for CN= */ - n = strlen(cp) - 3; - cn = cp; - while (n > 0) { - if (((cn[0] == 'C') || (cn[0] == 'c')) && - ((cn[1] == 'N') || (cn[1] == 'n')) && - (cn[2] == '=')) { - cn += 3; - break; - } - cn++; - n--; - } - if (n > 0) { - tcp = strchr(cn, ','); - if (tcp) - *tcp = '\000'; -#if COAP_CONSTRAINED_STACK - coap_mutex_unlock(&a_static_mutex); -#endif /* COAP_CONSTRAINED_STACK */ - return mbedtls_strdup(cn); - } - } - } -#if COAP_CONSTRAINED_STACK - coap_mutex_unlock(&a_static_mutex); -#endif /* COAP_CONSTRAINED_STACK */ - } - return NULL; -} - -/* - * return 0 All OK - * -ve Error Code - */ -static int -cert_verify_callback_mbedtls(void *data, mbedtls_x509_crt *crt, - int depth, uint32_t *flags) -{ - coap_session_t *c_session = (coap_session_t*)data; - coap_mbedtls_context_t *m_context = - (coap_mbedtls_context_t *)c_session->context->dtls_context; - coap_dtls_pki_t *setup_data = &m_context->setup_data; - char *cn = NULL; - - if (*flags == 0) - return 0; - - if (!setup_data->verify_peer_cert) { - /* Nothing is being checked */ - *flags = 0; - return 0; - } - - cn = get_san_or_cn_from_cert(crt); - - if (*flags & MBEDTLS_X509_BADCERT_EXPIRED) { - if (setup_data->allow_expired_certs) { - *flags &= ~MBEDTLS_X509_BADCERT_EXPIRED; - coap_log(LOG_WARNING, - " %s: %s: overridden: '%s' depth %d\n", - coap_session_str(c_session), - "The certificate has expired", cn ? cn : "?", depth); - } - } - if (*flags & MBEDTLS_X509_BADCERT_FUTURE) { - if (setup_data->allow_expired_certs) { - *flags &= ~MBEDTLS_X509_BADCERT_FUTURE; - coap_log(LOG_WARNING, - " %s: %s: overridden: '%s' depth %d\n", - coap_session_str(c_session), - "The certificate has a future date", cn ? cn : "?", depth); - } - } - if (*flags & MBEDTLS_X509_BADCERT_BAD_MD) { - if (setup_data->allow_bad_md_hash) { - *flags &= ~MBEDTLS_X509_BADCERT_BAD_MD; - coap_log(LOG_WARNING, - " %s: %s: overridden: '%s' depth %d\n", - coap_session_str(c_session), - "The certificate has a bad MD hash", cn ? cn : "?", depth); - } - } - if (*flags & MBEDTLS_X509_BADCERT_BAD_KEY) { - if (setup_data->allow_short_rsa_length) { - *flags &= ~MBEDTLS_X509_BADCERT_BAD_KEY; - coap_log(LOG_WARNING, - " %s: %s: overridden: '%s' depth %d\n", - coap_session_str(c_session), - "The certificate has a short RSA length", cn ? cn : "?", depth); - } - } - if (*flags & MBEDTLS_X509_BADCRL_EXPIRED) { - if (setup_data->check_cert_revocation && setup_data->allow_expired_crl) { - *flags &= ~MBEDTLS_X509_BADCRL_EXPIRED; - coap_log(LOG_WARNING, - " %s: %s: overridden: '%s' depth %d\n", - coap_session_str(c_session), - "The certificate's CRL has expired", cn ? cn : "?", depth); - } - else if (!setup_data->check_cert_revocation) { - *flags &= ~MBEDTLS_X509_BADCRL_EXPIRED; - } - } - if (*flags & MBEDTLS_X509_BADCRL_FUTURE) { - if (setup_data->check_cert_revocation && setup_data->allow_expired_crl) { - *flags &= ~MBEDTLS_X509_BADCRL_FUTURE; - coap_log(LOG_WARNING, - " %s: %s: overridden: '%s' depth %d\n", - coap_session_str(c_session), - "The certificate's CRL has a future date", cn ? cn : "?", depth); - } - else if (!setup_data->check_cert_revocation) { - *flags &= ~MBEDTLS_X509_BADCRL_FUTURE; - } - } - - if (*flags & MBEDTLS_X509_BADCERT_CN_MISMATCH) { - *flags &= ~MBEDTLS_X509_BADCERT_CN_MISMATCH; - } - if (setup_data->validate_cn_call_back) { - if (!setup_data->validate_cn_call_back(cn, - crt->raw.p, - crt->raw.len, - c_session, - depth, - *flags == 0, - setup_data->cn_call_back_arg)) { - *flags |= MBEDTLS_X509_BADCERT_CN_MISMATCH; - } - } - if (*flags != 0) { - char buf[128]; - char *tcp; - - mbedtls_x509_crt_verify_info(buf, sizeof(buf), "", *flags); - tcp = strchr(buf, '\n'); - while (tcp) { - *tcp = '\000'; - coap_log(LOG_WARNING, - " %s: %s: issue 0x%x: '%s' depth %d\n", - coap_session_str(c_session), - buf, *flags, cn ? cn : "?", depth); - tcp = strchr(tcp+1, '\n'); - } - } - - if (cn) - mbedtls_free(cn); - - return 0; -} - -static int -setup_pki_credentials(mbedtls_x509_crt *cacert, - mbedtls_x509_crt *public_cert, - mbedtls_pk_context *private_key, - coap_mbedtls_env_t *m_env, - coap_mbedtls_context_t *m_context, - coap_session_t *c_session, - coap_dtls_pki_t *setup_data, - coap_dtls_role_t role) -{ - int ret; - - switch (setup_data->pki_key.key_type) { - case COAP_PKI_KEY_PEM: - if (setup_data->pki_key.key.pem.public_cert && - setup_data->pki_key.key.pem.public_cert[0] && - setup_data->pki_key.key.pem.private_key && - setup_data->pki_key.key.pem.private_key[0]) { - - mbedtls_x509_crt_init(public_cert); - mbedtls_pk_init(private_key); - - ret = mbedtls_x509_crt_parse_file(public_cert, - setup_data->pki_key.key.pem.public_cert); - if (ret < 0) { - coap_log(LOG_ERR, "mbedtls_x509_crt_parse_file returned -0x%x\n\n", - -ret); - return ret; - } - - ret = mbedtls_pk_parse_keyfile(private_key, - setup_data->pki_key.key.pem.private_key, NULL); - if (ret < 0) { - coap_log(LOG_ERR, "mbedtls_pk_parse_keyfile returned -0x%x\n\n", -ret); - return ret; - } - - ret = mbedtls_ssl_conf_own_cert(&m_env->conf, public_cert, private_key); - if (ret < 0) { - coap_log(LOG_ERR, "mbedtls_ssl_conf_own_cert returned -0x%x\n\n", -ret); - return ret; - } - } - else if (role == COAP_DTLS_ROLE_SERVER) { - coap_log(LOG_ERR, - "***setup_pki: (D)TLS: No %s Certificate + Private " - "Key defined\n", - role == COAP_DTLS_ROLE_SERVER ? "Server" : "Client"); - return -1; - } - - if (setup_data->pki_key.key.pem.ca_file && - setup_data->pki_key.key.pem.ca_file[0]) { - mbedtls_x509_crt_init(cacert); - ret = mbedtls_x509_crt_parse_file(cacert, - setup_data->pki_key.key.pem.ca_file); - if (ret < 0) { - coap_log(LOG_ERR, "mbedtls_x509_crt_parse returned -0x%x\n\n", -ret); - return ret; - } - mbedtls_ssl_conf_authmode(&m_env->conf, setup_data->require_peer_cert ? - MBEDTLS_SSL_VERIFY_REQUIRED : - MBEDTLS_SSL_VERIFY_OPTIONAL); - mbedtls_ssl_conf_ca_chain(&m_env->conf, cacert, NULL); - } - break; - case COAP_PKI_KEY_PEM_BUF: - if (setup_data->pki_key.key.pem_buf.public_cert && - setup_data->pki_key.key.pem_buf.public_cert_len && - setup_data->pki_key.key.pem_buf.private_key && - setup_data->pki_key.key.pem_buf.private_key_len > 0) { - mbedtls_x509_crt_init(public_cert); - mbedtls_pk_init(private_key); - ret = mbedtls_x509_crt_parse(public_cert, - (const unsigned char *)setup_data->pki_key.key.pem_buf.public_cert, - setup_data->pki_key.key.pem_buf.public_cert_len); - if (ret < 0) { - coap_log(LOG_ERR, "mbedtls_x509_crt_parse returned -0x%x\n\n", -ret); - return ret; - } - - ret = mbedtls_pk_parse_key(private_key, - (const unsigned char *)setup_data->pki_key.key.pem_buf.private_key, - setup_data->pki_key.key.pem_buf.private_key_len, NULL, 0); - if (ret < 0) { - coap_log(LOG_ERR, "mbedtls_pk_parse_keyfile returned -0x%x\n\n", -ret); - return ret; - } - - ret = mbedtls_ssl_conf_own_cert(&m_env->conf, public_cert, private_key); - if (ret < 0) { - coap_log(LOG_ERR, "mbedtls_ssl_conf_own_cert returned -0x%x\n\n", -ret); - return ret; - } - } else if (role == COAP_DTLS_ROLE_SERVER) { - coap_log(LOG_ERR, - "***setup_pki: (D)TLS: No %s Certificate + Private " - "Key defined\n", - role == COAP_DTLS_ROLE_SERVER ? "Server" : "Client"); - return -1; - } - - if (setup_data->pki_key.key.pem_buf.ca_cert && - setup_data->pki_key.key.pem_buf.ca_cert_len > 0) { - mbedtls_x509_crt_init(cacert); - ret = mbedtls_x509_crt_parse(cacert, - (const unsigned char *)setup_data->pki_key.key.pem_buf.ca_cert, - setup_data->pki_key.key.pem_buf.ca_cert_len); - if (ret < 0) { - coap_log(LOG_ERR, "mbedtls_x509_crt_parse returned -0x%x\n\n", -ret); - return ret; - } - mbedtls_ssl_conf_authmode(&m_env->conf, setup_data->require_peer_cert ? - MBEDTLS_SSL_VERIFY_REQUIRED : - MBEDTLS_SSL_VERIFY_OPTIONAL); - mbedtls_ssl_conf_ca_chain(&m_env->conf, cacert, NULL); - } - break; - case COAP_PKI_KEY_ASN1: - if (setup_data->pki_key.key.asn1.public_cert && - setup_data->pki_key.key.asn1.public_cert_len && - setup_data->pki_key.key.asn1.private_key && - setup_data->pki_key.key.asn1.private_key_len > 0) { - - mbedtls_x509_crt_init(public_cert); - mbedtls_pk_init(private_key); - ret = mbedtls_x509_crt_parse(public_cert, - (const unsigned char *)setup_data->pki_key.key.asn1.public_cert, - setup_data->pki_key.key.asn1.public_cert_len); - if (ret < 0) { - coap_log(LOG_ERR, "mbedtls_x509_crt_parse returned -0x%x\n\n", -ret); - return ret; - } - - ret = mbedtls_pk_parse_key(private_key, - (const unsigned char *)setup_data->pki_key.key.asn1.private_key, - setup_data->pki_key.key.asn1.private_key_len, NULL, 0); - if (ret < 0) { - coap_log(LOG_ERR, "mbedtls_pk_parse_keyfile returned -0x%x\n\n", -ret); - return ret; - } - - ret = mbedtls_ssl_conf_own_cert(&m_env->conf, public_cert, private_key); - if (ret < 0) { - coap_log(LOG_ERR, "mbedtls_ssl_conf_own_cert returned -0x%x\n\n", -ret); - return ret; - } - } else if (role == COAP_DTLS_ROLE_SERVER) { - coap_log(LOG_ERR, - "***setup_pki: (D)TLS: No %s Certificate + Private " - "Key defined\n", - role == COAP_DTLS_ROLE_SERVER ? "Server" : "Client"); - return -1; - } - - if (setup_data->pki_key.key.asn1.ca_cert && - setup_data->pki_key.key.asn1.ca_cert_len > 0) { - mbedtls_x509_crt_init(cacert); - ret = mbedtls_x509_crt_parse(cacert, - (const unsigned char *)setup_data->pki_key.key.asn1.ca_cert, - setup_data->pki_key.key.asn1.ca_cert_len); - if (ret < 0) { - coap_log(LOG_ERR, "mbedtls_x509_crt_parse returned -0x%x\n\n", -ret); - return ret; - } - mbedtls_ssl_conf_authmode(&m_env->conf, setup_data->require_peer_cert ? - MBEDTLS_SSL_VERIFY_REQUIRED : - MBEDTLS_SSL_VERIFY_OPTIONAL); - mbedtls_ssl_conf_ca_chain(&m_env->conf, cacert, NULL); - } - break; - default: - coap_log(LOG_ERR, - "***setup_pki: (D)TLS: Unknown key type %d\n", - setup_data->pki_key.key_type); - return -1; - } - - if (m_context->root_ca_file) { - ret = mbedtls_x509_crt_parse_file(cacert, m_context->root_ca_file); - if (ret < 0) { - coap_log(LOG_ERR, "mbedtls_x509_crt_parse returned -0x%x\n\n", -ret); - return ret; - } - mbedtls_ssl_conf_ca_chain(&m_env->conf, cacert, NULL); - } - if (m_context->root_ca_path) { - ret = mbedtls_x509_crt_parse_file(cacert, m_context->root_ca_path); - if (ret < 0) { - coap_log(LOG_ERR, "mbedtls_x509_crt_parse returned -0x%x\n\n", -ret); - return ret; - } - mbedtls_ssl_conf_ca_chain(&m_env->conf, cacert, NULL); - } - - /* - * Verify Peer. - * Need to do all checking, even if setup_data->verify_peer_cert is not set - */ - mbedtls_ssl_conf_verify(&m_env->conf, - cert_verify_callback_mbedtls, c_session); - - return 0; -} - -#if !defined(ESPIDF_VERSION) || defined(CONFIG_MBEDTLS_TLS_SERVER) -/* - * PKI SNI callback. - */ -static int -pki_sni_callback(void *p_info, mbedtls_ssl_context *ssl, - const unsigned char *uname, size_t name_len) -{ - unsigned int i; - coap_dtls_pki_t sni_setup_data; - coap_session_t *c_session = (coap_session_t *)p_info; - coap_mbedtls_env_t *m_env = (coap_mbedtls_env_t *)c_session->tls; - coap_mbedtls_context_t *m_context = - (coap_mbedtls_context_t *)c_session->context->dtls_context; - int ret = 0; - - /* Is this a cached entry? */ - for (i = 0; i < m_context->pki_sni_count; i++) { - if (name_len == strlen(m_context->pki_sni_entry_list[i].sni) && - memcmp(uname, m_context->pki_sni_entry_list[i].sni, name_len) == 0) { - break; - } - } - if (i == m_context->pki_sni_count) { - /* - * New PKI SNI request - */ - char *name; - coap_dtls_key_t *new_entry; - - name = mbedtls_malloc(name_len+1); - if (name == NULL) { - ret = -1; - goto end; - } - - memcpy(name, uname, name_len); - name[name_len] = '\000'; - new_entry = - m_context->setup_data.validate_sni_call_back(name, - m_context->setup_data.sni_call_back_arg); - if (!new_entry) { - ret = -1; - mbedtls_free(name); - goto end; - } - - m_context->pki_sni_entry_list = - mbedtls_realloc(m_context->pki_sni_entry_list, - (i+1)*sizeof(pki_sni_entry)); - if (m_context->pki_sni_entry_list == NULL) { - ret = -1; - mbedtls_free(name); - goto end; - } - - m_context->pki_sni_entry_list[i].sni = name; - m_context->pki_sni_entry_list[i].pki_key = *new_entry; - sni_setup_data = m_context->setup_data; - sni_setup_data.pki_key = *new_entry; - if ((ret = setup_pki_credentials(&m_context->pki_sni_entry_list[i].cacert, - &m_context->pki_sni_entry_list[i].public_cert, - &m_context->pki_sni_entry_list[i].private_key, - m_env, - m_context, - c_session, - &sni_setup_data, COAP_DTLS_ROLE_SERVER)) < 0) { - ret = -1; - mbedtls_free(name); - goto end; - } - m_context->pki_sni_count++; - } - -end: - if (ret != -1) { - mbedtls_ssl_set_hs_ca_chain(ssl, &m_context->pki_sni_entry_list[i].cacert, - NULL); - return mbedtls_ssl_set_hs_own_cert(ssl, - &m_context->pki_sni_entry_list[i].public_cert, - &m_context->pki_sni_entry_list[i].private_key); - } - return ret; -} -#endif /* !ESPIDF_VERSION || CONFIG_MBEDTLS_TLS_SERVER */ - -#ifdef PSK2_PR -/* - * PSK SNI callback. - */ -static int -psk_sni_callback(void *p_info, mbedtls_ssl_context *ssl, - const unsigned char *uname, size_t name_len) -{ - unsigned int i; - coap_dtls_spsk_t sni_setup_data; - coap_session_t *c_session = (coap_session_t *)p_info; - coap_mbedtls_context_t *m_context = - (coap_mbedtls_context_t *)c_session->context->dtls_context; - int ret = 0; - - /* Is this a cached entry? */ - for (i = 0; i < m_context->psk_sni_count; i++) { - if (name_len == m_context->psk_sni_entry_list[i].sni.length && - memcmp(uname, m_context->psk_sni_entry_list[i].sni.s, name_len) == 0) { - break; - } - } - if (i == m_context->psk_sni_count) { - /* - * New PSK SNI request - */ - coap_str_const_t lsni; - uint8_t *name; - const coap_dtls_spsk_info_t *new_entry; - - name = mbedtls_malloc(name_len+1); - if (name == NULL) { - ret = -1; - goto end; - } - - memcpy(name, uname, name_len); - name[name_len] = '\000'; - - lsni.s = name; - lsni.length = name_len; - new_entry = - c_session->context->spsk_setup_data.validate_sni_call_back(&lsni, - c_session, - c_session->context->spsk_setup_data.sni_call_back_arg); - if (!new_entry) { - ret = -1; - mbedtls_free(name); - goto end; - } - - m_context->psk_sni_entry_list = - mbedtls_realloc(m_context->psk_sni_entry_list, - (i+1)*sizeof(psk_sni_entry)); - - if (m_context->psk_sni_entry_list == NULL) { - ret = -1; - mbedtls_free(name); - goto end; - } - - m_context->psk_sni_entry_list[i].sni.s = name; - m_context->psk_sni_entry_list[i].sni.length = name_len; - m_context->psk_sni_entry_list[i].psk_info = *new_entry; - sni_setup_data = c_session->context->spsk_setup_data; - sni_setup_data.psk_info = *new_entry; - m_context->psk_sni_count++; - } - -end: - if (ret != -1) { - coap_session_refresh_psk_hint(c_session, - &m_context->psk_sni_entry_list[i].psk_info.hint); - coap_session_refresh_psk_key(c_session, - &m_context->psk_sni_entry_list[i].psk_info.key); - return mbedtls_ssl_set_hs_psk(ssl, - m_context->psk_sni_entry_list[i].psk_info.key.s, - m_context->psk_sni_entry_list[i].psk_info.key.length); - } - return ret; -} -#endif /* PSK2_PR */ - -#if !defined(ESPIDF_VERSION) || defined(CONFIG_MBEDTLS_TLS_SERVER) - -static int setup_server_ssl_session(coap_session_t *c_session, - coap_mbedtls_env_t *m_env) -{ - coap_mbedtls_context_t *m_context = - (coap_mbedtls_context_t *)c_session->context->dtls_context; - int ret = 0; - m_context->psk_pki_enabled |= IS_SERVER; - - mbedtls_ssl_cookie_init(&m_env->cookie_ctx); - if ((ret = mbedtls_ssl_config_defaults(&m_env->conf, - MBEDTLS_SSL_IS_SERVER, - c_session->proto == COAP_PROTO_DTLS ? - MBEDTLS_SSL_TRANSPORT_DATAGRAM : - MBEDTLS_SSL_TRANSPORT_STREAM, - MBEDTLS_SSL_PRESET_DEFAULT)) != 0) { - coap_log(LOG_ERR, "mbedtls_ssl_config_defaults returned -0x%x\n", -ret); - goto fail; - } - - mbedtls_ssl_conf_rng(&m_env->conf, mbedtls_ctr_drbg_random, &m_env->ctr_drbg); - -#if !defined(ESPIDF_VERSION) || defined(CONFIG_MBEDTLS_SSL_PROTO_DTLS) - mbedtls_ssl_conf_handshake_timeout(&m_env->conf, 1000, 60000); - - if (m_context->psk_pki_enabled & IS_PSK) { -#if !defined(ESPIDF_VERSION) || defined(CONFIG_MBEDTLS_PSK_MODES) - mbedtls_ssl_conf_psk_cb(&m_env->conf, psk_server_callback, c_session); -#ifdef PSK2_PR - if (c_session->context->spsk_setup_data.validate_sni_call_back) { - mbedtls_ssl_conf_sni(&m_env->conf, psk_sni_callback, c_session); - } -#endif /* PSK2_PR */ -#endif /* !ESPIDF_VERSION || CONFIG_MBEDTLS_PSK_MODES */ - } -#endif /* !ESPIDF_VERSION || CONFIG_MBEDTLS_SSL_PROTO_DTLS */ - - if (m_context->psk_pki_enabled & IS_PKI) { - ret = setup_pki_credentials(&m_env->cacert, &m_env->public_cert, - &m_env->private_key, m_env, m_context, - c_session, &m_context->setup_data, - COAP_DTLS_ROLE_SERVER); - if (ret < 0) { - coap_log(LOG_ERR, "PKI setup failed\n"); - return ret; - } - if (m_context->setup_data.validate_sni_call_back) { - mbedtls_ssl_conf_sni(&m_env->conf, pki_sni_callback, c_session); - } - } - - if ((ret = mbedtls_ssl_cookie_setup(&m_env->cookie_ctx, - mbedtls_ctr_drbg_random, - &m_env->ctr_drbg)) != 0) { - coap_log(LOG_ERR, "mbedtls_ssl_cookie_setup: returned -0x%x\n", -ret); - goto fail; - } - -#if !defined(ESPIDF_VERSION) || defined(CONFIG_MBEDTLS_SSL_PROTO_DTLS) - mbedtls_ssl_conf_dtls_cookies(&m_env->conf, mbedtls_ssl_cookie_write, - mbedtls_ssl_cookie_check, - &m_env->cookie_ctx ); - mbedtls_ssl_set_mtu(&m_env->ssl, c_session->mtu); -#endif /* !ESPIDF_VERSION || CONFIG_MBEDTLS_SSL_PROTO_DTLS */ -fail: - return ret; -} -#endif /* !defined(ESPIDF_VERSION) || CONFIG_MBEDTLS_TLS_SERVER) */ - -#if !defined(ESPIDF_VERSION) || defined(CONFIG_MBEDTLS_PSK_MODES) -#define MAX_CIPHERS 100 -static int psk_ciphers[MAX_CIPHERS]; -static int pki_ciphers[MAX_CIPHERS]; -static int processed_ciphers = 0; - -static void -set_ciphersuites(mbedtls_ssl_config *conf, int is_psk) -{ - if (!processed_ciphers) { - const int *list = mbedtls_ssl_list_ciphersuites(); - int *psk_list = psk_ciphers; - int *pki_list = pki_ciphers; - - while (*list) { - const mbedtls_ssl_ciphersuite_t *cur = - mbedtls_ssl_ciphersuite_from_id(*list); - - if (cur) { - if (mbedtls_ssl_ciphersuite_uses_psk(cur)) { - if (&psk_ciphers[MAX_CIPHERS] - psk_list > 1) { - *psk_list = *list; - psk_list++; - } - else { - static int done = 0; - - if (!done) { - done = 1; - coap_log(LOG_ERR, "psk_ciphers[MAX_CIPHERS] insufficient\n"); - } - } - } - else { - if (&pki_ciphers[MAX_CIPHERS] - pki_list > 1) { - *pki_list = *list; - pki_list++; - } - else { - static int done = 0; - - if (!done) { - done = 1; - coap_log(LOG_ERR, "pki_ciphers[MAX_CIPHERS] insufficient\n"); - } - } - } - } - list++; - } - /* zero terminate */ - *psk_list = 0; - *pki_list = 0; - processed_ciphers = 1; - } - mbedtls_ssl_conf_ciphersuites(conf, is_psk ? psk_ciphers : pki_ciphers); -} -#endif /* !ESPIDF_VERSION || CONFIG_MBEDTLS_PSK_MODES */ - -static int setup_client_ssl_session(coap_session_t *c_session, - coap_mbedtls_env_t *m_env) -{ - int ret; - - coap_mbedtls_context_t *m_context = - (coap_mbedtls_context_t *)c_session->context->dtls_context; - - m_context->psk_pki_enabled |= IS_CLIENT; - - if ((ret = mbedtls_ssl_config_defaults(&m_env->conf, - MBEDTLS_SSL_IS_CLIENT, - c_session->proto == COAP_PROTO_DTLS ? - MBEDTLS_SSL_TRANSPORT_DATAGRAM : - MBEDTLS_SSL_TRANSPORT_STREAM, - MBEDTLS_SSL_PRESET_DEFAULT)) != 0) { - coap_log(LOG_ERR, "mbedtls_ssl_config_defaults returned -0x%x", -ret); - goto fail; - } - -#if !defined(ESPIDF_VERSION) || defined(CONFIG_MBEDTLS_SSL_PROTO_DTLS) - mbedtls_ssl_conf_handshake_timeout(&m_env->conf, 1000, 60000); -#endif /* !ESPIDF_VERSION || CONFIG_MBEDTLS_SSL_PROTO_DTLS */ - - mbedtls_ssl_conf_authmode(&m_env->conf, MBEDTLS_SSL_VERIFY_REQUIRED); - mbedtls_ssl_conf_rng(&m_env->conf, mbedtls_ctr_drbg_random, &m_env->ctr_drbg); - - if (m_context->psk_pki_enabled & IS_PSK) { -#if !defined(ESPIDF_VERSION) || defined(CONFIG_MBEDTLS_PSK_MODES) - uint8_t identity[64]; - size_t identity_len; - uint8_t psk_key[64]; - size_t psk_len; - size_t max_identity_len = sizeof(identity); - - coap_log(LOG_INFO, "Setting PSK key\n"); - psk_len = c_session->context->get_client_psk(c_session, - NULL, - 0, - identity, - &identity_len, - max_identity_len, - psk_key, - sizeof(psk_key)); - assert(identity_len < sizeof(identity)); - mbedtls_ssl_conf_psk(&m_env->conf, (const unsigned char *)psk_key, - psk_len, (const unsigned char *)identity, - identity_len); -#ifdef PSK2_PR - if (c_session->cpsk_setup_data.client_sni) { - mbedtls_ssl_set_hostname(&m_env->ssl, - c_session->cpsk_setup_data.client_sni); - } -#if 0 -/* Identity Hint currently not supported in MbedTLS */ - if (c_session->cpsk_setup_data.validate_ih_call_back) { - coap_log(LOG_DEBUG, - "CoAP Client restricted to (D)TLS1.2 with Identity Hint callback\n"); - mbedtls_ssl_conf_max_version(&m_env->conf, MBEDTLS_SSL_MAJOR_VERSION_3, - MBEDTLS_SSL_MINOR_VERSION_3); - } -#endif -#endif /* PSK2_PR */ - set_ciphersuites(&m_env->conf, 1); -#endif /* !ESPIDF_VERSION || CONFIG_MBEDTLS_PSK_MODES */ - } - else if ((m_context->psk_pki_enabled & IS_PKI) || - (m_context->psk_pki_enabled & (IS_PSK | IS_PKI)) == 0) { - /* - * If neither PSK or PKI have been set up, use PKI basics. - * This works providing COAP_PKI_KEY_PEM has a value of 0. - */ - if ((m_context->psk_pki_enabled & (IS_PSK | IS_PKI)) == 0) { - mbedtls_ssl_conf_authmode(&m_env->conf, MBEDTLS_SSL_VERIFY_OPTIONAL); - } - ret = setup_pki_credentials(&m_env->cacert, &m_env->public_cert, - &m_env->private_key, m_env, m_context, - c_session, &m_context->setup_data, - COAP_DTLS_ROLE_CLIENT); - if (ret < 0) { - coap_log(LOG_ERR, "PKI setup failed\n"); - return ret; - } -#if !defined(ESPIDF_VERSION) ||(defined(CONFIG_MBEDTLS_TLS_SERVER) && defined(CONFIG_MBEDTLS_SSL_ALPN)) - if (c_session->proto == COAP_PROTO_TLS) { - const char *alpn_list[2]; - - memset(alpn_list, 0, sizeof(alpn_list)); - alpn_list[0] = "coap"; - ret = mbedtls_ssl_conf_alpn_protocols(&m_env->conf, alpn_list); - if (ret != 0) { - coap_log(LOG_ERR, "ALPN setup failed %d)\n", ret); - } - } -#endif /* !ESPIDF_VERSION || (CONFIG_MBEDTLS_TLS_SERVER && CONFIG_MBEDTLS_SSL_ALPN) */ - if (m_context->setup_data.client_sni) { - mbedtls_ssl_set_hostname(&m_env->ssl, m_context->setup_data.client_sni); - } -#if !defined(ESPIDF_VERSION) || defined(CONFIG_MBEDTLS_SSL_PROTO_DTLS) - mbedtls_ssl_set_mtu(&m_env->ssl, c_session->mtu); -#endif /* !ESPIDF_VERSION || CONFIG_MBEDTLS_SSL_PROTO_DTLS */ -#if !defined(ESPIDF_VERSION) || defined(CONFIG_MBEDTLS_PSK_MODES) - set_ciphersuites(&m_env->conf, 0); -#endif /* !ESPIDF_VERSION || CONFIG_MBEDTLS_PSK_MODES */ - } - return 0; - -fail: - return ret; -} - -static void mbedtls_cleanup(coap_mbedtls_env_t *m_env) -{ - if (!m_env) { - return; - } - - mbedtls_x509_crt_free(&m_env->cacert); - mbedtls_x509_crt_free(&m_env->public_cert); - mbedtls_pk_free(&m_env->private_key); - mbedtls_entropy_free(&m_env->entropy); - mbedtls_ssl_config_free(&m_env->conf); - mbedtls_ctr_drbg_free(&m_env->ctr_drbg); - mbedtls_ssl_free(&m_env->ssl); - mbedtls_ssl_cookie_free(&m_env->cookie_ctx); -} - -static void -coap_dtls_free_mbedtls_env(coap_mbedtls_env_t *m_env) { - if (m_env) { - mbedtls_cleanup(m_env); - free(m_env); - } -} - -/* - * return -1 failure - * 0 not completed - * 1 established - */ -static int do_mbedtls_handshake(coap_session_t *c_session, - coap_mbedtls_env_t *m_env) { - int ret; - char buf[128]; - - ret = mbedtls_ssl_handshake(&m_env->ssl); - switch (ret) { - case 0: - m_env->established = 1; - coap_log(LOG_DEBUG, "* %s: MbedTLS established\n", - coap_session_str(c_session)); - ret = 1; - break; - case MBEDTLS_ERR_SSL_WANT_READ: - case MBEDTLS_ERR_SSL_WANT_WRITE: - errno = EAGAIN; - ret = 0; - break; - case MBEDTLS_ERR_SSL_HELLO_VERIFY_REQUIRED: - coap_log(LOG_INFO, "hello verification requested\n"); - ret = -1; - mbedtls_ssl_session_reset(&m_env->ssl); - break; - case MBEDTLS_ERR_SSL_FATAL_ALERT_MESSAGE: - c_session->dtls_event = COAP_EVENT_DTLS_CLOSED; - ret = -1; - break; - default: - mbedtls_strerror(ret, buf, sizeof(buf)); - coap_log(LOG_WARNING, - "do_mbedtls_handshake: session establish " - "returned -0x%x: '%s'\n", - -ret, buf); - ret = -1; - break; - } - return ret; -} - -static void -mbedtls_debug_out(void *ctx UNUSED, int level, - const char *file, int line, const char *str) { - int log_level; - - switch (level) { - case 4: - case 3: - case 2: - log_level = LOG_DEBUG; - break; - case 1: - log_level = LOG_ERR; - break; - case 0: - default: - log_level = 0; - break; - } - coap_log(log_level, "%s:%04d: %s", file, line, str); -} - -static coap_mbedtls_env_t *coap_dtls_new_mbedtls_env(coap_session_t *c_session, - coap_dtls_role_t role) -{ - int ret = 0; - coap_mbedtls_env_t *m_env = (coap_mbedtls_env_t *)c_session->tls; - - if (m_env) - return m_env; - - m_env = (coap_mbedtls_env_t *)calloc(1, sizeof(coap_mbedtls_env_t)); - if (!m_env) { - return NULL; - } - - mbedtls_ssl_init(&m_env->ssl); - mbedtls_ctr_drbg_init(&m_env->ctr_drbg); - mbedtls_ssl_config_init(&m_env->conf); - mbedtls_entropy_init(&m_env->entropy); - -#if defined(ESPIDF_VERSION) && defined(CONFIG_MBEDTLS_DEBUG) - mbedtls_esp_enable_debug_log(&m_env->conf, CONFIG_MBEDTLS_DEBUG_LEVEL); -#endif /* ESPIDF_VERSION && CONFIG_MBEDTLS_DEBUG */ - if ((ret = mbedtls_ctr_drbg_seed(&m_env->ctr_drbg, - mbedtls_entropy_func, &m_env->entropy, NULL, 0)) != 0) { - coap_log(LOG_ERR, "mbedtls_ctr_drbg_seed returned -0x%x", -ret); - goto fail; - } - - if (role == COAP_DTLS_ROLE_CLIENT) { - if (setup_client_ssl_session(c_session, m_env) != 0) { - goto fail; - } -#if !defined(ESPIDF_VERSION) || defined(CONFIG_MBEDTLS_TLS_SERVER) - } else if (role == COAP_DTLS_ROLE_SERVER) { - if (setup_server_ssl_session(c_session, m_env) != 0) { - goto fail; - } -#endif /* !ESPIDF_VERSION || CONFIG_MBEDTLS_TLS_SERVER */ - } else { - goto fail; - } - - if ((ret = mbedtls_ssl_setup(&m_env->ssl, &m_env->conf)) != 0) { - goto fail; - } - mbedtls_ssl_set_bio(&m_env->ssl, c_session, coap_dgram_write, - coap_dgram_read, NULL); - mbedtls_ssl_set_timer_cb(&m_env->ssl, &m_env->timer, - mbedtls_timing_set_delay, - mbedtls_timing_get_delay); - - mbedtls_ssl_conf_dbg(&m_env->conf, mbedtls_debug_out, stdout); - return m_env; - -fail: - if (m_env) { - free(m_env); - } - return NULL; -} - -int coap_dtls_is_supported(void) { -#if !defined(ESPIDF_VERSION) || defined(CONFIG_MBEDTLS_SSL_PROTO_DTLS) - return 1; -#else /* ESPIDF_VERSION && !CONFIG_MBEDTLS_SSL_PROTO_DTLS */ - coap_log(LOG_EMERG, - "libcoap not compiled for DTLS with MbedTLS" - " - update MbedTLS to include DTLS\n"); - return 0; -#endif /* ESPIDF_VERSION && !CONFIG_MBEDTLS_SSL_PROTO_DTLS */ -} - -int coap_tls_is_supported(void) -{ - return 0; -} - -void *coap_dtls_new_context(struct coap_context_t *c_context) -{ - coap_mbedtls_context_t *m_context; - (void)c_context; - - m_context = (coap_mbedtls_context_t *)calloc(1, sizeof(coap_mbedtls_context_t)); - if (m_context) { - memset(m_context, 0, sizeof(coap_mbedtls_context_t)); - } - return m_context; -} - -#ifndef PSK2_PR -int coap_dtls_context_set_psk(struct coap_context_t *c_context, - const char *identity_hint UNUSED, - coap_dtls_role_t role UNUSED) -{ - coap_mbedtls_context_t *m_context = - ((coap_mbedtls_context_t *)c_context->dtls_context); -#if defined(ESPIDF_VERSION) && (!defined(CONFIG_MBEDTLS_PSK_MODES) || !defined(CONFIG_MBEDTLS_KEY_EXCHANGE_PSK)) - coap_log(LOG_EMERG, "coap_dtls_context_set_psk:" - " libcoap not compiled with MBEDTLS_PSK_MODES and MBEDTLS_KEY_EXCHANGE_PSK" - " - update mbedTLS to include psk mode configs\n"); - return 0; -#endif /* ESPIDF_VERSION && (!CONFIG_MBEDTLS_PSK_MODES || !CONFIG_MBEDTLS_KEY_EXCHANGE_PSK) */ - -#if defined(ESPIDF_VERSION) && !defined(CONFIG_MBEDTLS_TLS_SERVER) - coap_log(LOG_EMERG, "coap_dtls_context_set_psk:" - " libcoap not compiled for Server Mode for MbedTLS" - " - update MbedTLS to include Server Mode\n"); - return 0; -#endif /* ESPIDF_VERSION && !CONFIG_MBEDTLS_TLS_SERVER */ - m_context->psk_pki_enabled |= IS_PSK; - return 1; -} -#else /* PSK2_PR */ -/* - * return 0 failed - * 1 passed - */ -int -coap_dtls_context_set_spsk(coap_context_t *c_context, - coap_dtls_spsk_t *setup_data -) { - coap_mbedtls_context_t *m_context = - ((coap_mbedtls_context_t *)c_context->dtls_context); - -#if defined(ESPIDF_VERSION) && !defined(CONFIG_MBEDTLS_TLS_SERVER) - coap_log(LOG_EMERG, "coap_dtls_context_set_spsk:" - " libcoap not compiled for Server Mode for MbedTLS" - " - update MbedTLS to include Server Mode\n"); - return 0; -#endif /* ESPIDF_VERSION && !CONFIG_MBEDTLS_TLS_SERVER */ - if (!m_context || !setup_data) - return 0; - - m_context->psk_pki_enabled |= IS_PSK; - return 1; -} - -/* - * return 0 failed - * 1 passed - */ -int -coap_dtls_context_set_cpsk(coap_context_t *c_context, - coap_dtls_cpsk_t *setup_data -) { - coap_mbedtls_context_t *m_context = - ((coap_mbedtls_context_t *)c_context->dtls_context); - - if (!m_context || !setup_data) - return 0; - - if (setup_data->validate_ih_call_back) { - coap_log(LOG_WARNING, - "CoAP Client with MbedTLS does not support Identity Hint selection\n"); - } - m_context->psk_pki_enabled |= IS_PSK; - return 1; -} - -#endif /* PSK2_PR */ - -int coap_dtls_context_set_pki(struct coap_context_t *c_context, - coap_dtls_pki_t *setup_data, - coap_dtls_role_t role UNUSED) -{ -#if defined(ESPIDF_VERSION) && (!defined(CONFIG_MBEDTLS_PSK_MODES) || !defined(CONFIG_MBEDTLS_KEY_EXCHANGE_PSK)) - coap_log(LOG_EMERG, "coap_dtls_context_set_pki:" - " libcoap not compiled with MBEDTLS_PSK_MODES and MBEDTLS_KEY_EXCHANGE_PSK" - " - update mbedTLS to include psk mode configs\n"); - return 0; -#endif /* ESPIDF_VERSION && (!CONFIG_MBEDTLS_PSK_MODES || !CONFIG_MBEDTLS_KEY_EXCHANGE_PSK) */ - - coap_mbedtls_context_t *m_context = - ((coap_mbedtls_context_t *)c_context->dtls_context); - - m_context->setup_data = *setup_data; - m_context->psk_pki_enabled |= IS_PKI; - return 1; -} - -int coap_dtls_context_set_pki_root_cas(struct coap_context_t *c_context, - const char *ca_file, - const char *ca_path) -{ - coap_mbedtls_context_t *m_context = - ((coap_mbedtls_context_t *)c_context->dtls_context); - - if (!m_context) { - coap_log(LOG_WARNING, - "coap_context_set_pki_root_cas: (D)TLS environment " - "not set up\n"); - return 0; - } - - if (ca_file == NULL && ca_path == NULL) { - coap_log(LOG_WARNING, - "coap_context_set_pki_root_cas: ca_file and/or ca_path " - "not defined\n"); - return 0; - } - if (m_context->root_ca_file) { - free(m_context->root_ca_file); - m_context->root_ca_file = NULL; - } - - if (ca_file) { - m_context->root_ca_file = mbedtls_strdup(ca_file); - } - - if (m_context->root_ca_path) { - free(m_context->root_ca_path); - m_context->root_ca_path = NULL; - } - - if (ca_path) { - m_context->root_ca_path = mbedtls_strdup(ca_path); - } - return 1; -} - -int coap_dtls_context_check_keys_enabled(struct coap_context_t *c_context) -{ - coap_mbedtls_context_t *m_context = - ((coap_mbedtls_context_t *)c_context->dtls_context); - return m_context->psk_pki_enabled ? 1 : 0; -} - -void coap_dtls_free_context(void *dtls_context) -{ - coap_mbedtls_context_t *m_context = (coap_mbedtls_context_t *)dtls_context; - unsigned int i; - - for (i = 0; i < m_context->pki_sni_count; i++) { - mbedtls_free(m_context->pki_sni_entry_list[i].sni); - - mbedtls_x509_crt_free(&m_context->pki_sni_entry_list[i].public_cert); - - mbedtls_pk_free(&m_context->pki_sni_entry_list[i].private_key); - - mbedtls_x509_crt_free(&m_context->pki_sni_entry_list[i].cacert); - } -#ifdef PSK2_PR - for (i = 0; i < m_context->psk_sni_count; i++) { - mbedtls_free(m_context->psk_sni_entry_list[i].sni.s); - } - if (m_context->psk_sni_entry_list) - mbedtls_free(m_context->pki_sni_entry_list); - -#endif /* PSK2_PR */ - - free(m_context); -} - -void *coap_dtls_new_client_session(coap_session_t *c_session) -{ -#if defined(ESPIDF_VERSION) && !defined(CONFIG_MBEDTLS_TLS_CLIENT) - (void)c_session; - coap_log(LOG_EMERG, "coap_dtls_new_client_session:" - " libcoap not compiled for Client Mode for MbedTLS" - " - update MbedTLS to include Client Mode\n"); - return NULL; -#else /* !ESPIDF_VERSION || CONFIG_MBEDTLS_TLS_CLIENT */ - coap_mbedtls_env_t *m_env = coap_dtls_new_mbedtls_env(c_session, - COAP_DTLS_ROLE_CLIENT); - int ret; - - if (m_env) { - ret = do_mbedtls_handshake(c_session, m_env); - if (ret == -1) { - coap_dtls_free_mbedtls_env(m_env); - return NULL; - } - } - return m_env; -#endif /* !ESPIDF_VERSION || CONFIG_MBEDTLS_TLS_CLIENT */ -} - -void *coap_dtls_new_server_session(coap_session_t *c_session) -{ - coap_mbedtls_env_t *m_env = - (coap_mbedtls_env_t *)c_session->tls; - if (m_env) { - m_env->seen_client_hello = 1; -#if !defined(ESPIDF_VERSION) || defined(CONFIG_MBEDTLS_SSL_PROTO_DTLS) - mbedtls_ssl_set_mtu(&m_env->ssl, c_session->mtu); -#endif /* !ESPIDF_VERSION || CONFIG_MBEDTLS_SSL_PROTO_DTLS */ - } - return m_env; -} - -void coap_dtls_free_session(coap_session_t *c_session) -{ - if (c_session && c_session->context) { - coap_dtls_free_mbedtls_env(c_session->tls); - c_session->tls = NULL; - } - return; -} - -void coap_dtls_session_update_mtu(coap_session_t *c_session) -{ -#if !defined(ESPIDF_VERSION) || defined(CONFIG_MBEDTLS_SSL_PROTO_DTLS) - coap_mbedtls_env_t *m_env = - (coap_mbedtls_env_t *)c_session->tls; - if (m_env) { - mbedtls_ssl_set_mtu(&m_env->ssl, c_session->mtu); - } -#endif /* !ESPIDF_VERSION || CONFIG_MBEDTLS_SSL_PROTO_DTLS */ -} - -int coap_dtls_send(coap_session_t *c_session, - const uint8_t *data, - size_t data_len) -{ - int ret; - coap_mbedtls_env_t *m_env = (coap_mbedtls_env_t *)c_session->tls; - char buf[128]; - - assert(m_env != NULL); - - if (!m_env) { - return -1; - } - c_session->dtls_event = -1; - if (m_env->established) { - ret = mbedtls_ssl_write(&m_env->ssl, (const unsigned char*) data, data_len); - if (ret <= 0) { - switch (ret) { - case MBEDTLS_ERR_SSL_WANT_READ: - case MBEDTLS_ERR_SSL_WANT_WRITE: - ret = 0; - break; - case MBEDTLS_ERR_SSL_FATAL_ALERT_MESSAGE: - c_session->dtls_event = COAP_EVENT_DTLS_CLOSED; - ret = -1; - break; - default: - mbedtls_strerror(ret, buf, sizeof(buf)); - coap_log(LOG_WARNING, - "coap_dtls_send: " - "returned -0x%x: '%s'\n", - -ret, buf); - ret = -1; - break; - } - if (ret == -1) { - coap_log(LOG_WARNING, "coap_dtls_send: cannot send PDU\n"); - } - } - } else { - ret = do_mbedtls_handshake(c_session, m_env); - if (ret == 1) { - /* Just connected, so send the data */ - return coap_dtls_send(c_session, data, data_len); - } - ret = -1; - } - - if (c_session->dtls_event >= 0) { - coap_handle_event(c_session->context, c_session->dtls_event, c_session); - if (c_session->dtls_event == COAP_EVENT_DTLS_ERROR || - c_session->dtls_event == COAP_EVENT_DTLS_CLOSED) { - coap_session_disconnected(c_session, COAP_NACK_TLS_FAILED); - ret = -1; - } - } - return ret; -} - -int coap_dtls_is_context_timeout(void) -{ - return 0; -} - -coap_tick_t coap_dtls_get_context_timeout(void *dtls_context UNUSED) -{ - return 0; -} - -coap_tick_t coap_dtls_get_timeout(coap_session_t *c_session, coap_tick_t now) -{ - coap_mbedtls_env_t *m_env = (coap_mbedtls_env_t *)c_session->tls; - int ret = mbedtls_timing_get_delay(&m_env->timer); - - switch (ret) { - case 0: - case 1: - /* int_ms has timed out, but not fin_ms */ - return now + 1; - case 2: - /* fin_ms has timed out - time for a retry */ - return now; - default: - break; - } - - return 0; -} - -void coap_dtls_handle_timeout(coap_session_t *c_session) -{ - coap_mbedtls_env_t *m_env = (coap_mbedtls_env_t *)c_session->tls; - - assert(m_env != NULL); - if (((c_session->state == COAP_SESSION_STATE_HANDSHAKE) && - (++c_session->dtls_timeout_count > c_session->max_retransmit)) || - (do_mbedtls_handshake(c_session, m_env) < 0)) { - /* Too many retries */ - coap_session_disconnected(c_session, COAP_NACK_TLS_FAILED); - } - return; -} - -int coap_dtls_receive(coap_session_t *c_session, - const uint8_t *data, - size_t data_len) -{ - int ret = 1; - - c_session->dtls_event = -1; - coap_mbedtls_env_t *m_env = (coap_mbedtls_env_t *)c_session->tls; - assert(m_env != NULL); - - coap_ssl_t *ssl_data = &m_env->coap_ssl_data; - if (ssl_data->pdu_len) { - coap_log(LOG_INFO, "** %s: Previous data not read %u bytes\n", - coap_session_str(c_session), ssl_data->pdu_len); - } - ssl_data->pdu = data; - ssl_data->pdu_len = (unsigned)data_len; - - if (m_env->established) { -#if COAP_CONSTRAINED_STACK - static coap_mutex_t b_static_mutex = COAP_MUTEX_INITIALIZER; - static uint8_t pdu[COAP_RXBUFFER_SIZE]; -#else /* ! COAP_CONSTRAINED_STACK */ - uint8_t pdu[COAP_RXBUFFER_SIZE]; -#endif /* ! COAP_CONSTRAINED_STACK */ - -#if COAP_CONSTRAINED_STACK - coap_mutex_lock(&b_static_mutex); -#endif /* COAP_CONSTRAINED_STACK */ - - if (c_session->state == COAP_SESSION_STATE_HANDSHAKE) { - coap_handle_event(c_session->context, COAP_EVENT_DTLS_CONNECTED, - c_session); - coap_session_connected(c_session); - } - - ret = mbedtls_ssl_read(&m_env->ssl, pdu, (int)sizeof(pdu)); - if (ret > 0) { - ret = coap_handle_dgram(c_session->context, c_session, pdu, (size_t)ret); -#if COAP_CONSTRAINED_STACK - coap_mutex_unlock(&b_static_mutex); -#endif /* COAP_CONSTRAINED_STACK */ - return ret; - } - else if (ret == 0 || ret == MBEDTLS_ERR_SSL_PEER_CLOSE_NOTIFY) { - c_session->dtls_event = COAP_EVENT_DTLS_CLOSED; - } - else if (ret != MBEDTLS_ERR_SSL_WANT_READ) { - char buf[128]; - - mbedtls_strerror(ret, buf, sizeof(buf)); - coap_log(LOG_WARNING, - "coap_dtls_receive: " - "returned -0x%x: '%s' (length %zd)\n", - -ret, buf, data_len); - } -#if COAP_CONSTRAINED_STACK - coap_mutex_unlock(&b_static_mutex); -#endif /* COAP_CONSTRAINED_STACK */ - ret = -1; - } - else { - ret = do_mbedtls_handshake(c_session, m_env); - if (ret == 1) { - /* Just connected, so send the data */ - coap_session_connected(c_session); - } else { - if (ssl_data->pdu_len) { - /* Do the handshake again incase of internal timeout */ - ret = do_mbedtls_handshake(c_session, m_env); - if (ret == 1) { - /* Just connected, so send the data */ - coap_session_connected(c_session); - } else { - ret = -1; - } - } - ret = -1; - } - } - if (c_session->dtls_event >= 0) { - coap_handle_event(c_session->context, c_session->dtls_event, c_session); - if (c_session->dtls_event == COAP_EVENT_DTLS_ERROR || - c_session->dtls_event == COAP_EVENT_DTLS_CLOSED) { - coap_session_disconnected(c_session, COAP_NACK_TLS_FAILED); - ret = -1; - } - } - return ret; -} - -int coap_dtls_hello(coap_session_t *c_session, - const uint8_t *data, - size_t data_len) -{ -#if defined(ESPIDF_VERSION) && (!defined(CONFIG_MBEDTLS_SSL_PROTO_DTLS) || !defined(CONFIG_MBEDTLS_TLS_SERVER)) - (void)c_session; - (void)data; - (void)data_len; - coap_log(LOG_EMERG, "coap_dtls_hello:" - " libcoap not compiled for DTLS or Server Mode for MbedTLS" - " - update MbedTLS to include DTLS and Server Mode\n"); - return -1; -#else /* !ESPIDF_VERSION) || (CONFIG_MBEDTLS_SSL_PROTO_DTLS && CONFIG_MBEDTLS_TLS_SERVER) */ - coap_mbedtls_env_t *m_env = (coap_mbedtls_env_t *)c_session->tls; - coap_ssl_t *ssl_data = m_env ? &m_env->coap_ssl_data : NULL; - int ret; - - if (m_env) { - char *str = get_ip_addr(&c_session->remote_addr); - if (!str) { - return -1; - } - if((ret = mbedtls_ssl_set_client_transport_id(&m_env->ssl, - (unsigned char *)str, strlen(str))) != 0) { - coap_log(LOG_ERR, - "mbedtls_ssl_set_client_transport_id() returned -0x%x\n\n", - -ret); - free(str); - return -1; - } - free(str); - } - - if (!m_env) { - m_env = coap_dtls_new_mbedtls_env(c_session, COAP_DTLS_ROLE_SERVER); - if (m_env) { - c_session->tls = m_env; - ssl_data = &m_env->coap_ssl_data; - ssl_data->pdu = data; - ssl_data->pdu_len = (unsigned)data_len; - char *str = get_ip_addr(&c_session->remote_addr); - if (!str) { - return -1; - } - if((ret = mbedtls_ssl_set_client_transport_id(&m_env->ssl, - (unsigned char *)str, strlen(str)) ) != 0) { - coap_log(LOG_ERR, - "mbedtls_ssl_set_client_transport_id() returned -0x%x\n", - -ret); - free(str); - return -1; - } - ret = do_mbedtls_handshake(c_session, m_env); - if (ret == 0 || m_env->seen_client_hello) { - m_env->seen_client_hello = 0; - free(str); - return 1; - } - free(str); - } - return 0; - } - - ssl_data->pdu = data; - ssl_data->pdu_len = (unsigned)data_len; - ret = do_mbedtls_handshake(c_session, m_env); - if (ret == 0 || m_env->seen_client_hello) { - /* The test for seen_client_hello gives the ability to setup a new - c_session to continue the do_mbedtls_handshake past the client hello - and safely allow updating of the m_env and separately - letting a new session cleanly start up. - */ - m_env->seen_client_hello = 0; - return 1; - } - return 0; -#endif /* !ESPIDF_VERSION) || (CONFIG_MBEDTLS_SSL_PROTO_DTLS && CONFIG_MBEDTLS_TLS_SERVER) */ -} - -unsigned int coap_dtls_get_overhead(coap_session_t *c_session UNUSED) -{ - return 13 + 8 + 8; -} - -void *coap_tls_new_client_session(coap_session_t *c_session UNUSED, int *connected UNUSED) -{ - return NULL; -} - -void *coap_tls_new_server_session(coap_session_t *c_session UNUSED, int *connected UNUSED) -{ - return NULL; -} - -void coap_tls_free_session( coap_session_t *c_session UNUSED) -{ - return; -} - -ssize_t coap_tls_write(coap_session_t *c_session UNUSED, - const uint8_t *data UNUSED, - size_t data_len UNUSED - ) -{ - return 0; -} - -ssize_t coap_tls_read(coap_session_t *c_session UNUSED, - uint8_t *data UNUSED, - size_t data_len UNUSED - ) -{ - return 0; -} - -void coap_dtls_startup(void) -{ - return; -} - -static int keep_log_level = 0; - -void coap_dtls_set_log_level(int level) -{ -#if !defined(ESPIDF_VERSION) - int use_level; - /* - * MbedTLS debug levels filter - * 0 No debug - * 1 Error - * 2 State change - * 3 Informational - * 4 Verbose - */ - - if (level <= LOG_ERR) { - use_level = 1; - } - else { - use_level = (level >= LOG_DEBUG) ? level - LOG_DEBUG + 2 : 0; - } - mbedtls_debug_set_threshold(use_level); -#endif /* !ESPIDF_VERSION) */ - keep_log_level = level; - return; -} - -int coap_dtls_get_log_level(void) -{ - return keep_log_level; -} - -coap_tls_version_t * coap_get_tls_library_version(void) -{ - static coap_tls_version_t version; - version.version = mbedtls_version_get_number(); - version.built_version = MBEDTLS_VERSION_NUMBER; - version.type = COAP_TLS_LIBRARY_MBEDTLS; - return &version; -} - -#else /* !HAVE_MBEDTLS */ - -#ifdef __clang__ -/* Make compilers happy that do not like empty modules. As this function is - * never used, we ignore -Wunused-function at the end of compiling this file - */ -#pragma GCC diagnostic ignored "-Wunused-function" -#endif -static inline void dummy(void) { -} - -#endif /* HAVE_MBEDTLS */ diff --git a/components/coap/port/coap_notls.c b/components/coap/port/coap_notls.c deleted file mode 100644 index aa2c27c688..0000000000 --- a/components/coap/port/coap_notls.c +++ /dev/null @@ -1,190 +0,0 @@ -/* -* coap_notls.c -- Stub Datagram Transport Layer Support for libcoap -* -* Copyright (C) 2016 Olaf Bergmann -* -* This file is part of the CoAP library libcoap. Please see README for terms -* of use. -*/ - -#include "coap_config.h" - -#if !defined(HAVE_LIBTINYDTLS) && !defined(HAVE_OPENSSL) && !defined(HAVE_LIBGNUTLS) && !defined(HAVE_MBEDTLS) - -#include "net.h" - -#ifdef __GNUC__ -#define UNUSED __attribute__((unused)) -#else /* __GNUC__ */ -#define UNUSED -#endif /* __GNUC__ */ - -int -coap_dtls_is_supported(void) { - return 0; -} - -int -coap_tls_is_supported(void) { - return 0; -} - -coap_tls_version_t * -coap_get_tls_library_version(void) { - static coap_tls_version_t version; - version.version = 0; - version.type = COAP_TLS_LIBRARY_NOTLS; - return &version; -} - -int -coap_dtls_context_set_pki(coap_context_t *ctx UNUSED, - coap_dtls_pki_t* setup_data UNUSED, - coap_dtls_role_t role UNUSED -) { - return 0; -} - -int -coap_dtls_context_set_pki_root_cas(struct coap_context_t *ctx UNUSED, - const char *ca_file UNUSED, - const char *ca_path UNUSED -) { - return 0; -} - -int -coap_dtls_context_set_psk(coap_context_t *ctx UNUSED, - const char *hint UNUSED, - coap_dtls_role_t role UNUSED -) { - return 0; -} - -int -coap_dtls_context_check_keys_enabled(coap_context_t *ctx UNUSED) -{ - return 0; -} - -static int dtls_log_level = 0; - -void coap_dtls_startup(void) { -} - -void -coap_dtls_set_log_level(int level) { - dtls_log_level = level; -} - -int -coap_dtls_get_log_level(void) { - return dtls_log_level; -} - -void * -coap_dtls_new_context(struct coap_context_t *coap_context UNUSED) { - return NULL; -} - -void -coap_dtls_free_context(void *handle UNUSED) { -} - -void *coap_dtls_new_server_session(coap_session_t *session UNUSED) { - return NULL; -} - -void *coap_dtls_new_client_session(coap_session_t *session UNUSED) { - return NULL; -} - -void coap_dtls_free_session(coap_session_t *coap_session UNUSED) { -} - -void coap_dtls_session_update_mtu(coap_session_t *session UNUSED) { -} - -int -coap_dtls_send(coap_session_t *session UNUSED, - const uint8_t *data UNUSED, - size_t data_len UNUSED -) { - return -1; -} - -int coap_dtls_is_context_timeout(void) { - return 1; -} - -coap_tick_t coap_dtls_get_context_timeout(void *dtls_context UNUSED) { - return 0; -} - -coap_tick_t -coap_dtls_get_timeout(coap_session_t *session UNUSED, coap_tick_t now UNUSED) { - return 0; -} - -void coap_dtls_handle_timeout(coap_session_t *session UNUSED) { -} - -int -coap_dtls_receive(coap_session_t *session UNUSED, - const uint8_t *data UNUSED, - size_t data_len UNUSED -) { - return -1; -} - -int -coap_dtls_hello(coap_session_t *session UNUSED, - const uint8_t *data UNUSED, - size_t data_len UNUSED -) { - return 0; -} - -unsigned int coap_dtls_get_overhead(coap_session_t *session UNUSED) { - return 0; -} - -void *coap_tls_new_client_session(coap_session_t *session UNUSED, int *connected UNUSED) { - return NULL; -} - -void *coap_tls_new_server_session(coap_session_t *session UNUSED, int *connected UNUSED) { - return NULL; -} - -void coap_tls_free_session(coap_session_t *coap_session UNUSED) { -} - -ssize_t coap_tls_write(coap_session_t *session UNUSED, - const uint8_t *data UNUSED, - size_t data_len UNUSED -) { - return -1; -} - -ssize_t coap_tls_read(coap_session_t *session UNUSED, - uint8_t *data UNUSED, - size_t data_len UNUSED -) { - return -1; -} - -#undef UNUSED - -#else /* !HAVE_LIBTINYDTLS && !HAVE_OPENSSL && !HAVE_LIBGNUTLS */ - -#ifdef __clang__ -/* Make compilers happy that do not like empty modules. As this function is - * never used, we ignore -Wunused-function at the end of compiling this file - */ -#pragma GCC diagnostic ignored "-Wunused-function" -#endif -static inline void dummy(void) { -} - -#endif /* !HAVE_LIBTINYDTLS && !HAVE_OPENSSL && !HAVE_LIBGNUTLS */ diff --git a/components/coap/port/include/coap/coap_dtls.h b/components/coap/port/include/coap/coap_dtls.h deleted file mode 100644 index 2dd0e88d2e..0000000000 --- a/components/coap/port/include/coap/coap_dtls.h +++ /dev/null @@ -1,631 +0,0 @@ -/* - * coap_dtls.h -- (Datagram) Transport Layer Support for libcoap - * - * Copyright (C) 2016 Olaf Bergmann - * Copyright (C) 2017 Jean-Claude Michelou - * - * This file is part of the CoAP library libcoap. Please see README for terms - * of use. - */ - -#ifndef COAP_DTLS_H_ -#define COAP_DTLS_H_ - -#include "coap_time.h" -#include "str.h" - -struct coap_context_t; -struct coap_session_t; -struct coap_dtls_pki_t; - -/** - * @defgroup dtls DTLS Support - * API functions for interfacing with DTLS libraries. - * @{ - */ - -/** - * Check whether DTLS is available. - * - * @return @c 1 if support for DTLS is enabled, or @c 0 otherwise. - */ -int coap_dtls_is_supported(void); - -/** - * Check whether TLS is available. - * - * @return @c 1 if support for TLS is enabled, or @c 0 otherwise. - */ -int coap_tls_is_supported(void); - -typedef enum coap_tls_library_t { - COAP_TLS_LIBRARY_NOTLS = 0, /**< No DTLS library */ - COAP_TLS_LIBRARY_TINYDTLS, /**< Using TinyDTLS library */ - COAP_TLS_LIBRARY_OPENSSL, /**< Using OpenSSL library */ - COAP_TLS_LIBRARY_GNUTLS, /**< Using GnuTLS library */ - COAP_TLS_LIBRARY_MBEDTLS, /**< Using MbedTLS library */ -} coap_tls_library_t; - -/** - * The structure used for returning the underlying (D)TLS library - * information. - */ -typedef struct coap_tls_version_t { - uint64_t version; /**< (D)TLS runtime Library Version */ - coap_tls_library_t type; /**< Library type. One of COAP_TLS_LIBRARY_* */ - uint64_t built_version; /**< (D)TLS Built against Library Version */ -} coap_tls_version_t; - -/** - * Determine the type and version of the underlying (D)TLS library. - * - * @return The version and type of library libcoap was compiled against. - */ -coap_tls_version_t *coap_get_tls_library_version(void); - -/** - * Additional Security setup handler that can be set up by - * coap_context_set_pki(). - * Invoked when libcoap has done the validation checks at the TLS level, - * but the application needs to do some additional checks/changes/updates. - * - * @param tls_session The security session definition - e.g. SSL * for OpenSSL. - * NULL if server call-back. - * This will be dependent on the underlying TLS library - - * see coap_get_tls_library_version() - * @param setup_data A structure containing setup data originally passed into - * coap_context_set_pki() or coap_new_client_session_pki(). - * - * @return @c 1 if successful, else @c 0. - */ -typedef int (*coap_dtls_security_setup_t)(void* tls_session, - struct coap_dtls_pki_t *setup_data); - -/** - * CN Validation call-back that can be set up by coap_context_set_pki(). - * Invoked when libcoap has done the validation checks at the TLS level, - * but the application needs to check that the CN is allowed. - * CN is the SubjectAltName in the cert, if not present, then the leftmost - * Common Name (CN) component of the subject name. - * - * @param cn The determined CN from the certificate - * @param asn1_public_cert The ASN.1 DER encoded X.509 certificate - * @param asn1_length The ASN.1 length - * @param coap_session The CoAP session associated with the certificate update - * @param depth Depth in cert chain. If 0, then client cert, else a CA - * @param validated TLS layer can find no issues if 1 - * @param arg The same as was passed into coap_context_set_pki() - * in setup_data->cn_call_back_arg - * - * @return @c 1 if accepted, else @c 0 if to be rejected. - */ -typedef int (*coap_dtls_cn_callback_t)(const char *cn, - const uint8_t *asn1_public_cert, - size_t asn1_length, - struct coap_session_t *coap_session, - unsigned depth, - int validated, - void *arg); - -/** - * The enum used for determining the provided PKI ASN.1 (DER) Private Key - * formats. - */ -typedef enum coap_asn1_privatekey_type_t { - COAP_ASN1_PKEY_NONE, /**< NONE */ - COAP_ASN1_PKEY_RSA, /**< RSA type */ - COAP_ASN1_PKEY_RSA2, /**< RSA2 type */ - COAP_ASN1_PKEY_DSA, /**< DSA type */ - COAP_ASN1_PKEY_DSA1, /**< DSA1 type */ - COAP_ASN1_PKEY_DSA2, /**< DSA2 type */ - COAP_ASN1_PKEY_DSA3, /**< DSA3 type */ - COAP_ASN1_PKEY_DSA4, /**< DSA4 type */ - COAP_ASN1_PKEY_DH, /**< DH type */ - COAP_ASN1_PKEY_DHX, /**< DHX type */ - COAP_ASN1_PKEY_EC, /**< EC type */ - COAP_ASN1_PKEY_HMAC, /**< HMAC type */ - COAP_ASN1_PKEY_CMAC, /**< CMAC type */ - COAP_ASN1_PKEY_TLS1_PRF, /**< TLS1_PRF type */ - COAP_ASN1_PKEY_HKDF /**< HKDF type */ -} coap_asn1_privatekey_type_t; - -/** - * The enum used for determining the PKI key formats. - */ -typedef enum coap_pki_key_t { - COAP_PKI_KEY_PEM = 0, /**< The PKI key type is PEM file */ - COAP_PKI_KEY_ASN1, /**< The PKI key type is ASN.1 (DER) */ - COAP_PKI_KEY_PEM_BUF, /**< The PKI key type is PEM buffer */ -} coap_pki_key_t; - -/** - * The structure that holds the PKI PEM definitions. - */ -typedef struct coap_pki_key_pem_t { - const char *ca_file; /**< File location of Common CA in PEM format */ - const char *public_cert; /**< File location of Public Cert in PEM format */ - const char *private_key; /**< File location of Private Key in PEM format */ -} coap_pki_key_pem_t; - -/** - * The structure that holds the PKI PEM buffer definitions. - */ -typedef struct coap_pki_key_pem_buf_t { - const uint8_t *ca_cert; /**< PEM buffer Common CA Cert */ - const uint8_t *public_cert; /**< PEM buffer Public Cert */ - const uint8_t *private_key; /**< PEM buffer Private Key */ - size_t ca_cert_len; /**< PEM buffer CA Cert length */ - size_t public_cert_len; /**< PEM buffer Public Cert length */ - size_t private_key_len; /**< PEM buffer Private Key length */ -} coap_pki_key_pem_buf_t; - -/** - * The structure that holds the PKI ASN.1 (DER) definitions. - */ -typedef struct coap_pki_key_asn1_t { - const uint8_t *ca_cert; /**< ASN1 (DER) Common CA Cert */ - const uint8_t *public_cert; /**< ASN1 (DER) Public Cert */ - const uint8_t *private_key; /**< ASN1 (DER) Private Key */ - size_t ca_cert_len; /**< ASN1 CA Cert length */ - size_t public_cert_len; /**< ASN1 Public Cert length */ - size_t private_key_len; /**< ASN1 Private Key length */ - coap_asn1_privatekey_type_t private_key_type; /**< Private Key Type */ -} coap_pki_key_asn1_t; - -/** - * The structure that holds the PKI key information. - */ -typedef struct coap_dtls_key_t { - coap_pki_key_t key_type; /**< key format type */ - union { - coap_pki_key_pem_t pem; /**< for PEM file keys */ - coap_pki_key_pem_buf_t pem_buf; /**< for PEM memory keys */ - coap_pki_key_asn1_t asn1; /**< for ASN.1 (DER) file keys */ - } key; -} coap_dtls_key_t; - -/** - * Server Name Indication (SNI) Validation call-back that can be set up by - * coap_context_set_pki(). - * Invoked if the SNI is not previously seen and prior to sending a certificate - * set back to the client so that the appropriate certificate set can be used - * based on the requesting SNI. - * - * @param sni The requested SNI - * @param arg The same as was passed into coap_context_set_pki() - * in setup_data->sni_call_back_arg - * - * @return New set of certificates to use, or @c NULL if SNI is to be rejected. - */ -typedef coap_dtls_key_t *(*coap_dtls_sni_callback_t)(const char *sni, - void* arg); - - -#define COAP_DTLS_PKI_SETUP_VERSION 1 /**< Latest PKI setup version */ - -/** - * The structure used for defining the PKI setup data to be used. - */ -typedef struct coap_dtls_pki_t { - uint8_t version; /** Set to 1 to support this version of the struct */ - - /* Options to enable different TLS functionality in libcoap */ - uint8_t verify_peer_cert; /**< 1 if peer cert is to be verified */ - uint8_t require_peer_cert; /**< 1 if peer cert is required */ - uint8_t allow_self_signed; /**< 1 if self signed certs are allowed */ - uint8_t allow_expired_certs; /**< 1 if expired certs are allowed */ - uint8_t cert_chain_validation; /**< 1 if to check cert_chain_verify_depth */ - uint8_t cert_chain_verify_depth; /**< recommended depth is 3 */ - uint8_t check_cert_revocation; /**< 1 if revocation checks wanted */ - uint8_t allow_no_crl; /**< 1 ignore if CRL not there */ - uint8_t allow_expired_crl; /**< 1 if expired crl is allowed */ - uint8_t allow_bad_md_hash; /**< 1 if expired certs are allowed */ - uint8_t allow_short_rsa_length; /**< 1 if expired certs are allowed */ - uint8_t reserved[4]; /**< Reserved - must be set to 0 for - future compatibility */ - /* Size of 4 chosen to align to next - * parameter, so if newly defined option - * it can use one of the reserverd slot so - * no need to change - * COAP_DTLS_PKI_SETUP_VERSION and just - * decrement the reserved[] count. - */ - - /** CN check call-back function. - * If not NULL, is called when the TLS connection has passed the configured - * TLS options above for the application to verify if the CN is valid. - */ - coap_dtls_cn_callback_t validate_cn_call_back; - void *cn_call_back_arg; /**< Passed in to the CN call-back function */ - - /** SNI check call-back function. - * If not @p NULL, called if the SNI is not previously seen and prior to - * sending a certificate set back to the client so that the appropriate - * certificate set can be used based on the requesting SNI. - */ - coap_dtls_sni_callback_t validate_sni_call_back; - void *sni_call_back_arg; /**< Passed in to the sni call-back function */ - - /** Additional Security call-back handler that is invoked when libcoap has - * done the standerd, defined validation checks at the TLS level, - * If not @p NULL, called from within the TLS Client Hello connection - * setup. - */ - coap_dtls_security_setup_t additional_tls_setup_call_back; - - char* client_sni; /**< If not NULL, SNI to use in client TLS setup. - Owned by the client app and must remain valid - during the call to coap_new_client_session_pki() */ - - coap_dtls_key_t pki_key; /**< PKI key definition */ -} coap_dtls_pki_t; - -/** @} */ - -/** - * @defgroup dtls_internal DTLS Support (Internal) - * Internal API functions for interfacing with DTLS libraries. - * @{ - */ - -/** - * Creates a new DTLS context for the given @p coap_context. This function - * returns a pointer to a new DTLS context object or @c NULL on error. - * - * Internal function. - * - * @param coap_context The CoAP context where the DTLS object shall be used. - * - * @return A DTLS context object or @c NULL on error. - */ -void * -coap_dtls_new_context(struct coap_context_t *coap_context); - -typedef enum coap_dtls_role_t { - COAP_DTLS_ROLE_CLIENT, /**< Internal function invoked for client */ - COAP_DTLS_ROLE_SERVER /**< Internal function invoked for server */ -} coap_dtls_role_t; - -/** - * Set the DTLS context's default PSK information. - * This does the PSK specifics following coap_dtls_new_context(). - * If @p COAP_DTLS_ROLE_SERVER, then identity hint will also get set. - * If @p COAP_DTLS_ROLE_SERVER, then the information will get put into the - * TLS library's context (from which sessions are derived). - * If @p COAP_DTLS_ROLE_CLIENT, then the information will get put into the - * TLS library's session. - * - * Internal function. - * - * @param coap_context The CoAP context. - * @param identity_hint The default PSK server identity hint sent to a client. - * Required parameter. If @p NULL, will be set to "". - * Empty string is a valid hint. - * This parameter is ignored if COAP_DTLS_ROLE_CLIENT - * @param role One of @p COAP_DTLS_ROLE_CLIENT or @p COAP_DTLS_ROLE_SERVER - * - * @return @c 1 if successful, else @c 0. - */ - -int -coap_dtls_context_set_psk(struct coap_context_t *coap_context, - const char *identity_hint, - coap_dtls_role_t role); - -/** - * Set the DTLS context's default server PKI information. - * This does the PKI specifics following coap_dtls_new_context(). - * If @p COAP_DTLS_ROLE_SERVER, then the information will get put into the - * TLS library's context (from which sessions are derived). - * If @p COAP_DTLS_ROLE_CLIENT, then the information will get put into the - * TLS library's session. - * - * Internal function. - * - * @param coap_context The CoAP context. - * @param setup_data Setup information defining how PKI is to be setup. - * Required parameter. If @p NULL, PKI will not be - * set up. - * @param role One of @p COAP_DTLS_ROLE_CLIENT or @p COAP_DTLS_ROLE_SERVER - * - * @return @c 1 if successful, else @c 0. - */ - -int -coap_dtls_context_set_pki(struct coap_context_t *coap_context, - coap_dtls_pki_t *setup_data, - coap_dtls_role_t role); - -/** - * Set the dtls context's default Root CA information for a client or server. - * - * Internal function. - * - * @param coap_context The current coap_context_t object. - * @param ca_file If not @p NULL, is the full path name of a PEM encoded - * file containing all the Root CAs to be used. - * @param ca_dir If not @p NULL, points to a directory containing PEM - * encoded files containing all the Root CAs to be used. - * - * @return @c 1 if successful, else @c 0. - */ - -int -coap_dtls_context_set_pki_root_cas(struct coap_context_t *coap_context, - const char *ca_file, - const char *ca_dir); - -/** - * Check whether one of the coap_dtls_context_set_{psk|pki}() functions have - * been called. - * - * Internal function. - * - * @param coap_context The current coap_context_t object. - * - * @return @c 1 if coap_dtls_context_set_{psk|pki}() called, else @c 0. - */ - -int coap_dtls_context_check_keys_enabled(struct coap_context_t *coap_context); - -/** - * Releases the storage allocated for @p dtls_context. - * - * Internal function. - * - * @param dtls_context The DTLS context as returned by coap_dtls_new_context(). - */ -void coap_dtls_free_context(void *dtls_context); - -/** - * Create a new client-side session. This should send a HELLO to the server. - * - * Internal function. - * - * @param coap_session The CoAP session. - * - * @return Opaque handle to underlying TLS library object containing security - * parameters for the session. -*/ -void *coap_dtls_new_client_session(struct coap_session_t *coap_session); - -/** - * Create a new DTLS server-side session. - * Called after coap_dtls_hello() has returned @c 1, signalling that a validated - * HELLO was received from a client. - * This should send a HELLO to the server. - * - * Internal function. - * - * @param coap_session The CoAP session. - * - * @return Opaque handle to underlying TLS library object containing security - * parameters for the DTLS session. - */ -void *coap_dtls_new_server_session(struct coap_session_t *coap_session); - -/** - * Terminates the DTLS session (may send an ALERT if necessary) then frees the - * underlying TLS library object containing security parameters for the session. - * - * Internal function. - * - * @param coap_session The CoAP session. - */ -void coap_dtls_free_session(struct coap_session_t *coap_session); - -/** - * Notify of a change in the CoAP session's MTU, for example after - * a PMTU update. - * - * Internal function. - * - * @param coap_session The CoAP session. - */ -void coap_dtls_session_update_mtu(struct coap_session_t *coap_session); - -/** - * Send data to a DTLS peer. - * - * Internal function. - * - * @param coap_session The CoAP session. - * @param data pointer to data. - * @param data_len Number of bytes to send. - * - * @return @c 0 if this would be blocking, @c -1 if there is an error or the - * number of cleartext bytes sent. - */ -int coap_dtls_send(struct coap_session_t *coap_session, - const uint8_t *data, - size_t data_len); - -/** - * Check if timeout is handled per CoAP session or per CoAP context. - * - * Internal function. - * - * @return @c 1 of timeout and retransmit is per context, @c 0 if it is - * per session. - */ -int coap_dtls_is_context_timeout(void); - -/** - * Do all pending retransmits and get next timeout - * - * Internal function. - * - * @param dtls_context The DTLS context. - * - * @return @c 0 if no event is pending or date of the next retransmit. - */ -coap_tick_t coap_dtls_get_context_timeout(void *dtls_context); - -/** - * Get next timeout for this session. - * - * Internal function. - * - * @param coap_session The CoAP session. - * @param now The current time in ticks. - * - * @return @c 0 If no event is pending or ticks time of the next retransmit. - */ -coap_tick_t coap_dtls_get_timeout(struct coap_session_t *coap_session, - coap_tick_t now); - -/** - * Handle a DTLS timeout expiration. - * - * Internal function. - * - * @param coap_session The CoAP session. - */ -void coap_dtls_handle_timeout(struct coap_session_t *coap_session); - -/** - * Handling incoming data from a DTLS peer. - * - * Internal function. - * - * @param coap_session The CoAP session. - * @param data Encrypted datagram. - * @param data_len Encrypted datagram size. - * - * @return Result of coap_handle_dgram on the decrypted CoAP PDU - * or @c -1 for error. - */ -int coap_dtls_receive(struct coap_session_t *coap_session, - const uint8_t *data, - size_t data_len); - -/** - * Handling client HELLO messages from a new candiate peer. - * Note that session->tls is empty. - * - * Internal function. - * - * @param coap_session The CoAP session. - * @param data Encrypted datagram. - * @param data_len Encrypted datagram size. - * - * @return @c 0 if a cookie verification message has been sent, @c 1 if the - * HELLO contains a valid cookie and a server session should be created, - * @c -1 if the message is invalid. - */ -int coap_dtls_hello(struct coap_session_t *coap_session, - const uint8_t *data, - size_t data_len); - -/** - * Get DTLS overhead over cleartext PDUs. - * - * Internal function. - * - * @param coap_session The CoAP session. - * - * @return Maximum number of bytes added by DTLS layer. - */ -unsigned int coap_dtls_get_overhead(struct coap_session_t *coap_session); - -/** - * Create a new TLS client-side session. - * - * Internal function. - * - * @param coap_session The CoAP session. - * @param connected Updated with whether the connection is connected yet or not. - * @c 0 is not connected, @c 1 is connected. - * - * @return Opaque handle to underlying TLS library object containing security - * parameters for the session. -*/ -void *coap_tls_new_client_session(struct coap_session_t *coap_session, int *connected); - -/** - * Create a TLS new server-side session. - * - * Internal function. - * - * @param coap_session The CoAP session. - * @param connected Updated with whether the connection is connected yet or not. - * @c 0 is not connected, @c 1 is connected. - * - * @return Opaque handle to underlying TLS library object containing security - * parameters for the session. - */ -void *coap_tls_new_server_session(struct coap_session_t *coap_session, int *connected); - -/** - * Terminates the TLS session (may send an ALERT if necessary) then frees the - * underlying TLS library object containing security parameters for the session. - * - * Internal function. - * - * @param coap_session The CoAP session. - */ -void coap_tls_free_session( struct coap_session_t *coap_session ); - -/** - * Send data to a TLS peer, with implicit flush. - * - * Internal function. - * - * @param coap_session The CoAP session. - * @param data Pointer to data. - * @param data_len Number of bytes to send. - * - * @return @c 0 if this should be retried, @c -1 if there is an error - * or the number of cleartext bytes sent. - */ -ssize_t coap_tls_write(struct coap_session_t *coap_session, - const uint8_t *data, - size_t data_len - ); - -/** - * Read some data from a TLS peer. - * - * Internal function. - * - * @param coap_session The CoAP session. - * @param data Pointer to data. - * @param data_len Maximum number of bytes to read. - * - * @return @c 0 if this should be retried, @c -1 if there is an error - * or the number of cleartext bytes read. - */ -ssize_t coap_tls_read(struct coap_session_t *coap_session, - uint8_t *data, - size_t data_len - ); - -/** - * Initialize the underlying (D)TLS Library layer. - * - * Internal function. - * - */ -void coap_dtls_startup(void); - -/** @} */ - -/** - * @ingroup logging - * Sets the (D)TLS logging level to the specified @p level. - * Note: coap_log_level() will influence output if at a specified level. - * - * @param level The logging level to use - LOG_* - */ -void coap_dtls_set_log_level(int level); - -/** - * @ingroup logging - * Get the current (D)TLS logging. - * - * @return The current log level (one of LOG_*). - */ -int coap_dtls_get_log_level(void); - - -#endif /* COAP_DTLS_H */ diff --git a/components/coap/port/include/coap/coap.h b/components/coap/port/include/coap3/coap.h similarity index 53% rename from components/coap/port/include/coap/coap.h rename to components/coap/port/include/coap3/coap.h index f048ca8571..c69d2734b3 100644 --- a/components/coap/port/include/coap/coap.h +++ b/components/coap/port/include/coap3/coap.h @@ -21,27 +21,28 @@ extern "C" { #endif -#include "libcoap.h" +#include "coap3/libcoap.h" -#include "address.h" -#include "async.h" -#include "bits.h" -#include "block.h" -#include "coap_dtls.h" -#include "coap_event.h" -#include "coap_io.h" -#include "coap_time.h" -#include "coap_debug.h" -#include "encode.h" -#include "mem.h" -#include "net.h" -#include "option.h" -#include "pdu.h" -#include "prng.h" -#include "resource.h" -#include "str.h" -#include "subscribe.h" -#include "uri.h" +#include "coap3/coap_forward_decls.h" +#include "coap3/address.h" +#include "coap3/async.h" +#include "coap3/block.h" +#include "coap3/coap_cache.h" +#include "coap3/coap_dtls.h" +#include "coap3/coap_event.h" +#include "coap3/coap_io.h" +#include "coap3/coap_time.h" +#include "coap3/coap_debug.h" +#include "coap3/encode.h" +#include "coap3/mem.h" +#include "coap3/net.h" +#include "coap3/option.h" +#include "coap3/pdu.h" +#include "coap3/coap_prng.h" +#include "coap3/resource.h" +#include "coap3/str.h" +#include "coap3/subscribe.h" +#include "coap3/uri.h" #ifdef __cplusplus } diff --git a/components/coap/port/include/coap_config_posix.h b/components/coap/port/include/coap_config_posix.h index 3f6b7c605f..b24335ad15 100644 --- a/components/coap/port/include/coap_config_posix.h +++ b/components/coap/port/include/coap_config_posix.h @@ -30,6 +30,7 @@ #define HAVE_NETDB_H #define HAVE_NETINET_IN_H #define HAVE_STRUCT_CMSGHDR +#define COAP_DISABLE_TCP 0 #define ipi_spec_dst ipi_addr struct in6_pktinfo { @@ -53,8 +54,6 @@ struct in6_pktinfo { #define COAP_CONSTRAINED_STACK 1 #define ESPIDF_VERSION -#define _POSIX_TIMERS 1 - #define gai_strerror(x) "gai_strerror() not supported" #endif /* WITH_POSIX */ diff --git a/examples/protocols/coap_client/README.md b/examples/protocols/coap_client/README.md index f2f024585e..1db75c611f 100644 --- a/examples/protocols/coap_client/README.md +++ b/examples/protocols/coap_client/README.md @@ -43,6 +43,8 @@ Component config ---> CoAP Configuration ---> * Set encryption method definition, PSK (default) or PKI * Enable CoAP debugging if required + High resolution timer (esp_timer) ---> + * Hardware timer to use for esp_timer - change if required (FRC2 for QEMU) ### Build and Flash @@ -59,20 +61,24 @@ See the Getting Started Guide for full steps to configure and use ESP-IDF to bui ## Example Output Prerequisite: we startup a CoAP server on coap server example, -or use the default of coaps://californium.eclipseprojects.io. +or use the default of coap://californium.eclipseprojects.io. and you could receive data from CoAP server if succeed, such as the following log: ``` ... -I (5104) esp_netif_handlers: example_connect: sta ip: 192.168.0.103, mask: 255.255.255.0, gw: 192.168.0.1 -I (5104) example_connect: Got IPv4 event: Interface "example_connect: sta" address: 192.168.0.103 -I (5604) example_connect: Got IPv6 event: Interface "example_connect: sta" address: fe80:0000:0000:0000:32ae:a4ff:fec5:3234, type: ESP_IP6_ADDR_IS_LINK_LOCAL -I (5604) example_connect: Connected to example_connect: sta -I (5614) example_connect: - IPv4 address: 192.168.0.103 -I (5614) example_connect: - IPv6 address: fe80:0000:0000:0000:32ae:a4ff:fec5:3234, type: ESP_IP6_ADDR_IS_LINK_LOCAL -I (6004) CoAP_client: DNS lookup succeeded. IP=35.185.40.182 +I (332) wifi: mode : sta (30:ae:a4:04:1b:7c) +I (1672) wifi: n:11 0, o:1 0, ap:255 255, sta:11 0, prof:1 +I (1672) wifi: state: init -> auth (b0) +I (1682) wifi: state: auth -> assoc (0) +I (1692) wifi: state: assoc -> run (10) +I (1692) wifi: connected with huawei_cw, channel 11 +I (1692) wifi: pm start, type: 1 + +I (2582) event: sta ip: 192.168.3.89, mask: 255.255.255.0, gw: 192.168.3.1 +I (2582) CoAP_client: Connected to AP +I (2582) CoAP_client: DNS lookup succeeded. IP=35.185.40.182 Received: **************************************************************** CoAP RFC 7252 Cf 3.0.0-SNAPSHOT @@ -86,7 +92,11 @@ published under EPL+EDL: http://www.eclipse.org/californium/ ``` ## libcoap Documentation -This can be found at https://libcoap.net/doc/reference/4.2.0/ +This can be found at [libcoap Documentation](https://libcoap.net/documentation.html). +The current API is 4.3.0. + +## libcoap Specific Issues +These can be raised at [libcoap Issues](https://github.com/obgm/libcoap/issues). ## Troubleshooting * Please make sure Target Url includes valid `host`, optional `port`, diff --git a/examples/protocols/coap_client/main/certs/coap_ca.pem b/examples/protocols/coap_client/main/certs/coap_ca.pem index 1bdf23d94b..07900ec471 100644 --- a/examples/protocols/coap_client/main/certs/coap_ca.pem +++ b/examples/protocols/coap_client/main/certs/coap_ca.pem @@ -1,23 +1,27 @@ -----BEGIN CERTIFICATE----- -MIID3DCCA0WgAwIBAgIJAMnlgL1czsmjMA0GCSqGSIb3DQEBCwUAMIGTMQswCQYD -VQQGEwJGUjEPMA0GA1UECAwGUmFkaXVzMRIwEAYDVQQHDAlTb21ld2hlcmUxFTAT -BgNVBAoMDEV4YW1wbGUgSW5jLjEgMB4GCSqGSIb3DQEJARYRYWRtaW5AZXhhbXBs -ZS5jb20xJjAkBgNVBAMMHUV4YW1wbGUgQ2VydGlmaWNhdGUgQXV0aG9yaXR5MB4X -DTE3MDYwNzA4MDY0OVoXDTI3MDYwNTA4MDY0OVowgZMxCzAJBgNVBAYTAkZSMQ8w -DQYDVQQIDAZSYWRpdXMxEjAQBgNVBAcMCVNvbWV3aGVyZTEVMBMGA1UECgwMRXhh -bXBsZSBJbmMuMSAwHgYJKoZIhvcNAQkBFhFhZG1pbkBleGFtcGxlLmNvbTEmMCQG -A1UEAwwdRXhhbXBsZSBDZXJ0aWZpY2F0ZSBBdXRob3JpdHkwgZ8wDQYJKoZIhvcN -AQEBBQADgY0AMIGJAoGBALpWR23fn/TmHxsXsHdrydzPSd17fZkc71WsaicgQR66 -1tIVYb22UWGfj9KPM8THMsV74ew4ZkaQ39qvU0iuQIRrKARFHFok+vbaecgWMeWe -vGIqdnmyB9gJYaFOKgtSkfXsu2ddsqdvLYwcDbczrq8X9yEXpN6mnxXeCcPG4F0p -AgMBAAGjggE0MIIBMDAdBgNVHQ4EFgQUgigpdAUpONoDq0pQ3yfxrslCSpcwgcgG -A1UdIwSBwDCBvYAUgigpdAUpONoDq0pQ3yfxrslCSpehgZmkgZYwgZMxCzAJBgNV -BAYTAkZSMQ8wDQYDVQQIDAZSYWRpdXMxEjAQBgNVBAcMCVNvbWV3aGVyZTEVMBMG -A1UECgwMRXhhbXBsZSBJbmMuMSAwHgYJKoZIhvcNAQkBFhFhZG1pbkBleGFtcGxl -LmNvbTEmMCQGA1UEAwwdRXhhbXBsZSBDZXJ0aWZpY2F0ZSBBdXRob3JpdHmCCQDJ -5YC9XM7JozAMBgNVHRMEBTADAQH/MDYGA1UdHwQvMC0wK6ApoCeGJWh0dHA6Ly93 -d3cuZXhhbXBsZS5jb20vZXhhbXBsZV9jYS5jcmwwDQYJKoZIhvcNAQELBQADgYEA -euxOBPInSJRKAIseMxPmAabtAqKNslZSmpG4He3lkKt+HM3jfznUt3psmD7j1hFW -S4l7KXzzajvaGYybDq5N9MqrDjhGn3VXZqOLMUNDL7OQq96TzgqsTBT1dmVSbNlt -PQgiAeKAk3tmH4lRRi9MTBSyJ6I92JYcS5H6Bs4ZwCc= +MIICDzCCAbSgAwIBAgIIAbOUoVFDz/QwDAYIKoZIzj0EAwIFADBcMRAwDgYDVQQD +EwdjZi1yb290MRQwEgYDVQQLEwtDYWxpZm9ybml1bTEUMBIGA1UEChMLRWNsaXBz +ZSBJb1QxDzANBgNVBAcTBk90dGF3YTELMAkGA1UEBhMCQ0EwHhcNMjAxMTExMTAz +MDMzWhcNMjExMTExMTAzMDMzWjBaMQ4wDAYDVQQDEwVjZi1jYTEUMBIGA1UECxML +Q2FsaWZvcm5pdW0xFDASBgNVBAoTC0VjbGlwc2UgSW9UMQ8wDQYDVQQHEwZPdHRh +d2ExCzAJBgNVBAYTAkNBMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAE7/3EXOZn +GZXNEIj7LuQAMZ8lfRYSCnpME1TBjKjZPtVeztLtGWgkkLvIX11pAJcBh51cpi7Z +fQtGpVE9CLOh6aNgMF4wHQYDVR0OBBYEFEvf57UcJhYYkx14twkeitd691fVMAsG +A1UdDwQEAwIBBjAPBgNVHRMECDAGAQH/AgEBMB8GA1UdIwQYMBaAFAsi3KbVERiK +JzFCfC/GVrYksGzEMAwGCCqGSM49BAMCBQADRwAwRAIgc5nVF/5Pip0XB17IZXqi +V84FXanWdn9Z0SiPdpOgvZMCIH13vL9tkCCjPN3tg3TYRY/bzyGohFGBcTrrEtUr +rVIm +-----END CERTIFICATE----- +-----BEGIN CERTIFICATE----- +MIIB4DCCAYWgAwIBAgIIQR8ro8AQ02AwDAYIKoZIzj0EAwIFADBcMRAwDgYDVQQD +EwdjZi1yb290MRQwEgYDVQQLEwtDYWxpZm9ybml1bTEUMBIGA1UEChMLRWNsaXBz +ZSBJb1QxDzANBgNVBAcTBk90dGF3YTELMAkGA1UEBhMCQ0EwHhcNMjAxMTExMTAz +MDMyWhcNMjExMTExMTAzMDMyWjBcMRAwDgYDVQQDEwdjZi1yb290MRQwEgYDVQQL +EwtDYWxpZm9ybml1bTEUMBIGA1UEChMLRWNsaXBzZSBJb1QxDzANBgNVBAcTBk90 +dGF3YTELMAkGA1UEBhMCQ0EwWTATBgcqhkjOPQIBBggqhkjOPQMBBwNCAATZ1BRM +T1//Fzh9sneRZNwS4kgCxN1PvgwT271qCpYqyxnjLEa38AP1IAanhpiD/OkVc0Zd +7NgDPCw7n94EULMyoy8wLTAdBgNVHQ4EFgQUCyLcptURGIonMUJ8L8ZWtiSwbMQw +DAYDVR0TBAUwAwEB/zAMBggqhkjOPQQDAgUAA0cAMEQCIAdLEgcUWdpAl9jwdJiz +/cHW7/CBIWEvqiQfzE+XLyLOAiAvuxSdOtSDjh2aC5qEjUCH8CSKCxWB74j23tmp +aqPH4A== -----END CERTIFICATE----- diff --git a/examples/protocols/coap_client/main/certs/coap_client.crt b/examples/protocols/coap_client/main/certs/coap_client.crt index 12dbfc8f55..e774231cb3 100644 --- a/examples/protocols/coap_client/main/certs/coap_client.crt +++ b/examples/protocols/coap_client/main/certs/coap_client.crt @@ -1,70 +1,13 @@ -Certificate: - Data: - Version: 3 (0x2) - Serial Number: 48 (0x30) - Signature Algorithm: sha1WithRSAEncryption - Issuer: C=FR, ST=Radius, L=Somewhere, O=Example Inc./emailAddress=admin@example.com, CN=Example Certificate Authority - Validity - Not Before: Jun 7 08:06:49 2017 GMT - Not After : Jun 5 08:06:49 2027 GMT - Subject: C=FR, ST=Radius, O=Example Inc., CN=user@example.com/emailAddress=user@example.com - Subject Public Key Info: - Public Key Algorithm: rsaEncryption - Public-Key: (2048 bit) - Modulus: - 00:d2:f6:be:72:a5:ab:2e:56:0c:dd:f2:3b:2c:7c: - e0:5d:05:40:af:0c:8c:f3:82:0c:d0:18:34:b4:e3: - 7d:5f:8d:0a:3e:aa:79:02:f9:96:ad:10:00:ec:51: - e9:dc:3f:fb:ea:b0:57:eb:48:c7:ca:ef:e8:05:ab: - ee:3f:66:ba:5c:9e:7f:40:85:9f:25:a0:e0:e3:7c: - cf:b6:e6:31:f5:fd:24:03:c8:f4:fb:d8:a4:f3:92: - 29:05:aa:55:43:80:f7:3e:13:10:43:3a:89:24:be: - d8:01:86:d1:69:73:44:7d:f8:b9:46:2b:6b:51:d0: - 11:31:4b:06:ae:9f:45:fa:12:17:0c:ef:6a:fa:d0: - f7:36:46:eb:2e:db:4e:20:46:01:33:ac:b1:f7:4a: - e6:18:3d:53:22:dc:e8:4a:12:78:11:2f:e4:3b:92: - bd:d7:07:5a:c9:81:5d:48:58:c8:0f:9b:e9:a4:0f: - bb:89:b1:ad:38:07:6f:93:d0:a6:12:56:f9:07:48: - d2:23:2f:a3:a9:93:b0:11:0a:27:4c:48:0a:8d:70: - 41:68:76:7a:dd:bc:54:c3:42:33:b0:7b:f6:ae:1f: - e7:95:5e:11:ca:f2:b4:4b:5c:ba:47:64:f0:f3:d7: - 87:95:7f:93:06:a1:72:c9:81:12:a5:b7:8f:9d:7e: - d1:ef - Exponent: 65537 (0x10001) - X509v3 extensions: - X509v3 Extended Key Usage: - TLS Web Client Authentication - X509v3 CRL Distribution Points: - - Full Name: - URI:http://www.example.com/example_ca.crl - - Signature Algorithm: sha1WithRSAEncryption - 2d:02:bc:7b:88:b8:5c:e1:07:b8:bb:ba:b2:f3:98:14:8f:cb: - b0:21:13:b5:e5:6f:05:4f:92:fa:ac:c0:53:a7:b0:cd:7e:ba: - 87:36:85:25:d7:41:c5:29:84:22:74:af:bf:3e:34:36:d5:24: - 7a:81:e2:1b:54:52:85:6f:76:de:dc:63:98:45:fc:2c:31:fa: - 22:a4:72:3a:8d:d4:6a:2e:de:33:10:41:eb:94:1d:e3:59:cd: - b2:be:ab:f0:b6:20:86:9c:b8:46:ee:c5:64:ba:b6:6c:cc:53: - 44:7a:80:12:77:7c:e7:51:67:91:32:2f:88:9d:93:a8:ef:d6: - cd:de -----BEGIN CERTIFICATE----- -MIIDTjCCAregAwIBAgIBMDANBgkqhkiG9w0BAQUFADCBkzELMAkGA1UEBhMCRlIx -DzANBgNVBAgMBlJhZGl1czESMBAGA1UEBwwJU29tZXdoZXJlMRUwEwYDVQQKDAxF -eGFtcGxlIEluYy4xIDAeBgkqhkiG9w0BCQEWEWFkbWluQGV4YW1wbGUuY29tMSYw -JAYDVQQDDB1FeGFtcGxlIENlcnRpZmljYXRlIEF1dGhvcml0eTAeFw0xNzA2MDcw -ODA2NDlaFw0yNzA2MDUwODA2NDlaMHExCzAJBgNVBAYTAkZSMQ8wDQYDVQQIDAZS -YWRpdXMxFTATBgNVBAoMDEV4YW1wbGUgSW5jLjEZMBcGA1UEAwwQdXNlckBleGFt -cGxlLmNvbTEfMB0GCSqGSIb3DQEJARYQdXNlckBleGFtcGxlLmNvbTCCASIwDQYJ -KoZIhvcNAQEBBQADggEPADCCAQoCggEBANL2vnKlqy5WDN3yOyx84F0FQK8MjPOC -DNAYNLTjfV+NCj6qeQL5lq0QAOxR6dw/++qwV+tIx8rv6AWr7j9mulyef0CFnyWg -4ON8z7bmMfX9JAPI9PvYpPOSKQWqVUOA9z4TEEM6iSS+2AGG0WlzRH34uUYra1HQ -ETFLBq6fRfoSFwzvavrQ9zZG6y7bTiBGATOssfdK5hg9UyLc6EoSeBEv5DuSvdcH -WsmBXUhYyA+b6aQPu4mxrTgHb5PQphJW+QdI0iMvo6mTsBEKJ0xICo1wQWh2et28 -VMNCM7B79q4f55VeEcrytEtcukdk8PPXh5V/kwahcsmBEqW3j51+0e8CAwEAAaNP -ME0wEwYDVR0lBAwwCgYIKwYBBQUHAwIwNgYDVR0fBC8wLTAroCmgJ4YlaHR0cDov -L3d3dy5leGFtcGxlLmNvbS9leGFtcGxlX2NhLmNybDANBgkqhkiG9w0BAQUFAAOB -gQAtArx7iLhc4Qe4u7qy85gUj8uwIRO15W8FT5L6rMBTp7DNfrqHNoUl10HFKYQi -dK+/PjQ21SR6geIbVFKFb3be3GOYRfwsMfoipHI6jdRqLt4zEEHrlB3jWc2yvqvw -tiCGnLhG7sVkurZszFNEeoASd3znUWeRMi+InZOo79bN3g== +MIICAzCCAaagAwIBAgIJAJnE6sMNQNAoMAwGCCqGSM49BAMCBQAwWjEOMAwGA1UE +AxMFY2YtY2ExFDASBgNVBAsTC0NhbGlmb3JuaXVtMRQwEgYDVQQKEwtFY2xpcHNl +IElvVDEPMA0GA1UEBxMGT3R0YXdhMQswCQYDVQQGEwJDQTAeFw0yMDExMTExMDMw +NDVaFw0yMTExMTExMDMwNDVaMF4xEjAQBgNVBAMTCWNmLWNsaWVudDEUMBIGA1UE +CxMLQ2FsaWZvcm5pdW0xFDASBgNVBAoTC0VjbGlwc2UgSW9UMQ8wDQYDVQQHEwZP +dHRhd2ExCzAJBgNVBAYTAkNBMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEFGno +107kFgJ4AvABQviE9hTJlEeB4wfS3L58Q5J8srWxSunEgniIbfr0p8Shw+C1XAcz +FxJrn8SjFCVqOKjrrqNPME0wHQYDVR0OBBYEFIwAAdmpYSm184Jx1ycc3BQGybhN +MAsGA1UdDwQEAwIHgDAfBgNVHSMEGDAWgBRL3+e1HCYWGJMdeLcJHorXevdX1TAM +BggqhkjOPQQDAgUAA0kAMEYCIQC+w/hm8TfTCqUV6midHAvmNxJN7MfMcpAiyi4e +6NBrPAIhAPeMUrnOlykTMcpYMRZs4YnyM6ihgU/F8UjknhDpkywm -----END CERTIFICATE----- diff --git a/examples/protocols/coap_client/main/certs/coap_client.key b/examples/protocols/coap_client/main/certs/coap_client.key index 99936e25b7..dca2e92167 100644 --- a/examples/protocols/coap_client/main/certs/coap_client.key +++ b/examples/protocols/coap_client/main/certs/coap_client.key @@ -1,27 +1,4 @@ ------BEGIN RSA PRIVATE KEY----- -MIIEpAIBAAKCAQEA0va+cqWrLlYM3fI7LHzgXQVArwyM84IM0Bg0tON9X40KPqp5 -AvmWrRAA7FHp3D/76rBX60jHyu/oBavuP2a6XJ5/QIWfJaDg43zPtuYx9f0kA8j0 -+9ik85IpBapVQ4D3PhMQQzqJJL7YAYbRaXNEffi5RitrUdARMUsGrp9F+hIXDO9q -+tD3NkbrLttOIEYBM6yx90rmGD1TItzoShJ4ES/kO5K91wdayYFdSFjID5vppA+7 -ibGtOAdvk9CmElb5B0jSIy+jqZOwEQonTEgKjXBBaHZ63bxUw0IzsHv2rh/nlV4R -yvK0S1y6R2Tw89eHlX+TBqFyyYESpbePnX7R7wIDAQABAoIBAQC5PncO3tBIeMEF -pu007FZq9/DLhP7D2B9+HrMxX0y4uXUUf8aQyS74ukPFP0xV3U1M0BnzfU4KscyQ -Jl+nBoKAT6C3vF15wiGXQAJ4vPuD4Ate03fjKWH2ixJAakhCZR01QbIXBnBkdrvf -401BBjlPUDcIGZo8FbLzEMlGTo84vE9v3Qmkbi+PzPCh2YC+NDmsOcIW1zpmwyYC -ZYCpoWgl4++kqXXn0NGhuaOgB0JLsJOBpx/hOOjBU/wXCKaXZ1vchYqfbvvx2gf2 -WX4P0CiTH1z7MEAHanaZkcnNyxV/oF1EIMY5p0vDDzgrKtppvPOqspjydje03+CE -t0wKGPi5AoGBAPAG2Y4efgwLcoWdPjKZtsHLhDhLJnvxkqnNkzdPnLZojNi8pKkV -/Yu++pPemJZZa4YAp+OnqyEfhcha+HYqKMwRC8t3YrEVOlRQTfW/OoSrp059JIRV -jTvq/u7DdYGJRRgMLUJiEI+7xj1WbTc2EceJAgn0qfKvbvBtVJP0LH1TAoGBAOEA -xZB7SwyX+zDGRTugqMYg+sYobbQHJ7utLyoX+ckeG+sPEjEYLpQQfshET/gwF8ZK -4aILkACx/tna799xCjQdmyyc338NO9WULlY1xF+65WfeaxrtTAsqVikX3p19McRI -ijX8k7Msy3gYWJXev3MCtPT2+g68IgbL/W2wY+l1AoGAT7xGy0Jv5vpqid5pig+s -OYatHrJAT445hXUIQaiNy77Bg0JvhMgMWT8RKMwabl+4K2TOYP8TB0bcf2lQ/pgU -w22qOGYpf+AoZ1fh/hAPlYEcbCOAXQG6kDwJgjGmOGjsbgelhVbkX4smWLv8PgoV -L+7goYQIbNlAhlgbb6b+nIcCgYBB7Zr2Cdpkt0en9ACnRx0M6O7yDziNzqbqzAUM -3XeYYZUmnATlk8NaKTcs8S9JdrYQqTJR6/dm7MDTDt7IZvPpb19fhBvMu5DztPaa -1ihTMI01kStq+WsVvnL+mXrmRJ/HdsXgqcCReKep6eBTEbChP4LMYG3G0YNa4HzC -njO4XQKBgQDRnbqqg2CNTnS94BN2D3uzzELtwsIG6aVCtl09ZsLnGaBKVVDtP6BI -j2hGD7xw4g5JeSPIJU5J03nALTY3hz1JyI7AJCX7+JRtUTX2A8C4mlbeul7ilGaU -A7MFT8GqhjYYa84GzNcA1mK8ynlixpL8+yzTT/8lWInWRBa69SkktA== ------END RSA PRIVATE KEY----- +-----BEGIN PRIVATE KEY----- +MEECAQAwEwYHKoZIzj0CAQYIKoZIzj0DAQcEJzAlAgEBBCBgNuyqKuRW0RxU1DVs +aEpBPtVRVLRZYq6hZRzvZ6igBw== +-----END PRIVATE KEY----- diff --git a/examples/protocols/coap_client/main/coap_client_example_main.c b/examples/protocols/coap_client/main/coap_client_example_main.c index f44112e916..1a59e37b27 100644 --- a/examples/protocols/coap_client/main/coap_client_example_main.c +++ b/examples/protocols/coap_client/main/coap_client_example_main.c @@ -31,17 +31,12 @@ #include "protocol_examples_common.h" -#if 1 -/* Needed until coap_dtls.h becomes a part of libcoap proper */ -#include "libcoap.h" -#include "coap_dtls.h" -#endif -#include "coap.h" +#include "coap3/coap.h" -#define COAP_DEFAULT_TIME_SEC 5 +#define COAP_DEFAULT_TIME_SEC 60 /* The examples use simple Pre-Shared-Key configuration that you can set via - 'make menuconfig'. + 'idf.py menuconfig'. If you'd rather not, just change the below entries to strings with the config you want - ie #define EXAMPLE_COAP_PSK_KEY "some-agreed-preshared-key" @@ -54,7 +49,7 @@ #define EXAMPLE_COAP_PSK_IDENTITY CONFIG_EXAMPLE_COAP_PSK_IDENTITY /* The examples use uri Logging Level that - you can set via 'make menuconfig'. + you can set via 'idf.py menuconfig'. If you'd rather not, just change the below entry to a value that is between 0 and 7 with @@ -62,11 +57,11 @@ */ #define EXAMPLE_COAP_LOG_DEFAULT_LEVEL CONFIG_COAP_LOG_DEFAULT_LEVEL -/* The examples use uri "coap://californium.eclipse.org" that +/* The examples use uri "coap://californium.eclipseprojects.io" that you can set via the project configuration (idf.py menuconfig) If you'd rather not, just change the below entries to strings with - the config you want - ie #define COAP_DEFAULT_DEMO_URI "coaps://californium.eclipse.org" + the config you want - ie #define COAP_DEFAULT_DEMO_URI "coaps://californium.eclipseprojects.io" */ #define COAP_DEFAULT_DEMO_URI CONFIG_EXAMPLE_TARGET_DOMAIN_URI @@ -81,8 +76,9 @@ static int wait_ms; Client cert, taken from coap_client.crt Client key, taken from coap_client.key - The PEM, CRT and KEY file are examples taken from the wpa2 enterprise - example. + The PEM, CRT and KEY file are examples taken from + https://github.com/eclipse/californium/tree/master/demo-certs/src/main/resources + as the Certificate test (by default) is against the californium server. To embed it in the app binary, the PEM, CRT and KEY file is named in the component.mk COMPONENT_EMBED_TXTFILES variable. @@ -95,84 +91,39 @@ extern uint8_t client_key_start[] asm("_binary_coap_client_key_start"); extern uint8_t client_key_end[] asm("_binary_coap_client_key_end"); #endif /* CONFIG_COAP_MBEDTLS_PKI */ -static void message_handler(coap_context_t *ctx, coap_session_t *session, - coap_pdu_t *sent, coap_pdu_t *received, - const coap_tid_t id) +static coap_response_t +message_handler(coap_session_t *session, + const coap_pdu_t *sent, + const coap_pdu_t *received, + const coap_mid_t mid) { - unsigned char *data = NULL; + const unsigned char *data = NULL; size_t data_len; - coap_pdu_t *pdu = NULL; - coap_opt_t *block_opt; - coap_opt_iterator_t opt_iter; - unsigned char buf[4]; - coap_optlist_t *option; - coap_tid_t tid; + size_t offset; + size_t total; + coap_pdu_code_t rcvd_code = coap_pdu_get_code(received); - if (COAP_RESPONSE_CLASS(received->code) == 2) { - /* Need to see if blocked response */ - block_opt = coap_check_option(received, COAP_OPTION_BLOCK2, &opt_iter); - if (block_opt) { - uint16_t blktype = opt_iter.type; - - if (coap_opt_block_num(block_opt) == 0) { - printf("Received:\n"); - } - if (coap_get_data(received, &data_len, &data)) { - printf("%.*s", (int)data_len, data); - } - if (COAP_OPT_BLOCK_MORE(block_opt)) { - /* more bit is set */ - - /* create pdu with request for next block */ - pdu = coap_new_pdu(session); - if (!pdu) { - ESP_LOGE(TAG, "coap_new_pdu() failed"); - goto clean_up; - } - pdu->type = COAP_MESSAGE_CON; - pdu->tid = coap_new_message_id(session); - pdu->code = COAP_REQUEST_GET; - - /* add URI components from optlist */ - for (option = optlist; option; option = option->next ) { - switch (option->number) { - case COAP_OPTION_URI_HOST : - case COAP_OPTION_URI_PORT : - case COAP_OPTION_URI_PATH : - case COAP_OPTION_URI_QUERY : - coap_add_option(pdu, option->number, option->length, - option->data); - break; - default: - ; /* skip other options */ - } - } - - /* finally add updated block option from response, clear M bit */ - /* blocknr = (blocknr & 0xfffffff7) + 0x10; */ - coap_add_option(pdu, - blktype, - coap_encode_var_safe(buf, sizeof(buf), - ((coap_opt_block_num(block_opt) + 1) << 4) | - COAP_OPT_BLOCK_SZX(block_opt)), buf); - - tid = coap_send(session, pdu); - - if (tid != COAP_INVALID_TID) { - resp_wait = 1; - wait_ms = COAP_DEFAULT_TIME_SEC * 1000; - return; - } - } - printf("\n"); - } else { - if (coap_get_data(received, &data_len, &data)) { - printf("Received: %.*s\n", (int)data_len, data); + if (COAP_RESPONSE_CLASS(rcvd_code) == 2) { + if (coap_get_data_large(received, &data_len, &data, &offset, &total)) { + if (data_len != total) { + printf("Unexpected partial data received offset %u, length %u\n", offset, data_len); } + printf("Received:\n%.*s\n", (int)data_len, data); + resp_wait = 0; + } + return COAP_RESPONSE_OK; + } + printf("%d.%02d", (rcvd_code >> 5), rcvd_code & 0x1F); + if (coap_get_data_large(received, &data_len, &data, &offset, &total)) { + printf(": "); + while(data_len--) { + printf("%c", isprint(*data) ? *data : '.'); + data++; } } -clean_up: + printf("\n"); resp_wait = 0; + return COAP_RESPONSE_OK; } #ifdef CONFIG_COAP_MBEDTLS_PKI @@ -193,210 +144,303 @@ verify_cn_callback(const char *cn, } #endif /* CONFIG_COAP_MBEDTLS_PKI */ -static void coap_example_client(void *p) +static void +coap_log_handler (coap_log_t level, const char *message) { - struct hostent *hp; - coap_address_t dst_addr; - static coap_uri_t uri; - const char *server_uri = COAP_DEFAULT_DEMO_URI; + uint32_t esp_level = ESP_LOG_INFO; + char *cp = strchr(message, '\n'); + + if (cp) + ESP_LOG_LEVEL(esp_level, TAG, "%.*s", (int)(cp-message), message); + else + ESP_LOG_LEVEL(esp_level, TAG, "%s", message); +} + +static coap_address_t * +coap_get_address(coap_uri_t *uri) +{ + static coap_address_t dst_addr; char *phostname = NULL; + struct addrinfo hints; + struct addrinfo *addrres; + int error; + char tmpbuf[INET6_ADDRSTRLEN]; - coap_set_log_level(EXAMPLE_COAP_LOG_DEFAULT_LEVEL); + phostname = (char *)calloc(1, uri->host.length + 1); + if (phostname == NULL) { + ESP_LOGE(TAG, "calloc failed"); + return NULL; + } + memcpy(phostname, uri->host.s, uri->host.length); - while (1) { -#define BUFSIZE 40 - unsigned char _buf[BUFSIZE]; - unsigned char *buf; - size_t buflen; - int res; - coap_context_t *ctx = NULL; - coap_session_t *session = NULL; - coap_pdu_t *request = NULL; + memset ((char *)&hints, 0, sizeof(hints)); + hints.ai_socktype = SOCK_DGRAM; + hints.ai_family = AF_UNSPEC; - optlist = NULL; - if (coap_split_uri((const uint8_t *)server_uri, strlen(server_uri), &uri) == -1) { - ESP_LOGE(TAG, "CoAP server uri error"); - break; - } - - if (uri.scheme == COAP_URI_SCHEME_COAPS && !coap_dtls_is_supported()) { - ESP_LOGE(TAG, "MbedTLS (D)TLS Client Mode not configured"); - break; - } - if (uri.scheme == COAP_URI_SCHEME_COAPS_TCP && !coap_tls_is_supported()) { - ESP_LOGE(TAG, "CoAP server uri coaps+tcp:// scheme is not supported"); - break; - } - - phostname = (char *)calloc(1, uri.host.length + 1); - if (phostname == NULL) { - ESP_LOGE(TAG, "calloc failed"); - break; - } - - memcpy(phostname, uri.host.s, uri.host.length); - hp = gethostbyname(phostname); + error = getaddrinfo(phostname, NULL, &hints, &addrres); + if (error != 0) { + ESP_LOGE(TAG, "DNS lookup failed for destination address %s. error: %d", phostname, error); free(phostname); + return NULL; + } + if (addrres == NULL) { + ESP_LOGE(TAG, "DNS lookup %s did not return any addresses", phostname); + free(phostname); + return NULL; + } + free(phostname); + coap_address_init(&dst_addr); + switch (addrres->ai_family) { + case AF_INET: + memcpy(&dst_addr.addr.sin, addrres->ai_addr, sizeof(dst_addr.addr.sin)); + dst_addr.addr.sin.sin_port = htons(uri->port); + inet_ntop(AF_INET, &dst_addr.addr.sin.sin_addr, tmpbuf, sizeof(tmpbuf)); + ESP_LOGI(TAG, "DNS lookup succeeded. IP=%s", tmpbuf); + break; + case AF_INET6: + memcpy(&dst_addr.addr.sin6, addrres->ai_addr, sizeof(dst_addr.addr.sin6)); + dst_addr.addr.sin6.sin6_port = htons(uri->port); + inet_ntop(AF_INET6, &dst_addr.addr.sin6.sin6_addr, tmpbuf, sizeof(tmpbuf)); + ESP_LOGI(TAG, "DNS lookup succeeded. IP=%s", tmpbuf); + break; + default: + ESP_LOGE(TAG, "DNS lookup response failed"); + return NULL; + } + freeaddrinfo(addrres); - if (hp == NULL) { - ESP_LOGE(TAG, "DNS lookup failed"); - vTaskDelay(1000 / portTICK_PERIOD_MS); - free(phostname); - continue; + return &dst_addr; +} + +static int +coap_build_optlist(coap_uri_t *uri) +{ +#define BUFSIZE 40 + unsigned char _buf[BUFSIZE]; + unsigned char *buf; + size_t buflen; + int res; + + optlist = NULL; + + if (uri->scheme == COAP_URI_SCHEME_COAPS && !coap_dtls_is_supported()) { + ESP_LOGE(TAG, "MbedTLS (D)TLS Client Mode not configured"); + return 0; + } + if (uri->scheme == COAP_URI_SCHEME_COAPS_TCP && !coap_tls_is_supported()) { + ESP_LOGE(TAG, "CoAP server uri->+tcp:// scheme is not supported"); + return 0; + } + + if (uri->path.length) { + buflen = BUFSIZE; + buf = _buf; + res = coap_split_path(uri->path.s, uri->path.length, buf, &buflen); + + while (res--) { + coap_insert_optlist(&optlist, + coap_new_optlist(COAP_OPTION_URI_PATH, + coap_opt_length(buf), + coap_opt_value(buf))); + + buf += coap_opt_size(buf); } - char tmpbuf[INET6_ADDRSTRLEN]; - coap_address_init(&dst_addr); - switch (hp->h_addrtype) { - case AF_INET: - dst_addr.addr.sin.sin_family = AF_INET; - dst_addr.addr.sin.sin_port = htons(uri.port); - memcpy(&dst_addr.addr.sin.sin_addr, hp->h_addr, sizeof(dst_addr.addr.sin.sin_addr)); - inet_ntop(AF_INET, &dst_addr.addr.sin.sin_addr, tmpbuf, sizeof(tmpbuf)); - ESP_LOGI(TAG, "DNS lookup succeeded. IP=%s", tmpbuf); - break; - case AF_INET6: - dst_addr.addr.sin6.sin6_family = AF_INET6; - dst_addr.addr.sin6.sin6_port = htons(uri.port); - memcpy(&dst_addr.addr.sin6.sin6_addr, hp->h_addr, sizeof(dst_addr.addr.sin6.sin6_addr)); - inet_ntop(AF_INET6, &dst_addr.addr.sin6.sin6_addr, tmpbuf, sizeof(tmpbuf)); - ESP_LOGI(TAG, "DNS lookup succeeded. IP=%s", tmpbuf); - break; - default: - ESP_LOGE(TAG, "DNS lookup response failed"); - goto clean_up; + } + + if (uri->query.length) { + buflen = BUFSIZE; + buf = _buf; + res = coap_split_query(uri->query.s, uri->query.length, buf, &buflen); + + while (res--) { + coap_insert_optlist(&optlist, + coap_new_optlist(COAP_OPTION_URI_QUERY, + coap_opt_length(buf), + coap_opt_value(buf))); + + buf += coap_opt_size(buf); } - - if (uri.path.length) { - buflen = BUFSIZE; - buf = _buf; - res = coap_split_path(uri.path.s, uri.path.length, buf, &buflen); - - while (res--) { - coap_insert_optlist(&optlist, - coap_new_optlist(COAP_OPTION_URI_PATH, - coap_opt_length(buf), - coap_opt_value(buf))); - - buf += coap_opt_size(buf); - } - } - - if (uri.query.length) { - buflen = BUFSIZE; - buf = _buf; - res = coap_split_query(uri.query.s, uri.query.length, buf, &buflen); - - while (res--) { - coap_insert_optlist(&optlist, - coap_new_optlist(COAP_OPTION_URI_QUERY, - coap_opt_length(buf), - coap_opt_value(buf))); - - buf += coap_opt_size(buf); - } - } - - ctx = coap_new_context(NULL); - if (!ctx) { - ESP_LOGE(TAG, "coap_new_context() failed"); - goto clean_up; - } - - /* - * Note that if the URI starts with just coap:// (not coaps://) the - * session will still be plain text. - * - * coaps+tcp:// is NOT supported by the libcoap->mbedtls interface - * so COAP_URI_SCHEME_COAPS_TCP will have failed in a test above, - * but the code is left in for completeness. - */ - if (uri.scheme == COAP_URI_SCHEME_COAPS || uri.scheme == COAP_URI_SCHEME_COAPS_TCP) { -#ifndef CONFIG_MBEDTLS_TLS_CLIENT - ESP_LOGE(TAG, "MbedTLS (D)TLS Client Mode not configured"); - goto clean_up; -#endif /* CONFIG_MBEDTLS_TLS_CLIENT */ + } + return 1; +} #ifdef CONFIG_COAP_MBEDTLS_PSK - session = coap_new_client_session_psk(ctx, NULL, &dst_addr, - uri.scheme == COAP_URI_SCHEME_COAPS ? COAP_PROTO_DTLS : COAP_PROTO_TLS, - EXAMPLE_COAP_PSK_IDENTITY, - (const uint8_t *)EXAMPLE_COAP_PSK_KEY, - sizeof(EXAMPLE_COAP_PSK_KEY) - 1); +static coap_session_t * +coap_start_psk_session(coap_context_t *ctx, coap_address_t *dst_addr, coap_uri_t *uri) +{ + static coap_dtls_cpsk_t dtls_psk; + static char client_sni[256]; + + memset(client_sni, 0, sizeof(client_sni)); + memset (&dtls_psk, 0, sizeof(dtls_psk)); + dtls_psk.version = COAP_DTLS_CPSK_SETUP_VERSION; + dtls_psk.validate_ih_call_back = NULL; + dtls_psk.ih_call_back_arg = NULL; + if (uri->host.length) + memcpy(client_sni, uri->host.s, MIN(uri->host.length, sizeof(client_sni) - 1)); + else + memcpy(client_sni, "localhost", 9); + dtls_psk.client_sni = client_sni; + dtls_psk.psk_info.identity.s = (const uint8_t *)EXAMPLE_COAP_PSK_IDENTITY; + dtls_psk.psk_info.identity.length = sizeof(EXAMPLE_COAP_PSK_IDENTITY)-1; + dtls_psk.psk_info.key.s = (const uint8_t *)EXAMPLE_COAP_PSK_KEY; + dtls_psk.psk_info.key.length = sizeof(EXAMPLE_COAP_PSK_KEY)-1; + return coap_new_client_session_psk2(ctx, NULL, dst_addr, + uri->scheme == COAP_URI_SCHEME_COAPS ? COAP_PROTO_DTLS : COAP_PROTO_TLS, + &dtls_psk); +} #endif /* CONFIG_COAP_MBEDTLS_PSK */ #ifdef CONFIG_COAP_MBEDTLS_PKI - unsigned int ca_pem_bytes = ca_pem_end - ca_pem_start; - unsigned int client_crt_bytes = client_crt_end - client_crt_start; - unsigned int client_key_bytes = client_key_end - client_key_start; - coap_dtls_pki_t dtls_pki; - static char client_sni[256]; +static coap_session_t * +coap_start_pki_session(coap_context_t *ctx, coap_address_t *dst_addr, coap_uri_t *uri) +{ + unsigned int ca_pem_bytes = ca_pem_end - ca_pem_start; + unsigned int client_crt_bytes = client_crt_end - client_crt_start; + unsigned int client_key_bytes = client_key_end - client_key_start; + static coap_dtls_pki_t dtls_pki; + static char client_sni[256]; - memset (&dtls_pki, 0, sizeof(dtls_pki)); - dtls_pki.version = COAP_DTLS_PKI_SETUP_VERSION; - if (ca_pem_bytes) { - /* - * Add in additional certificate checking. - * This list of enabled can be tuned for the specific - * requirements - see 'man coap_encryption'. - * - * Note: A list of root ca file can be setup separately using - * coap_context_set_pki_root_cas(), but the below is used to - * define what checking actually takes place. - */ - dtls_pki.verify_peer_cert = 1; - dtls_pki.require_peer_cert = 1; - dtls_pki.allow_self_signed = 1; - dtls_pki.allow_expired_certs = 1; - dtls_pki.cert_chain_validation = 1; - dtls_pki.cert_chain_verify_depth = 2; - dtls_pki.check_cert_revocation = 1; - dtls_pki.allow_no_crl = 1; - dtls_pki.allow_expired_crl = 1; - dtls_pki.allow_bad_md_hash = 1; - dtls_pki.allow_short_rsa_length = 1; - dtls_pki.validate_cn_call_back = verify_cn_callback; - dtls_pki.cn_call_back_arg = NULL; - dtls_pki.validate_sni_call_back = NULL; - dtls_pki.sni_call_back_arg = NULL; - memset(client_sni, 0, sizeof(client_sni)); - if (uri.host.length) { - memcpy(client_sni, uri.host.s, MIN(uri.host.length, sizeof(client_sni))); - } else { - memcpy(client_sni, "localhost", 9); - } - dtls_pki.client_sni = client_sni; - } - dtls_pki.pki_key.key_type = COAP_PKI_KEY_PEM_BUF; - dtls_pki.pki_key.key.pem_buf.public_cert = client_crt_start; - dtls_pki.pki_key.key.pem_buf.public_cert_len = client_crt_bytes; - dtls_pki.pki_key.key.pem_buf.private_key = client_key_start; - dtls_pki.pki_key.key.pem_buf.private_key_len = client_key_bytes; - dtls_pki.pki_key.key.pem_buf.ca_cert = ca_pem_start; - dtls_pki.pki_key.key.pem_buf.ca_cert_len = ca_pem_bytes; - - session = coap_new_client_session_pki(ctx, NULL, &dst_addr, - uri.scheme == COAP_URI_SCHEME_COAPS ? COAP_PROTO_DTLS : COAP_PROTO_TLS, - &dtls_pki); -#endif /* CONFIG_COAP_MBEDTLS_PKI */ + memset (&dtls_pki, 0, sizeof(dtls_pki)); + dtls_pki.version = COAP_DTLS_PKI_SETUP_VERSION; + if (ca_pem_bytes) { + /* + * Add in additional certificate checking. + * This list of enabled can be tuned for the specific + * requirements - see 'man coap_encryption'. + * + * Note: A list of root cas file can be setup separately using + * coap_context_set_pki_root_cas(), but the below is used to + * define what checking actually takes place. + */ + dtls_pki.verify_peer_cert = 1; + dtls_pki.check_common_ca = 1; + dtls_pki.allow_self_signed = 1; + dtls_pki.allow_expired_certs = 1; + dtls_pki.cert_chain_validation = 1; + dtls_pki.cert_chain_verify_depth = 2; + dtls_pki.check_cert_revocation = 1; + dtls_pki.allow_no_crl = 1; + dtls_pki.allow_expired_crl = 1; + dtls_pki.allow_bad_md_hash = 1; + dtls_pki.allow_short_rsa_length = 1; + dtls_pki.validate_cn_call_back = verify_cn_callback; + dtls_pki.cn_call_back_arg = NULL; + dtls_pki.validate_sni_call_back = NULL; + dtls_pki.sni_call_back_arg = NULL; + memset(client_sni, 0, sizeof(client_sni)); + if (uri->host.length) { + memcpy(client_sni, uri->host.s, MIN(uri->host.length, sizeof(client_sni))); } else { - session = coap_new_client_session(ctx, NULL, &dst_addr, - uri.scheme == COAP_URI_SCHEME_COAP_TCP ? COAP_PROTO_TCP : - COAP_PROTO_UDP); - } - if (!session) { - ESP_LOGE(TAG, "coap_new_client_session() failed"); - goto clean_up; + memcpy(client_sni, "localhost", 9); } + dtls_pki.client_sni = client_sni; + } + dtls_pki.pki_key.key_type = COAP_PKI_KEY_PEM_BUF; + dtls_pki.pki_key.key.pem_buf.public_cert = client_crt_start; + dtls_pki.pki_key.key.pem_buf.public_cert_len = client_crt_bytes; + dtls_pki.pki_key.key.pem_buf.private_key = client_key_start; + dtls_pki.pki_key.key.pem_buf.private_key_len = client_key_bytes; + dtls_pki.pki_key.key.pem_buf.ca_cert = ca_pem_start; + dtls_pki.pki_key.key.pem_buf.ca_cert_len = ca_pem_bytes; - coap_register_response_handler(ctx, message_handler); + return coap_new_client_session_pki(ctx, NULL, dst_addr, + uri->scheme == COAP_URI_SCHEME_COAPS ? COAP_PROTO_DTLS : COAP_PROTO_TLS, + &dtls_pki); +} +#endif /* CONFIG_COAP_MBEDTLS_PKI */ - request = coap_new_pdu(session); +static void coap_example_client(void *p) +{ + coap_address_t *dst_addr; + static coap_uri_t uri; + const char *server_uri = COAP_DEFAULT_DEMO_URI; + coap_context_t *ctx = NULL; + coap_session_t *session = NULL; + coap_pdu_t *request = NULL; + unsigned char token[8]; + size_t tokenlength; + + /* Set up the CoAP logging */ + coap_set_log_handler(coap_log_handler); + coap_set_log_level(EXAMPLE_COAP_LOG_DEFAULT_LEVEL); + + /* Set up the CoAP context */ + ctx = coap_new_context(NULL); + if (!ctx) { + ESP_LOGE(TAG, "coap_new_context() failed"); + goto clean_up; + } + coap_context_set_block_mode(ctx, + COAP_BLOCK_USE_LIBCOAP|COAP_BLOCK_SINGLE_BODY); + + coap_register_response_handler(ctx, message_handler); + + if (coap_split_uri((const uint8_t *)server_uri, strlen(server_uri), &uri) == -1) { + ESP_LOGE(TAG, "CoAP server uri error"); + goto clean_up; + } + if (!coap_build_optlist(&uri)) + goto clean_up; + + dst_addr = coap_get_address(&uri); + if (!dst_addr) + goto clean_up; + + /* + * Note that if the URI starts with just coap:// (not coaps://) the + * session will still be plain text. + * + * coaps+tcp:// is NOT yet supported by the libcoap->mbedtls interface + * so COAP_URI_SCHEME_COAPS_TCP will have failed in a test above, + * but the code is left in for completeness. + */ + if (uri.scheme == COAP_URI_SCHEME_COAPS || uri.scheme == COAP_URI_SCHEME_COAPS_TCP) { +#ifndef CONFIG_MBEDTLS_TLS_CLIENT + ESP_LOGE(TAG, "MbedTLS (D)TLS Client Mode not configured"); + goto clean_up; +#endif /* CONFIG_MBEDTLS_TLS_CLIENT */ + +#ifdef CONFIG_COAP_MBEDTLS_PSK + session = coap_start_psk_session(ctx, dst_addr, &uri); +#endif /* CONFIG_COAP_MBEDTLS_PSK */ + +#ifdef CONFIG_COAP_MBEDTLS_PKI + session = coap_start_pki_session(ctx, dst_addr, &uri); +#endif /* CONFIG_COAP_MBEDTLS_PKI */ + } else { + session = coap_new_client_session(ctx, NULL, dst_addr, + uri.scheme == COAP_URI_SCHEME_COAP_TCP ? COAP_PROTO_TCP : + COAP_PROTO_UDP); + } + if (!session) { + ESP_LOGE(TAG, "coap_new_client_session() failed"); + goto clean_up; + } + + while (1) { + request = coap_new_pdu(coap_is_mcast(dst_addr) ? COAP_MESSAGE_NON : COAP_MESSAGE_CON, + COAP_REQUEST_CODE_GET, session); if (!request) { ESP_LOGE(TAG, "coap_new_pdu() failed"); goto clean_up; } - request->type = COAP_MESSAGE_CON; - request->tid = coap_new_message_id(session); - request->code = COAP_REQUEST_GET; + /* Add in an unique token */ + coap_session_new_token(session, &tokenlength, token); + coap_add_token(request, tokenlength, token); + + /* + * To make this a POST, you will need to do the following + * Change COAP_REQUEST_CODE_GET to COAP_REQUEST_CODE_POST for coap_new_pdu() + * Add in here a Content-Type Option based on the format of the POST text. E.G. for JSON + * u_char buf[4]; + * coap_insert_optlist(&optlist, + * coap_new_optlist(COAP_OPTION_CONTENT_FORMAT, + * coap_encode_var_safe (buf, sizeof (buf), + * COAP_MEDIATYPE_APPLICATION_JSON)); + * Add in here the POST data of length length. E.G. + * coap_add_data_large_request(session, request length, data, NULL, NULL); + */ + coap_add_optlist_pdu(request, &optlist); resp_wait = 1; @@ -405,35 +449,37 @@ static void coap_example_client(void *p) wait_ms = COAP_DEFAULT_TIME_SEC * 1000; while (resp_wait) { - int result = coap_run_once(ctx, wait_ms > 1000 ? 1000 : wait_ms); + int result = coap_io_process(ctx, wait_ms > 1000 ? 1000 : wait_ms); if (result >= 0) { if (result >= wait_ms) { - ESP_LOGE(TAG, "select timeout"); + ESP_LOGE(TAG, "No response from server"); break; } else { wait_ms -= result; } } } -clean_up: - if (optlist) { - coap_delete_optlist(optlist); - optlist = NULL; + for(int countdown = 10; countdown >= 0; countdown--) { + ESP_LOGI(TAG, "%d... ", countdown); + vTaskDelay(1000 / portTICK_PERIOD_MS); } - if (session) { - coap_session_release(session); - } - if (ctx) { - coap_free_context(ctx); - } - coap_cleanup(); - /* - * change the following line to something like sleep(2) - * if you want the request to continually be sent - */ - break; + ESP_LOGI(TAG, "Starting again!"); } +clean_up: + if (optlist) { + coap_delete_optlist(optlist); + optlist = NULL; + } + if (session) { + coap_session_release(session); + } + if (ctx) { + coap_free_context(ctx); + } + coap_cleanup(); + + ESP_LOGI(TAG, "Finished"); vTaskDelete(NULL); } diff --git a/examples/protocols/coap_client/sdkconfig.defaults b/examples/protocols/coap_client/sdkconfig.defaults index 03171ab264..308ca1c49a 100644 --- a/examples/protocols/coap_client/sdkconfig.defaults +++ b/examples/protocols/coap_client/sdkconfig.defaults @@ -1,3 +1,4 @@ CONFIG_MBEDTLS_SSL_PROTO_DTLS=y CONFIG_MBEDTLS_PSK_MODES=y CONFIG_MBEDTLS_KEY_EXCHANGE_PSK=y +CONFIG_LWIP_NETBUF_RECVINFO=y diff --git a/examples/protocols/coap_server/README.md b/examples/protocols/coap_server/README.md index 9be65ad5a6..bb37783ff4 100644 --- a/examples/protocols/coap_server/README.md +++ b/examples/protocols/coap_server/README.md @@ -40,6 +40,9 @@ Component config ---> CoAP Configuration ---> * Set encryption method definition, PSK (default) or PKI * Enable CoAP debugging if required + High resolution timer (esp_timer) ---> + * Hardware timer to use for esp_timer - change if required (FRC2 for QEMU) + ### Build and Flash @@ -77,7 +80,11 @@ If a CoAP client queries the `/Espressif` resource, CoAP server will return `"He until a CoAP client does a PUT with different data. ## libcoap Documentation -This can be found at https://libcoap.net/doc/reference/4.2.0/ +This can be found at [libcoap Documentation](https://libcoap.net/documentation.html). +The current API is 4.3.0. + +## libcoap Specific Issues +These can be raised at [libcoap Issues](https://github.com/obgm/libcoap/issues). ## Troubleshooting * Please make sure CoAP client fetchs or puts data under path: `/Espressif` or diff --git a/examples/protocols/coap_server/main/Kconfig.projbuild b/examples/protocols/coap_server/main/Kconfig.projbuild index 19da8165a6..3c0fbfc230 100644 --- a/examples/protocols/coap_server/main/Kconfig.projbuild +++ b/examples/protocols/coap_server/main/Kconfig.projbuild @@ -8,4 +8,54 @@ menu "Example CoAP Server Configuration" The Preshared Key to use to encrypt the communicatons. The same key must be used at both ends of the CoAP connection, and the CoaP client must request an URI prefixed with coaps:// instead of coap:// for DTLS to be used. + + choice EXAMPLE_COAP_MCAST_IP_MODE + prompt "Receive Multicast IP type" + help + Example can receive multicast IPV4, IPV6, both or none. + + config EXAMPLE_COAP_MCAST_NONE + bool "None" + + config EXAMPLE_COAP_MCAST_IPV4_V6 + bool "IPV4 & IPV6" + select EXAMPLE_COAP_MCAST_IPV4 + select EXAMPLE_COAP_MCAST_IPV6 + + config EXAMPLE_COAP_MCAST_IPV4_ONLY + bool "IPV4" + select EXAMPLE_COAP_MCAST_IPV4 + + config EXAMPLE_COAP_MCAST_IPV6_ONLY + bool "IPV6" + select EXAMPLE_COAP_MCAST_IPV6 + + endchoice + + config EXAMPLE_COAP_MCAST_IPV4 + bool + config EXAMPLE_COAP_MCAST_IPV6 + bool + select EXAMPLE_CONNECT_IPV6 if IDF_TARGET_ESP32 + + config EXAMPLE_COAP_MULTICAST_IPV4_ADDR + string "CoAP Multicast IPV4 Address (receive)" + default "224.0.1.187" + depends on EXAMPLE_COAP_MCAST_IPV4 + help + IPV4 multicast address to receive multicast traffic on. + + The default CoAP IPV4 address is 224.0.1.187. + + config EXAMPLE_COAP_MULTICAST_IPV6_ADDR + string "CoAP Multicast IPV6 Address (receive)" + default "FF02::FD" + depends on EXAMPLE_COAP_MCAST_IPV6 + help + IPV6 multicast address to receive multicast traffic on. + + The default CoAP FF02::FD address is a link-local multicast address. + Consult IPV6 specifications or documentation for information about + meaning of different IPV6 multicast ranges. + endmenu diff --git a/examples/protocols/coap_server/main/certs/coap_ca.pem b/examples/protocols/coap_server/main/certs/coap_ca.pem index 1bdf23d94b..07900ec471 100644 --- a/examples/protocols/coap_server/main/certs/coap_ca.pem +++ b/examples/protocols/coap_server/main/certs/coap_ca.pem @@ -1,23 +1,27 @@ -----BEGIN CERTIFICATE----- -MIID3DCCA0WgAwIBAgIJAMnlgL1czsmjMA0GCSqGSIb3DQEBCwUAMIGTMQswCQYD -VQQGEwJGUjEPMA0GA1UECAwGUmFkaXVzMRIwEAYDVQQHDAlTb21ld2hlcmUxFTAT -BgNVBAoMDEV4YW1wbGUgSW5jLjEgMB4GCSqGSIb3DQEJARYRYWRtaW5AZXhhbXBs -ZS5jb20xJjAkBgNVBAMMHUV4YW1wbGUgQ2VydGlmaWNhdGUgQXV0aG9yaXR5MB4X -DTE3MDYwNzA4MDY0OVoXDTI3MDYwNTA4MDY0OVowgZMxCzAJBgNVBAYTAkZSMQ8w -DQYDVQQIDAZSYWRpdXMxEjAQBgNVBAcMCVNvbWV3aGVyZTEVMBMGA1UECgwMRXhh -bXBsZSBJbmMuMSAwHgYJKoZIhvcNAQkBFhFhZG1pbkBleGFtcGxlLmNvbTEmMCQG -A1UEAwwdRXhhbXBsZSBDZXJ0aWZpY2F0ZSBBdXRob3JpdHkwgZ8wDQYJKoZIhvcN -AQEBBQADgY0AMIGJAoGBALpWR23fn/TmHxsXsHdrydzPSd17fZkc71WsaicgQR66 -1tIVYb22UWGfj9KPM8THMsV74ew4ZkaQ39qvU0iuQIRrKARFHFok+vbaecgWMeWe -vGIqdnmyB9gJYaFOKgtSkfXsu2ddsqdvLYwcDbczrq8X9yEXpN6mnxXeCcPG4F0p -AgMBAAGjggE0MIIBMDAdBgNVHQ4EFgQUgigpdAUpONoDq0pQ3yfxrslCSpcwgcgG -A1UdIwSBwDCBvYAUgigpdAUpONoDq0pQ3yfxrslCSpehgZmkgZYwgZMxCzAJBgNV -BAYTAkZSMQ8wDQYDVQQIDAZSYWRpdXMxEjAQBgNVBAcMCVNvbWV3aGVyZTEVMBMG -A1UECgwMRXhhbXBsZSBJbmMuMSAwHgYJKoZIhvcNAQkBFhFhZG1pbkBleGFtcGxl -LmNvbTEmMCQGA1UEAwwdRXhhbXBsZSBDZXJ0aWZpY2F0ZSBBdXRob3JpdHmCCQDJ -5YC9XM7JozAMBgNVHRMEBTADAQH/MDYGA1UdHwQvMC0wK6ApoCeGJWh0dHA6Ly93 -d3cuZXhhbXBsZS5jb20vZXhhbXBsZV9jYS5jcmwwDQYJKoZIhvcNAQELBQADgYEA -euxOBPInSJRKAIseMxPmAabtAqKNslZSmpG4He3lkKt+HM3jfznUt3psmD7j1hFW -S4l7KXzzajvaGYybDq5N9MqrDjhGn3VXZqOLMUNDL7OQq96TzgqsTBT1dmVSbNlt -PQgiAeKAk3tmH4lRRi9MTBSyJ6I92JYcS5H6Bs4ZwCc= +MIICDzCCAbSgAwIBAgIIAbOUoVFDz/QwDAYIKoZIzj0EAwIFADBcMRAwDgYDVQQD +EwdjZi1yb290MRQwEgYDVQQLEwtDYWxpZm9ybml1bTEUMBIGA1UEChMLRWNsaXBz +ZSBJb1QxDzANBgNVBAcTBk90dGF3YTELMAkGA1UEBhMCQ0EwHhcNMjAxMTExMTAz +MDMzWhcNMjExMTExMTAzMDMzWjBaMQ4wDAYDVQQDEwVjZi1jYTEUMBIGA1UECxML +Q2FsaWZvcm5pdW0xFDASBgNVBAoTC0VjbGlwc2UgSW9UMQ8wDQYDVQQHEwZPdHRh +d2ExCzAJBgNVBAYTAkNBMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAE7/3EXOZn +GZXNEIj7LuQAMZ8lfRYSCnpME1TBjKjZPtVeztLtGWgkkLvIX11pAJcBh51cpi7Z +fQtGpVE9CLOh6aNgMF4wHQYDVR0OBBYEFEvf57UcJhYYkx14twkeitd691fVMAsG +A1UdDwQEAwIBBjAPBgNVHRMECDAGAQH/AgEBMB8GA1UdIwQYMBaAFAsi3KbVERiK +JzFCfC/GVrYksGzEMAwGCCqGSM49BAMCBQADRwAwRAIgc5nVF/5Pip0XB17IZXqi +V84FXanWdn9Z0SiPdpOgvZMCIH13vL9tkCCjPN3tg3TYRY/bzyGohFGBcTrrEtUr +rVIm +-----END CERTIFICATE----- +-----BEGIN CERTIFICATE----- +MIIB4DCCAYWgAwIBAgIIQR8ro8AQ02AwDAYIKoZIzj0EAwIFADBcMRAwDgYDVQQD +EwdjZi1yb290MRQwEgYDVQQLEwtDYWxpZm9ybml1bTEUMBIGA1UEChMLRWNsaXBz +ZSBJb1QxDzANBgNVBAcTBk90dGF3YTELMAkGA1UEBhMCQ0EwHhcNMjAxMTExMTAz +MDMyWhcNMjExMTExMTAzMDMyWjBcMRAwDgYDVQQDEwdjZi1yb290MRQwEgYDVQQL +EwtDYWxpZm9ybml1bTEUMBIGA1UEChMLRWNsaXBzZSBJb1QxDzANBgNVBAcTBk90 +dGF3YTELMAkGA1UEBhMCQ0EwWTATBgcqhkjOPQIBBggqhkjOPQMBBwNCAATZ1BRM +T1//Fzh9sneRZNwS4kgCxN1PvgwT271qCpYqyxnjLEa38AP1IAanhpiD/OkVc0Zd +7NgDPCw7n94EULMyoy8wLTAdBgNVHQ4EFgQUCyLcptURGIonMUJ8L8ZWtiSwbMQw +DAYDVR0TBAUwAwEB/zAMBggqhkjOPQQDAgUAA0cAMEQCIAdLEgcUWdpAl9jwdJiz +/cHW7/CBIWEvqiQfzE+XLyLOAiAvuxSdOtSDjh2aC5qEjUCH8CSKCxWB74j23tmp +aqPH4A== -----END CERTIFICATE----- diff --git a/examples/protocols/coap_server/main/certs/coap_server.crt b/examples/protocols/coap_server/main/certs/coap_server.crt index 0af6f1741f..6522f4e4cd 100644 --- a/examples/protocols/coap_server/main/certs/coap_server.crt +++ b/examples/protocols/coap_server/main/certs/coap_server.crt @@ -1,70 +1,13 @@ -Certificate: - Data: - Version: 3 (0x2) - Serial Number: 47 (0x2f) - Signature Algorithm: sha1WithRSAEncryption - Issuer: C=FR, ST=Radius, L=Somewhere, O=Example Inc./emailAddress=admin@example.com, CN=Example Certificate Authority - Validity - Not Before: Jun 7 08:06:49 2017 GMT - Not After : Jun 5 08:06:49 2027 GMT - Subject: C=FR, ST=Radius, O=Example Inc., CN=Example Server Certificate/emailAddress=admin@example.com - Subject Public Key Info: - Public Key Algorithm: rsaEncryption - Public-Key: (2048 bit) - Modulus: - 00:c9:d8:e2:e0:75:91:83:87:d8:c8:80:c6:20:4d: - e9:14:24:30:98:33:53:fa:56:0e:ec:9a:43:7f:87: - a9:22:94:26:06:c7:ac:b5:d9:ec:55:06:81:b7:0d: - c9:24:51:49:fa:47:fb:4b:4e:fc:ed:75:8a:e1:28: - 32:bc:c5:e0:4c:45:c4:58:60:15:67:1e:6b:40:19: - 3f:f0:ab:92:61:92:2d:71:10:2e:f2:eb:bc:81:2f: - 5a:3b:74:ca:5f:fd:e0:ee:d1:d9:07:6a:6c:20:c0: - 07:88:b4:8b:0f:ad:1e:c9:4f:7c:11:98:37:89:15: - de:24:b1:11:1a:7c:97:4a:cf:f3:c8:cb:79:9e:9c: - c3:71:da:a6:94:97:f5:95:fd:61:06:44:e2:3f:12: - 43:0b:1d:33:48:91:d2:ce:4f:97:a1:ed:6a:30:c7: - 5d:98:b5:6e:0a:b7:4f:d9:03:ec:80:76:09:b0:40: - a1:a1:af:ab:2a:59:c4:0f:56:22:bc:be:14:be:18: - df:10:7d:5d:22:bf:e5:04:77:7a:75:6b:3e:eb:6d: - 20:a1:a7:60:d4:f1:87:9d:9f:60:b9:d3:db:2c:25: - f4:91:4a:f1:d2:40:e5:a1:10:88:a0:41:5a:98:40: - ca:15:d7:e3:e6:3e:c0:6a:d5:46:b2:b4:90:b4:ae: - 3b:e3 - Exponent: 65537 (0x10001) - X509v3 extensions: - X509v3 Extended Key Usage: - TLS Web Server Authentication - X509v3 CRL Distribution Points: - - Full Name: - URI:http://www.example.com/example_ca.crl - - Signature Algorithm: sha1WithRSAEncryption - a4:25:21:51:0b:22:6c:63:8d:a9:c1:4f:04:33:69:79:34:f0: - 36:dd:8f:6a:27:5f:07:a2:1d:ef:8b:f0:96:e6:e7:a3:b8:3b: - 85:5e:3f:26:43:8a:8e:95:58:9c:a6:db:9c:51:bf:ea:53:16: - 3e:c1:a8:11:1a:c6:cf:0e:a1:17:18:64:d2:05:f1:c0:9c:a6: - 2b:16:c4:29:54:03:d2:17:bd:15:74:d6:ad:8a:8f:2d:cc:27: - 3b:88:88:f2:ea:d0:a2:cb:e9:42:57:df:26:9f:8a:a2:02:2f: - 35:b6:19:1d:26:43:44:af:12:4b:bc:b9:84:50:02:fd:1d:fa: - 50:e8 -----BEGIN CERTIFICATE----- -MIIDWTCCAsKgAwIBAgIBLzANBgkqhkiG9w0BAQUFADCBkzELMAkGA1UEBhMCRlIx -DzANBgNVBAgMBlJhZGl1czESMBAGA1UEBwwJU29tZXdoZXJlMRUwEwYDVQQKDAxF -eGFtcGxlIEluYy4xIDAeBgkqhkiG9w0BCQEWEWFkbWluQGV4YW1wbGUuY29tMSYw -JAYDVQQDDB1FeGFtcGxlIENlcnRpZmljYXRlIEF1dGhvcml0eTAeFw0xNzA2MDcw -ODA2NDlaFw0yNzA2MDUwODA2NDlaMHwxCzAJBgNVBAYTAkZSMQ8wDQYDVQQIDAZS -YWRpdXMxFTATBgNVBAoMDEV4YW1wbGUgSW5jLjEjMCEGA1UEAwwaRXhhbXBsZSBT -ZXJ2ZXIgQ2VydGlmaWNhdGUxIDAeBgkqhkiG9w0BCQEWEWFkbWluQGV4YW1wbGUu -Y29tMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAydji4HWRg4fYyIDG -IE3pFCQwmDNT+lYO7JpDf4epIpQmBsestdnsVQaBtw3JJFFJ+kf7S0787XWK4Sgy -vMXgTEXEWGAVZx5rQBk/8KuSYZItcRAu8uu8gS9aO3TKX/3g7tHZB2psIMAHiLSL -D60eyU98EZg3iRXeJLERGnyXSs/zyMt5npzDcdqmlJf1lf1hBkTiPxJDCx0zSJHS -zk+Xoe1qMMddmLVuCrdP2QPsgHYJsEChoa+rKlnED1YivL4UvhjfEH1dIr/lBHd6 -dWs+620goadg1PGHnZ9gudPbLCX0kUrx0kDloRCIoEFamEDKFdfj5j7AatVGsrSQ -tK474wIDAQABo08wTTATBgNVHSUEDDAKBggrBgEFBQcDATA2BgNVHR8ELzAtMCug -KaAnhiVodHRwOi8vd3d3LmV4YW1wbGUuY29tL2V4YW1wbGVfY2EuY3JsMA0GCSqG -SIb3DQEBBQUAA4GBAKQlIVELImxjjanBTwQzaXk08Dbdj2onXweiHe+L8Jbm56O4 -O4VePyZDio6VWJym25xRv+pTFj7BqBEaxs8OoRcYZNIF8cCcpisWxClUA9IXvRV0 -1q2Kjy3MJzuIiPLq0KLL6UJX3yafiqICLzW2GR0mQ0SvEku8uYRQAv0d+lDo +MIICAzCCAaagAwIBAgIJANqCHDjOKHh+MAwGCCqGSM49BAMCBQAwWjEOMAwGA1UE +AxMFY2YtY2ExFDASBgNVBAsTC0NhbGlmb3JuaXVtMRQwEgYDVQQKEwtFY2xpcHNl +IElvVDEPMA0GA1UEBxMGT3R0YXdhMQswCQYDVQQGEwJDQTAeFw0yMDExMTExMDMw +MzRaFw0yMTExMTExMDMwMzRaMF4xEjAQBgNVBAMTCWNmLXNlcnZlcjEUMBIGA1UE +CxMLQ2FsaWZvcm5pdW0xFDASBgNVBAoTC0VjbGlwc2UgSW9UMQ8wDQYDVQQHEwZP +dHRhd2ExCzAJBgNVBAYTAkNBMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAE+obM +gHmMB7zS4KArciXPD7CrvgEYqlnAf7NOTdb54RbTr4qEpPL+OJ6Pg8VhrF4hGEne +T6Aa4qqpmTkxmfT0vqNPME0wHQYDVR0OBBYEFE4XpfFad+F3+RcwI+s1cmJbTZWG +MAsGA1UdDwQEAwIHgDAfBgNVHSMEGDAWgBRL3+e1HCYWGJMdeLcJHorXevdX1TAM +BggqhkjOPQQDAgUAA0kAMEYCIQCEo+O5zqYKdwi/ElB4wfNVIf76P1OhIXAT5CHc +3ebBPQIhAN6UhCgQ0av6kf7INCazV3KmN7HmPXARaY4YKWsRwsg+ -----END CERTIFICATE----- diff --git a/examples/protocols/coap_server/main/certs/coap_server.key b/examples/protocols/coap_server/main/certs/coap_server.key index 9b3433273e..362851524f 100644 --- a/examples/protocols/coap_server/main/certs/coap_server.key +++ b/examples/protocols/coap_server/main/certs/coap_server.key @@ -1,27 +1,4 @@ ------BEGIN RSA PRIVATE KEY----- -MIIEpAIBAAKCAQEAydji4HWRg4fYyIDGIE3pFCQwmDNT+lYO7JpDf4epIpQmBses -tdnsVQaBtw3JJFFJ+kf7S0787XWK4SgyvMXgTEXEWGAVZx5rQBk/8KuSYZItcRAu -8uu8gS9aO3TKX/3g7tHZB2psIMAHiLSLD60eyU98EZg3iRXeJLERGnyXSs/zyMt5 -npzDcdqmlJf1lf1hBkTiPxJDCx0zSJHSzk+Xoe1qMMddmLVuCrdP2QPsgHYJsECh -oa+rKlnED1YivL4UvhjfEH1dIr/lBHd6dWs+620goadg1PGHnZ9gudPbLCX0kUrx -0kDloRCIoEFamEDKFdfj5j7AatVGsrSQtK474wIDAQABAoIBAQC2kGDEPBJdMSW2 -VCLfXRiPixwYzXQLXIMrJWwfkQg9qlmqkDd6U50aWkRA2UswegW7RhfYSZ0i+cmf -VMhvTVpOIlwwwtcY6b5/v1bBy60eaySGuuh79xQMlFO8qynQIMStvUfbGTqrdIRb -9VBB4YeS9T12fILejtTZwv2BQ2dj1Y1SCay6Ri85UzJqSClRKgHISybvVdLNjPvP -0TRFBr57zyjL6WE8teKiKchzQko2u86No5uBCdKGsrAkrsdcR0YqlM/pZxd3VKNm -+eny0k+dZZlvcPxzkzP4hEp9+Rw5rP9/s3s/cCwvuuC5JO32ATBWKCbTvPv/XPDb -MdSJtOshAoGBAPzk0eswkcbFYtpnpBNmBAr1dtAdW1lfjUI2ucMMwt7Wns0P/tt+ -gq6Hi1wTaGP0l/dIECgeHwjtWj31ZJjQtFJ1y/kafxo4o9cA8vCydpdvSZaldAfg -sbLlDTDYzEpelaDIbNQBBXFoC5U9JlBhBsIFCL5Z8ZuIeFPsb7t5wwuHAoGBAMxT -jyWfNm1uNxp1xgCnrRsLPQPVnURrSFAqcHrECqRu3F7sozTN7q/cZViemxPvVDGQ -p9c+9bHwaYvW4trO5qDHJ++gGwm5L52bMAY1VUfeTt67fqrey43XpdmzcTX1V9Uj -QWawPUCSDzFjL1MjfCIejtyYf5ash53vj+T8r/vFAoGAA/OPVB1uKazr3n3AEo2F -gqZTNO1AgCT+EArK3EFWyiSQVqPpV4SihheYFdg3yVgJB9QYbIgL9BfBUTaEW97m -8mLkzP+c/Mvlw3ZAVYJ0V+llPPVY2saoACOUES9SAdd4fwqiqK1baGo3xB0wfBEI -CgAKIu9E1ylKuAT5ufQtGAECgYEAtP/kU5h5N3El4QupTdU7VDSdZTMqsHw0v8cI -gsf9AXKvRmtrnBA8u46KPHmruHoO5CVXeSZtsaXdaaH+rYQQ6yXg67WxnehtFLlv -TmCaXiLBTS9cYvMf8FOyuGnsBLeEietEOTov2G5KhR5uwsAxa2wUc7endor5S9/2 -YQuyvV0CgYALbiFpILd5l1ip65eE6JdA3hfttUbV2j2NSW12ej69vqbeOfaSgNse -uYCcXFsBbQPhNPwA+4d1oCe8SyXZg1f7gE812z2Tyr/3vdVnNZlitoxhsHmGiyS7 -gZdaTYCb78l9z0EBdaCVvA16owEle4SR6f9eCwzSI0WPOUra+x/hrA== ------END RSA PRIVATE KEY----- +-----BEGIN PRIVATE KEY----- +MEECAQAwEwYHKoZIzj0CAQYIKoZIzj0DAQcEJzAlAgEBBCCLBQT66xp2w4+1K+Ai +/TXEC8tQZBxl9brFyK4F7AQNGw== +-----END PRIVATE KEY----- diff --git a/examples/protocols/coap_server/main/coap_server_example_main.c b/examples/protocols/coap_server/main/coap_server_example_main.c index 58a698d8ae..ed96cc6e21 100644 --- a/examples/protocols/coap_server/main/coap_server_example_main.c +++ b/examples/protocols/coap_server/main/coap_server_example_main.c @@ -29,15 +29,10 @@ #include "protocol_examples_common.h" -#if 1 -/* Needed until coap_dtls.h becomes a part of libcoap proper */ -#include "libcoap.h" -#include "coap_dtls.h" -#endif -#include "coap.h" +#include "coap3/coap.h" /* The examples use simple Pre-Shared-Key configuration that you can set via - 'make menuconfig'. + 'idf.py menuconfig'. If you'd rather not, just change the below entries to strings with the config you want - ie #define EXAMPLE_COAP_PSK_KEY "some-agreed-preshared-key" @@ -49,7 +44,7 @@ #define EXAMPLE_COAP_PSK_KEY CONFIG_EXAMPLE_COAP_PSK_KEY /* The examples use CoAP Logging Level that - you can set via 'make menuconfig'. + you can set via 'idf.py menuconfig'. If you'd rather not, just change the below entry to a value that is between 0 and 7 with @@ -67,8 +62,10 @@ static int espressif_data_len = 0; Server cert, taken from coap_server.crt Server key, taken from coap_server.key - The PEM, CRT and KEY file are examples taken from the wpa2 enterprise - example. + The PEM, CRT and KEY file are examples taken from + https://github.com/eclipse/californium/tree/master/demo-certs/src/main/resources + as the Certificate test (by default) for the coap_client is against the + californium server. To embed it in the app binary, the PEM, CRT and KEY file is named in the component.mk COMPONENT_EMBED_TXTFILES variable. @@ -87,39 +84,42 @@ extern uint8_t server_key_end[] asm("_binary_coap_server_key_end"); * The resource handler */ static void -hnd_espressif_get(coap_context_t *ctx, coap_resource_t *resource, +hnd_espressif_get(coap_resource_t *resource, coap_session_t *session, - coap_pdu_t *request, coap_binary_t *token, - coap_string_t *query, coap_pdu_t *response) + const coap_pdu_t *request, + const coap_string_t *query, + coap_pdu_t *response) { - coap_add_data_blocked_response(resource, session, request, response, token, - COAP_MEDIATYPE_TEXT_PLAIN, 0, - (size_t)espressif_data_len, - (const u_char *)espressif_data); + coap_pdu_set_code(response, COAP_RESPONSE_CODE_CONTENT); + coap_add_data_large_response(resource, session, request, response, + query, COAP_MEDIATYPE_TEXT_PLAIN, 60, 0, + (size_t)espressif_data_len, + (const u_char *)espressif_data, + NULL, NULL); } static void -hnd_espressif_put(coap_context_t *ctx, - coap_resource_t *resource, +hnd_espressif_put(coap_resource_t *resource, coap_session_t *session, - coap_pdu_t *request, - coap_binary_t *token, - coap_string_t *query, + const coap_pdu_t *request, + const coap_string_t *query, coap_pdu_t *response) { size_t size; - unsigned char *data; + size_t offset; + size_t total; + const unsigned char *data; coap_resource_notify_observers(resource, NULL); if (strcmp (espressif_data, INITIAL_DATA) == 0) { - response->code = COAP_RESPONSE_CODE(201); + coap_pdu_set_code(response, COAP_RESPONSE_CODE_CREATED); } else { - response->code = COAP_RESPONSE_CODE(204); + coap_pdu_set_code(response, COAP_RESPONSE_CODE_CHANGED); } - /* coap_get_data() sets size to 0 on error */ - (void)coap_get_data(request, &size, &data); + /* coap_get_data_large() sets size to 0 on error */ + (void)coap_get_data_large(request, &size, &data, &offset, &total); if (size == 0) { /* re-init */ snprintf(espressif_data, sizeof(espressif_data), INITIAL_DATA); @@ -131,18 +131,16 @@ hnd_espressif_put(coap_context_t *ctx, } static void -hnd_espressif_delete(coap_context_t *ctx, - coap_resource_t *resource, +hnd_espressif_delete(coap_resource_t *resource, coap_session_t *session, - coap_pdu_t *request, - coap_binary_t *token, - coap_string_t *query, + const coap_pdu_t *request, + const coap_string_t *query, coap_pdu_t *response) { coap_resource_notify_observers(resource, NULL); snprintf(espressif_data, sizeof(espressif_data), INITIAL_DATA); espressif_data_len = strlen(espressif_data); - response->code = COAP_RESPONSE_CODE(202); + coap_pdu_set_code(response, COAP_RESPONSE_CODE_DELETED); } #ifdef CONFIG_COAP_MBEDTLS_PKI @@ -163,6 +161,18 @@ verify_cn_callback(const char *cn, } #endif /* CONFIG_COAP_MBEDTLS_PKI */ +static void +coap_log_handler (coap_log_t level, const char *message) +{ + uint32_t esp_level = ESP_LOG_INFO; + char *cp = strchr(message, '\n'); + + if (cp) + ESP_LOG_LEVEL(esp_level, TAG, "%.*s", (int)(cp-message), message); + else + ESP_LOG_LEVEL(esp_level, TAG, "%s", message); +} + static void coap_example_server(void *p) { coap_context_t *ctx = NULL; @@ -171,6 +181,7 @@ static void coap_example_server(void *p) snprintf(espressif_data, sizeof(espressif_data), INITIAL_DATA); espressif_data_len = strlen(espressif_data); + coap_set_log_handler(coap_log_handler); coap_set_log_level(EXAMPLE_COAP_LOG_DEFAULT_LEVEL); while (1) { @@ -179,15 +190,16 @@ static void coap_example_server(void *p) /* Prepare the CoAP server socket */ coap_address_init(&serv_addr); - serv_addr.addr.sin.sin_family = AF_INET; - serv_addr.addr.sin.sin_addr.s_addr = INADDR_ANY; - serv_addr.addr.sin.sin_port = htons(COAP_DEFAULT_PORT); + serv_addr.addr.sin6.sin6_family = AF_INET6; + serv_addr.addr.sin6.sin6_port = htons(COAP_DEFAULT_PORT); ctx = coap_new_context(NULL); if (!ctx) { ESP_LOGE(TAG, "coap_new_context() failed"); continue; } + coap_context_set_block_mode(ctx, + COAP_BLOCK_USE_LIBCOAP|COAP_BLOCK_SINGLE_BODY); #ifdef CONFIG_COAP_MBEDTLS_PSK /* Need PSK setup before we set up endpoints */ coap_context_set_psk(ctx, "CoAP", @@ -196,6 +208,7 @@ static void coap_example_server(void *p) #endif /* CONFIG_COAP_MBEDTLS_PSK */ #ifdef CONFIG_COAP_MBEDTLS_PKI + /* Need PKI setup before we set up endpoints */ unsigned int ca_pem_bytes = ca_pem_end - ca_pem_start; unsigned int server_crt_bytes = server_crt_end - server_crt_start; unsigned int server_key_bytes = server_key_end - server_key_start; @@ -214,7 +227,7 @@ static void coap_example_server(void *p) * define what checking actually takes place. */ dtls_pki.verify_peer_cert = 1; - dtls_pki.require_peer_cert = 1; + dtls_pki.check_common_ca = 1; dtls_pki.allow_self_signed = 1; dtls_pki.allow_expired_certs = 1; dtls_pki.cert_chain_validation = 1; @@ -256,7 +269,7 @@ static void coap_example_server(void *p) /* This is not critical as unencrypted support is still available */ ESP_LOGI(TAG, "MbedTLS (D)TLS Server Mode not configured"); #else /* CONFIG_MBEDTLS_TLS_SERVER */ - serv_addr.addr.sin.sin_port = htons(COAPS_DEFAULT_PORT); + serv_addr.addr.sin6.sin6_port = htons(COAPS_DEFAULT_PORT); ep = coap_new_endpoint(ctx, &serv_addr, COAP_PROTO_DTLS); if (!ep) { ESP_LOGE(TAG, "dtls: coap_new_endpoint() failed"); @@ -267,7 +280,7 @@ static void coap_example_server(void *p) /* This is not critical as unencrypted support is still available */ ESP_LOGI(TAG, "MbedTLS (D)TLS Server Mode not configured"); } -#endif /* CONFIG_COAP_MBEDTLS_PSK CONFIG_COAP_MBEDTLS_PKI */ +#endif /* CONFIG_COAP_MBEDTLS_PSK || CONFIG_COAP_MBEDTLS_PKI */ resource = coap_resource_init(coap_make_str_const("Espressif"), 0); if (!resource) { ESP_LOGE(TAG, "coap_resource_init() failed"); @@ -280,10 +293,26 @@ static void coap_example_server(void *p) coap_resource_set_get_observable(resource, 1); coap_add_resource(ctx, resource); +#if defined(CONFIG_EXAMPLE_COAP_MCAST_IPV4) || defined(CONFIG_EXAMPLE_COAP_MCAST_IPV6) + esp_netif_t *netif = NULL; + for (int i = 0; i < esp_netif_get_nr_of_ifs(); ++i) { + char buf[8]; + netif = esp_netif_next(netif); + esp_netif_get_netif_impl_name(netif, buf); +#if defined(CONFIG_EXAMPLE_COAP_MCAST_IPV4) + coap_join_mcast_group_intf(ctx, CONFIG_EXAMPLE_COAP_MULTICAST_IPV4_ADDR, buf); +#endif /* CONFIG_EXAMPLE_COAP_MCAST_IPV4 */ +#if defined(CONFIG_EXAMPLE_COAP_MCAST_IPV6) + /* When adding IPV6 esp-idf requires ifname param to be filled in */ + coap_join_mcast_group_intf(ctx, CONFIG_EXAMPLE_COAP_MULTICAST_IPV6_ADDR, buf); +#endif /* CONFIG_EXAMPLE_COAP_MCAST_IPV6 */ + } +#endif /* CONFIG_EXAMPLE_COAP_MCAST_IPV4 || CONFIG_EXAMPLE_COAP_MCAST_IPV6 */ + wait_ms = COAP_RESOURCE_CHECK_TIME * 1000; while (1) { - int result = coap_run_once(ctx, wait_ms); + int result = coap_io_process(ctx, wait_ms); if (result < 0) { break; } else if (result && (unsigned)result < wait_ms) { diff --git a/examples/protocols/coap_server/sdkconfig.defaults b/examples/protocols/coap_server/sdkconfig.defaults index 03171ab264..308ca1c49a 100644 --- a/examples/protocols/coap_server/sdkconfig.defaults +++ b/examples/protocols/coap_server/sdkconfig.defaults @@ -1,3 +1,4 @@ CONFIG_MBEDTLS_SSL_PROTO_DTLS=y CONFIG_MBEDTLS_PSK_MODES=y CONFIG_MBEDTLS_KEY_EXCHANGE_PSK=y +CONFIG_LWIP_NETBUF_RECVINFO=y