Skip to content

Commit

Permalink
avs_commons 5.4.0
Browse files Browse the repository at this point in the history
BREAKING CHANGES
- Default POSIX socket implementation now doesn't include ``errno.h`` if
  definition of ``EDOM`` (available by e.g. including lwIP's ``lwip/errno.h``)
  is included in ``AVS_COMMONS_POSIX_COMPAT_HEADER``.

Improvements
- Made MD5 length define publicly visible (for easier avs_stream_md5 usage)
- Made (D)TLS session resumption and persistence possible on Mbed TLS 3.0+ even
  when MBEDTLS_SSL_SRV_C is disabled

Bugfixes
- Added missing null guards in (D)TLS socket implementations so that all methods
  are now safe to call in any state
- When using lwIP, default POSIX socket implementation and appropriate compat
  header now include lwIP's ``lwip/errno.h`` instead of system ``errno.h``
  • Loading branch information
Kucmasz committed Sep 7, 2023
1 parent a227958 commit 5d578fc
Show file tree
Hide file tree
Showing 13 changed files with 152 additions and 102 deletions.
21 changes: 21 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,26 @@
# Changelog

## avs_commons 5.4.0 (September 7th, 2023)

### BREAKING CHANGES

* Default POSIX socket implementation now doesn't include ``errno.h`` if
definition of ``EDOM`` (available by e.g. including lwIP's ``lwip/errno.h``)
is included in ``AVS_COMMONS_POSIX_COMPAT_HEADER``.

### Improvements

* Made MD5 length define publicly visible (for easier avs_stream_md5 usage)
* Made (D)TLS session resumption and persistence possible on Mbed TLS 3.0+ even
when MBEDTLS_SSL_SRV_C is disabled

### Bugfixes

* Added missing null guards in (D)TLS socket implementations so that all methods
are now safe to call in any state
* When using lwIP, default POSIX socket implementation and appropriate compat
header now include lwIP's ``lwip/errno.h`` instead of system ``errno.h``

## avs_commons 5.3.1 (June 12th, 2023)

### Features
Expand Down
2 changes: 1 addition & 1 deletion CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@
cmake_minimum_required(VERSION 3.6.0)
project(avs_commons C)

set(AVS_COMMONS_VERSION "5.3.1")
set(AVS_COMMONS_VERSION "5.4.0")

################# DISTRIBUTION #################################################

Expand Down
3 changes: 3 additions & 0 deletions compat/lwip-posix-compat.h
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,9 @@

#include "lwipopts.h"

/* Provides lwIP's alternative errno header, used in avs_net_impl.c */
#include "lwip/errno.h"

/* Provides htons/ntohs/htonl/ntohl */
#include "lwip/inet.h"

Expand Down
6 changes: 3 additions & 3 deletions include_public/avsystem/commons/avs_errno_map.h
Original file line number Diff line number Diff line change
Expand Up @@ -23,9 +23,9 @@
extern "C" {
#endif

// Note: It might seem more appropriate to write #ifndef errno, but even though
// ISO C defines errno as being a macro, on some platforms (e.g. lwIP) it isn't
// a macro, but rather just an external linkage symbol.
// Note: It might seem more appropriate to write #ifndef errno, but wording
// seems to allow to errno to be not a macro, but an external linkage symbol and
// lwIP does just that.
#ifndef EDOM
# error "For this header to be useful, you have to include your system / library / whatever errno.h first."
#endif // EDOM
Expand Down
2 changes: 2 additions & 0 deletions include_public/avsystem/commons/avs_stream_md5.h
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,8 @@
extern "C" {
#endif

#define AVS_COMMONS_MD5_LENGTH 16

avs_stream_t *avs_stream_md5_create(void);

#ifdef __cplusplus
Expand Down
33 changes: 33 additions & 0 deletions src/crypto/mbedtls/avs_mbedtls_private.h
Original file line number Diff line number Diff line change
Expand Up @@ -165,6 +165,39 @@ static inline int mbedtls_ssl_is_handshake_over(mbedtls_ssl_context *ssl) {
return ssl->MBEDTLS_PRIVATE(state) == MBEDTLS_SSL_HANDSHAKE_OVER;
}
# endif // MBEDTLS_VERSION_NUMBER < 0x03020000

# ifndef MBEDTLS_SSL_SRV_C
// HACK: We (ab)use mbedtls_ssl_conf_session_cache() in avs_net to detect
// whether a (D)TLS session has been resumed or a new one has been created.
// However, this API is normally used for handling session cache, which only
// makes sense on the server side - hence, this function is only defined by
// Mbed TLS if MBEDTLS_SSL_SRV_C is enabled. However, the fields in
// mbedtls_ssl_config and the code that actually calls f_set_cache is compiled
// unconditionally. So we define our own clone of
// mbedtls_ssl_conf_session_cache() if MBEDTLS_SSL_SRV_C is disabled.
//
// Additionally, in Mbed TLS 2.x, there were no typedefs for the f_get_cache
// and f_set_cache function pointers. We define those here to make the setter
// below compatible with both 2.x and 3.x lines. Note that the f_get_cache and
// f_set_cache function signatures are different between Mbed TLS 2.x and 3.x -
// we define the 2.x variants here, because the typedefs are already there in
// 3.x. The difference in actual signatures is handled in avs_mbedtls_socket.c.
# if MBEDTLS_VERSION_NUMBER < 0x03000000
typedef int mbedtls_ssl_cache_get_t(void *data, mbedtls_ssl_session *session);
typedef int mbedtls_ssl_cache_set_t(void *data,
const mbedtls_ssl_session *session);
# endif // MBEDTLS_VERSION_NUMBER < 0x03000000

static inline void
mbedtls_ssl_conf_session_cache(mbedtls_ssl_config *conf,
void *p_cache,
mbedtls_ssl_cache_get_t *f_get_cache,
mbedtls_ssl_cache_set_t *f_set_cache) {
conf->MBEDTLS_PRIVATE(p_cache) = p_cache;
conf->MBEDTLS_PRIVATE(f_get_cache) = f_get_cache;
conf->MBEDTLS_PRIVATE(f_set_cache) = f_set_cache;
}
# endif // MBEDTLS_SSL_SRV_C
#endif // AVS_COMMONS_WITH_AVS_NET

#if defined(AVS_COMMONS_WITH_AVS_NET) \
Expand Down
56 changes: 44 additions & 12 deletions src/net/avs_ssl_common.h
Original file line number Diff line number Diff line change
Expand Up @@ -218,7 +218,11 @@ static const void *system_socket_ssl(avs_net_socket_t *socket_) {
static avs_error_t shutdown_ssl(avs_net_socket_t *socket_) {
LOG(TRACE, _("shutdown_ssl(socket=") "%p" _(")"), (void *) socket_);
ssl_socket_t *socket = (ssl_socket_t *) socket_;
return avs_net_socket_shutdown(socket->backend_socket);
if (socket->backend_socket) {
return avs_net_socket_shutdown(socket->backend_socket);
} else {
return avs_errno(AVS_EBADF);
}
}

static avs_error_t close_ssl(avs_net_socket_t *socket_) {
Expand All @@ -232,47 +236,72 @@ static avs_error_t
interface_name_ssl(avs_net_socket_t *ssl_socket_,
avs_net_socket_interface_name_t *if_name) {
ssl_socket_t *ssl_socket = (ssl_socket_t *) ssl_socket_;
return avs_net_socket_interface_name(ssl_socket->backend_socket, if_name);
if (ssl_socket->backend_socket) {
return avs_net_socket_interface_name(ssl_socket->backend_socket,
if_name);
} else {
return avs_errno(AVS_EBADF);
}
}

static avs_error_t remote_host_ssl(avs_net_socket_t *socket_,
char *out_buffer,
size_t out_buffer_size) {
ssl_socket_t *socket = (ssl_socket_t *) socket_;
return avs_net_socket_get_remote_host(socket->backend_socket, out_buffer,
out_buffer_size);
if (socket->backend_socket) {
return avs_net_socket_get_remote_host(socket->backend_socket,
out_buffer, out_buffer_size);
} else {
return avs_errno(AVS_EBADF);
}
}

static avs_error_t remote_hostname_ssl(avs_net_socket_t *socket_,
char *out_buffer,
size_t out_buffer_size) {
ssl_socket_t *socket = (ssl_socket_t *) socket_;
return avs_net_socket_get_remote_hostname(socket->backend_socket,
out_buffer, out_buffer_size);
if (socket->backend_socket) {
return avs_net_socket_get_remote_hostname(socket->backend_socket,
out_buffer, out_buffer_size);
} else {
return avs_errno(AVS_EBADF);
}
}

static avs_error_t remote_port_ssl(avs_net_socket_t *socket_,
char *out_buffer,
size_t out_buffer_size) {
ssl_socket_t *socket = (ssl_socket_t *) socket_;
return avs_net_socket_get_remote_port(socket->backend_socket, out_buffer,
out_buffer_size);
if (socket->backend_socket) {
return avs_net_socket_get_remote_port(socket->backend_socket,
out_buffer, out_buffer_size);
} else {
return avs_errno(AVS_EBADF);
}
}

static avs_error_t local_host_ssl(avs_net_socket_t *socket_,
char *out_buffer,
size_t out_buffer_size) {
ssl_socket_t *socket = (ssl_socket_t *) socket_;
return avs_net_socket_get_local_host(socket->backend_socket, out_buffer,
out_buffer_size);
if (socket->backend_socket) {
return avs_net_socket_get_local_host(socket->backend_socket, out_buffer,
out_buffer_size);
} else {
return avs_errno(AVS_EBADF);
}
}

static avs_error_t local_port_ssl(avs_net_socket_t *socket_,
char *out_buffer,
size_t out_buffer_size) {
ssl_socket_t *socket = (ssl_socket_t *) socket_;
return avs_net_socket_get_local_port(socket->backend_socket, out_buffer,
out_buffer_size);
if (socket->backend_socket) {
return avs_net_socket_get_local_port(socket->backend_socket, out_buffer,
out_buffer_size);
} else {
return avs_errno(AVS_EBADF);
}
}

static int get_socket_inner_mtu_or_zero(avs_net_socket_t *sock) {
Expand Down Expand Up @@ -413,6 +442,9 @@ static avs_error_t get_opt_ssl(avs_net_socket_t *ssl_socket_,
if (has_buffered_data(ssl_socket)) {
out_option_value->flag = true;
return AVS_OK;
} else if (!ssl_socket->backend_socket) {
out_option_value->flag = false;
return AVS_OK;
} else {
return avs_net_socket_get_opt(ssl_socket->backend_socket,
AVS_NET_SOCKET_HAS_BUFFERED_DATA,
Expand Down
12 changes: 11 additions & 1 deletion src/net/compat/posix/avs_net_impl.c
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,17 @@

# include <avs_commons_posix_init.h>

# include <errno.h>
// Some libraries, like lwIP, define their own errno.h-like header with own
// error macro mappings and definition of errno macro/symbol. This allows for
// including such headers in AVS_COMMONS_POSIX_COMPAT_HEADER and prevents from
// including errno.h defined by standard library.
//
// Note: It might seem more appropriate to write #ifndef errno, but ISO C seems
// to allow to errno to be not only a macro, but also an external linkage symbol
// and lwIP does just that.
# ifndef EDOM
# include <errno.h>
# endif // EDOM

# include <avsystem/commons/avs_errno_map.h>

Expand Down
87 changes: 16 additions & 71 deletions src/net/mbedtls/avs_mbedtls_socket.c
Original file line number Diff line number Diff line change
Expand Up @@ -227,10 +227,11 @@ avs_bio_recv(void *ctx, unsigned char *buf, size_t len, uint32_t timeout_ms) {
avs_net_socket_opt_value_t new_timeout;
size_t read_bytes;
int result;
if (avs_is_err((socket->bio_error = avs_net_socket_get_opt(
socket->backend_socket,
AVS_NET_SOCKET_OPT_RECV_TIMEOUT,
&orig_timeout)))) {
if (!socket->backend_socket
|| avs_is_err((socket->bio_error = avs_net_socket_get_opt(
socket->backend_socket,
AVS_NET_SOCKET_OPT_RECV_TIMEOUT,
&orig_timeout)))) {
return MBEDTLS_ERR_NET_RECV_FAILED;
}
new_timeout = orig_timeout;
Expand Down Expand Up @@ -258,8 +259,9 @@ avs_bio_recv(void *ctx, unsigned char *buf, size_t len, uint32_t timeout_ms) {

static int avs_bio_send(void *ctx, const unsigned char *buf, size_t len) {
ssl_socket_t *socket = (ssl_socket_t *) ctx;
if (avs_is_err((socket->bio_error = avs_net_socket_send(
socket->backend_socket, buf, len)))) {
if (!socket->backend_socket
|| avs_is_err((socket->bio_error = avs_net_socket_send(
socket->backend_socket, buf, len)))) {
return MBEDTLS_ERR_NET_SEND_FAILED;
} else {
return (int) len;
Expand Down Expand Up @@ -850,65 +852,24 @@ rng_function(void *ctx, unsigned char *out_buf, size_t out_buf_size) {
}

# ifdef AVS_COMMONS_NET_WITH_TLS_SESSION_PERSISTENCE
# ifdef MBEDTLS_SSL_SRV_C
static int fake_session_cache_set(void *socket_,
# if MBEDTLS_VERSION_NUMBER >= 0x03000000
# if MBEDTLS_VERSION_NUMBER >= 0x03000000
unsigned char const *session_id,
size_t session_id_len,
# endif // MBEDTLS_VERSION_NUMBER >= 0x03000000
# endif // MBEDTLS_VERSION_NUMBER >= 0x03000000
const mbedtls_ssl_session *session) {
ssl_socket_t *socket = (ssl_socket_t *) socket_;
# if MBEDTLS_VERSION_NUMBER >= 0x03000000
# if MBEDTLS_VERSION_NUMBER >= 0x03000000
(void) session_id;
(void) session_id_len;
# endif // MBEDTLS_VERSION_NUMBER >= 0x03000000
# endif // MBEDTLS_VERSION_NUMBER >= 0x03000000
(void) session;
// This will be called only if a new session has been established;
// not if one has been resumed.
socket->flags.session_fresh = true;
return 0;
}
# else // MBEDTLS_SSL_SRV_C
# if MBEDTLS_VERSION_NUMBER >= 0x03000000
# error "TLS session persistence is only supported with Mbed TLS >=3.0 if MBEDTLS_SSL_SRV_C is enabled"
# endif // MBEDTLS_VERSION_NUMBER >= 0x03000000
typedef struct {
# ifdef MBEDTLS_HAVE_TIME
mbedtls_time_t start;
# endif // MBEDTLS_HAVE_TIME
int ciphersuite;
int compression;
size_t id_len;
unsigned char id[sizeof(((mbedtls_ssl_session *) NULL)->id)];
} resumed_session_data_t;

static void session_copy(resumed_session_data_t *dest,
const mbedtls_ssl_session *src) {
# ifdef MBEDTLS_HAVE_TIME
dest->start = src->start;
# endif // MBEDTLS_HAVE_TIME
dest->ciphersuite = src->ciphersuite;
dest->compression = src->compression;
dest->id_len = src->id_len;
assert(dest->id_len <= sizeof(dest->id));
memcpy(dest->id, src->id, dest->id_len);
}

static bool sessions_equal(const mbedtls_ssl_session *left,
const resumed_session_data_t *right) {
if (!left && !right) {
return true;
}
return left && right && left->ciphersuite == right->ciphersuite
&& left->compression == right->compression
# ifdef MBEDTLS_HAVE_TIME
&& left->start == right->start
# endif // MBEDTLS_HAVE_TIME
&& left->id_len == right->id_len
&& memcmp(left->id, right->id, left->id_len) == 0;
}
# endif // MBEDTLS_SSL_SRV_C
# endif // AVS_COMMONS_NET_WITH_TLS_SESSION_PERSISTENCE
# endif // AVS_COMMONS_NET_WITH_TLS_SESSION_PERSISTENCE

static int socket_set_dtls_handshake_timeouts(
ssl_socket_t *socket,
Expand Down Expand Up @@ -1017,16 +978,14 @@ configure_ssl(ssl_socket_t *socket,
}
# endif // MBEDTLS_SSL_DTLS_CONNECTION_ID

# if defined(AVS_COMMONS_NET_WITH_TLS_SESSION_PERSISTENCE) \
&& defined(MBEDTLS_SSL_SRV_C)
# ifdef AVS_COMMONS_NET_WITH_TLS_SESSION_PERSISTENCE
// This is a hack. Session cache is normally used only for server-side TLS.
// We (ab)use this mechanism on the client side, taking advantage of the
// fact that Mbed TLS calls it if, and only if, a fresh session has been
// established, to determine session freshness if resuption is attempted.
mbedtls_ssl_conf_session_cache(&socket->config, socket, NULL,
fake_session_cache_set);
# endif // defined(AVS_COMMONS_NET_WITH_TLS_SESSION_PERSISTENCE) &&
// defined(MBEDTLS_SSL_SRV_C)
# endif // AVS_COMMONS_NET_WITH_TLS_SESSION_PERSISTENCE

avs_free(socket->effective_ciphersuites);
if (!(socket->effective_ciphersuites =
Expand Down Expand Up @@ -1194,14 +1153,7 @@ static avs_error_t start_ssl(ssl_socket_t *socket, const char *host) {
socket->flags.session_fresh = false;
}
}
# ifndef MBEDTLS_SSL_SRV_C
resumed_session_data_t restored_session;
memset(&restored_session, 0, sizeof(restored_session));
if (!socket->flags.session_fresh && get_context(socket)->session) {
session_copy(&restored_session, get_context(socket)->session);
}
# endif // MBEDTLS_SSL_SRV_C
# endif // AVS_COMMONS_NET_WITH_TLS_SESSION_PERSISTENCE
# endif // AVS_COMMONS_NET_WITH_TLS_SESSION_PERSISTENCE
# if defined(MBEDTLS_SSL_PROTO_DTLS)
if (transport_for_socket_type(socket->backend_type)
== MBEDTLS_SSL_TRANSPORT_DATAGRAM) {
Expand Down Expand Up @@ -1280,13 +1232,6 @@ static avs_error_t start_ssl(ssl_socket_t *socket, const char *host) {
# endif // defined(AVS_COMMONS_WITH_INTERNAL_LOGS) &&
// defined(MBEDTLS_SSL_DTLS_CONNECTION_ID)
# ifdef AVS_COMMONS_NET_WITH_TLS_SESSION_PERSISTENCE
# ifndef MBEDTLS_SSL_SRV_C
if (!socket->flags.session_fresh
&& !sessions_equal(get_context(socket)->session,
&restored_session)) {
socket->flags.session_fresh = true;
}
# endif // MBEDTLS_SSL_SRV_C
if (socket->flags.session_fresh) {
// We rely on session renegotation being disabled in
// configuration.
Expand Down
Loading

0 comments on commit 5d578fc

Please sign in to comment.