mirror of
https://github.com/espressif/esp-idf.git
synced 2024-10-05 20:47:46 -04:00
Add DTLS support to libcoap using MbedTLS
This update supports DTLS, TLS is a future TODO components/coap/CMakeLists.txt: components/coap/component.mk: Add in the new files that have to be built Replace libcoap/src/coap_notls.c with libcoap/src/coap_mbedtls.c components/coap/libcoap: Update the version to include the current version for supporting MbedTLS components/coap/port/coap_debug.c: components/coap/port/coap_mbedtls.c: components/coap/port/include/coap/coap_dtls.h: New port files for DTLS components/coap/port/include/coap_config_posix.h: Include building with MbedTLS examples/protocols/coap_client/README.md: examples/protocols/coap_client/main/CMakeLists.txt: examples/protocols/coap_client/main/Kconfig.projbuild: examples/protocols/coap_client/main/coap_client_example_main.c: examples/protocols/coap_client/main/component.mk: Update CoAP client to support DTLS examples/protocols/coap_client/main/coap_ca.pem examples/protocols/coap_client/main/coap_client.crt examples/protocols/coap_client/main/coap_client.key New PKI Certs for CoAP client (copied from wpa2_enterprise example) examples/protocols/coap_server/README.md: examples/protocols/coap_server/main/CMakeLists.txt: examples/protocols/coap_server/main/Kconfig.projbuild: examples/protocols/coap_server/main/coap_server_example_main.c: examples/protocols/coap_server/main/component.mk: Update CoAP server to support DTLS Change "no data" to "Hello World!" to prevent confusion examples/protocols/coap_server/main/coap_ca.pem examples/protocols/coap_server/main/coap_server.crt examples/protocols/coap_server/main/coap_server.key New PKI Certs for CoAP server (copied from wpa2_enterprise example) Closes https://github.com/espressif/esp-idf/pull/3345 Closes https://github.com/espressif/esp-idf/issues/1379
This commit is contained in:
parent
39f090a4f1
commit
1aaec808da
@ -8,7 +8,7 @@ set(srcs
|
||||
"libcoap/src/coap_hashkey.c"
|
||||
"libcoap/src/coap_session.c"
|
||||
"libcoap/src/coap_time.c"
|
||||
"libcoap/src/coap_debug.c"
|
||||
"port/coap_debug.c"
|
||||
"libcoap/src/encode.c"
|
||||
"libcoap/src/mem.c"
|
||||
"libcoap/src/net.c"
|
||||
@ -18,8 +18,8 @@ set(srcs
|
||||
"libcoap/src/str.c"
|
||||
"libcoap/src/subscribe.c"
|
||||
"libcoap/src/uri.c"
|
||||
"libcoap/src/coap_notls.c"
|
||||
"port/coap_io.c")
|
||||
"libcoap/src/coap_io.c"
|
||||
"port/coap_mbedtls.c")
|
||||
|
||||
set(COMPONENT_REQUIRES lwip)
|
||||
|
||||
@ -28,7 +28,7 @@ idf_component_register(SRCS "${srcs}"
|
||||
REQUIRES lwip)
|
||||
|
||||
# Silence format truncation warning, until it is fixed upstream
|
||||
set_source_files_properties(libcoap/src/coap_debug.c PROPERTIES COMPILE_FLAGS -Wno-format-truncation)
|
||||
set_source_files_properties(port/coap_debug.c PROPERTIES COMPILE_FLAGS -Wno-format-truncation)
|
||||
|
||||
# Needed for coap headers in public builds, also.
|
||||
#
|
||||
|
@ -4,11 +4,11 @@
|
||||
|
||||
COMPONENT_ADD_INCLUDEDIRS := port/include port/include/coap libcoap/include libcoap/include/coap2
|
||||
|
||||
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 libcoap/src/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 libcoap/src/coap_notls.o port/coap_io.o
|
||||
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
|
||||
|
||||
COMPONENT_SRCDIRS := libcoap/src libcoap port
|
||||
|
||||
COMPONENT_SUBMODULES += libcoap
|
||||
|
||||
# Silence format truncation warning, until it is fixed upstream
|
||||
libcoap/src/coap_debug.o: CFLAGS += -Wno-format-truncation
|
||||
port/coap_debug.o: CFLAGS += -Wno-format-truncation
|
||||
|
@ -1 +1 @@
|
||||
Subproject commit cfec0d072c5b99ed3e54828ca50ea2f6b91e1f50
|
||||
Subproject commit 98954eb30a2e728e172a6cd29430ae5bc999b585
|
888
components/coap/port/coap_debug.c
Normal file
888
components/coap/port/coap_debug.c
Normal file
@ -0,0 +1,888 @@
|
||||
/* 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
1796
components/coap/port/coap_mbedtls.c
Normal file
1796
components/coap/port/coap_mbedtls.c
Normal file
File diff suppressed because it is too large
Load Diff
631
components/coap/port/include/coap/coap_dtls.h
Normal file
631
components/coap/port/include/coap/coap_dtls.h
Normal file
@ -0,0 +1,631 @@
|
||||
/*
|
||||
* 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 */
|
@ -21,18 +21,27 @@
|
||||
#ifdef WITH_POSIX
|
||||
|
||||
#include <sys/socket.h>
|
||||
#include <net/if.h>
|
||||
|
||||
#define HAVE_SYS_SOCKET_H
|
||||
#define HAVE_MALLOC
|
||||
#define HAVE_ARPA_INET_H
|
||||
#define HAVE_TIME_H
|
||||
#define HAVE_NETDB_H
|
||||
#define HAVE_NETINET_IN_H
|
||||
|
||||
#define IPV6_PKTINFO IPV6_V6ONLY
|
||||
|
||||
#define PACKAGE_NAME "libcoap-posix"
|
||||
#define PACKAGE_VERSION "?"
|
||||
|
||||
#define COAP_BAD_RECVMSG
|
||||
#define HAVE_MBEDTLS
|
||||
#define COAP_CONSTRAINED_STACK 1
|
||||
#define ESPIDF_VERSION
|
||||
|
||||
#define _POSIX_TIMERS 1
|
||||
|
||||
#define gai_strerror(x) "gai_strerror() not supported"
|
||||
|
||||
#endif /* WITH_POSIX */
|
||||
#endif /* COAP_CONFIG_POSIX_H_ */
|
||||
|
@ -25,6 +25,7 @@ target_sources(mbedtls PRIVATE "${COMPONENT_DIR}/port/esp_bignum.c"
|
||||
"${COMPONENT_DIR}/port/esp_sha1.c"
|
||||
"${COMPONENT_DIR}/port/esp_sha256.c"
|
||||
"${COMPONENT_DIR}/port/esp_sha512.c"
|
||||
"${COMPONENT_DIR}/port/esp_timing.c"
|
||||
"${COMPONENT_DIR}/port/mbedtls_debug.c"
|
||||
"${COMPONENT_DIR}/port/net_sockets.c"
|
||||
"${COMPONENT_DIR}/port/esp32/aes.c"
|
||||
@ -36,4 +37,4 @@ foreach(target ${mbedtls_targets})
|
||||
endforeach()
|
||||
|
||||
# Link mbedtls libraries to component library
|
||||
target_link_libraries(${COMPONENT_LIB} INTERFACE ${mbedtls_targets})
|
||||
target_link_libraries(${COMPONENT_LIB} INTERFACE ${mbedtls_targets})
|
||||
|
102
components/mbedtls/port/esp_timing.c
Normal file
102
components/mbedtls/port/esp_timing.c
Normal file
@ -0,0 +1,102 @@
|
||||
/*
|
||||
* Portable interface to the CPU cycle counter
|
||||
*
|
||||
* Copyright (C) 2006-2015, ARM Limited, All Rights Reserved
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License"); you may
|
||||
* not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
||||
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*
|
||||
* This file is part of mbed TLS (https://tls.mbed.org)
|
||||
*/
|
||||
|
||||
/*
|
||||
* mbedtls_timing_get_timer()m mbedtls_timing_set_delay() and
|
||||
* mbedtls_timing_set_delay only abstracted from mbedtls/library/timing.c
|
||||
* as that does not build on ESP-IDF but these 2 functions are needed for
|
||||
* DTLS (in particular mbedtls_ssl_set_timer_cb() must be called for DTLS
|
||||
* which requires these 2 delay functions).
|
||||
*/
|
||||
|
||||
#if !defined(MBEDTLS_CONFIG_FILE)
|
||||
#include "mbedtls/config.h"
|
||||
#else
|
||||
#include MBEDTLS_CONFIG_FILE
|
||||
#endif
|
||||
|
||||
#if !defined(MBEDTLS_ESP_TIMING_C)
|
||||
|
||||
#include <sys/time.h>
|
||||
#include "mbedtls/timing.h"
|
||||
|
||||
struct _hr_time
|
||||
{
|
||||
struct timeval start;
|
||||
};
|
||||
|
||||
unsigned long mbedtls_timing_get_timer( struct mbedtls_timing_hr_time *val, int reset )
|
||||
{
|
||||
struct _hr_time *t = (struct _hr_time *) val;
|
||||
|
||||
if( reset )
|
||||
{
|
||||
gettimeofday( &t->start, NULL );
|
||||
return( 0 );
|
||||
}
|
||||
else
|
||||
{
|
||||
unsigned long delta;
|
||||
struct timeval now;
|
||||
gettimeofday( &now, NULL );
|
||||
delta = ( now.tv_sec - t->start.tv_sec ) * 1000ul
|
||||
+ ( now.tv_usec - t->start.tv_usec ) / 1000;
|
||||
return( delta );
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Set delays to watch
|
||||
*/
|
||||
void mbedtls_timing_set_delay( void *data, uint32_t int_ms, uint32_t fin_ms )
|
||||
{
|
||||
mbedtls_timing_delay_context *ctx = (mbedtls_timing_delay_context *) data;
|
||||
|
||||
ctx->int_ms = int_ms;
|
||||
ctx->fin_ms = fin_ms;
|
||||
|
||||
if( fin_ms != 0 )
|
||||
(void) mbedtls_timing_get_timer( &ctx->timer, 1 );
|
||||
}
|
||||
|
||||
/*
|
||||
* Get number of delays expired
|
||||
*/
|
||||
int mbedtls_timing_get_delay( void *data )
|
||||
{
|
||||
mbedtls_timing_delay_context *ctx = (mbedtls_timing_delay_context *) data;
|
||||
unsigned long elapsed_ms;
|
||||
|
||||
if( ctx->fin_ms == 0 )
|
||||
return( -1 );
|
||||
|
||||
elapsed_ms = mbedtls_timing_get_timer( &ctx->timer, 0 );
|
||||
|
||||
if( elapsed_ms >= ctx->fin_ms )
|
||||
return( 2 );
|
||||
|
||||
if( elapsed_ms >= ctx->int_ms )
|
||||
return( 1 );
|
||||
|
||||
return( 0 );
|
||||
}
|
||||
|
||||
#endif /* MBEDTLS_ESP_TIMING_C */
|
@ -2,14 +2,27 @@
|
||||
# CoAP client example
|
||||
|
||||
(See the README.md file in the upper level 'examples' directory for more information about examples.)
|
||||
this CoAP client example is adaptation of one of the [libcoap](https://github.com/obgm/libcoap) example.
|
||||
This CoAP client example is very simplified adaptation of one of the
|
||||
[libcoap](https://github.com/obgm/libcoap) examples.
|
||||
|
||||
CoAP client example would connect your ESP32 device to any CoAP server, fetch data from CoAP server and upstream data to CoAP server.
|
||||
CoAP client example will connect your ESP32 device to a CoAP server, send off a GET request and
|
||||
fetch the response data from CoAP server. The client can be extended to PUT / POST / DELETE requests,
|
||||
as well as supporting the Observer extensions [RFC7641](https://tools.ietf.org/html/rfc7641).
|
||||
|
||||
The Constrained Application Protocol (CoAP) is a specialized web transfer protocol for use with constrained nodes and constrained networks in the Internet of Things.
|
||||
The protocol is designed for machine-to-machine (M2M) applications such as smart energy and building automation.
|
||||
If the URI is prefixed with coaps:// instead of coap://, then the CoAP client will attempt to use
|
||||
the DTLS protocol using the defined Pre-Shared Keys(PSK) or Public Key Infrastructure (PKI) which the
|
||||
CoAP server needs to know about.
|
||||
|
||||
please refer to [RFC7252](https://www.rfc-editor.org/rfc/pdfrfc/rfc7252.txt.pdf) for more details.
|
||||
If the URI is prefixed with coap+tcp://, then the CoAP will try to use TCP for the communication.
|
||||
|
||||
NOTE: coaps+tcp:// is not currently supported, even though both libcoap and MbedTLS support it.
|
||||
|
||||
The Constrained Application Protocol (CoAP) is a specialized web transfer protocol for use with
|
||||
constrained nodes and constrained networks in the Internet of Things.
|
||||
The protocol is designed for machine-to-machine (M2M) applications such as smart energy and
|
||||
building automation.
|
||||
|
||||
Please refer to [RFC7252](https://www.rfc-editor.org/rfc/pdfrfc/rfc7252.txt.pdf) for more details.
|
||||
|
||||
## How to use example
|
||||
|
||||
@ -19,16 +32,29 @@ please refer to [RFC7252](https://www.rfc-editor.org/rfc/pdfrfc/rfc7252.txt.pdf)
|
||||
idf.py menuconfig
|
||||
```
|
||||
|
||||
* Set serial port under Serial Flasher config
|
||||
* Set Target Uri under Example Configuration
|
||||
* Set WiFi SSID under Example Configuration
|
||||
* Set WiFi Password under Example Configuration
|
||||
Example Connection Configuration --->
|
||||
* Set WiFi SSID under Example Configuration
|
||||
* Set WiFi Password under Example Configuration
|
||||
Example CoAP Client Configuration --->
|
||||
* Set CoAP Target Uri
|
||||
* Set encryption method definitions (None, PSK or PKI)
|
||||
* If PSK Set CoAP Preshared Key to use in connection to the server
|
||||
* If PSK Set CoAP PSK Client identity (username)
|
||||
Enable CoAP debugging if required
|
||||
Component config --->
|
||||
mbedTLS --->
|
||||
[*] Enable mbedtls certificate expiry check
|
||||
TLS Key Exchange Methods --->
|
||||
[*] Enable pre-shared-key ciphersuites
|
||||
[*] Enable PSK based ciphersuite modes
|
||||
[*] Support DTLS protocol (all versions)
|
||||
|
||||
### Build and Flash
|
||||
|
||||
Build the project and flash it to the board, then run monitor tool to view serial output:
|
||||
|
||||
```
|
||||
idf.py build
|
||||
idf.py -p PORT flash monitor
|
||||
```
|
||||
|
||||
@ -72,9 +98,11 @@ published under EPL+EDL: http://www.eclipse.org/californium/
|
||||
This can be found at https://libcoap.net/doc/reference/4.2.0/
|
||||
|
||||
## Troubleshooting
|
||||
* Please make sure Target Url includes valid `host`, optional `port`, optional `path`, and begins
|
||||
with `coap://` or `coap+tcp://` for a coap server that supports TCP
|
||||
* Please make sure Target Url includes valid `host`, optional `port`,
|
||||
optional `path`, and begins with `coap://`, `coaps://` or `coap+tcp://`
|
||||
for a coap server that supports TCP
|
||||
(not all do including coap+tcp://californium.eclipse.org).
|
||||
|
||||
* libcoap logging can be increased by changing `#define COAP_LOGGING_LEVEL 0`
|
||||
to `#define COAP_LOGGING_LEVEL 9`
|
||||
* CoAP logging can be enabled by running 'make menuconfig' and enable debugging
|
||||
|
||||
* Encryption (MbedTLS) can be enabled by running 'make menuconfig' and enable debugging
|
||||
|
@ -1,2 +1,4 @@
|
||||
# Embed CA, certificate & key directly into binary
|
||||
idf_component_register(SRCS "coap_client_example_main.c"
|
||||
INCLUDE_DIRS ".")
|
||||
INCLUDE_DIRS "."
|
||||
EMBED_TXTFILES coap_ca.pem coap_client.crt coap_client.key)
|
||||
|
@ -1,9 +1,96 @@
|
||||
menu "Example Configuration"
|
||||
menu "Example CoAP Client Configuration"
|
||||
|
||||
config TARGET_DOMAIN_URI
|
||||
string "Target Uri"
|
||||
default "coap://californium.eclipse.org"
|
||||
help
|
||||
Target uri for the example to use.
|
||||
Target uri for the example to use. Use coaps:// prefix for encrypted traffic
|
||||
using Pre-Shared Key (PSK) or Public Key Infrastructure (PKI).
|
||||
|
||||
choice MBEDTLS_COAP_ENCRYPTION_MODE
|
||||
prompt "CoAP Encryption method"
|
||||
default MBEDTLS_COAP_PKI_NONE
|
||||
help
|
||||
If the CoAP information is to be encrypted, the encryption environment
|
||||
can be set up in one of three ways
|
||||
|
||||
- None defined (will use PKI if coaps:// used)
|
||||
- Encrypt using defined Pre-Shared Keys (PSK)
|
||||
- Encrypt using defined Public Key Infrastructure (PKI)
|
||||
|
||||
config MBEDTLS_COAP_NONE
|
||||
bool "None defined"
|
||||
|
||||
config MBEDTLS_COAP_PSK
|
||||
bool "Pre-Shared Keys"
|
||||
|
||||
config MBEDTLS_COAP_PKI
|
||||
bool "PKI Certificates"
|
||||
|
||||
endchoice #MBEDTLS_COAP_ENCRYPTION_MODE
|
||||
|
||||
config COAP_PSK_KEY
|
||||
string "Preshared Key (PSK) to used in the connection to the CoAP server"
|
||||
depends on MBEDTLS_COAP_PSK
|
||||
default "secret-key"
|
||||
help
|
||||
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.
|
||||
|
||||
config COAP_PSK_IDENTITY
|
||||
string "PSK Client identity (username)"
|
||||
depends on MBEDTLS_COAP_PSK
|
||||
default "coap-client"
|
||||
help
|
||||
The identity (or username) to use to identify to the CoAP server which
|
||||
PSK key to use.
|
||||
|
||||
config MBEDTLS_COAP_DEBUG
|
||||
bool "Enable CoAP debugging"
|
||||
default n
|
||||
help
|
||||
Enable CoAP debugging functions at compile time for the example code.
|
||||
|
||||
If this option is enabled, call coap_set_log_level()
|
||||
at runtime in order to enable CoAP debug output via the ESP
|
||||
log mechanism.
|
||||
|
||||
choice MBEDTLS_COAP_DEBUG_LEVEL
|
||||
bool "Set CoAP debugging level"
|
||||
depends on MBEDTLS_COAP_DEBUG
|
||||
default COAP_LOG_WARNING
|
||||
help
|
||||
Set CoAP debugging level
|
||||
|
||||
config COAP_LOG_EMERG
|
||||
bool "Emergency"
|
||||
config COAP_LOG_ALERT
|
||||
bool "Alert"
|
||||
config COAP_LOG_CRIT
|
||||
bool "Critical"
|
||||
config COAP_LOG_ERROR
|
||||
bool "Error"
|
||||
config COAP_LOG_WARNING
|
||||
bool "Warning"
|
||||
config COAP_LOG_NOTICE
|
||||
bool "Notice"
|
||||
config COAP_LOG_INFO
|
||||
bool "Info"
|
||||
config COAP_LOG_DEBUG
|
||||
bool "Debug"
|
||||
endchoice
|
||||
|
||||
config COAP_LOG_DEFAULT_LEVEL
|
||||
int
|
||||
default 0 if !MBEDTLS_COAP_DEBUG
|
||||
default 0 if COAP_LOG_EMERG
|
||||
default 1 if COAP_LOG_ALERT
|
||||
default 2 if COAP_LOG_CRIT
|
||||
default 3 if COAP_LOG_ERROR
|
||||
default 4 if COAP_LOG_WARNING
|
||||
default 5 if COAP_LOG_NOTICE
|
||||
default 6 if COAP_LOG_INFO
|
||||
default 7 if COAP_LOG_DEBUG
|
||||
|
||||
endmenu
|
||||
|
23
examples/protocols/coap_client/main/coap_ca.pem
Normal file
23
examples/protocols/coap_client/main/coap_ca.pem
Normal file
@ -0,0 +1,23 @@
|
||||
-----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=
|
||||
-----END CERTIFICATE-----
|
70
examples/protocols/coap_client/main/coap_client.crt
Normal file
70
examples/protocols/coap_client/main/coap_client.crt
Normal file
@ -0,0 +1,70 @@
|
||||
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==
|
||||
-----END CERTIFICATE-----
|
27
examples/protocols/coap_client/main/coap_client.key
Normal file
27
examples/protocols/coap_client/main/coap_client.key
Normal file
@ -0,0 +1,27 @@
|
||||
-----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-----
|
@ -7,6 +7,13 @@
|
||||
CONDITIONS OF ANY KIND, either express or implied.
|
||||
*/
|
||||
|
||||
/*
|
||||
* WARNING
|
||||
* libcoap is not multi-thread safe, so only this thread must make any coap_*()
|
||||
* calls. Any external (to this thread) data transmitted in/out via libcoap
|
||||
* therefore has to be passed in/out by xQueue*() via this thread.
|
||||
*/
|
||||
|
||||
#include <string.h>
|
||||
#include <sys/socket.h>
|
||||
#include <netdb.h>
|
||||
@ -23,12 +30,36 @@
|
||||
|
||||
#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"
|
||||
|
||||
#define COAP_DEFAULT_TIME_SEC 5
|
||||
|
||||
/* Set this to 9 to get verbose logging from within libcoap */
|
||||
#define COAP_LOGGING_LEVEL 0
|
||||
/* The examples use simple Pre-Shared-Key configuration that you can set via
|
||||
'make 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"
|
||||
|
||||
Note: PSK will only be used if the URI is prefixed with coaps://
|
||||
instead of coap:// and the PSK must be one that the server supports
|
||||
(potentially associated with the IDENTITY)
|
||||
*/
|
||||
#define EXAMPLE_COAP_PSK_KEY CONFIG_COAP_PSK_KEY
|
||||
#define EXAMPLE_COAP_PSK_IDENTITY CONFIG_COAP_PSK_IDENTITY
|
||||
|
||||
/* The examples use uri Logging Level that
|
||||
you can set via 'make menuconfig'.
|
||||
|
||||
If you'd rather not, just change the below entry to a value
|
||||
that is between 0 and 7 with
|
||||
the config you want - ie #define EXAMPLE_COAP_LOG_DEFAULT_LEVEL 7
|
||||
*/
|
||||
#define EXAMPLE_COAP_LOG_DEFAULT_LEVEL CONFIG_COAP_LOG_DEFAULT_LEVEL
|
||||
|
||||
/* The examples use uri "coap://californium.eclipse.org" that
|
||||
you can set via the project configuration (idf.py menuconfig)
|
||||
@ -124,17 +155,44 @@ clean_up:
|
||||
resp_wait = 0;
|
||||
}
|
||||
|
||||
static void coap_example_task(void *p)
|
||||
#ifdef CONFIG_MBEDTLS_COAP_PKI
|
||||
|
||||
#ifdef __GNUC__
|
||||
#define UNUSED_PARAM __attribute__ ((unused))
|
||||
#else /* not a GCC */
|
||||
#define UNUSED_PARAM
|
||||
#endif /* GCC */
|
||||
|
||||
#ifndef min
|
||||
#define min(a,b) ((a) < (b) ? (a) : (b))
|
||||
#endif
|
||||
|
||||
static int
|
||||
verify_cn_callback(const char *cn,
|
||||
const uint8_t *asn1_public_cert UNUSED_PARAM,
|
||||
size_t asn1_length UNUSED_PARAM,
|
||||
coap_session_t *session UNUSED_PARAM,
|
||||
unsigned depth,
|
||||
int validated UNUSED_PARAM,
|
||||
void *arg UNUSED_PARAM
|
||||
) {
|
||||
coap_log(LOG_INFO, "CN '%s' presented by server (%s)\n",
|
||||
cn, depth ? "CA" : "Certificate");
|
||||
return 1;
|
||||
}
|
||||
#endif /* CONFIG_MBEDTLS_COAP_PKI */
|
||||
|
||||
static void coap_example_client(void *p)
|
||||
{
|
||||
struct hostent *hp;
|
||||
struct ip4_addr *ip4_addr;
|
||||
|
||||
coap_address_t dst_addr, src_addr;
|
||||
coap_address_t dst_addr;
|
||||
static coap_uri_t uri;
|
||||
const char* server_uri = COAP_DEFAULT_DEMO_URI;
|
||||
char* phostname = NULL;
|
||||
|
||||
coap_set_log_level(COAP_LOGGING_LEVEL);
|
||||
coap_set_log_level(EXAMPLE_COAP_LOG_DEFAULT_LEVEL);
|
||||
|
||||
while (1) {
|
||||
#define BUFSIZE 40
|
||||
unsigned char _buf[BUFSIZE];
|
||||
@ -153,7 +211,7 @@ static void coap_example_task(void *p)
|
||||
|
||||
if ((uri.scheme==COAP_URI_SCHEME_COAPS && !coap_dtls_is_supported()) ||
|
||||
(uri.scheme==COAP_URI_SCHEME_COAPS_TCP && !coap_tls_is_supported())) {
|
||||
ESP_LOGE(TAG, "CoAP server uri scheme error");
|
||||
ESP_LOGE(TAG, "CoAP server uri scheme is not supported");
|
||||
break;
|
||||
}
|
||||
|
||||
@ -172,19 +230,31 @@ static void coap_example_task(void *p)
|
||||
ESP_LOGE(TAG, "DNS lookup failed");
|
||||
vTaskDelay(1000 / portTICK_PERIOD_MS);
|
||||
free(phostname);
|
||||
continue;
|
||||
goto clean_up;
|
||||
}
|
||||
{
|
||||
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;
|
||||
}
|
||||
}
|
||||
|
||||
/* Code to print the resolved IP.
|
||||
|
||||
Note: inet_ntoa is non-reentrant, look at ipaddr_ntoa_r for "real" code */
|
||||
ip4_addr = (struct ip4_addr *)hp->h_addr;
|
||||
ESP_LOGI(TAG, "DNS lookup succeeded. IP=%s", inet_ntoa(*ip4_addr));
|
||||
|
||||
coap_address_init(&src_addr);
|
||||
src_addr.addr.sin.sin_family = AF_INET;
|
||||
src_addr.addr.sin.sin_port = htons(0);
|
||||
src_addr.addr.sin.sin_addr.s_addr = INADDR_ANY;
|
||||
|
||||
if (uri.path.length) {
|
||||
buflen = BUFSIZE;
|
||||
@ -222,15 +292,102 @@ static void coap_example_task(void *p)
|
||||
goto clean_up;
|
||||
}
|
||||
|
||||
coap_address_init(&dst_addr);
|
||||
dst_addr.addr.sin.sin_family = AF_INET;
|
||||
dst_addr.addr.sin.sin_port = htons(uri.port);
|
||||
dst_addr.addr.sin.sin_addr.s_addr = ip4_addr->addr;
|
||||
/*
|
||||
* 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) {
|
||||
#ifdef CONFIG_MBEDTLS_COAP_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);
|
||||
#endif /* CONFIG_MBEDTLS_COAP_PSK */
|
||||
|
||||
session = coap_new_client_session(ctx, &src_addr, &dst_addr,
|
||||
uri.scheme==COAP_URI_SCHEME_COAP_TCP ? COAP_PROTO_TCP :
|
||||
uri.scheme==COAP_URI_SCHEME_COAPS_TCP ? COAP_PROTO_TLS :
|
||||
uri.scheme==COAP_URI_SCHEME_COAPS ? COAP_PROTO_DTLS : COAP_PROTO_UDP);
|
||||
#ifdef CONFIG_MBEDTLS_COAP_PKI
|
||||
/* CA cert, taken from coap_ca.pem
|
||||
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.
|
||||
|
||||
To embed it in the app binary, the PEM, CRT and KEY file is named
|
||||
in the component.mk COMPONENT_EMBED_TXTFILES variable.
|
||||
*/
|
||||
extern uint8_t ca_pem_start[] asm("_binary_coap_ca_pem_start");
|
||||
extern uint8_t ca_pem_end[] asm("_binary_coap_ca_pem_end");
|
||||
extern uint8_t client_crt_start[] asm("_binary_coap_client_crt_start");
|
||||
extern uint8_t client_crt_end[] asm("_binary_coap_client_crt_end");
|
||||
extern uint8_t client_key_start[] asm("_binary_coap_client_key_start");
|
||||
extern uint8_t client_key_end[] asm("_binary_coap_client_key_end");
|
||||
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];
|
||||
|
||||
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_MBEDTLS_COAP_PKI */
|
||||
|
||||
#ifdef CONFIG_MBEDTLS_COAP_NONE
|
||||
session = coap_new_client_session(ctx, NULL, &dst_addr,
|
||||
uri.scheme==COAP_URI_SCHEME_COAPS ? COAP_PROTO_DTLS : COAP_PROTO_TLS);
|
||||
#endif /* CONFIG_MBEDTLS_COAP_NONE */
|
||||
} 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;
|
||||
@ -272,7 +429,10 @@ clean_up:
|
||||
if (session) coap_session_release(session);
|
||||
if (ctx) coap_free_context(ctx);
|
||||
coap_cleanup();
|
||||
/* Only send the request off once */
|
||||
/*
|
||||
* change the following line to something like sleep(2)
|
||||
* if you want the request to continually be sent
|
||||
*/
|
||||
break;
|
||||
}
|
||||
|
||||
@ -285,11 +445,19 @@ void app_main(void)
|
||||
tcpip_adapter_init();
|
||||
ESP_ERROR_CHECK(esp_event_loop_create_default());
|
||||
|
||||
#if 0
|
||||
/* See https://github.com/Ebiroll/qemu_esp32 for further information */
|
||||
#include "emul_ip.h"
|
||||
if (is_running_qemu()) {
|
||||
xTaskCreate(task_lwip_init, "task_lwip_init", 2*4096, NULL, 20, NULL);
|
||||
}
|
||||
else
|
||||
#endif
|
||||
/* This helper function configures Wi-Fi or Ethernet, as selected in menuconfig.
|
||||
* Read "Establishing Wi-Fi or Ethernet Connection" section in
|
||||
* examples/protocols/README.md for more information about this function.
|
||||
*/
|
||||
ESP_ERROR_CHECK(example_connect());
|
||||
|
||||
xTaskCreate(coap_example_task, "coap", 5 * 1024, NULL, 5, NULL);
|
||||
xTaskCreate(coap_example_client, "coap", 8 * 1024, NULL, 5, NULL);
|
||||
}
|
||||
|
@ -3,3 +3,8 @@
|
||||
#
|
||||
# (Uses default behaviour of compiling all source files in directory, adding 'include' to include path.)
|
||||
|
||||
# embed files from the "certs" directory as binary data symbols
|
||||
# in the app
|
||||
COMPONENT_EMBED_TXTFILES := coap_ca.pem
|
||||
COMPONENT_EMBED_TXTFILES += coap_client.crt
|
||||
COMPONENT_EMBED_TXTFILES += coap_client.key
|
||||
|
@ -2,14 +2,26 @@
|
||||
# CoAP server example
|
||||
|
||||
(See the README.md file in the upper level 'examples' directory for more information about examples.)
|
||||
This CoAP server example is adaptation of one of the [libcoap](https://github.com/obgm/libcoap) example.
|
||||
This CoAP server example is very simplified adaptation of one of the
|
||||
[libcoap](https://github.com/obgm/libcoap) examples.
|
||||
|
||||
CoAP server example would startup a daemon task, receive data from CoAP client and transmit data to CoAP client.
|
||||
CoAP server example will startup a daemon task, receive requests / data from CoAP client and transmit
|
||||
data to CoAP client.
|
||||
|
||||
The Constrained Application Protocol (CoAP) is a specialized web transfer protocol for use with constrained nodes and constrained networks in the Internet of Things.
|
||||
The protocol is designed for machine-to-machine (M2M) applications such as smart energy and building automation.
|
||||
If the incoming request requests the use of DTLS (connecting to port 5684), then the CoAP server will
|
||||
try to establish a DTLS session using the previously defined Pre-Shared Key (PSK) - which
|
||||
must be the same as the one that the CoAP client is using, or Public Key Infrastructure (PKI) where
|
||||
the PKI information must match as requested.
|
||||
|
||||
please refer to [RFC7252](https://www.rfc-editor.org/rfc/pdfrfc/rfc7252.txt.pdf) for more details.
|
||||
NOTE: Client sessions trying to use coaps+tcp:// are not currently supported, even though both
|
||||
libcoap and MbedTLS support it.
|
||||
|
||||
The Constrained Application Protocol (CoAP) is a specialized web transfer protocol for use with
|
||||
constrained nodes and constrained networks in the Internet of Things.
|
||||
The protocol is designed for machine-to-machine (M2M) applications such as smart energy and
|
||||
building automation.
|
||||
|
||||
Please refer to [RFC7252](https://www.rfc-editor.org/rfc/pdfrfc/rfc7252.txt.pdf) for more details.
|
||||
|
||||
## How to use example
|
||||
|
||||
@ -19,15 +31,29 @@ please refer to [RFC7252](https://www.rfc-editor.org/rfc/pdfrfc/rfc7252.txt.pdf)
|
||||
idf.py menuconfig
|
||||
```
|
||||
|
||||
* Set default serial port under Serial Flasher config
|
||||
* Set WiFi SSID under Example Configuration
|
||||
* Set WiFi Password under Example Configuration
|
||||
Example Connection Configuration --->
|
||||
* Set WiFi SSID under Example Configuration
|
||||
* Set WiFi Password under Example Configuration
|
||||
Example CoAP Client Configuration --->
|
||||
* Set CoAP Target Uri
|
||||
* Set encryption method definitions (None, PSK or PKI)
|
||||
* If PSK Set CoAP Preshared Key to use in connection to the server
|
||||
* If PSK Set CoAP PSK Client identity (username)
|
||||
Enable CoAP debugging if required
|
||||
Component config --->
|
||||
mbedTLS --->
|
||||
[*] Enable mbedtls certificate expiry check
|
||||
TLS Key Exchange Methods --->
|
||||
[*] Enable pre-shared-key ciphersuites
|
||||
[*] Enable PSK based ciphersuite modes
|
||||
[*] Support DTLS protocol (all versions)
|
||||
|
||||
### Build and Flash
|
||||
|
||||
Build the project and flash it to the board, then run monitor tool to view serial output:
|
||||
|
||||
```
|
||||
idf.py build
|
||||
idf.py -p PORT flash monitor
|
||||
```
|
||||
|
||||
@ -54,8 +80,8 @@ I (2622) CoAP_server: Connected to AP
|
||||
...
|
||||
```
|
||||
|
||||
if a CoAP client query `/Espressif` resource, CoAP server would return `"no data"`
|
||||
until a CoAP client does a PUT with some data.
|
||||
If a CoAP client queries the `/Espressif` resource, CoAP server will return `"Hello World!"`
|
||||
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/
|
||||
@ -64,5 +90,7 @@ This can be found at https://libcoap.net/doc/reference/4.2.0/
|
||||
* Please make sure CoAP client fetchs or puts data under path: `/Espressif` or
|
||||
fetches `/.well-known/core`
|
||||
|
||||
* libcoap logging can be increased by changing `#define COAP_LOGGING_LEVEL 0`
|
||||
to `#define COAP_LOGGING_LEVEL 9`
|
||||
* CoAP logging can be enabled by running 'make menuconfig' and enable debugging
|
||||
|
||||
* Encryption (MbedTLS) can be enabled by running 'make menuconfig' and enable debugging
|
||||
|
||||
|
@ -1,2 +1,3 @@
|
||||
idf_component_register(SRCS "coap_server_example_main.c"
|
||||
INCLUDE_DIRS ".")
|
||||
INCLUDE_DIRS "."
|
||||
EMBED_TXTFILES coap_ca.pem coap_server.crt coap_server.key)
|
||||
|
74
examples/protocols/coap_server/main/Kconfig.projbuild
Normal file
74
examples/protocols/coap_server/main/Kconfig.projbuild
Normal file
@ -0,0 +1,74 @@
|
||||
menu "Example CoAP Server Configuration"
|
||||
|
||||
config MBEDTLS_COAP_PSK
|
||||
bool "Pre-Shared Keys (PSK)"
|
||||
default n
|
||||
help
|
||||
Use Pre-Shared Keys to encrypt the communications between the
|
||||
CoAP Server and CoAP Client. Both ends need the same
|
||||
Pre-Shared Key.
|
||||
|
||||
config COAP_PSK_KEY
|
||||
string "Preshared Key (PSK) to used in the connection from the CoAP client"
|
||||
depends on MBEDTLS_COAP_PSK
|
||||
default "secret-key"
|
||||
help
|
||||
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.
|
||||
|
||||
config MBEDTLS_COAP_PKI
|
||||
bool "Public Key Infrastructure (PKI)"
|
||||
default n
|
||||
help
|
||||
Use PKI Certificates and Private Keys to encrypt the communications
|
||||
between the CoAP Server and CoAP Client.
|
||||
|
||||
config MBEDTLS_COAP_DEBUG
|
||||
bool "Enable CoAP debugging"
|
||||
default n
|
||||
help
|
||||
Enable CoAP debugging functions at compile time for the example code.
|
||||
|
||||
If this option is enabled, call coap_set_log_level()
|
||||
at runtime in order to enable CoAP debug output via the ESP
|
||||
log mechanism.
|
||||
|
||||
choice MBEDTLS_COAP_DEBUG_LEVEL
|
||||
bool "Set CoAP debugging level"
|
||||
depends on MBEDTLS_COAP_DEBUG
|
||||
default COAP_LOG_WARNING
|
||||
help
|
||||
Set CoAP debugging level
|
||||
|
||||
config COAP_LOG_EMERG
|
||||
bool "Emergency"
|
||||
config COAP_LOG_ALERT
|
||||
bool "Alert"
|
||||
config COAP_LOG_CRIT
|
||||
bool "Critical"
|
||||
config COAP_LOG_ERROR
|
||||
bool "Error"
|
||||
config COAP_LOG_WARNING
|
||||
bool "Warning"
|
||||
config COAP_LOG_NOTICE
|
||||
bool "Notice"
|
||||
config COAP_LOG_INFO
|
||||
bool "Info"
|
||||
config COAP_LOG_DEBUG
|
||||
bool "Debug"
|
||||
endchoice
|
||||
|
||||
config COAP_LOG_DEFAULT_LEVEL
|
||||
int
|
||||
default 0 if !MBEDTLS_COAP_DEBUG
|
||||
default 0 if COAP_LOG_EMERG
|
||||
default 1 if COAP_LOG_ALERT
|
||||
default 2 if COAP_LOG_CRIT
|
||||
default 3 if COAP_LOG_ERROR
|
||||
default 4 if COAP_LOG_WARNING
|
||||
default 5 if COAP_LOG_NOTICE
|
||||
default 6 if COAP_LOG_INFO
|
||||
default 7 if COAP_LOG_DEBUG
|
||||
|
||||
endmenu
|
23
examples/protocols/coap_server/main/coap_ca.pem
Normal file
23
examples/protocols/coap_server/main/coap_ca.pem
Normal file
@ -0,0 +1,23 @@
|
||||
-----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=
|
||||
-----END CERTIFICATE-----
|
70
examples/protocols/coap_server/main/coap_server.crt
Normal file
70
examples/protocols/coap_server/main/coap_server.crt
Normal file
@ -0,0 +1,70 @@
|
||||
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
|
||||
-----END CERTIFICATE-----
|
27
examples/protocols/coap_server/main/coap_server.key
Normal file
27
examples/protocols/coap_server/main/coap_server.key
Normal file
@ -0,0 +1,27 @@
|
||||
-----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-----
|
@ -7,6 +7,13 @@
|
||||
CONDITIONS OF ANY KIND, either express or implied.
|
||||
*/
|
||||
|
||||
/*
|
||||
* WARNING
|
||||
* libcoap is not multi-thread safe, so only this thread must make any coap_*()
|
||||
* calls. Any external (to this thread) data transmitted in/out via libcoap
|
||||
* therefore has to be passed in/out by xQueue*() via this thread.
|
||||
*/
|
||||
|
||||
#include <string.h>
|
||||
#include <sys/socket.h>
|
||||
|
||||
@ -22,14 +29,39 @@
|
||||
|
||||
#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"
|
||||
|
||||
/* Set this to 9 to get verbose logging from within libcoap */
|
||||
#define COAP_LOGGING_LEVEL 0
|
||||
/* The examples use simple Pre-Shared-Key configuration that you can set via
|
||||
'make 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"
|
||||
|
||||
Note: PSK will only be used if the URI is prefixed with coaps://
|
||||
instead of coap:// and the PSK must be one that the server supports
|
||||
(potentially associated with the IDENTITY)
|
||||
*/
|
||||
#define EXAMPLE_COAP_PSK_KEY CONFIG_COAP_PSK_KEY
|
||||
|
||||
/* The examples use CoAP Logging Level that
|
||||
you can set via 'make menuconfig'.
|
||||
|
||||
If you'd rather not, just change the below entry to a value
|
||||
that is between 0 and 7 with
|
||||
the config you want - ie #define EXAMPLE_COAP_LOG_DEFAULT_LEVEL 7
|
||||
*/
|
||||
#define EXAMPLE_COAP_LOG_DEFAULT_LEVEL CONFIG_COAP_LOG_DEFAULT_LEVEL
|
||||
|
||||
static char espressif_data[100];
|
||||
static int espressif_data_len = 0;
|
||||
|
||||
#define INITIAL_DATA "Hello World!"
|
||||
|
||||
/*
|
||||
* The resource handler
|
||||
*/
|
||||
@ -59,7 +91,7 @@ hnd_espressif_put(coap_context_t *ctx,
|
||||
|
||||
coap_resource_notify_observers(resource, NULL);
|
||||
|
||||
if (strcmp (espressif_data, "no data") == 0) {
|
||||
if (strcmp (espressif_data, INITIAL_DATA) == 0) {
|
||||
response->code = COAP_RESPONSE_CODE(201);
|
||||
}
|
||||
else {
|
||||
@ -70,7 +102,7 @@ hnd_espressif_put(coap_context_t *ctx,
|
||||
(void)coap_get_data(request, &size, &data);
|
||||
|
||||
if (size == 0) { /* re-init */
|
||||
snprintf(espressif_data, sizeof(espressif_data), "no data");
|
||||
snprintf(espressif_data, sizeof(espressif_data), INITIAL_DATA);
|
||||
espressif_data_len = strlen(espressif_data);
|
||||
} else {
|
||||
espressif_data_len = size > sizeof (espressif_data) ? sizeof (espressif_data) : size;
|
||||
@ -88,23 +120,50 @@ hnd_espressif_delete(coap_context_t *ctx,
|
||||
coap_pdu_t *response)
|
||||
{
|
||||
coap_resource_notify_observers(resource, NULL);
|
||||
snprintf(espressif_data, sizeof(espressif_data), "no data");
|
||||
snprintf(espressif_data, sizeof(espressif_data), INITIAL_DATA);
|
||||
espressif_data_len = strlen(espressif_data);
|
||||
response->code = COAP_RESPONSE_CODE(202);
|
||||
}
|
||||
|
||||
static void coap_example_thread(void *p)
|
||||
#ifdef CONFIG_MBEDTLS_COAP_PKI
|
||||
|
||||
#ifdef __GNUC__
|
||||
#define UNUSED_PARAM __attribute__ ((unused))
|
||||
#else /* not a GCC */
|
||||
#define UNUSED_PARAM
|
||||
#endif /* GCC */
|
||||
|
||||
#ifndef min
|
||||
#define min(a,b) ((a) < (b) ? (a) : (b))
|
||||
#endif
|
||||
|
||||
static int
|
||||
verify_cn_callback(const char *cn,
|
||||
const uint8_t *asn1_public_cert UNUSED_PARAM,
|
||||
size_t asn1_length UNUSED_PARAM,
|
||||
coap_session_t *session UNUSED_PARAM,
|
||||
unsigned depth,
|
||||
int validated UNUSED_PARAM,
|
||||
void *arg UNUSED_PARAM
|
||||
) {
|
||||
coap_log(LOG_INFO, "CN '%s' presented by server (%s)\n",
|
||||
cn, depth ? "CA" : "Certificate");
|
||||
return 1;
|
||||
}
|
||||
#endif /* CONFIG_MBEDTLS_COAP_PKI */
|
||||
|
||||
static void coap_example_server(void *p)
|
||||
{
|
||||
coap_context_t *ctx = NULL;
|
||||
coap_address_t serv_addr;
|
||||
coap_address_t serv_addr;
|
||||
coap_resource_t *resource = NULL;
|
||||
|
||||
snprintf(espressif_data, sizeof(espressif_data), "no data");
|
||||
snprintf(espressif_data, sizeof(espressif_data), INITIAL_DATA);
|
||||
espressif_data_len = strlen(espressif_data);
|
||||
coap_set_log_level(COAP_LOGGING_LEVEL);
|
||||
coap_set_log_level(EXAMPLE_COAP_LOG_DEFAULT_LEVEL);
|
||||
|
||||
while (1) {
|
||||
coap_endpoint_t *ep_udp = NULL;
|
||||
coap_endpoint_t *ep_tcp = NULL;
|
||||
coap_endpoint_t *ep = NULL;
|
||||
unsigned wait_ms;
|
||||
|
||||
/* Prepare the CoAP server socket */
|
||||
@ -117,14 +176,91 @@ static void coap_example_thread(void *p)
|
||||
if (!ctx) {
|
||||
continue;
|
||||
}
|
||||
ep_udp = coap_new_endpoint(ctx, &serv_addr, COAP_PROTO_UDP);
|
||||
if (!ep_udp) {
|
||||
#ifdef CONFIG_MBEDTLS_COAP_PSK
|
||||
/* Need PSK setup before we set up endpoints */
|
||||
coap_context_set_psk(ctx, "CoAP",
|
||||
(const uint8_t*)EXAMPLE_COAP_PSK_KEY,
|
||||
sizeof(EXAMPLE_COAP_PSK_KEY)-1);
|
||||
#endif /* CONFIG_MBEDTLS_COAP_PSK */
|
||||
|
||||
#ifdef CONFIG_MBEDTLS_COAP_PKI
|
||||
/* CA cert, taken from coap_ca.pem
|
||||
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.
|
||||
|
||||
To embed it in the app binary, the PEM, CRT and KEY file is named
|
||||
in the component.mk COMPONENT_EMBED_TXTFILES variable.
|
||||
*/
|
||||
extern uint8_t ca_pem_start[] asm("_binary_coap_ca_pem_start");
|
||||
extern uint8_t ca_pem_end[] asm("_binary_coap_ca_pem_end");
|
||||
extern uint8_t server_crt_start[] asm("_binary_coap_server_crt_start");
|
||||
extern uint8_t server_crt_end[] asm("_binary_coap_server_crt_end");
|
||||
extern uint8_t server_key_start[] asm("_binary_coap_server_key_start");
|
||||
extern uint8_t server_key_end[] asm("_binary_coap_server_key_end");
|
||||
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;
|
||||
coap_dtls_pki_t dtls_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 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;
|
||||
}
|
||||
dtls_pki.pki_key.key_type = COAP_PKI_KEY_PEM_BUF;
|
||||
dtls_pki.pki_key.key.pem_buf.public_cert = server_crt_start;
|
||||
dtls_pki.pki_key.key.pem_buf.public_cert_len = server_crt_bytes;
|
||||
dtls_pki.pki_key.key.pem_buf.private_key = server_key_start;
|
||||
dtls_pki.pki_key.key.pem_buf.private_key_len = server_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_context_set_pki(ctx, &dtls_pki);
|
||||
#endif /* CONFIG_MBEDTLS_COAP_PKI */
|
||||
|
||||
ep = coap_new_endpoint(ctx, &serv_addr, COAP_PROTO_UDP);
|
||||
if (!ep) {
|
||||
goto clean_up;
|
||||
}
|
||||
ep_tcp = coap_new_endpoint(ctx, &serv_addr, COAP_PROTO_TCP);
|
||||
if (!ep_tcp) {
|
||||
ep = coap_new_endpoint(ctx, &serv_addr, COAP_PROTO_TCP);
|
||||
if (!ep) {
|
||||
goto clean_up;
|
||||
}
|
||||
#if defined(CONFIG_MBEDTLS_COAP_PSK) || defined(CONFIG_MBEDTLS_COAP_PKI)
|
||||
if (coap_dtls_is_supported()) {
|
||||
serv_addr.addr.sin.sin_port = htons(COAPS_DEFAULT_PORT);
|
||||
ep = coap_new_endpoint(ctx, &serv_addr, COAP_PROTO_DTLS);
|
||||
if (!ep) {
|
||||
goto clean_up;
|
||||
}
|
||||
}
|
||||
#endif /* CONFIG_MBEDTLS_COAP_PSK CONFIG_MBEDTLS_COAP_PKI */
|
||||
resource = coap_resource_init(coap_make_str_const("Espressif"), 0);
|
||||
if (!resource) {
|
||||
goto clean_up;
|
||||
@ -165,11 +301,19 @@ void app_main(void)
|
||||
tcpip_adapter_init();
|
||||
ESP_ERROR_CHECK(esp_event_loop_create_default());
|
||||
|
||||
#if 0
|
||||
/* See https://github.com/Ebiroll/qemu_esp32 for further information */
|
||||
#include "emul_ip.h"
|
||||
if (is_running_qemu()) {
|
||||
xTaskCreate(task_lwip_init, "task_lwip_init", 2*4096, NULL, 20, NULL);
|
||||
}
|
||||
else
|
||||
#endif
|
||||
/* This helper function configures Wi-Fi or Ethernet, as selected in menuconfig.
|
||||
* Read "Establishing Wi-Fi or Ethernet Connection" section in
|
||||
* examples/protocols/README.md for more information about this function.
|
||||
*/
|
||||
ESP_ERROR_CHECK(example_connect());
|
||||
|
||||
xTaskCreate(coap_example_thread, "coap", 1024 * 5, NULL, 5, NULL);
|
||||
xTaskCreate(coap_example_server, "coap", 8 * 1024, NULL, 5, NULL);
|
||||
}
|
||||
|
@ -3,3 +3,8 @@
|
||||
#
|
||||
# (Uses default behaviour of compiling all source files in directory, adding 'include' to include path.)
|
||||
|
||||
# embed files from the "certs" directory as binary data symbols
|
||||
# in the app
|
||||
COMPONENT_EMBED_TXTFILES := coap_ca.pem
|
||||
COMPONENT_EMBED_TXTFILES += coap_server.crt
|
||||
COMPONENT_EMBED_TXTFILES += coap_server.key
|
||||
|
Loading…
x
Reference in New Issue
Block a user