diff --git a/examples/coap-client.c b/examples/coap-client.c index b8d1fb39b8..a837c5eceb 100644 --- a/examples/coap-client.c +++ b/examples/coap-client.c @@ -1924,8 +1924,12 @@ main(int argc, char **argv) { coap_register_nack_handler(ctx, nack_handler); if (the_token.length > COAP_TOKEN_DEFAULT_MAX) coap_context_set_max_token_size(ctx, the_token.length); - if (cid_every) - coap_context_set_cid_tuple_change(ctx, cid_every); + if (cid_every) { + if (!coap_context_set_cid_tuple_change(ctx, cid_every)) { + coap_log_warn("coap_context_set_cid_tuple_change: " + "Unable to set CID tuple change\n"); + } + } session = get_session(ctx, node_str[0] ? node_str : NULL, diff --git a/include/coap3/coap_dtls.h b/include/coap3/coap_dtls.h index 1fc2d2f030..25e44762ee 100644 --- a/include/coap3/coap_dtls.h +++ b/include/coap3/coap_dtls.h @@ -29,6 +29,8 @@ * @{ */ +int coap_dtls_cid_is_supported(void); + typedef struct coap_dtls_pki_t coap_dtls_pki_t; #ifndef COAP_DTLS_HINT_LENGTH diff --git a/include/coap3/coap_dtls_internal.h b/include/coap3/coap_dtls_internal.h index 4224af65d9..98744b10f2 100644 --- a/include/coap3/coap_dtls_internal.h +++ b/include/coap3/coap_dtls_internal.h @@ -481,6 +481,17 @@ int coap_dtls_define_issue(coap_define_issue_key_t type, coap_dtls_key_t *key, const coap_dtls_role_t role, int ret); + +/** + * Set the Connection ID client tuple frequency change for testing CIDs. + * + * @param context The coap_context_t object. + * @param every Change the client's source port @p every packets sent. + * + * @return @c 1 if frequency change set (CID supported), else @c 0. + */ +int coap_dtls_set_cid_tuple_change(coap_context_t *context, uint8_t every); + /** @} */ #endif /* COAP_DTLS_INTERNAL_H */ diff --git a/include/coap3/coap_net.h b/include/coap3/coap_net.h index 15a0d764aa..cc1ebe8c7a 100644 --- a/include/coap3/coap_net.h +++ b/include/coap3/coap_net.h @@ -235,8 +235,10 @@ void coap_context_set_keepalive(coap_context_t *context, unsigned int seconds); * * @param context The coap_context_t object. * @param every Change the client's source port @p every packets sent. + * + * @return @c 1 if frequency change set (CID supported), else @c 0. */ -void coap_context_set_cid_tuple_change(coap_context_t *context, uint8_t every); +int coap_context_set_cid_tuple_change(coap_context_t *context, uint8_t every); /** * Set the maximum token size (RFC8974). diff --git a/include/coap3/coap_session_internal.h b/include/coap3/coap_session_internal.h index be6d8b235c..e464a82de2 100644 --- a/include/coap3/coap_session_internal.h +++ b/include/coap3/coap_session_internal.h @@ -203,6 +203,10 @@ struct coap_session_t { #endif /* COAP_OSCORE_SUPPORT */ volatile uint8_t max_token_checked; /**< Check for max token size coap_ext_token_check_t */ +#if COAP_CLIENT_SUPPORT + uint8_t negotiated_cid; /**< Set for a client if CID negotiated */ +#endif /* COAP_CLIENT_SUPPORT */ + uint8_t is_dtls13; /**< Set if session is DTLS1.3 */ coap_mid_t remote_test_mid; /**< mid used for checking remote support */ uint32_t max_token_size; /**< Largest token size supported RFC8974 */ diff --git a/libcoap-3.map b/libcoap-3.map index 7d34f4f192..161ad7614b 100644 --- a/libcoap-3.map +++ b/libcoap-3.map @@ -81,6 +81,7 @@ global: coap_delete_str_const; coap_delete_string; coap_delete_uri; + coap_dtls_cid_is_supported; coap_dtls_get_log_level; coap_dtls_is_supported; coap_dtls_pkcs11_is_supported; diff --git a/libcoap-3.sym b/libcoap-3.sym index 9bf070e68a..7fc345e23b 100644 --- a/libcoap-3.sym +++ b/libcoap-3.sym @@ -79,6 +79,7 @@ coap_delete_resource coap_delete_str_const coap_delete_string coap_delete_uri +coap_dtls_cid_is_supported coap_dtls_get_log_level coap_dtls_is_supported coap_dtls_pkcs11_is_supported diff --git a/man/coap_context.txt.in b/man/coap_context.txt.in index 1887778df0..4b40a20999 100644 --- a/man/coap_context.txt.in +++ b/man/coap_context.txt.in @@ -65,7 +65,7 @@ size_t _max_token_size_);* *void *coap_context_get_app_data(const coap_context_t *_context_);* -*void coap_context_set_cid_tuple_change(coap_context_t *_context_context, uint8_t _every_);* +*int coap_context_set_cid_tuple_change(coap_context_t *_context_context, uint8_t _every_);* For specific (D)TLS library support, link with *-lcoap-@LIBCOAP_API_VERSION@-notls*, *-lcoap-@LIBCOAP_API_VERSION@-gnutls*, @@ -190,7 +190,8 @@ pointer previously defined by *coap_context_set_app_data*(). The *coap_context_set_cid_tuple_change*() function is used to define to a client to force the client's port to change _every_ packets sent, providing the ability -to test a CID (RFC9146) enabled server. +to test a CID (RFC9146) enabled server. Only supported by DTLS libraries that +support CID. RETURN VALUES ------------- @@ -211,6 +212,8 @@ out an idle server session. *coap_context_get_app_data*() returns a previously defined pointer. +*coap_context_set_cid_tuple_change*() returns 1 on success, else 0; + SEE ALSO -------- *coap_session*(3) diff --git a/src/coap_debug.c b/src/coap_debug.c index 0e3d93f797..60d0307c52 100644 --- a/src/coap_debug.c +++ b/src/coap_debug.c @@ -1233,6 +1233,7 @@ coap_string_tls_support(char *buffer, size_t bufsize) { const int have_pki = coap_dtls_pki_is_supported(); const int have_pkcs11 = coap_dtls_pkcs11_is_supported(); const int have_rpk = coap_dtls_rpk_is_supported(); + const int have_cid = coap_dtls_cid_is_supported(); const int have_oscore = coap_oscore_is_supported(); const int have_ws = coap_ws_is_supported(); @@ -1241,13 +1242,14 @@ coap_string_tls_support(char *buffer, size_t bufsize) { return buffer; } snprintf(buffer, bufsize, - "(%sDTLS and %sTLS support; %sPSK, %sPKI, %sPKCS11, and %sRPK support)\n(%sOSCORE)\n(%sWebSockets)", + "(%sDTLS and %sTLS support; %sPSK, %sPKI, %sPKCS11, %sRPK and %sCID support)\n(%sOSCORE)\n(%sWebSockets)", have_dtls ? "" : "No ", have_tls ? "" : "no ", have_psk ? "" : "no ", have_pki ? "" : "no ", have_pkcs11 ? "" : "no ", have_rpk ? "" : "no ", + have_cid ? "" : "no ", have_oscore ? "Have " : "No ", have_ws ? "Have " : "No "); return buffer; diff --git a/src/coap_gnutls.c b/src/coap_gnutls.c index 816ede38d9..30190dad44 100644 --- a/src/coap_gnutls.c +++ b/src/coap_gnutls.c @@ -243,6 +243,24 @@ coap_dtls_rpk_is_supported(void) { #endif /* GNUTLS_VERSION_NUMBER < 0x030606 */ } +/* + * return 0 failed + * 1 passed + */ +int +coap_dtls_cid_is_supported(void) { + return 0; +} + +#if COAP_CLIENT_SUPPORT +int +coap_dtls_set_cid_tuple_change(coap_context_t *c_context, uint8_t every) { + (void)c_context; + (void)every; + return 0; +} +#endif /* COAP_CLIENT_SUPPORT */ + coap_tls_version_t * coap_get_tls_library_version(void) { static coap_tls_version_t version; diff --git a/src/coap_io.c b/src/coap_io.c index 0ca9e096b3..d0dd7b08cb 100644 --- a/src/coap_io.c +++ b/src/coap_io.c @@ -782,8 +782,9 @@ static uint32_t cid_track_counter; static void coap_test_cid_tuple_change(coap_session_t *session) { if (session->type == COAP_SESSION_TYPE_CLIENT && + session->negotiated_cid && session->state == COAP_SESSION_STATE_ESTABLISHED && - COAP_PROTO_NOT_RELIABLE(session->proto) && session->context->testing_cids) { + session->proto == COAP_PROTO_DTLS && session->context->testing_cids) { if ((++cid_track_counter) % session->context->testing_cids == 0) { coap_address_t local_if = session->addr_info.local; uint16_t port = coap_address_get_port(&local_if); diff --git a/src/coap_mbedtls.c b/src/coap_mbedtls.c index 1e44ce198e..c932740e7b 100644 --- a/src/coap_mbedtls.c +++ b/src/coap_mbedtls.c @@ -1467,6 +1467,31 @@ do_mbedtls_handshake(coap_session_t *c_session, coap_log_debug("* %s: Mbed TLS established\n", coap_session_str(c_session)); ret = 1; +#ifdef MBEDTLS_SSL_DTLS_CONNECTION_ID +#if COAP_CLIENT_SUPPORT + if (c_session->type == COAP_SESSION_TYPE_CLIENT && + c_session->proto == COAP_PROTO_DTLS) { + coap_mbedtls_context_t *m_context; + + m_context = (coap_mbedtls_context_t *)c_session->context->dtls_context; + if ((m_context->psk_pki_enabled & IS_PSK && c_session->cpsk_setup_data.use_cid) || + m_context->setup_data.use_cid) { + unsigned char peer_cid[MBEDTLS_SSL_CID_OUT_LEN_MAX]; + int enabled; + size_t peer_cid_len; + + /* See whether CID was negotiated */ + if (mbedtls_ssl_get_peer_cid(&m_env->ssl, &enabled, peer_cid, &peer_cid_len) == 0 && + enabled == MBEDTLS_SSL_CID_ENABLED) { + c_session->negotiated_cid = 1; + } else { + coap_log_info("** %s: CID was not negotiated\n", coap_session_str(c_session)); + c_session->negotiated_cid = 0; + } + } + } +#endif /* COAP_CLIENT_SUPPORT */ +#endif /* MBEDTLS_SSL_DTLS_CONNECTION_ID */ break; case MBEDTLS_ERR_SSL_WANT_READ: case MBEDTLS_ERR_SSL_WANT_WRITE: @@ -1886,6 +1911,33 @@ coap_dtls_rpk_is_supported(void) { return 0; } +/* + * return 0 failed + * 1 passed + */ +int +coap_dtls_cid_is_supported(void) { +#ifdef MBEDTLS_SSL_DTLS_CONNECTION_ID + return 1; +#else /* ! MBEDTLS_SSL_DTLS_CONNECTION_ID */ + return 0; +#endif /* ! MBEDTLS_SSL_DTLS_CONNECTION_ID */ +} + +#if COAP_CLIENT_SUPPORT +int +coap_dtls_set_cid_tuple_change(coap_context_t *c_context, uint8_t every) { +#ifdef MBEDTLS_SSL_DTLS_CONNECTION_ID + c_context->testing_cids = every; + return 1; +#else /* ! MBEDTLS_SSL_DTLS_CONNECTION_ID */ + (void)c_context; + (void)every; + return 0; +#endif /* ! MBEDTLS_SSL_DTLS_CONNECTION_ID */ +} +#endif /* COAP_CLIENT_SUPPORT */ + void * coap_dtls_new_context(coap_context_t *c_context) { coap_mbedtls_context_t *m_context; diff --git a/src/coap_net.c b/src/coap_net.c index 5827a023ca..91a1516309 100644 --- a/src/coap_net.c +++ b/src/coap_net.c @@ -459,13 +459,14 @@ coap_context_set_keepalive(coap_context_t *context, unsigned int seconds) { context->ping_timeout = seconds; } -void +int coap_context_set_cid_tuple_change(coap_context_t *context, uint8_t every) { #if COAP_CLIENT_SUPPORT - context->testing_cids = every; + return coap_dtls_set_cid_tuple_change(context, every); #else /* ! COAP_CLIENT_SUPPORT */ (void)context; (void)every; + return 0; #endif /* ! COAP_CLIENT_SUPPORT */ } diff --git a/src/coap_notls.c b/src/coap_notls.c index 02239e2fc5..0fc6c52d26 100644 --- a/src/coap_notls.c +++ b/src/coap_notls.c @@ -78,6 +78,24 @@ coap_dtls_rpk_is_supported(void) { return 0; } +/* + * return 0 failed + * 1 passed + */ +int +coap_dtls_cid_is_supported(void) { + return 0; +} + +#if COAP_CLIENT_SUPPORT +int +coap_dtls_set_cid_tuple_change(coap_context_t *c_context, uint8_t every) { + (void)c_context; + (void)every; + return 0; +} +#endif /* COAP_CLIENT_SUPPORT */ + coap_tls_version_t * coap_get_tls_library_version(void) { static coap_tls_version_t version; diff --git a/src/coap_openssl.c b/src/coap_openssl.c index 535d536f81..a8ed48ebcd 100644 --- a/src/coap_openssl.c +++ b/src/coap_openssl.c @@ -256,6 +256,24 @@ coap_dtls_rpk_is_supported(void) { return 0; } +/* + * return 0 failed + * 1 passed + */ +int +coap_dtls_cid_is_supported(void) { + return 0; +} + +#if COAP_CLIENT_SUPPORT +int +coap_dtls_set_cid_tuple_change(coap_context_t *c_context, uint8_t every) { + (void)c_context; + (void)every; + return 0; +} +#endif /* COAP_CLIENT_SUPPORT */ + coap_tls_version_t * coap_get_tls_library_version(void) { static coap_tls_version_t version; diff --git a/src/coap_session.c b/src/coap_session.c index 1545735b3f..f0e790cc1e 100644 --- a/src/coap_session.c +++ b/src/coap_session.c @@ -1148,6 +1148,7 @@ coap_endpoint_get_session(coap_endpoint_t *endpoint, #define DTLS_HT_CLIENT_HELLO 1 /* Client Hello handshake type */ #define DTLS_CT_CID 25 /* Content Type Connection ID */ #define OFF_CID 11 /* offset of CID in dtls_record_handshake_t */ +#define OFF_CID_DTLS13 1 /* offset of CID in DTLS1.3 Unified Header */ const uint8_t *payload = (const uint8_t *)packet->payload; size_t length = packet->length; @@ -1157,18 +1158,24 @@ coap_endpoint_get_session(coap_endpoint_t *endpoint, OFF_HANDSHAKE_TYPE + 1); return NULL; } - if (payload[OFF_CONTENT_TYPE] == DTLS_CT_CID) { + if ((payload[OFF_CONTENT_TYPE] & 0x30) == 0x30 || + payload[OFF_CONTENT_TYPE] == DTLS_CT_CID) { /* Client may have changed its IP address */ int changed = 0; SESSIONS_ITER(endpoint->sessions, session, rtmp) { if (session->client_cid) { - if (memcmp(session->client_cid->s, &payload[OFF_CID], - session->client_cid->length) == 0) { + if ((session->is_dtls13 && (payload[OFF_CONTENT_TYPE] & 0x30) == 0x30 && + memcmp(session->client_cid->s, &payload[OFF_CID_DTLS13], + session->client_cid->length) == 0) || + (!session->is_dtls13 && payload[OFF_CONTENT_TYPE] == DTLS_CT_CID && + memcmp(session->client_cid->s, &payload[OFF_CID], + session->client_cid->length) == 0)) { /* Updating IP address */ coap_log_info("***%s: CID: Old Client Session\n", coap_session_str(session)); SESSIONS_DELETE(endpoint->sessions, session); session->addr_info = packet->addr_info; + memcpy(&session->addr_hash, &addr_hash, sizeof(session->addr_hash)); SESSIONS_ADD(endpoint->sessions, session); coap_log_info("***%s: CID: New Client Session\n", coap_session_str(session)); return session; @@ -1184,7 +1191,8 @@ coap_endpoint_get_session(coap_endpoint_t *endpoint, /* only log if not a late alert */ if (payload[OFF_CONTENT_TYPE] != DTLS_CT_ALERT) coap_log_debug("coap_dtls_hello: ContentType %d Handshake %d dropped\n", - payload[OFF_CONTENT_TYPE], payload[OFF_HANDSHAKE_TYPE]); + payload[OFF_CONTENT_TYPE], + payload[OFF_HANDSHAKE_TYPE]); return NULL; } } diff --git a/src/coap_tinydtls.c b/src/coap_tinydtls.c index c1bdf526f5..27c0200d8c 100644 --- a/src/coap_tinydtls.c +++ b/src/coap_tinydtls.c @@ -47,6 +47,9 @@ typedef struct coap_tiny_context_t { coap_binary_t *priv_key; coap_binary_t *pub_key; #endif /* DTLS_ECC */ +#if (DTLS_MAX_CID_LENGTH > 0) + uint8_t use_cid; +#endif /* DTLS_MAX_CID_LENGTH > 0 */ } coap_tiny_context_t; #if ! defined(DTLS_PSK) && ! defined(DTLS_ECC) @@ -105,6 +108,37 @@ coap_dtls_rpk_is_supported(void) { #endif /* ! DTLS_ECC */ } +/* + * return 0 failed + * 1 passed + */ +int +coap_dtls_cid_is_supported(void) { +#if (DTLS_MAX_CID_LENGTH > 0) + return 1; +#else /* ! DTLS_MAX_CID_LENGTH > 0 */ + return 0; +#endif /* ! DTLS_MAX_CID_LENGTH > 0 */ +} + +#if COAP_CLIENT_SUPPORT +/* + * TinyDTLS only supports client CID if compiled appropriately, and + * has CID support (i.e DTLS_MAX_CID_LENGTH is defined and used). + */ +int +coap_dtls_set_cid_tuple_change(coap_context_t *c_context, uint8_t every) { +#if (DTLS_MAX_CID_LENGTH > 0) + c_context->testing_cids = every; + return 1; +#else /* ! DTLS_MAX_CID_LENGTH > 0 */ + (void)c_context; + (void)every; + return 0; +#endif /* ! DTLS_MAX_CID_LENGTH > 0 */ +} +#endif /* COAP_CLIENT_SUPPORT */ + static coap_log_t dtls_map_logging(log_t d_level) { /* DTLS_LOG_ERR is missing, so account for the gap */ @@ -580,6 +614,20 @@ get_psk_info(struct dtls_context_t *dtls_context, } #endif /* DTLS_PSK */ +static void +dtls_update_user_parameters(struct dtls_context_t *ctx, + session_t *session, dtls_user_parameters_t *user_parameters) { + (void) ctx; + (void) session; +#if (DTLS_MAX_CID_LENGTH > 0) + coap_tiny_context_t *t_context = + (coap_tiny_context_t *)dtls_get_app_data(ctx); + user_parameters->support_cid = t_context ? t_context->use_cid : 0; +#else /* ! DTLS_MAX_CID_LENGTH > 0 */ + (void)user_parameters; +#endif /* ! DTLS_MAX_CID_LENGTH > 0 */ +} + #ifdef DTLS_ECC static int get_ecdsa_key(struct dtls_context_t *dtls_context, @@ -658,9 +706,11 @@ verify_ecdsa_key(struct dtls_context_t *dtls_context COAP_UNUSED, } return 0; } + static dtls_handler_t ec_cb = { .write = dtls_send_to_peer, .read = dtls_application_data, + .get_user_parameters = dtls_update_user_parameters, .event = dtls_event, #ifdef DTLS_PSK .get_psk_info = NULL, @@ -673,6 +723,7 @@ static dtls_handler_t ec_cb = { static dtls_handler_t psk_cb = { .write = dtls_send_to_peer, .read = dtls_application_data, + .get_user_parameters = dtls_update_user_parameters, .event = dtls_event, #ifdef DTLS_PSK .get_psk_info = get_psk_info, @@ -830,10 +881,24 @@ coap_dtls_send(coap_session_t *session, /* COAP_EVENT_DTLS_CLOSED event reported in coap_session_disconnected_lkd() */ if (coap_event_dtls != COAP_EVENT_DTLS_CLOSED) coap_handle_event_lkd(session->context, coap_event_dtls, session); - if (coap_event_dtls == COAP_EVENT_DTLS_CONNECTED) + if (coap_event_dtls == COAP_EVENT_DTLS_CONNECTED) { +#if (DTLS_MAX_CID_LENGTH > 0) + if (session->type == COAP_SESSION_TYPE_CLIENT) { + dtls_peer_t *peer = dtls_get_peer(dtls_context, (session_t *)session->tls); + dtls_security_parameters_t *security = dtls_security_params(peer); + + if (security->write_cid_length > 0) { + session->negotiated_cid = 1; + } else { + coap_log_info("** %s: CID was not negotiated\n", coap_session_str(session)); + session->negotiated_cid = 0; + } + } +#endif /* DTLS_MAX_CID_LENGTH > 0 */ coap_session_connected(session); - else if (coap_event_dtls == COAP_EVENT_DTLS_CLOSED || coap_event_dtls == COAP_EVENT_DTLS_ERROR) + } else if (coap_event_dtls == COAP_EVENT_DTLS_CLOSED || coap_event_dtls == COAP_EVENT_DTLS_ERROR) { coap_session_disconnected_lkd(session, COAP_NACK_TLS_FAILED); + } } return res; @@ -899,9 +964,21 @@ coap_dtls_receive(coap_session_t *session, /* COAP_EVENT_DTLS_CLOSED event reported in coap_session_disconnected_lkd() */ if (coap_event_dtls != COAP_EVENT_DTLS_CLOSED) coap_handle_event_lkd(session->context, coap_event_dtls, session); - if (coap_event_dtls == COAP_EVENT_DTLS_CONNECTED) + if (coap_event_dtls == COAP_EVENT_DTLS_CONNECTED) { coap_session_connected(session); - else if (coap_event_dtls == COAP_EVENT_DTLS_CLOSED || coap_event_dtls == COAP_EVENT_DTLS_ERROR) { +#if (DTLS_MAX_CID_LENGTH > 0) + if (session->type == COAP_SESSION_TYPE_CLIENT) { + dtls_peer_t *peer = dtls_get_peer(dtls_context, (session_t *)session->tls); + dtls_security_parameters_t *security = dtls_security_params(peer); + + if (security->write_cid_length > 0) { + session->negotiated_cid = 1; + } else { + session->negotiated_cid = 0; + } + } +#endif /* DTLS_MAX_CID_LENGTH > 0 */ + } else if (coap_event_dtls == COAP_EVENT_DTLS_CLOSED || coap_event_dtls == COAP_EVENT_DTLS_ERROR) { coap_session_disconnected_lkd(session, COAP_NACK_TLS_FAILED); err = -1; } @@ -1445,6 +1522,14 @@ coap_dtls_context_set_pki(coap_context_t *ctx, } } + if (setup_data->use_cid) { +#if (DTLS_MAX_CID_LENGTH == 0) + coap_log_warn("TinyDTLS has no Connection-ID support\n"); +#endif /* DTLS_MAX_CID_LENGTH == 0 */ + } +#if (DTLS_MAX_CID_LENGTH > 0) + t_context->use_cid = setup_data->use_cid; +#endif /* DTLS_MAX_CID_LENGTH > 0 */ return 1; #else /* ! DTLS_ECC */ (void)ctx; @@ -1453,9 +1538,6 @@ coap_dtls_context_set_pki(coap_context_t *ctx, coap_log_warn("TinyDTLS not compiled with ECC support\n"); return 0; #endif /* ! DTLS_ECC */ - if (setup_data->use_cid) { - coap_log_warn("TinyDTLS has no Connection-ID support\n"); - } } int @@ -1469,15 +1551,25 @@ coap_dtls_context_set_pki_root_cas(coap_context_t *ctx COAP_UNUSED, #if COAP_CLIENT_SUPPORT int -coap_dtls_context_set_cpsk(coap_context_t *coap_context COAP_UNUSED, - coap_dtls_cpsk_t *setup_data - ) { +coap_dtls_context_set_cpsk(coap_context_t *coap_context, + coap_dtls_cpsk_t *setup_data) { + coap_tiny_context_t *t_context; + if (!setup_data) return 0; + t_context = (coap_tiny_context_t *)coap_context->dtls_context; + if (!t_context) + return 0; + if (setup_data->use_cid) { +#if (DTLS_MAX_CID_LENGTH == 0) coap_log_warn("TinyDTLS has no Connection-ID support\n"); +#endif /* DTLS_MAX_CID_LENGTH == 0 */ } +#if (DTLS_MAX_CID_LENGTH > 0) + t_context->use_cid = setup_data->use_cid; +#endif /* DTLS_MAX_CID_LENGTH > 0 */ #ifdef DTLS_PSK if (setup_data->ec_jpake) { coap_log_warn("TinyDTLS has no EC-JPAKE support\n"); diff --git a/src/coap_wolfssl.c b/src/coap_wolfssl.c index 71123b82a6..4c2083a59e 100644 --- a/src/coap_wolfssl.c +++ b/src/coap_wolfssl.c @@ -63,6 +63,11 @@ * If wolfSSL RPK support is required, then the wolfSSL library needs to be built with * $ ./configure CFLAGS="-DHAVE_RPK" * + * If wolfSSL CID support is required, then the wolfSSL library needs to be built with + * $ ./configure --enable-dtls13 --enable-dtlscid CFLAGS="-DDTLS_CID_MAX_SIZE=8" + * NOTE: For interoperability with MbedTLS, https://github.com/wolfSSL/wolfssl/pull/7841 + * needs to be installed. + * * When building the wolfSSL library from scratch, it is suggested that the library * built with * $ ./configure --enable-all @@ -368,6 +373,15 @@ coap_dtls_pkcs11_is_supported(void) { */ int coap_dtls_rpk_is_supported(void) { + return 0; +} + +/* + * return 0 failed + * 1 passed + */ +int +coap_dtls_cid_is_supported(void) { #if defined(HAVE_RPK) && LIBWOLFSSL_VERSION_HEX >= 0x05006004 return 1; #else /* ! HAVE_RPK || LIBWOLFSSL_VERSION_HEX < 0x05006004 */ @@ -375,6 +389,20 @@ coap_dtls_rpk_is_supported(void) { #endif /* ! HAVE_RPK || LIBWOLFSSL_VERSION_HEX < 0x05006004 */ } +#if COAP_CLIENT_SUPPORT +int +coap_dtls_set_cid_tuple_change(coap_context_t *c_context, uint8_t every) { +#if defined(WOLFSSL_DTLS_CID) + c_context->testing_cids = every; + return 1; +#else /* ! WOLFSSL_DTLS_CID */ + (void)c_context; + (void)every; + return 0; +#endif /* ! WOLFSSL_DTLS_CID */ +} +#endif /* COAP_CLIENT_SUPPORT */ + coap_tls_version_t * coap_get_tls_library_version(void) { static coap_tls_version_t version; @@ -1067,7 +1095,9 @@ coap_dtls_context_set_cpsk(coap_context_t *c_context, coap_log_warn("wolfSSL has no EC-JPAKE support\n"); } if (setup_data->use_cid) { +#if ! defined(WOLFSSL_DTLS_CID) coap_log_warn("wolfSSL has no Connection-ID support\n"); +#endif /* ! WOLFSSL_DTLS_CID */ } w_context->psk_pki_enabled |= IS_PSK; return 1; @@ -1768,7 +1798,9 @@ coap_dtls_context_set_pki(coap_context_t *ctx, w_context->psk_pki_enabled |= IS_PKI; if (setup_data->use_cid) { +#if ! defined(WOLFSSL_DTLS_CID) coap_log_warn("wolfSSL has no Connection-ID support\n"); +#endif /* ! WOLFSSL_DTLS_CID */ } return 1; } @@ -1908,6 +1940,24 @@ coap_dtls_new_server_session(coap_session_t *session) { } #endif /* WOLFSSL_DTLS_CH_FRAG && WOLFSSL_DTLS13 */ +#if defined(WOLFSSL_DTLS_CID) && defined(WOLFSSL_DTLS13) + +#if COAP_DTLS_CID_LENGTH > DTLS_CID_MAX_SIZE +#bad COAP_DTLS_CID_LENGTH > DTLS_CID_MAX_SIZE +#endif /* COAP_DTLS_CID_LENGTH > DTLS_CID_MAX_SIZE */ + + if (wolfSSL_dtls_cid_use(ssl) != WOLFSSL_SUCCESS) + goto error; + u_char cid[COAP_DTLS_CID_LENGTH]; + /* + * Enable server DTLS CID support. + */ + coap_prng_lkd(cid, sizeof(cid)); + if (wolfSSL_dtls_cid_set(ssl, cid, sizeof(cid)) != WOLFSSL_SUCCESS) + goto error; + session->client_cid = coap_new_bin_const(cid, sizeof(cid)); +#endif /* WOLFSSL_DTLS_CID && WOLFSSL_DTLS13 */ + coap_ticks(&now); w_env->last_timeout = now; w_env->ssl = ssl; @@ -1965,6 +2015,18 @@ setup_client_ssl_session(coap_session_t *session, WOLFSSL *ssl) { setup_data->client_sni); } wolfSSL_set_psk_client_callback(ssl, coap_dtls_psk_client_callback); + +#if defined(WOLFSSL_DTLS_CID) && defined(WOLFSSL_DTLS13) + if (setup_data->use_cid) { + if (wolfSSL_dtls_cid_use(ssl) != WOLFSSL_SUCCESS) + return 0; + /* + * Enable client DTLS CID negotiation. + */ + if (wolfSSL_dtls_cid_set(ssl, NULL, 0) != WOLFSSL_SUCCESS) + return 0; + } +#endif /* WOLFSSL_DTLS_CID && WOLFSSL_DTLS13 */ } if (w_context->psk_pki_enabled & IS_PKI) { coap_dtls_pki_t *setup_data = &w_context->setup_data; @@ -2009,6 +2071,18 @@ setup_client_ssl_session(coap_session_t *session, WOLFSSL *ssl) { if (setup_data->cert_chain_validation) wolfSSL_set_verify_depth(ssl, setup_data->cert_chain_verify_depth + 1); +#if defined(WOLFSSL_DTLS_CID) && defined(WOLFSSL_DTLS13) + if (setup_data->use_cid) { + if (wolfSSL_dtls_cid_use(ssl) != WOLFSSL_SUCCESS) + return 0; + /* + * Enable client DTLS CID negotiation. + */ + if (wolfSSL_dtls_cid_set(ssl, NULL, 0) != WOLFSSL_SUCCESS) + return 0; + } +#endif /* WOLFSSL_DTLS_CID && WOLFSSL_DTLS13 */ + } return 1; } @@ -2270,6 +2344,22 @@ coap_dtls_receive(coap_session_t *session, const uint8_t *data, size_t data_len) if (in_init && wolfSSL_is_init_finished(ssl)) { coap_dtls_log(COAP_LOG_INFO, "* %s: Using cipher: %s\n", coap_session_str(session), wolfSSL_get_cipher((ssl))); +#if defined(WOLFSSL_DTLS_CID) && defined(WOLFSSL_DTLS13) && COAP_CLIENT_SUPPORT + if (session->type == COAP_SESSION_TYPE_CLIENT && + session->proto == COAP_PROTO_DTLS) { + if (wolfSSL_dtls_cid_is_enabled(ssl)) { + session->negotiated_cid = 1; + } else { + coap_log_info("** %s: CID was not negotiated\n", coap_session_str(session)); + session->negotiated_cid = 0; + } + } +#endif /* WOLFSSL_DTLS_CID && WOLFSSL_DTLS13 && COAP_CLIENT_SUPPORT */ + if (!strcmp(wolfSSL_get_version(ssl), "DTLSv1.3")) { + session->is_dtls13 = 1; + } else { + session->is_dtls13 = 0; + } coap_handle_event_lkd(session->context, COAP_EVENT_DTLS_CONNECTED, session); session->sock.lfunc[COAP_LAYER_TLS].l_establish(session); }