diff options
author | Hugo Landau <hlandau@openssl.org> | 2024-01-22 13:16:58 +0000 |
---|---|---|
committer | Hugo Landau <hlandau@openssl.org> | 2024-02-08 16:50:00 +0000 |
commit | 57eee469f72b449c124c93513e573582bcef1166 (patch) | |
tree | 9b29442362e47f62d40363bfc9bd49db7858a1d8 | |
parent | ecff7ca4c1043265a7af09d7f9286a08779dd098 (diff) |
QUIC APL: Add feature query implementation
Fixes https://github.com/openssl/project/issues/412
Fixes https://github.com/openssl/project/issues/415
Reviewed-by: Neil Horman <nhorman@openssl.org>
Reviewed-by: Matt Caswell <matt@openssl.org>
Reviewed-by: Tomas Mraz <tomas@openssl.org>
(Merged from https://github.com/openssl/openssl/pull/23360)
-rw-r--r-- | include/internal/quic_ssl.h | 4 | ||||
-rw-r--r-- | ssl/quic/quic_impl.c | 144 |
2 files changed, 148 insertions, 0 deletions
diff --git a/include/internal/quic_ssl.h b/include/internal/quic_ssl.h index 47e856cd79..38963d6bdc 100644 --- a/include/internal/quic_ssl.h +++ b/include/internal/quic_ssl.h @@ -85,6 +85,10 @@ __owur int ossl_quic_set_incoming_stream_policy(SSL *s, int policy, uint64_t aec); __owur SSL *ossl_quic_accept_stream(SSL *s, uint64_t flags); __owur size_t ossl_quic_get_accept_stream_queue_len(SSL *s); +__owur int ossl_quic_get_value_uint(SSL *s, uint32_t class_, uint32_t id, + uint64_t *value); +__owur int ossl_quic_set_value_uint(SSL *s, uint32_t class_, uint32_t id, + uint64_t value); __owur int ossl_quic_stream_reset(SSL *ssl, const SSL_STREAM_RESET_ARGS *args, diff --git a/ssl/quic/quic_impl.c b/ssl/quic/quic_impl.c index 6261075b76..f760f5f84d 100644 --- a/ssl/quic/quic_impl.c +++ b/ssl/quic/quic_impl.c @@ -3199,6 +3199,150 @@ int ossl_quic_set_incoming_stream_policy(SSL *s, int policy, } /* + * SSL_get_value, SSL_set_value + * ---------------------------- + */ +QUIC_TAKES_LOCK +static int qc_getset_idle_timeout(QCTX *ctx, uint32_t class_, + uint64_t *p_value_out, uint64_t *p_value_in) +{ + int ret = 0; + uint64_t value_out, value_in; + + quic_lock(ctx->qc); + + switch (class_) { + case SSL_VALUE_CLASS_FEATURE_REQUEST: + value_out = ossl_quic_channel_get_max_idle_timeout_request(ctx->qc->ch); + + if (p_value_in != NULL) { + value_in = *p_value_in; + if (value_in > OSSL_QUIC_VLINT_MAX) { + QUIC_RAISE_NON_NORMAL_ERROR(ctx, ERR_R_PASSED_INVALID_ARGUMENT, + NULL); + goto err; + } + + if (ossl_quic_channel_have_generated_transport_params(ctx->qc->ch)) { + QUIC_RAISE_NON_NORMAL_ERROR(ctx, SSL_R_FEATURE_NOT_RENEGOTIABLE, + NULL); + goto err; + } + + ossl_quic_channel_set_max_idle_timeout_request(ctx->qc->ch, value_in); + } + break; + + case SSL_VALUE_CLASS_FEATURE_PEER_REQUEST: + case SSL_VALUE_CLASS_FEATURE_NEGOTIATED: + if (p_value_in != NULL) { + QUIC_RAISE_NON_NORMAL_ERROR(ctx, SSL_R_UNSUPPORTED_CONFIG_VALUE_OP, + NULL); + goto err; + } + + if (!ossl_quic_channel_is_handshake_complete(ctx->qc->ch)) { + QUIC_RAISE_NON_NORMAL_ERROR(ctx, SSL_R_FEATURE_NEGOTIATION_NOT_COMPLETE, + NULL); + goto err; + } + + value_out = (class_ == SSL_VALUE_CLASS_FEATURE_NEGOTIATED) + ? ossl_quic_channel_get_max_idle_timeout_actual(ctx->qc->ch) + : ossl_quic_channel_get_max_idle_timeout_peer_request(ctx->qc->ch); + break; + + default: + QUIC_RAISE_NON_NORMAL_ERROR(ctx, SSL_R_UNSUPPORTED_CONFIG_VALUE_CLASS, + NULL); + goto err; + } + + ret = 1; +err: + quic_unlock(ctx->qc); + if (ret && p_value_out != NULL) + *p_value_out = value_out; + + return ret; +} + +QUIC_TAKES_LOCK +static int qc_get_stream_avail(QCTX *ctx, uint32_t class_, + int is_uni, int is_remote, + uint64_t *value) +{ + int ret = 0; + + if (class_ != SSL_VALUE_CLASS_GENERIC) { + QUIC_RAISE_NON_NORMAL_ERROR(ctx, SSL_R_UNSUPPORTED_CONFIG_VALUE_CLASS, + NULL); + return 0; + } + + quic_lock(ctx->qc); + + *value = is_remote + ? ossl_quic_channel_get_remote_stream_count_avail(ctx->qc->ch, is_uni) + : ossl_quic_channel_get_local_stream_count_avail(ctx->qc->ch, is_uni); + + ret = 1; + quic_unlock(ctx->qc); + return ret; +} + +QUIC_TAKES_LOCK +int ossl_quic_get_value_uint(SSL *s, uint32_t class_, uint32_t id, + uint64_t *value) +{ + QCTX ctx; + + if (!expect_quic_conn_only(s, &ctx)) + return 0; + + switch (id) { + case SSL_VALUE_QUIC_IDLE_TIMEOUT: + return qc_getset_idle_timeout(&ctx, class_, value, NULL); + + case SSL_VALUE_QUIC_STREAM_BIDI_LOCAL_AVAIL: + return qc_get_stream_avail(&ctx, class_, /*uni=*/0, /*remote=*/0, value); + case SSL_VALUE_QUIC_STREAM_BIDI_REMOTE_AVAIL: + return qc_get_stream_avail(&ctx, class_, /*uni=*/0, /*remote=*/1, value); + case SSL_VALUE_QUIC_STREAM_UNI_LOCAL_AVAIL: + return qc_get_stream_avail(&ctx, class_, /*uni=*/1, /*remote=*/0, value); + case SSL_VALUE_QUIC_STREAM_UNI_REMOTE_AVAIL: + return qc_get_stream_avail(&ctx, class_, /*uni=*/1, /*remote=*/1, value); + + default: + return QUIC_RAISE_NON_NORMAL_ERROR(&ctx, + SSL_R_UNSUPPORTED_CONFIG_VALUE, NULL); + } + + return 1; +} + +QUIC_TAKES_LOCK +int ossl_quic_set_value_uint(SSL *s, uint32_t class_, uint32_t id, + uint64_t value) +{ + QCTX ctx; + + if (!expect_quic_conn_only(s, &ctx)) + return 0; + + switch (id) { + case SSL_VALUE_QUIC_IDLE_TIMEOUT: + return qc_getset_idle_timeout(&ctx, class_, NULL, &value); + + default: + return QUIC_RAISE_NON_NORMAL_ERROR(&ctx, + SSL_R_UNSUPPORTED_CONFIG_VALUE, NULL); + } + + return 1; +} + +/* * SSL_accept_stream * ----------------- */ |