Skip to content

Commit 9908754

Browse files
committed
net: sockets: tls: Add new option to register certificate verify cb
Add new TLS socket option, TLS_CERT_VERIFY_CALLBACK, which allows to register an application callback to verify certificates obtained during the TLS handshake. Signed-off-by: Robert Lubos <[email protected]>
1 parent cae8dd3 commit 9908754

File tree

3 files changed

+86
-0
lines changed

3 files changed

+86
-0
lines changed

include/zephyr/net/socket.h

+26
Original file line numberDiff line numberDiff line change
@@ -247,6 +247,19 @@ extern "C" {
247247
* section of x509.h header.
248248
*/
249249
#define TLS_CERT_VERIFY_RESULT 19
250+
/** Write-only socket option to configure certificate verification callback for
251+
* the socket. The option accepts a pointer to @ref tls_cert_verify_cb
252+
* structure, which contains pointers to the actual callback function and
253+
* application-defined context.
254+
*
255+
* If set, the certificate verification is delegated to the registered callback.
256+
* In such case it's the application responsibility to verify the provided
257+
* certificates and decide whether to proceed or abort the handshake.
258+
*
259+
* The option is only available if CONFIG_NET_SOCKETS_TLS_CERT_VERIFY_CALLBACK
260+
* Kconfig option is enabled.
261+
*/
262+
#define TLS_CERT_VERIFY_CALLBACK 20
250263

251264
/* Valid values for @ref TLS_PEER_VERIFY option */
252265
#define TLS_PEER_VERIFY_NONE 0 /**< Peer verification disabled. */
@@ -275,6 +288,19 @@ extern "C" {
275288
#define TLS_DTLS_CID_STATUS_DOWNLINK 1 /**< CID is in use by us */
276289
#define TLS_DTLS_CID_STATUS_UPLINK 2 /**< CID is in use by peer */
277290
#define TLS_DTLS_CID_STATUS_BIDIRECTIONAL 3 /**< CID is in use by us and peer */
291+
292+
/** Data structure for @ref TLS_CERT_VERIFY_CALLBACK socket option. */
293+
struct tls_cert_verify_cb {
294+
/** A pointer to the certificate verification callback function.
295+
*
296+
* The actual callback function type is defined by mbed TLS, see
297+
* documentation of @ref mbedtls_x509_crt_verify function.
298+
*/
299+
void *cb;
300+
301+
/** A pointer to an opaque context passed to the callback. */
302+
void *ctx;
303+
};
278304
/** @} */ /* for @name */
279305
/** @} */ /* for @defgroup */
280306

subsys/net/lib/sockets/Kconfig

+8
Original file line numberDiff line numberDiff line change
@@ -243,6 +243,14 @@ config NET_SOCKETS_TLS_MAX_CLIENT_SESSION_COUNT
243243
This variable specifies maximum number of stored TLS/DTLS sessions,
244244
used for TLS/DTLS session resumption.
245245

246+
config NET_SOCKETS_TLS_CERT_VERIFY_CALLBACK
247+
bool "TLS certificate verification callback support"
248+
depends on NET_SOCKETS_SOCKOPT_TLS
249+
help
250+
This option controls whether TLS_CERT_VERIFY_CALLBACK TLS socket option
251+
is available to use. It allows to register a certificate verification
252+
callback, which is called by the TLS backend during the TLS handshake.
253+
246254
config NET_SOCKETS_OFFLOAD
247255
bool "Offload Socket APIs"
248256
help

subsys/net/lib/sockets/sockets_tls.c

+52
Original file line numberDiff line numberDiff line change
@@ -207,6 +207,10 @@ __net_socket struct tls_context {
207207

208208
bool dtls_handshake_on_connect;
209209
#endif /* CONFIG_NET_SOCKETS_ENABLE_DTLS */
210+
211+
#if defined(CONFIG_NET_SOCKETS_TLS_CERT_VERIFY_CALLBACK)
212+
struct tls_cert_verify_cb cert_verify;
213+
#endif /* CONFIG_NET_SOCKETS_TLS_CERT_VERIFY_CALLBACK */
210214
} options;
211215

212216
#if defined(CONFIG_NET_SOCKETS_ENABLE_DTLS)
@@ -1425,6 +1429,14 @@ static int tls_mbedtls_init(struct tls_context *context, bool is_server)
14251429
mbedtls_ssl_conf_early_data(&context->config, MBEDTLS_SSL_EARLY_DATA_ENABLED);
14261430
#endif
14271431

1432+
#if defined(CONFIG_NET_SOCKETS_TLS_CERT_VERIFY_CALLBACK)
1433+
if (context->options.cert_verify.cb != NULL) {
1434+
mbedtls_ssl_conf_verify(&context->config,
1435+
context->options.cert_verify.cb,
1436+
context->options.cert_verify.ctx);
1437+
}
1438+
#endif /* CONFIG_NET_SOCKETS_TLS_CERT_VERIFY_CALLBACK */
1439+
14281440
ret = mbedtls_ssl_setup(&context->ssl,
14291441
&context->config);
14301442
if (ret != 0) {
@@ -2044,6 +2056,42 @@ static int tls_opt_dtls_role_set(struct tls_context *context,
20442056
return 0;
20452057
}
20462058

2059+
#if defined(CONFIG_NET_SOCKETS_TLS_CERT_VERIFY_CALLBACK)
2060+
static int tls_opt_cert_verify_callback_set(struct tls_context *context,
2061+
const void *optval,
2062+
socklen_t optlen)
2063+
{
2064+
struct tls_cert_verify_cb *cert_verify;
2065+
2066+
if (!optval) {
2067+
return -EINVAL;
2068+
}
2069+
2070+
if (optlen != sizeof(struct tls_cert_verify_cb)) {
2071+
return -EINVAL;
2072+
}
2073+
2074+
cert_verify = (struct tls_cert_verify_cb *)optval;
2075+
if (cert_verify->cb == NULL && cert_verify->ctx != NULL) {
2076+
return -EINVAL;
2077+
}
2078+
2079+
context->options.cert_verify = *cert_verify;
2080+
2081+
return 0;
2082+
}
2083+
#else /* CONFIG_NET_SOCKETS_TLS_CERT_VERIFY_CALLBACK */
2084+
static int tls_opt_cert_verify_callback_set(struct tls_context *context,
2085+
const void *optval,
2086+
socklen_t optlen)
2087+
{
2088+
NET_ERR("TLS_CERT_VERIFY_CALLBACK option requires "
2089+
"CONFIG_NET_SOCKETS_TLS_CERT_VERIFY_CALLBACK enabled");
2090+
2091+
return -ENOPROTOOPT;
2092+
}
2093+
#endif /* CONFIG_NET_SOCKETS_TLS_CERT_VERIFY_CALLBACK */
2094+
20472095
static int protocol_check(int family, int type, int *proto)
20482096
{
20492097
if (family != AF_INET && family != AF_INET6) {
@@ -3631,6 +3679,10 @@ int ztls_setsockopt_ctx(struct tls_context *ctx, int level, int optname,
36313679
err = tls_opt_session_cache_purge_set(ctx, optval, optlen);
36323680
break;
36333681

3682+
case TLS_CERT_VERIFY_CALLBACK:
3683+
err = tls_opt_cert_verify_callback_set(ctx, optval, optlen);
3684+
break;
3685+
36343686
#if defined(CONFIG_NET_SOCKETS_ENABLE_DTLS)
36353687
case TLS_DTLS_HANDSHAKE_TIMEOUT_MIN:
36363688
err = tls_opt_dtls_handshake_timeout_set(ctx, optval,

0 commit comments

Comments
 (0)