From: Hugo Landau Date: Mon, 22 Jan 2024 13:16:58 +0000 (+0000) Subject: QUIC APL: Add feature query implementation X-Git-Tag: openssl-3.3.0-alpha1~156 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=57eee469f72b449c124c93513e573582bcef1166;p=thirdparty%2Fopenssl.git 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 Reviewed-by: Matt Caswell Reviewed-by: Tomas Mraz (Merged from https://github.com/openssl/openssl/pull/23360) --- diff --git a/include/internal/quic_ssl.h b/include/internal/quic_ssl.h index 47e856cd79f..38963d6bdca 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 6261075b769..f760f5f84d1 100644 --- a/ssl/quic/quic_impl.c +++ b/ssl/quic/quic_impl.c @@ -3198,6 +3198,150 @@ int ossl_quic_set_incoming_stream_policy(SSL *s, int policy, return ret; } +/* + * 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 * -----------------