20#ifdef 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;
52#if ! defined(DTLS_PSK) && ! defined(DTLS_ECC)
53#error Neither DTLS_PSK or DTLS_ECC defined
56static dtls_tick_t dtls_tick_0 = 0;
109dtls_map_logging(log_t d_level) {
124 case DTLS_LOG_NOTICE:
137#ifdef HAVE_DTLS_SET_LOG_HANDLER
140dtls_logging(log_t d_level,
const char *message) {
141 coap_log_t c_level = dtls_map_logging(d_level);
150 dtls_ticks(&dtls_tick_0);
152#ifdef HAVE_DTLS_SET_LOG_HANDLER
154 dtls_set_log_handler(dtls_logging);
170 const coap_tiny_context_t *t_context =
173 return t_context->dtls_context;
185 d_level = DTLS_LOG_EMERG;
188 d_level = DTLS_LOG_ALERT;
192 d_level = DTLS_LOG_CRIT;
195 d_level = DTLS_LOG_WARN;
198 d_level = DTLS_LOG_NOTICE;
201 d_level = DTLS_LOG_INFO;
207 d_level = DTLS_LOG_DEBUG;
210 dtls_set_log_level(d_level);
215 log_t d_level = dtls_get_log_level();
217 return dtls_map_logging(d_level);
222#if defined(WITH_CONTIKI) || defined(WITH_LWIP)
224 memset(&a->
addr, 0,
sizeof(a->
addr));
225 switch (s->addr.sa.sa_family) {
228 memcpy(&a->
addr, &s->
addr.
sin.sin_addr,
sizeof(s->addr.sin.sin_addr));
229 a->port = s->
addr.
sin.sin_port;
234 memcpy(&a->
addr, &s->
addr.
sin6.sin6_addr,
sizeof(s->addr.sin6.sin6_addr));
245#elif defined(WITH_RIOT_SOCK)
246 if (s->addr.family == AF_INET6) {
247 a->riot.family = s->
addr.family;
248 memcpy(&a->riot.
addr.ipv6, &s->
addr.ipv6,
249 sizeof(a->riot.
addr.ipv6));
250 a->riot.port = ntohs(s->addr.port);
253 }
else if (s->addr.family == AF_INET) {
254 a->riot.family = s->
addr.family;
255 memcpy(&a->riot.
addr.ipv4, &s->
addr.ipv4,
sizeof(a->riot.
addr.ipv4));
256 a->riot.port = ntohs(s->addr.port);
261 if (s->addr.sa.sa_family == AF_INET6) {
264 }
else if (s->addr.sa.sa_family == AF_INET) {
268 a->
size = (socklen_t)s->size;
276#if defined(WITH_CONTIKI) || defined(WITH_LWIP)
278#if LWIP_IPV6 && LWIP_IPV4
279 if (a->
addr.type == IPADDR_TYPE_V6) {
280 s->addr.sa.sa_family = AF_INET6;
281 s->size = (socklen_t)
sizeof(s->addr.sin6);
282 memcpy(&s->addr.sin6.sin6_addr, &a->
addr,
sizeof(s->addr.sin6.sin6_addr));
283 s->addr.sin6.sin6_port = a->port;
284 }
else if (a->
addr.type == IPADDR_TYPE_V4) {
285 s->
addr.
sa.sa_family = AF_INET;
286 s->size = (socklen_t)
sizeof(s->addr.sin);
287 memcpy(&s->addr.sin.sin_addr, &a->
addr,
sizeof(s->addr.sin.sin_addr));
288 s->addr.sin.sin_port = a->port;
293 s->
size = (
unsigned char)
sizeof(s->addr);
297#elif defined(WITH_RIOT_SOCK)
298 if (a->riot.family == AF_INET6) {
299 s->
size =
sizeof(s->addr.ipv6);
300 s->addr.family = a->riot.family;
301 memcpy(&s->addr.ipv6, &a->riot.
addr.ipv6,
302 sizeof(s->addr.ipv6));
303 s->addr.port = htons(a->riot.port);
305 }
else if (a->r.family == AF_INET) {
306 s->size =
sizeof(s->addr.ipv4);
307 s->addr.family = a->r.family;
308 memcpy(&a->
addr.ipv4, &s->r.
addr.ipv4,
sizeof(a->
addr.ipv4));
309 s->addr.port = htons(a->r.port);
313 if (a->
addr.
sa.sa_family == AF_INET6) {
314 s->size = (socklen_t)
sizeof(s->addr.sin6);
316 }
else if (a->
addr.
sa.sa_family == AF_INET) {
317 s->size = (socklen_t)
sizeof(s->addr.sin);
320 s->size = (socklen_t)a->
size;
327dtls_send_to_peer(
struct dtls_context_t *dtls_context,
328 session_t *dtls_session, uint8 *data,
size_t len) {
329 coap_tiny_context_t *t_context =
330 (coap_tiny_context_t *)dtls_get_app_data(dtls_context);
331 coap_context_t *coap_context = t_context ? t_context->coap_context : NULL;
335 assert(coap_context);
336 get_session_addr(dtls_session, &remote_addr);
339 coap_log_warn(
"dtls_send_to_peer: cannot find local interface\n");
347dtls_application_data(
struct dtls_context_t *dtls_context,
348 session_t *dtls_session, uint8 *data,
size_t len) {
349 coap_tiny_context_t *t_context =
350 (coap_tiny_context_t *)dtls_get_app_data(dtls_context);
351 coap_context_t *coap_context = t_context ? t_context->coap_context : NULL;
355 assert(coap_context);
356 get_session_addr(dtls_session, &remote_addr);
359 coap_log_debug(
"dropped message that was received on invalid interface\n");
368static int coap_event_dtls = 0;
371dtls_event(
struct dtls_context_t *dtls_context,
372 session_t *dtls_session,
373 dtls_alert_level_t level,
374 unsigned short code) {
378 if (level == DTLS_ALERT_LEVEL_FATAL)
383 case DTLS_ALERT_CLOSE_NOTIFY: {
387 case DTLS_EVENT_CONNECTED: {
391#ifdef DTLS_EVENT_RENEGOTIATE
392 case DTLS_EVENT_RENEGOTIATE: {
409get_psk_info(
struct dtls_context_t *dtls_context,
410 const session_t *dtls_session,
411 dtls_credentials_type_t type,
412 const uint8_t *
id,
size_t id_len,
413 unsigned char *result,
size_t result_length) {
415 coap_tiny_context_t *t_context =
416 (coap_tiny_context_t *)dtls_get_app_data(dtls_context);
417 coap_context_t *coap_context = t_context ? t_context->coap_context : NULL;
419 int fatal_error = DTLS_ALERT_INTERNAL_ERROR;
421#if COAP_CLIENT_SUPPORT
427#if COAP_SERVER_SUPPORT
432 assert(coap_context);
433 get_session_addr(dtls_session, &remote_addr);
441 case DTLS_PSK_IDENTITY:
443#if COAP_CLIENT_SUPPORT
455 id ? (
const char *)
id :
"");
467 psk_identity = &cpsk_info->
identity;
476 if (psk_identity == NULL) {
478 fatal_error = DTLS_ALERT_CLOSE_NOTIFY;
481 if (psk_identity->
length > result_length) {
482 coap_log_warn(
"psk_identity too large, truncated to %zd bytes\n",
486 result_length = psk_identity->
length;
488 memcpy(result, psk_identity->
s, result_length);
489 return result_length;
495#if COAP_CLIENT_SUPPORT
498 if (psk_key == NULL) {
500 fatal_error = DTLS_ALERT_CLOSE_NOTIFY;
503 if (psk_key->
length > result_length) {
508 result_length = psk_key->
length;
510 memcpy(result, psk_key->
s, result_length);
511 return result_length;
514#if COAP_SERVER_SUPPORT
518 lidentity.
length =
id ? id_len : 0;
519 lidentity.
s =
id ? (
const uint8_t *)
id : (const uint8_t *)
"";
526 (
int)lidentity.
length, lidentity.
s);
537 if (psk_key == NULL) {
543 if (psk_key->
length > result_length) {
548 result_length = psk_key->
length;
550 memcpy(result, psk_key->
s, result_length);
551 return result_length;
557#if COAP_SERVER_SUPPORT
559 if (psk_hint == NULL)
561 if (psk_hint->
length > result_length) {
562 coap_log_warn(
"psk_hint too large, truncated to %zd bytes\n",
566 result_length = psk_hint->
length;
568 memcpy(result, psk_hint->
s, result_length);
569 return result_length;
579 return dtls_alert_fatal_create(fatal_error);
585get_ecdsa_key(
struct dtls_context_t *dtls_context,
587 const dtls_ecdsa_key_t **result) {
588 static dtls_ecdsa_key_t ecdsa_key;
589 coap_tiny_context_t *t_context =
590 (coap_tiny_context_t *)dtls_get_app_data(dtls_context);
592 ecdsa_key.curve = DTLS_ECDH_CURVE_SECP256R1;
593 ecdsa_key.priv_key = t_context->priv_key->s;
594 ecdsa_key.pub_key_x = t_context->pub_key->s;
595 ecdsa_key.pub_key_y = &t_context->pub_key->s[DTLS_EC_KEY_SIZE];
597 *result = &ecdsa_key;
602static const unsigned char cert_asn1_header[] = {
606 0x2A, 0x86, 0x48, 0xCE, 0x3D, 0x02, 0x01,
608 0x2A, 0x86, 0x48, 0xCE, 0x3D, 0x03, 0x01, 0x07,
612#define DTLS_CE_LENGTH (sizeof(cert_asn1_header) + key_size + key_size)
615verify_ecdsa_key(
struct dtls_context_t *dtls_context
COAP_UNUSED,
617 const uint8_t *other_pub_x,
618 const uint8_t *other_pub_y,
620 coap_tiny_context_t *t_context =
621 (coap_tiny_context_t *)dtls_get_app_data(dtls_context);
622 if (t_context && t_context->setup_data.validate_cn_call_back) {
625 uint8 buf[DTLS_CE_LENGTH];
634 memcpy(p, &cert_asn1_header,
sizeof(cert_asn1_header));
635 p +=
sizeof(cert_asn1_header);
637 memcpy(p, other_pub_x, key_size);
640 memcpy(p, other_pub_y, key_size);
643 assert(p <= (buf +
sizeof(buf)));
645 get_session_addr(dtls_session, &remote_addr);
647 &remote_addr, dtls_session->ifindex);
651 buf, p-buf, c_session, 0, 1, t_context->setup_data.cn_call_back_arg)) {
657static dtls_handler_t ec_cb = {
658 .write = dtls_send_to_peer,
659 .read = dtls_application_data,
662 .get_psk_info = NULL,
664 .get_ecdsa_key = get_ecdsa_key,
665 .verify_ecdsa_key = verify_ecdsa_key
669static dtls_handler_t psk_cb = {
670 .write = dtls_send_to_peer,
671 .read = dtls_application_data,
674 .get_psk_info = get_psk_info,
677 .get_ecdsa_key = NULL,
678 .verify_ecdsa_key = NULL
685 struct dtls_context_t *dtls_context = t_context ? dtls_new_context(t_context) : NULL;
688 memset(t_context, 0,
sizeof(coap_tiny_context_t));
689 t_context->coap_context = coap_context;
690 t_context->dtls_context = dtls_context;
691 dtls_set_handler(dtls_context, &psk_cb);
704 coap_tiny_context_t *t_context = (coap_tiny_context_t *)handle;
706 if (t_context->priv_key) {
708 t_context->priv_key = NULL;
710 if (t_context->pub_key) {
712 t_context->pub_key = NULL;
715 if (t_context->dtls_context)
716 dtls_free_context(t_context->dtls_context);
728 dtls_session_init(dtls_session);
730 dtls_session->ifindex = session->
ifindex;
737#if COAP_SERVER_SUPPORT
740 return coap_dtls_new_session(session);
744#if COAP_CLIENT_SUPPORT
749 dtls_context_t *dtls_context = t_context ? t_context->dtls_context : NULL;
750 session_t *dtls_session = dtls_context ? coap_dtls_new_session(session) : NULL;
755 dtls_get_peer(dtls_context, dtls_session);
761 if (dtls_connect(dtls_context, dtls_session) >= 0) {
763 dtls_get_peer(dtls_context, dtls_session);
784 coap_tiny_context_t *t_context =
786 dtls_context_t *dtls_context = t_context ? t_context->dtls_context : NULL;
788 if (dtls_context == NULL)
790 if (coap_session->
tls && dtls_context) {
791 dtls_peer_t *peer = dtls_get_peer(dtls_context, (session_t *)coap_session->
tls);
793 dtls_reset_peer(dtls_context, peer);
795 dtls_close(dtls_context, (session_t *)coap_session->
tls);
798 coap_session->
tls = NULL;
810 dtls_context_t *dtls_context = t_context ? t_context->dtls_context : NULL;
812 assert(dtls_context);
814 coap_event_dtls = -1;
818 memcpy(&data_rw, &data,
sizeof(data_rw));
819 res = dtls_write(dtls_context,
820 (session_t *)session->
tls, data_rw, data_len);
825 if (coap_event_dtls >= 0) {
845 clock_time_t next = 0;
846 coap_tiny_context_t *t_context = (coap_tiny_context_t *)tiny_context;
847 dtls_context_t *dtls_context = t_context ? t_context->dtls_context : NULL;
849 dtls_check_retransmit(dtls_context, &next);
878 session_t *dtls_session = (session_t *)session->
tls;
882 dtls_context_t *dtls_context = t_context ? t_context->dtls_context : NULL;
884 assert(dtls_context);
885 coap_event_dtls = -1;
887 memcpy(&data_rw, &data,
sizeof(data_rw));
888 err = dtls_handle_message(dtls_context, dtls_session, data_rw, (
int)data_len);
894 if (coap_event_dtls >= 0) {
909#if COAP_SERVER_SUPPORT
915 session_t dtls_session;
917 dtls_context_t *dtls_context = t_context ? t_context->dtls_context : NULL;
920 assert(dtls_context);
921 dtls_session_init(&dtls_session);
923 dtls_session.ifindex = session->
ifindex;
925 memcpy(&data_rw, &data,
sizeof(data_rw));
926 int res = dtls_handle_message(dtls_context, &dtls_session,
927 data_rw, (
int)data_len);
929 if (dtls_get_peer(dtls_context, &dtls_session))
952 const char *vers = dtls_package_version();
956 long int p1, p2 = 0, p3 = 0;
959 p1 = strtol(vers, &endptr, 10);
960 if (*endptr ==
'.') {
961 p2 = strtol(endptr+1, &endptr, 10);
962 if (*endptr ==
'.') {
963 p3 = strtol(endptr+1, &endptr, 10);
966 version.
version = (p1 << 16) | (p2 << 8) | p3;
974static const uint8_t b64_6[256] = {
975 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64,
976 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64,
978 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 62, 64, 64, 64, 63,
980 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 64, 64, 64, 64, 64, 64,
982 64, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14,
984 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 64, 64, 64, 64, 64,
986 64, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40,
988 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 64, 64, 64, 64, 64,
989 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64,
990 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64,
991 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64,
992 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64,
993 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64,
994 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64,
995 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64,
996 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64
1001pem_base64_decode(
const uint8_t *data,
size_t size) {
1003 size_t nbytesdecoded;
1008 size_t nb64bytes = 0;
1010 for (i = 0; i < size; i++) {
1018 if (b64_6[data[i]] == 64)
1020 tbuf[nb64bytes++] = data[i];
1026 nbytesdecoded = ((nb64bytes + 3) / 4) * 3;
1034 while (nb64bytes > 4) {
1035 *(out++) = b64_6[ptr[0]] << 2 | b64_6[ptr[1]] >> 4;
1036 *(out++) = b64_6[ptr[1]] << 4 | b64_6[ptr[2]] >> 2;
1037 *(out++) = b64_6[ptr[2]] << 6 | b64_6[ptr[3]];
1043 if (nb64bytes > 1) {
1044 *(out++) = b64_6[ptr[0]] << 2 | b64_6[ptr[1]] >> 4;
1046 if (nb64bytes > 2) {
1047 *(out++) = b64_6[ptr[1]] << 4 | b64_6[ptr[2]] >> 2;
1049 if (nb64bytes > 3) {
1050 *(out++) = b64_6[ptr[2]] << 6 | b64_6[ptr[3]];
1053 decoded->
length = nbytesdecoded - ((4 - nb64bytes) & 3);
1058typedef coap_binary_t *(*asn1_callback)(
const uint8_t *data,
size_t size);
1061asn1_verify_privkey(
const uint8_t *data,
size_t size) {
1064 if (size - 1 == DTLS_EC_KEY_SIZE && *data ==
'\000') {
1070 if (size != DTLS_EC_KEY_SIZE)
1077asn1_verify_pubkey(
const uint8_t *data,
size_t size) {
1082 if (size - 2 != 2 * DTLS_EC_KEY_SIZE)
1089asn1_verify_curve(
const uint8_t *data,
size_t size) {
1090 static uint8_t prime256v1_oid[] =
1092 { 0x2a, 0x86, 0x48, 0xce, 0x3d, 0x03, 0x01, 0x07 };
1095 if (size !=
sizeof(prime256v1_oid) ||
1096 memcmp(data, prime256v1_oid, size) != 0)
1103asn1_verify_pkcs8_version(
const uint8_t *data,
size_t size) {
1105 if (size != 1 || *data != 0)
1112asn1_verify_ec_identifier(
const uint8_t *data,
size_t size) {
1113 static uint8_t ec_public_key_oid[] =
1115 { 0x2a, 0x86, 0x48, 0xce, 0x3d, 0x02, 0x01 };
1118 if (size !=
sizeof(ec_public_key_oid) ||
1119 memcmp(data, ec_public_key_oid, size) != 0)
1126asn1_verify_ec_key(
const uint8_t *data,
size_t size) {
1136asn1_derive_keys(coap_tiny_context_t *t_context,
1137 const uint8_t *priv_data,
size_t priv_len,
1138 const uint8_t *pub_data,
size_t pub_len,
1143 priv_len, asn1_verify_privkey);
1144 if (!t_context->priv_key) {
1149 if (t_context->priv_key->length - 1 == DTLS_EC_KEY_SIZE &&
1150 t_context->priv_key->s[0] ==
'\000') {
1151 t_context->priv_key->length--;
1152 t_context->priv_key->s++;
1160 coap_log_info(
"EC Private Key (RPK) invalid elliptic curve\n");
1162 t_context->priv_key = NULL;
1169 asn1_verify_pubkey);
1170 if (!t_context->pub_key) {
1173 t_context->priv_key = NULL;
1177 t_context->pub_key->s += 2;
1178 t_context->pub_key->length -= 2;
1179 dtls_set_handler(t_context->dtls_context, &ec_cb);
1184ec_abstract_pkcs8_asn1(
const uint8_t *asn1_ptr,
size_t asn1_length) {
1188 asn1_verify_pkcs8_version);
1195 asn1_verify_ec_identifier);
1203 coap_log_info(
"EC Private Key (RPK) invalid elliptic curve\n");
1209 asn1_verify_ec_key);
1214pem_decode_mem_asn1(
const char *begstr,
const uint8_t *str) {
1215 char *bcp = str ? strstr((
const char *)str, begstr) : NULL;
1216 char *tcp = bcp ? strstr(bcp,
"-----END ") : NULL;
1219 bcp += strlen(begstr);
1220 return pem_base64_decode((
const uint8_t *)bcp, tcp - bcp);
1232 coap_tiny_context_t *t_context;
1249 if (t_context->priv_key) {
1251 t_context->priv_key = NULL;
1253 if (t_context->pub_key) {
1255 t_context->pub_key = NULL;
1257 t_context->setup_data = *setup_data;
1272 asn1_priv = pem_decode_mem_asn1(
"-----BEGIN EC PRIVATE KEY-----",
1275 asn1_priv = pem_decode_mem_asn1(
"-----BEGIN PRIVATE KEY-----",
1282 asn1_temp = ec_abstract_pkcs8_asn1(asn1_priv->
s, asn1_priv->
length);
1284 coap_log_info(
"*** setup_pki: (D)TLS: PKCS#8 Private Key (RPK) invalid\n");
1291 asn1_priv = asn1_temp;
1294 asn1_pub = pem_decode_mem_asn1(
"-----BEGIN PUBLIC KEY-----",
1297 asn1_pub = pem_decode_mem_asn1(
"-----BEGIN EC PRIVATE KEY-----",
1300 asn1_pub = pem_decode_mem_asn1(
"-----BEGIN PRIVATE KEY-----",
1303 coap_log_info(
"*** setup_pki: (D)TLS: Public Key (RPK) invalid\n");
1309 asn1_temp = ec_abstract_pkcs8_asn1(asn1_pub->
s, asn1_pub->
length);
1311 coap_log_info(
"*** setup_pki: (D)TLS: PKCS#8 Private Key (RPK) invalid\n");
1319 asn1_pub = asn1_temp;
1323 if (!asn1_derive_keys(t_context, asn1_priv->
s, asn1_priv->
length,
1324 asn1_pub->
s, asn1_pub->
length, is_pkcs8)) {
1325 coap_log_info(
"*** setup_pki: (D)TLS: Unable to derive Public/Private Keys\n");
1344 private_key = asn1_temp->
s;
1345 private_key_len = asn1_temp->
length;
1351 if (!asn1_derive_keys(t_context,
1357 coap_log_info(
"*** setup_pki: (D)TLS: Unable to derive Public/Private Keys\n");
1362 if (!asn1_derive_keys(t_context,
1368 coap_log_info(
"*** setup_pki: (D)TLS: Unable to derive Public/Private Keys\n");
1463#if COAP_CLIENT_SUPPORT
1480#if COAP_SERVER_SUPPORT
1490 coap_log_warn(
"CoAP Server with TinyDTLS does not support SNI selection\n");
1506#if !COAP_DISABLE_TCP
1507#if COAP_CLIENT_SUPPORT
1514#if COAP_SERVER_SUPPORT
1552#if COAP_SERVER_SUPPORT
1558 dtls_sha256_init(digest_ctx);
1571 const uint8_t *data,
1573 dtls_sha256_update(digest_ctx, data, data_len);
1581 dtls_sha256_final((uint8_t *)digest_buffer, digest_ctx);
1613#if COAP_OSCORE_SUPPORT
1625static struct cipher_algs {
1636 for (idx = 0; idx <
sizeof(ciphers)/
sizeof(
struct cipher_algs); idx++) {
1637 if (ciphers[idx].alg == alg)
1638 return ciphers[idx].cipher_type;
1640 coap_log_debug(
"get_cipher_alg: COSE cipher %d not supported\n", alg);
1649static struct hmac_algs {
1660 for (idx = 0; idx <
sizeof(hmacs)/
sizeof(
struct hmac_algs); idx++) {
1661 if (hmacs[idx].hmac_alg == hmac_alg)
1662 return hmacs[idx].hmac_type;
1664 coap_log_debug(
"get_hmac_alg: COSE HMAC %d not supported\n", hmac_alg);
1670 return get_cipher_alg(alg);
1679 return get_hmac_alg(hmac_alg);
1686 uint8_t *result,
size_t *max_result_len) {
1689 dtls_ccm_params_t dtls_params;
1697 if (get_cipher_alg(params->
alg) == 0) {
1698 coap_log_debug(
"coap_crypto_encrypt: algorithm %d not supported\n",
1709 dtls_params.nonce = ccm->
nonce;
1710 dtls_params.tag_length = ccm->
tag_len;
1711 dtls_params.l = ccm->
l;
1720 num_bytes = dtls_encrypt_params(&dtls_params,
1725 if (num_bytes < 0) {
1728 *max_result_len = num_bytes;
1736 uint8_t *result,
size_t *max_result_len) {
1739 dtls_ccm_params_t dtls_params;
1747 if (get_cipher_alg(params->
alg) == 0) {
1748 coap_log_debug(
"coap_crypto_decrypt: algorithm %d not supported\n",
1760 dtls_params.nonce = ccm->
nonce;
1761 dtls_params.tag_length = ccm->
tag_len;
1762 dtls_params.l = ccm->
l;
1771 num_bytes = dtls_decrypt_params(&dtls_params,
1776 if (num_bytes < 0) {
1779 *max_result_len = num_bytes;
1786 dtls_hmac_context_t hmac_context;
1793 if (get_hmac_alg(hmac_alg) == 0) {
1794 coap_log_debug(
"coap_crypto_hmac: algorithm %d not supported\n", hmac_alg);
1802 dtls_hmac_init(&hmac_context, key->
s, key->
length);
1803 dtls_hmac_update(&hmac_context, data->
s, data->
length);
1804 num_bytes = dtls_hmac_finalize(&hmac_context,
dummy->s);
1806 if (num_bytes != DTLS_SHA256_DIGEST_LENGTH) {
1822#pragma GCC diagnostic ignored "-Wunused-function"
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_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 SHA1Result(SHA1Context *, uint8_t Message_Digest[SHA1HashSize])
int SHA1Reset(SHA1Context *)
int SHA1Input(SHA1Context *, const uint8_t *, unsigned int)
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.
void coap_digest_free(coap_digest_ctx_t *digest_ctx)
Free off coap_digest_ctx_t.
int coap_digest_final(coap_digest_ctx_t *digest_ctx, coap_digest_t *digest_buffer)
Finalize the coap_digest information into the provided digest_buffer.
int coap_digest_update(coap_digest_ctx_t *digest_ctx, const uint8_t *data, size_t data_len)
Update the coap_digest information with the next chunk of data.
coap_digest_ctx_t * coap_digest_setup(void)
Initialize a coap_digest.
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 *)
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.
void * coap_tls_new_server_session(coap_session_t *coap_session)
Create a TLS new server-side session.
const coap_bin_const_t * coap_get_session_client_psk_identity(const coap_session_t *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_new_client_session(coap_session_t *coap_session)
Create a new client-side session.
void * coap_dtls_new_server_session(coap_session_t *coap_session)
Create a new DTLS server-side session.
int coap_dtls_hello(coap_session_t *coap_session, const uint8_t *data, size_t data_len)
Handling client HELLO messages from a new candiate peer.
int coap_dtls_is_context_timeout(void)
Check if timeout is handled per CoAP session or per CoAP context.
int coap_dtls_context_set_cpsk(coap_context_t *coap_context, coap_dtls_cpsk_t *setup_data)
Set the DTLS context's default client PSK information.
int coap_dtls_context_set_spsk(coap_context_t *coap_context, coap_dtls_spsk_t *setup_data)
Set the DTLS context's default server PSK information.
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_tls_new_client_session(coap_session_t *coap_session)
Create a new TLS client-side session.
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.
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.
#define COAP_DTLS_RPK_CERT_CN
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_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
Triggerred 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_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_oscore_is_supported(void)
Check whether OSCORE is available.
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.
coap_address_t remote
remote address and port
Multi-purpose address abstraction.
socklen_t size
size of addr
union coap_address_t::@0 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.
coap_dtls_spsk_t spsk_setup_data
Contains the initial PSK server setup data.
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::@2 params
coap_crypto_aes_ccm_t aes
Used if AES type encryption.
cose_alg_t alg
The COSE algorith 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.
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.
The structure that holds the PKI key information.
coap_pki_key_define_t define
for definable type keys
union coap_dtls_key_t::@3 key
coap_pki_key_t key_type
key format type
The structure used for defining the PKI setup data to be used.
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.
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
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