From a4dabec1fa978ded10ddd2eb586d3786cbab69a0 Mon Sep 17 00:00:00 2001 From: Jon Shallow Date: Mon, 22 Jul 2024 15:39:16 +0100 Subject: [PATCH] Connection-ID: Only change source port when CID has been negotiated Only support changing the client's source port if the DTLS library has support / configured for CID. Used when debugging server handling source address changes and CID is in use. Add in support for TinyDTLS (Client only) if TinyDTLS is patched appropriately (not currently available on TinyDTLS main branch). Add in new function coap_dtls_cid_is_supported(). --- examples/coap-client.c | 8 +- include/coap3/coap_dtls.h | 2 + include/coap3/coap_dtls_internal.h | 11 +++ include/coap3/coap_net.h | 4 +- include/coap3/coap_session_internal.h | 4 + libcoap-3.map | 1 + libcoap-3.sym | 1 + man/coap_context.txt.in | 7 +- src/coap_debug.c | 4 +- src/coap_gnutls.c | 18 +++++ src/coap_io.c | 3 +- src/coap_mbedtls.c | 52 ++++++++++++ src/coap_net.c | 5 +- src/coap_notls.c | 18 +++++ src/coap_openssl.c | 18 +++++ src/coap_session.c | 16 +++- src/coap_tinydtls.c | 112 +++++++++++++++++++++++--- src/coap_wolfssl.c | 88 ++++++++++++++++++++ 18 files changed, 349 insertions(+), 23 deletions(-) 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..dca6a287dd 100644 --- a/src/coap_wolfssl.c +++ b/src/coap_wolfssl.c @@ -63,6 +63,9 @@ * 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" + * * When building the wolfSSL library from scratch, it is suggested that the library * built with * $ ./configure --enable-all @@ -368,6 +371,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 +387,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 +1093,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 +1796,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 +1938,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 +2013,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 +2069,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 +2342,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); }