20#if COAP_WITH_LIBTINYDTLS
23#undef PACKAGE_BUGREPORT
31#include <tinydtls/tinydtls.h>
32#include <tinydtls/dtls.h>
33#include <tinydtls/dtls_debug.h>
34#include <tinydtls/dtls_time.h>
38#include <dtls_debug.h>
42typedef struct coap_tiny_context_t {
43 struct dtls_context_t *dtls_context;
50#if (DTLS_MAX_CID_LENGTH > 0)
55#if ! defined(DTLS_PSK) && ! defined(DTLS_ECC)
56#error Neither DTLS_PSK or DTLS_ECC defined
59static dtls_tick_t dtls_tick_0 = 0;
117#if (DTLS_MAX_CID_LENGTH > 0)
124#if COAP_CLIENT_SUPPORT
131#if (DTLS_MAX_CID_LENGTH > 0)
132 c_context->testing_cids = every;
143dtls_map_logging(log_t d_level) {
158 case DTLS_LOG_NOTICE:
171#ifdef HAVE_DTLS_SET_LOG_HANDLER
174dtls_logging(log_t d_level,
const char *message) {
175 coap_log_t c_level = dtls_map_logging(d_level);
184 dtls_ticks(&dtls_tick_0);
186#ifdef HAVE_DTLS_SET_LOG_HANDLER
188 dtls_set_log_handler(dtls_logging);
208 const coap_tiny_context_t *t_context =
211 return t_context->dtls_context;
223 d_level = DTLS_LOG_EMERG;
226 d_level = DTLS_LOG_ALERT;
230 d_level = DTLS_LOG_CRIT;
233 d_level = DTLS_LOG_WARN;
236 d_level = DTLS_LOG_NOTICE;
239 d_level = DTLS_LOG_INFO;
245 d_level = DTLS_LOG_DEBUG;
248 dtls_set_log_level(d_level);
253 log_t d_level = dtls_get_log_level();
255 return dtls_map_logging(d_level);
261#if defined(WITH_CONTIKI) || defined(WITH_LWIP)
263 switch (s->addr.sa.sa_family) {
266 memcpy(&a->
addr, &s->
addr.
sin.sin_addr,
sizeof(s->addr.sin.sin_addr));
267 a->port = s->
addr.
sin.sin_port;
272 memcpy(&a->
addr, &s->
addr.
sin6.sin6_addr,
sizeof(s->addr.sin6.sin6_addr));
283#elif defined(WITH_RIOT_SOCK)
285 if (s->addr.family == AF_INET6) {
286 a->riot.family = s->
addr.family;
287 memcpy(&a->riot.
addr.ipv6, &s->
addr.ipv6,
288 sizeof(a->riot.
addr.ipv6));
289 a->riot.port = ntohs(s->addr.port);
294 if (s->addr.family == AF_INET) {
295 a->riot.family = s->
addr.family;
296 memcpy(&a->riot.
addr.ipv4, &s->
addr.ipv4,
sizeof(a->riot.
addr.ipv4));
297 a->riot.port = ntohs(s->addr.port);
302 if (s->addr.sa.sa_family == AF_INET6) {
305 }
else if (s->addr.sa.sa_family == AF_INET) {
308#if COAP_AF_UNIX_SUPPORT
309 }
else if (s->addr.sa.sa_family == AF_UNIX) {
316 a->
size = (socklen_t)s->size;
324#if defined(WITH_CONTIKI) || defined(WITH_LWIP)
326#if LWIP_IPV6 && LWIP_IPV4
327 if (a->
addr.type == IPADDR_TYPE_V6) {
328 s->addr.sa.sa_family = AF_INET6;
329 s->size = (socklen_t)
sizeof(s->addr.sin6);
330 memcpy(&s->addr.sin6.sin6_addr, &a->
addr,
sizeof(s->addr.sin6.sin6_addr));
331 s->addr.sin6.sin6_port = a->port;
332 }
else if (a->
addr.type == IPADDR_TYPE_V4) {
333 s->addr.sa.sa_family = AF_INET;
334 s->size = (socklen_t)
sizeof(s->addr.sin);
335 memcpy(&s->addr.sin.sin_addr, &a->
addr,
sizeof(s->addr.sin.sin_addr));
336 s->addr.sin.sin_port = a->port;
339 s->
addr.
sa.sa_family = AF_INET;
340 s->size = (socklen_t)
sizeof(s->addr.sin);
341 memcpy(&s->addr.sin.sin_addr, &a->
addr,
sizeof(s->addr.sin.sin_addr));
342 s->addr.sin.sin_port = a->port;
344 s->
addr.
sa.sa_family = AF_INET6;
345 s->size = (socklen_t)
sizeof(s->addr.sin6);
346 memcpy(&s->addr.sin6.sin6_addr, &a->
addr,
sizeof(s->addr.sin6.sin6_addr));
347 s->addr.sin6.sin6_port = a->port;
351 s->
size = (
unsigned char)
sizeof(s->addr);
355#elif defined(WITH_RIOT_SOCK)
357 if (a->riot.family == AF_INET6) {
358 s->size =
sizeof(s->addr.ipv6);
359 s->addr.family = a->riot.family;
360 memcpy(&s->addr.ipv6, &a->riot.
addr.ipv6,
361 sizeof(s->addr.ipv6));
362 s->addr.port = htons(a->riot.port);
366 if (a->riot.family == AF_INET) {
367 s->size =
sizeof(s->addr.ipv4);
368 s->addr.family = a->riot.family;
369 memcpy(&s->addr.ipv4, &a->riot.
addr.ipv4,
sizeof(s->addr.ipv4));
370 s->addr.port = htons(a->riot.port);
374 if (a->
addr.
sa.sa_family == AF_INET6) {
375 s->size = (socklen_t)
sizeof(s->addr.sin6);
377 }
else if (a->
addr.
sa.sa_family == AF_INET) {
378 s->size = (socklen_t)
sizeof(s->addr.sin);
380#if COAP_AF_UNIX_SUPPORT
381 }
else if (a->
addr.
sa.sa_family == AF_UNIX) {
387 s->size = (socklen_t)a->
size;
394dtls_send_to_peer(
struct dtls_context_t *dtls_context,
395 session_t *dtls_session, uint8 *data,
size_t len) {
396 coap_tiny_context_t *t_context =
397 (coap_tiny_context_t *)dtls_get_app_data(dtls_context);
403 assert(coap_context);
404 get_session_addr(dtls_session, &remote_addr);
407 coap_log_warn(
"dtls_send_to_peer: cannot find local interface\n");
411 if (ret == -1 && (errno == ENOTCONN || errno == ECONNREFUSED))
417dtls_application_data(
struct dtls_context_t *dtls_context,
418 session_t *dtls_session, uint8 *data,
size_t len) {
419 coap_tiny_context_t *t_context =
420 (coap_tiny_context_t *)dtls_get_app_data(dtls_context);
425 assert(coap_context);
426 get_session_addr(dtls_session, &remote_addr);
429 coap_log_debug(
"dropped message that was received on invalid interface\n");
438static int coap_event_dtls = 0;
441dtls_event(
struct dtls_context_t *dtls_context,
442 session_t *dtls_session,
443 dtls_alert_level_t level,
444 unsigned short code) {
448 if (level == DTLS_ALERT_LEVEL_FATAL)
453 case DTLS_ALERT_CLOSE_NOTIFY: {
457 case DTLS_EVENT_CONNECTED: {
461#ifdef DTLS_EVENT_RENEGOTIATE
462 case DTLS_EVENT_RENEGOTIATE: {
479get_psk_info(
struct dtls_context_t *dtls_context,
480 const session_t *dtls_session,
481 dtls_credentials_type_t type,
482 const uint8_t *
id,
size_t id_len,
483 unsigned char *result,
size_t result_length) {
485 coap_tiny_context_t *t_context =
486 (coap_tiny_context_t *)dtls_get_app_data(dtls_context);
489 int fatal_error = DTLS_ALERT_INTERNAL_ERROR;
491#if COAP_CLIENT_SUPPORT
497#if COAP_SERVER_SUPPORT
502 assert(coap_context);
503 get_session_addr(dtls_session, &remote_addr);
511 case DTLS_PSK_IDENTITY:
513#if COAP_CLIENT_SUPPORT
525 id ? (
const char *)
id :
"");
537 psk_identity = &cpsk_info->
identity;
546 if (psk_identity ==
NULL) {
548 fatal_error = DTLS_ALERT_CLOSE_NOTIFY;
551 if (psk_identity->
length > result_length) {
556 result_length = psk_identity->
length;
558 memcpy(result, psk_identity->
s, result_length);
559 return result_length;
565#if COAP_CLIENT_SUPPORT
568 if (psk_key ==
NULL) {
570 fatal_error = DTLS_ALERT_CLOSE_NOTIFY;
573 if (psk_key->
length > result_length) {
578 result_length = psk_key->
length;
580 memcpy(result, psk_key->
s, result_length);
581 return result_length;
584#if COAP_SERVER_SUPPORT
588 lidentity.
length =
id ? id_len : 0;
589 lidentity.
s =
id ? (
const uint8_t *)
id : (const uint8_t *)
"";
590 setup_sdata = &coap_session->
context->spsk_setup_data;
596 (
int)lidentity.
length, lidentity.
s);
607 if (psk_key ==
NULL) {
613 if (psk_key->
length > result_length) {
618 result_length = psk_key->
length;
620 memcpy(result, psk_key->
s, result_length);
621 return result_length;
627#if COAP_SERVER_SUPPORT
629 if (psk_hint ==
NULL)
631 if (psk_hint->
length > result_length) {
636 result_length = psk_hint->
length;
638 memcpy(result, psk_hint->
s, result_length);
639 return result_length;
649 return dtls_alert_fatal_create(fatal_error);
654dtls_update_user_parameters(
struct dtls_context_t *ctx,
655 session_t *session, dtls_user_parameters_t *user_parameters) {
658#if (DTLS_MAX_CID_LENGTH > 0)
659 coap_tiny_context_t *t_context =
660 (coap_tiny_context_t *)dtls_get_app_data(ctx);
661 user_parameters->support_cid = t_context ? t_context->use_cid : 0;
663 (void)user_parameters;
669get_ecdsa_key(
struct dtls_context_t *dtls_context,
671 const dtls_ecdsa_key_t **result) {
672 static dtls_ecdsa_key_t ecdsa_key;
673 coap_tiny_context_t *t_context =
674 (coap_tiny_context_t *)dtls_get_app_data(dtls_context);
676 ecdsa_key.curve = DTLS_ECDH_CURVE_SECP256R1;
677 ecdsa_key.priv_key = t_context->priv_key->s;
678 ecdsa_key.pub_key_x = t_context->pub_key->s;
679 ecdsa_key.pub_key_y = &t_context->pub_key->s[DTLS_EC_KEY_SIZE];
681 *result = &ecdsa_key;
686static const unsigned char cert_asn1_header[] = {
690 0x2A, 0x86, 0x48, 0xCE, 0x3D, 0x02, 0x01,
692 0x2A, 0x86, 0x48, 0xCE, 0x3D, 0x03, 0x01, 0x07,
696#define DTLS_CE_LENGTH (sizeof(cert_asn1_header) + key_size + key_size)
699verify_ecdsa_key(
struct dtls_context_t *dtls_context
COAP_UNUSED,
701 const uint8_t *other_pub_x,
702 const uint8_t *other_pub_y,
704 coap_tiny_context_t *t_context =
705 (coap_tiny_context_t *)dtls_get_app_data(dtls_context);
708 if (t_context && t_context->setup_data.validate_cn_call_back) {
710 get_session_addr(dtls_session, &remote_addr);
712 &remote_addr, dtls_session->ifindex);
725 memcpy(p, &cert_asn1_header,
sizeof(cert_asn1_header));
726 p +=
sizeof(cert_asn1_header);
728 memcpy(p, other_pub_x, key_size);
731 memcpy(p, other_pub_y, key_size);
736 buf, p-buf, c_session, 0, 1, t_context->setup_data.cn_call_back_arg));
745static dtls_handler_t ec_cb = {
746 .write = dtls_send_to_peer,
747 .read = dtls_application_data,
748 .get_user_parameters = dtls_update_user_parameters,
751 .get_psk_info =
NULL,
753 .get_ecdsa_key = get_ecdsa_key,
754 .verify_ecdsa_key = verify_ecdsa_key
758static dtls_handler_t psk_cb = {
759 .write = dtls_send_to_peer,
760 .read = dtls_application_data,
761 .get_user_parameters = dtls_update_user_parameters,
764 .get_psk_info = get_psk_info,
767 .get_ecdsa_key =
NULL,
768 .verify_ecdsa_key =
NULL
775 struct dtls_context_t *dtls_context = t_context ? dtls_new_context(t_context) :
NULL;
778 memset(t_context, 0,
sizeof(coap_tiny_context_t));
779 t_context->coap_context = coap_context;
780 t_context->dtls_context = dtls_context;
781 dtls_set_handler(dtls_context, &psk_cb);
794 coap_tiny_context_t *t_context = (coap_tiny_context_t *)handle;
796 if (t_context->priv_key) {
798 t_context->priv_key =
NULL;
800 if (t_context->pub_key) {
802 t_context->pub_key =
NULL;
805 if (t_context->dtls_context)
806 dtls_free_context(t_context->dtls_context);
818 dtls_session_init(dtls_session);
820 dtls_session->ifindex = session->
ifindex;
827#if COAP_SERVER_SUPPORT
830 return coap_dtls_new_session(session);
834#if COAP_CLIENT_SUPPORT
839 dtls_context_t *dtls_context = t_context ? t_context->dtls_context :
NULL;
841 session_t *dtls_session = dtls_context ? !is_af_unix ? coap_dtls_new_session(session) :
NULL :
NULL;
846 dtls_get_peer(dtls_context, dtls_session);
852 if (dtls_connect(dtls_context, dtls_session) >= 0) {
854 dtls_get_peer(dtls_context, dtls_session);
875 coap_tiny_context_t *t_context =
877 dtls_context_t *dtls_context = t_context ? t_context->dtls_context :
NULL;
879 if (dtls_context ==
NULL)
881 if (coap_session->
tls && dtls_context) {
882 dtls_peer_t *peer = dtls_get_peer(dtls_context, (session_t *)coap_session->
tls);
884 dtls_reset_peer(dtls_context, peer);
886 dtls_close(dtls_context, (session_t *)coap_session->
tls);
901 dtls_context_t *dtls_context = t_context ? t_context->dtls_context :
NULL;
903 if (!dtls_context || !session->
tls) {
908 coap_event_dtls = -1;
912 memcpy(&data_rw, &data,
sizeof(data_rw));
913 res = dtls_write(dtls_context,
914 (session_t *)session->
tls, data_rw, data_len);
919 if (coap_event_dtls >= 0) {
922#if (DTLS_MAX_CID_LENGTH > 0) && COAP_CLIENT_SUPPORT
924 dtls_peer_t *peer = dtls_get_peer(dtls_context, (session_t *)session->
tls);
925 dtls_security_parameters_t *security = dtls_security_params(peer);
927 if (security->write_cid_length > 0) {
928 session->negotiated_cid = 1;
931 session->negotiated_cid = 0;
951 clock_time_t next = 0;
952 coap_tiny_context_t *t_context = (coap_tiny_context_t *)tiny_context;
953 dtls_context_t *dtls_context = t_context ? t_context->dtls_context :
NULL;
955 dtls_check_retransmit(dtls_context, &next);
984 session_t *dtls_session = (session_t *)session->
tls;
988 dtls_context_t *dtls_context = t_context ? t_context->dtls_context :
NULL;
990 if (!dtls_context || !dtls_session) {
994 coap_event_dtls = -1;
996 memcpy(&data_rw, &data,
sizeof(data_rw));
997 err = dtls_handle_message(dtls_context, dtls_session, data_rw, (
int)data_len);
1003 if (coap_event_dtls >= 0) {
1007#if (DTLS_MAX_CID_LENGTH > 0) && COAP_CLIENT_SUPPORT
1009 dtls_peer_t *peer = dtls_get_peer(dtls_context, (session_t *)session->
tls);
1010 dtls_security_parameters_t *security = dtls_security_params(peer);
1012 if (security->write_cid_length > 0) {
1013 session->negotiated_cid = 1;
1015 session->negotiated_cid = 0;
1028#if COAP_SERVER_SUPPORT
1031 const uint8_t *data,
1034 session_t dtls_session;
1036 dtls_context_t *dtls_context = t_context ? t_context->dtls_context :
NULL;
1039 assert(dtls_context);
1040 dtls_session_init(&dtls_session);
1042 dtls_session.ifindex = session->
ifindex;
1044 memcpy(&data_rw, &data,
sizeof(data_rw));
1045 int res = dtls_handle_message(dtls_context, &dtls_session,
1046 data_rw, (
int)data_len);
1048 if (dtls_get_peer(dtls_context, &dtls_session))
1071 const char *vers = dtls_package_version();
1075 long int p1, p2 = 0, p3 = 0;
1078 p1 = strtol(vers, &endptr, 10);
1079 if (*endptr ==
'.') {
1080 p2 = strtol(endptr+1, &endptr, 10);
1081 if (*endptr ==
'.') {
1082 p3 = strtol(endptr+1, &endptr, 10);
1085 version.
version = (p1 << 16) | (p2 << 8) | p3;
1093static const uint8_t b64_6[256] = {
1094 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64,
1095 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64,
1097 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 62, 64, 64, 64, 63,
1099 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 64, 64, 64, 64, 64, 64,
1101 64, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14,
1103 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 64, 64, 64, 64, 64,
1105 64, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40,
1107 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 64, 64, 64, 64, 64,
1108 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64,
1109 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64,
1110 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64,
1111 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64,
1112 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64,
1113 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64,
1114 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64,
1115 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64
1120pem_base64_decode(
const uint8_t *data,
size_t size) {
1122 size_t nbytesdecoded;
1127 size_t nb64bytes = 0;
1129 for (i = 0; i < size; i++) {
1137 if (b64_6[data[i]] == 64)
1139 tbuf[nb64bytes++] = data[i];
1145 nbytesdecoded = ((nb64bytes + 3) / 4) * 3;
1153 while (nb64bytes > 4) {
1154 *(out++) = b64_6[ptr[0]] << 2 | b64_6[ptr[1]] >> 4;
1155 *(out++) = b64_6[ptr[1]] << 4 | b64_6[ptr[2]] >> 2;
1156 *(out++) = b64_6[ptr[2]] << 6 | b64_6[ptr[3]];
1162 if (nb64bytes > 1) {
1163 *(out++) = b64_6[ptr[0]] << 2 | b64_6[ptr[1]] >> 4;
1165 if (nb64bytes > 2) {
1166 *(out++) = b64_6[ptr[1]] << 4 | b64_6[ptr[2]] >> 2;
1168 if (nb64bytes > 3) {
1169 *(out++) = b64_6[ptr[2]] << 6 | b64_6[ptr[3]];
1172 decoded->
length = nbytesdecoded - ((4 - nb64bytes) & 3);
1177typedef coap_binary_t *(*asn1_callback)(
const uint8_t *data,
size_t size);
1180asn1_verify_privkey(
const uint8_t *data,
size_t size) {
1183 if (size - 1 == DTLS_EC_KEY_SIZE && *data ==
'\000') {
1189 if (size != DTLS_EC_KEY_SIZE)
1196asn1_verify_pubkey(
const uint8_t *data,
size_t size) {
1201 if (size - 2 != 2 * DTLS_EC_KEY_SIZE)
1208asn1_verify_curve(
const uint8_t *data,
size_t size) {
1209 static uint8_t prime256v1_oid[] =
1211 { 0x2a, 0x86, 0x48, 0xce, 0x3d, 0x03, 0x01, 0x07 };
1214 if (size !=
sizeof(prime256v1_oid) ||
1215 memcmp(data, prime256v1_oid, size) != 0)
1222asn1_verify_pkcs8_version(
const uint8_t *data,
size_t size) {
1224 if (size != 1 || *data != 0)
1231asn1_verify_ec_identifier(
const uint8_t *data,
size_t size) {
1232 static uint8_t ec_public_key_oid[] =
1234 { 0x2a, 0x86, 0x48, 0xce, 0x3d, 0x02, 0x01 };
1237 if (size !=
sizeof(ec_public_key_oid) ||
1238 memcmp(data, ec_public_key_oid, size) != 0)
1245asn1_verify_ec_key(
const uint8_t *data,
size_t size) {
1255asn1_derive_keys(coap_tiny_context_t *t_context,
1256 const uint8_t *priv_data,
size_t priv_len,
1257 const uint8_t *pub_data,
size_t pub_len,
1262 priv_len, asn1_verify_privkey);
1263 if (!t_context->priv_key) {
1268 if (t_context->priv_key->length - 1 == DTLS_EC_KEY_SIZE &&
1269 t_context->priv_key->s[0] ==
'\000') {
1270 t_context->priv_key->length--;
1271 t_context->priv_key->s++;
1279 coap_log_info(
"EC Private Key (RPK) invalid elliptic curve\n");
1281 t_context->priv_key =
NULL;
1288 asn1_verify_pubkey);
1289 if (!t_context->pub_key) {
1292 t_context->priv_key =
NULL;
1296 t_context->pub_key->s += 2;
1297 t_context->pub_key->length -= 2;
1298 dtls_set_handler(t_context->dtls_context, &ec_cb);
1303ec_abstract_pkcs8_asn1(
const uint8_t *asn1_ptr,
size_t asn1_length) {
1307 asn1_verify_pkcs8_version);
1314 asn1_verify_ec_identifier);
1322 coap_log_info(
"EC Private Key (RPK) invalid elliptic curve\n");
1328 asn1_verify_ec_key);
1333pem_decode_mem_asn1(
const char *begstr,
const uint8_t *str) {
1334 char *bcp = str ? strstr((
const char *)str, begstr) :
NULL;
1335 char *tcp = bcp ? strstr(bcp,
"-----END ") :
NULL;
1338 bcp += strlen(begstr);
1339 return pem_base64_decode((
const uint8_t *)bcp, tcp - bcp);
1351 coap_tiny_context_t *t_context;
1368 if (t_context->priv_key) {
1370 t_context->priv_key =
NULL;
1372 if (t_context->pub_key) {
1374 t_context->pub_key =
NULL;
1376 t_context->setup_data = *setup_data;
1391 asn1_priv = pem_decode_mem_asn1(
"-----BEGIN EC PRIVATE KEY-----",
1394 asn1_priv = pem_decode_mem_asn1(
"-----BEGIN PRIVATE KEY-----",
1401 asn1_temp = ec_abstract_pkcs8_asn1(asn1_priv->
s, asn1_priv->
length);
1403 coap_log_info(
"*** setup_pki: (D)TLS: PKCS#8 Private Key (RPK) invalid\n");
1410 asn1_priv = asn1_temp;
1413 asn1_pub = pem_decode_mem_asn1(
"-----BEGIN PUBLIC KEY-----",
1416 asn1_pub = pem_decode_mem_asn1(
"-----BEGIN EC PRIVATE KEY-----",
1419 asn1_pub = pem_decode_mem_asn1(
"-----BEGIN PRIVATE KEY-----",
1422 coap_log_info(
"*** setup_pki: (D)TLS: Public Key (RPK) invalid\n");
1428 asn1_temp = ec_abstract_pkcs8_asn1(asn1_pub->
s, asn1_pub->
length);
1430 coap_log_info(
"*** setup_pki: (D)TLS: PKCS#8 Private Key (RPK) invalid\n");
1438 asn1_pub = asn1_temp;
1442 if (!asn1_derive_keys(t_context, asn1_priv->
s, asn1_priv->
length,
1443 asn1_pub->
s, asn1_pub->
length, is_pkcs8)) {
1444 coap_log_info(
"*** setup_pki: (D)TLS: Unable to derive Public/Private Keys\n");
1463 private_key = asn1_temp->
s;
1464 private_key_len = asn1_temp->
length;
1470 if (!asn1_derive_keys(t_context,
1476 coap_log_info(
"*** setup_pki: (D)TLS: Unable to derive Public/Private Keys\n");
1481 if (!asn1_derive_keys(t_context,
1487 coap_log_info(
"*** setup_pki: (D)TLS: Unable to derive Public/Private Keys\n");
1564#if (DTLS_MAX_CID_LENGTH == 0)
1568#if (DTLS_MAX_CID_LENGTH > 0)
1569 t_context->use_cid = setup_data->
use_cid;
1595#if COAP_CLIENT_SUPPORT
1599 coap_tiny_context_t *t_context;
1604 t_context = (coap_tiny_context_t *)coap_context->
dtls_context;
1609#if (DTLS_MAX_CID_LENGTH == 0)
1613#if (DTLS_MAX_CID_LENGTH > 0)
1614 t_context->use_cid = setup_data->
use_cid;
1628#if COAP_SERVER_SUPPORT
1638 coap_log_warn(
"CoAP Server with TinyDTLS does not support SNI selection\n");
1657#if !COAP_DISABLE_TCP
1658#if COAP_CLIENT_SUPPORT
1665#if COAP_SERVER_SUPPORT
1703#if COAP_SERVER_SUPPORT
1705coap_digest_setup(
void) {
1709 dtls_sha256_init(digest_ctx);
1716coap_digest_free(coap_digest_ctx_t *digest_ctx) {
1721coap_digest_update(coap_digest_ctx_t *digest_ctx,
1722 const uint8_t *data,
1724 dtls_sha256_update(digest_ctx, data, data_len);
1730coap_digest_final(coap_digest_ctx_t *digest_ctx,
1731 coap_digest_t *digest_buffer) {
1732 dtls_sha256_final((uint8_t *)digest_buffer, digest_ctx);
1734 coap_digest_free(digest_ctx);
1764#if COAP_OSCORE_SUPPORT
1776static struct cipher_algs {
1778 uint32_t cipher_type;
1787 for (idx = 0; idx <
sizeof(ciphers)/
sizeof(
struct cipher_algs); idx++) {
1788 if (ciphers[idx].alg == alg)
1789 return ciphers[idx].cipher_type;
1791 coap_log_debug(
"get_cipher_alg: COSE cipher %d not supported\n", alg);
1800static struct hmac_algs {
1811 for (idx = 0; idx <
sizeof(hmacs)/
sizeof(
struct hmac_algs); idx++) {
1812 if (hmacs[idx].hmac_alg == hmac_alg)
1813 return hmacs[idx].hmac_type;
1815 coap_log_debug(
"get_hmac_alg: COSE HMAC %d not supported\n", hmac_alg);
1821 return get_cipher_alg(alg);
1830 return get_hmac_alg(hmac_alg);
1837 uint8_t *result,
size_t *max_result_len) {
1840 dtls_ccm_params_t dtls_params;
1848 if (get_cipher_alg(params->
alg) == 0) {
1849 coap_log_debug(
"coap_crypto_encrypt: algorithm %d not supported\n",
1861 dtls_params.tag_length = ccm->
tag_len;
1862 dtls_params.l = ccm->
l;
1871 num_bytes = dtls_encrypt_params(&dtls_params,
1876 if (num_bytes < 0) {
1879 *max_result_len = num_bytes;
1887 uint8_t *result,
size_t *max_result_len) {
1890 dtls_ccm_params_t dtls_params;
1898 if (get_cipher_alg(params->
alg) == 0) {
1899 coap_log_debug(
"coap_crypto_decrypt: algorithm %d not supported\n",
1912 dtls_params.tag_length = ccm->
tag_len;
1913 dtls_params.l = ccm->
l;
1922 num_bytes = dtls_decrypt_params(&dtls_params,
1927 if (num_bytes < 0) {
1930 *max_result_len = num_bytes;
1937 dtls_hmac_context_t hmac_context;
1944 if (get_hmac_alg(hmac_alg) == 0) {
1945 coap_log_debug(
"coap_crypto_hmac: algorithm %d not supported\n", hmac_alg);
1953 dtls_hmac_init(&hmac_context, key->
s, key->
length);
1954 dtls_hmac_update(&hmac_context, data->
s, data->
length);
1955 num_bytes = dtls_hmac_finalize(&hmac_context,
dummy->s);
1957 if (num_bytes != DTLS_SHA256_DIGEST_LENGTH) {
1973#pragma GCC diagnostic ignored "-Wunused-function"
int coap_is_af_unix(const coap_address_t *a)
Checks if given address a denotes a AF_UNIX address.
void coap_address_init(coap_address_t *addr)
Resets the given coap_address_t object addr to its default values.
struct coap_context_t coap_context_t
Library specific build wrapper for coap_internal.h.
void * coap_malloc_type(coap_memory_tag_t type, size_t size)
Allocates a chunk of size bytes and returns a pointer to the newly allocated memory.
void coap_free_type(coap_memory_tag_t type, void *p)
Releases the memory that was allocated by coap_malloc_type().
int coap_dtls_context_set_pki(coap_context_t *ctx COAP_UNUSED, const coap_dtls_pki_t *setup_data COAP_UNUSED, const coap_dtls_role_t role COAP_UNUSED)
coap_tick_t coap_dtls_get_timeout(coap_session_t *session COAP_UNUSED, coap_tick_t now COAP_UNUSED)
ssize_t coap_tls_read(coap_session_t *session COAP_UNUSED, uint8_t *data COAP_UNUSED, size_t data_len COAP_UNUSED)
coap_tick_t coap_dtls_get_context_timeout(void *dtls_context COAP_UNUSED)
int coap_dtls_receive(coap_session_t *session COAP_UNUSED, const uint8_t *data COAP_UNUSED, size_t data_len COAP_UNUSED)
void * coap_dtls_get_tls(const coap_session_t *c_session COAP_UNUSED, coap_tls_library_t *tls_lib)
unsigned int coap_dtls_get_overhead(coap_session_t *session COAP_UNUSED)
int coap_dtls_context_load_pki_trust_store(coap_context_t *ctx COAP_UNUSED)
int coap_dtls_context_check_keys_enabled(coap_context_t *ctx COAP_UNUSED)
ssize_t coap_dtls_send(coap_session_t *session COAP_UNUSED, const uint8_t *data COAP_UNUSED, size_t data_len COAP_UNUSED)
ssize_t coap_tls_write(coap_session_t *session COAP_UNUSED, const uint8_t *data COAP_UNUSED, size_t data_len COAP_UNUSED)
void coap_dtls_session_update_mtu(coap_session_t *session COAP_UNUSED)
int coap_dtls_context_set_pki_root_cas(coap_context_t *ctx COAP_UNUSED, const char *ca_file COAP_UNUSED, const char *ca_path COAP_UNUSED)
int coap_dtls_handle_timeout(coap_session_t *session COAP_UNUSED)
void coap_dtls_free_context(void *handle COAP_UNUSED)
void coap_dtls_free_session(coap_session_t *coap_session COAP_UNUSED)
void * coap_dtls_new_context(coap_context_t *coap_context COAP_UNUSED)
void coap_tls_free_session(coap_session_t *coap_session COAP_UNUSED)
int SHA1Reset(SHA1Context *context)
int SHA1Input(SHA1Context *context, const uint8_t *message_array, unsigned length)
int SHA1Result(SHA1Context *context, uint8_t Message_Digest[SHA1HashSize])
coap_binary_t * get_asn1_tag(coap_asn1_tag_t ltag, const uint8_t *ptr, size_t tlen, asn1_validate validate)
Get the asn1 tag and data from the current ptr.
uint64_t coap_tick_t
This data type represents internal timer ticks with COAP_TICKS_PER_SECOND resolution.
#define COAP_TICKS_PER_SECOND
Use ms resolution on POSIX systems.
int coap_handle_event_lkd(coap_context_t *context, coap_event_t event, coap_session_t *session)
Invokes the event handler of context for the given event and data.
int coap_handle_dgram(coap_context_t *ctx, coap_session_t *session, uint8_t *msg, size_t msg_len)
Parses and interprets a CoAP datagram with context ctx.
void coap_ticks(coap_tick_t *t)
Returns the current value of an internal tick counter.
int coap_crypto_hmac(cose_hmac_alg_t hmac_alg, coap_bin_const_t *key, coap_bin_const_t *data, coap_bin_const_t **hmac)
Create a HMAC hash of the provided data.
int coap_crypto_aead_decrypt(const coap_crypto_param_t *params, coap_bin_const_t *data, coap_bin_const_t *aad, uint8_t *result, size_t *max_result_len)
Decrypt the provided encrypted data into plaintext.
int coap_crypto_aead_encrypt(const coap_crypto_param_t *params, coap_bin_const_t *data, coap_bin_const_t *aad, uint8_t *result, size_t *max_result_len)
Encrypt the provided plaintext data.
int coap_crypto_hash(cose_alg_t alg, const coap_bin_const_t *data, coap_bin_const_t **hash)
Create a hash of the provided data.
int coap_crypto_check_hkdf_alg(cose_hkdf_alg_t hkdf_alg)
Check whether the defined hkdf algorithm is supported by the underlying crypto library.
int coap_crypto_check_cipher_alg(cose_alg_t alg)
Check whether the defined cipher algorithm is supported by the underlying crypto library.
const coap_bin_const_t * coap_get_session_client_psk_identity(const coap_session_t *coap_session)
Get the current client's PSK identity.
void coap_dtls_startup(void)
Initialize the underlying (D)TLS Library layer.
int coap_dtls_define_issue(coap_define_issue_key_t type, coap_define_issue_fail_t fail, coap_dtls_key_t *key, const coap_dtls_role_t role, int ret)
Report PKI DEFINE type issue.
void coap_dtls_thread_shutdown(void)
Close down the underlying (D)TLS Library layer.
int coap_dtls_set_cid_tuple_change(coap_context_t *context, uint8_t every)
Set the Connection ID client tuple frequency change for testing CIDs.
int coap_dtls_is_context_timeout(void)
Check if timeout is handled per CoAP session or per CoAP context.
void coap_dtls_shutdown(void)
Close down the underlying (D)TLS Library layer.
const coap_bin_const_t * coap_get_session_client_psk_key(const coap_session_t *coap_session)
Get the current client's PSK key.
void coap_dtls_map_key_type_to_define(const coap_dtls_pki_t *setup_data, coap_dtls_key_t *key)
Map the PKI key definitions to the new DEFINE format.
const coap_bin_const_t * coap_get_session_server_psk_key(const coap_session_t *coap_session)
Get the current server's PSK key.
const coap_bin_const_t * coap_get_session_server_psk_hint(const coap_session_t *coap_session)
Get the current server's PSK identity hint.
@ COAP_DEFINE_KEY_PRIVATE
@ COAP_DEFINE_FAIL_NOT_SUPPORTED
coap_tls_version_t * coap_get_tls_library_version(void)
Determine the type and version of the underlying (D)TLS library.
#define COAP_DTLS_RPK_CERT_CN
struct coap_dtls_pki_t coap_dtls_pki_t
@ COAP_PKI_KEY_DEF_PKCS11
The PKI key type is PKCS11 (pkcs11:...).
@ COAP_PKI_KEY_DEF_DER_BUF
The PKI key type is DER buffer (ASN.1).
@ COAP_PKI_KEY_DEF_PEM_BUF
The PKI key type is PEM buffer.
@ COAP_PKI_KEY_DEF_PEM
The PKI key type is PEM file.
@ COAP_PKI_KEY_DEF_ENGINE
The PKI key type is to be passed to ENGINE.
@ COAP_PKI_KEY_DEF_RPK_BUF
The PKI key type is RPK in buffer.
@ COAP_PKI_KEY_DEF_DER
The PKI key type is DER file.
@ COAP_PKI_KEY_DEF_PKCS11_RPK
The PKI key type is PKCS11 w/ RPK (pkcs11:...).
@ COAP_PKI_KEY_DEFINE
The individual PKI key types are Definable.
@ COAP_ASN1_PKEY_EC
EC type.
@ COAP_TLS_LIBRARY_TINYDTLS
Using TinyDTLS library.
@ COAP_EVENT_DTLS_CLOSED
Triggerrd when (D)TLS session closed.
@ COAP_EVENT_DTLS_CONNECTED
Triggered when (D)TLS session connected.
@ COAP_EVENT_DTLS_RENEGOTIATE
Triggered when (D)TLS session renegotiated.
@ COAP_EVENT_DTLS_ERROR
Triggered when (D)TLS error occurs.
#define coap_lock_callback_ret(r, func)
Dummy for no thread-safe code.
#define coap_log_debug(...)
coap_log_t coap_dtls_get_log_level(void)
Get the current (D)TLS logging.
#define coap_dtls_log(level,...)
Logging function.
void coap_dtls_set_log_level(coap_log_t level)
Sets the (D)TLS logging level to the specified level.
const char * coap_session_str(const coap_session_t *session)
Get session description.
#define coap_log_info(...)
#define coap_log_warn(...)
int cose_get_hmac_alg_for_hkdf(cose_hkdf_alg_t hkdf_alg, cose_hmac_alg_t *hmac_alg)
@ COSE_HMAC_ALG_HMAC256_256
@ COSE_ALGORITHM_AES_CCM_16_64_128
int coap_session_refresh_psk_hint(coap_session_t *session, const coap_bin_const_t *psk_hint)
Refresh the session's current Identity Hint (PSK).
int coap_session_refresh_psk_key(coap_session_t *session, const coap_bin_const_t *psk_key)
Refresh the session's current pre-shared key (PSK).
void coap_session_connected(coap_session_t *session)
Notify session that it has just connected or reconnected.
int coap_session_refresh_psk_identity(coap_session_t *session, const coap_bin_const_t *psk_identity)
Refresh the session's current pre-shared identity (PSK).
void coap_session_disconnected_lkd(coap_session_t *session, coap_nack_reason_t reason)
Notify session that it has failed.
coap_session_t * coap_session_get_by_peer(const coap_context_t *ctx, const coap_address_t *remote_addr, int ifindex)
Get the session associated with the specified remote_addr and index.
@ COAP_SESSION_TYPE_CLIENT
client-side
coap_binary_t * coap_new_binary(size_t size)
Returns a new binary object with at least size bytes storage allocated.
void coap_delete_binary(coap_binary_t *s)
Deletes the given coap_binary_t object and releases any memory allocated.
struct coap_binary_t coap_binary_t
CoAP binary data definition.
int coap_dtls_cid_is_supported(void)
Check whether (D)TLS CID is available.
int coap_dtls_psk_is_supported(void)
Check whether (D)TLS PSK is available.
int coap_tls_is_supported(void)
Check whether TLS is available.
int coap_oscore_is_supported(void)
Check whether OSCORE is available.
int coap_dtls_is_supported(void)
Check whether DTLS is available.
int coap_dtls_pki_is_supported(void)
Check whether (D)TLS PKI is available.
int coap_dtls_rpk_is_supported(void)
Check whether (D)TLS RPK is available.
int coap_dtls_pkcs11_is_supported(void)
Check whether (D)TLS PKCS11 is available.
coap_address_t remote
remote address and port
Multi-purpose address abstraction.
socklen_t size
size of addr
union coap_address_t::@236157306151077000227147123371042320347205022262 addr
CoAP binary data definition with const data.
size_t length
length of binary data
const uint8_t * s
read-only binary data
CoAP binary data definition.
size_t length
length of binary data
The CoAP stack's global state is stored in a coap_context_t object.
The structure that holds the AES Crypto information.
size_t l
The number of bytes in the length field.
const uint8_t * nonce
must be exactly 15 - l bytes
coap_crypto_key_t key
The Key to use.
size_t tag_len
The size of the Tag.
The common structure that holds the Crypto information.
union coap_crypto_param_t::@336067007110166000152341120316336117257114376002 params
coap_crypto_aes_ccm_t aes
Used if AES type encryption.
cose_alg_t alg
The COSE algorithm to use.
The structure that holds the Client PSK information.
coap_bin_const_t identity
The structure used for defining the Client PSK setup data to be used.
uint8_t use_cid
Set to 1 if DTLS Connection ID is to be used.
void * ih_call_back_arg
Passed in to the Identity Hint callback function.
coap_dtls_ih_callback_t validate_ih_call_back
Identity Hint check callback function.
uint8_t ec_jpake
Set to COAP_DTLS_CPSK_SETUP_VERSION to support this version of the struct.
The structure that holds the PKI key information.
coap_pki_key_define_t define
for definable type keys
coap_pki_key_t key_type
key format type
union coap_dtls_key_t::@146152304343152074137121235026247234256116265267 key
The structure used for defining the PKI setup data to be used.
uint8_t use_cid
1 if DTLS Connection ID is to be used (Client only, server always enabled) if supported
uint8_t is_rpk_not_cert
1 is RPK instead of Public Certificate.
The structure used for defining the Server PSK setup data to be used.
coap_dtls_psk_sni_callback_t validate_sni_call_back
SNI check callback function.
coap_dtls_id_callback_t validate_id_call_back
Identity check callback function.
void * id_call_back_arg
Passed in to the Identity callback function.
uint8_t ec_jpake
Set to COAP_DTLS_SPSK_SETUP_VERSION to support this version of the struct.
coap_layer_write_t l_write
coap_const_char_ptr_t public_cert
define: Public Cert
coap_asn1_privatekey_type_t private_key_type
define: ASN1 Private Key Type (if needed)
coap_const_char_ptr_t private_key
define: Private Key
coap_const_char_ptr_t ca
define: Common CA Certificate
size_t public_cert_len
define Public Cert length (if needed)
coap_pki_define_t private_key_def
define: Private Key type definition
size_t private_key_len
define Private Key length (if needed)
coap_pki_define_t ca_def
define: Common CA type definition
coap_pki_define_t public_cert_def
define: Public Cert type definition
Abstraction of virtual session that can be attached to coap_context_t (client) or coap_endpoint_t (se...
coap_socket_t sock
socket object for the session, if any
coap_addr_tuple_t addr_info
remote/local address info
coap_dtls_cpsk_t cpsk_setup_data
client provided PSK initial setup data
int dtls_event
Tracking any (D)TLS events on this session.
void * tls
security parameters
coap_session_type_t type
client or server side socket
coap_context_t * context
session's context
int ifindex
interface index
coap_layer_func_t lfunc[COAP_LAYER_LAST]
Layer functions to use.
CoAP string data definition with const data.
const uint8_t * s
read-only string data
size_t length
length of string
The structure used for returning the underlying (D)TLS library information.
uint64_t built_version
(D)TLS Built against Library Version
coap_tls_library_t type
Library type.
uint64_t version
(D)TLS runtime Library Version
const uint8_t * u_byte
unsigned char ptr