net: sockets: tls: Implement TLS_DTLS_CID option
Add TLS_DTLS_CID socket option, which enables to use the Connection ID extension for the DTLS session. The option provides control of the use of CID with the `setsockopt()` function. The value provided can disable, enable, and control whether to provide a CID to the peer. It uses a random self CID (if told to provide one to the peer) unless TLS_DTLS_CID_VALUE set previously. Add TLS_DTLS_CID_VALUE to get or set the CID sent to the peer, if any. Add TLS_DTLS_PEER_CID_VALUE to get the CID value provided by the peer, if any. Add TLS_DTLS_CID_STATUS to determine if CID used, and whether bidirectional or one way. Signed-off-by: Robert Lubos <robert.lubos@nordicsemi.no> Signed-off-by: Pete Skeggs <peter.skeggs@nordicsemi.no>
This commit is contained in:
parent
232e4ad6b8
commit
d8a96b1be0
|
@ -140,6 +140,7 @@ struct zsock_pollfd {
|
|||
*/
|
||||
#define TLS_DTLS_HANDSHAKE_TIMEOUT_MIN 8
|
||||
#define TLS_DTLS_HANDSHAKE_TIMEOUT_MAX 9
|
||||
|
||||
/** Socket option for preventing certificates from being copied to the mbedTLS
|
||||
* heap if possible. The option is only effective for DER certificates and is
|
||||
* ignored for PEM certificates.
|
||||
|
@ -165,7 +166,40 @@ struct zsock_pollfd {
|
|||
* This option accepts any value.
|
||||
*/
|
||||
#define TLS_SESSION_CACHE_PURGE 13
|
||||
|
||||
/** Write-only socket option to control DTLS CID.
|
||||
* The option accepts an integer, indicating the setting.
|
||||
* Accepted vaules for the option are: 0, 1 and 2.
|
||||
* Effective when set before connecting to the socket.
|
||||
* - 0 - DTLS CID will be disabled.
|
||||
* - 1 - DTLS CID will be enabled, and a 0 length CID value to be sent to the
|
||||
* peer.
|
||||
* - 2 - DTLS CID will be enabled, and the most recent value set with
|
||||
* TLS_DTLS_CID_VALUE will be sent to the peer. Otherwise, a random value
|
||||
* will be used.
|
||||
*/
|
||||
#define TLS_DTLS_CID 14
|
||||
/** Read-only socket option to get DTLS CID status.
|
||||
* The option accepts a pointer to an integer, indicating the setting upon
|
||||
* return.
|
||||
* Returned vaules for the option are:
|
||||
* - 0 - DTLS CID is disabled.
|
||||
* - 1 - DTLS CID is received on the downlink.
|
||||
* - 2 - DTLS CID is sent to the uplink.
|
||||
* - 3 - DTLS CID is used in both directions.
|
||||
*/
|
||||
#define TLS_DTLS_CID_STATUS 15
|
||||
/** Socket option to set or get the value of the DTLS connection ID to be
|
||||
* used for the DTLS session.
|
||||
* The option accepts a byte array, holding the CID value.
|
||||
*/
|
||||
#define TLS_DTLS_CID_VALUE 16
|
||||
/** Read-only socket option to get the value of the DTLS connection ID
|
||||
* received from the peer.
|
||||
* The option accepts a pointer to a byte array, holding the CID value upon
|
||||
* return. The optlen returned will be 0 if the peer did not provide a
|
||||
* connection ID, otherwise will contain the length of the CID value.
|
||||
*/
|
||||
#define TLS_DTLS_PEER_CID_VALUE 17
|
||||
/** @} */
|
||||
|
||||
/* Valid values for TLS_PEER_VERIFY option */
|
||||
|
@ -185,6 +219,17 @@ struct zsock_pollfd {
|
|||
#define TLS_SESSION_CACHE_DISABLED 0 /**< Disable TLS session caching. */
|
||||
#define TLS_SESSION_CACHE_ENABLED 1 /**< Enable TLS session caching. */
|
||||
|
||||
/* Valid values for TLS_DTLS_CID option */
|
||||
#define TLS_DTLS_CID_DISABLED 0
|
||||
#define TLS_DTLS_CID_SUPPORTED 1
|
||||
#define TLS_DTLS_CID_ENABLED 2
|
||||
|
||||
/* Valid values for TLS_DTLS_CID_STATUS option */
|
||||
#define TLS_DTLS_CID_STATUS_DISABLED 0
|
||||
#define TLS_DTLS_CID_STATUS_DOWNLINK 1
|
||||
#define TLS_DTLS_CID_STATUS_UPLINK 2
|
||||
#define TLS_DTLS_CID_STATUS_BIDIRECTIONAL 3
|
||||
|
||||
struct zsock_addrinfo {
|
||||
struct zsock_addrinfo *ai_next;
|
||||
int ai_flags;
|
||||
|
|
|
@ -112,6 +112,15 @@ struct tls_session_cache {
|
|||
size_t session_len;
|
||||
};
|
||||
|
||||
#if defined(CONFIG_NET_SOCKETS_ENABLE_DTLS)
|
||||
struct tls_dtls_cid {
|
||||
bool enabled;
|
||||
unsigned char cid[MAX(MBEDTLS_SSL_CID_OUT_LEN_MAX,
|
||||
MBEDTLS_SSL_CID_IN_LEN_MAX)];
|
||||
size_t cid_len;
|
||||
};
|
||||
#endif
|
||||
|
||||
/** TLS context information. */
|
||||
__net_socket struct tls_context {
|
||||
/** Information whether TLS context is used. */
|
||||
|
@ -185,6 +194,8 @@ __net_socket struct tls_context {
|
|||
/* DTLS handshake timeout */
|
||||
uint32_t dtls_handshake_timeout_min;
|
||||
uint32_t dtls_handshake_timeout_max;
|
||||
|
||||
struct tls_dtls_cid dtls_cid;
|
||||
#endif /* CONFIG_NET_SOCKETS_ENABLE_DTLS */
|
||||
} options;
|
||||
|
||||
|
@ -446,6 +457,8 @@ static struct tls_context *tls_alloc(void)
|
|||
MBEDTLS_SSL_DTLS_TIMEOUT_DFL_MIN;
|
||||
tls->options.dtls_handshake_timeout_max =
|
||||
MBEDTLS_SSL_DTLS_TIMEOUT_DFL_MAX;
|
||||
tls->options.dtls_cid.cid_len = 0;
|
||||
tls->options.dtls_cid.enabled = false;
|
||||
#endif
|
||||
#if defined(MBEDTLS_X509_CRT_PARSE_C)
|
||||
mbedtls_x509_crt_init(&tls->ca_chain);
|
||||
|
@ -1291,6 +1304,18 @@ static int tls_mbedtls_init(struct tls_context *context, bool is_server)
|
|||
context->options.dtls_handshake_timeout_min,
|
||||
context->options.dtls_handshake_timeout_max);
|
||||
|
||||
#if defined(CONFIG_MBEDTLS_SSL_DTLS_CONNECTION_ID)
|
||||
if (context->options.dtls_cid.enabled) {
|
||||
ret = mbedtls_ssl_conf_cid(
|
||||
&context->config,
|
||||
context->options.dtls_cid.cid_len,
|
||||
MBEDTLS_SSL_UNEXPECTED_CID_IGNORE);
|
||||
if (ret != 0) {
|
||||
return -EINVAL;
|
||||
}
|
||||
}
|
||||
#endif /* CONFIG_MBEDTLS_SSL_DTLS_CONNECTION_ID */
|
||||
|
||||
/* Configure cookie for DTLS server */
|
||||
if (role == MBEDTLS_SSL_IS_SERVER) {
|
||||
ret = mbedtls_ssl_cookie_setup(&context->cookie,
|
||||
|
@ -1373,6 +1398,19 @@ static int tls_mbedtls_init(struct tls_context *context, bool is_server)
|
|||
return -ENOMEM;
|
||||
}
|
||||
|
||||
#if defined(CONFIG_NET_SOCKETS_ENABLE_DTLS) && defined(CONFIG_MBEDTLS_SSL_DTLS_CONNECTION_ID)
|
||||
if (type == MBEDTLS_SSL_TRANSPORT_DATAGRAM) {
|
||||
if (context->options.dtls_cid.enabled) {
|
||||
ret = mbedtls_ssl_set_cid(&context->ssl, MBEDTLS_SSL_CID_ENABLED,
|
||||
context->options.dtls_cid.cid,
|
||||
context->options.dtls_cid.cid_len);
|
||||
if (ret != 0) {
|
||||
return -EINVAL;
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif /* CONFIG_NET_SOCKETS_ENABLE_DTLS && CONFIG_MBEDTLS_SSL_DTLS_CONNECTION_ID */
|
||||
|
||||
context->is_initialized = true;
|
||||
|
||||
return 0;
|
||||
|
@ -1613,6 +1651,160 @@ static int tls_opt_dtls_handshake_timeout_set(struct tls_context *context,
|
|||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int tls_opt_dtls_connection_id_set(struct tls_context *context,
|
||||
const void *optval, socklen_t optlen)
|
||||
{
|
||||
#if defined(CONFIG_MBEDTLS_SSL_DTLS_CONNECTION_ID)
|
||||
int value;
|
||||
|
||||
if (optlen > 0 && optval == NULL) {
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
if (optlen != sizeof(int)) {
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
value = *((int *)optval);
|
||||
|
||||
switch (value) {
|
||||
case TLS_DTLS_CID_DISABLED:
|
||||
context->options.dtls_cid.enabled = false;
|
||||
context->options.dtls_cid.cid_len = 0;
|
||||
break;
|
||||
case TLS_DTLS_CID_SUPPORTED:
|
||||
context->options.dtls_cid.enabled = true;
|
||||
context->options.dtls_cid.cid_len = 0;
|
||||
break;
|
||||
case TLS_DTLS_CID_ENABLED:
|
||||
context->options.dtls_cid.enabled = true;
|
||||
if (context->options.dtls_cid.cid_len == 0) {
|
||||
/* generate random self cid */
|
||||
#if defined(CONFIG_ENTROPY_HAS_DRIVER)
|
||||
sys_csrand_get(context->options.dtls_cid.cid,
|
||||
MBEDTLS_SSL_CID_OUT_LEN_MAX);
|
||||
#else
|
||||
sys_rand_get(context->options.dtls_cid.cid,
|
||||
MBEDTLS_SSL_CID_OUT_LEN_MAX);
|
||||
#endif
|
||||
context->options.dtls_cid.cid_len = MBEDTLS_SSL_CID_OUT_LEN_MAX;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
return 0;
|
||||
#else
|
||||
return -ENOPROTOOPT;
|
||||
#endif /* CONFIG_MBEDTLS_SSL_DTLS_CONNECTION_ID */
|
||||
}
|
||||
|
||||
static int tls_opt_dtls_connection_id_value_set(struct tls_context *context,
|
||||
const void *optval,
|
||||
socklen_t optlen)
|
||||
{
|
||||
#if defined(CONFIG_MBEDTLS_SSL_DTLS_CONNECTION_ID)
|
||||
if (optlen > 0 && optval == NULL) {
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
if (optlen > MBEDTLS_SSL_CID_IN_LEN_MAX) {
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
context->options.dtls_cid.cid_len = optlen;
|
||||
memcpy(context->options.dtls_cid.cid, optval, optlen);
|
||||
|
||||
return 0;
|
||||
#else
|
||||
return -ENOPROTOOPT;
|
||||
#endif /* CONFIG_MBEDTLS_SSL_DTLS_CONNECTION_ID */
|
||||
}
|
||||
|
||||
static int tls_opt_dtls_connection_id_value_get(struct tls_context *context,
|
||||
void *optval, socklen_t *optlen)
|
||||
{
|
||||
#if defined(CONFIG_MBEDTLS_SSL_DTLS_CONNECTION_ID)
|
||||
|
||||
if (*optlen < context->options.dtls_cid.cid_len) {
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
*optlen = context->options.dtls_cid.cid_len;
|
||||
memcpy(optval, context->options.dtls_cid.cid, *optlen);
|
||||
|
||||
return 0;
|
||||
#else
|
||||
return -ENOPROTOOPT;
|
||||
#endif
|
||||
}
|
||||
|
||||
static int tls_opt_dtls_peer_connection_id_value_get(struct tls_context *context,
|
||||
void *optval,
|
||||
socklen_t *optlen)
|
||||
{
|
||||
#if defined(CONFIG_MBEDTLS_SSL_DTLS_CONNECTION_ID)
|
||||
int enabled = false;
|
||||
int ret;
|
||||
|
||||
ret = mbedtls_ssl_get_peer_cid(&context->ssl, &enabled, optval, optlen);
|
||||
if (!enabled) {
|
||||
*optlen = 0;
|
||||
}
|
||||
return ret;
|
||||
#else
|
||||
return -ENOPROTOOPT;
|
||||
#endif
|
||||
}
|
||||
|
||||
static int tls_opt_dtls_connection_id_status_get(struct tls_context *context,
|
||||
void *optval, socklen_t *optlen)
|
||||
{
|
||||
#if defined(CONFIG_MBEDTLS_SSL_DTLS_CONNECTION_ID)
|
||||
struct tls_dtls_cid cid;
|
||||
int ret;
|
||||
int val;
|
||||
int enabled;
|
||||
bool have_self_cid;
|
||||
bool have_peer_cid;
|
||||
|
||||
if (sizeof(int) != *optlen) {
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
ret = mbedtls_ssl_get_peer_cid(&context->ssl, &enabled,
|
||||
cid.cid,
|
||||
&cid.cid_len);
|
||||
if (ret) {
|
||||
/* Handshake is not complete */
|
||||
return -EAGAIN;
|
||||
}
|
||||
|
||||
cid.enabled = (enabled == MBEDTLS_SSL_CID_ENABLED);
|
||||
have_self_cid = (context->options.dtls_cid.cid_len != 0);
|
||||
have_peer_cid = (cid.cid_len != 0);
|
||||
|
||||
if (!context->options.dtls_cid.enabled) {
|
||||
val = TLS_DTLS_CID_STATUS_DISABLED;
|
||||
} else if (have_self_cid && have_peer_cid) {
|
||||
val = TLS_DTLS_CID_STATUS_BIDIRECTIONAL;
|
||||
} else if (have_self_cid) {
|
||||
val = TLS_DTLS_CID_STATUS_DOWNLINK;
|
||||
} else if (have_peer_cid) {
|
||||
val = TLS_DTLS_CID_STATUS_UPLINK;
|
||||
} else {
|
||||
val = TLS_DTLS_CID_STATUS_DISABLED;
|
||||
}
|
||||
|
||||
*((int *)optval) = val;
|
||||
return 0;
|
||||
#else
|
||||
return -ENOPROTOOPT;
|
||||
#endif
|
||||
}
|
||||
|
||||
#endif /* CONFIG_NET_SOCKETS_ENABLE_DTLS */
|
||||
|
||||
static int tls_opt_alpn_list_get(struct tls_context *context,
|
||||
|
@ -3004,6 +3196,20 @@ int ztls_getsockopt_ctx(struct tls_context *ctx, int level, int optname,
|
|||
err = tls_opt_dtls_handshake_timeout_get(ctx, optval,
|
||||
optlen, true);
|
||||
break;
|
||||
|
||||
case TLS_DTLS_CID_STATUS:
|
||||
err = tls_opt_dtls_connection_id_status_get(ctx, optval,
|
||||
optlen);
|
||||
break;
|
||||
|
||||
case TLS_DTLS_CID_VALUE:
|
||||
err = tls_opt_dtls_connection_id_value_get(ctx, optval, optlen);
|
||||
break;
|
||||
|
||||
case TLS_DTLS_PEER_CID_VALUE:
|
||||
err = tls_opt_dtls_peer_connection_id_value_get(ctx, optval,
|
||||
optlen);
|
||||
break;
|
||||
#endif /* CONFIG_NET_SOCKETS_ENABLE_DTLS */
|
||||
|
||||
default:
|
||||
|
@ -3108,6 +3314,15 @@ int ztls_setsockopt_ctx(struct tls_context *ctx, int level, int optname,
|
|||
err = tls_opt_dtls_handshake_timeout_set(ctx, optval,
|
||||
optlen, true);
|
||||
break;
|
||||
|
||||
case TLS_DTLS_CID:
|
||||
err = tls_opt_dtls_connection_id_set(ctx, optval, optlen);
|
||||
break;
|
||||
|
||||
case TLS_DTLS_CID_VALUE:
|
||||
err = tls_opt_dtls_connection_id_value_set(ctx, optval, optlen);
|
||||
break;
|
||||
|
||||
#endif /* CONFIG_NET_SOCKETS_ENABLE_DTLS */
|
||||
|
||||
case TLS_NATIVE:
|
||||
|
|
Loading…
Reference in a new issue