mirror of https://github.com/openssl/openssl.git
Compare commits
8 Commits
6aa496a6fb
...
582b77a368
| Author | SHA1 | Date |
|---|---|---|
|
|
582b77a368 | |
|
|
13a6583ed0 | |
|
|
7c9b69220a | |
|
|
296f1f6dd8 | |
|
|
fd7fc90346 | |
|
|
fcb5e20ac7 | |
|
|
b9ff440dd6 | |
|
|
f77fafd16e |
|
|
@ -93,7 +93,6 @@ EOF
|
|||
|
||||
my %cmd_disabler = (
|
||||
ciphers => "sock",
|
||||
genrsa => "rsa",
|
||||
gendsa => "dsa",
|
||||
dsaparam => "dsa",
|
||||
gendh => "dh",
|
||||
|
|
@ -107,7 +106,7 @@ EOF
|
|||
# [2] = preprocessor conditional for excluding irrespective of deprecation
|
||||
# rsa => [ "pkey", "3_0", "rsa" ],
|
||||
# genrsa => [ "genpkey", "3_0", "rsa" ],
|
||||
rsautl => [ "pkeyutl", "3_0", "rsa" ],
|
||||
rsautl => [ "pkeyutl", "3_0", "" ],
|
||||
# dhparam => [ "pkeyparam", "3_0", "dh" ],
|
||||
# dsaparam => [ "pkeyparam", "3_0", "dsa" ],
|
||||
# dsa => [ "pkey", "3_0", "dsa" ],
|
||||
|
|
|
|||
|
|
@ -261,10 +261,12 @@ int EVP_PKEY_encrypt(EVP_PKEY_CTX *ctx,
|
|||
|
||||
cipher = ctx->op.ciph.cipher;
|
||||
desc = cipher->description != NULL ? cipher->description : "";
|
||||
ERR_set_mark();
|
||||
ret = cipher->encrypt(ctx->op.ciph.algctx, out, outlen, (out == NULL ? 0 : *outlen), in, inlen);
|
||||
if (ret <= 0)
|
||||
if (ret <= 0 && ERR_count_to_mark() == 0)
|
||||
ERR_raise_data(ERR_LIB_EVP, EVP_R_PROVIDER_ASYM_CIPHER_FAILURE,
|
||||
"%s encrypt:%s", cipher->type_name, desc);
|
||||
ERR_clear_last_mark();
|
||||
return ret;
|
||||
|
||||
legacy:
|
||||
|
|
@ -309,10 +311,12 @@ int EVP_PKEY_decrypt(EVP_PKEY_CTX *ctx,
|
|||
|
||||
cipher = ctx->op.ciph.cipher;
|
||||
desc = cipher->description != NULL ? cipher->description : "";
|
||||
ERR_set_mark();
|
||||
ret = cipher->decrypt(ctx->op.ciph.algctx, out, outlen, (out == NULL ? 0 : *outlen), in, inlen);
|
||||
if (ret <= 0)
|
||||
if (ret <= 0 && ERR_count_to_mark() == 0)
|
||||
ERR_raise_data(ERR_LIB_EVP, EVP_R_PROVIDER_ASYM_CIPHER_FAILURE,
|
||||
"%s decrypt:%s", cipher->type_name, desc);
|
||||
ERR_clear_last_mark();
|
||||
|
||||
return ret;
|
||||
|
||||
|
|
|
|||
|
|
@ -460,10 +460,12 @@ void *evp_keymgmt_gen(const EVP_KEYMGMT *keymgmt, void *genctx,
|
|||
return NULL;
|
||||
}
|
||||
|
||||
ERR_set_mark();
|
||||
ret = keymgmt->gen(genctx, cb, cbarg);
|
||||
if (ret == NULL)
|
||||
if (ret == NULL && ERR_count_to_mark() == 0)
|
||||
ERR_raise_data(ERR_LIB_EVP, EVP_R_PROVIDER_KEYMGMT_FAILURE,
|
||||
"%s key generation:%s", keymgmt->type_name, desc);
|
||||
ERR_clear_last_mark();
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -426,10 +426,12 @@ int EVP_DigestSignUpdate(EVP_MD_CTX *ctx, const void *data, size_t dsize)
|
|||
return 0;
|
||||
}
|
||||
|
||||
ERR_set_mark();
|
||||
ret = signature->digest_sign_update(pctx->op.sig.algctx, data, dsize);
|
||||
if (ret <= 0)
|
||||
if (ret <= 0 && ERR_count_to_mark() == 0)
|
||||
ERR_raise_data(ERR_LIB_EVP, EVP_R_PROVIDER_SIGNATURE_FAILURE,
|
||||
"%s digest_sign_update:%s", signature->type_name, desc);
|
||||
ERR_clear_last_mark();
|
||||
return ret;
|
||||
|
||||
legacy:
|
||||
|
|
@ -474,10 +476,12 @@ int EVP_DigestVerifyUpdate(EVP_MD_CTX *ctx, const void *data, size_t dsize)
|
|||
return 0;
|
||||
}
|
||||
|
||||
ERR_set_mark();
|
||||
ret = signature->digest_verify_update(pctx->op.sig.algctx, data, dsize);
|
||||
if (ret <= 0)
|
||||
if (ret <= 0 && ERR_count_to_mark() == 0)
|
||||
ERR_raise_data(ERR_LIB_EVP, EVP_R_PROVIDER_SIGNATURE_FAILURE,
|
||||
"%s digest_verify_update:%s", signature->type_name, desc);
|
||||
ERR_clear_last_mark();
|
||||
return ret;
|
||||
|
||||
legacy:
|
||||
|
|
@ -527,11 +531,13 @@ int EVP_DigestSignFinal(EVP_MD_CTX *ctx, unsigned char *sigret,
|
|||
pctx = dctx;
|
||||
}
|
||||
|
||||
ERR_set_mark();
|
||||
r = signature->digest_sign_final(pctx->op.sig.algctx, sigret, siglen,
|
||||
sigret == NULL ? 0 : *siglen);
|
||||
if (!r)
|
||||
if (!r && ERR_count_to_mark() == 0)
|
||||
ERR_raise_data(ERR_LIB_EVP, EVP_R_PROVIDER_SIGNATURE_FAILURE,
|
||||
"%s digest_sign_final:%s", signature->type_name, desc);
|
||||
ERR_clear_last_mark();
|
||||
if (dctx == NULL && sigret != NULL)
|
||||
ctx->flags |= EVP_MD_CTX_FLAG_FINALISED;
|
||||
else
|
||||
|
|
@ -638,11 +644,13 @@ int EVP_DigestSign(EVP_MD_CTX *ctx, unsigned char *sigret, size_t *siglen,
|
|||
|
||||
if (sigret != NULL)
|
||||
ctx->flags |= EVP_MD_CTX_FLAG_FINALISED;
|
||||
ERR_set_mark();
|
||||
ret = signature->digest_sign(pctx->op.sig.algctx, sigret, siglen,
|
||||
sigret == NULL ? 0 : *siglen, tbs, tbslen);
|
||||
if (ret <= 0)
|
||||
if (ret <= 0 && ERR_count_to_mark() == 0)
|
||||
ERR_raise_data(ERR_LIB_EVP, EVP_R_PROVIDER_SIGNATURE_FAILURE,
|
||||
"%s digest_sign:%s", signature->type_name, desc);
|
||||
ERR_clear_last_mark();
|
||||
return ret;
|
||||
}
|
||||
} else {
|
||||
|
|
@ -693,10 +701,12 @@ int EVP_DigestVerifyFinal(EVP_MD_CTX *ctx, const unsigned char *sig,
|
|||
pctx = dctx;
|
||||
}
|
||||
|
||||
ERR_set_mark();
|
||||
r = signature->digest_verify_final(pctx->op.sig.algctx, sig, siglen);
|
||||
if (!r)
|
||||
if (!r && ERR_count_to_mark() == 0)
|
||||
ERR_raise_data(ERR_LIB_EVP, EVP_R_PROVIDER_SIGNATURE_FAILURE,
|
||||
"%s digest_verify_final:%s", signature->type_name, desc);
|
||||
ERR_clear_last_mark();
|
||||
if (dctx == NULL)
|
||||
ctx->flags |= EVP_MD_CTX_FLAG_FINALISED;
|
||||
else
|
||||
|
|
@ -769,10 +779,12 @@ int EVP_DigestVerify(EVP_MD_CTX *ctx, const unsigned char *sigret,
|
|||
int ret;
|
||||
|
||||
ctx->flags |= EVP_MD_CTX_FLAG_FINALISED;
|
||||
ERR_set_mark();
|
||||
ret = signature->digest_verify(pctx->op.sig.algctx, sigret, siglen, tbs, tbslen);
|
||||
if (ret <= 0)
|
||||
if (ret <= 0 && ERR_count_to_mark() == 0)
|
||||
ERR_raise_data(ERR_LIB_EVP, EVP_R_PROVIDER_SIGNATURE_FAILURE,
|
||||
"%s digest_verify:%s", signature->type_name, desc);
|
||||
ERR_clear_last_mark();
|
||||
return ret;
|
||||
}
|
||||
} else {
|
||||
|
|
|
|||
|
|
@ -2419,6 +2419,11 @@ static int core_pop_error_to_mark(const OSSL_CORE_HANDLE *handle)
|
|||
return ERR_pop_to_mark();
|
||||
}
|
||||
|
||||
static int core_count_to_mark(const OSSL_CORE_HANDLE *handle)
|
||||
{
|
||||
return ERR_count_to_mark();
|
||||
}
|
||||
|
||||
static void core_indicator_get_callback(OPENSSL_CORE_CTX *libctx,
|
||||
OSSL_INDICATOR_CALLBACK **cb)
|
||||
{
|
||||
|
|
@ -2600,6 +2605,7 @@ static const OSSL_DISPATCH core_dispatch_[] = {
|
|||
{ OSSL_FUNC_CORE_CLEAR_LAST_ERROR_MARK,
|
||||
(void (*)(void))core_clear_last_error_mark },
|
||||
{ OSSL_FUNC_CORE_POP_ERROR_TO_MARK, (void (*)(void))core_pop_error_to_mark },
|
||||
{ OSSL_FUNC_CORE_COUNT_TO_MARK, (void (*)(void))core_count_to_mark },
|
||||
{ OSSL_FUNC_BIO_NEW_FILE, (void (*)(void))ossl_core_bio_new_file },
|
||||
{ OSSL_FUNC_BIO_NEW_MEMBUF, (void (*)(void))ossl_core_bio_new_mem_buf },
|
||||
{ OSSL_FUNC_BIO_READ_EX, (void (*)(void))ossl_core_bio_read_ex },
|
||||
|
|
|
|||
|
|
@ -154,6 +154,10 @@ provider):
|
|||
core_new_error OSSL_FUNC_CORE_NEW_ERROR
|
||||
core_set_error_debug OSSL_FUNC_CORE_SET_ERROR_DEBUG
|
||||
core_vset_error OSSL_FUNC_CORE_VSET_ERROR
|
||||
core_set_error_mark OSSL_FUNC_CORE_SET_ERROR_MARK
|
||||
core_clear_last_error_mark OSSL_FUNC_CORE_CLEAR_LAST_ERROR_MARK
|
||||
core_pop_error_to_mark OSSL_FUNC_CORE_POP_ERROR_TO_MARK
|
||||
core_count_to_mark OSSL_FUNC_CORE_COUNT_TO_MARK
|
||||
core_obj_add_sigid OSSL_FUNC_CORE_OBJ_ADD_SIGID
|
||||
core_obj_create OSSL_FUNC_CORE_OBJ_CREATE
|
||||
CRYPTO_malloc OSSL_FUNC_CRYPTO_MALLOC
|
||||
|
|
@ -270,6 +274,33 @@ error occurred or was reported.
|
|||
|
||||
This corresponds to the OpenSSL function L<ERR_vset_error(3)>.
|
||||
|
||||
=item core_set_error_mark()
|
||||
|
||||
sets a mark on the current topmost error record if there is one.
|
||||
|
||||
This corresponds to the OpenSSL function L<ERR_set_mark(3)>.
|
||||
|
||||
=item core_clear_last_error_mark()
|
||||
|
||||
removes the last mark added if there is one.
|
||||
|
||||
This corresponds to the OpenSSL function L<ERR_clear_last_mark(3)>.
|
||||
|
||||
=item core_pop_error_to_mark()
|
||||
|
||||
pops the top of the error stack until a mark is found. The mark is then removed.
|
||||
If there is no mark, the whole stack is removed.
|
||||
|
||||
This corresponds to the OpenSSL function L<ERR_pop_to_mark(3)>.
|
||||
|
||||
=item core_count_to_mark()
|
||||
|
||||
returns the number of entries on the error stack above the most recently
|
||||
marked entry, not including that entry. If there is no mark in the error stack,
|
||||
the number of entries in the error stack is returned.
|
||||
|
||||
This corresponds to the OpenSSL function L<ERR_count_to_mark(3)>.
|
||||
|
||||
=back
|
||||
|
||||
The core_obj_create() function registers a new OID and associated short name
|
||||
|
|
|
|||
|
|
@ -590,10 +590,7 @@ int FuzzerTestOneInput(const uint8_t *buf, size_t len)
|
|||
SSL *server;
|
||||
BIO *in;
|
||||
BIO *out;
|
||||
#if !defined(OPENSSL_NO_EC) \
|
||||
|| (!defined(OPENSSL_NO_DSA) && !defined(OPENSSL_NO_DEPRECATED_3_0))
|
||||
BIO *bio_buf;
|
||||
#endif
|
||||
SSL_CTX *ctx;
|
||||
int ret;
|
||||
#ifndef OPENSSL_NO_DEPRECATED_3_0
|
||||
|
|
|
|||
|
|
@ -345,6 +345,8 @@ int ossl_quic_channel_is_terminated(const QUIC_CHANNEL *ch);
|
|||
int ossl_quic_channel_is_active(const QUIC_CHANNEL *ch);
|
||||
int ossl_quic_channel_is_handshake_complete(const QUIC_CHANNEL *ch);
|
||||
int ossl_quic_channel_is_handshake_confirmed(const QUIC_CHANNEL *ch);
|
||||
int ossl_quic_channel_is_server(const QUIC_CHANNEL *ch);
|
||||
void ossl_quic_channel_notify_flush_done(QUIC_CHANNEL *ch);
|
||||
|
||||
QUIC_PORT *ossl_quic_channel_get0_port(QUIC_CHANNEL *ch);
|
||||
QUIC_ENGINE *ossl_quic_channel_get0_engine(QUIC_CHANNEL *ch);
|
||||
|
|
@ -470,6 +472,8 @@ int ossl_quic_bind_channel(QUIC_CHANNEL *ch, const BIO_ADDR *peer,
|
|||
const QUIC_CONN_ID *scid, const QUIC_CONN_ID *dcid,
|
||||
const QUIC_CONN_ID *odcid);
|
||||
|
||||
void ossl_quic_channel_set_tcause(QUIC_CHANNEL *ch, uint64_t app_error_code,
|
||||
const char *app_reason);
|
||||
# endif
|
||||
|
||||
#endif
|
||||
|
|
|
|||
|
|
@ -554,6 +554,7 @@ static ossl_inline ossl_unused size_t ossl_quic_stream_recv_pending(const QUIC_S
|
|||
*/
|
||||
struct quic_stream_map_st {
|
||||
LHASH_OF(QUIC_STREAM) *map;
|
||||
QUIC_CHANNEL *ch;
|
||||
QUIC_STREAM_LIST_NODE active_list;
|
||||
QUIC_STREAM_LIST_NODE accept_list;
|
||||
QUIC_STREAM_LIST_NODE ready_for_gc_list;
|
||||
|
|
@ -564,7 +565,6 @@ struct quic_stream_map_st {
|
|||
void *get_stream_limit_cb_arg;
|
||||
QUIC_RXFC *max_streams_bidi_rxfc;
|
||||
QUIC_RXFC *max_streams_uni_rxfc;
|
||||
int is_server;
|
||||
};
|
||||
|
||||
/*
|
||||
|
|
@ -585,7 +585,7 @@ int ossl_quic_stream_map_init(QUIC_STREAM_MAP *qsm,
|
|||
void *get_stream_limit_cb_arg,
|
||||
QUIC_RXFC *max_streams_bidi_rxfc,
|
||||
QUIC_RXFC *max_streams_uni_rxfc,
|
||||
int is_server);
|
||||
QUIC_CHANNEL *ch);
|
||||
|
||||
/*
|
||||
* Any streams still in the map will be released as though
|
||||
|
|
|
|||
|
|
@ -253,6 +253,10 @@ OSSL_CORE_MAKE_FUNC(int, provider_up_ref,
|
|||
OSSL_CORE_MAKE_FUNC(int, provider_free,
|
||||
(const OSSL_CORE_HANDLE *prov, int deactivate))
|
||||
|
||||
/* Additional error functions provided by the core */
|
||||
# define OSSL_FUNC_CORE_COUNT_TO_MARK 120
|
||||
OSSL_CORE_MAKE_FUNC(int, core_count_to_mark, (const OSSL_CORE_HANDLE *prov))
|
||||
|
||||
/* Functions provided by the provider to the Core, reserved numbers 1024-1535 */
|
||||
# define OSSL_FUNC_PROVIDER_TEARDOWN 1024
|
||||
OSSL_CORE_MAKE_FUNC(void, provider_teardown, (void *provctx))
|
||||
|
|
|
|||
|
|
@ -65,6 +65,7 @@ static OSSL_FUNC_core_vset_error_fn *c_vset_error;
|
|||
static OSSL_FUNC_core_set_error_mark_fn *c_set_error_mark;
|
||||
static OSSL_FUNC_core_clear_last_error_mark_fn *c_clear_last_error_mark;
|
||||
static OSSL_FUNC_core_pop_error_to_mark_fn *c_pop_error_to_mark;
|
||||
static OSSL_FUNC_core_count_to_mark_fn *c_count_to_mark;
|
||||
static OSSL_FUNC_CRYPTO_malloc_fn *c_CRYPTO_malloc;
|
||||
static OSSL_FUNC_CRYPTO_zalloc_fn *c_CRYPTO_zalloc;
|
||||
static OSSL_FUNC_CRYPTO_free_fn *c_CRYPTO_free;
|
||||
|
|
@ -834,6 +835,9 @@ int OSSL_provider_init_int(const OSSL_CORE_HANDLE *handle,
|
|||
case OSSL_FUNC_CORE_POP_ERROR_TO_MARK:
|
||||
set_func(c_pop_error_to_mark, OSSL_FUNC_core_pop_error_to_mark(in));
|
||||
break;
|
||||
case OSSL_FUNC_CORE_COUNT_TO_MARK:
|
||||
set_func(c_count_to_mark, OSSL_FUNC_core_count_to_mark(in));
|
||||
break;
|
||||
case OSSL_FUNC_CRYPTO_MALLOC:
|
||||
set_func(c_CRYPTO_malloc, OSSL_FUNC_CRYPTO_malloc(in));
|
||||
break;
|
||||
|
|
@ -1072,6 +1076,11 @@ int ERR_pop_to_mark(void)
|
|||
return c_pop_error_to_mark(NULL);
|
||||
}
|
||||
|
||||
int ERR_count_to_mark(void)
|
||||
{
|
||||
return c_count_to_mark != NULL ? c_count_to_mark(NULL) : 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* This must take a library context, since it's called from the depths
|
||||
* of crypto/initthread.c code, where it's (correctly) assumed that the
|
||||
|
|
|
|||
|
|
@ -48,6 +48,7 @@ static OSSL_FUNC_core_vset_error_fn *c_vset_error;
|
|||
static OSSL_FUNC_core_set_error_mark_fn *c_set_error_mark;
|
||||
static OSSL_FUNC_core_clear_last_error_mark_fn *c_clear_last_error_mark;
|
||||
static OSSL_FUNC_core_pop_error_to_mark_fn *c_pop_error_to_mark;
|
||||
static OSSL_FUNC_core_count_to_mark_fn *c_count_to_mark;
|
||||
#endif
|
||||
|
||||
/* Parameters we provide to the core */
|
||||
|
|
@ -234,6 +235,9 @@ int OSSL_provider_init(const OSSL_CORE_HANDLE *handle,
|
|||
case OSSL_FUNC_CORE_POP_ERROR_TO_MARK:
|
||||
set_func(c_pop_error_to_mark, OSSL_FUNC_core_pop_error_to_mark(tmp));
|
||||
break;
|
||||
case OSSL_FUNC_CORE_COUNT_TO_MARK:
|
||||
set_func(c_count_to_mark, OSSL_FUNC_core_count_to_mark(in));
|
||||
break;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
|
@ -301,4 +305,9 @@ int ERR_pop_to_mark(void)
|
|||
{
|
||||
return c_pop_error_to_mark(NULL);
|
||||
}
|
||||
|
||||
int ERR_count_to_mark(void)
|
||||
{
|
||||
return c_count_to_mark != NULL ? c_count_to_mark(NULL) : 0;
|
||||
}
|
||||
#endif
|
||||
|
|
|
|||
|
|
@ -249,7 +249,7 @@ static int ch_init(QUIC_CHANNEL *ch)
|
|||
if (!ossl_quic_stream_map_init(&ch->qsm, get_stream_limit, ch,
|
||||
&ch->max_streams_bidi_rxfc,
|
||||
&ch->max_streams_uni_rxfc,
|
||||
ch->is_server))
|
||||
ch))
|
||||
goto err;
|
||||
|
||||
ch->have_qsm = 1;
|
||||
|
|
@ -649,6 +649,45 @@ int ossl_quic_channel_is_term_any(const QUIC_CHANNEL *ch)
|
|||
|| ossl_quic_channel_is_terminated(ch);
|
||||
}
|
||||
|
||||
int ossl_quic_channel_is_server(const QUIC_CHANNEL *ch)
|
||||
{
|
||||
return ch->is_server;
|
||||
}
|
||||
|
||||
void ossl_quic_channel_notify_flush_done(QUIC_CHANNEL *ch)
|
||||
{
|
||||
ch_record_state_transition(ch, ch->terminate_cause.remote
|
||||
? QUIC_CHANNEL_STATE_TERMINATING_DRAINING
|
||||
: QUIC_CHANNEL_STATE_TERMINATING_CLOSING);
|
||||
/*
|
||||
* RFC 9000 s. 10.2 Immediate Close
|
||||
* These states SHOULD persist for at least three times
|
||||
* the current PTO interval as defined in [QUIC-RECOVERY].
|
||||
*/
|
||||
ch->terminate_deadline
|
||||
= ossl_time_add(get_time(ch),
|
||||
ossl_time_multiply(ossl_ackm_get_pto_duration(ch->ackm), 3));
|
||||
if (!ch->terminate_cause.remote) {
|
||||
OSSL_QUIC_FRAME_CONN_CLOSE f = {0};
|
||||
|
||||
/* best effort */
|
||||
f.error_code = ch->terminate_cause.error_code;
|
||||
f.frame_type = ch->terminate_cause.frame_type;
|
||||
f.is_app = ch->terminate_cause.app;
|
||||
f.reason = (char *)ch->terminate_cause.reason;
|
||||
f.reason_len = ch->terminate_cause.reason_len;
|
||||
ossl_quic_tx_packetiser_schedule_conn_close(ch->txp, &f);
|
||||
/*
|
||||
* RFC 9000 s. 10.2.2 Draining Connection State:
|
||||
* An endpoint that receives a CONNECTION_CLOSE frame MAY
|
||||
* send a single packet containing a CONNECTION_CLOSE
|
||||
* frame before entering the draining state, using a
|
||||
* NO_ERROR code if appropriate
|
||||
*/
|
||||
ch->conn_close_queued = 1;
|
||||
}
|
||||
}
|
||||
|
||||
const QUIC_TERMINATE_CAUSE *
|
||||
ossl_quic_channel_get_terminate_cause(const QUIC_CHANNEL *ch)
|
||||
{
|
||||
|
|
@ -3140,14 +3179,17 @@ int ossl_quic_channel_on_handshake_confirmed(QUIC_CHANNEL *ch)
|
|||
static void copy_tcause(QUIC_TERMINATE_CAUSE *dst,
|
||||
const QUIC_TERMINATE_CAUSE *src)
|
||||
{
|
||||
/*
|
||||
* do not override reason once it got set.
|
||||
*/
|
||||
if (dst->reason != NULL)
|
||||
return;
|
||||
|
||||
dst->error_code = src->error_code;
|
||||
dst->frame_type = src->frame_type;
|
||||
dst->app = src->app;
|
||||
dst->remote = src->remote;
|
||||
|
||||
dst->reason = NULL;
|
||||
dst->reason_len = 0;
|
||||
|
||||
if (src->reason != NULL && src->reason_len > 0) {
|
||||
size_t l = src->reason_len;
|
||||
char *r;
|
||||
|
|
@ -3168,6 +3210,18 @@ static void copy_tcause(QUIC_TERMINATE_CAUSE *dst,
|
|||
}
|
||||
}
|
||||
|
||||
void ossl_quic_channel_set_tcause(QUIC_CHANNEL *ch, uint64_t app_error_code,
|
||||
const char *app_reason)
|
||||
{
|
||||
QUIC_TERMINATE_CAUSE tcause = {0};
|
||||
|
||||
tcause.app = 1;
|
||||
tcause.error_code = app_error_code;
|
||||
tcause.reason = app_reason;
|
||||
tcause.reason_len = app_reason != NULL ? strlen(app_reason) : 0;
|
||||
copy_tcause(&ch->terminate_cause, &tcause);
|
||||
}
|
||||
|
||||
static void ch_start_terminating(QUIC_CHANNEL *ch,
|
||||
const QUIC_TERMINATE_CAUSE *tcause,
|
||||
int force_immediate)
|
||||
|
|
@ -3189,38 +3243,7 @@ static void ch_start_terminating(QUIC_CHANNEL *ch,
|
|||
ossl_qlog_event_connectivity_connection_closed(ch_get_qlog(ch), tcause);
|
||||
|
||||
if (!force_immediate) {
|
||||
ch_record_state_transition(ch, tcause->remote
|
||||
? QUIC_CHANNEL_STATE_TERMINATING_DRAINING
|
||||
: QUIC_CHANNEL_STATE_TERMINATING_CLOSING);
|
||||
/*
|
||||
* RFC 9000 s. 10.2 Immediate Close
|
||||
* These states SHOULD persist for at least three times
|
||||
* the current PTO interval as defined in [QUIC-RECOVERY].
|
||||
*/
|
||||
ch->terminate_deadline
|
||||
= ossl_time_add(get_time(ch),
|
||||
ossl_time_multiply(ossl_ackm_get_pto_duration(ch->ackm),
|
||||
3));
|
||||
|
||||
if (!tcause->remote) {
|
||||
OSSL_QUIC_FRAME_CONN_CLOSE f = {0};
|
||||
|
||||
/* best effort */
|
||||
f.error_code = ch->terminate_cause.error_code;
|
||||
f.frame_type = ch->terminate_cause.frame_type;
|
||||
f.is_app = ch->terminate_cause.app;
|
||||
f.reason = (char *)ch->terminate_cause.reason;
|
||||
f.reason_len = ch->terminate_cause.reason_len;
|
||||
ossl_quic_tx_packetiser_schedule_conn_close(ch->txp, &f);
|
||||
/*
|
||||
* RFC 9000 s. 10.2.2 Draining Connection State:
|
||||
* An endpoint that receives a CONNECTION_CLOSE frame MAY
|
||||
* send a single packet containing a CONNECTION_CLOSE
|
||||
* frame before entering the draining state, using a
|
||||
* NO_ERROR code if appropriate
|
||||
*/
|
||||
ch->conn_close_queued = 1;
|
||||
}
|
||||
ossl_quic_channel_notify_flush_done(ch);
|
||||
} else {
|
||||
ch_on_terminating_timeout(ch);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1501,6 +1501,36 @@ static int quic_shutdown_peer_wait(void *arg)
|
|||
return ossl_quic_channel_is_term_any(qc->ch);
|
||||
}
|
||||
|
||||
/*
|
||||
* This function deals with local shutdown.
|
||||
* Function must consider those scenarios:
|
||||
* - blocking mode (1)
|
||||
* - non-blocking mode (2)
|
||||
* - non-blocking mode with assistance from SSL_poll() (3)
|
||||
* (1) The function completes shutdown then returns back to caller.
|
||||
* To complete shutdown we must do:
|
||||
* - flush all streams, unless we got SSL_SHUTDOWN_FLAG_NO_STREAM_FLUSH,
|
||||
* which means the connection is closed without waiting for streams
|
||||
* to deliver data written by application.
|
||||
* - let remote peer know local application is going to close connection,
|
||||
* unless we got SSL_SHUTDOWN_FLAG_WAIT_PEER in which case we await
|
||||
* until remote peer closes the connection
|
||||
* - wait for peer to confirm connection close
|
||||
*
|
||||
* (2) The function does not block waiting for streams to be flushed
|
||||
* nor for peer to close connection (when running with SSL_SHUTDOWN_FLAG_WAIT_PEER)
|
||||
* Application is supposed to call SSL_shutdown() repeatedly as long as
|
||||
* function returns 0 which indicates the operation is still in progress.
|
||||
*
|
||||
* (3) In this case application uses SSL_poll() to wait for completion
|
||||
* of each step of shutdown process. Application calls SSL_shutdown()
|
||||
* to start with connection shutdown. The function does not block.
|
||||
* Application then uses SSL_poll() on connection object to monitor
|
||||
* progress of shutdown. The SSL_poll() indicates progress by signaling
|
||||
* SSL_POLL_EVENT_EC event. Application must check connection object
|
||||
* for error. If no error is indicated, then application must call
|
||||
* SSL_shutdown() to move to the next stop in shutdown process.
|
||||
*/
|
||||
QUIC_TAKES_LOCK
|
||||
int ossl_quic_conn_shutdown(SSL *s, uint64_t flags,
|
||||
const SSL_SHUTDOWN_EX_ARGS *args,
|
||||
|
|
@ -1527,6 +1557,19 @@ int ossl_quic_conn_shutdown(SSL *s, uint64_t flags,
|
|||
return 1;
|
||||
}
|
||||
|
||||
if (!wait_peer) {
|
||||
/*
|
||||
* Set shutdown reason now when local application wants to do
|
||||
* active close (does not waant to wait for peer to close th
|
||||
* connection). The reason will be sent to peer with connection
|
||||
* close notification as soon as streams will be flushed.
|
||||
*/
|
||||
if (args != NULL) {
|
||||
ossl_quic_channel_set_tcause(ctx.qc->ch, args->quic_error_code,
|
||||
args->quic_reason);
|
||||
}
|
||||
}
|
||||
|
||||
/* Phase 1: Stream Flushing */
|
||||
if (!wait_peer && stream_flush) {
|
||||
qc_shutdown_flush_init(ctx.qc);
|
||||
|
|
|
|||
|
|
@ -9,6 +9,7 @@
|
|||
|
||||
#include "internal/quic_stream_map.h"
|
||||
#include "internal/nelem.h"
|
||||
#include "internal/quic_channel.h"
|
||||
|
||||
/*
|
||||
* QUIC Stream Map
|
||||
|
|
@ -92,7 +93,7 @@ int ossl_quic_stream_map_init(QUIC_STREAM_MAP *qsm,
|
|||
void *get_stream_limit_cb_arg,
|
||||
QUIC_RXFC *max_streams_bidi_rxfc,
|
||||
QUIC_RXFC *max_streams_uni_rxfc,
|
||||
int is_server)
|
||||
QUIC_CHANNEL *ch)
|
||||
{
|
||||
qsm->map = lh_QUIC_STREAM_new(hash_stream, cmp_stream);
|
||||
qsm->active_list.prev = qsm->active_list.next = &qsm->active_list;
|
||||
|
|
@ -111,7 +112,7 @@ int ossl_quic_stream_map_init(QUIC_STREAM_MAP *qsm,
|
|||
qsm->get_stream_limit_cb_arg = get_stream_limit_cb_arg;
|
||||
qsm->max_streams_bidi_rxfc = max_streams_bidi_rxfc;
|
||||
qsm->max_streams_uni_rxfc = max_streams_uni_rxfc;
|
||||
qsm->is_server = is_server;
|
||||
qsm->ch = ch;
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
|
@ -156,7 +157,7 @@ QUIC_STREAM *ossl_quic_stream_map_alloc(QUIC_STREAM_MAP *qsm,
|
|||
|
||||
s->id = stream_id;
|
||||
s->type = type;
|
||||
s->as_server = qsm->is_server;
|
||||
s->as_server = ossl_quic_channel_is_server(qsm->ch);
|
||||
s->send_state = (ossl_quic_stream_is_local_init(s)
|
||||
|| ossl_quic_stream_is_bidi(s))
|
||||
? QUIC_SSTREAM_STATE_READY
|
||||
|
|
@ -329,7 +330,7 @@ void ossl_quic_stream_map_update_state(QUIC_STREAM_MAP *qsm, QUIC_STREAM *s)
|
|||
{
|
||||
int should_be_active, allowed_by_stream_limit = 1;
|
||||
|
||||
if (ossl_quic_stream_is_server_init(s) == qsm->is_server) {
|
||||
if (ossl_quic_stream_is_server_init(s) == ossl_quic_channel_is_server(qsm->ch)) {
|
||||
int is_uni = !ossl_quic_stream_is_bidi(s);
|
||||
uint64_t stream_ordinal = s->id >> 2;
|
||||
|
||||
|
|
@ -425,6 +426,14 @@ static void shutdown_flush_done(QUIC_STREAM_MAP *qsm, QUIC_STREAM *qs)
|
|||
assert(qsm->num_shutdown_flush > 0);
|
||||
qs->shutdown_flush = 0;
|
||||
--qsm->num_shutdown_flush;
|
||||
|
||||
/*
|
||||
* when num_shutdown_flush becomes zero we need to poke
|
||||
* SSL_poll() it's time to poke to SSL_shutdown() to proceed
|
||||
* with shutdown process as all streams are gone (flushed).
|
||||
*/
|
||||
if (qsm->num_shutdown_flush == 0)
|
||||
ossl_quic_channel_notify_flush_done(qsm->ch);
|
||||
}
|
||||
|
||||
int ossl_quic_stream_map_notify_totally_acked(QUIC_STREAM_MAP *qsm,
|
||||
|
|
|
|||
|
|
@ -23,9 +23,19 @@ print <<"_____";
|
|||
#ifndef OPENSSL_NO_STDIO
|
||||
# include <stdio.h>
|
||||
#endif
|
||||
_____
|
||||
|
||||
if (${name_uc} eq "RSA") {
|
||||
print("#include <openssl/rsa.h>");
|
||||
}
|
||||
else {
|
||||
print <<"_____";
|
||||
#ifndef OPENSSL_NO_${name_uc}
|
||||
# include <openssl/$name.h>
|
||||
#endif
|
||||
_____
|
||||
}
|
||||
print <<"_____";
|
||||
|
||||
int main(void)
|
||||
{
|
||||
|
|
|
|||
|
|
@ -119,6 +119,20 @@ static void demux_default_handler(QUIC_URXE *e, void *arg,
|
|||
ossl_qrx_inject_urxe(h->qrx, e);
|
||||
}
|
||||
|
||||
/*
|
||||
* we don't need fully initialized channel for TX-packetizer test.
|
||||
* We just need a mockup channel instance which makes function
|
||||
* ossl_quic_channel_is_serve() to return zero, Zero buffer
|
||||
* which size is greater than sizeof (struct quic_channel_st) is
|
||||
* is sufficient.
|
||||
*/
|
||||
static QUIC_CHANNEL *get_client_test_channel(void)
|
||||
{
|
||||
static char test_client_channel[4096] = { 0 };
|
||||
|
||||
return (QUIC_CHANNEL *)test_client_channel;
|
||||
}
|
||||
|
||||
static int helper_init(struct helper *h)
|
||||
{
|
||||
int rc = 0;
|
||||
|
|
@ -189,7 +203,7 @@ static int helper_init(struct helper *h)
|
|||
if (!TEST_true(ossl_quic_stream_map_init(&h->qsm, NULL, NULL,
|
||||
&h->max_streams_bidi_rxfc,
|
||||
&h->max_streams_uni_rxfc,
|
||||
/*is_server=*/0)))
|
||||
get_client_test_channel())))
|
||||
goto err;
|
||||
|
||||
h->have_qsm = 1;
|
||||
|
|
|
|||
|
|
@ -1984,7 +1984,7 @@ static int test_tlsext_status_type(void)
|
|||
if (!create_ssl_ctx_pair(libctx, TLS_server_method(), TLS_client_method(),
|
||||
TLS1_VERSION, 0,
|
||||
&sctx, &cctx, leaf, skey))
|
||||
return 0;
|
||||
goto end;
|
||||
if (SSL_CTX_use_certificate_chain_file(sctx, leaf_chain) <= 0)
|
||||
goto end;
|
||||
if (SSL_CTX_get_tlsext_status_type(cctx) != -1)
|
||||
|
|
|
|||
Loading…
Reference in New Issue