libcoap_430: Update code for use with libcoap 4.3.0

Remove no longer needed code from coap_server/coap_client.

Add in multicast support for coap_server/coap_client.

Update libcoap logging to use esp-idf logging

Signed-off-by: Harshit Malpani <harshit.malpani@espressif.com>
This commit is contained in:
Jon Shallow 2021-03-02 15:32:07 +00:00 committed by bot
parent ef5fe39faa
commit ed3d440428
23 changed files with 598 additions and 4177 deletions

View File

@ -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.
#

View File

@ -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

View File

@ -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

@ -1 +1 @@
Subproject commit 98954eb30a2e728e172a6cd29430ae5bc999b585
Subproject commit 9b6451c3654bc1f625e36c87f018c2da34bea5e6

View File

@ -1,888 +0,0 @@
/* debug.c -- debug utilities
*
* Copyright (C) 2010--2012,2014--2019 Olaf Bergmann <bergmann@tzi.org> 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 <assert.h>
#endif
#include <stdarg.h>
#include <stdio.h>
#include <string.h>
#include <ctype.h>
#ifdef HAVE_ARPA_INET_H
#include <arpa/inet.h>
#endif
#ifdef HAVE_WS2TCPIP_H
#include <ws2tcpip.h>
#endif
#ifdef HAVE_TIME_H
#include <time.h>
#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;
}

File diff suppressed because it is too large Load Diff

View File

@ -1,190 +0,0 @@
/*
* coap_notls.c -- Stub Datagram Transport Layer Support for libcoap
*
* Copyright (C) 2016 Olaf Bergmann <bergmann@tzi.org>
*
* 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 */

View File

@ -1,631 +0,0 @@
/*
* coap_dtls.h -- (Datagram) Transport Layer Support for libcoap
*
* Copyright (C) 2016 Olaf Bergmann <bergmann@tzi.org>
* Copyright (C) 2017 Jean-Claude Michelou <jcm@spinetix.com>
*
* 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 */

View File

@ -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
}

View File

@ -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 */

View File

@ -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`,

View File

@ -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-----

View File

@ -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-----

View File

@ -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-----

View File

@ -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);
}

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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-----

View File

@ -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-----

View File

@ -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-----

View File

@ -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) {

View File

@ -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