QUIC DISPATCH/APL: Implement SSL_set_default_stream_mode, default XSO refactor

Reviewed-by: Matt Caswell <matt@openssl.org>
Reviewed-by: Tomas Mraz <tomas@openssl.org>
(Merged from https://github.com/openssl/openssl/pull/20765)
This commit is contained in:
Hugo Landau 2023-04-18 19:30:55 +01:00
parent 19cb088772
commit 8b7be3aa7e
10 changed files with 339 additions and 56 deletions

View File

@ -1465,6 +1465,7 @@ SSL_R_NO_SHARED_CIPHER:193:no shared cipher
SSL_R_NO_SHARED_GROUPS:410:no shared groups SSL_R_NO_SHARED_GROUPS:410:no shared groups
SSL_R_NO_SHARED_SIGNATURE_ALGORITHMS:376:no shared signature algorithms SSL_R_NO_SHARED_SIGNATURE_ALGORITHMS:376:no shared signature algorithms
SSL_R_NO_SRTP_PROFILES:359:no srtp profiles SSL_R_NO_SRTP_PROFILES:359:no srtp profiles
SSL_R_NO_STREAM:355:no stream
SSL_R_NO_SUITABLE_DIGEST_ALGORITHM:297:no suitable digest algorithm SSL_R_NO_SUITABLE_DIGEST_ALGORITHM:297:no suitable digest algorithm
SSL_R_NO_SUITABLE_GROUPS:295:no suitable groups SSL_R_NO_SUITABLE_GROUPS:295:no suitable groups
SSL_R_NO_SUITABLE_KEY_SHARE:101:no suitable key share SSL_R_NO_SUITABLE_KEY_SHARE:101:no suitable key share

View File

@ -84,6 +84,19 @@
*/ */
# define QUIC_TAKES_LOCK # define QUIC_TAKES_LOCK
/*
* The function acquires the channel mutex and leaves it acquired
* when returning success.
*
* Any function tagged with this has the following precondition and
* postcondition:
*
* Precondition: must not hold channel mutex (unchecked)
* Postcondition: channel mutex is held by calling thread
* or function returned failure
*/
# define QUIC_ACQUIRES_LOCK
# define QUIC_TODO_LOCK # define QUIC_TODO_LOCK
# define QUIC_CHANNEL_STATE_IDLE 0 # define QUIC_CHANNEL_STATE_IDLE 0

View File

@ -69,6 +69,9 @@ __owur SSL *ossl_quic_conn_stream_new(SSL *s, uint64_t flags);
__owur SSL *ossl_quic_get0_connection(SSL *s); __owur SSL *ossl_quic_get0_connection(SSL *s);
__owur int ossl_quic_get_stream_type(SSL *s); __owur int ossl_quic_get_stream_type(SSL *s);
__owur uint64_t ossl_quic_get_stream_id(SSL *s); __owur uint64_t ossl_quic_get_stream_id(SSL *s);
__owur int ossl_quic_set_default_stream_mode(SSL *s, uint32_t mode);
__owur SSL *ossl_quic_detach_stream(SSL *s);
__owur int ossl_quic_attach_stream(SSL *conn, SSL *stream);
/* /*
* Used to override ossl_time_now() for debug purposes. Must be called before * Used to override ossl_time_now() for debug purposes. Must be called before

View File

@ -2277,6 +2277,14 @@ __owur int SSL_get_stream_type(SSL *s);
__owur uint64_t SSL_get_stream_id(SSL *s); __owur uint64_t SSL_get_stream_id(SSL *s);
#define SSL_DEFAULT_STREAM_MODE_NONE 0
#define SSL_DEFAULT_STREAM_MODE_AUTO_BIDI 1
#define SSL_DEFAULT_STREAM_MODE_AUTO_UNI 2
__owur int SSL_set_default_stream_mode(SSL *s, uint32_t mode);
__owur SSL *SSL_detach_stream(SSL *s);
__owur int SSL_attach_stream(SSL *conn, SSL *stream);
#define SSL_STREAM_FLAG_UNI (1U << 0) #define SSL_STREAM_FLAG_UNI (1U << 0)
__owur SSL *SSL_new_stream(SSL *s, uint64_t flags); __owur SSL *SSL_new_stream(SSL *s, uint64_t flags);

View File

@ -202,6 +202,7 @@
# define SSL_R_NO_SHARED_GROUPS 410 # define SSL_R_NO_SHARED_GROUPS 410
# define SSL_R_NO_SHARED_SIGNATURE_ALGORITHMS 376 # define SSL_R_NO_SHARED_SIGNATURE_ALGORITHMS 376
# define SSL_R_NO_SRTP_PROFILES 359 # define SSL_R_NO_SRTP_PROFILES 359
# define SSL_R_NO_STREAM 355
# define SSL_R_NO_SUITABLE_DIGEST_ALGORITHM 297 # define SSL_R_NO_SUITABLE_DIGEST_ALGORITHM 297
# define SSL_R_NO_SUITABLE_GROUPS 295 # define SSL_R_NO_SUITABLE_GROUPS 295
# define SSL_R_NO_SUITABLE_KEY_SHARE 101 # define SSL_R_NO_SUITABLE_KEY_SHARE 101
@ -353,5 +354,6 @@
# define SSL_R_WRONG_VERSION_NUMBER 267 # define SSL_R_WRONG_VERSION_NUMBER 267
# define SSL_R_X509_LIB 268 # define SSL_R_X509_LIB 268
# define SSL_R_X509_VERIFICATION_SETUP_PROBLEMS 269 # define SSL_R_X509_VERIFICATION_SETUP_PROBLEMS 269
# define SSL_R_CONN_USE_ONLY 411
#endif #endif

View File

@ -20,7 +20,11 @@
static void aon_write_finish(QUIC_XSO *xso); static void aon_write_finish(QUIC_XSO *xso);
static int create_channel(QUIC_CONNECTION *qc); static int create_channel(QUIC_CONNECTION *qc);
static QUIC_XSO *create_xso_from_stream(QUIC_CONNECTION *qc, QUIC_STREAM *qs); static QUIC_XSO *create_xso_from_stream(QUIC_CONNECTION *qc, QUIC_STREAM *qs);
static int qc_try_create_default_xso(QUIC_CONNECTION *qc, int remote_init); static int qc_try_create_default_xso_for_write(QUIC_CONNECTION *qc);
static int qc_wait_for_default_xso_for_read(QUIC_CONNECTION *qc);
static void quic_lock(QUIC_CONNECTION *qc);
static void quic_unlock(QUIC_CONNECTION *qc);
static int quic_do_handshake(QUIC_CONNECTION *qc);
/* /*
* QUIC Front-End I/O API: Common Utilities * QUIC Front-End I/O API: Common Utilities
@ -136,7 +140,7 @@ static int expect_quic(const SSL *s, QCTX *ctx)
ctx->is_stream = 0; ctx->is_stream = 0;
if (s == NULL) if (s == NULL)
return QUIC_RAISE_NON_NORMAL_ERROR(NULL, ERR_R_INTERNAL_ERROR, NULL); return QUIC_RAISE_NON_NORMAL_ERROR(NULL, ERR_R_PASSED_NULL_PARAMETER, NULL);
switch (s->type) { switch (s->type) {
case SSL_TYPE_QUIC_CONNECTION: case SSL_TYPE_QUIC_CONNECTION:
@ -165,22 +169,50 @@ static int expect_quic(const SSL *s, QCTX *ctx)
* *
* remote_init determines if we expect the default XSO to be remotely created or * remote_init determines if we expect the default XSO to be remotely created or
* not. If it is -1, do not instantiate a default XSO if one does not yet exist. * not. If it is -1, do not instantiate a default XSO if one does not yet exist.
*
* Channel mutex is acquired and retained on success.
*/ */
static int ossl_unused expect_quic_with_stream(const SSL *s, int remote_init, QUIC_ACQUIRES_LOCK
QCTX *ctx) static int ossl_unused expect_quic_with_stream_lock(const SSL *s, int remote_init,
QCTX *ctx)
{ {
if (!expect_quic(s, ctx)) if (!expect_quic(s, ctx))
return 0; return 0;
quic_lock(ctx->qc);
if (ctx->xso == NULL && remote_init >= 0) { if (ctx->xso == NULL && remote_init >= 0) {
qc_try_create_default_xso(ctx->qc, remote_init); if (ossl_quic_channel_is_term_any(ctx->qc->ch)) {
QUIC_RAISE_NON_NORMAL_ERROR(ctx->qc, SSL_R_PROTOCOL_IS_SHUTDOWN, NULL);
goto err;
}
/* If we haven't finished the handshake, try to advance it. */
if (quic_do_handshake(ctx->qc) < 1)
/* ossl_quic_do_handshake raised error here */
goto err;
if (remote_init == 0) {
if (!qc_try_create_default_xso_for_write(ctx->qc))
goto err;
} else {
if (!qc_wait_for_default_xso_for_read(ctx->qc))
goto err;
}
ctx->xso = ctx->qc->default_xso; ctx->xso = ctx->qc->default_xso;
} }
if (ctx->xso == NULL) if (ctx->xso == NULL) {
return QUIC_RAISE_NON_NORMAL_ERROR(ctx->qc, ERR_R_INTERNAL_ERROR, NULL); QUIC_RAISE_NON_NORMAL_ERROR(ctx->qc, SSL_R_NO_STREAM, NULL);
goto err;
}
return 1; return 1; /* lock held */
err:
quic_unlock(ctx->qc);
return 0;
} }
/* /*
@ -193,7 +225,7 @@ static int ossl_unused expect_quic_conn_only(const SSL *s, QCTX *ctx)
return 0; return 0;
if (ctx->is_stream) if (ctx->is_stream)
return QUIC_RAISE_NON_NORMAL_ERROR(ctx->qc, ERR_R_INTERNAL_ERROR, NULL); return QUIC_RAISE_NON_NORMAL_ERROR(ctx->qc, SSL_R_CONN_USE_ONLY, NULL);
return 1; return 1;
} }
@ -261,6 +293,7 @@ SSL *ossl_quic_new(SSL_CTX *ctx)
qc->as_server = 0; /* TODO(QUIC): server support */ qc->as_server = 0; /* TODO(QUIC): server support */
qc->as_server_state = qc->as_server; qc->as_server_state = qc->as_server;
qc->default_stream_mode = SSL_DEFAULT_STREAM_MODE_AUTO_BIDI;
qc->default_ssl_mode = qc->ssl.ctx->mode; qc->default_ssl_mode = qc->ssl.ctx->mode;
qc->default_blocking = 1; qc->default_blocking = 1;
qc->last_error = SSL_ERROR_NONE; qc->last_error = SSL_ERROR_NONE;
@ -1119,50 +1152,123 @@ int ossl_quic_accept(SSL *s)
* exists). Note that this is NOT an error condition. * exists). Note that this is NOT an error condition.
*/ */
QUIC_NEEDS_LOCK QUIC_NEEDS_LOCK
static int qc_try_create_default_xso(QUIC_CONNECTION *qc, int remote_init) static int qc_try_create_default_xso_for_write(QUIC_CONNECTION *qc)
{ {
QUIC_STREAM *qs; uint64_t flags = 0;
if (qc->default_xso != NULL) if (qc->default_xso_created
qc->default_xso_created = 1; || qc->default_stream_mode == SSL_DEFAULT_STREAM_MODE_NONE)
if (qc->default_xso_created)
/* /*
* We only do this once. If the user detaches a previously created * We only do this once. If the user detaches a previously created
* default XSO we don't auto-create another one. * default XSO we don't auto-create another one.
*/ */
return 0; return QUIC_RAISE_NON_NORMAL_ERROR(qc, SSL_R_NO_STREAM, NULL);
if (!remote_init) { /* Create a locally-initiated stream. */
/* if (qc->default_stream_mode == SSL_DEFAULT_STREAM_MODE_AUTO_UNI)
* We are writing to the stream first, so this is a locally-initiated flags |= SSL_STREAM_FLAG_UNI;
* stream.
*/
qc->default_xso = (QUIC_XSO *)ossl_quic_conn_stream_new(&qc->ssl, 0);
if (qc->default_xso == NULL)
return 0;
} else {
/*
* Client is reading first. This means it is expecting to get data on a
* stream the peer writes to first, meaning this is a remotely-initiated
* stream. Ordinarily, we wait for the RXDP to handle a STREAM frame to
* create such a stream. But in this case, special case it and create
* the bookkeeping structures for the first peer-initiated bidirectional
* stream so the client can start to wait on it.
*/
qs = ossl_quic_channel_new_stream_remote(qc->ch,
QUIC_STREAM_INITIATOR_SERVER
| QUIC_STREAM_DIR_BIDI);
if (qs == NULL)
return 0;
qc->default_xso = create_xso_from_stream(qc, qs); qc->default_xso = (QUIC_XSO *)ossl_quic_conn_stream_new(&qc->ssl, flags);
if (qc->default_xso == NULL) { if (qc->default_xso == NULL)
ossl_quic_stream_map_release(ossl_quic_channel_get_qsm(qc->ch), qs); return QUIC_RAISE_NON_NORMAL_ERROR(qc, ERR_R_INTERNAL_ERROR, NULL);
return 0;
} qc->default_xso_created = 1;
return 1;
}
struct quic_wait_for_stream_args {
QUIC_CONNECTION *qc;
QUIC_STREAM *qs;
uint64_t expect_id;
};
QUIC_NEEDS_LOCK
static int quic_wait_for_stream(void *arg)
{
struct quic_wait_for_stream_args *args = arg;
if (!ossl_quic_channel_is_active(args->qc->ch)) {
/* If connection is torn down due to an error while blocking, stop. */
QUIC_RAISE_NON_NORMAL_ERROR(args->qc, SSL_R_PROTOCOL_IS_SHUTDOWN, NULL);
return -1;
} }
args->qs = ossl_quic_stream_map_get_by_id(ossl_quic_channel_get_qsm(args->qc->ch),
args->expect_id);
if (args->qs != NULL)
return 1; /* stream now exists */
return 0; /* did not get a stream, keep trying */
}
QUIC_NEEDS_LOCK
static int qc_wait_for_default_xso_for_read(QUIC_CONNECTION *qc)
{
/* Called on a QCSO and we don't currently have a default stream. */
uint64_t expect_id;
QUIC_STREAM *qs;
int res;
struct quic_wait_for_stream_args wargs;
/*
* If default stream functionality is disabled or we already detached
* one, don't make another default stream and just fail.
*/
if (qc->default_xso_created
|| qc->default_stream_mode == SSL_DEFAULT_STREAM_MODE_NONE)
return QUIC_RAISE_NON_NORMAL_ERROR(qc, SSL_R_NO_STREAM, NULL);
/*
* The peer may have opened a stream since we last ticked. So tick and
* see if the stream with ordinal 0 (remote, bidi/uni based on stream
* mode) exists yet. QUIC stream IDs must be allocated in order, so the
* first stream created by a peer must have an ordinal of 0.
*/
expect_id = qc->as_server
? QUIC_STREAM_INITIATOR_CLIENT
: QUIC_STREAM_INITIATOR_SERVER;
expect_id |= (qc->default_stream_mode == SSL_DEFAULT_STREAM_MODE_AUTO_UNI)
? QUIC_STREAM_DIR_UNI
: QUIC_STREAM_DIR_BIDI;
qs = ossl_quic_stream_map_get_by_id(ossl_quic_channel_get_qsm(qc->ch),
expect_id);
if (qs == NULL) {
ossl_quic_reactor_tick(ossl_quic_channel_get_reactor(qc->ch), 0);
qs = ossl_quic_stream_map_get_by_id(ossl_quic_channel_get_qsm(qc->ch),
expect_id);
}
if (qs == NULL) {
if (!qc_blocking_mode(qc))
/* Non-blocking mode, so just bail immediately. */
return QUIC_RAISE_NORMAL_ERROR(qc, SSL_ERROR_WANT_READ);
/* Block until we have a stream. */
wargs.qc = qc;
wargs.qs = NULL;
wargs.expect_id = expect_id;
res = block_until_pred(qc, quic_wait_for_stream, &wargs, 0);
if (res == 0)
return QUIC_RAISE_NON_NORMAL_ERROR(qc, ERR_R_INTERNAL_ERROR, NULL);
else if (res < 0 || wargs.qs == NULL)
/* quic_wait_for_stream raised error here */
return 0;
qs = wargs.qs;
}
/*
* We now have qs != NULL. Make it the default stream, creating the
* necessary XSO.
*/
qc->default_xso = create_xso_from_stream(qc, qs);
if (qc->default_xso == NULL)
return QUIC_RAISE_NON_NORMAL_ERROR(qc, ERR_R_INTERNAL_ERROR, NULL);
qc->default_xso_created = 1; qc->default_xso_created = 1;
return 1; return 1;
} }
@ -1218,6 +1324,7 @@ SSL *ossl_quic_conn_stream_new(SSL *s, uint64_t flags)
if (xso == NULL) if (xso == NULL)
goto err; goto err;
ctx.qc->default_xso_created = 1; /* inhibits default XSO */
quic_unlock(ctx.qc); quic_unlock(ctx.qc);
return &xso->ssl; return &xso->ssl;
@ -1508,11 +1615,11 @@ int ossl_quic_write(SSL *s, const void *buf, size_t len, size_t *written)
*written = 0; *written = 0;
if (!expect_quic_with_stream(s, /*remote_init=*/0, &ctx)) { if (len == 0)
return 0; return 1;
}
quic_lock(ctx.qc); if (!expect_quic_with_stream_lock(s, /*remote_init=*/0, &ctx))
return 0;
partial_write = ((ctx.xso->ssl_mode & SSL_MODE_ENABLE_PARTIAL_WRITE) != 0); partial_write = ((ctx.xso->ssl_mode & SSL_MODE_ENABLE_PARTIAL_WRITE) != 0);
@ -1647,7 +1754,7 @@ static int quic_read(SSL *s, void *buf, size_t len, size_t *bytes_read, int peek
*bytes_read = 0; *bytes_read = 0;
if (!expect_quic_with_stream(s, /*remote_init=*/0, &ctx)) if (!expect_quic(s, &ctx))
return 0; return 0;
quic_lock(ctx.qc); quic_lock(ctx.qc);
@ -1663,6 +1770,21 @@ static int quic_read(SSL *s, void *buf, size_t len, size_t *bytes_read, int peek
goto out; goto out;
} }
if (ctx.xso == NULL) {
/*
* Called on a QCSO and we don't currently have a default stream.
*
* Wait until we get a stream initiated by the peer (blocking mode) or
* fail if we don't have one yet (non-blocking mode).
*/
if (!qc_wait_for_default_xso_for_read(ctx.qc)) {
ret = 0; /* error already raised here */
goto out;
}
ctx.xso = ctx.qc->default_xso;
}
if (ctx.xso->stream == NULL) { if (ctx.xso->stream == NULL) {
ret = QUIC_RAISE_NON_NORMAL_ERROR(ctx.qc, ERR_R_INTERNAL_ERROR, NULL); ret = QUIC_RAISE_NON_NORMAL_ERROR(ctx.qc, ERR_R_INTERNAL_ERROR, NULL);
goto out; goto out;
@ -1734,11 +1856,9 @@ static size_t ossl_quic_pending_int(const SSL *s)
size_t avail = 0; size_t avail = 0;
int fin = 0; int fin = 0;
if (!expect_quic_with_stream(s, /*remote_init=*/-1, &ctx)) if (!expect_quic_with_stream_lock(s, /*remote_init=*/-1, &ctx))
return 0; return 0;
quic_lock(ctx.qc);
if (ctx.xso->stream == NULL || ctx.xso->stream->rstream == NULL) if (ctx.xso->stream == NULL || ctx.xso->stream->rstream == NULL)
/* Cannot raise errors here because we are const, just fail. */ /* Cannot raise errors here because we are const, just fail. */
goto out; goto out;
@ -1771,11 +1891,9 @@ int ossl_quic_conn_stream_conclude(SSL *s)
QCTX ctx; QCTX ctx;
QUIC_STREAM *qs; QUIC_STREAM *qs;
if (!expect_quic_with_stream(s, /*remote_init=*/0, &ctx)) if (!expect_quic_with_stream_lock(s, /*remote_init=*/0, &ctx))
return 0; return 0;
quic_lock(ctx.qc);
qs = ctx.xso->stream; qs = ctx.xso->stream;
if (qs == NULL || qs->sstream == NULL) { if (qs == NULL || qs->sstream == NULL) {
@ -1874,11 +1992,105 @@ int ossl_quic_get_stream_type(SSL *s)
uint64_t ossl_quic_get_stream_id(SSL *s) uint64_t ossl_quic_get_stream_id(SSL *s)
{ {
QCTX ctx; QCTX ctx;
uint64_t id;
if (!expect_quic_with_stream(s, /*remote_init=*/-1, &ctx)) if (!expect_quic_with_stream_lock(s, /*remote_init=*/-1, &ctx))
return UINT64_MAX; return UINT64_MAX;
return ctx.xso->stream->id; id = ctx.xso->stream->id;
quic_unlock(ctx.qc);
return id;
}
/*
* SSL_set_default_stream_mode
* ---------------------------
*/
int ossl_quic_set_default_stream_mode(SSL *s, uint32_t mode)
{
QCTX ctx;
if (!expect_quic_conn_only(s, &ctx))
return 0;
quic_lock(ctx.qc);
if (ctx.qc->default_xso_created)
return QUIC_RAISE_NON_NORMAL_ERROR(ctx.qc, ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED,
"too late to change default stream mode");
switch (mode) {
case SSL_DEFAULT_STREAM_MODE_NONE:
case SSL_DEFAULT_STREAM_MODE_AUTO_BIDI:
case SSL_DEFAULT_STREAM_MODE_AUTO_UNI:
ctx.qc->default_stream_mode = mode;
break;
default:
quic_unlock(ctx.qc);
return QUIC_RAISE_NON_NORMAL_ERROR(ctx.qc, ERR_R_PASSED_INVALID_ARGUMENT,
"bad default stream type");
}
quic_unlock(ctx.qc);
return 1;
}
/*
* SSL_detach_stream
* -----------------
*/
SSL *ossl_quic_detach_stream(SSL *s)
{
QCTX ctx;
QUIC_XSO *xso;
if (!expect_quic_conn_only(s, &ctx))
return NULL;
quic_lock(ctx.qc);
xso = ctx.qc->default_xso;
ctx.qc->default_xso = NULL;
/* Calling this function inhibits default XSO autocreation. */
ctx.qc->default_xso_created = 1;
quic_unlock(ctx.qc);
return &xso->ssl;
}
/*
* SSL_attach_stream
* -----------------
*/
int ossl_quic_attach_stream(SSL *conn, SSL *stream)
{
QCTX ctx;
if (!expect_quic_conn_only(conn, &ctx))
return 0;
if (stream == NULL || stream->type != SSL_TYPE_QUIC_XSO)
return QUIC_RAISE_NON_NORMAL_ERROR(ctx.qc, ERR_R_PASSED_NULL_PARAMETER,
"stream to attach must be a valid QUIC stream");
quic_lock(ctx.qc);
if (ctx.qc->default_xso != NULL) {
quic_unlock(ctx.qc);
return QUIC_RAISE_NON_NORMAL_ERROR(ctx.qc, ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED,
"connection already has a default stream");
}
ctx.qc->default_xso = (QUIC_XSO *)stream;
/* Calling this function inhibits default XSO autocreation. */
ctx.qc->default_xso_created = 1;
quic_unlock(ctx.qc);
return 1;
} }
/* /*

View File

@ -172,6 +172,9 @@ struct quic_conn_st {
/* Have we created a default XSO yet? */ /* Have we created a default XSO yet? */
unsigned int default_xso_created : 1; unsigned int default_xso_created : 1;
/* Default stream type. Defaults to SSL_DEFAULT_STREAM_MODE_AUTO_BIDI. */
uint32_t default_stream_mode;
/* SSL_set_mode. This is not used directly but inherited by new XSOs. */ /* SSL_set_mode. This is not used directly but inherited by new XSOs. */
uint32_t default_ssl_mode; uint32_t default_ssl_mode;

View File

@ -311,6 +311,7 @@ static const ERR_STRING_DATA SSL_str_reasons[] = {
{ERR_PACK(ERR_LIB_SSL, 0, SSL_R_NO_SHARED_SIGNATURE_ALGORITHMS), {ERR_PACK(ERR_LIB_SSL, 0, SSL_R_NO_SHARED_SIGNATURE_ALGORITHMS),
"no shared signature algorithms"}, "no shared signature algorithms"},
{ERR_PACK(ERR_LIB_SSL, 0, SSL_R_NO_SRTP_PROFILES), "no srtp profiles"}, {ERR_PACK(ERR_LIB_SSL, 0, SSL_R_NO_SRTP_PROFILES), "no srtp profiles"},
{ERR_PACK(ERR_LIB_SSL, 0, SSL_R_NO_STREAM), "no stream"},
{ERR_PACK(ERR_LIB_SSL, 0, SSL_R_NO_SUITABLE_DIGEST_ALGORITHM), {ERR_PACK(ERR_LIB_SSL, 0, SSL_R_NO_SUITABLE_DIGEST_ALGORITHM),
"no suitable digest algorithm"}, "no suitable digest algorithm"},
{ERR_PACK(ERR_LIB_SSL, 0, SSL_R_NO_SUITABLE_GROUPS), "no suitable groups"}, {ERR_PACK(ERR_LIB_SSL, 0, SSL_R_NO_SUITABLE_GROUPS), "no suitable groups"},

View File

@ -7352,6 +7352,42 @@ uint64_t SSL_get_stream_id(SSL *s)
#endif #endif
} }
int SSL_set_default_stream_mode(SSL *s, uint32_t mode)
{
#ifndef OPENSSL_NO_QUIC
if (!IS_QUIC(s))
return 0;
return ossl_quic_set_default_stream_mode(s, mode);
#else
return 0;
#endif
}
SSL *SSL_detach_stream(SSL *s)
{
#ifndef OPENSSL_NO_QUIC
if (!IS_QUIC(s))
return NULL;
return ossl_quic_detach_stream(s);
#else
return NULL;
#endif
}
int SSL_attach_stream(SSL *conn, SSL *stream)
{
#ifndef OPENSSL_NO_QUIC
if (!IS_QUIC(conn))
return 0;
return ossl_quic_attach_stream(conn, stream);
#else
return NULL;
#endif
}
int SSL_add_expected_rpk(SSL *s, EVP_PKEY *rpk) int SSL_add_expected_rpk(SSL *s, EVP_PKEY *rpk)
{ {
unsigned char *data = NULL; unsigned char *data = NULL;

View File

@ -564,3 +564,7 @@ SSL_new_stream ? 3_2_0 EXIST::FUNCTION:
SSL_get0_connection ? 3_2_0 EXIST::FUNCTION: SSL_get0_connection ? 3_2_0 EXIST::FUNCTION:
SSL_is_connection ? 3_2_0 EXIST::FUNCTION: SSL_is_connection ? 3_2_0 EXIST::FUNCTION:
SSL_get_stream_type ? 3_2_0 EXIST::FUNCTION: SSL_get_stream_type ? 3_2_0 EXIST::FUNCTION:
SSL_get_stream_id ? 3_2_0 EXIST::FUNCTION:
SSL_set_default_stream_mode ? 3_2_0 EXIST::FUNCTION:
SSL_detach_stream ? 3_2_0 EXIST::FUNCTION:
SSL_attach_stream ? 3_2_0 EXIST::FUNCTION: