diff options
Diffstat (limited to 'crypto/bio')
29 files changed, 1809 insertions, 635 deletions
diff --git a/crypto/bio/bf_buff.c b/crypto/bio/bf_buff.c index 51ae1f918d87..53bd02fe1416 100644 --- a/crypto/bio/bf_buff.c +++ b/crypto/bio/bf_buff.c @@ -1,7 +1,7 @@ /* - * Copyright 1995-2016 The OpenSSL Project Authors. All Rights Reserved. + * Copyright 1995-2021 The OpenSSL Project Authors. All Rights Reserved. * - * Licensed under the OpenSSL license (the "License"). You may not use + * 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 * in the file LICENSE in the source distribution or at * https://www.openssl.org/source/license.html @@ -25,10 +25,8 @@ static long buffer_callback_ctrl(BIO *h, int cmd, BIO_info_cb *fp); static const BIO_METHOD methods_buffer = { BIO_TYPE_BUFFER, "buffer", - /* TODO: Convert to new style write function */ bwrite_conv, buffer_write, - /* TODO: Convert to new style read function */ bread_conv, buffer_read, buffer_puts, @@ -289,7 +287,9 @@ static long buffer_ctrl(BIO *b, int cmd, long num, void *ptr) break; case BIO_C_SET_BUFF_READ_DATA: if (num > ctx->ibuf_size) { - p1 = OPENSSL_malloc((int)num); + if (num <= 0) + return 0; + p1 = OPENSSL_malloc((size_t)num); if (p1 == NULL) goto malloc_error; OPENSSL_free(ctx->ibuf); @@ -318,12 +318,14 @@ static long buffer_ctrl(BIO *b, int cmd, long num, void *ptr) p1 = ctx->ibuf; p2 = ctx->obuf; if ((ibs > DEFAULT_BUFFER_SIZE) && (ibs != ctx->ibuf_size)) { - p1 = OPENSSL_malloc((int)num); + if (num <= 0) + return 0; + p1 = OPENSSL_malloc((size_t)num); if (p1 == NULL) goto malloc_error; } if ((obs > DEFAULT_BUFFER_SIZE) && (obs != ctx->obuf_size)) { - p2 = OPENSSL_malloc((int)num); + p2 = OPENSSL_malloc((size_t)num); if (p2 == NULL) { if (p1 != ctx->ibuf) OPENSSL_free(p1); @@ -381,8 +383,8 @@ static long buffer_ctrl(BIO *b, int cmd, long num, void *ptr) break; case BIO_CTRL_DUP: dbio = (BIO *)ptr; - if (!BIO_set_read_buffer_size(dbio, ctx->ibuf_size) || - !BIO_set_write_buffer_size(dbio, ctx->obuf_size)) + if (BIO_set_read_buffer_size(dbio, ctx->ibuf_size) <= 0 || + BIO_set_write_buffer_size(dbio, ctx->obuf_size) <= 0) ret = 0; break; case BIO_CTRL_PEEK: @@ -404,22 +406,15 @@ static long buffer_ctrl(BIO *b, int cmd, long num, void *ptr) } return ret; malloc_error: - BIOerr(BIO_F_BUFFER_CTRL, ERR_R_MALLOC_FAILURE); + ERR_raise(ERR_LIB_BIO, ERR_R_MALLOC_FAILURE); return 0; } static long buffer_callback_ctrl(BIO *b, int cmd, BIO_info_cb *fp) { - long ret = 1; - if (b->next_bio == NULL) return 0; - switch (cmd) { - default: - ret = BIO_callback_ctrl(b->next_bio, cmd, fp); - break; - } - return ret; + return BIO_callback_ctrl(b->next_bio, cmd, fp); } static int buffer_gets(BIO *b, char *buf, int size) diff --git a/crypto/bio/bf_lbuf.c b/crypto/bio/bf_lbuf.c index 72f9901813ea..6908e64d3652 100644 --- a/crypto/bio/bf_lbuf.c +++ b/crypto/bio/bf_lbuf.c @@ -1,7 +1,7 @@ /* - * Copyright 1995-2018 The OpenSSL Project Authors. All Rights Reserved. + * Copyright 1995-2021 The OpenSSL Project Authors. All Rights Reserved. * - * Licensed under the OpenSSL license (the "License"). You may not use + * 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 * in the file LICENSE in the source distribution or at * https://www.openssl.org/source/license.html @@ -30,10 +30,8 @@ static long linebuffer_callback_ctrl(BIO *h, int cmd, BIO_info_cb *fp); static const BIO_METHOD methods_linebuffer = { BIO_TYPE_LINEBUFFER, "linebuffer", - /* TODO: Convert to new style write function */ bwrite_conv, linebuffer_write, - /* TODO: Convert to new style read function */ bread_conv, linebuffer_read, linebuffer_puts, @@ -60,12 +58,12 @@ static int linebuffer_new(BIO *bi) BIO_LINEBUFFER_CTX *ctx; if ((ctx = OPENSSL_malloc(sizeof(*ctx))) == NULL) { - BIOerr(BIO_F_LINEBUFFER_NEW, ERR_R_MALLOC_FAILURE); + ERR_raise(ERR_LIB_BIO, ERR_R_MALLOC_FAILURE); return 0; } ctx->obuf = OPENSSL_malloc(DEFAULT_LINEBUFFER_SIZE); if (ctx->obuf == NULL) { - BIOerr(BIO_F_LINEBUFFER_NEW, ERR_R_MALLOC_FAILURE); + ERR_raise(ERR_LIB_BIO, ERR_R_MALLOC_FAILURE); OPENSSL_free(ctx); return 0; } @@ -232,10 +230,12 @@ static long linebuffer_ctrl(BIO *b, int cmd, long num, void *ptr) } break; case BIO_C_SET_BUFF_SIZE: + if (num > INT_MAX) + return 0; obs = (int)num; p = ctx->obuf; if ((obs > DEFAULT_LINEBUFFER_SIZE) && (obs != ctx->obuf_size)) { - p = OPENSSL_malloc((int)num); + p = OPENSSL_malloc((size_t)obs); if (p == NULL) goto malloc_error; } @@ -284,7 +284,7 @@ static long linebuffer_ctrl(BIO *b, int cmd, long num, void *ptr) break; case BIO_CTRL_DUP: dbio = (BIO *)ptr; - if (!BIO_set_write_buffer_size(dbio, ctx->obuf_size)) + if (BIO_set_write_buffer_size(dbio, ctx->obuf_size) <= 0) ret = 0; break; default: @@ -295,22 +295,15 @@ static long linebuffer_ctrl(BIO *b, int cmd, long num, void *ptr) } return ret; malloc_error: - BIOerr(BIO_F_LINEBUFFER_CTRL, ERR_R_MALLOC_FAILURE); + ERR_raise(ERR_LIB_BIO, ERR_R_MALLOC_FAILURE); return 0; } static long linebuffer_callback_ctrl(BIO *b, int cmd, BIO_info_cb *fp) { - long ret = 1; - if (b->next_bio == NULL) return 0; - switch (cmd) { - default: - ret = BIO_callback_ctrl(b->next_bio, cmd, fp); - break; - } - return ret; + return BIO_callback_ctrl(b->next_bio, cmd, fp); } static int linebuffer_gets(BIO *b, char *buf, int size) diff --git a/crypto/bio/bf_nbio.c b/crypto/bio/bf_nbio.c index dd7011ab669f..f9ea1730ba31 100644 --- a/crypto/bio/bf_nbio.c +++ b/crypto/bio/bf_nbio.c @@ -1,7 +1,7 @@ /* - * Copyright 1995-2018 The OpenSSL Project Authors. All Rights Reserved. + * Copyright 1995-2021 The OpenSSL Project Authors. All Rights Reserved. * - * Licensed under the OpenSSL license (the "License"). You may not use + * 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 * in the file LICENSE in the source distribution or at * https://www.openssl.org/source/license.html @@ -34,10 +34,8 @@ typedef struct nbio_test_st { static const BIO_METHOD methods_nbiof = { BIO_TYPE_NBIO_TEST, "non-blocking IO test filter", - /* TODO: Convert to new style write function */ bwrite_conv, nbiof_write, - /* TODO: Convert to new style read function */ bread_conv, nbiof_read, nbiof_puts, @@ -58,7 +56,7 @@ static int nbiof_new(BIO *bi) NBIO_TEST *nt; if ((nt = OPENSSL_zalloc(sizeof(*nt))) == NULL) { - BIOerr(BIO_F_NBIOF_NEW, ERR_R_MALLOC_FAILURE); + ERR_raise(ERR_LIB_BIO, ERR_R_MALLOC_FAILURE); return 0; } nt->lrn = -1; @@ -173,16 +171,9 @@ static long nbiof_ctrl(BIO *b, int cmd, long num, void *ptr) static long nbiof_callback_ctrl(BIO *b, int cmd, BIO_info_cb *fp) { - long ret = 1; - if (b->next_bio == NULL) return 0; - switch (cmd) { - default: - ret = BIO_callback_ctrl(b->next_bio, cmd, fp); - break; - } - return ret; + return BIO_callback_ctrl(b->next_bio, cmd, fp); } static int nbiof_gets(BIO *bp, char *buf, int size) diff --git a/crypto/bio/bf_null.c b/crypto/bio/bf_null.c index 48c6be692a5d..7add76a4ca5c 100644 --- a/crypto/bio/bf_null.c +++ b/crypto/bio/bf_null.c @@ -1,7 +1,7 @@ /* - * Copyright 1995-2018 The OpenSSL Project Authors. All Rights Reserved. + * Copyright 1995-2021 The OpenSSL Project Authors. All Rights Reserved. * - * Licensed under the OpenSSL license (the "License"). You may not use + * 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 * in the file LICENSE in the source distribution or at * https://www.openssl.org/source/license.html @@ -25,10 +25,8 @@ static long nullf_callback_ctrl(BIO *h, int cmd, BIO_info_cb *fp); static const BIO_METHOD methods_nullf = { BIO_TYPE_NULL_FILTER, "NULL filter", - /* TODO: Convert to new style write function */ bwrite_conv, nullf_write, - /* TODO: Convert to new style read function */ bread_conv, nullf_read, nullf_puts, @@ -95,16 +93,9 @@ static long nullf_ctrl(BIO *b, int cmd, long num, void *ptr) static long nullf_callback_ctrl(BIO *b, int cmd, BIO_info_cb *fp) { - long ret = 1; - if (b->next_bio == NULL) return 0; - switch (cmd) { - default: - ret = BIO_callback_ctrl(b->next_bio, cmd, fp); - break; - } - return ret; + return BIO_callback_ctrl(b->next_bio, cmd, fp); } static int nullf_gets(BIO *bp, char *buf, int size) diff --git a/crypto/bio/bf_prefix.c b/crypto/bio/bf_prefix.c new file mode 100644 index 000000000000..872efa13b559 --- /dev/null +++ b/crypto/bio/bf_prefix.c @@ -0,0 +1,207 @@ +/* + * Copyright 2018-2021 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 + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html + */ + +#include <stdio.h> +#include <string.h> +#include <errno.h> +#include "bio_local.h" + +static int prefix_write(BIO *b, const char *out, size_t outl, + size_t *numwritten); +static int prefix_read(BIO *b, char *buf, size_t size, size_t *numread); +static int prefix_puts(BIO *b, const char *str); +static int prefix_gets(BIO *b, char *str, int size); +static long prefix_ctrl(BIO *b, int cmd, long arg1, void *arg2); +static int prefix_create(BIO *b); +static int prefix_destroy(BIO *b); +static long prefix_callback_ctrl(BIO *b, int cmd, BIO_info_cb *fp); + +static const BIO_METHOD prefix_meth = { + BIO_TYPE_BUFFER, + "prefix", + prefix_write, + NULL, + prefix_read, + NULL, + prefix_puts, + prefix_gets, + prefix_ctrl, + prefix_create, + prefix_destroy, + prefix_callback_ctrl, +}; + +const BIO_METHOD *BIO_f_prefix(void) +{ + return &prefix_meth; +} + +typedef struct prefix_ctx_st { + char *prefix; /* Text prefix, given by user */ + unsigned int indent; /* Indentation amount, given by user */ + + int linestart; /* flag to indicate we're at the line start */ +} PREFIX_CTX; + +static int prefix_create(BIO *b) +{ + PREFIX_CTX *ctx = OPENSSL_zalloc(sizeof(*ctx)); + + if (ctx == NULL) + return 0; + + ctx->prefix = NULL; + ctx->indent = 0; + ctx->linestart = 1; + BIO_set_data(b, ctx); + BIO_set_init(b, 1); + return 1; +} + +static int prefix_destroy(BIO *b) +{ + PREFIX_CTX *ctx = BIO_get_data(b); + + OPENSSL_free(ctx->prefix); + OPENSSL_free(ctx); + return 1; +} + +static int prefix_read(BIO *b, char *in, size_t size, size_t *numread) +{ + return BIO_read_ex(BIO_next(b), in, size, numread); +} + +static int prefix_write(BIO *b, const char *out, size_t outl, + size_t *numwritten) +{ + PREFIX_CTX *ctx = BIO_get_data(b); + + if (ctx == NULL) + return 0; + + /* + * If no prefix is set or if it's empty, and no indentation amount is set, + * we've got nothing to do here + */ + if ((ctx->prefix == NULL || *ctx->prefix == '\0') + && ctx->indent == 0) { + /* + * We do note if what comes next will be a new line, though, so we're + * prepared to handle prefix and indentation the next time around. + */ + if (outl > 0) + ctx->linestart = (out[outl-1] == '\n'); + return BIO_write_ex(BIO_next(b), out, outl, numwritten); + } + + *numwritten = 0; + + while (outl > 0) { + size_t i; + char c; + + /* + * If we know that we're at the start of the line, output prefix and + * indentation. + */ + if (ctx->linestart) { + size_t dontcare; + + if (ctx->prefix != NULL + && !BIO_write_ex(BIO_next(b), ctx->prefix, strlen(ctx->prefix), + &dontcare)) + return 0; + BIO_printf(BIO_next(b), "%*s", ctx->indent, ""); + ctx->linestart = 0; + } + + /* Now, go look for the next LF, or the end of the string */ + for (i = 0, c = '\0'; i < outl && (c = out[i]) != '\n'; i++) + continue; + if (c == '\n') + i++; + + /* Output what we found so far */ + while (i > 0) { + size_t num = 0; + + if (!BIO_write_ex(BIO_next(b), out, i, &num)) + return 0; + out += num; + outl -= num; + *numwritten += num; + i -= num; + } + + /* If we found a LF, what follows is a new line, so take note */ + if (c == '\n') + ctx->linestart = 1; + } + + return 1; +} + +static long prefix_ctrl(BIO *b, int cmd, long num, void *ptr) +{ + long ret = 0; + PREFIX_CTX *ctx; + + if (b == NULL || (ctx = BIO_get_data(b)) == NULL) + return -1; + + switch (cmd) { + case BIO_CTRL_SET_PREFIX: + OPENSSL_free(ctx->prefix); + if (ptr == NULL) { + ctx->prefix = NULL; + ret = 1; + } else { + ctx->prefix = OPENSSL_strdup((const char *)ptr); + ret = ctx->prefix != NULL; + } + break; + case BIO_CTRL_SET_INDENT: + if (num >= 0) { + ctx->indent = (unsigned int)num; + ret = 1; + } + break; + case BIO_CTRL_GET_INDENT: + ret = (long)ctx->indent; + break; + default: + /* Commands that we intercept before passing them along */ + switch (cmd) { + case BIO_C_FILE_SEEK: + case BIO_CTRL_RESET: + ctx->linestart = 1; + break; + } + if (BIO_next(b) != NULL) + ret = BIO_ctrl(BIO_next(b), cmd, num, ptr); + break; + } + return ret; +} + +static long prefix_callback_ctrl(BIO *b, int cmd, BIO_info_cb *fp) +{ + return BIO_callback_ctrl(BIO_next(b), cmd, fp); +} + +static int prefix_gets(BIO *b, char *buf, int size) +{ + return BIO_gets(BIO_next(b), buf, size); +} + +static int prefix_puts(BIO *b, const char *str) +{ + return BIO_write(b, str, strlen(str)); +} diff --git a/crypto/bio/bf_readbuff.c b/crypto/bio/bf_readbuff.c new file mode 100644 index 000000000000..2409c9db97cc --- /dev/null +++ b/crypto/bio/bf_readbuff.c @@ -0,0 +1,291 @@ +/* + * Copyright 2021-2024 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 + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html + */ + +/* + * This is a read only BIO filter that can be used to add BIO_tell() and + * BIO_seek() support to source/sink BIO's (such as a file BIO that uses stdin). + * It does this by caching ALL data read from the BIO source/sink into a + * resizable memory buffer. + */ + +#include <stdio.h> +#include <errno.h> +#include "bio_local.h" +#include "internal/cryptlib.h" + +#define DEFAULT_BUFFER_SIZE 4096 + +static int readbuffer_write(BIO *h, const char *buf, int num); +static int readbuffer_read(BIO *h, char *buf, int size); +static int readbuffer_puts(BIO *h, const char *str); +static int readbuffer_gets(BIO *h, char *str, int size); +static long readbuffer_ctrl(BIO *h, int cmd, long arg1, void *arg2); +static int readbuffer_new(BIO *h); +static int readbuffer_free(BIO *data); +static long readbuffer_callback_ctrl(BIO *h, int cmd, BIO_info_cb *fp); + +static const BIO_METHOD methods_readbuffer = { + BIO_TYPE_BUFFER, + "readbuffer", + bwrite_conv, + readbuffer_write, + bread_conv, + readbuffer_read, + readbuffer_puts, + readbuffer_gets, + readbuffer_ctrl, + readbuffer_new, + readbuffer_free, + readbuffer_callback_ctrl, +}; + +const BIO_METHOD *BIO_f_readbuffer(void) +{ + return &methods_readbuffer; +} + +static int readbuffer_new(BIO *bi) +{ + BIO_F_BUFFER_CTX *ctx = OPENSSL_zalloc(sizeof(*ctx)); + + if (ctx == NULL) + return 0; + ctx->ibuf_size = DEFAULT_BUFFER_SIZE; + ctx->ibuf = OPENSSL_zalloc(DEFAULT_BUFFER_SIZE); + if (ctx->ibuf == NULL) { + OPENSSL_free(ctx); + return 0; + } + + bi->init = 1; + bi->ptr = (char *)ctx; + bi->flags = 0; + return 1; +} + +static int readbuffer_free(BIO *a) +{ + BIO_F_BUFFER_CTX *b; + + if (a == NULL) + return 0; + b = (BIO_F_BUFFER_CTX *)a->ptr; + OPENSSL_free(b->ibuf); + OPENSSL_free(a->ptr); + a->ptr = NULL; + a->init = 0; + a->flags = 0; + return 1; +} + +static int readbuffer_resize(BIO_F_BUFFER_CTX *ctx, int sz) +{ + char *tmp; + + /* Figure out how many blocks are required */ + sz += (ctx->ibuf_off + DEFAULT_BUFFER_SIZE - 1); + sz = DEFAULT_BUFFER_SIZE * (sz / DEFAULT_BUFFER_SIZE); + + /* Resize if the buffer is not big enough */ + if (sz > ctx->ibuf_size) { + tmp = OPENSSL_realloc(ctx->ibuf, sz); + if (tmp == NULL) + return 0; + ctx->ibuf = tmp; + ctx->ibuf_size = sz; + } + return 1; +} + +static int readbuffer_read(BIO *b, char *out, int outl) +{ + int i, num = 0; + BIO_F_BUFFER_CTX *ctx; + + if (out == NULL || outl == 0) + return 0; + ctx = (BIO_F_BUFFER_CTX *)b->ptr; + + if ((ctx == NULL) || (b->next_bio == NULL)) + return 0; + BIO_clear_retry_flags(b); + + for (;;) { + i = ctx->ibuf_len; + /* If there is something in the buffer just read it. */ + if (i != 0) { + if (i > outl) + i = outl; + memcpy(out, &(ctx->ibuf[ctx->ibuf_off]), i); + ctx->ibuf_off += i; + ctx->ibuf_len -= i; + num += i; + /* Exit if we have read the bytes required out of the buffer */ + if (outl == i) + return num; + outl -= i; + out += i; + } + + /* Only gets here if the buffer has been consumed */ + if (!readbuffer_resize(ctx, outl)) + return 0; + + /* Do some buffering by reading from the next bio */ + i = BIO_read(b->next_bio, ctx->ibuf + ctx->ibuf_off, outl); + if (i <= 0) { + BIO_copy_next_retry(b); + if (i < 0) + return ((num > 0) ? num : i); + else + return num; /* i == 0 */ + } + ctx->ibuf_len = i; + } +} + +static int readbuffer_write(BIO *b, const char *in, int inl) +{ + return 0; +} +static int readbuffer_puts(BIO *b, const char *str) +{ + return 0; +} + +static long readbuffer_ctrl(BIO *b, int cmd, long num, void *ptr) +{ + BIO_F_BUFFER_CTX *ctx; + long ret = 1, sz; + + ctx = (BIO_F_BUFFER_CTX *)b->ptr; + + switch (cmd) { + case BIO_CTRL_EOF: + if (ctx->ibuf_len > 0) + return 0; + if (b->next_bio == NULL) + return 1; + ret = BIO_ctrl(b->next_bio, cmd, num, ptr); + break; + + case BIO_C_FILE_SEEK: + case BIO_CTRL_RESET: + sz = ctx->ibuf_off + ctx->ibuf_len; + /* Assume it can only seek backwards */ + if (num < 0 || num > sz) + return 0; + ctx->ibuf_off = num; + ctx->ibuf_len = sz - num; + break; + + case BIO_C_FILE_TELL: + case BIO_CTRL_INFO: + ret = (long)ctx->ibuf_off; + break; + case BIO_CTRL_PENDING: + ret = (long)ctx->ibuf_len; + if (ret == 0) { + if (b->next_bio == NULL) + return 0; + ret = BIO_ctrl(b->next_bio, cmd, num, ptr); + } + break; + case BIO_CTRL_DUP: + case BIO_CTRL_FLUSH: + ret = 1; + break; + default: + ret = 0; + break; + } + return ret; +} + +static long readbuffer_callback_ctrl(BIO *b, int cmd, BIO_info_cb *fp) +{ + if (b->next_bio == NULL) + return 0; + return BIO_callback_ctrl(b->next_bio, cmd, fp); +} + +static int readbuffer_gets(BIO *b, char *buf, int size) +{ + BIO_F_BUFFER_CTX *ctx; + int num = 0, num_chars, found_newline; + char *p; + int i, j; + + if (buf == NULL || size == 0) + return 0; + --size; /* the passed in size includes the terminator - so remove it here */ + ctx = (BIO_F_BUFFER_CTX *)b->ptr; + + if (ctx == NULL || b->next_bio == NULL) + return 0; + BIO_clear_retry_flags(b); + + /* If data is already buffered then use this first */ + if (ctx->ibuf_len > 0) { + p = ctx->ibuf + ctx->ibuf_off; + found_newline = 0; + for (num_chars = 0; + (num_chars < ctx->ibuf_len) && (num_chars < size); + num_chars++) { + *buf++ = p[num_chars]; + if (p[num_chars] == '\n') { + found_newline = 1; + num_chars++; + break; + } + } + num += num_chars; + size -= num_chars; + ctx->ibuf_len -= num_chars; + ctx->ibuf_off += num_chars; + if (found_newline || size == 0) { + *buf = '\0'; + return num; + } + } + /* + * If there is no buffered data left then read any remaining data from the + * next bio. + */ + + /* Resize if we have to */ + if (!readbuffer_resize(ctx, 1 + size)) + return 0; + /* + * Read more data from the next bio using BIO_read_ex: + * Note we cannot use BIO_gets() here as it does not work on a + * binary stream that contains 0x00. (Since strlen() will stop at + * any 0x00 not at the last read '\n' in a FILE bio). + * Also note that some applications open and close the file bio + * multiple times and need to read the next available block when using + * stdin - so we need to READ one byte at a time! + */ + p = ctx->ibuf + ctx->ibuf_off; + for (i = 0; i < size; ++i) { + j = BIO_read(b->next_bio, p, 1); + if (j <= 0) { + BIO_copy_next_retry(b); + *buf = '\0'; + return num > 0 ? num : j; + } + *buf++ = *p; + num++; + ctx->ibuf_off++; + if (*p == '\n') + break; + ++p; + } + *buf = '\0'; + return num; +} diff --git a/crypto/bio/b_addr.c b/crypto/bio/bio_addr.c index 0af7a330bc68..d462f424d3a4 100644 --- a/crypto/bio/b_addr.c +++ b/crypto/bio/bio_addr.c @@ -1,7 +1,7 @@ /* - * Copyright 2016-2022 The OpenSSL Project Authors. All Rights Reserved. + * Copyright 2016-2025 The OpenSSL Project Authors. All Rights Reserved. * - * Licensed under the OpenSSL license (the "License"). You may not use + * 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 * in the file LICENSE in the source distribution or at * https://www.openssl.org/source/license.html @@ -11,6 +11,16 @@ # define _GNU_SOURCE #endif +/* + * VC configurations may define UNICODE, to indicate to the C RTL that + * WCHAR functions are preferred. + * This affects functions like gai_strerror(), which is implemented as + * an alias macro for gai_strerrorA() (which returns a const char *) or + * gai_strerrorW() (which returns a const WCHAR *). This source file + * assumes POSIX declarations, so prefer the non-UNICODE definitions. + */ +#undef UNICODE + #include <assert.h> #include <string.h> @@ -44,7 +54,7 @@ BIO_ADDR *BIO_ADDR_new(void) BIO_ADDR *ret = OPENSSL_zalloc(sizeof(*ret)); if (ret == NULL) { - BIOerr(BIO_F_BIO_ADDR_NEW, ERR_R_MALLOC_FAILURE); + ERR_raise(ERR_LIB_BIO, ERR_R_MALLOC_FAILURE); return NULL; } @@ -211,13 +221,12 @@ static int addr_strings(const BIO_ADDR *ap, int numeric, flags)) != 0) { # ifdef EAI_SYSTEM if (ret == EAI_SYSTEM) { - SYSerr(SYS_F_GETNAMEINFO, get_last_socket_error()); - BIOerr(BIO_F_ADDR_STRINGS, ERR_R_SYS_LIB); + ERR_raise_data(ERR_LIB_SYS, get_last_socket_error(), + "calling getnameinfo()"); } else # endif { - BIOerr(BIO_F_ADDR_STRINGS, ERR_R_SYS_LIB); - ERR_add_error_data(1, gai_strerror(ret)); + ERR_raise_data(ERR_LIB_BIO, ERR_R_SYS_LIB, gai_strerror(ret)); } return 0; } @@ -258,7 +267,7 @@ static int addr_strings(const BIO_ADDR *ap, int numeric, OPENSSL_free(*service); *service = NULL; } - BIOerr(BIO_F_ADDR_STRINGS, ERR_R_MALLOC_FAILURE); + ERR_raise(ERR_LIB_BIO, ERR_R_MALLOC_FAILURE); return 0; } @@ -538,20 +547,25 @@ int BIO_parse_hostserv(const char *hostserv, char **host, char **service, *service = NULL; } else { *service = OPENSSL_strndup(p, pl); - if (*service == NULL) + if (*service == NULL) { + if (h != NULL && host != NULL) { + OPENSSL_free(*host); + *host = NULL; + } goto memerr; + } } } return 1; amb_err: - BIOerr(BIO_F_BIO_PARSE_HOSTSERV, BIO_R_AMBIGUOUS_HOST_OR_SERVICE); + ERR_raise(ERR_LIB_BIO, BIO_R_AMBIGUOUS_HOST_OR_SERVICE); return 0; spec_err: - BIOerr(BIO_F_BIO_PARSE_HOSTSERV, BIO_R_MALFORMED_HOST_OR_SERVICE); + ERR_raise(ERR_LIB_BIO, BIO_R_MALFORMED_HOST_OR_SERVICE); return 0; memerr: - BIOerr(BIO_F_BIO_PARSE_HOSTSERV, ERR_R_MALLOC_FAILURE); + ERR_raise(ERR_LIB_BIO, ERR_R_MALLOC_FAILURE); return 0; } @@ -570,7 +584,7 @@ static int addrinfo_wrap(int family, int socktype, BIO_ADDRINFO **bai) { if ((*bai = OPENSSL_zalloc(sizeof(**bai))) == NULL) { - BIOerr(BIO_F_ADDRINFO_WRAP, ERR_R_MALLOC_FAILURE); + ERR_raise(ERR_LIB_BIO, ERR_R_MALLOC_FAILURE); return 0; } @@ -607,8 +621,6 @@ static int addrinfo_wrap(int family, int socktype, DEFINE_RUN_ONCE_STATIC(do_bio_lookup_init) { - if (!OPENSSL_init_crypto(0, NULL)) - return 0; bio_lookup_lock = CRYPTO_THREAD_lock_new(); return bio_lookup_lock != NULL; } @@ -621,8 +633,8 @@ int BIO_lookup(const char *host, const char *service, } /*- - * BIO_lookup_ex - look up the node and service you want to connect to. - * @node: the node you want to connect to. + * BIO_lookup_ex - look up the host and service you want to connect to. + * @host: the host (or node, in case family == AF_UNIX) you want to connect to. * @service: the service you want to connect to. * @lookup_type: declare intent with the result, client or server. * @family: the address family you want to use. Use AF_UNSPEC for any, or @@ -635,7 +647,7 @@ int BIO_lookup(const char *host, const char *service, * with 0 for the protocol) * @res: Storage place for the resulting list of returned addresses * - * This will do a lookup of the node and service that you want to connect to. + * This will do a lookup of the host and service that you want to connect to. * It returns a linked list of different addresses you can try to connect to. * * When no longer needed you should call BIO_ADDRINFO_free() to free the result. @@ -660,7 +672,7 @@ int BIO_lookup_ex(const char *host, const char *service, int lookup_type, #endif break; default: - BIOerr(BIO_F_BIO_LOOKUP_EX, BIO_R_UNSUPPORTED_PROTOCOL_FAMILY); + ERR_raise(ERR_LIB_BIO, BIO_R_UNSUPPORTED_PROTOCOL_FAMILY); return 0; } @@ -669,7 +681,7 @@ int BIO_lookup_ex(const char *host, const char *service, int lookup_type, if (addrinfo_wrap(family, socktype, host, strlen(host), 0, res)) return 1; else - BIOerr(BIO_F_BIO_LOOKUP_EX, ERR_R_MALLOC_FAILURE); + ERR_raise(ERR_LIB_BIO, ERR_R_MALLOC_FAILURE); return 0; } #endif @@ -706,13 +718,14 @@ int BIO_lookup_ex(const char *host, const char *service, int lookup_type, switch ((gai_ret = getaddrinfo(host, service, &hints, res))) { # ifdef EAI_SYSTEM case EAI_SYSTEM: - SYSerr(SYS_F_GETADDRINFO, get_last_socket_error()); - BIOerr(BIO_F_BIO_LOOKUP_EX, ERR_R_SYS_LIB); + ERR_raise_data(ERR_LIB_SYS, get_last_socket_error(), + "calling getaddrinfo()"); + ERR_raise(ERR_LIB_BIO, ERR_R_SYS_LIB); break; # endif # ifdef EAI_MEMORY case EAI_MEMORY: - BIOerr(BIO_F_BIO_LOOKUP_EX, ERR_R_MALLOC_FAILURE); + ERR_raise(ERR_LIB_BIO, ERR_R_MALLOC_FAILURE); break; # endif case 0: @@ -727,8 +740,8 @@ int BIO_lookup_ex(const char *host, const char *service, int lookup_type, goto retry; } # endif - BIOerr(BIO_F_BIO_LOOKUP_EX, ERR_R_SYS_LIB); - ERR_add_error_data(1, gai_strerror(old_ret ? old_ret : gai_ret)); + ERR_raise_data(ERR_LIB_BIO, ERR_R_SYS_LIB, + gai_strerror(old_ret ? old_ret : gai_ret)); break; } } else { @@ -769,12 +782,13 @@ int BIO_lookup_ex(const char *host, const char *service, int lookup_type, #endif if (!RUN_ONCE(&bio_lookup_init, do_bio_lookup_init)) { - BIOerr(BIO_F_BIO_LOOKUP_EX, ERR_R_MALLOC_FAILURE); - ret = 0; - goto err; + ERR_raise(ERR_LIB_BIO, ERR_R_MALLOC_FAILURE); + return 0; } - CRYPTO_THREAD_write_lock(bio_lookup_lock); + if (!CRYPTO_THREAD_write_lock(bio_lookup_lock)) + return 0; + he_fallback_address = INADDR_ANY; if (host == NULL) { he = &he_fallback; @@ -788,7 +802,7 @@ int BIO_lookup_ex(const char *host, const char *service, int lookup_type, default: /* We forgot to handle a lookup type! */ assert("We forgot to handle a lookup type!" == NULL); - BIOerr(BIO_F_BIO_LOOKUP_EX, ERR_R_INTERNAL_ERROR); + ERR_raise(ERR_LIB_BIO, ERR_R_INTERNAL_ERROR); ret = 0; goto err; } @@ -810,12 +824,15 @@ int BIO_lookup_ex(const char *host, const char *service, int lookup_type, */ # if defined(OPENSSL_SYS_VXWORKS) /* h_errno doesn't exist on VxWorks */ - SYSerr(SYS_F_GETHOSTBYNAME, 1000 ); + ERR_raise_data(ERR_LIB_SYS, 1000, + "calling gethostbyname()"); # else - SYSerr(SYS_F_GETHOSTBYNAME, 1000 + h_errno); + ERR_raise_data(ERR_LIB_SYS, 1000 + h_errno, + "calling gethostbyname()"); # endif #else - SYSerr(SYS_F_GETHOSTBYNAME, WSAGetLastError()); + ERR_raise_data(ERR_LIB_SYS, get_last_socket_error(), + "calling gethostbyname()"); #endif ret = 0; goto err; @@ -861,15 +878,12 @@ int BIO_lookup_ex(const char *host, const char *service, int lookup_type, se = getservbyname(service, proto); if (se == NULL) { -#ifndef OPENSSL_SYS_WINDOWS - SYSerr(SYS_F_GETSERVBYNAME, errno); -#else - SYSerr(SYS_F_GETSERVBYNAME, WSAGetLastError()); -#endif + ERR_raise_data(ERR_LIB_SYS, get_last_socket_error(), + "calling getservbyname()"); goto err; } } else { - BIOerr(BIO_F_BIO_LOOKUP_EX, BIO_R_MALFORMED_HOST_OR_SERVICE); + ERR_raise(ERR_LIB_BIO, BIO_R_MALFORMED_HOST_OR_SERVICE); goto err; } } @@ -911,7 +925,7 @@ int BIO_lookup_ex(const char *host, const char *service, int lookup_type, addrinfo_malloc_err: BIO_ADDRINFO_free(*res); *res = NULL; - BIOerr(BIO_F_BIO_LOOKUP_EX, ERR_R_MALLOC_FAILURE); + ERR_raise(ERR_LIB_BIO, ERR_R_MALLOC_FAILURE); ret = 0; goto err; } diff --git a/crypto/bio/bio_cb.c b/crypto/bio/bio_cb.c index a153100a8825..522a05369dc7 100644 --- a/crypto/bio/bio_cb.c +++ b/crypto/bio/bio_cb.c @@ -1,12 +1,14 @@ /* - * Copyright 1995-2017 The OpenSSL Project Authors. All Rights Reserved. + * Copyright 1995-2021 The OpenSSL Project Authors. All Rights Reserved. * - * Licensed under the OpenSSL license (the "License"). You may not use + * 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 * in the file LICENSE in the source distribution or at * https://www.openssl.org/source/license.html */ +#define OPENSSL_SUPPRESS_DEPRECATED + #include <stdio.h> #include <string.h> #include <stdlib.h> @@ -14,25 +16,25 @@ #include "internal/cryptlib.h" #include <openssl/err.h> -long BIO_debug_callback(BIO *bio, int cmd, const char *argp, - int argi, long argl, long ret) +long BIO_debug_callback_ex(BIO *bio, int cmd, const char *argp, size_t len, + int argi, long argl, int ret, size_t *processed) { BIO *b; char buf[256]; char *p; - long r = 1; - int len, left; + int left; + size_t l = 0; - if (BIO_CB_RETURN & cmd) - r = ret; + if (processed != NULL) + l = *processed; - len = BIO_snprintf(buf, sizeof(buf), "BIO[%p]: ", (void *)bio); + left = BIO_snprintf(buf, sizeof(buf), "BIO[%p]: ", (void *)bio); /* Ignore errors and continue printing the other information. */ - if (len < 0) - len = 0; - p = buf + len; - left = sizeof(buf) - len; + if (left < 0) + left = 0; + p = buf + left; + left = sizeof(buf) - left; switch (cmd) { case BIO_CB_FREE: @@ -40,47 +42,47 @@ long BIO_debug_callback(BIO *bio, int cmd, const char *argp, break; case BIO_CB_READ: if (bio->method->type & BIO_TYPE_DESCRIPTOR) - BIO_snprintf(p, left, "read(%d,%lu) - %s fd=%d\n", - bio->num, (unsigned long)argi, + BIO_snprintf(p, left, "read(%d,%zu) - %s fd=%d\n", + bio->num, len, bio->method->name, bio->num); else - BIO_snprintf(p, left, "read(%d,%lu) - %s\n", - bio->num, (unsigned long)argi, bio->method->name); + BIO_snprintf(p, left, "read(%d,%zu) - %s\n", + bio->num, len, bio->method->name); break; case BIO_CB_WRITE: if (bio->method->type & BIO_TYPE_DESCRIPTOR) - BIO_snprintf(p, left, "write(%d,%lu) - %s fd=%d\n", - bio->num, (unsigned long)argi, + BIO_snprintf(p, left, "write(%d,%zu) - %s fd=%d\n", + bio->num, len, bio->method->name, bio->num); else - BIO_snprintf(p, left, "write(%d,%lu) - %s\n", - bio->num, (unsigned long)argi, bio->method->name); + BIO_snprintf(p, left, "write(%d,%zu) - %s\n", + bio->num, len, bio->method->name); break; case BIO_CB_PUTS: BIO_snprintf(p, left, "puts() - %s\n", bio->method->name); break; case BIO_CB_GETS: - BIO_snprintf(p, left, "gets(%lu) - %s\n", (unsigned long)argi, + BIO_snprintf(p, left, "gets(%zu) - %s\n", len, bio->method->name); break; case BIO_CB_CTRL: - BIO_snprintf(p, left, "ctrl(%lu) - %s\n", (unsigned long)argi, + BIO_snprintf(p, left, "ctrl(%d) - %s\n", argi, bio->method->name); break; case BIO_CB_RETURN | BIO_CB_READ: - BIO_snprintf(p, left, "read return %ld\n", ret); + BIO_snprintf(p, left, "read return %d processed: %zu\n", ret, l); break; case BIO_CB_RETURN | BIO_CB_WRITE: - BIO_snprintf(p, left, "write return %ld\n", ret); + BIO_snprintf(p, left, "write return %d processed: %zu\n", ret, l); break; case BIO_CB_RETURN | BIO_CB_GETS: - BIO_snprintf(p, left, "gets return %ld\n", ret); + BIO_snprintf(p, left, "gets return %d processed: %zu\n", ret, l); break; case BIO_CB_RETURN | BIO_CB_PUTS: - BIO_snprintf(p, left, "puts return %ld\n", ret); + BIO_snprintf(p, left, "puts return %d processed: %zu\n", ret, l); break; case BIO_CB_RETURN | BIO_CB_CTRL: - BIO_snprintf(p, left, "ctrl return %ld\n", ret); + BIO_snprintf(p, left, "ctrl return %d\n", ret); break; default: BIO_snprintf(p, left, "bio callback - unknown type (%d)\n", cmd); @@ -94,5 +96,19 @@ long BIO_debug_callback(BIO *bio, int cmd, const char *argp, else fputs(buf, stderr); #endif - return r; + return ret; +} + +#ifndef OPENSSL_NO_DEPRECATED_3_0 +long BIO_debug_callback(BIO *bio, int cmd, const char *argp, + int argi, long argl, long ret) +{ + size_t processed = 0; + + if (ret > 0) + processed = (size_t)ret; + BIO_debug_callback_ex(bio, cmd, argp, (size_t)argi, + argi, argl, ret > 0 ? 1 : (int)ret, &processed); + return ret; } +#endif diff --git a/crypto/bio/b_dump.c b/crypto/bio/bio_dump.c index f175e244b233..04191a653054 100644 --- a/crypto/bio/b_dump.c +++ b/crypto/bio/bio_dump.c @@ -1,7 +1,7 @@ /* - * Copyright 1995-2018 The OpenSSL Project Authors. All Rights Reserved. + * Copyright 1995-2025 The OpenSSL Project Authors. All Rights Reserved. * - * Licensed under the OpenSSL license (the "License"). You may not use + * 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 * in the file LICENSE in the source distribution or at * https://www.openssl.org/source/license.html @@ -20,15 +20,16 @@ #define SPACE(buf, pos, n) (sizeof(buf) - (pos) > (n)) int BIO_dump_cb(int (*cb) (const void *data, size_t len, void *u), - void *u, const char *s, int len) + void *u, const void *s, int len) { return BIO_dump_indent_cb(cb, u, s, len, 0); } int BIO_dump_indent_cb(int (*cb) (const void *data, size_t len, void *u), - void *u, const char *s, int len, int indent) + void *u, const void *v, int len, int indent) { - int ret = 0; + const unsigned char *s = v; + int res, ret = 0; char buf[288 + 1]; int i, j, rows, n; unsigned char ch; @@ -46,12 +47,14 @@ int BIO_dump_indent_cb(int (*cb) (const void *data, size_t len, void *u), for (i = 0; i < rows; i++) { n = BIO_snprintf(buf, sizeof(buf), "%*s%04x - ", indent, "", i * dump_width); + if (n < 0) + return -1; for (j = 0; j < dump_width; j++) { if (SPACE(buf, n, 3)) { if (((i * dump_width) + j) >= len) { strcpy(buf + n, " "); } else { - ch = ((unsigned char)*(s + i * dump_width + j)) & 0xff; + ch = *(s + i * dump_width + j) & 0xff; BIO_snprintf(buf + n, 4, "%02x%c", ch, j == 7 ? '-' : ' '); } @@ -66,7 +69,7 @@ int BIO_dump_indent_cb(int (*cb) (const void *data, size_t len, void *u), if (((i * dump_width) + j) >= len) break; if (SPACE(buf, n, 1)) { - ch = ((unsigned char)*(s + i * dump_width + j)) & 0xff; + ch = *(s + i * dump_width + j) & 0xff; #ifndef CHARSET_EBCDIC buf[n++] = ((ch >= ' ') && (ch <= '~')) ? ch : '.'; #else @@ -85,7 +88,10 @@ int BIO_dump_indent_cb(int (*cb) (const void *data, size_t len, void *u), * if this is the last call then update the ddt_dump thing so that we * will move the selection point in the debug window */ - ret += cb((void *)buf, n, u); + res = cb((void *)buf, n, u); + if (res < 0) + return res; + ret += res; } return ret; } @@ -96,12 +102,12 @@ static int write_fp(const void *data, size_t len, void *fp) return UP_fwrite(data, len, 1, fp); } -int BIO_dump_fp(FILE *fp, const char *s, int len) +int BIO_dump_fp(FILE *fp, const void *s, int len) { return BIO_dump_cb(write_fp, fp, s, len); } -int BIO_dump_indent_fp(FILE *fp, const char *s, int len, int indent) +int BIO_dump_indent_fp(FILE *fp, const void *s, int len, int indent) { return BIO_dump_indent_cb(write_fp, fp, s, len, indent); } @@ -112,19 +118,20 @@ static int write_bio(const void *data, size_t len, void *bp) return BIO_write((BIO *)bp, (const char *)data, len); } -int BIO_dump(BIO *bp, const char *s, int len) +int BIO_dump(BIO *bp, const void *s, int len) { return BIO_dump_cb(write_bio, bp, s, len); } -int BIO_dump_indent(BIO *bp, const char *s, int len, int indent) +int BIO_dump_indent(BIO *bp, const void *s, int len, int indent) { return BIO_dump_indent_cb(write_bio, bp, s, len, indent); } -int BIO_hex_string(BIO *out, int indent, int width, unsigned char *data, +int BIO_hex_string(BIO *out, int indent, int width, const void *data, int datalen) { + const unsigned char *d = data; int i, j = 0; if (datalen < 1) @@ -134,7 +141,7 @@ int BIO_hex_string(BIO *out, int indent, int width, unsigned char *data, if (i && !j) BIO_printf(out, "%*s", indent, ""); - BIO_printf(out, "%02X:", data[i]); + BIO_printf(out, "%02X:", d[i]); j = (j + 1) % width; if (!j) @@ -143,6 +150,6 @@ int BIO_hex_string(BIO *out, int indent, int width, unsigned char *data, if (i && !j) BIO_printf(out, "%*s", indent, ""); - BIO_printf(out, "%02X", data[datalen - 1]); + BIO_printf(out, "%02X", d[datalen - 1]); return 1; } diff --git a/crypto/bio/bio_err.c b/crypto/bio/bio_err.c index 7aa9dabb2915..7a36c61148a7 100644 --- a/crypto/bio/bio_err.c +++ b/crypto/bio/bio_err.c @@ -1,8 +1,8 @@ /* * Generated by util/mkerr.pl DO NOT EDIT - * Copyright 1995-2018 The OpenSSL Project Authors. All Rights Reserved. + * Copyright 1995-2021 The OpenSSL Project Authors. All Rights Reserved. * - * Licensed under the OpenSSL license (the "License"). You may not use + * 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 * in the file LICENSE in the source distribution or at * https://www.openssl.org/source/license.html @@ -10,69 +10,10 @@ #include <openssl/err.h> #include <openssl/bioerr.h> +#include "crypto/bioerr.h" #ifndef OPENSSL_NO_ERR -static const ERR_STRING_DATA BIO_str_functs[] = { - {ERR_PACK(ERR_LIB_BIO, BIO_F_ACPT_STATE, 0), "acpt_state"}, - {ERR_PACK(ERR_LIB_BIO, BIO_F_ADDRINFO_WRAP, 0), "addrinfo_wrap"}, - {ERR_PACK(ERR_LIB_BIO, BIO_F_ADDR_STRINGS, 0), "addr_strings"}, - {ERR_PACK(ERR_LIB_BIO, BIO_F_BIO_ACCEPT, 0), "BIO_accept"}, - {ERR_PACK(ERR_LIB_BIO, BIO_F_BIO_ACCEPT_EX, 0), "BIO_accept_ex"}, - {ERR_PACK(ERR_LIB_BIO, BIO_F_BIO_ACCEPT_NEW, 0), "BIO_ACCEPT_new"}, - {ERR_PACK(ERR_LIB_BIO, BIO_F_BIO_ADDR_NEW, 0), "BIO_ADDR_new"}, - {ERR_PACK(ERR_LIB_BIO, BIO_F_BIO_BIND, 0), "BIO_bind"}, - {ERR_PACK(ERR_LIB_BIO, BIO_F_BIO_CALLBACK_CTRL, 0), "BIO_callback_ctrl"}, - {ERR_PACK(ERR_LIB_BIO, BIO_F_BIO_CONNECT, 0), "BIO_connect"}, - {ERR_PACK(ERR_LIB_BIO, BIO_F_BIO_CONNECT_NEW, 0), "BIO_CONNECT_new"}, - {ERR_PACK(ERR_LIB_BIO, BIO_F_BIO_CTRL, 0), "BIO_ctrl"}, - {ERR_PACK(ERR_LIB_BIO, BIO_F_BIO_GETS, 0), "BIO_gets"}, - {ERR_PACK(ERR_LIB_BIO, BIO_F_BIO_GET_HOST_IP, 0), "BIO_get_host_ip"}, - {ERR_PACK(ERR_LIB_BIO, BIO_F_BIO_GET_NEW_INDEX, 0), "BIO_get_new_index"}, - {ERR_PACK(ERR_LIB_BIO, BIO_F_BIO_GET_PORT, 0), "BIO_get_port"}, - {ERR_PACK(ERR_LIB_BIO, BIO_F_BIO_LISTEN, 0), "BIO_listen"}, - {ERR_PACK(ERR_LIB_BIO, BIO_F_BIO_LOOKUP, 0), "BIO_lookup"}, - {ERR_PACK(ERR_LIB_BIO, BIO_F_BIO_LOOKUP_EX, 0), "BIO_lookup_ex"}, - {ERR_PACK(ERR_LIB_BIO, BIO_F_BIO_MAKE_PAIR, 0), "bio_make_pair"}, - {ERR_PACK(ERR_LIB_BIO, BIO_F_BIO_METH_NEW, 0), "BIO_meth_new"}, - {ERR_PACK(ERR_LIB_BIO, BIO_F_BIO_NEW, 0), "BIO_new"}, - {ERR_PACK(ERR_LIB_BIO, BIO_F_BIO_NEW_DGRAM_SCTP, 0), "BIO_new_dgram_sctp"}, - {ERR_PACK(ERR_LIB_BIO, BIO_F_BIO_NEW_FILE, 0), "BIO_new_file"}, - {ERR_PACK(ERR_LIB_BIO, BIO_F_BIO_NEW_MEM_BUF, 0), "BIO_new_mem_buf"}, - {ERR_PACK(ERR_LIB_BIO, BIO_F_BIO_NREAD, 0), "BIO_nread"}, - {ERR_PACK(ERR_LIB_BIO, BIO_F_BIO_NREAD0, 0), "BIO_nread0"}, - {ERR_PACK(ERR_LIB_BIO, BIO_F_BIO_NWRITE, 0), "BIO_nwrite"}, - {ERR_PACK(ERR_LIB_BIO, BIO_F_BIO_NWRITE0, 0), "BIO_nwrite0"}, - {ERR_PACK(ERR_LIB_BIO, BIO_F_BIO_PARSE_HOSTSERV, 0), "BIO_parse_hostserv"}, - {ERR_PACK(ERR_LIB_BIO, BIO_F_BIO_PUTS, 0), "BIO_puts"}, - {ERR_PACK(ERR_LIB_BIO, BIO_F_BIO_READ, 0), "BIO_read"}, - {ERR_PACK(ERR_LIB_BIO, BIO_F_BIO_READ_EX, 0), "BIO_read_ex"}, - {ERR_PACK(ERR_LIB_BIO, BIO_F_BIO_READ_INTERN, 0), "bio_read_intern"}, - {ERR_PACK(ERR_LIB_BIO, BIO_F_BIO_SOCKET, 0), "BIO_socket"}, - {ERR_PACK(ERR_LIB_BIO, BIO_F_BIO_SOCKET_NBIO, 0), "BIO_socket_nbio"}, - {ERR_PACK(ERR_LIB_BIO, BIO_F_BIO_SOCK_INFO, 0), "BIO_sock_info"}, - {ERR_PACK(ERR_LIB_BIO, BIO_F_BIO_SOCK_INIT, 0), "BIO_sock_init"}, - {ERR_PACK(ERR_LIB_BIO, BIO_F_BIO_WRITE, 0), "BIO_write"}, - {ERR_PACK(ERR_LIB_BIO, BIO_F_BIO_WRITE_EX, 0), "BIO_write_ex"}, - {ERR_PACK(ERR_LIB_BIO, BIO_F_BIO_WRITE_INTERN, 0), "bio_write_intern"}, - {ERR_PACK(ERR_LIB_BIO, BIO_F_BUFFER_CTRL, 0), "buffer_ctrl"}, - {ERR_PACK(ERR_LIB_BIO, BIO_F_CONN_CTRL, 0), "conn_ctrl"}, - {ERR_PACK(ERR_LIB_BIO, BIO_F_CONN_STATE, 0), "conn_state"}, - {ERR_PACK(ERR_LIB_BIO, BIO_F_DGRAM_SCTP_NEW, 0), "dgram_sctp_new"}, - {ERR_PACK(ERR_LIB_BIO, BIO_F_DGRAM_SCTP_READ, 0), "dgram_sctp_read"}, - {ERR_PACK(ERR_LIB_BIO, BIO_F_DGRAM_SCTP_WRITE, 0), "dgram_sctp_write"}, - {ERR_PACK(ERR_LIB_BIO, BIO_F_DOAPR_OUTCH, 0), "doapr_outch"}, - {ERR_PACK(ERR_LIB_BIO, BIO_F_FILE_CTRL, 0), "file_ctrl"}, - {ERR_PACK(ERR_LIB_BIO, BIO_F_FILE_READ, 0), "file_read"}, - {ERR_PACK(ERR_LIB_BIO, BIO_F_LINEBUFFER_CTRL, 0), "linebuffer_ctrl"}, - {ERR_PACK(ERR_LIB_BIO, BIO_F_LINEBUFFER_NEW, 0), "linebuffer_new"}, - {ERR_PACK(ERR_LIB_BIO, BIO_F_MEM_WRITE, 0), "mem_write"}, - {ERR_PACK(ERR_LIB_BIO, BIO_F_NBIOF_NEW, 0), "nbiof_new"}, - {ERR_PACK(ERR_LIB_BIO, BIO_F_SLG_WRITE, 0), "slg_write"}, - {ERR_PACK(ERR_LIB_BIO, BIO_F_SSL_NEW, 0), "SSL_new"}, - {0, NULL} -}; - static const ERR_STRING_DATA BIO_str_reasons[] = { {ERR_PACK(ERR_LIB_BIO, 0, BIO_R_ACCEPT_ERROR), "accept error"}, {ERR_PACK(ERR_LIB_BIO, 0, BIO_R_ADDRINFO_ADDR_IS_NOT_AF_INET), @@ -82,6 +23,7 @@ static const ERR_STRING_DATA BIO_str_reasons[] = { {ERR_PACK(ERR_LIB_BIO, 0, BIO_R_BAD_FOPEN_MODE), "bad fopen mode"}, {ERR_PACK(ERR_LIB_BIO, 0, BIO_R_BROKEN_PIPE), "broken pipe"}, {ERR_PACK(ERR_LIB_BIO, 0, BIO_R_CONNECT_ERROR), "connect error"}, + {ERR_PACK(ERR_LIB_BIO, 0, BIO_R_CONNECT_TIMEOUT), "connect timeout"}, {ERR_PACK(ERR_LIB_BIO, 0, BIO_R_GETHOSTBYNAME_ADDR_IS_NOT_AF_INET), "gethostbyname addr is not af inet"}, {ERR_PACK(ERR_LIB_BIO, 0, BIO_R_GETSOCKNAME_ERROR), "getsockname error"}, @@ -104,7 +46,8 @@ static const ERR_STRING_DATA BIO_str_reasons[] = { "no hostname or service specified"}, {ERR_PACK(ERR_LIB_BIO, 0, BIO_R_NO_PORT_DEFINED), "no port defined"}, {ERR_PACK(ERR_LIB_BIO, 0, BIO_R_NO_SUCH_FILE), "no such file"}, - {ERR_PACK(ERR_LIB_BIO, 0, BIO_R_NULL_PARAMETER), "null parameter"}, + {ERR_PACK(ERR_LIB_BIO, 0, BIO_R_TRANSFER_ERROR), "transfer error"}, + {ERR_PACK(ERR_LIB_BIO, 0, BIO_R_TRANSFER_TIMEOUT), "transfer timeout"}, {ERR_PACK(ERR_LIB_BIO, 0, BIO_R_UNABLE_TO_BIND_SOCKET), "unable to bind socket"}, {ERR_PACK(ERR_LIB_BIO, 0, BIO_R_UNABLE_TO_CREATE_SOCKET), @@ -133,13 +76,11 @@ static const ERR_STRING_DATA BIO_str_reasons[] = { #endif -int ERR_load_BIO_strings(void) +int ossl_err_load_BIO_strings(void) { #ifndef OPENSSL_NO_ERR - if (ERR_func_error_string(BIO_str_functs[0].error) == NULL) { - ERR_load_strings_const(BIO_str_functs); + if (ERR_reason_error_string(BIO_str_reasons[0].error) == NULL) ERR_load_strings_const(BIO_str_reasons); - } #endif return 1; } diff --git a/crypto/bio/bio_lib.c b/crypto/bio/bio_lib.c index d2202e537b30..245a75afa1b8 100644 --- a/crypto/bio/bio_lib.c +++ b/crypto/bio/bio_lib.c @@ -1,26 +1,32 @@ /* - * Copyright 1995-2018 The OpenSSL Project Authors. All Rights Reserved. + * Copyright 1995-2024 The OpenSSL Project Authors. All Rights Reserved. * - * Licensed under the OpenSSL license (the "License"). You may not use + * 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 * in the file LICENSE in the source distribution or at * https://www.openssl.org/source/license.html */ +#define OPENSSL_SUPPRESS_DEPRECATED + #include <stdio.h> #include <errno.h> #include <openssl/crypto.h> +#include "internal/numbers.h" #include "bio_local.h" -#include "internal/cryptlib.h" - /* * Helper macro for the callback to determine whether an operator expects a * len parameter or not */ -#define HAS_LEN_OPER(o) ((o) == BIO_CB_READ || (o) == BIO_CB_WRITE || \ - (o) == BIO_CB_GETS) +#define HAS_LEN_OPER(o) ((o) == BIO_CB_READ || (o) == BIO_CB_WRITE \ + || (o) == BIO_CB_GETS) +#ifndef OPENSSL_NO_DEPRECATED_3_0 +# define HAS_CALLBACK(b) ((b)->callback != NULL || (b)->callback_ex != NULL) +#else +# define HAS_CALLBACK(b) ((b)->callback_ex != NULL) +#endif /* * Helper function to work out whether to call the new style callback or the old * one, and translate between the two. @@ -29,14 +35,18 @@ * for the "long" used for "inret" */ static long bio_call_callback(BIO *b, int oper, const char *argp, size_t len, - int argi, long argl, long inret, size_t *processed) + int argi, long argl, long inret, + size_t *processed) { - long ret; + long ret = inret; +#ifndef OPENSSL_NO_DEPRECATED_3_0 int bareoper; if (b->callback_ex != NULL) +#endif return b->callback_ex(b, oper, argp, len, argi, argl, inret, processed); +#ifndef OPENSSL_NO_DEPRECATED_3_0 /* Strip off any BIO_CB_RETURN flag */ bareoper = oper & ~BIO_CB_RETURN; @@ -64,19 +74,20 @@ static long bio_call_callback(BIO *b, int oper, const char *argp, size_t len, *processed = (size_t)ret; ret = 1; } - +#endif return ret; } -BIO *BIO_new(const BIO_METHOD *method) +BIO *BIO_new_ex(OSSL_LIB_CTX *libctx, const BIO_METHOD *method) { BIO *bio = OPENSSL_zalloc(sizeof(*bio)); if (bio == NULL) { - BIOerr(BIO_F_BIO_NEW, ERR_R_MALLOC_FAILURE); + ERR_raise(ERR_LIB_BIO, ERR_R_MALLOC_FAILURE); return NULL; } + bio->libctx = libctx; bio->method = method; bio->shutdown = 1; bio->references = 1; @@ -86,13 +97,13 @@ BIO *BIO_new(const BIO_METHOD *method) bio->lock = CRYPTO_THREAD_lock_new(); if (bio->lock == NULL) { - BIOerr(BIO_F_BIO_NEW, ERR_R_MALLOC_FAILURE); + ERR_raise(ERR_LIB_BIO, ERR_R_MALLOC_FAILURE); CRYPTO_free_ex_data(CRYPTO_EX_INDEX_BIO, bio, &bio->ex_data); goto err; } if (method->create != NULL && !method->create(bio)) { - BIOerr(BIO_F_BIO_NEW, ERR_R_INIT_FAIL); + ERR_raise(ERR_LIB_BIO, ERR_R_INIT_FAIL); CRYPTO_free_ex_data(CRYPTO_EX_INDEX_BIO, bio, &bio->ex_data); CRYPTO_THREAD_lock_free(bio->lock); goto err; @@ -107,6 +118,11 @@ err: return NULL; } +BIO *BIO_new(const BIO_METHOD *method) +{ + return BIO_new_ex(NULL, method); +} + int BIO_free(BIO *a) { int ret; @@ -122,10 +138,10 @@ int BIO_free(BIO *a) return 1; REF_ASSERT_ISNT(ret < 0); - if (a->callback != NULL || a->callback_ex != NULL) { + if (HAS_CALLBACK(a)) { ret = (int)bio_call_callback(a, BIO_CB_FREE, NULL, 0, 0, 0L, 1L, NULL); if (ret <= 0) - return ret; + return 0; } if ((a->method != NULL) && (a->method->destroy != NULL)) @@ -184,7 +200,7 @@ int BIO_up_ref(BIO *a) REF_PRINT_COUNT("BIO", a); REF_ASSERT_ISNT(i < 2); - return ((i > 1) ? 1 : 0); + return i > 1; } void BIO_clear_flags(BIO *b, int flags) @@ -202,6 +218,7 @@ void BIO_set_flags(BIO *b, int flags) b->flags |= flags; } +#ifndef OPENSSL_NO_DEPRECATED_3_0 BIO_callback_fn BIO_get_callback(const BIO *b) { return b->callback; @@ -211,6 +228,7 @@ void BIO_set_callback(BIO *b, BIO_callback_fn cb) { b->callback = cb; } +#endif BIO_callback_fn_ex BIO_get_callback_ex(const BIO *b) { @@ -252,19 +270,23 @@ static int bio_read_intern(BIO *b, void *data, size_t dlen, size_t *readbytes) { int ret; - if ((b == NULL) || (b->method == NULL) || (b->method->bread == NULL)) { - BIOerr(BIO_F_BIO_READ_INTERN, BIO_R_UNSUPPORTED_METHOD); + if (b == NULL) { + ERR_raise(ERR_LIB_BIO, ERR_R_PASSED_NULL_PARAMETER); + return -1; + } + if (b->method == NULL || b->method->bread == NULL) { + ERR_raise(ERR_LIB_BIO, BIO_R_UNSUPPORTED_METHOD); return -2; } - if ((b->callback != NULL || b->callback_ex != NULL) && + if (HAS_CALLBACK(b) && ((ret = (int)bio_call_callback(b, BIO_CB_READ, data, dlen, 0, 0L, 1L, NULL)) <= 0)) return ret; if (!b->init) { - BIOerr(BIO_F_BIO_READ_INTERN, BIO_R_UNINITIALIZED); - return -2; + ERR_raise(ERR_LIB_BIO, BIO_R_UNINITIALIZED); + return -1; } ret = b->method->bread(b, data, dlen, readbytes); @@ -272,13 +294,13 @@ static int bio_read_intern(BIO *b, void *data, size_t dlen, size_t *readbytes) if (ret > 0) b->num_read += (uint64_t)*readbytes; - if (b->callback != NULL || b->callback_ex != NULL) + if (HAS_CALLBACK(b)) ret = (int)bio_call_callback(b, BIO_CB_READ | BIO_CB_RETURN, data, dlen, 0, 0L, ret, readbytes); /* Shouldn't happen */ if (ret > 0 && *readbytes > dlen) { - BIOerr(BIO_F_BIO_READ_INTERN, ERR_R_INTERNAL_ERROR); + ERR_raise(ERR_LIB_BIO, ERR_R_INTERNAL_ERROR); return -1; } @@ -305,50 +327,50 @@ int BIO_read(BIO *b, void *data, int dlen) int BIO_read_ex(BIO *b, void *data, size_t dlen, size_t *readbytes) { - int ret; - - ret = bio_read_intern(b, data, dlen, readbytes); - - if (ret > 0) - ret = 1; - else - ret = 0; - - return ret; + return bio_read_intern(b, data, dlen, readbytes) > 0; } static int bio_write_intern(BIO *b, const void *data, size_t dlen, size_t *written) { + size_t local_written; int ret; + if (written != NULL) + *written = 0; + /* + * b == NULL is not an error but just means that zero bytes are written. + * Do not raise an error here. + */ if (b == NULL) return 0; - if ((b->method == NULL) || (b->method->bwrite == NULL)) { - BIOerr(BIO_F_BIO_WRITE_INTERN, BIO_R_UNSUPPORTED_METHOD); + if (b->method == NULL || b->method->bwrite == NULL) { + ERR_raise(ERR_LIB_BIO, BIO_R_UNSUPPORTED_METHOD); return -2; } - if ((b->callback != NULL || b->callback_ex != NULL) && + if (HAS_CALLBACK(b) && ((ret = (int)bio_call_callback(b, BIO_CB_WRITE, data, dlen, 0, 0L, 1L, NULL)) <= 0)) return ret; if (!b->init) { - BIOerr(BIO_F_BIO_WRITE_INTERN, BIO_R_UNINITIALIZED); - return -2; + ERR_raise(ERR_LIB_BIO, BIO_R_UNINITIALIZED); + return -1; } - ret = b->method->bwrite(b, data, dlen, written); + ret = b->method->bwrite(b, data, dlen, &local_written); if (ret > 0) - b->num_write += (uint64_t)*written; + b->num_write += (uint64_t)local_written; - if (b->callback != NULL || b->callback_ex != NULL) + if (HAS_CALLBACK(b)) ret = (int)bio_call_callback(b, BIO_CB_WRITE | BIO_CB_RETURN, data, - dlen, 0, 0L, ret, written); + dlen, 0, 0L, ret, &local_written); + if (written != NULL) + *written = local_written; return ret; } @@ -357,13 +379,13 @@ int BIO_write(BIO *b, const void *data, int dlen) size_t written; int ret; - if (dlen < 0) + if (dlen <= 0) return 0; ret = bio_write_intern(b, data, (size_t)dlen, &written); if (ret > 0) { - /* *written should always be <= dlen */ + /* written should always be <= dlen */ ret = (int)written; } @@ -372,16 +394,8 @@ int BIO_write(BIO *b, const void *data, int dlen) int BIO_write_ex(BIO *b, const void *data, size_t dlen, size_t *written) { - int ret; - - ret = bio_write_intern(b, data, dlen, written); - - if (ret > 0) - ret = 1; - else - ret = 0; - - return ret; + return bio_write_intern(b, data, dlen, written) > 0 + || (b != NULL && dlen == 0); /* order is important for *written */ } int BIO_puts(BIO *b, const char *buf) @@ -389,20 +403,24 @@ int BIO_puts(BIO *b, const char *buf) int ret; size_t written = 0; - if ((b == NULL) || (b->method == NULL) || (b->method->bputs == NULL)) { - BIOerr(BIO_F_BIO_PUTS, BIO_R_UNSUPPORTED_METHOD); + if (b == NULL) { + ERR_raise(ERR_LIB_BIO, ERR_R_PASSED_NULL_PARAMETER); + return -1; + } + if (b->method == NULL || b->method->bputs == NULL) { + ERR_raise(ERR_LIB_BIO, BIO_R_UNSUPPORTED_METHOD); return -2; } - if (b->callback != NULL || b->callback_ex != NULL) { + if (HAS_CALLBACK(b)) { ret = (int)bio_call_callback(b, BIO_CB_PUTS, buf, 0, 0, 0L, 1L, NULL); if (ret <= 0) return ret; } if (!b->init) { - BIOerr(BIO_F_BIO_PUTS, BIO_R_UNINITIALIZED); - return -2; + ERR_raise(ERR_LIB_BIO, BIO_R_UNINITIALIZED); + return -1; } ret = b->method->bputs(b, buf); @@ -413,13 +431,13 @@ int BIO_puts(BIO *b, const char *buf) ret = 1; } - if (b->callback != NULL || b->callback_ex != NULL) + if (HAS_CALLBACK(b)) ret = (int)bio_call_callback(b, BIO_CB_PUTS | BIO_CB_RETURN, buf, 0, 0, 0L, ret, &written); if (ret > 0) { if (written > INT_MAX) { - BIOerr(BIO_F_BIO_PUTS, BIO_R_LENGTH_TOO_LONG); + ERR_raise(ERR_LIB_BIO, BIO_R_LENGTH_TOO_LONG); ret = -1; } else { ret = (int)written; @@ -434,25 +452,29 @@ int BIO_gets(BIO *b, char *buf, int size) int ret; size_t readbytes = 0; - if ((b == NULL) || (b->method == NULL) || (b->method->bgets == NULL)) { - BIOerr(BIO_F_BIO_GETS, BIO_R_UNSUPPORTED_METHOD); + if (b == NULL) { + ERR_raise(ERR_LIB_BIO, ERR_R_PASSED_NULL_PARAMETER); + return -1; + } + if (b->method == NULL || b->method->bgets == NULL) { + ERR_raise(ERR_LIB_BIO, BIO_R_UNSUPPORTED_METHOD); return -2; } if (size < 0) { - BIOerr(BIO_F_BIO_GETS, BIO_R_INVALID_ARGUMENT); - return 0; + ERR_raise(ERR_LIB_BIO, BIO_R_INVALID_ARGUMENT); + return -1; } - if (b->callback != NULL || b->callback_ex != NULL) { + if (HAS_CALLBACK(b)) { ret = (int)bio_call_callback(b, BIO_CB_GETS, buf, size, 0, 0L, 1, NULL); if (ret <= 0) return ret; } if (!b->init) { - BIOerr(BIO_F_BIO_GETS, BIO_R_UNINITIALIZED); - return -2; + ERR_raise(ERR_LIB_BIO, BIO_R_UNINITIALIZED); + return -1; } ret = b->method->bgets(b, buf, size); @@ -462,7 +484,7 @@ int BIO_gets(BIO *b, char *buf, int size) ret = 1; } - if (b->callback != NULL || b->callback_ex != NULL) + if (HAS_CALLBACK(b)) ret = (int)bio_call_callback(b, BIO_CB_GETS | BIO_CB_RETURN, buf, size, 0, 0L, ret, &readbytes); @@ -477,6 +499,37 @@ int BIO_gets(BIO *b, char *buf, int size) return ret; } +int BIO_get_line(BIO *bio, char *buf, int size) +{ + int ret = 0; + char *ptr = buf; + + if (buf == NULL) { + ERR_raise(ERR_LIB_BIO, ERR_R_PASSED_NULL_PARAMETER); + return -1; + } + if (size <= 0) { + ERR_raise(ERR_LIB_BIO, BIO_R_INVALID_ARGUMENT); + return -1; + } + *buf = '\0'; + + if (bio == NULL) { + ERR_raise(ERR_LIB_BIO, ERR_R_PASSED_NULL_PARAMETER); + return -1; + } + if (!bio->init) { + ERR_raise(ERR_LIB_BIO, BIO_R_UNINITIALIZED); + return -1; + } + + while (size-- > 1 && (ret = BIO_read(bio, ptr, 1)) > 0) + if (*ptr++ == '\n') + break; + *ptr = '\0'; + return ret > 0 || BIO_eof(bio) ? ptr - buf : ret; +} + int BIO_indent(BIO *b, int indent, int max) { if (indent < 0) @@ -512,14 +565,13 @@ long BIO_ctrl(BIO *b, int cmd, long larg, void *parg) long ret; if (b == NULL) - return 0; - - if ((b->method == NULL) || (b->method->ctrl == NULL)) { - BIOerr(BIO_F_BIO_CTRL, BIO_R_UNSUPPORTED_METHOD); + return -1; + if (b->method == NULL || b->method->ctrl == NULL) { + ERR_raise(ERR_LIB_BIO, BIO_R_UNSUPPORTED_METHOD); return -2; } - if (b->callback != NULL || b->callback_ex != NULL) { + if (HAS_CALLBACK(b)) { ret = bio_call_callback(b, BIO_CB_CTRL, parg, 0, cmd, larg, 1L, NULL); if (ret <= 0) return ret; @@ -527,7 +579,7 @@ long BIO_ctrl(BIO *b, int cmd, long larg, void *parg) ret = b->method->ctrl(b, cmd, larg, parg); - if (b->callback != NULL || b->callback_ex != NULL) + if (HAS_CALLBACK(b)) ret = bio_call_callback(b, BIO_CB_CTRL | BIO_CB_RETURN, parg, 0, cmd, larg, ret, NULL); @@ -539,15 +591,14 @@ long BIO_callback_ctrl(BIO *b, int cmd, BIO_info_cb *fp) long ret; if (b == NULL) - return 0; - - if ((b->method == NULL) || (b->method->callback_ctrl == NULL) - || (cmd != BIO_CTRL_SET_CALLBACK)) { - BIOerr(BIO_F_BIO_CALLBACK_CTRL, BIO_R_UNSUPPORTED_METHOD); + return -2; + if (b->method == NULL || b->method->callback_ctrl == NULL + || cmd != BIO_CTRL_SET_CALLBACK) { + ERR_raise(ERR_LIB_BIO, BIO_R_UNSUPPORTED_METHOD); return -2; } - if (b->callback != NULL || b->callback_ex != NULL) { + if (HAS_CALLBACK(b)) { ret = bio_call_callback(b, BIO_CB_CTRL, (void *)&fp, 0, cmd, 0, 1L, NULL); if (ret <= 0) @@ -556,7 +607,7 @@ long BIO_callback_ctrl(BIO *b, int cmd, BIO_info_cb *fp) ret = b->method->callback_ctrl(b, cmd, fp); - if (b->callback != NULL || b->callback_ex != NULL) + if (HAS_CALLBACK(b)) ret = bio_call_callback(b, BIO_CB_CTRL | BIO_CB_RETURN, (void *)&fp, 0, cmd, 0, ret, NULL); @@ -570,12 +621,28 @@ long BIO_callback_ctrl(BIO *b, int cmd, BIO_info_cb *fp) */ size_t BIO_ctrl_pending(BIO *bio) { - return BIO_ctrl(bio, BIO_CTRL_PENDING, 0, NULL); + long ret = BIO_ctrl(bio, BIO_CTRL_PENDING, 0, NULL); + + if (ret < 0) + ret = 0; +#if LONG_MAX > SIZE_MAX + if (ret > SIZE_MAX) + ret = SIZE_MAX; +#endif + return (size_t)ret; } size_t BIO_ctrl_wpending(BIO *bio) { - return BIO_ctrl(bio, BIO_CTRL_WPENDING, 0, NULL); + long ret = BIO_ctrl(bio, BIO_CTRL_WPENDING, 0, NULL); + + if (ret < 0) + ret = 0; +#if LONG_MAX > SIZE_MAX + if (ret > SIZE_MAX) + ret = SIZE_MAX; +#endif + return (size_t)ret; } /* put the 'bio' on the end of b's list of operators */ @@ -649,8 +716,10 @@ BIO *BIO_find_type(BIO *bio, int type) { int mt, mask; - if (bio == NULL) + if (bio == NULL) { + ERR_raise(ERR_LIB_BIO, ERR_R_PASSED_NULL_PARAMETER); return NULL; + } mask = type & 0xff; do { if (bio->method != NULL) { @@ -659,8 +728,9 @@ BIO *BIO_find_type(BIO *bio, int type) if (!mask) { if (mt & type) return bio; - } else if (mt == type) + } else if (mt == type) { return bio; + } } bio = bio->next_bio; } while (bio != NULL); @@ -702,7 +772,9 @@ BIO *BIO_dup_chain(BIO *in) for (bio = in; bio != NULL; bio = bio->next_bio) { if ((new_bio = BIO_new(bio->method)) == NULL) goto err; +#ifndef OPENSSL_NO_DEPRECATED_3_0 new_bio->callback = bio->callback; +#endif new_bio->callback_ex = bio->callback_ex; new_bio->cb_arg = bio->cb_arg; new_bio->init = bio->init; @@ -712,7 +784,7 @@ BIO *BIO_dup_chain(BIO *in) /* This will let SSL_s_sock() work with stdin/stdout */ new_bio->num = bio->num; - if (!BIO_dup_state(bio, (char *)new_bio)) { + if (BIO_dup_state(bio, (char *)new_bio) <= 0) { BIO_free(new_bio); goto err; } @@ -750,7 +822,7 @@ int BIO_set_ex_data(BIO *bio, int idx, void *data) return CRYPTO_set_ex_data(&(bio->ex_data), idx, data); } -void *BIO_get_ex_data(BIO *bio, int idx) +void *BIO_get_ex_data(const BIO *bio, int idx) { return CRYPTO_get_ex_data(&(bio->ex_data), idx); } @@ -784,3 +856,131 @@ void bio_cleanup(void) CRYPTO_THREAD_lock_free(bio_type_lock); bio_type_lock = NULL; } + +/* Internal variant of the below BIO_wait() not calling BIOerr() */ +static int bio_wait(BIO *bio, time_t max_time, unsigned int nap_milliseconds) +{ +#ifndef OPENSSL_NO_SOCK + int fd; +#endif + long sec_diff; + + if (max_time == 0) /* no timeout */ + return 1; + +#ifndef OPENSSL_NO_SOCK + if (BIO_get_fd(bio, &fd) > 0) { + int ret = BIO_socket_wait(fd, BIO_should_read(bio), max_time); + + if (ret != -1) + return ret; + } +#endif + /* fall back to polling since no sockets are available */ + + sec_diff = (long)(max_time - time(NULL)); /* might overflow */ + if (sec_diff < 0) + return 0; /* clearly timeout */ + + /* now take a nap at most the given number of milliseconds */ + if (sec_diff == 0) { /* we are below the 1 seconds resolution of max_time */ + if (nap_milliseconds > 1000) + nap_milliseconds = 1000; + } else { /* for sec_diff > 0, take min(sec_diff * 1000, nap_milliseconds) */ + if ((unsigned long)sec_diff * 1000 < nap_milliseconds) + nap_milliseconds = (unsigned int)sec_diff * 1000; + } + ossl_sleep(nap_milliseconds); + return 1; +} + +/*- + * Wait on (typically socket-based) BIO at most until max_time. + * Succeed immediately if max_time == 0. + * If sockets are not available support polling: succeed after waiting at most + * the number of nap_milliseconds in order to avoid a tight busy loop. + * Call BIOerr(...) on timeout or error. + * Returns -1 on error, 0 on timeout, and 1 on success. + */ +int BIO_wait(BIO *bio, time_t max_time, unsigned int nap_milliseconds) +{ + int rv = bio_wait(bio, max_time, nap_milliseconds); + + if (rv <= 0) + ERR_raise(ERR_LIB_BIO, + rv == 0 ? BIO_R_TRANSFER_TIMEOUT : BIO_R_TRANSFER_ERROR); + return rv; +} + +/* + * Connect via given BIO using BIO_do_connect() until success/timeout/error. + * Parameter timeout == 0 means no timeout, < 0 means exactly one try. + * For non-blocking and potentially even non-socket BIOs perform polling with + * the given density: between polls sleep nap_milliseconds using BIO_wait() + * in order to avoid a tight busy loop. + * Returns -1 on error, 0 on timeout, and 1 on success. + */ +int BIO_do_connect_retry(BIO *bio, int timeout, int nap_milliseconds) +{ + int blocking = timeout <= 0; + time_t max_time = timeout > 0 ? time(NULL) + timeout : 0; + int rv; + + if (bio == NULL) { + ERR_raise(ERR_LIB_BIO, ERR_R_PASSED_NULL_PARAMETER); + return -1; + } + + if (nap_milliseconds < 0) + nap_milliseconds = 100; + BIO_set_nbio(bio, !blocking); + + retry: + ERR_set_mark(); + rv = BIO_do_connect(bio); + + if (rv <= 0) { /* could be timeout or retryable error or fatal error */ + int err = ERR_peek_last_error(); + int reason = ERR_GET_REASON(err); + int do_retry = BIO_should_retry(bio); /* may be 1 only if !blocking */ + + if (ERR_GET_LIB(err) == ERR_LIB_BIO) { + switch (reason) { + case ERR_R_SYS_LIB: + /* + * likely retryable system error occurred, which may be + * EAGAIN (resource temporarily unavailable) some 40 secs after + * calling getaddrinfo(): Temporary failure in name resolution + * or a premature ETIMEDOUT, some 30 seconds after connect() + */ + case BIO_R_CONNECT_ERROR: + case BIO_R_NBIO_CONNECT_ERROR: + /* some likely retryable connection error occurred */ + (void)BIO_reset(bio); /* often needed to avoid retry failure */ + do_retry = 1; + break; + default: + break; + } + } + if (timeout >= 0 && do_retry) { + ERR_pop_to_mark(); + /* will not actually wait if timeout == 0 (i.e., blocking BIO): */ + rv = bio_wait(bio, max_time, nap_milliseconds); + if (rv > 0) + goto retry; + ERR_raise(ERR_LIB_BIO, + rv == 0 ? BIO_R_CONNECT_TIMEOUT : BIO_R_CONNECT_ERROR); + } else { + ERR_clear_last_mark(); + rv = -1; + if (err == 0) /* missing error queue entry */ + /* workaround: general error */ + ERR_raise(ERR_LIB_BIO, BIO_R_CONNECT_ERROR); + } + } else { + ERR_clear_last_mark(); + } + + return rv; +} diff --git a/crypto/bio/bio_local.h b/crypto/bio/bio_local.h index 8b2122129396..749e8f810c30 100644 --- a/crypto/bio/bio_local.h +++ b/crypto/bio/bio_local.h @@ -1,7 +1,7 @@ /* - * Copyright 2005-2016 The OpenSSL Project Authors. All Rights Reserved. + * Copyright 2005-2021 The OpenSSL Project Authors. All Rights Reserved. * - * Licensed under the OpenSSL license (the "License"). You may not use + * 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 * in the file LICENSE in the source distribution or at * https://www.openssl.org/source/license.html @@ -9,7 +9,6 @@ #include "e_os.h" #include "internal/sockets.h" -#include "internal/refcount.h" /* BEGIN BIO_ADDRINFO/BIO_ADDR stuff. */ @@ -30,7 +29,7 @@ # ifdef OSSL_INTERNAL_CRYPTLIB_H # error internal/cryptlib.h included before bio_local.h # endif -# ifdef HEADER_BIO_H +# ifdef OPENSSL_BIO_H # error openssl/bio.h included before bio_local.h # endif @@ -88,6 +87,7 @@ union bio_addr_st { #include "internal/cryptlib.h" #include "internal/bio.h" +#include "internal/refcount.h" typedef struct bio_f_buffer_ctx_struct { /*- @@ -113,9 +113,12 @@ typedef struct bio_f_buffer_ctx_struct { } BIO_F_BUFFER_CTX; struct bio_st { + OSSL_LIB_CTX *libctx; const BIO_METHOD *method; /* bio, mode, argp, argi, argl, ret */ +#ifndef OPENSSL_NO_DEPRECATED_3_0 BIO_callback_fn callback; +#endif BIO_callback_fn_ex callback_ex; char *cb_arg; /* first argument for the callback */ int init; @@ -152,7 +155,7 @@ extern CRYPTO_RWLOCK *bio_type_lock; void bio_sock_cleanup_int(void); -#if BIO_FLAGS_UPLINK==0 +#if BIO_FLAGS_UPLINK_INTERNAL==0 /* Shortcut UPLINK calls on most platforms... */ # define UP_stdin stdin # define UP_stdout stdout diff --git a/crypto/bio/bio_meth.c b/crypto/bio/bio_meth.c index da116461922e..469715ba09eb 100644 --- a/crypto/bio/bio_meth.c +++ b/crypto/bio/bio_meth.c @@ -1,7 +1,7 @@ /* - * Copyright 2016-2018 The OpenSSL Project Authors. All Rights Reserved. + * Copyright 2016-2020 The OpenSSL Project Authors. All Rights Reserved. * - * Licensed under the OpenSSL license (the "License"). You may not use + * 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 * in the file LICENSE in the source distribution or at * https://www.openssl.org/source/license.html @@ -25,7 +25,7 @@ int BIO_get_new_index(void) int newval; if (!RUN_ONCE(&bio_type_init, do_bio_type_init)) { - BIOerr(BIO_F_BIO_GET_NEW_INDEX, ERR_R_MALLOC_FAILURE); + ERR_raise(ERR_LIB_BIO, ERR_R_MALLOC_FAILURE); return -1; } if (!CRYPTO_UP_REF(&bio_count, &newval, bio_type_lock)) @@ -40,7 +40,7 @@ BIO_METHOD *BIO_meth_new(int type, const char *name) if (biom == NULL || (biom->name = OPENSSL_strdup(name)) == NULL) { OPENSSL_free(biom); - BIOerr(BIO_F_BIO_METH_NEW, ERR_R_MALLOC_FAILURE); + ERR_raise(ERR_LIB_BIO, ERR_R_MALLOC_FAILURE); return NULL; } biom->type = type; diff --git a/crypto/bio/b_print.c b/crypto/bio/bio_print.c index 45d4e9f004b1..1934a6884251 100644 --- a/crypto/bio/b_print.c +++ b/crypto/bio/bio_print.c @@ -1,7 +1,7 @@ /* - * Copyright 1995-2023 The OpenSSL Project Authors. All Rights Reserved. + * Copyright 1995-2025 The OpenSSL Project Authors. All Rights Reserved. * - * Licensed under the OpenSSL license (the "License"). You may not use + * 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 * in the file LICENSE in the source distribution or at * https://www.openssl.org/source/license.html @@ -13,7 +13,7 @@ #include "crypto/ctype.h" #include "internal/numbers.h" #include <openssl/bio.h> -#include <openssl/opensslconf.h> +#include <openssl/configuration.h> /* * Copyright Patrick Powell 1995 @@ -344,7 +344,7 @@ _dopr(char **sbuffer, break; case 'w': /* not supported yet, treat as next char */ - ch = *format++; + format++; break; default: /* unknown, skip */ @@ -535,6 +535,10 @@ static LDOUBLE abs_val(LDOUBLE value) LDOUBLE result = value; if (value < 0) result = -value; + if (result > 0 && result / 2 == result) /* INF */ + result = 0; + else if (result != result) /* NAN */ + result = 0; return result; } @@ -590,6 +594,9 @@ fmtfp(char **sbuffer, signvalue = '+'; else if (flags & DP_F_SPACE) signvalue = ' '; + ufvalue = abs_val(fvalue); + if (ufvalue == 0 && fvalue != 0) /* INF or NAN? */ + signvalue = '?'; /* * G_FORMAT sometimes prints like E_FORMAT and sometimes like F_FORMAT @@ -597,12 +604,12 @@ fmtfp(char **sbuffer, * that from here on. */ if (style == G_FORMAT) { - if (fvalue == 0.0) { + if (ufvalue == 0.0) { realstyle = F_FORMAT; - } else if (fvalue < 0.0001) { + } else if (ufvalue < 0.0001) { realstyle = E_FORMAT; - } else if ((max == 0 && fvalue >= 10) - || (max > 0 && fvalue >= pow_10(max))) { + } else if ((max == 0 && ufvalue >= 10) + || (max > 0 && ufvalue >= pow_10(max))) { realstyle = E_FORMAT; } else { realstyle = F_FORMAT; @@ -612,9 +619,9 @@ fmtfp(char **sbuffer, } if (style != F_FORMAT) { - tmpvalue = fvalue; + tmpvalue = ufvalue; /* Calculate the exponent */ - if (fvalue != 0.0) { + if (ufvalue != 0.0) { while (tmpvalue < 1) { tmpvalue *= 10; exp--; @@ -638,6 +645,7 @@ fmtfp(char **sbuffer, /* * Should not happen. If we're in F_FORMAT then exp < max? */ + (void)doapr_outch(sbuffer, buffer, currlen, maxlen, '\0'); return 0; } } else { @@ -650,15 +658,16 @@ fmtfp(char **sbuffer, } } if (realstyle == E_FORMAT) - fvalue = tmpvalue; + ufvalue = tmpvalue; } - ufvalue = abs_val(fvalue); + /* * By subtracting 65535 (2^16-1) we cancel the low order 15 bits * of ULONG_MAX to avoid using imprecise floating point values. */ if (ufvalue >= (double)(ULONG_MAX - 65535) + 65536.0) { /* Number too big */ + (void)doapr_outch(sbuffer, buffer, currlen, maxlen, '\0'); return 0; } intpart = (unsigned long)ufvalue; @@ -722,8 +731,10 @@ fmtfp(char **sbuffer, tmpexp = (tmpexp / 10); } while (tmpexp > 0 && eplace < (int)sizeof(econvert)); /* Exponent is huge!! Too big to print */ - if (tmpexp > 0) + if (tmpexp > 0) { + (void)doapr_outch(sbuffer, buffer, currlen, maxlen, '\0'); return 0; + } /* Add a leading 0 for single digit exponents */ if (eplace == 1) econvert[eplace++] = '0'; @@ -844,7 +855,7 @@ doapr_outch(char **sbuffer, *maxlen += BUFFER_INC; if (*buffer == NULL) { if ((*buffer = OPENSSL_malloc(*maxlen)) == NULL) { - BIOerr(BIO_F_DOAPR_OUTCH, ERR_R_MALLOC_FAILURE); + ERR_raise(ERR_LIB_BIO, ERR_R_MALLOC_FAILURE); return 0; } if (*currlen > 0) { @@ -855,9 +866,12 @@ doapr_outch(char **sbuffer, *sbuffer = NULL; } else { char *tmpbuf; + tmpbuf = OPENSSL_realloc(*buffer, *maxlen); - if (tmpbuf == NULL) + if (tmpbuf == NULL) { + ERR_raise(ERR_LIB_BIO, ERR_R_MALLOC_FAILURE); return 0; + } *buffer = tmpbuf; } } @@ -949,6 +963,5 @@ int BIO_vsnprintf(char *buf, size_t n, const char *format, va_list args) * been large enough.) */ return -1; - else - return (retlen <= INT_MAX) ? (int)retlen : -1; + return (retlen <= INT_MAX) ? (int)retlen : -1; } diff --git a/crypto/bio/b_sock.c b/crypto/bio/bio_sock.c index df431e6d523d..84496de6f6bd 100644 --- a/crypto/bio/b_sock.c +++ b/crypto/bio/bio_sock.c @@ -1,7 +1,7 @@ /* - * Copyright 1995-2018 The OpenSSL Project Authors. All Rights Reserved. + * Copyright 1995-2025 The OpenSSL Project Authors. All Rights Reserved. * - * Licensed under the OpenSSL license (the "License"). You may not use + * 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 * in the file LICENSE in the source distribution or at * https://www.openssl.org/source/license.html @@ -9,7 +9,6 @@ #include <stdio.h> #include <stdlib.h> -#include <errno.h> #include "bio_local.h" #ifndef OPENSSL_NO_SOCK # define SOCKET_PROTOCOL IPPROTO_TCP @@ -24,7 +23,26 @@ static int wsa_init_done = 0; # endif -# if OPENSSL_API_COMPAT < 0x10100000L +# if defined __TANDEM +# include <unistd.h> +# include <sys/time.h> /* select */ +# if defined(OPENSSL_TANDEM_FLOSS) +# include <floss.h(floss_select)> +# endif +# elif defined _WIN32 +# include <winsock.h> /* for type fd_set */ +# else +# include <unistd.h> +# if defined __VMS +# include <sys/socket.h> +# elif defined _HPUX_SOURCE +# include <sys/time.h> +# else +# include <sys/select.h> +# endif +# endif + +# ifndef OPENSSL_NO_DEPRECATED_1_1_0 int BIO_get_host_ip(const char *str, unsigned char *ip) { BIO_ADDRINFO *res = NULL; @@ -37,8 +55,7 @@ int BIO_get_host_ip(const char *str, unsigned char *ip) size_t l; if (BIO_ADDRINFO_family(res) != AF_INET) { - BIOerr(BIO_F_BIO_GET_HOST_IP, - BIO_R_GETHOSTBYNAME_ADDR_IS_NOT_AF_INET); + ERR_raise(ERR_LIB_BIO, BIO_R_GETHOSTBYNAME_ADDR_IS_NOT_AF_INET); } else if (BIO_ADDR_rawaddress(BIO_ADDRINFO_address(res), NULL, &l)) { /* * Because only AF_INET addresses will reach this far, we can assert @@ -61,7 +78,7 @@ int BIO_get_port(const char *str, unsigned short *port_ptr) int ret = 0; if (str == NULL) { - BIOerr(BIO_F_BIO_GET_PORT, BIO_R_NO_PORT_DEFINED); + ERR_raise(ERR_LIB_BIO, BIO_R_NO_PORT_DEFINED); return 0; } @@ -70,8 +87,7 @@ int BIO_get_port(const char *str, unsigned short *port_ptr) if (BIO_lookup(NULL, str, BIO_LOOKUP_CLIENT, AF_INET, SOCK_STREAM, &res)) { if (BIO_ADDRINFO_family(res) != AF_INET) { - BIOerr(BIO_F_BIO_GET_PORT, - BIO_R_ADDRINFO_ADDR_IS_NOT_AF_INET); + ERR_raise(ERR_LIB_BIO, BIO_R_ADDRINFO_ADDR_IS_NOT_AF_INET); } else { *port_ptr = ntohs(BIO_ADDR_rawport(BIO_ADDRINFO_address(res))); ret = 1; @@ -103,7 +119,7 @@ int BIO_sock_error(int sock) return j; } -# if OPENSSL_API_COMPAT < 0x10100000L +# ifndef OPENSSL_NO_DEPRECATED_1_1_0 struct hostent *BIO_gethostbyname(const char *name) { /* @@ -120,8 +136,6 @@ int BIO_sock_init(void) static struct WSAData wsa_state; if (!wsa_init_done) { - int err; - wsa_init_done = 1; memset(&wsa_state, 0, sizeof(wsa_state)); /* @@ -131,9 +145,9 @@ int BIO_sock_init(void) * probed at run-time with DSO_global_lookup. */ if (WSAStartup(0x0202, &wsa_state) != 0) { - err = WSAGetLastError(); - SYSerr(SYS_F_WSASTARTUP, err); - BIOerr(BIO_F_BIO_SOCK_INIT, BIO_R_WSASTARTUP); + ERR_raise_data(ERR_LIB_SYS, get_last_socket_error(), + "calling wsastartup()"); + ERR_raise(ERR_LIB_BIO, BIO_R_WSASTARTUP); return -1; } } @@ -192,11 +206,12 @@ int BIO_socket_ioctl(int fd, long type, void *arg) i = ioctlsocket(fd, type, ARG); # endif /* __DJGPP__ */ if (i < 0) - SYSerr(SYS_F_IOCTLSOCKET, get_last_socket_error()); + ERR_raise_data(ERR_LIB_SYS, get_last_socket_error(), + "calling ioctlsocket()"); return i; } -# if OPENSSL_API_COMPAT < 0x10100000L +# ifndef OPENSSL_NO_DEPRECATED_1_1_0 int BIO_get_accept_socket(char *host, int bind_mode) { int s = INVALID_SOCKET; @@ -207,7 +222,7 @@ int BIO_get_accept_socket(char *host, int bind_mode) return INVALID_SOCKET; if (BIO_sock_init() != 1) - return INVALID_SOCKET; + goto err; if (BIO_lookup(h, p, BIO_LOOKUP_SERVER, AF_UNSPEC, SOCK_STREAM, &res) != 0) goto err; @@ -243,8 +258,9 @@ int BIO_accept(int sock, char **ip_port) ret = -2; goto end; } - SYSerr(SYS_F_ACCEPT, get_last_socket_error()); - BIOerr(BIO_F_BIO_ACCEPT, BIO_R_ACCEPT_ERROR); + ERR_raise_data(ERR_LIB_SYS, get_last_socket_error(), + "calling accept()"); + ERR_raise(ERR_LIB_BIO, BIO_R_ACCEPT_ERROR); goto end; } @@ -257,7 +273,7 @@ int BIO_accept(int sock, char **ip_port) *ip_port = NULL; if (*ip_port == NULL) { - BIOerr(BIO_F_BIO_ACCEPT, ERR_R_MALLOC_FAILURE); + ERR_raise(ERR_LIB_BIO, ERR_R_MALLOC_FAILURE); BIO_closesocket(ret); ret = (int)INVALID_SOCKET; } else { @@ -308,7 +324,8 @@ int BIO_socket_nbio(int s, int mode) l = fcntl(s, F_GETFL, 0); if (l == -1) { - SYSerr(SYS_F_FCNTL, get_last_sys_error()); + ERR_raise_data(ERR_LIB_SYS, get_last_sys_error(), + "calling fcntl()"); ret = -1; } else { # if defined(O_NONBLOCK) @@ -326,12 +343,13 @@ int BIO_socket_nbio(int s, int mode) ret = fcntl(s, F_SETFL, l); if (ret < 0) { - SYSerr(SYS_F_FCNTL, get_last_sys_error()); + ERR_raise_data(ERR_LIB_SYS, get_last_sys_error(), + "calling fcntl()"); } } # else /* make sure this call always pushes an error level; BIO_socket_ioctl() does so, so we do too. */ - BIOerr(BIO_F_BIO_SOCKET_NBIO, ERR_R_PASSED_INVALID_ARGUMENT); + ERR_raise(ERR_LIB_BIO, ERR_R_PASSED_INVALID_ARGUMENT); # endif return (ret == 0); @@ -349,21 +367,53 @@ int BIO_sock_info(int sock, ret = getsockname(sock, BIO_ADDR_sockaddr_noconst(info->addr), &addr_len); if (ret == -1) { - SYSerr(SYS_F_GETSOCKNAME, get_last_socket_error()); - BIOerr(BIO_F_BIO_SOCK_INFO, BIO_R_GETSOCKNAME_ERROR); + ERR_raise_data(ERR_LIB_SYS, get_last_socket_error(), + "calling getsockname()"); + ERR_raise(ERR_LIB_BIO, BIO_R_GETSOCKNAME_ERROR); return 0; } if ((size_t)addr_len > sizeof(*info->addr)) { - BIOerr(BIO_F_BIO_SOCK_INFO, BIO_R_GETSOCKNAME_TRUNCATED_ADDRESS); + ERR_raise(ERR_LIB_BIO, BIO_R_GETSOCKNAME_TRUNCATED_ADDRESS); return 0; } } break; default: - BIOerr(BIO_F_BIO_SOCK_INFO, BIO_R_UNKNOWN_INFO_TYPE); + ERR_raise(ERR_LIB_BIO, BIO_R_UNKNOWN_INFO_TYPE); return 0; } return 1; } +/* + * Wait on fd at most until max_time; succeed immediately if max_time == 0. + * If for_read == 0 then assume to wait for writing, else wait for reading. + * Returns -1 on error, 0 on timeout, and 1 on success. + */ +int BIO_socket_wait(int fd, int for_read, time_t max_time) +{ + fd_set confds; + struct timeval tv; + time_t now; + +#ifdef _WIN32 + if ((SOCKET)fd == INVALID_SOCKET) +#else + if (fd < 0 || fd >= FD_SETSIZE) #endif + return -1; + if (max_time == 0) + return 1; + + now = time(NULL); + if (max_time < now) + return 0; + + FD_ZERO(&confds); + openssl_fdset(fd, &confds); + tv.tv_usec = 0; + tv.tv_sec = (long)(max_time - now); /* might overflow */ + return select(fd + 1, for_read ? &confds : NULL, + for_read ? NULL : &confds, NULL, &tv); +} +#endif /* !defined(OPENSSL_NO_SOCK) */ diff --git a/crypto/bio/b_sock2.c b/crypto/bio/bio_sock2.c index 104ff31b0d2e..8bdad0c0b6ae 100644 --- a/crypto/bio/b_sock2.c +++ b/crypto/bio/bio_sock2.c @@ -1,7 +1,7 @@ /* - * Copyright 2016-2021 The OpenSSL Project Authors. All Rights Reserved. + * Copyright 2016-2022 The OpenSSL Project Authors. All Rights Reserved. * - * Licensed under the OpenSSL license (the "License"). You may not use + * 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 * in the file LICENSE in the source distribution or at * https://www.openssl.org/source/license.html @@ -12,6 +12,7 @@ #include <errno.h> #include "bio_local.h" +#include "internal/ktls.h" #include <openssl/err.h> @@ -46,8 +47,9 @@ int BIO_socket(int domain, int socktype, int protocol, int options) sock = socket(domain, socktype, protocol); if (sock == -1) { - SYSerr(SYS_F_SOCKET, get_last_socket_error()); - BIOerr(BIO_F_BIO_SOCKET, BIO_R_UNABLE_TO_CREATE_SOCKET); + ERR_raise_data(ERR_LIB_SYS, get_last_socket_error(), + "calling socket()"); + ERR_raise(ERR_LIB_BIO, BIO_R_UNABLE_TO_CREATE_SOCKET); return INVALID_SOCKET; } @@ -79,7 +81,7 @@ int BIO_connect(int sock, const BIO_ADDR *addr, int options) const int on = 1; if (sock == -1) { - BIOerr(BIO_F_BIO_CONNECT, BIO_R_INVALID_SOCKET); + ERR_raise(ERR_LIB_BIO, BIO_R_INVALID_SOCKET); return 0; } @@ -89,8 +91,9 @@ int BIO_connect(int sock, const BIO_ADDR *addr, int options) if (options & BIO_SOCK_KEEPALIVE) { if (setsockopt(sock, SOL_SOCKET, SO_KEEPALIVE, (const void *)&on, sizeof(on)) != 0) { - SYSerr(SYS_F_SETSOCKOPT, get_last_socket_error()); - BIOerr(BIO_F_BIO_CONNECT, BIO_R_UNABLE_TO_KEEPALIVE); + ERR_raise_data(ERR_LIB_SYS, get_last_socket_error(), + "calling setsockopt()"); + ERR_raise(ERR_LIB_BIO, BIO_R_UNABLE_TO_KEEPALIVE); return 0; } } @@ -98,8 +101,9 @@ int BIO_connect(int sock, const BIO_ADDR *addr, int options) if (options & BIO_SOCK_NODELAY) { if (setsockopt(sock, IPPROTO_TCP, TCP_NODELAY, (const void *)&on, sizeof(on)) != 0) { - SYSerr(SYS_F_SETSOCKOPT, get_last_socket_error()); - BIOerr(BIO_F_BIO_CONNECT, BIO_R_UNABLE_TO_NODELAY); + ERR_raise_data(ERR_LIB_SYS, get_last_socket_error(), + "calling setsockopt()"); + ERR_raise(ERR_LIB_BIO, BIO_R_UNABLE_TO_NODELAY); return 0; } } @@ -107,11 +111,21 @@ int BIO_connect(int sock, const BIO_ADDR *addr, int options) if (connect(sock, BIO_ADDR_sockaddr(addr), BIO_ADDR_sockaddr_size(addr)) == -1) { if (!BIO_sock_should_retry(-1)) { - SYSerr(SYS_F_CONNECT, get_last_socket_error()); - BIOerr(BIO_F_BIO_CONNECT, BIO_R_CONNECT_ERROR); + ERR_raise_data(ERR_LIB_SYS, get_last_socket_error(), + "calling connect()"); + ERR_raise(ERR_LIB_BIO, BIO_R_CONNECT_ERROR); } return 0; } +# ifndef OPENSSL_NO_KTLS + /* + * The new socket is created successfully regardless of ktls_enable. + * ktls_enable doesn't change any functionality of the socket, except + * changing the setsockopt to enable the processing of ktls_start. + * Thus, it is not a problem to call it for non-TLS sockets. + */ + ktls_enable(sock); +# endif return 1; } @@ -138,7 +152,7 @@ int BIO_bind(int sock, const BIO_ADDR *addr, int options) # endif if (sock == -1) { - BIOerr(BIO_F_BIO_BIND, BIO_R_INVALID_SOCKET); + ERR_raise(ERR_LIB_BIO, BIO_R_INVALID_SOCKET); return 0; } @@ -150,16 +164,18 @@ int BIO_bind(int sock, const BIO_ADDR *addr, int options) if (options & BIO_SOCK_REUSEADDR) { if (setsockopt(sock, SOL_SOCKET, SO_REUSEADDR, (const void *)&on, sizeof(on)) != 0) { - SYSerr(SYS_F_SETSOCKOPT, get_last_socket_error()); - BIOerr(BIO_F_BIO_BIND, BIO_R_UNABLE_TO_REUSEADDR); + ERR_raise_data(ERR_LIB_SYS, get_last_socket_error(), + "calling setsockopt()"); + ERR_raise(ERR_LIB_BIO, BIO_R_UNABLE_TO_REUSEADDR); return 0; } } # endif if (bind(sock, BIO_ADDR_sockaddr(addr), BIO_ADDR_sockaddr_size(addr)) != 0) { - SYSerr(SYS_F_BIND, get_last_socket_error()); - BIOerr(BIO_F_BIO_BIND, BIO_R_UNABLE_TO_BIND_SOCKET); + ERR_raise_data(ERR_LIB_SYS, get_last_socket_error() /* may be 0 */, + "calling bind()"); + ERR_raise(ERR_LIB_BIO, BIO_R_UNABLE_TO_BIND_SOCKET); return 0; } @@ -210,15 +226,16 @@ int BIO_listen(int sock, const BIO_ADDR *addr, int options) socklen_t socktype_len = sizeof(socktype); if (sock == -1) { - BIOerr(BIO_F_BIO_LISTEN, BIO_R_INVALID_SOCKET); + ERR_raise(ERR_LIB_BIO, BIO_R_INVALID_SOCKET); return 0; } if (getsockopt(sock, SOL_SOCKET, SO_TYPE, (void *)&socktype, &socktype_len) != 0 || socktype_len != sizeof(socktype)) { - SYSerr(SYS_F_GETSOCKOPT, get_last_socket_error()); - BIOerr(BIO_F_BIO_LISTEN, BIO_R_GETTING_SOCKTYPE); + ERR_raise_data(ERR_LIB_SYS, get_last_socket_error(), + "calling getsockopt()"); + ERR_raise(ERR_LIB_BIO, BIO_R_GETTING_SOCKTYPE); return 0; } @@ -228,8 +245,9 @@ int BIO_listen(int sock, const BIO_ADDR *addr, int options) if (options & BIO_SOCK_KEEPALIVE) { if (setsockopt(sock, SOL_SOCKET, SO_KEEPALIVE, (const void *)&on, sizeof(on)) != 0) { - SYSerr(SYS_F_SETSOCKOPT, get_last_socket_error()); - BIOerr(BIO_F_BIO_LISTEN, BIO_R_UNABLE_TO_KEEPALIVE); + ERR_raise_data(ERR_LIB_SYS, get_last_socket_error(), + "calling setsockopt()"); + ERR_raise(ERR_LIB_BIO, BIO_R_UNABLE_TO_KEEPALIVE); return 0; } } @@ -237,8 +255,9 @@ int BIO_listen(int sock, const BIO_ADDR *addr, int options) if (options & BIO_SOCK_NODELAY) { if (setsockopt(sock, IPPROTO_TCP, TCP_NODELAY, (const void *)&on, sizeof(on)) != 0) { - SYSerr(SYS_F_SETSOCKOPT, get_last_socket_error()); - BIOerr(BIO_F_BIO_LISTEN, BIO_R_UNABLE_TO_NODELAY); + ERR_raise_data(ERR_LIB_SYS, get_last_socket_error(), + "calling setsockopt()"); + ERR_raise(ERR_LIB_BIO, BIO_R_UNABLE_TO_NODELAY); return 0; } } @@ -253,8 +272,9 @@ int BIO_listen(int sock, const BIO_ADDR *addr, int options) on = options & BIO_SOCK_V6_ONLY ? 1 : 0; if (setsockopt(sock, IPPROTO_IPV6, IPV6_V6ONLY, (const void *)&on, sizeof(on)) != 0) { - SYSerr(SYS_F_SETSOCKOPT, get_last_socket_error()); - BIOerr(BIO_F_BIO_LISTEN, BIO_R_LISTEN_V6_ONLY); + ERR_raise_data(ERR_LIB_SYS, get_last_socket_error(), + "calling setsockopt()"); + ERR_raise(ERR_LIB_BIO, BIO_R_LISTEN_V6_ONLY); return 0; } } @@ -264,8 +284,9 @@ int BIO_listen(int sock, const BIO_ADDR *addr, int options) return 0; if (socktype != SOCK_DGRAM && listen(sock, MAX_LISTEN) == -1) { - SYSerr(SYS_F_LISTEN, get_last_socket_error()); - BIOerr(BIO_F_BIO_LISTEN, BIO_R_UNABLE_TO_LISTEN_SOCKET); + ERR_raise_data(ERR_LIB_SYS, get_last_socket_error(), + "calling listen()"); + ERR_raise(ERR_LIB_BIO, BIO_R_UNABLE_TO_LISTEN_SOCKET); return 0; } @@ -291,8 +312,9 @@ int BIO_accept_ex(int accept_sock, BIO_ADDR *addr_, int options) BIO_ADDR_sockaddr_noconst(addr), &len); if (accepted_sock == -1) { if (!BIO_sock_should_retry(accepted_sock)) { - SYSerr(SYS_F_ACCEPT, get_last_socket_error()); - BIOerr(BIO_F_BIO_ACCEPT_EX, BIO_R_ACCEPT_ERROR); + ERR_raise_data(ERR_LIB_SYS, get_last_socket_error(), + "calling accept()"); + ERR_raise(ERR_LIB_BIO, BIO_R_ACCEPT_ERROR); } return INVALID_SOCKET; } @@ -311,7 +333,7 @@ int BIO_accept_ex(int accept_sock, BIO_ADDR *addr_, int options) */ int BIO_closesocket(int sock) { - if (closesocket(sock) < 0) + if (sock < 0 || closesocket(sock) < 0) return 0; return 1; } diff --git a/crypto/bio/bss_acpt.c b/crypto/bio/bss_acpt.c index 4461eae2333d..8870831039e9 100644 --- a/crypto/bio/bss_acpt.c +++ b/crypto/bio/bss_acpt.c @@ -1,12 +1,14 @@ /* - * Copyright 1995-2020 The OpenSSL Project Authors. All Rights Reserved. + * Copyright 1995-2023 The OpenSSL Project Authors. All Rights Reserved. * - * Licensed under the OpenSSL license (the "License"). You may not use + * 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 * in the file LICENSE in the source distribution or at * https://www.openssl.org/source/license.html */ +#define OPENSSL_SUPPRESS_DEPRECATED + #include <stdio.h> #include <errno.h> #include "bio_local.h" @@ -54,10 +56,8 @@ static void BIO_ACCEPT_free(BIO_ACCEPT *a); static const BIO_METHOD methods_acceptp = { BIO_TYPE_ACCEPT, "socket accept", - /* TODO: Convert to new style write function */ bwrite_conv, acpt_write, - /* TODO: Convert to new style read function */ bread_conv, acpt_read, acpt_puts, @@ -93,7 +93,7 @@ static BIO_ACCEPT *BIO_ACCEPT_new(void) BIO_ACCEPT *ret; if ((ret = OPENSSL_zalloc(sizeof(*ret))) == NULL) { - BIOerr(BIO_F_BIO_ACCEPT_NEW, ERR_R_MALLOC_FAILURE); + ERR_raise(ERR_LIB_BIO, ERR_R_MALLOC_FAILURE); return NULL; } ret->accept_family = BIO_FAMILY_IPANY; @@ -156,10 +156,10 @@ static int acpt_state(BIO *b, BIO_ACCEPT *c) switch (c->state) { case ACPT_S_BEFORE: if (c->param_addr == NULL && c->param_serv == NULL) { - BIOerr(BIO_F_ACPT_STATE, BIO_R_NO_ACCEPT_ADDR_OR_SERVICE_SPECIFIED); - ERR_add_error_data(4, - "hostname=", c->param_addr, - " service=", c->param_serv); + ERR_raise_data(ERR_LIB_BIO, + BIO_R_NO_ACCEPT_ADDR_OR_SERVICE_SPECIFIED, + "hostname=%s, service=%s", + c->param_addr, c->param_serv); goto exit_loop; } @@ -192,7 +192,7 @@ static int acpt_state(BIO *b, BIO_ACCEPT *c) family = AF_INET6; } else { #endif - BIOerr(BIO_F_ACPT_STATE, BIO_R_UNAVAILABLE_IP_FAMILY); + ERR_raise(ERR_LIB_BIO, BIO_R_UNAVAILABLE_IP_FAMILY); goto exit_loop; } break; @@ -203,7 +203,7 @@ static int acpt_state(BIO *b, BIO_ACCEPT *c) family = AF_UNSPEC; break; default: - BIOerr(BIO_F_ACPT_STATE, BIO_R_UNSUPPORTED_IP_FAMILY); + ERR_raise(ERR_LIB_BIO, BIO_R_UNSUPPORTED_IP_FAMILY); goto exit_loop; } if (BIO_lookup(c->param_addr, c->param_serv, BIO_LOOKUP_SERVER, @@ -211,26 +211,31 @@ static int acpt_state(BIO *b, BIO_ACCEPT *c) goto exit_loop; } if (c->addr_first == NULL) { - BIOerr(BIO_F_ACPT_STATE, BIO_R_LOOKUP_RETURNED_NOTHING); + ERR_raise(ERR_LIB_BIO, BIO_R_LOOKUP_RETURNED_NOTHING); goto exit_loop; } - /* We're currently not iterating, but set this as preparation - * for possible future development in that regard - */ c->addr_iter = c->addr_first; c->state = ACPT_S_CREATE_SOCKET; break; case ACPT_S_CREATE_SOCKET: + ERR_set_mark(); s = BIO_socket(BIO_ADDRINFO_family(c->addr_iter), BIO_ADDRINFO_socktype(c->addr_iter), BIO_ADDRINFO_protocol(c->addr_iter), 0); if (s == (int)INVALID_SOCKET) { - SYSerr(SYS_F_SOCKET, get_last_socket_error()); - ERR_add_error_data(4, - "hostname=", c->param_addr, - " service=", c->param_serv); - BIOerr(BIO_F_ACPT_STATE, BIO_R_UNABLE_TO_CREATE_SOCKET); + if ((c->addr_iter = BIO_ADDRINFO_next(c->addr_iter)) != NULL) { + /* + * if there are more addresses to try, do that first + */ + ERR_pop_to_mark(); + break; + } + ERR_clear_last_mark(); + ERR_raise_data(ERR_LIB_SYS, get_last_socket_error(), + "calling socket(%s, %s)", + c->param_addr, c->param_serv); + ERR_raise(ERR_LIB_BIO, BIO_R_UNABLE_TO_CREATE_SOCKET); goto exit_loop; } c->accept_sock = s; @@ -306,9 +311,11 @@ static int acpt_state(BIO *b, BIO_ACCEPT *c) if (bio == NULL) goto exit_loop; + BIO_set_callback_ex(bio, BIO_get_callback_ex(b)); +#ifndef OPENSSL_NO_DEPRECATED_3_0 BIO_set_callback(bio, BIO_get_callback(b)); +#endif BIO_set_callback_arg(bio, BIO_get_callback_arg(b)); - /* * If the accept BIO has an bio_chain, we dup it and put the new * socket at the end. @@ -559,7 +566,7 @@ BIO *BIO_new_accept(const char *str) ret = BIO_new(BIO_s_accept()); if (ret == NULL) return NULL; - if (BIO_set_accept_name(ret, str)) + if (BIO_set_accept_name(ret, str) > 0) return ret; BIO_free(ret); return NULL; diff --git a/crypto/bio/bss_bio.c b/crypto/bio/bss_bio.c index c97349e43282..7fa8778cae10 100644 --- a/crypto/bio/bss_bio.c +++ b/crypto/bio/bss_bio.c @@ -1,7 +1,7 @@ /* - * Copyright 1999-2017 The OpenSSL Project Authors. All Rights Reserved. + * Copyright 1999-2021 The OpenSSL Project Authors. All Rights Reserved. * - * Licensed under the OpenSSL license (the "License"). You may not use + * 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 * in the file LICENSE in the source distribution or at * https://www.openssl.org/source/license.html @@ -38,10 +38,8 @@ static void bio_destroy_pair(BIO *bio); static const BIO_METHOD methods_biop = { BIO_TYPE_BIO, "BIO pair", - /* TODO: Convert to new style write function */ bwrite_conv, bio_write, - /* TODO: Convert to new style read function */ bread_conv, bio_read, bio_puts, @@ -286,7 +284,7 @@ static int bio_write(BIO *bio, const char *buf, int num_) b->request = 0; if (b->closed) { /* we already closed */ - BIOerr(BIO_F_BIO_WRITE, BIO_R_BROKEN_PIPE); + ERR_raise(ERR_LIB_BIO, BIO_R_BROKEN_PIPE); return -1; } @@ -362,7 +360,7 @@ static ossl_ssize_t bio_nwrite0(BIO *bio, char **buf) b->request = 0; if (b->closed) { - BIOerr(BIO_F_BIO_NWRITE0, BIO_R_BROKEN_PIPE); + ERR_raise(ERR_LIB_BIO, BIO_R_BROKEN_PIPE); return -1; } @@ -427,10 +425,10 @@ static long bio_ctrl(BIO *bio, int cmd, long num, void *ptr) case BIO_C_SET_WRITE_BUF_SIZE: if (b->peer) { - BIOerr(BIO_F_BIO_CTRL, BIO_R_IN_USE); + ERR_raise(ERR_LIB_BIO, BIO_R_IN_USE); ret = 0; } else if (num == 0) { - BIOerr(BIO_F_BIO_CTRL, BIO_R_INVALID_ARGUMENT); + ERR_raise(ERR_LIB_BIO, BIO_R_INVALID_ARGUMENT); ret = 0; } else { size_t new_size = num; @@ -616,14 +614,14 @@ static int bio_make_pair(BIO *bio1, BIO *bio2) b2 = bio2->ptr; if (b1->peer != NULL || b2->peer != NULL) { - BIOerr(BIO_F_BIO_MAKE_PAIR, BIO_R_IN_USE); + ERR_raise(ERR_LIB_BIO, BIO_R_IN_USE); return 0; } if (b1->buf == NULL) { b1->buf = OPENSSL_malloc(b1->size); if (b1->buf == NULL) { - BIOerr(BIO_F_BIO_MAKE_PAIR, ERR_R_MALLOC_FAILURE); + ERR_raise(ERR_LIB_BIO, ERR_R_MALLOC_FAILURE); return 0; } b1->len = 0; @@ -633,7 +631,7 @@ static int bio_make_pair(BIO *bio1, BIO *bio2) if (b2->buf == NULL) { b2->buf = OPENSSL_malloc(b2->size); if (b2->buf == NULL) { - BIOerr(BIO_F_BIO_MAKE_PAIR, ERR_R_MALLOC_FAILURE); + ERR_raise(ERR_LIB_BIO, ERR_R_MALLOC_FAILURE); return 0; } b2->len = 0; @@ -750,7 +748,7 @@ int BIO_nread0(BIO *bio, char **buf) long ret; if (!bio->init) { - BIOerr(BIO_F_BIO_NREAD0, BIO_R_UNINITIALIZED); + ERR_raise(ERR_LIB_BIO, BIO_R_UNINITIALIZED); return -2; } @@ -766,7 +764,7 @@ int BIO_nread(BIO *bio, char **buf, int num) int ret; if (!bio->init) { - BIOerr(BIO_F_BIO_NREAD, BIO_R_UNINITIALIZED); + ERR_raise(ERR_LIB_BIO, BIO_R_UNINITIALIZED); return -2; } @@ -781,7 +779,7 @@ int BIO_nwrite0(BIO *bio, char **buf) long ret; if (!bio->init) { - BIOerr(BIO_F_BIO_NWRITE0, BIO_R_UNINITIALIZED); + ERR_raise(ERR_LIB_BIO, BIO_R_UNINITIALIZED); return -2; } @@ -797,7 +795,7 @@ int BIO_nwrite(BIO *bio, char **buf, int num) int ret; if (!bio->init) { - BIOerr(BIO_F_BIO_NWRITE, BIO_R_UNINITIALIZED); + ERR_raise(ERR_LIB_BIO, BIO_R_UNINITIALIZED); return -2; } diff --git a/crypto/bio/bss_conn.c b/crypto/bio/bss_conn.c index 807a82b23ba2..0d91f25fe70e 100644 --- a/crypto/bio/bss_conn.c +++ b/crypto/bio/bss_conn.c @@ -1,7 +1,7 @@ /* - * Copyright 1995-2020 The OpenSSL Project Authors. All Rights Reserved. + * Copyright 1995-2022 The OpenSSL Project Authors. All Rights Reserved. * - * Licensed under the OpenSSL license (the "License"). You may not use + * 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 * in the file LICENSE in the source distribution or at * https://www.openssl.org/source/license.html @@ -11,6 +11,7 @@ #include <errno.h> #include "bio_local.h" +#include "internal/ktls.h" #ifndef OPENSSL_NO_SOCK @@ -20,6 +21,9 @@ typedef struct bio_connect_st { char *param_hostname; char *param_service; int connect_mode; +# ifndef OPENSSL_NO_KTLS + unsigned char record_type; +# endif BIO_ADDRINFO *addr_first; const BIO_ADDRINFO *addr_iter; @@ -59,10 +63,8 @@ void BIO_CONNECT_free(BIO_CONNECT *a); static const BIO_METHOD methods_connectp = { BIO_TYPE_CONNECT, "socket connect", - /* TODO: Convert to new style write function */ bwrite_conv, conn_write, - /* TODO: Convert to new style read function */ bread_conv, conn_read, conn_puts, @@ -85,10 +87,10 @@ static int conn_state(BIO *b, BIO_CONNECT *c) switch (c->state) { case BIO_CONN_S_BEFORE: if (c->param_hostname == NULL && c->param_service == NULL) { - BIOerr(BIO_F_CONN_STATE, BIO_R_NO_HOSTNAME_OR_SERVICE_SPECIFIED); - ERR_add_error_data(4, - "hostname=", c->param_hostname, - " service=", c->param_service); + ERR_raise_data(ERR_LIB_BIO, + BIO_R_NO_HOSTNAME_OR_SERVICE_SPECIFIED, + "hostname=%s service=%s", + c->param_hostname, c->param_service); goto exit_loop; } c->state = BIO_CONN_S_GET_ADDR; @@ -107,7 +109,7 @@ static int conn_state(BIO *b, BIO_CONNECT *c) family = AF_INET6; } else { #endif - BIOerr(BIO_F_CONN_STATE, BIO_R_UNAVAILABLE_IP_FAMILY); + ERR_raise(ERR_LIB_BIO, BIO_R_UNAVAILABLE_IP_FAMILY); goto exit_loop; } break; @@ -118,7 +120,7 @@ static int conn_state(BIO *b, BIO_CONNECT *c) family = AF_UNSPEC; break; default: - BIOerr(BIO_F_CONN_STATE, BIO_R_UNSUPPORTED_IP_FAMILY); + ERR_raise(ERR_LIB_BIO, BIO_R_UNSUPPORTED_IP_FAMILY); goto exit_loop; } if (BIO_lookup(c->param_hostname, c->param_service, @@ -127,7 +129,7 @@ static int conn_state(BIO *b, BIO_CONNECT *c) goto exit_loop; } if (c->addr_first == NULL) { - BIOerr(BIO_F_CONN_STATE, BIO_R_LOOKUP_RETURNED_NOTHING); + ERR_raise(ERR_LIB_BIO, BIO_R_LOOKUP_RETURNED_NOTHING); goto exit_loop; } c->addr_iter = c->addr_first; @@ -139,11 +141,10 @@ static int conn_state(BIO *b, BIO_CONNECT *c) BIO_ADDRINFO_socktype(c->addr_iter), BIO_ADDRINFO_protocol(c->addr_iter), 0); if (ret == (int)INVALID_SOCKET) { - SYSerr(SYS_F_SOCKET, get_last_socket_error()); - ERR_add_error_data(4, - "hostname=", c->param_hostname, - " service=", c->param_service); - BIOerr(BIO_F_CONN_STATE, BIO_R_UNABLE_TO_CREATE_SOCKET); + ERR_raise_data(ERR_LIB_SYS, get_last_socket_error(), + "calling socket(%s, %s)", + c->param_hostname, c->param_service); + ERR_raise(ERR_LIB_BIO, BIO_R_UNABLE_TO_CREATE_SOCKET); goto exit_loop; } b->num = ret; @@ -152,6 +153,7 @@ static int conn_state(BIO *b, BIO_CONNECT *c) case BIO_CONN_S_CONNECT: BIO_clear_retry_flags(b); + ERR_set_mark(); ret = BIO_connect(b->num, BIO_ADDRINFO_address(c->addr_iter), BIO_SOCK_KEEPALIVE | c->connect_mode); b->retry_reason = 0; @@ -160,7 +162,7 @@ static int conn_state(BIO *b, BIO_CONNECT *c) BIO_set_retry_special(b); c->state = BIO_CONN_S_BLOCKED_CONNECT; b->retry_reason = BIO_RR_CONNECT; - ERR_clear_error(); + ERR_pop_to_mark(); } else if ((c->addr_iter = BIO_ADDRINFO_next(c->addr_iter)) != NULL) { /* @@ -168,23 +170,27 @@ static int conn_state(BIO *b, BIO_CONNECT *c) */ BIO_closesocket(b->num); c->state = BIO_CONN_S_CREATE_SOCKET; - ERR_clear_error(); + ERR_pop_to_mark(); break; } else { - SYSerr(SYS_F_CONNECT, get_last_socket_error()); - ERR_add_error_data(4, - "hostname=", c->param_hostname, - " service=", c->param_service); + ERR_clear_last_mark(); + ERR_raise_data(ERR_LIB_SYS, get_last_socket_error(), + "calling connect(%s, %s)", + c->param_hostname, c->param_service); c->state = BIO_CONN_S_CONNECT_ERROR; break; } goto exit_loop; } else { + ERR_clear_last_mark(); c->state = BIO_CONN_S_OK; } break; case BIO_CONN_S_BLOCKED_CONNECT: + /* wait for socket being writable, before querying BIO_sock_error */ + if (BIO_socket_wait(b->num, 0, time(NULL)) == 0) + break; i = BIO_sock_error(b->num); if (i != 0) { BIO_clear_retry_flags(b); @@ -194,22 +200,30 @@ static int conn_state(BIO *b, BIO_CONNECT *c) */ BIO_closesocket(b->num); c->state = BIO_CONN_S_CREATE_SOCKET; - ERR_clear_error(); break; } - SYSerr(SYS_F_CONNECT, i); - ERR_add_error_data(4, - "hostname=", c->param_hostname, - " service=", c->param_service); - BIOerr(BIO_F_CONN_STATE, BIO_R_NBIO_CONNECT_ERROR); + ERR_raise_data(ERR_LIB_SYS, i, + "calling connect(%s, %s)", + c->param_hostname, c->param_service); + ERR_raise(ERR_LIB_BIO, BIO_R_NBIO_CONNECT_ERROR); ret = 0; goto exit_loop; - } else + } else { c->state = BIO_CONN_S_OK; +# ifndef OPENSSL_NO_KTLS + /* + * The new socket is created successfully regardless of ktls_enable. + * ktls_enable doesn't change any functionality of the socket, except + * changing the setsockopt to enable the processing of ktls_start. + * Thus, it is not a problem to call it for non-TLS sockets. + */ + ktls_enable(b->num); +# endif + } break; case BIO_CONN_S_CONNECT_ERROR: - BIOerr(BIO_F_CONN_STATE, BIO_R_CONNECT_ERROR); + ERR_raise(ERR_LIB_BIO, BIO_R_CONNECT_ERROR); ret = 0; goto exit_loop; @@ -240,7 +254,7 @@ BIO_CONNECT *BIO_CONNECT_new(void) BIO_CONNECT *ret; if ((ret = OPENSSL_zalloc(sizeof(*ret))) == NULL) { - BIOerr(BIO_F_BIO_CONNECT_NEW, ERR_R_MALLOC_FAILURE); + ERR_raise(ERR_LIB_BIO, ERR_R_MALLOC_FAILURE); return NULL; } ret->state = BIO_CONN_S_BEFORE; @@ -320,7 +334,12 @@ static int conn_read(BIO *b, char *out, int outl) if (out != NULL) { clear_socket_error(); - ret = readsocket(b->num, out, outl); +# ifndef OPENSSL_NO_KTLS + if (BIO_get_ktls_recv(b)) + ret = ktls_read_record(b->num, out, outl); + else +# endif + ret = readsocket(b->num, out, outl); BIO_clear_retry_flags(b); if (ret <= 0) { if (BIO_sock_should_retry(ret)) @@ -345,7 +364,16 @@ static int conn_write(BIO *b, const char *in, int inl) } clear_socket_error(); - ret = writesocket(b->num, in, inl); +# ifndef OPENSSL_NO_KTLS + if (BIO_should_ktls_ctrl_msg_flag(b)) { + ret = ktls_send_ctrl_message(b->num, data->record_type, in, inl); + if (ret >= 0) { + ret = inl; + BIO_clear_ktls_ctrl_msg_flag(b); + } + } else +# endif + ret = writesocket(b->num, in, inl); BIO_clear_retry_flags(b); if (ret <= 0) { if (BIO_sock_should_retry(ret)) @@ -361,6 +389,9 @@ static long conn_ctrl(BIO *b, int cmd, long num, void *ptr) const char **pptr = NULL; long ret = 1; BIO_CONNECT *data; +# ifndef OPENSSL_NO_KTLS + ktls_crypto_info_t *crypto_info; +# endif data = (BIO_CONNECT *)b->ptr; @@ -518,8 +549,29 @@ static long conn_ctrl(BIO *b, int cmd, long num, void *ptr) } break; case BIO_CTRL_EOF: - ret = (b->flags & BIO_FLAGS_IN_EOF) != 0 ? 1 : 0; + ret = (b->flags & BIO_FLAGS_IN_EOF) != 0; + break; +# ifndef OPENSSL_NO_KTLS + case BIO_CTRL_SET_KTLS: + crypto_info = (ktls_crypto_info_t *)ptr; + ret = ktls_start(b->num, crypto_info, num); + if (ret) + BIO_set_ktls_flag(b, num); + break; + case BIO_CTRL_GET_KTLS_SEND: + return BIO_should_ktls_flag(b, 1) != 0; + case BIO_CTRL_GET_KTLS_RECV: + return BIO_should_ktls_flag(b, 0) != 0; + case BIO_CTRL_SET_KTLS_TX_SEND_CTRL_MSG: + BIO_set_ktls_ctrl_msg_flag(b); + data->record_type = num; + ret = 0; + break; + case BIO_CTRL_CLEAR_KTLS_TX_CTRL_MSG: + BIO_clear_ktls_ctrl_msg_flag(b); + ret = 0; break; +# endif default: ret = 0; break; diff --git a/crypto/bio/bss_core.c b/crypto/bio/bss_core.c new file mode 100644 index 000000000000..7a84b20460c8 --- /dev/null +++ b/crypto/bio/bss_core.c @@ -0,0 +1,194 @@ +/* + * Copyright 2019-2022 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 + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html + */ + +#include <openssl/core_dispatch.h> +#include "bio_local.h" +#include "internal/cryptlib.h" + +typedef struct { + OSSL_FUNC_BIO_read_ex_fn *c_bio_read_ex; + OSSL_FUNC_BIO_write_ex_fn *c_bio_write_ex; + OSSL_FUNC_BIO_gets_fn *c_bio_gets; + OSSL_FUNC_BIO_puts_fn *c_bio_puts; + OSSL_FUNC_BIO_ctrl_fn *c_bio_ctrl; + OSSL_FUNC_BIO_up_ref_fn *c_bio_up_ref; + OSSL_FUNC_BIO_free_fn *c_bio_free; +} BIO_CORE_GLOBALS; + +static void bio_core_globals_free(void *vbcg) +{ + OPENSSL_free(vbcg); +} + +static void *bio_core_globals_new(OSSL_LIB_CTX *ctx) +{ + return OPENSSL_zalloc(sizeof(BIO_CORE_GLOBALS)); +} + +static const OSSL_LIB_CTX_METHOD bio_core_globals_method = { + OSSL_LIB_CTX_METHOD_DEFAULT_PRIORITY, + bio_core_globals_new, + bio_core_globals_free, +}; + +static ossl_inline BIO_CORE_GLOBALS *get_globals(OSSL_LIB_CTX *libctx) +{ + return ossl_lib_ctx_get_data(libctx, OSSL_LIB_CTX_BIO_CORE_INDEX, + &bio_core_globals_method); +} + +static int bio_core_read_ex(BIO *bio, char *data, size_t data_len, + size_t *bytes_read) +{ + BIO_CORE_GLOBALS *bcgbl = get_globals(bio->libctx); + + if (bcgbl == NULL || bcgbl->c_bio_read_ex == NULL) + return 0; + return bcgbl->c_bio_read_ex(BIO_get_data(bio), data, data_len, bytes_read); +} + +static int bio_core_write_ex(BIO *bio, const char *data, size_t data_len, + size_t *written) +{ + BIO_CORE_GLOBALS *bcgbl = get_globals(bio->libctx); + + if (bcgbl == NULL || bcgbl->c_bio_write_ex == NULL) + return 0; + return bcgbl->c_bio_write_ex(BIO_get_data(bio), data, data_len, written); +} + +static long bio_core_ctrl(BIO *bio, int cmd, long num, void *ptr) +{ + BIO_CORE_GLOBALS *bcgbl = get_globals(bio->libctx); + + if (bcgbl == NULL || bcgbl->c_bio_ctrl == NULL) + return -1; + return bcgbl->c_bio_ctrl(BIO_get_data(bio), cmd, num, ptr); +} + +static int bio_core_gets(BIO *bio, char *buf, int size) +{ + BIO_CORE_GLOBALS *bcgbl = get_globals(bio->libctx); + + if (bcgbl == NULL || bcgbl->c_bio_gets == NULL) + return -1; + return bcgbl->c_bio_gets(BIO_get_data(bio), buf, size); +} + +static int bio_core_puts(BIO *bio, const char *str) +{ + BIO_CORE_GLOBALS *bcgbl = get_globals(bio->libctx); + + if (bcgbl == NULL || bcgbl->c_bio_puts == NULL) + return -1; + return bcgbl->c_bio_puts(BIO_get_data(bio), str); +} + +static int bio_core_new(BIO *bio) +{ + BIO_set_init(bio, 1); + + return 1; +} + +static int bio_core_free(BIO *bio) +{ + BIO_CORE_GLOBALS *bcgbl = get_globals(bio->libctx); + + if (bcgbl == NULL) + return 0; + + BIO_set_init(bio, 0); + bcgbl->c_bio_free(BIO_get_data(bio)); + + return 1; +} + +static const BIO_METHOD corebiometh = { + BIO_TYPE_CORE_TO_PROV, + "BIO to Core filter", + bio_core_write_ex, + NULL, + bio_core_read_ex, + NULL, + bio_core_puts, + bio_core_gets, + bio_core_ctrl, + bio_core_new, + bio_core_free, + NULL, +}; + +const BIO_METHOD *BIO_s_core(void) +{ + return &corebiometh; +} + +BIO *BIO_new_from_core_bio(OSSL_LIB_CTX *libctx, OSSL_CORE_BIO *corebio) +{ + BIO *outbio; + BIO_CORE_GLOBALS *bcgbl = get_globals(libctx); + + /* Check the library context has been initialised with the callbacks */ + if (bcgbl == NULL || (bcgbl->c_bio_write_ex == NULL && bcgbl->c_bio_read_ex == NULL)) + return NULL; + + if ((outbio = BIO_new_ex(libctx, BIO_s_core())) == NULL) + return NULL; + + if (!bcgbl->c_bio_up_ref(corebio)) { + BIO_free(outbio); + return NULL; + } + BIO_set_data(outbio, corebio); + return outbio; +} + +int ossl_bio_init_core(OSSL_LIB_CTX *libctx, const OSSL_DISPATCH *fns) +{ + BIO_CORE_GLOBALS *bcgbl = get_globals(libctx); + + if (bcgbl == NULL) + return 0; + + for (; fns->function_id != 0; fns++) { + switch (fns->function_id) { + case OSSL_FUNC_BIO_READ_EX: + if (bcgbl->c_bio_read_ex == NULL) + bcgbl->c_bio_read_ex = OSSL_FUNC_BIO_read_ex(fns); + break; + case OSSL_FUNC_BIO_WRITE_EX: + if (bcgbl->c_bio_write_ex == NULL) + bcgbl->c_bio_write_ex = OSSL_FUNC_BIO_write_ex(fns); + break; + case OSSL_FUNC_BIO_GETS: + if (bcgbl->c_bio_gets == NULL) + bcgbl->c_bio_gets = OSSL_FUNC_BIO_gets(fns); + break; + case OSSL_FUNC_BIO_PUTS: + if (bcgbl->c_bio_puts == NULL) + bcgbl->c_bio_puts = OSSL_FUNC_BIO_puts(fns); + break; + case OSSL_FUNC_BIO_CTRL: + if (bcgbl->c_bio_ctrl == NULL) + bcgbl->c_bio_ctrl = OSSL_FUNC_BIO_ctrl(fns); + break; + case OSSL_FUNC_BIO_UP_REF: + if (bcgbl->c_bio_up_ref == NULL) + bcgbl->c_bio_up_ref = OSSL_FUNC_BIO_up_ref(fns); + break; + case OSSL_FUNC_BIO_FREE: + if (bcgbl->c_bio_free == NULL) + bcgbl->c_bio_free = OSSL_FUNC_BIO_free(fns); + break; + } + } + + return 1; +} diff --git a/crypto/bio/bss_dgram.c b/crypto/bio/bss_dgram.c index c87ba4d26508..4292d805a16a 100644 --- a/crypto/bio/bss_dgram.c +++ b/crypto/bio/bss_dgram.c @@ -1,7 +1,7 @@ /* - * Copyright 2005-2021 The OpenSSL Project Authors. All Rights Reserved. + * Copyright 2005-2025 The OpenSSL Project Authors. All Rights Reserved. * - * Licensed under the OpenSSL license (the "License"). You may not use + * 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 * in the file LICENSE in the source distribution or at * https://www.openssl.org/source/license.html @@ -57,6 +57,8 @@ static int dgram_sctp_puts(BIO *h, const char *str); static long dgram_sctp_ctrl(BIO *h, int cmd, long arg1, void *arg2); static int dgram_sctp_new(BIO *h); static int dgram_sctp_free(BIO *data); +static int dgram_sctp_wait_for_dry(BIO *b); +static int dgram_sctp_msg_waiting(BIO *b); # ifdef SCTP_AUTHENTICATION_EVENT static void dgram_sctp_handle_auth_free_key_event(BIO *b, union sctp_notification *snp); @@ -70,10 +72,8 @@ static void get_current_time(struct timeval *t); static const BIO_METHOD methods_dgramp = { BIO_TYPE_DGRAM, "datagram socket", - /* TODO: Convert to new style write function */ bwrite_conv, dgram_write, - /* TODO: Convert to new style read function */ bread_conv, dgram_read, dgram_puts, @@ -88,10 +88,8 @@ static const BIO_METHOD methods_dgramp = { static const BIO_METHOD methods_dgramp_sctp = { BIO_TYPE_DGRAM_SCTP, "datagram sctp socket", - /* TODO: Convert to new style write function */ bwrite_conv, dgram_sctp_write, - /* TODO: Convert to new style write function */ bread_conv, dgram_sctp_read, dgram_sctp_puts, @@ -128,7 +126,7 @@ typedef struct bio_dgram_sctp_data_st { struct bio_dgram_sctp_sndinfo sndinfo; struct bio_dgram_sctp_rcvinfo rcvinfo; struct bio_dgram_sctp_prinfo prinfo; - void (*handle_notifications) (BIO *bio, void *context, void *buf); + BIO_dgram_sctp_notification_handler_fn handle_notifications; void *notification_context; int in_handshake; int ccs_rcvd; @@ -197,12 +195,6 @@ static void dgram_adjust_rcv_timeout(BIO *b) { # if defined(SO_RCVTIMEO) bio_dgram_data *data = (bio_dgram_data *)b->ptr; - union { - size_t s; - int i; - } sz = { - 0 - }; /* Is a timer active? */ if (data->next_timeout.tv_sec > 0 || data->next_timeout.tv_usec > 0) { @@ -212,21 +204,21 @@ static void dgram_adjust_rcv_timeout(BIO *b) # ifdef OPENSSL_SYS_WINDOWS int timeout; - sz.i = sizeof(timeout); + int sz = sizeof(timeout); if (getsockopt(b->num, SOL_SOCKET, SO_RCVTIMEO, - (void *)&timeout, &sz.i) < 0) { + (void *)&timeout, &sz) < 0) { perror("getsockopt"); } else { data->socket_timeout.tv_sec = timeout / 1000; data->socket_timeout.tv_usec = (timeout % 1000) * 1000; } # else - sz.i = sizeof(data->socket_timeout); + socklen_t sz = sizeof(data->socket_timeout); if (getsockopt(b->num, SOL_SOCKET, SO_RCVTIMEO, - &(data->socket_timeout), (void *)&sz) < 0) { + &(data->socket_timeout), &sz) < 0) { perror("getsockopt"); - } else if (sizeof(sz.s) != sizeof(sz.i) && sz.i == 0) - OPENSSL_assert(sz.s <= sizeof(data->socket_timeout)); + } else + OPENSSL_assert(sz <= sizeof(data->socket_timeout)); # endif /* Get current time */ @@ -357,11 +349,11 @@ static int dgram_write(BIO *b, const char *in, int inl) return ret; } -static long dgram_get_mtu_overhead(bio_dgram_data *data) +static long dgram_get_mtu_overhead(BIO_ADDR *addr) { long ret; - switch (BIO_ADDR_family(&data->peer)) { + switch (BIO_ADDR_family(addr)) { case AF_INET: /* * Assume this is UDP - 20 bytes for IP, 8 bytes for UDP @@ -373,7 +365,8 @@ static long dgram_get_mtu_overhead(bio_dgram_data *data) { # ifdef IN6_IS_ADDR_V4MAPPED struct in6_addr tmp_addr; - if (BIO_ADDR_rawaddress(&data->peer, &tmp_addr, NULL) + + if (BIO_ADDR_rawaddress(addr, &tmp_addr, NULL) && IN6_IS_ADDR_V4MAPPED(&tmp_addr)) /* * Assume this is UDP - 20 bytes for IP, 8 bytes for UDP @@ -500,11 +493,7 @@ static long dgram_ctrl(BIO *b, int cmd, long num, void *ptr) &sockopt_len)) < 0 || sockopt_val < 0) { ret = 0; } else { - /* - * we assume that the transport protocol is UDP and no IP - * options are used. - */ - data->mtu = sockopt_val - 8 - 20; + data->mtu = sockopt_val - dgram_get_mtu_overhead(&addr); ret = data->mtu; } break; @@ -516,11 +505,7 @@ static long dgram_ctrl(BIO *b, int cmd, long num, void *ptr) || sockopt_val < 0) { ret = 0; } else { - /* - * we assume that the transport protocol is UDP and no IPV6 - * options are used. - */ - data->mtu = sockopt_val - 8 - 40; + data->mtu = sockopt_val - dgram_get_mtu_overhead(&addr); ret = data->mtu; } break; @@ -534,7 +519,7 @@ static long dgram_ctrl(BIO *b, int cmd, long num, void *ptr) # endif break; case BIO_CTRL_DGRAM_GET_FALLBACK_MTU: - ret = -dgram_get_mtu_overhead(data); + ret = -dgram_get_mtu_overhead(&data->peer); switch (BIO_ADDR_family(&data->peer)) { case AF_INET: ret += 576; @@ -609,19 +594,14 @@ static long dgram_ctrl(BIO *b, int cmd, long num, void *ptr) break; case BIO_CTRL_DGRAM_GET_RECV_TIMEOUT: { - union { - size_t s; - int i; - } sz = { - 0 - }; # ifdef OPENSSL_SYS_WINDOWS + int sz = 0; int timeout; struct timeval *tv = (struct timeval *)ptr; - sz.i = sizeof(timeout); + sz = sizeof(timeout); if (getsockopt(b->num, SOL_SOCKET, SO_RCVTIMEO, - (void *)&timeout, &sz.i) < 0) { + (void *)&timeout, &sz) < 0) { perror("getsockopt"); ret = -1; } else { @@ -630,16 +610,15 @@ static long dgram_ctrl(BIO *b, int cmd, long num, void *ptr) ret = sizeof(*tv); } # else - sz.i = sizeof(struct timeval); + socklen_t sz = sizeof(struct timeval); if (getsockopt(b->num, SOL_SOCKET, SO_RCVTIMEO, - ptr, (void *)&sz) < 0) { + ptr, &sz) < 0) { perror("getsockopt"); ret = -1; - } else if (sizeof(sz.s) != sizeof(sz.i) && sz.i == 0) { - OPENSSL_assert(sz.s <= sizeof(struct timeval)); - ret = (int)sz.s; - } else - ret = sz.i; + } else { + OPENSSL_assert(sz <= sizeof(struct timeval)); + ret = (int)sz; + } # endif } break; @@ -666,19 +645,14 @@ static long dgram_ctrl(BIO *b, int cmd, long num, void *ptr) break; case BIO_CTRL_DGRAM_GET_SEND_TIMEOUT: { - union { - size_t s; - int i; - } sz = { - 0 - }; # ifdef OPENSSL_SYS_WINDOWS + int sz = 0; int timeout; struct timeval *tv = (struct timeval *)ptr; - sz.i = sizeof(timeout); + sz = sizeof(timeout); if (getsockopt(b->num, SOL_SOCKET, SO_SNDTIMEO, - (void *)&timeout, &sz.i) < 0) { + (void *)&timeout, &sz) < 0) { perror("getsockopt"); ret = -1; } else { @@ -687,16 +661,15 @@ static long dgram_ctrl(BIO *b, int cmd, long num, void *ptr) ret = sizeof(*tv); } # else - sz.i = sizeof(struct timeval); + socklen_t sz = sizeof(struct timeval); if (getsockopt(b->num, SOL_SOCKET, SO_SNDTIMEO, - ptr, (void *)&sz) < 0) { + ptr, &sz) < 0) { perror("getsockopt"); ret = -1; - } else if (sizeof(sz.s) != sizeof(sz.i) && sz.i == 0) { - OPENSSL_assert(sz.s <= sizeof(struct timeval)); - ret = (int)sz.s; - } else - ret = sz.i; + } else { + OPENSSL_assert(sz <= sizeof(struct timeval)); + ret = (int)sz; + } # endif } break; @@ -780,7 +753,7 @@ static long dgram_ctrl(BIO *b, int cmd, long num, void *ptr) } break; case BIO_CTRL_DGRAM_GET_MTU_OVERHEAD: - ret = dgram_get_mtu_overhead(data); + ret = dgram_get_mtu_overhead(&data->peer); break; /* @@ -845,8 +818,8 @@ BIO *BIO_new_dgram_sctp(int fd, int close_flag) sizeof(struct sctp_authchunk)); if (ret < 0) { BIO_vfree(bio); - BIOerr(BIO_F_BIO_NEW_DGRAM_SCTP, ERR_R_SYS_LIB); - ERR_add_error_data(1, "Ensure SCTP AUTH chunks are enabled in kernel"); + ERR_raise_data(ERR_LIB_BIO, ERR_R_SYS_LIB, + "Ensure SCTP AUTH chunks are enabled in kernel"); return NULL; } auth.sauth_chunk = OPENSSL_SCTP_FORWARD_CUM_TSN_CHUNK_TYPE; @@ -855,8 +828,8 @@ BIO *BIO_new_dgram_sctp(int fd, int close_flag) sizeof(struct sctp_authchunk)); if (ret < 0) { BIO_vfree(bio); - BIOerr(BIO_F_BIO_NEW_DGRAM_SCTP, ERR_R_SYS_LIB); - ERR_add_error_data(1, "Ensure SCTP AUTH chunks are enabled in kernel"); + ERR_raise_data(ERR_LIB_BIO, ERR_R_SYS_LIB, + "Ensure SCTP AUTH chunks are enabled in kernel"); return NULL; } @@ -893,10 +866,9 @@ BIO *BIO_new_dgram_sctp(int fd, int close_flag) if (!auth_data || !auth_forward) { BIO_vfree(bio); - BIOerr(BIO_F_BIO_NEW_DGRAM_SCTP, ERR_R_SYS_LIB); - ERR_add_error_data(1, - "Ensure SCTP AUTH chunks are enabled on the " - "underlying socket"); + ERR_raise_data(ERR_LIB_BIO, ERR_R_SYS_LIB, + "Ensure SCTP AUTH chunks are enabled on the " + "underlying socket"); return NULL; } @@ -960,7 +932,7 @@ static int dgram_sctp_new(BIO *bi) bi->init = 0; bi->num = 0; if ((data = OPENSSL_zalloc(sizeof(*data))) == NULL) { - BIOerr(BIO_F_DGRAM_SCTP_NEW, ERR_R_MALLOC_FAILURE); + ERR_raise(ERR_LIB_BIO, ERR_R_MALLOC_FAILURE); return 0; } # ifdef SCTP_PR_SCTP_NONE @@ -1011,7 +983,6 @@ static int dgram_sctp_read(BIO *b, char *out, int outl) int ret = 0, n = 0, i, optval; socklen_t optlen; bio_dgram_sctp_data *data = (bio_dgram_sctp_data *) b->ptr; - union sctp_notification *snp; struct msghdr msg; struct iovec iov; struct cmsghdr *cmsg; @@ -1077,8 +1048,10 @@ static int dgram_sctp_read(BIO *b, char *out, int outl) } if (msg.msg_flags & MSG_NOTIFICATION) { - snp = (union sctp_notification *)out; - if (snp->sn_header.sn_type == SCTP_SENDER_DRY_EVENT) { + union sctp_notification snp; + + memcpy(&snp, out, sizeof(snp)); + if (snp.sn_header.sn_type == SCTP_SENDER_DRY_EVENT) { # ifdef SCTP_EVENT struct sctp_event event; # else @@ -1118,17 +1091,19 @@ static int dgram_sctp_read(BIO *b, char *out, int outl) # endif } # ifdef SCTP_AUTHENTICATION_EVENT - if (snp->sn_header.sn_type == SCTP_AUTHENTICATION_EVENT) - dgram_sctp_handle_auth_free_key_event(b, snp); + if (snp.sn_header.sn_type == SCTP_AUTHENTICATION_EVENT) + dgram_sctp_handle_auth_free_key_event(b, &snp); # endif if (data->handle_notifications != NULL) data->handle_notifications(b, data->notification_context, (void *)out); + memset(&snp, 0, sizeof(snp)); memset(out, 0, outl); - } else + } else { ret += n; + } } while ((msg.msg_flags & MSG_NOTIFICATION) && (msg.msg_flags & MSG_EOR) && (ret < outl)); @@ -1195,7 +1170,7 @@ static int dgram_sctp_read(BIO *b, char *out, int outl) (socklen_t) (sizeof(sctp_assoc_t) + 256 * sizeof(uint8_t)); authchunks = OPENSSL_malloc(optlen); if (authchunks == NULL) { - BIOerr(BIO_F_DGRAM_SCTP_READ, ERR_R_MALLOC_FAILURE); + ERR_raise(ERR_LIB_BIO, ERR_R_MALLOC_FAILURE); return -1; } memset(authchunks, 0, optlen); @@ -1215,7 +1190,7 @@ static int dgram_sctp_read(BIO *b, char *out, int outl) OPENSSL_free(authchunks); if (!auth_data || !auth_forward) { - BIOerr(BIO_F_DGRAM_SCTP_READ, BIO_R_CONNECT_ERROR); + ERR_raise(ERR_LIB_BIO, BIO_R_CONNECT_ERROR); return -1; } @@ -1566,6 +1541,10 @@ static long dgram_sctp_ctrl(BIO *b, int cmd, long num, void *ptr) else data->save_shutdown = 0; break; + case BIO_CTRL_DGRAM_SCTP_WAIT_FOR_DRY: + return dgram_sctp_wait_for_dry(b); + case BIO_CTRL_DGRAM_SCTP_MSG_WAITING: + return dgram_sctp_msg_waiting(b); default: /* @@ -1578,11 +1557,8 @@ static long dgram_sctp_ctrl(BIO *b, int cmd, long num, void *ptr) } int BIO_dgram_sctp_notification_cb(BIO *b, - void (*handle_notifications) (BIO *bio, - void - *context, - void *buf), - void *context) + BIO_dgram_sctp_notification_handler_fn handle_notifications, + void *context) { bio_dgram_sctp_data *data = (bio_dgram_sctp_data *) b->ptr; @@ -1610,6 +1586,11 @@ int BIO_dgram_sctp_notification_cb(BIO *b, */ int BIO_dgram_sctp_wait_for_dry(BIO *b) { + return (int)BIO_ctrl(b, BIO_CTRL_DGRAM_SCTP_WAIT_FOR_DRY, 0, NULL); +} + +static int dgram_sctp_wait_for_dry(BIO *b) +{ int is_dry = 0; int sockflags = 0; int n, ret; @@ -1768,6 +1749,11 @@ int BIO_dgram_sctp_wait_for_dry(BIO *b) int BIO_dgram_sctp_msg_waiting(BIO *b) { + return (int)BIO_ctrl(b, BIO_CTRL_DGRAM_SCTP_MSG_WAITING, 0, NULL); +} + +static int dgram_sctp_msg_waiting(BIO *b) +{ int n, sockflags; union sctp_notification snp; struct msghdr msg; @@ -1907,22 +1893,22 @@ static void get_current_time(struct timeval *t) { # if defined(_WIN32) SYSTEMTIME st; - union { - unsigned __int64 ul; - FILETIME ft; - } now; + unsigned __int64 now_ul; + FILETIME now_ft; GetSystemTime(&st); - SystemTimeToFileTime(&st, &now.ft); + SystemTimeToFileTime(&st, &now_ft); + now_ul = ((unsigned __int64)now_ft.dwHighDateTime << 32) | now_ft.dwLowDateTime; # ifdef __MINGW32__ - now.ul -= 116444736000000000ULL; + now_ul -= 116444736000000000ULL; # else - now.ul -= 116444736000000000UI64; /* re-bias to 1/1/1970 */ + now_ul -= 116444736000000000UI64; /* re-bias to 1/1/1970 */ # endif - t->tv_sec = (long)(now.ul / 10000000); - t->tv_usec = ((int)(now.ul % 10000000)) / 10; + t->tv_sec = (long)(now_ul / 10000000); + t->tv_usec = ((int)(now_ul % 10000000)) / 10; # else - gettimeofday(t, NULL); + if (gettimeofday(t, NULL) < 0) + perror("gettimeofday"); # endif } diff --git a/crypto/bio/bss_fd.c b/crypto/bio/bss_fd.c index ccbe1626baf2..f756225edb21 100644 --- a/crypto/bio/bss_fd.c +++ b/crypto/bio/bss_fd.c @@ -1,7 +1,7 @@ /* - * Copyright 1995-2020 The OpenSSL Project Authors. All Rights Reserved. + * Copyright 1995-2021 The OpenSSL Project Authors. All Rights Reserved. * - * Licensed under the OpenSSL license (the "License"). You may not use + * 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 * in the file LICENSE in the source distribution or at * https://www.openssl.org/source/license.html @@ -60,10 +60,8 @@ int BIO_fd_should_retry(int s); static const BIO_METHOD methods_fdp = { BIO_TYPE_FD, "file descriptor", - /* TODO: Convert to new style write function */ bwrite_conv, fd_write, - /* TODO: Convert to new style read function */ bread_conv, fd_read, fd_puts, @@ -94,7 +92,7 @@ static int fd_new(BIO *bi) bi->init = 0; bi->num = -1; bi->ptr = NULL; - bi->flags = BIO_FLAGS_UPLINK; /* essentially redundant */ + bi->flags = BIO_FLAGS_UPLINK_INTERNAL; /* essentially redundant */ return 1; } @@ -107,7 +105,7 @@ static int fd_free(BIO *a) UP_close(a->num); } a->init = 0; - a->flags = BIO_FLAGS_UPLINK; + a->flags = BIO_FLAGS_UPLINK_INTERNAL; } return 1; } @@ -189,7 +187,7 @@ static long fd_ctrl(BIO *b, int cmd, long num, void *ptr) ret = 1; break; case BIO_CTRL_EOF: - ret = (b->flags & BIO_FLAGS_IN_EOF) != 0 ? 1 : 0; + ret = (b->flags & BIO_FLAGS_IN_EOF) != 0; break; default: ret = 0; diff --git a/crypto/bio/bss_file.c b/crypto/bio/bss_file.c index 1a70ce799404..0c57c1bfb474 100644 --- a/crypto/bio/bss_file.c +++ b/crypto/bio/bss_file.c @@ -1,7 +1,7 @@ /* - * Copyright 1995-2019 The OpenSSL Project Authors. All Rights Reserved. + * Copyright 1995-2025 The OpenSSL Project Authors. All Rights Reserved. * - * Licensed under the OpenSSL license (the "License"). You may not use + * 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 * in the file LICENSE in the source distribution or at * https://www.openssl.org/source/license.html @@ -42,10 +42,8 @@ static int file_free(BIO *data); static const BIO_METHOD methods_filep = { BIO_TYPE_FILE, "FILE pointer", - /* TODO: Convert to new style write function */ bwrite_conv, file_write, - /* TODO: Convert to new style read function */ bread_conv, file_read, file_puts, @@ -66,16 +64,17 @@ BIO *BIO_new_file(const char *filename, const char *mode) fp_flags |= BIO_FP_TEXT; if (file == NULL) { - SYSerr(SYS_F_FOPEN, get_last_sys_error()); - ERR_add_error_data(5, "fopen('", filename, "','", mode, "')"); + ERR_raise_data(ERR_LIB_SYS, get_last_sys_error(), + "calling fopen(%s, %s)", + filename, mode); if (errno == ENOENT #ifdef ENXIO || errno == ENXIO #endif ) - BIOerr(BIO_F_BIO_NEW_FILE, BIO_R_NO_SUCH_FILE); + ERR_raise(ERR_LIB_BIO, BIO_R_NO_SUCH_FILE); else - BIOerr(BIO_F_BIO_NEW_FILE, ERR_R_SYS_LIB); + ERR_raise(ERR_LIB_BIO, ERR_R_SYS_LIB); return NULL; } if ((ret = BIO_new(BIO_s_file())) == NULL) { @@ -83,8 +82,8 @@ BIO *BIO_new_file(const char *filename, const char *mode) return NULL; } - BIO_clear_flags(ret, BIO_FLAGS_UPLINK); /* we did fopen -> we disengage - * UPLINK */ + /* we did fopen -> we disengage UPLINK */ + BIO_clear_flags(ret, BIO_FLAGS_UPLINK_INTERNAL); BIO_set_fp(ret, file, fp_flags); return ret; } @@ -97,7 +96,7 @@ BIO *BIO_new_fp(FILE *stream, int close_flag) return NULL; /* redundant flag, left for documentation purposes */ - BIO_set_flags(ret, BIO_FLAGS_UPLINK); + BIO_set_flags(ret, BIO_FLAGS_UPLINK_INTERNAL); BIO_set_fp(ret, stream, close_flag); return ret; } @@ -112,7 +111,7 @@ static int file_new(BIO *bi) bi->init = 0; bi->num = 0; bi->ptr = NULL; - bi->flags = BIO_FLAGS_UPLINK; /* default to UPLINK */ + bi->flags = BIO_FLAGS_UPLINK_INTERNAL; /* default to UPLINK */ return 1; } @@ -122,12 +121,12 @@ static int file_free(BIO *a) return 0; if (a->shutdown) { if ((a->init) && (a->ptr != NULL)) { - if (a->flags & BIO_FLAGS_UPLINK) + if (a->flags & BIO_FLAGS_UPLINK_INTERNAL) UP_fclose(a->ptr); else fclose(a->ptr); a->ptr = NULL; - a->flags = BIO_FLAGS_UPLINK; + a->flags = BIO_FLAGS_UPLINK_INTERNAL; } a->init = 0; } @@ -139,15 +138,16 @@ static int file_read(BIO *b, char *out, int outl) int ret = 0; if (b->init && (out != NULL)) { - if (b->flags & BIO_FLAGS_UPLINK) + if (b->flags & BIO_FLAGS_UPLINK_INTERNAL) ret = UP_fread(out, 1, (int)outl, b->ptr); else ret = fread(out, 1, (int)outl, (FILE *)b->ptr); if (ret == 0 - && (b->flags & BIO_FLAGS_UPLINK) ? UP_ferror((FILE *)b->ptr) : - ferror((FILE *)b->ptr)) { - SYSerr(SYS_F_FREAD, get_last_sys_error()); - BIOerr(BIO_F_FILE_READ, ERR_R_SYS_LIB); + && (b->flags & BIO_FLAGS_UPLINK_INTERNAL + ? UP_ferror((FILE *)b->ptr) : ferror((FILE *)b->ptr))) { + ERR_raise_data(ERR_LIB_SYS, get_last_sys_error(), + "calling fread()"); + ERR_raise(ERR_LIB_BIO, ERR_R_SYS_LIB); ret = -1; } } @@ -159,7 +159,7 @@ static int file_write(BIO *b, const char *in, int inl) int ret = 0; if (b->init && (in != NULL)) { - if (b->flags & BIO_FLAGS_UPLINK) + if (b->flags & BIO_FLAGS_UPLINK_INTERNAL) ret = UP_fwrite(in, (int)inl, 1, b->ptr); else ret = fwrite(in, (int)inl, 1, (FILE *)b->ptr); @@ -186,20 +186,20 @@ static long file_ctrl(BIO *b, int cmd, long num, void *ptr) switch (cmd) { case BIO_C_FILE_SEEK: case BIO_CTRL_RESET: - if (b->flags & BIO_FLAGS_UPLINK) + if (b->flags & BIO_FLAGS_UPLINK_INTERNAL) ret = (long)UP_fseek(b->ptr, num, 0); else ret = (long)fseek(fp, num, 0); break; case BIO_CTRL_EOF: - if (b->flags & BIO_FLAGS_UPLINK) + if (b->flags & BIO_FLAGS_UPLINK_INTERNAL) ret = (long)UP_feof(fp); else ret = (long)feof(fp); break; case BIO_C_FILE_TELL: case BIO_CTRL_INFO: - if (b->flags & BIO_FLAGS_UPLINK) + if (b->flags & BIO_FLAGS_UPLINK_INTERNAL) ret = UP_ftell(b->ptr); else ret = ftell(fp); @@ -209,22 +209,22 @@ static long file_ctrl(BIO *b, int cmd, long num, void *ptr) b->shutdown = (int)num & BIO_CLOSE; b->ptr = ptr; b->init = 1; -# if BIO_FLAGS_UPLINK!=0 +# if BIO_FLAGS_UPLINK_INTERNAL!=0 # if defined(__MINGW32__) && defined(__MSVCRT__) && !defined(_IOB_ENTRIES) # define _IOB_ENTRIES 20 # endif /* Safety net to catch purely internal BIO_set_fp calls */ -# if defined(_MSC_VER) && _MSC_VER>=1900 +# if (defined(_MSC_VER) && _MSC_VER>=1900) || defined(__BORLANDC__) if (ptr == stdin || ptr == stdout || ptr == stderr) - BIO_clear_flags(b, BIO_FLAGS_UPLINK); + BIO_clear_flags(b, BIO_FLAGS_UPLINK_INTERNAL); # elif defined(_IOB_ENTRIES) if ((size_t)ptr >= (size_t)stdin && (size_t)ptr < (size_t)(stdin + _IOB_ENTRIES)) - BIO_clear_flags(b, BIO_FLAGS_UPLINK); + BIO_clear_flags(b, BIO_FLAGS_UPLINK_INTERNAL); # endif # endif # ifdef UP_fsetmod - if (b->flags & BIO_FLAGS_UPLINK) + if (b->flags & BIO_FLAGS_UPLINK_INTERNAL) UP_fsetmod(b->ptr, (char)((num & BIO_FP_TEXT) ? 't' : 'b')); else # endif @@ -235,6 +235,15 @@ static long file_ctrl(BIO *b, int cmd, long num, void *ptr) _setmode(fd, _O_TEXT); else _setmode(fd, _O_BINARY); + /* + * Reports show that ftell() isn't trustable in text mode. + * This has been confirmed as a bug in the Universal C RTL, see + * https://developercommunity.visualstudio.com/content/problem/425878/fseek-ftell-fail-in-text-mode-for-unix-style-text.html + * The suggested work-around from Microsoft engineering is to + * turn off buffering until the bug is resolved. + */ + if ((num & BIO_FP_TEXT) != 0) + setvbuf((FILE *)ptr, NULL, _IONBF, 0); # elif defined(OPENSSL_SYS_MSDOS) int fd = fileno((FILE *)ptr); /* Set correct text/binary mode */ @@ -270,7 +279,7 @@ static long file_ctrl(BIO *b, int cmd, long num, void *ptr) else if (num & BIO_FP_READ) OPENSSL_strlcpy(p, "r", sizeof(p)); else { - BIOerr(BIO_F_FILE_CTRL, BIO_R_BAD_FOPEN_MODE); + ERR_raise(ERR_LIB_BIO, BIO_R_BAD_FOPEN_MODE); ret = 0; break; } @@ -285,16 +294,17 @@ static long file_ctrl(BIO *b, int cmd, long num, void *ptr) # endif fp = openssl_fopen(ptr, p); if (fp == NULL) { - SYSerr(SYS_F_FOPEN, get_last_sys_error()); - ERR_add_error_data(5, "fopen('", ptr, "','", p, "')"); - BIOerr(BIO_F_FILE_CTRL, ERR_R_SYS_LIB); + ERR_raise_data(ERR_LIB_SYS, get_last_sys_error(), + "calling fopen(%s, %s)", + (const char *)ptr, p); + ERR_raise(ERR_LIB_BIO, ERR_R_SYS_LIB); ret = 0; break; } b->ptr = fp; b->init = 1; - BIO_clear_flags(b, BIO_FLAGS_UPLINK); /* we did fopen -> we disengage - * UPLINK */ + /* we did fopen -> we disengage UPLINK */ + BIO_clear_flags(b, BIO_FLAGS_UPLINK_INTERNAL); break; case BIO_C_GET_FILE_PTR: /* the ptr parameter is actually a FILE ** in this case. */ @@ -310,12 +320,12 @@ static long file_ctrl(BIO *b, int cmd, long num, void *ptr) b->shutdown = (int)num; break; case BIO_CTRL_FLUSH: - st = b->flags & BIO_FLAGS_UPLINK + st = b->flags & BIO_FLAGS_UPLINK_INTERNAL ? UP_fflush(b->ptr) : fflush((FILE *)b->ptr); if (st == EOF) { - SYSerr(SYS_F_FFLUSH, get_last_sys_error()); - ERR_add_error_data(1, "fflush()"); - BIOerr(BIO_F_FILE_CTRL, ERR_R_SYS_LIB); + ERR_raise_data(ERR_LIB_SYS, get_last_sys_error(), + "calling fflush()"); + ERR_raise(ERR_LIB_BIO, ERR_R_SYS_LIB); ret = 0; } break; @@ -339,7 +349,7 @@ static int file_gets(BIO *bp, char *buf, int size) int ret = 0; buf[0] = '\0'; - if (bp->flags & BIO_FLAGS_UPLINK) { + if (bp->flags & BIO_FLAGS_UPLINK_INTERNAL) { if (!UP_fgets(buf, size, bp->ptr)) goto err; } else { @@ -395,10 +405,8 @@ static int file_free(BIO *a) static const BIO_METHOD methods_filep = { BIO_TYPE_FILE, "FILE pointer", - /* TODO: Convert to new style write function */ bwrite_conv, file_write, - /* TODO: Convert to new style read function */ bread_conv, file_read, file_puts, diff --git a/crypto/bio/bss_log.c b/crypto/bio/bss_log.c index b9579faaa2a5..63b30e300fec 100644 --- a/crypto/bio/bss_log.c +++ b/crypto/bio/bss_log.c @@ -1,7 +1,7 @@ /* - * Copyright 1999-2018 The OpenSSL Project Authors. All Rights Reserved. + * Copyright 1999-2021 The OpenSSL Project Authors. All Rights Reserved. * - * Licensed under the OpenSSL license (the "License"). You may not use + * 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 * in the file LICENSE in the source distribution or at * https://www.openssl.org/source/license.html @@ -87,7 +87,6 @@ static void xcloselog(BIO *bp); static const BIO_METHOD methods_slg = { BIO_TYPE_MEM, "syslog", - /* TODO: Convert to new style write function */ bwrite_conv, slg_write, NULL, /* slg_write_old, */ @@ -196,8 +195,10 @@ static int slg_write(BIO *b, const char *in, int inl) /* The default */ }; + if (inl < 0) + return 0; if ((buf = OPENSSL_malloc(inl + 1)) == NULL) { - BIOerr(BIO_F_SLG_WRITE, ERR_R_MALLOC_FAILURE); + ERR_raise(ERR_LIB_BIO, ERR_R_MALLOC_FAILURE); return 0; } memcpy(buf, in, inl); @@ -280,7 +281,7 @@ static void xsyslog(BIO *bp, int priority, const char *string) break; } - sprintf(pidbuf, "[%lu] ", GetCurrentProcessId()); + BIO_snprintf(pidbuf, sizeof(pidbuf), "[%lu] ", GetCurrentProcessId()); lpszStrings[0] = pidbuf; lpszStrings[1] = string; diff --git a/crypto/bio/bss_mem.c b/crypto/bio/bss_mem.c index 2420b26553e0..9153c1f1cd81 100644 --- a/crypto/bio/bss_mem.c +++ b/crypto/bio/bss_mem.c @@ -1,7 +1,7 @@ /* * Copyright 1995-2021 The OpenSSL Project Authors. All Rights Reserved. * - * Licensed under the OpenSSL license (the "License"). You may not use + * 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 * in the file LICENSE in the source distribution or at * https://www.openssl.org/source/license.html @@ -26,10 +26,8 @@ static int mem_buf_sync(BIO *h); static const BIO_METHOD mem_method = { BIO_TYPE_MEM, "memory buffer", - /* TODO: Convert to new style write function */ bwrite_conv, mem_write, - /* TODO: Convert to new style read function */ bread_conv, mem_read, mem_puts, @@ -43,10 +41,8 @@ static const BIO_METHOD mem_method = { static const BIO_METHOD secmem_method = { BIO_TYPE_MEM, "secure memory buffer", - /* TODO: Convert to new style write function */ bwrite_conv, mem_write, - /* TODO: Convert to new style read function */ bread_conv, mem_read, mem_puts, @@ -91,7 +87,7 @@ BIO *BIO_new_mem_buf(const void *buf, int len) size_t sz; if (buf == NULL) { - BIOerr(BIO_F_BIO_NEW_MEM_BUF, BIO_R_NULL_PARAMETER); + ERR_raise(ERR_LIB_BIO, ERR_R_PASSED_NULL_PARAMETER); return NULL; } sz = (len < 0) ? strlen(buf) : (size_t)len; @@ -176,6 +172,7 @@ static int mem_buf_free(BIO *a) /* * Reallocate memory buffer if read pointer differs + * NOT FOR RDONLY */ static int mem_buf_sync(BIO *b) { @@ -220,17 +217,17 @@ static int mem_write(BIO *b, const char *in, int inl) int blen; BIO_BUF_MEM *bbm = (BIO_BUF_MEM *)b->ptr; - if (in == NULL) { - BIOerr(BIO_F_MEM_WRITE, BIO_R_NULL_PARAMETER); - goto end; - } if (b->flags & BIO_FLAGS_MEM_RDONLY) { - BIOerr(BIO_F_MEM_WRITE, BIO_R_WRITE_TO_READ_ONLY_BIO); + ERR_raise(ERR_LIB_BIO, BIO_R_WRITE_TO_READ_ONLY_BIO); goto end; } BIO_clear_retry_flags(b); if (inl == 0) return 0; + if (in == NULL) { + ERR_raise(ERR_LIB_BIO, ERR_R_PASSED_NULL_PARAMETER); + goto end; + } blen = bbm->readp->length; mem_buf_sync(b); if (BUF_MEM_grow_clean(bbm->buf, blen + inl) == 0) @@ -247,12 +244,18 @@ static long mem_ctrl(BIO *b, int cmd, long num, void *ptr) long ret = 1; char **pptr; BIO_BUF_MEM *bbm = (BIO_BUF_MEM *)b->ptr; - BUF_MEM *bm; + BUF_MEM *bm, *bo; /* bio_mem, bio_other */ + long off, remain; - if (b->flags & BIO_FLAGS_MEM_RDONLY) + if (b->flags & BIO_FLAGS_MEM_RDONLY) { bm = bbm->buf; - else + bo = bbm->readp; + } else { bm = bbm->readp; + bo = bbm->buf; + } + off = (bm->data == bo->data) ? 0 : bm->data - bo->data; + remain = bm->length; switch (cmd) { case BIO_CTRL_RESET: @@ -270,6 +273,18 @@ static long mem_ctrl(BIO *b, int cmd, long num, void *ptr) } } break; + case BIO_C_FILE_SEEK: + if (num < 0 || num > off + remain) + return -1; /* Can't see outside of the current buffer */ + + bm->data = (num != 0) ? bo->data + num : bo->data; + bm->length = bo->length - num; + bm->max = bo->max - num; + off = num; + /* FALLTHRU */ + case BIO_C_FILE_TELL: + ret = off; + break; case BIO_CTRL_EOF: ret = (long)(bm->length == 0); break; @@ -280,7 +295,7 @@ static long mem_ctrl(BIO *b, int cmd, long num, void *ptr) ret = (long)bm->length; if (ptr != NULL) { pptr = (char **)ptr; - *pptr = (char *)bm->data; + *pptr = (char *)(bm->data); } break; case BIO_C_SET_BUF_MEM: diff --git a/crypto/bio/bss_null.c b/crypto/bio/bss_null.c index e73ce7841d41..ba266f186c21 100644 --- a/crypto/bio/bss_null.c +++ b/crypto/bio/bss_null.c @@ -1,7 +1,7 @@ /* - * Copyright 1995-2018 The OpenSSL Project Authors. All Rights Reserved. + * Copyright 1995-2021 The OpenSSL Project Authors. All Rights Reserved. * - * Licensed under the OpenSSL license (the "License"). You may not use + * 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 * in the file LICENSE in the source distribution or at * https://www.openssl.org/source/license.html @@ -20,10 +20,8 @@ static long null_ctrl(BIO *h, int cmd, long arg1, void *arg2); static const BIO_METHOD null_method = { BIO_TYPE_NULL, "NULL", - /* TODO: Convert to new style write function */ bwrite_conv, null_write, - /* TODO: Convert to new style read function */ bread_conv, null_read, null_puts, diff --git a/crypto/bio/bss_sock.c b/crypto/bio/bss_sock.c index 6251f3d46a17..f5d88102303a 100644 --- a/crypto/bio/bss_sock.c +++ b/crypto/bio/bss_sock.c @@ -1,7 +1,7 @@ /* - * Copyright 1995-2020 The OpenSSL Project Authors. All Rights Reserved. + * Copyright 1995-2021 The OpenSSL Project Authors. All Rights Reserved. * - * Licensed under the OpenSSL license (the "License"). You may not use + * 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 * in the file LICENSE in the source distribution or at * https://www.openssl.org/source/license.html @@ -11,6 +11,7 @@ #include <errno.h> #include "bio_local.h" #include "internal/cryptlib.h" +#include "internal/ktls.h" #ifndef OPENSSL_NO_SOCK @@ -37,10 +38,8 @@ int BIO_sock_should_retry(int s); static const BIO_METHOD methods_sockp = { BIO_TYPE_SOCKET, "socket", - /* TODO: Convert to new style write function */ bwrite_conv, sock_write, - /* TODO: Convert to new style read function */ bread_conv, sock_read, sock_puts, @@ -64,6 +63,17 @@ BIO *BIO_new_socket(int fd, int close_flag) if (ret == NULL) return NULL; BIO_set_fd(ret, fd, close_flag); +# ifndef OPENSSL_NO_KTLS + { + /* + * The new socket is created successfully regardless of ktls_enable. + * ktls_enable doesn't change any functionality of the socket, except + * changing the setsockopt to enable the processing of ktls_start. + * Thus, it is not a problem to call it for non-TLS sockets. + */ + ktls_enable(fd); + } +# endif return ret; } @@ -96,7 +106,12 @@ static int sock_read(BIO *b, char *out, int outl) if (out != NULL) { clear_socket_error(); - ret = readsocket(b->num, out, outl); +# ifndef OPENSSL_NO_KTLS + if (BIO_get_ktls_recv(b)) + ret = ktls_read_record(b->num, out, outl); + else +# endif + ret = readsocket(b->num, out, outl); BIO_clear_retry_flags(b); if (ret <= 0) { if (BIO_sock_should_retry(ret)) @@ -110,10 +125,20 @@ static int sock_read(BIO *b, char *out, int outl) static int sock_write(BIO *b, const char *in, int inl) { - int ret; + int ret = 0; clear_socket_error(); - ret = writesocket(b->num, in, inl); +# ifndef OPENSSL_NO_KTLS + if (BIO_should_ktls_ctrl_msg_flag(b)) { + unsigned char record_type = (intptr_t)b->ptr; + ret = ktls_send_ctrl_message(b->num, record_type, in, inl); + if (ret >= 0) { + ret = inl; + BIO_clear_ktls_ctrl_msg_flag(b); + } + } else +# endif + ret = writesocket(b->num, in, inl); BIO_clear_retry_flags(b); if (ret <= 0) { if (BIO_sock_should_retry(ret)) @@ -126,6 +151,9 @@ static long sock_ctrl(BIO *b, int cmd, long num, void *ptr) { long ret = 1; int *ip; +# ifndef OPENSSL_NO_KTLS + ktls_crypto_info_t *crypto_info; +# endif switch (cmd) { case BIO_C_SET_FD: @@ -153,8 +181,29 @@ static long sock_ctrl(BIO *b, int cmd, long num, void *ptr) case BIO_CTRL_FLUSH: ret = 1; break; +# ifndef OPENSSL_NO_KTLS + case BIO_CTRL_SET_KTLS: + crypto_info = (ktls_crypto_info_t *)ptr; + ret = ktls_start(b->num, crypto_info, num); + if (ret) + BIO_set_ktls_flag(b, num); + break; + case BIO_CTRL_GET_KTLS_SEND: + return BIO_should_ktls_flag(b, 1) != 0; + case BIO_CTRL_GET_KTLS_RECV: + return BIO_should_ktls_flag(b, 0) != 0; + case BIO_CTRL_SET_KTLS_TX_SEND_CTRL_MSG: + BIO_set_ktls_ctrl_msg_flag(b); + b->ptr = (void *)num; + ret = 0; + break; + case BIO_CTRL_CLEAR_KTLS_TX_CTRL_MSG: + BIO_clear_ktls_ctrl_msg_flag(b); + ret = 0; + break; +# endif case BIO_CTRL_EOF: - ret = (b->flags & BIO_FLAGS_IN_EOF) != 0 ? 1 : 0; + ret = (b->flags & BIO_FLAGS_IN_EOF) != 0; break; default: ret = 0; diff --git a/crypto/bio/build.info b/crypto/bio/build.info index d1e7d73c5509..b203ed5e63fe 100644 --- a/crypto/bio/build.info +++ b/crypto/bio/build.info @@ -1,8 +1,18 @@ LIBS=../../libcrypto + +# Base library SOURCE[../../libcrypto]=\ bio_lib.c bio_cb.c bio_err.c \ - bss_mem.c bss_null.c bss_fd.c \ - bss_file.c bss_sock.c bss_conn.c \ - bf_null.c bf_buff.c b_print.c b_dump.c b_addr.c \ - b_sock.c b_sock2.c bss_acpt.c bf_nbio.c bss_log.c bss_bio.c \ - bss_dgram.c bio_meth.c bf_lbuf.c + bio_print.c bio_dump.c bio_addr.c \ + bio_sock.c bio_sock2.c \ + bio_meth.c ossl_core_bio.c + +# Source / sink implementations +SOURCE[../../libcrypto]=\ + bss_null.c bss_mem.c bss_bio.c bss_fd.c bss_file.c \ + bss_sock.c bss_conn.c bss_acpt.c bss_dgram.c \ + bss_log.c bss_core.c + +# Filters +SOURCE[../../libcrypto]=\ + bf_null.c bf_buff.c bf_lbuf.c bf_nbio.c bf_prefix.c bf_readbuff.c diff --git a/crypto/bio/ossl_core_bio.c b/crypto/bio/ossl_core_bio.c new file mode 100644 index 000000000000..328302ea34e6 --- /dev/null +++ b/crypto/bio/ossl_core_bio.c @@ -0,0 +1,124 @@ +/* + * Copyright 2021 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 + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html + */ + +#include <openssl/core.h> +#include "bio_local.h" + +/*- + * Core BIO structure + * This is distinct from a BIO to prevent casting between the two which could + * lead to versioning problems. + */ +struct ossl_core_bio_st { + CRYPTO_REF_COUNT ref_cnt; + CRYPTO_RWLOCK *ref_lock; + BIO *bio; +}; + +static OSSL_CORE_BIO *core_bio_new(void) +{ + OSSL_CORE_BIO *cb = OPENSSL_malloc(sizeof(*cb)); + + if (cb == NULL || (cb->ref_lock = CRYPTO_THREAD_lock_new()) == NULL) { + OPENSSL_free(cb); + return NULL; + } + cb->ref_cnt = 1; + return cb; +} + +int ossl_core_bio_up_ref(OSSL_CORE_BIO *cb) +{ + int ref = 0; + + return CRYPTO_UP_REF(&cb->ref_cnt, &ref, cb->ref_lock); +} + +int ossl_core_bio_free(OSSL_CORE_BIO *cb) +{ + int ref = 0, res = 1; + + if (cb != NULL) { + CRYPTO_DOWN_REF(&cb->ref_cnt, &ref, cb->ref_lock); + if (ref <= 0) { + res = BIO_free(cb->bio); + CRYPTO_THREAD_lock_free(cb->ref_lock); + OPENSSL_free(cb); + } + } + return res; +} + +OSSL_CORE_BIO *ossl_core_bio_new_from_bio(BIO *bio) +{ + OSSL_CORE_BIO *cb = core_bio_new(); + + if (cb == NULL || !BIO_up_ref(bio)) { + ossl_core_bio_free(cb); + return NULL; + } + cb->bio = bio; + return cb; +} + +static OSSL_CORE_BIO *core_bio_new_from_new_bio(BIO *bio) +{ + OSSL_CORE_BIO *cb = NULL; + + if (bio == NULL) + return NULL; + if ((cb = core_bio_new()) == NULL) { + BIO_free(bio); + return NULL; + } + cb->bio = bio; + return cb; +} + +OSSL_CORE_BIO *ossl_core_bio_new_file(const char *filename, const char *mode) +{ + return core_bio_new_from_new_bio(BIO_new_file(filename, mode)); +} + +OSSL_CORE_BIO *ossl_core_bio_new_mem_buf(const void *buf, int len) +{ + return core_bio_new_from_new_bio(BIO_new_mem_buf(buf, len)); +} + +int ossl_core_bio_read_ex(OSSL_CORE_BIO *cb, void *data, size_t dlen, + size_t *readbytes) +{ + return BIO_read_ex(cb->bio, data, dlen, readbytes); +} + +int ossl_core_bio_write_ex(OSSL_CORE_BIO *cb, const void *data, size_t dlen, + size_t *written) +{ + return BIO_write_ex(cb->bio, data, dlen, written); +} + +int ossl_core_bio_gets(OSSL_CORE_BIO *cb, char *buf, int size) +{ + return BIO_gets(cb->bio, buf, size); +} + +int ossl_core_bio_puts(OSSL_CORE_BIO *cb, const char *buf) +{ + return BIO_puts(cb->bio, buf); +} + +long ossl_core_bio_ctrl(OSSL_CORE_BIO *cb, int cmd, long larg, void *parg) +{ + return BIO_ctrl(cb->bio, cmd, larg, parg); +} + +int ossl_core_bio_vprintf(OSSL_CORE_BIO *cb, const char *format, va_list args) +{ + return BIO_vprintf(cb->bio, format, args); +} |