Files
libcoap/include/coap3/coap_dtls_internal.h
T
Jon Shallow af024f9138 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().
2024-08-07 09:13:52 +01:00

498 lines
15 KiB
C

/*
* coap_dtls_internal.h -- (Datagram) Transport Layer Support for libcoap
*
* Copyright (C) 2016 Olaf Bergmann <bergmann@tzi.org>
* Copyright (C) 2017 Jean-Claude Michelou <jcm@spinetix.com>
* Copyright (C) 2023-2024 Jon Shallow <supjps-libcoap@jpshallow.com>
*
* SPDX-License-Identifier: BSD-2-Clause
*
* This file is part of the CoAP library libcoap. Please see README for terms
* of use.
*/
/**
* @file coap_dtls_internal.h
* @brief Internal CoAP DTLS support
*/
#ifndef COAP_DTLS_INTERNAL_H_
#define COAP_DTLS_INTERNAL_H_
#include "coap_internal.h"
/**
* @ingroup internal_api
* @defgroup dtls_internal DTLS Support
* Internal API for DTLS Support
* @{
*/
/* https://rfc-editor.org/rfc/rfc6347#section-4.2.4.1 */
#ifndef COAP_DTLS_RETRANSMIT_MS
#define COAP_DTLS_RETRANSMIT_MS 1000
#endif
#ifndef COAP_DTLS_RETRANSMIT_TOTAL_MS
#define COAP_DTLS_RETRANSMIT_TOTAL_MS 60000
#endif
#define COAP_DTLS_RETRANSMIT_COAP_TICKS (COAP_DTLS_RETRANSMIT_MS * COAP_TICKS_PER_SECOND / 1000)
/* For RFC9146 Connection ID support */
#ifndef COAP_DTLS_CID_LENGTH
#define COAP_DTLS_CID_LENGTH 8
#endif
typedef enum {
COAP_DEFINE_KEY_CA,
COAP_DEFINE_KEY_ROOT_CA,
COAP_DEFINE_KEY_PUBLIC,
COAP_DEFINE_KEY_PRIVATE
} coap_define_issue_key_t;
typedef enum {
COAP_DEFINE_FAIL_BAD,
COAP_DEFINE_FAIL_NOT_SUPPORTED,
COAP_DEFINE_FAIL_NONE
} coap_define_issue_fail_t;
/**
* Creates a new DTLS context for the given @p coap_context. This function
* returns a pointer to a new DTLS context object or @c NULL on error.
*
* @param coap_context The CoAP context where the DTLS object shall be used.
*
* @return A DTLS context object or @c NULL on error.
*/
void *coap_dtls_new_context(coap_context_t *coap_context);
#if COAP_SERVER_SUPPORT
/**
* Set the DTLS context's default server PSK information.
* This does the PSK specifics following coap_dtls_new_context().
*
* @param coap_context The CoAP context.
* @param setup_data A structure containing setup data originally passed into
* coap_context_set_psk2().
*
* @return @c 1 if successful, else @c 0.
*/
int coap_dtls_context_set_spsk(coap_context_t *coap_context,
coap_dtls_spsk_t *setup_data);
#endif /* COAP_SERVER_SUPPORT */
#if COAP_CLIENT_SUPPORT
/**
* Set the DTLS context's default client PSK information.
* This does the PSK specifics following coap_dtls_new_context().
*
* @param coap_context The CoAP context.
* @param setup_data A structure containing setup data originally passed into
* coap_new_client_session_psk2_lkd().
*
* @return @c 1 if successful, else @c 0.
*/
int coap_dtls_context_set_cpsk(coap_context_t *coap_context,
coap_dtls_cpsk_t *setup_data);
#endif /* COAP_CLIENT_SUPPORT */
/**
* Set the DTLS context's default server PKI information.
* This does the PKI specifics following coap_dtls_new_context().
* If @p COAP_DTLS_ROLE_SERVER, then the information will get put into the
* TLS library's context (from which sessions are derived).
* If @p COAP_DTLS_ROLE_CLIENT, then the information will get put into the
* TLS library's session.
*
* @param coap_context The CoAP context.
* @param setup_data Setup information defining how PKI is to be setup.
* Required parameter. If @p NULL, PKI will not be
* set up.
* @param role One of @p COAP_DTLS_ROLE_CLIENT or @p COAP_DTLS_ROLE_SERVER
*
* @return @c 1 if successful, else @c 0.
*/
int coap_dtls_context_set_pki(coap_context_t *coap_context,
const coap_dtls_pki_t *setup_data,
const coap_dtls_role_t role);
/**
* Set the dtls context's default Root CA information for a client or server.
*
* @param coap_context The current coap_context_t object.
* @param ca_file If not @p NULL, is the full path name of a PEM encoded
* file containing all the Root CAs to be used.
* @param ca_dir If not @p NULL, points to a directory containing PEM
* encoded files containing all the Root CAs to be used.
*
* @return @c 1 if successful, else @c 0.
*/
int coap_dtls_context_set_pki_root_cas(coap_context_t *coap_context,
const char *ca_file,
const char *ca_dir);
/**
* Check whether one of the coap_dtls_context_set_{psk|pki}() functions have
* been called.
*
* @param coap_context The current coap_context_t object.
*
* @return @c 1 if coap_dtls_context_set_{psk|pki}() called, else @c 0.
*/
int coap_dtls_context_check_keys_enabled(coap_context_t *coap_context);
/**
* Releases the storage allocated for @p dtls_context.
*
* @param dtls_context The DTLS context as returned by coap_dtls_new_context().
*/
void coap_dtls_free_context(void *dtls_context);
#if COAP_CLIENT_SUPPORT
/**
* Create a new client-side session. This should send a HELLO to the server.
*
* @param coap_session The CoAP session.
*
* @return Opaque handle to underlying TLS library object containing security
* parameters for the session.
*/
void *coap_dtls_new_client_session(coap_session_t *coap_session);
#endif /* COAP_CLIENT_SUPPORT */
#if COAP_SERVER_SUPPORT
/**
* Create a new DTLS server-side session.
* Called after coap_dtls_hello() has returned @c 1, signalling that a validated
* HELLO was received from a client.
* This should send a HELLO to the server.
*
* @param coap_session The CoAP session.
*
* @return Opaque handle to underlying TLS library object containing security
* parameters for the DTLS session.
*/
void *coap_dtls_new_server_session(coap_session_t *coap_session);
#endif /* COAP_SERVER_SUPPORT */
/**
* Terminates the DTLS session (may send an ALERT if necessary) then frees the
* underlying TLS library object containing security parameters for the session.
*
* @param coap_session The CoAP session.
*/
void coap_dtls_free_session(coap_session_t *coap_session);
/**
* Notify of a change in the CoAP session's MTU, for example after
* a PMTU update.
*
* @param coap_session The CoAP session.
*/
void coap_dtls_session_update_mtu(coap_session_t *coap_session);
/**
* Send data to a DTLS peer.
*
* @param coap_session The CoAP session.
* @param data pointer to data.
* @param data_len Number of bytes to send.
*
* @return @c 0 if this would be blocking, @c -1 if there is an error or the
* number of cleartext bytes sent.
*/
ssize_t coap_dtls_send(coap_session_t *coap_session,
const uint8_t *data,
size_t data_len);
/**
* Check if timeout is handled per CoAP session or per CoAP context.
*
* @return @c 1 of timeout and retransmit is per context, @c 0 if it is
* per session.
*/
int coap_dtls_is_context_timeout(void);
/**
* Do all pending retransmits and get next timeout
*
* @param dtls_context The DTLS context.
*
* @return @c 0 if no event is pending or date of the next retransmit.
*/
coap_tick_t coap_dtls_get_context_timeout(void *dtls_context);
/**
* Get next timeout for this session.
*
* @param coap_session The CoAP session.
* @param now The current time in ticks.
*
* @return @c 0 If no event is pending or ticks time of the next retransmit.
*/
coap_tick_t coap_dtls_get_timeout(coap_session_t *coap_session,
coap_tick_t now);
/**
* Handle a DTLS timeout expiration.
*
* @param coap_session The CoAP session.
*
* @return @c 1 timed out or @c 0 still timing out
*/
int coap_dtls_handle_timeout(coap_session_t *coap_session);
/**
* Handling incoming data from a DTLS peer.
*
* @param coap_session The CoAP session.
* @param data Encrypted datagram.
* @param data_len Encrypted datagram size.
*
* @return Result of coap_handle_dgram on the decrypted CoAP PDU
* or @c -1 for error.
*/
int coap_dtls_receive(coap_session_t *coap_session,
const uint8_t *data,
size_t data_len);
#if COAP_SERVER_SUPPORT
/**
* Handling client HELLO messages from a new candiate peer.
* Note that session->tls is empty.
*
* @param coap_session The CoAP session.
* @param data Encrypted datagram.
* @param data_len Encrypted datagram size.
*
* @return @c 0 if a cookie verification message has been sent, @c 1 if the
* HELLO contains a valid cookie and a server session should be created,
* @c -1 if the message is invalid.
*/
int coap_dtls_hello(coap_session_t *coap_session,
const uint8_t *data,
size_t data_len);
#endif /* COAP_SERVER_SUPPORT */
/**
* Layer function interface for layer below DTLS connect being
* established.
*
* If this layer is properly established on invocation, then the next layer
* must get called by calling
* session->lfunc[COAP_LAYER_TLS].establish(session)
* (or done at any point when DTLS is established).
*
* @param session Session that the lower layer connect was done on.
*
*/
void coap_dtls_establish(coap_session_t *session);
/**
* Layer function interface for DTLS close for a session.
*
* @param session Session to do the DTLS close on.
*/
void coap_dtls_close(coap_session_t *session);
/**
* Get DTLS overhead over cleartext PDUs.
*
* @param coap_session The CoAP session.
*
* @return Maximum number of bytes added by DTLS layer.
*/
unsigned int coap_dtls_get_overhead(coap_session_t *coap_session);
#if COAP_CLIENT_SUPPORT
/**
* Create a new TLS client-side session.
*
* @param coap_session The CoAP session.
*
* @return Opaque handle to underlying TLS library object containing security
* parameters for the session.
*/
void *coap_tls_new_client_session(coap_session_t *coap_session);
#endif /* COAP_CLIENT_SUPPORT */
#if COAP_SERVER_SUPPORT
/**
* Create a TLS new server-side session.
*
* @param coap_session The CoAP session.
*
* @return Opaque handle to underlying TLS library object containing security
* parameters for the session.
*/
void *coap_tls_new_server_session(coap_session_t *coap_session);
#endif /* COAP_SERVER_SUPPORT */
/**
* Terminates the TLS session (may send an ALERT if necessary) then frees the
* underlying TLS library object containing security parameters for the session.
*
* @param coap_session The CoAP session.
*/
void coap_tls_free_session(coap_session_t *coap_session);
/**
* Send data to a TLS peer, with implicit flush.
*
* @param coap_session The CoAP session.
* @param data Pointer to data.
* @param data_len Number of bytes to send.
*
* @return @c 0 if this should be retried, @c -1 if there is an error
* or the number of cleartext bytes sent.
*/
ssize_t coap_tls_write(coap_session_t *coap_session,
const uint8_t *data,
size_t data_len
);
/**
* Read some data from a TLS peer.
*
* @param coap_session The CoAP session.
* @param data Pointer to data.
* @param data_len Maximum number of bytes to read.
*
* @return @c 0 if this should be retried, @c -1 if there is an error
* or the number of cleartext bytes read.
*/
ssize_t coap_tls_read(coap_session_t *coap_session,
uint8_t *data,
size_t data_len
);
/**
* Layer function interface for layer below TLS accept/connect being
* established. This function initiates an accept/connect at the TLS layer.
*
* If this layer is properly established on invocation, then the next layer
* must get called by calling
* session->lfunc[COAP_LAYER_TLS].establish(session)
* (or done at any point when TLS is established).
*
* @param session Session that the lower layer accept/connect was done on.
*
*/
void coap_tls_establish(coap_session_t *session);
/**
* Layer function interface for TLS close for a session.
*
* @param session Session to do the TLS close on.
*/
void coap_tls_close(coap_session_t *session);
/**
* Get the current client's PSK key.
*
* @param coap_session The CoAP session.
*
* @return @c NULL if no key, else a pointer the current key.
*/
const coap_bin_const_t *coap_get_session_client_psk_key(
const coap_session_t *coap_session);
/**
* Get the current client's PSK identity.
*
* @param coap_session The CoAP session.
*
* @return @c NULL if no identity, else a pointer the current identity.
*/
const coap_bin_const_t *coap_get_session_client_psk_identity(
const coap_session_t *coap_session);
/**
* Get the current server's PSK key.
*
* @param coap_session The CoAP session.
*
* @return @c NULL if no key, else a pointer the current key.
*/
const coap_bin_const_t *coap_get_session_server_psk_key(
const coap_session_t *coap_session);
/**
* Get the current server's PSK identity hint.
*
* @param coap_session The CoAP session.
*
* @return @c NULL if no hint, else a pointer the current hint.
*/
const coap_bin_const_t *coap_get_session_server_psk_hint(
const coap_session_t *coap_session);
/**
* Initialize the underlying (D)TLS Library layer.
*
*/
void coap_dtls_startup(void);
/**
* Close down the underlying (D)TLS Library layer.
*
*/
void coap_dtls_shutdown(void);
/**
* Get the actual (D)TLS object for the session.
*
* @param session The session.
* @param tls_lib Updated with the library type.
*
* @return The TLS information.
*/
void *coap_dtls_get_tls(const coap_session_t *session,
coap_tls_library_t *tls_lib);
/**
* Map the PKI key definitions to the new DEFINE format.
*
* @param setup_data The PKI definition.
* @param key Updated with the DEFINE format of the key definitions.
*
*/
void coap_dtls_map_key_type_to_define(const coap_dtls_pki_t *setup_data,
coap_dtls_key_t *key);
/**
* Report PKI DEFINE type issue
*
* @param type The type of key with the issue.
* @param fail Why the key is failing.
* @param key The key with the issue.
* @param role Whether this is for the Client or Server.
* @param ret Value to return.
*
* @return @c 0 as there is a failure.
*/
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);
/**
* 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 */