diff options
Diffstat (limited to 'ssl/bio_ssl.c')
-rw-r--r-- | ssl/bio_ssl.c | 77 |
1 files changed, 56 insertions, 21 deletions
diff --git a/ssl/bio_ssl.c b/ssl/bio_ssl.c index be3159b32a9f..d1034814bff2 100644 --- a/ssl/bio_ssl.c +++ b/ssl/bio_ssl.c @@ -1,5 +1,5 @@ /* - * Copyright 1995-2024 The OpenSSL Project Authors. All Rights Reserved. + * Copyright 1995-2025 The OpenSSL Project Authors. All Rights Reserved. * * Licensed under the Apache License 2.0 (the "License"). You may not use * this file except in compliance with the License. You can obtain a copy @@ -15,6 +15,8 @@ #include "internal/bio.h" #include <openssl/err.h> #include "ssl_local.h" +#include "internal/ssl_unwrap.h" +#include "internal/sockets.h" static int ssl_write(BIO *h, const char *buf, size_t size, size_t *written); static int ssl_read(BIO *b, char *buf, size_t size, size_t *readbytes); @@ -25,7 +27,11 @@ static int ssl_free(BIO *data); static long ssl_callback_ctrl(BIO *h, int cmd, BIO_info_cb *fp); typedef struct bio_ssl_st { SSL *ssl; /* The ssl handle :-) */ - /* re-negotiate every time the total number of bytes is this size */ + /* + * Re-negotiate every time the total number of bytes is this size + * or when timeout expires. + * There is no proper support for TLS-1.3 or QUIC yet. + */ int num_renegotiates; unsigned long renegotiate_count; size_t byte_count; @@ -57,10 +63,8 @@ static int ssl_new(BIO *bi) { BIO_SSL *bs = OPENSSL_zalloc(sizeof(*bs)); - if (bs == NULL) { - ERR_raise(ERR_LIB_BIO, ERR_R_MALLOC_FAILURE); + if (bs == NULL) return 0; - } BIO_set_init(bi, 0); BIO_set_data(bi, bs); /* Clear all flags */ @@ -172,7 +176,7 @@ static int ssl_write(BIO *b, const char *buf, size_t size, size_t *written) BIO_clear_retry_flags(b); - ret = ssl_write_internal(ssl, buf, size, written); + ret = ssl_write_internal(ssl, buf, size, 0, written); switch (SSL_get_error(ssl, ret)) { case SSL_ERROR_NONE: @@ -227,19 +231,24 @@ static long ssl_ctrl(BIO *b, int cmd, long num, void *ptr) BIO *dbio, *bio; long ret = 1; BIO *next; + SSL_CONNECTION *sc = NULL; bs = BIO_get_data(b); next = BIO_next(b); ssl = bs->ssl; - if ((ssl == NULL) && (cmd != BIO_C_SET_SSL)) + if (ssl == NULL && cmd != BIO_C_SET_SSL) return 0; switch (cmd) { case BIO_CTRL_RESET: + /* TODO(QUIC FUTURE): Add support when SSL_clear() is supported */ + if ((sc = SSL_CONNECTION_FROM_SSL_ONLY(ssl)) == NULL) + return 0; + SSL_shutdown(ssl); - if (ssl->handshake_func == ssl->method->ssl_connect) + if (sc->handshake_func == ssl->method->ssl_connect) SSL_set_connect_state(ssl); - else if (ssl->handshake_func == ssl->method->ssl_accept) + else if (sc->handshake_func == ssl->method->ssl_accept) SSL_set_accept_state(ssl); if (!SSL_clear(ssl)) { @@ -249,8 +258,8 @@ static long ssl_ctrl(BIO *b, int cmd, long num, void *ptr) if (next != NULL) ret = BIO_ctrl(next, cmd, num, ptr); - else if (ssl->rbio != NULL) - ret = BIO_ctrl(ssl->rbio, cmd, num, ptr); + else if (sc->rbio != NULL) + ret = BIO_ctrl(sc->rbio, cmd, num, ptr); else ret = 1; break; @@ -290,10 +299,13 @@ static long ssl_ctrl(BIO *b, int cmd, long num, void *ptr) bs->ssl = ssl; bio = SSL_get_rbio(ssl); if (bio != NULL) { + if (!BIO_up_ref(bio)) { + ret = 0; + break; + } if (next != NULL) BIO_push(bio, next); BIO_set_next(b, bio); - BIO_up_ref(bio); } BIO_set_init(b, 1); break; @@ -311,26 +323,28 @@ static long ssl_ctrl(BIO *b, int cmd, long num, void *ptr) BIO_set_shutdown(b, (int)num); break; case BIO_CTRL_WPENDING: - ret = BIO_ctrl(ssl->wbio, cmd, num, ptr); + ret = BIO_ctrl(SSL_get_wbio(ssl), cmd, num, ptr); break; case BIO_CTRL_PENDING: ret = SSL_pending(ssl); if (ret == 0) - ret = BIO_pending(ssl->rbio); + ret = BIO_pending(SSL_get_rbio(ssl)); break; case BIO_CTRL_FLUSH: BIO_clear_retry_flags(b); - ret = BIO_ctrl(ssl->wbio, cmd, num, ptr); + ret = BIO_ctrl(SSL_get_wbio(ssl), cmd, num, ptr); BIO_copy_next_retry(b); break; case BIO_CTRL_PUSH: - if ((next != NULL) && (next != ssl->rbio)) { + if ((next != NULL) && (next != SSL_get_rbio(ssl))) { /* * We are going to pass ownership of next to the SSL object...but * we don't own a reference to pass yet - so up ref */ - BIO_up_ref(next); - SSL_set_bio(ssl, next, next); + if (!BIO_up_ref(next)) + ret = 0; + else + SSL_set_bio(ssl, next, next); } break; case BIO_CTRL_POP: @@ -378,13 +392,21 @@ static long ssl_ctrl(BIO *b, int cmd, long num, void *ptr) ret = (dbs->ssl != NULL); break; case BIO_C_GET_FD: - ret = BIO_ctrl(ssl->rbio, cmd, num, ptr); + ret = BIO_ctrl(SSL_get_rbio(ssl), cmd, num, ptr); break; case BIO_CTRL_SET_CALLBACK: ret = 0; /* use callback ctrl */ break; + case BIO_CTRL_GET_RPOLL_DESCRIPTOR: + if (!SSL_get_rpoll_descriptor(ssl, (BIO_POLL_DESCRIPTOR *)ptr)) + ret = 0; + break; + case BIO_CTRL_GET_WPOLL_DESCRIPTOR: + if (!SSL_get_wpoll_descriptor(ssl, (BIO_POLL_DESCRIPTOR *)ptr)) + ret = 0; + break; default: - ret = BIO_ctrl(ssl->rbio, cmd, num, ptr); + ret = BIO_ctrl(SSL_get_rbio(ssl), cmd, num, ptr); break; } return ret; @@ -400,7 +422,7 @@ static long ssl_callback_ctrl(BIO *b, int cmd, BIO_info_cb *fp) ssl = bs->ssl; switch (cmd) { case BIO_CTRL_SET_CALLBACK: - ret = BIO_callback_ctrl(ssl->rbio, cmd, fp); + ret = BIO_callback_ctrl(SSL_get_rbio(ssl), cmd, fp); break; default: ret = 0; @@ -423,6 +445,12 @@ BIO *BIO_new_buffer_ssl_connect(SSL_CTX *ctx) #ifndef OPENSSL_NO_SOCK BIO *ret = NULL, *buf = NULL, *ssl = NULL; +# ifndef OPENSSL_NO_QUIC + if (ctx != NULL && IS_QUIC_CTX(ctx)) + /* Never use buffering for QUIC. */ + return BIO_new_ssl_connect(ctx); +# endif + if ((buf = BIO_new(BIO_f_buffer())) == NULL) return NULL; if ((ssl = BIO_new_ssl_connect(ctx)) == NULL) @@ -444,6 +472,13 @@ BIO *BIO_new_ssl_connect(SSL_CTX *ctx) if ((con = BIO_new(BIO_s_connect())) == NULL) return NULL; + +# ifndef OPENSSL_NO_QUIC + if (ctx != NULL && IS_QUIC_CTX(ctx)) + if (!BIO_set_sock_type(con, SOCK_DGRAM)) + goto err; +#endif + if ((ssl = BIO_new_ssl(ctx, 1)) == NULL) goto err; if ((ret = BIO_push(ssl, con)) == NULL) |