diff options
-rw-r--r-- | .gitignore | 1 | ||||
-rw-r--r-- | LIBTLS_VERSION | 2 | ||||
-rw-r--r-- | Makefile.am | 10 | ||||
-rw-r--r-- | Makefile.am.common | 4 | ||||
-rw-r--r-- | VERSION | 2 | ||||
-rw-r--r-- | compat/arc4random.c | 10 | ||||
-rw-r--r-- | compat/getentropy_aix.c | 4 | ||||
-rw-r--r-- | compat/posix_win.c | 113 | ||||
-rw-r--r-- | empty.c | 0 | ||||
-rw-r--r-- | include/compat/sys/socket.h | 1 | ||||
-rw-r--r-- | include/compat/sys/types.h | 12 | ||||
-rw-r--r-- | include/compat/unistd.h | 4 | ||||
-rw-r--r-- | include/tls.h | 34 | ||||
-rw-r--r-- | man/tls_config_set_protocols.3 | 12 | ||||
-rw-r--r-- | tls.c | 46 | ||||
-rw-r--r-- | tls.sym | 7 | ||||
-rw-r--r-- | tls_bio_cb.c | 2 | ||||
-rw-r--r-- | tls_client.c | 2 | ||||
-rw-r--r-- | tls_config.c | 6 | ||||
-rw-r--r-- | tls_conninfo.c | 2 | ||||
-rw-r--r-- | tls_internal.h | 27 | ||||
-rw-r--r-- | tls_ocsp.c | 4 | ||||
-rw-r--r-- | tls_server.c | 4 | ||||
-rw-r--r-- | tls_signer.c | 19 | ||||
-rw-r--r-- | tls_util.c | 2 | ||||
-rw-r--r-- | tls_verify.c | 121 |
26 files changed, 296 insertions, 155 deletions
diff --git a/.gitignore b/.gitignore index 55f559c..5acc290 100644 --- a/.gitignore +++ b/.gitignore @@ -13,6 +13,7 @@ /configure /depcomp /install-sh +/libtls_la_objects.mk /libtls.pc /libtool /ltmain.sh diff --git a/LIBTLS_VERSION b/LIBTLS_VERSION index 27179fd..fd02cce 100644 --- a/LIBTLS_VERSION +++ b/LIBTLS_VERSION @@ -1 +1 @@ -24:1:0 +28:0:0 diff --git a/Makefile.am b/Makefile.am index 69a8133..bfcf55e 100644 --- a/Makefile.am +++ b/Makefile.am @@ -13,6 +13,16 @@ EXTRA_DIST += LIBTLS_VERSION EXTRA_DIST += tls.sym EXTRA_DIST += README.7 EXTRA_DIST += scripts +EXTRA_DIST += empty.c + +CLEANFILES = libtls_la_objects.mk + +EXTRA_libtls_la_DEPENDENCIES = libtls_la_objects.mk + +libtls_la_objects.mk: Makefile + @echo "libtls_la_objects= $(libtls_la_OBJECTS)" \ + | sed -e 's/ *$$//' -e 's/ */ $$\(abs_top_builddir\)\/tls\//g' \ + > libtls_la_objects.mk libtls_la_LDFLAGS = -version-info @LIBTLS_VERSION@ -no-undefined -export-symbols $(top_srcdir)/tls.sym libtls_la_LDFLAGS += $(OPENSSL_LDFLAGS) diff --git a/Makefile.am.common b/Makefile.am.common index 87aa807..5405704 100644 --- a/Makefile.am.common +++ b/Makefile.am.common @@ -1,3 +1,5 @@ AM_CFLAGS = -AM_CPPFLAGS = -I$(top_srcdir)/include -I$(top_srcdir)/include/compat -DLIBRESSL_INTERNAL +AM_CPPFLAGS = -I$(top_srcdir)/include +AM_CPPFLAGS += -I$(abs_top_builddir)/include +AM_CPPFLAGS += -I$(top_srcdir)/include/compat -DLIBRESSL_INTERNAL AM_CPPFLAGS += -D__BEGIN_HIDDEN_DECLS= -D__END_HIDDEN_DECLS= diff --git a/VERSION b/VERSION index 6f711e8..1693986 100644 --- a/VERSION +++ b/VERSION @@ -1,2 +1,2 @@ -3.5.1 +3.8.1 diff --git a/compat/arc4random.c b/compat/arc4random.c index 6f95d57..1ec8e1e 100644 --- a/compat/arc4random.c +++ b/compat/arc4random.c @@ -1,4 +1,4 @@ -/* $OpenBSD: arc4random.c,v 1.56 2022/02/28 21:56:29 dtucker Exp $ */ +/* $OpenBSD: arc4random.c,v 1.58 2022/07/31 13:41:45 tb Exp $ */ /* * Copyright (c) 1996, David Mazieres <dm@uun.org> @@ -49,6 +49,8 @@ #define BLOCKSZ 64 #define RSBUFSZ (16*BLOCKSZ) +#define REKEY_BASE (1024*1024) /* NB. should be a power of 2 */ + /* Marked MAP_INHERIT_ZERO, so zero'd out in fork children. */ static struct _rs { size_t rs_have; /* valid bytes at end of rs_buf */ @@ -86,6 +88,7 @@ static void _rs_stir(void) { u_char rnd[KEYSZ + IVSZ]; + uint32_t rekey_fuzz = 0; if (getentropy(rnd, sizeof rnd) == -1) _getentropy_fail(); @@ -100,7 +103,10 @@ _rs_stir(void) rs->rs_have = 0; memset(rsx->rs_buf, 0, sizeof(rsx->rs_buf)); - rs->rs_count = 1600000; + /* rekey interval should not be predictable */ + chacha_encrypt_bytes(&rsx->rs_chacha, (uint8_t *)&rekey_fuzz, + (uint8_t *)&rekey_fuzz, sizeof(rekey_fuzz)); + rs->rs_count = REKEY_BASE + (rekey_fuzz % REKEY_BASE); } static inline void diff --git a/compat/getentropy_aix.c b/compat/getentropy_aix.c index 7fb857e..9d085cf 100644 --- a/compat/getentropy_aix.c +++ b/compat/getentropy_aix.c @@ -1,4 +1,4 @@ -/* $OpenBSD: getentropy_aix.c,v 1.8 2021/10/24 21:24:20 deraadt Exp $ */ +/* $OpenBSD: getentropy_aix.c,v 1.9 2022/12/26 07:18:50 jmc Exp $ */ /* * Copyright (c) 2015 Michael Felt <aixtools@gmail.com> @@ -21,7 +21,7 @@ * http://man.openbsd.org/getentropy.2 */ /* - * -lperfstat is needed for the psuedo entropy data + * -lperfstat is needed for the pseudo entropy data */ #include <sys/mman.h> diff --git a/compat/posix_win.c b/compat/posix_win.c index 30c93cd..b3a4687 100644 --- a/compat/posix_win.c +++ b/compat/posix_win.c @@ -148,6 +148,49 @@ wsa_errno(int err) return -1; } +/* + * Employ a similar trick to cpython (pycore_fileutils.h) where the CRT report + * handler is disabled while checking if a descriptor is a socket or a file + */ +#if defined _MSC_VER && _MSC_VER >= 1900 + +#include <crtdbg.h> +#include <stdlib.h> + +static void noop_handler(const wchar_t *expression, const wchar_t *function, + const wchar_t *file, unsigned int line, uintptr_t pReserved) +{ + return; +} + +#define BEGIN_SUPPRESS_IPH \ + _invalid_parameter_handler old_handler = _set_thread_local_invalid_parameter_handler(noop_handler) +#define END_SUPPRESS_IPH \ + _set_thread_local_invalid_parameter_handler(old_handler) + +#else + +#define BEGIN_SUPPRESS_IPH +#define END_SUPPRESS_IPH + +#endif + +static int +is_socket(int fd) +{ + intptr_t hd; + + BEGIN_SUPPRESS_IPH; + hd = _get_osfhandle(fd); + END_SUPPRESS_IPH; + + if (hd == (intptr_t)INVALID_HANDLE_VALUE) { + return 1; /* fd is not file descriptor */ + } + + return 0; +} + int posix_connect(int sockfd, const struct sockaddr *addr, socklen_t addrlen) { @@ -160,24 +203,31 @@ posix_connect(int sockfd, const struct sockaddr *addr, socklen_t addrlen) int posix_close(int fd) { - if (closesocket(fd) == SOCKET_ERROR) { - int err = WSAGetLastError(); - return (err == WSAENOTSOCK || err == WSAEBADF || - err == WSANOTINITIALISED) ? - close(fd) : wsa_errno(err); + int rc; + + if (is_socket(fd)) { + if ((rc = closesocket(fd)) == SOCKET_ERROR) { + int err = WSAGetLastError(); + rc = wsa_errno(err); + } + } else { + rc = close(fd); } - return 0; + return rc; } ssize_t posix_read(int fd, void *buf, size_t count) { - ssize_t rc = recv(fd, buf, count, 0); - if (rc == SOCKET_ERROR) { - int err = WSAGetLastError(); - return (err == WSAENOTSOCK || err == WSAEBADF || - err == WSANOTINITIALISED) ? - read(fd, buf, count) : wsa_errno(err); + ssize_t rc; + + if (is_socket(fd)) { + if ((rc = recv(fd, buf, count, 0)) == SOCKET_ERROR) { + int err = WSAGetLastError(); + rc = wsa_errno(err); + } + } else { + rc = read(fd, buf, count); } return rc; } @@ -185,12 +235,13 @@ posix_read(int fd, void *buf, size_t count) ssize_t posix_write(int fd, const void *buf, size_t count) { - ssize_t rc = send(fd, buf, count, 0); - if (rc == SOCKET_ERROR) { - int err = WSAGetLastError(); - return (err == WSAENOTSOCK || err == WSAEBADF || - err == WSANOTINITIALISED) ? - write(fd, buf, count) : wsa_errno(err); + ssize_t rc; + if (is_socket(fd)) { + if ((rc = send(fd, buf, count, 0)) == SOCKET_ERROR) { + rc = wsa_errno(WSAGetLastError()); + } + } else { + rc = write(fd, buf, count); } return rc; } @@ -199,17 +250,32 @@ int posix_getsockopt(int sockfd, int level, int optname, void *optval, socklen_t *optlen) { - int rc = getsockopt(sockfd, level, optname, (char *)optval, optlen); - return rc == 0 ? 0 : wsa_errno(WSAGetLastError()); - + int rc; + if (is_socket(sockfd)) { + rc = getsockopt(sockfd, level, optname, (char *)optval, optlen); + if (rc != 0) { + rc = wsa_errno(WSAGetLastError()); + } + } else { + rc = -1; + } + return rc; } int posix_setsockopt(int sockfd, int level, int optname, const void *optval, socklen_t optlen) { - int rc = setsockopt(sockfd, level, optname, (char *)optval, optlen); - return rc == 0 ? 0 : wsa_errno(WSAGetLastError()); + int rc; + if (is_socket(sockfd)) { + rc = setsockopt(sockfd, level, optname, (char *)optval, optlen); + if (rc != 0) { + rc = wsa_errno(WSAGetLastError()); + } + } else { + rc = -1; + } + return rc; } uid_t getuid(void) @@ -241,5 +307,4 @@ int gettimeofday(struct timeval * tp, struct timezone * tzp) tp->tv_usec = (long)(system_time.wMilliseconds * 1000); return 0; } - #endif diff --git a/empty.c b/empty.c new file mode 100644 index 0000000..e69de29 --- /dev/null +++ b/empty.c diff --git a/include/compat/sys/socket.h b/include/compat/sys/socket.h index 10eb05f..2f0b197 100644 --- a/include/compat/sys/socket.h +++ b/include/compat/sys/socket.h @@ -10,6 +10,7 @@ #endif #if !defined(SOCK_NONBLOCK) || !defined(SOCK_CLOEXEC) +#define NEED_SOCKET_FLAGS #define SOCK_CLOEXEC 0x8000 /* set FD_CLOEXEC */ #define SOCK_NONBLOCK 0x4000 /* set O_NONBLOCK */ int bsd_socketpair(int domain, int type, int protocol, int socket_vector[2]); diff --git a/include/compat/sys/types.h b/include/compat/sys/types.h index 4967843..59664bc 100644 --- a/include/compat/sys/types.h +++ b/include/compat/sys/types.h @@ -45,18 +45,6 @@ typedef SSIZE_T ssize_t; #endif -#if !defined(HAVE_ATTRIBUTE__BOUNDED__) && !defined(__bounded__) -# define __bounded__(x, y, z) -#endif - -#if !defined(HAVE_ATTRIBUTE__DEAD) && !defined(__dead) -#ifdef _MSC_VER -#define __dead __declspec(noreturn) -#else -#define __dead __attribute__((__noreturn__)) -#endif -#endif - #ifdef _WIN32 #define __warn_references(sym,msg) #else diff --git a/include/compat/unistd.h b/include/compat/unistd.h index 5e6ab1d..2583a6e 100644 --- a/include/compat/unistd.h +++ b/include/compat/unistd.h @@ -64,6 +64,10 @@ int getentropy(void *buf, size_t buflen); #endif #endif +#ifndef HAVE_GETOPT +#include <getopt.h> +#endif + #ifndef HAVE_GETPAGESIZE int getpagesize(void); #endif diff --git a/include/tls.h b/include/tls.h index 429c171..59b2c4c 100644 --- a/include/tls.h +++ b/include/tls.h @@ -1,4 +1,4 @@ -/* $OpenBSD: tls.h,v 1.61 2022/02/01 17:18:38 jsing Exp $ */ +/* $OpenBSD: tls.h,v 1.63 2023/07/02 06:37:27 beck Exp $ */ /* * Copyright (c) 2014 Joel Sing <jsing@openbsd.org> * @@ -36,14 +36,18 @@ typedef SSIZE_T ssize_t; #define TLS_API 20200120 -#define TLS_PROTOCOL_TLSv1_0 (1 << 1) -#define TLS_PROTOCOL_TLSv1_1 (1 << 2) +/* + * Deprecated versions of TLS. Using these effectively selects + * the minimum supported version. + */ +#define TLS_PROTOCOL_TLSv1_0 (1 << 3) +#define TLS_PROTOCOL_TLSv1_1 (1 << 3) +/* Supported versions of TLS */ #define TLS_PROTOCOL_TLSv1_2 (1 << 3) #define TLS_PROTOCOL_TLSv1_3 (1 << 4) #define TLS_PROTOCOL_TLSv1 \ - (TLS_PROTOCOL_TLSv1_0|TLS_PROTOCOL_TLSv1_1|\ - TLS_PROTOCOL_TLSv1_2|TLS_PROTOCOL_TLSv1_3) + (TLS_PROTOCOL_TLSv1_2|TLS_PROTOCOL_TLSv1_3) #define TLS_PROTOCOLS_ALL TLS_PROTOCOL_TLSv1 #define TLS_PROTOCOLS_DEFAULT (TLS_PROTOCOL_TLSv1_2|TLS_PROTOCOL_TLSv1_3) @@ -79,10 +83,6 @@ typedef SSIZE_T ssize_t; #define TLS_MAX_SESSION_ID_LENGTH 32 #define TLS_TICKET_KEY_SIZE 48 -#define TLS_PADDING_NONE 0 -#define TLS_PADDING_RSA_PKCS1 1 -#define TLS_PADDING_RSA_X9_31 2 - struct tls; struct tls_config; @@ -90,9 +90,6 @@ typedef ssize_t (*tls_read_cb)(struct tls *_ctx, void *_buf, size_t _buflen, void *_cb_arg); typedef ssize_t (*tls_write_cb)(struct tls *_ctx, const void *_buf, size_t _buflen, void *_cb_arg); -typedef int (*tls_sign_cb)(void *_cb_arg, const char *_pubkey_hash, - const uint8_t *_input, size_t _input_len, int _padding_type, - uint8_t **_out_signature, size_t *_out_signature_len); int tls_init(void); @@ -149,8 +146,6 @@ int tls_config_set_ocsp_staple_file(struct tls_config *_config, int tls_config_set_protocols(struct tls_config *_config, uint32_t _protocols); int tls_config_set_session_fd(struct tls_config *_config, int _session_fd); int tls_config_set_verify_depth(struct tls_config *_config, int _verify_depth); -int tls_config_set_sign_cb(struct tls_config *_config, tls_sign_cb _cb, - void *_cb_arg); void tls_config_prefer_ciphers_client(struct tls_config *_config); void tls_config_prefer_ciphers_server(struct tls_config *_config); @@ -228,17 +223,6 @@ time_t tls_peer_ocsp_revocation_time(struct tls *_ctx); time_t tls_peer_ocsp_this_update(struct tls *_ctx); const char *tls_peer_ocsp_url(struct tls *_ctx); -struct tls_signer* tls_signer_new(void); -void tls_signer_free(struct tls_signer * _signer); -const char *tls_signer_error(struct tls_signer * _signer); -int tls_signer_add_keypair_file(struct tls_signer *_signer, - const char *_cert_file, const char *_key_file); -int tls_signer_add_keypair_mem(struct tls_signer *_signer, const uint8_t *_cert, - size_t _cert_len, const uint8_t *_key, size_t _key_len); -int tls_signer_sign(struct tls_signer *_signer, const char *_pubkey_hash, - const uint8_t *_input, size_t _input_len, int _padding_type, - uint8_t **_out_signature, size_t *_out_signature_len); - #ifdef __cplusplus } #endif diff --git a/man/tls_config_set_protocols.3 b/man/tls_config_set_protocols.3 index 7c62493..32b8cce 100644 --- a/man/tls_config_set_protocols.3 +++ b/man/tls_config_set_protocols.3 @@ -1,4 +1,4 @@ -.\" $OpenBSD: tls_config_set_protocols.3,v 1.11 2021/01/02 19:58:44 schwarze Exp $ +.\" $OpenBSD: tls_config_set_protocols.3,v 1.12 2023/07/02 06:37:27 beck Exp $ .\" .\" Copyright (c) 2014 Ted Unangst <tedu@openbsd.org> .\" Copyright (c) 2015, 2016 Joel Sing <jsing@openbsd.org> @@ -16,7 +16,7 @@ .\" ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF .\" OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. .\" -.Dd $Mdocdate: January 2 2021 $ +.Dd $Mdocdate: July 2 2023 $ .Dt TLS_CONFIG_SET_PROTOCOLS 3 .Os .Sh NAME @@ -76,10 +76,6 @@ Possible values are the bitwise OR of: .Pp .Bl -item -offset indent -compact .It -.Dv TLS_PROTOCOL_TLSv1_0 -.It -.Dv TLS_PROTOCOL_TLSv1_1 -.It .Dv TLS_PROTOCOL_TLSv1_2 .It .Dv TLS_PROTOCOL_TLSv1_3 @@ -87,7 +83,7 @@ Possible values are the bitwise OR of: .Pp Additionally, the values .Dv TLS_PROTOCOL_TLSv1 -(TLSv1.0, TLSv1.1, TLSv1.2, TLSv1.3), +(TLSv1.2, TLSv1.3), .Dv TLS_PROTOCOLS_ALL (all supported protocols) and .Dv TLS_PROTOCOLS_DEFAULT @@ -106,8 +102,6 @@ The protocol string is a comma or colon separated list of keywords. Valid keywords are: .Pp .Bl -tag -width "tlsv1.3" -offset indent -compact -.It Dv tlsv1.0 -.It Dv tlsv1.1 .It Dv tlsv1.2 .It Dv tlsv1.3 .It Dv all diff --git a/tls.c b/tls.c index 6883c58..d387952 100644 --- a/tls.c +++ b/tls.c @@ -1,4 +1,4 @@ -/* $OpenBSD: tls.c,v 1.94 2022/02/08 19:13:50 tb Exp $ */ +/* $OpenBSD: tls.c,v 1.98 2023/07/02 06:37:27 beck Exp $ */ /* * Copyright (c) 2014 Joel Sing <jsing@openbsd.org> * @@ -470,12 +470,18 @@ tls_keypair_setup_pkey(struct tls *ctx, struct tls_keypair *keypair, EVP_PKEY *p tls_set_errorx(ctx, "RSA key setup failure"); goto err; } - if (ctx->config->sign_cb == NULL) - break; - if ((rsa_method = tls_signer_rsa_method()) == NULL || - RSA_set_ex_data(rsa, 1, ctx->config) == 0 || - RSA_set_method(rsa, rsa_method) == 0) { - tls_set_errorx(ctx, "failed to setup RSA key"); + if (ctx->config->sign_cb != NULL) { + rsa_method = tls_signer_rsa_method(); + if (rsa_method == NULL || + RSA_set_ex_data(rsa, 1, ctx->config) == 0 || + RSA_set_method(rsa, rsa_method) == 0) { + tls_set_errorx(ctx, "failed to setup RSA key"); + goto err; + } + } + /* Reset the key to work around caching in OpenSSL 3. */ + if (EVP_PKEY_set1_RSA(pkey, rsa) == 0) { + tls_set_errorx(ctx, "failed to set RSA key"); goto err; } break; @@ -485,12 +491,18 @@ tls_keypair_setup_pkey(struct tls *ctx, struct tls_keypair *keypair, EVP_PKEY *p tls_set_errorx(ctx, "EC key setup failure"); goto err; } - if (ctx->config->sign_cb == NULL) - break; - if ((ecdsa_method = tls_signer_ecdsa_method()) == NULL || - EC_KEY_set_ex_data(eckey, 1, ctx->config) == 0 || - EC_KEY_set_method(eckey, ecdsa_method) == 0) { - tls_set_errorx(ctx, "failed to setup EC key"); + if (ctx->config->sign_cb != NULL) { + ecdsa_method = tls_signer_ecdsa_method(); + if (ecdsa_method == NULL || + EC_KEY_set_ex_data(eckey, 1, ctx->config) == 0 || + EC_KEY_set_method(eckey, ecdsa_method) == 0) { + tls_set_errorx(ctx, "failed to setup EC key"); + goto err; + } + } + /* Reset the key to work around caching in OpenSSL 3. */ + if (EVP_PKEY_set1_EC_KEY(pkey, eckey) == 0) { + tls_set_errorx(ctx, "failed to set EC key"); goto err; } break; @@ -568,16 +580,12 @@ tls_configure_ssl(struct tls *ctx, SSL_CTX *ssl_ctx) SSL_CTX_set_options(ssl_ctx, SSL_OP_NO_SSLv2); SSL_CTX_set_options(ssl_ctx, SSL_OP_NO_SSLv3); + SSL_CTX_set_options(ssl_ctx, SSL_OP_NO_TLSv1); + SSL_CTX_set_options(ssl_ctx, SSL_OP_NO_TLSv1_1); - SSL_CTX_clear_options(ssl_ctx, SSL_OP_NO_TLSv1); - SSL_CTX_clear_options(ssl_ctx, SSL_OP_NO_TLSv1_1); SSL_CTX_clear_options(ssl_ctx, SSL_OP_NO_TLSv1_2); SSL_CTX_clear_options(ssl_ctx, SSL_OP_NO_TLSv1_3); - if ((ctx->config->protocols & TLS_PROTOCOL_TLSv1_0) == 0) - SSL_CTX_set_options(ssl_ctx, SSL_OP_NO_TLSv1); - if ((ctx->config->protocols & TLS_PROTOCOL_TLSv1_1) == 0) - SSL_CTX_set_options(ssl_ctx, SSL_OP_NO_TLSv1_1); if ((ctx->config->protocols & TLS_PROTOCOL_TLSv1_2) == 0) SSL_CTX_set_options(ssl_ctx, SSL_OP_NO_TLSv1_2); if ((ctx->config->protocols & TLS_PROTOCOL_TLSv1_3) == 0) diff --git a/tls.sym b/tls.sym index 54d8dd7..42c039d 100644 --- a/tls.sym +++ b/tls.sym @@ -43,7 +43,6 @@ tls_config_set_protocols tls_config_set_session_id tls_config_set_session_lifetime tls_config_set_session_fd -tls_config_set_sign_cb tls_config_set_verify_depth tls_config_skip_private_key_check tls_config_use_fake_private_key @@ -88,11 +87,5 @@ tls_peer_ocsp_url tls_read tls_reset tls_server -tls_signer_add_keypair_file -tls_signer_add_keypair_mem -tls_signer_error -tls_signer_free -tls_signer_new -tls_signer_sign tls_unload_file tls_write diff --git a/tls_bio_cb.c b/tls_bio_cb.c index 9dd435a..8a1edfd 100644 --- a/tls_bio_cb.c +++ b/tls_bio_cb.c @@ -1,4 +1,4 @@ -/* $OpenBSD: tls_bio_cb.c,v 1.20 2022/01/10 23:39:48 tb Exp $ */ +/* $OpenBSD: tls_bio_cb.c,v 1.21 2023/05/14 07:26:25 op Exp $ */ /* * Copyright (c) 2016 Tobias Pape <tobias@netshed.de> * diff --git a/tls_client.c b/tls_client.c index b1d2a44..deb24eb 100644 --- a/tls_client.c +++ b/tls_client.c @@ -1,4 +1,4 @@ -/* $OpenBSD: tls_client.c,v 1.48 2021/10/21 08:38:11 tb Exp $ */ +/* $OpenBSD: tls_client.c,v 1.49 2023/05/14 07:26:25 op Exp $ */ /* * Copyright (c) 2014 Joel Sing <jsing@openbsd.org> * diff --git a/tls_config.c b/tls_config.c index 38ed1bb..59c69f0 100644 --- a/tls_config.c +++ b/tls_config.c @@ -1,4 +1,4 @@ -/* $OpenBSD: tls_config.c,v 1.65 2022/01/25 21:51:24 eric Exp $ */ +/* $OpenBSD: tls_config.c,v 1.67 2023/07/02 06:37:27 beck Exp $ */ /* * Copyright (c) 2014 Joel Sing <jsing@openbsd.org> * @@ -251,9 +251,9 @@ tls_config_parse_protocols(uint32_t *protocols, const char *protostr) if (strcasecmp(p, "tlsv1") == 0) proto = TLS_PROTOCOL_TLSv1; else if (strcasecmp(p, "tlsv1.0") == 0) - proto = TLS_PROTOCOL_TLSv1_0; + proto = TLS_PROTOCOL_TLSv1_2; else if (strcasecmp(p, "tlsv1.1") == 0) - proto = TLS_PROTOCOL_TLSv1_1; + proto = TLS_PROTOCOL_TLSv1_2; else if (strcasecmp(p, "tlsv1.2") == 0) proto = TLS_PROTOCOL_TLSv1_2; else if (strcasecmp(p, "tlsv1.3") == 0) diff --git a/tls_conninfo.c b/tls_conninfo.c index 72d60c2..0a295a2 100644 --- a/tls_conninfo.c +++ b/tls_conninfo.c @@ -1,4 +1,4 @@ -/* $OpenBSD: tls_conninfo.c,v 1.22 2021/01/05 15:57:38 tb Exp $ */ +/* $OpenBSD: tls_conninfo.c,v 1.23 2023/05/14 07:26:25 op Exp $ */ /* * Copyright (c) 2015 Joel Sing <jsing@openbsd.org> * Copyright (c) 2015 Bob Beck <beck@openbsd.org> diff --git a/tls_internal.h b/tls_internal.h index e3f177d..e1dcf35 100644 --- a/tls_internal.h +++ b/tls_internal.h @@ -1,4 +1,4 @@ -/* $OpenBSD: tls_internal.h,v 1.79 2022/01/25 21:51:24 eric Exp $ */ +/* $OpenBSD: tls_internal.h,v 1.83 2023/06/27 18:19:59 tb Exp $ */ /* * Copyright (c) 2014 Jeremie Courreges-Anglas <jca@openbsd.org> * Copyright (c) 2014 Joel Sing <jsing@openbsd.org> @@ -28,6 +28,10 @@ __BEGIN_HIDDEN_DECLS +#ifndef TLS_DEFAULT_CA_FILE +#define TLS_DEFAULT_CA_FILE "/etc/ssl/cert.pem" +#endif + #define TLS_CIPHERS_DEFAULT TLS_CIPHERS_COMPAT #define TLS_CIPHERS_COMPAT "HIGH:!aNULL" #define TLS_CIPHERS_LEGACY "HIGH:MEDIUM:!aNULL" @@ -74,6 +78,10 @@ struct tls_ticket_key { time_t time; }; +typedef int (*tls_sign_cb)(void *_cb_arg, const char *_pubkey_hash, + const uint8_t *_input, size_t _input_len, int _padding_type, + uint8_t **_out_signature, size_t *_out_signature_len); + struct tls_config { struct tls_error error; @@ -292,6 +300,23 @@ int tls_password_cb(char *_buf, int _size, int _rwflag, void *_u); RSA_METHOD *tls_signer_rsa_method(void); EC_KEY_METHOD *tls_signer_ecdsa_method(void); +#define TLS_PADDING_NONE 0 +#define TLS_PADDING_RSA_PKCS1 1 + +int tls_config_set_sign_cb(struct tls_config *_config, tls_sign_cb _cb, + void *_cb_arg); + +struct tls_signer* tls_signer_new(void); +void tls_signer_free(struct tls_signer * _signer); +const char *tls_signer_error(struct tls_signer * _signer); +int tls_signer_add_keypair_file(struct tls_signer *_signer, + const char *_cert_file, const char *_key_file); +int tls_signer_add_keypair_mem(struct tls_signer *_signer, const uint8_t *_cert, + size_t _cert_len, const uint8_t *_key, size_t _key_len); +int tls_signer_sign(struct tls_signer *_signer, const char *_pubkey_hash, + const uint8_t *_input, size_t _input_len, int _padding_type, + uint8_t **_out_signature, size_t *_out_signature_len); + __END_HIDDEN_DECLS /* XXX this function is not fully hidden so relayd can use it */ diff --git a/tls_ocsp.c b/tls_ocsp.c index f1c54ab..7670d1f 100644 --- a/tls_ocsp.c +++ b/tls_ocsp.c @@ -1,4 +1,4 @@ -/* $OpenBSD: tls_ocsp.c,v 1.22 2021/10/31 16:39:32 tb Exp $ */ +/* $OpenBSD: tls_ocsp.c,v 1.23 2023/05/14 07:26:25 op Exp $ */ /* * Copyright (c) 2015 Marko Kreen <markokr@gmail.com> * Copyright (c) 2016 Bob Beck <beck@openbsd.org> @@ -22,6 +22,8 @@ #include <arpa/inet.h> #include <netinet/in.h> +#include <string.h> + #include <openssl/err.h> #include <openssl/ocsp.h> #include <openssl/x509.h> diff --git a/tls_server.c b/tls_server.c index ebf76bc..11303ca 100644 --- a/tls_server.c +++ b/tls_server.c @@ -1,4 +1,4 @@ -/* $OpenBSD: tls_server.c,v 1.48 2022/01/19 11:10:55 inoguchi Exp $ */ +/* $OpenBSD: tls_server.c,v 1.49 2023/05/14 07:26:25 op Exp $ */ /* * Copyright (c) 2014 Joel Sing <jsing@openbsd.org> * @@ -20,6 +20,8 @@ #include <arpa/inet.h> +#include <string.h> + #include <openssl/ec.h> #include <openssl/err.h> #include <openssl/ssl.h> diff --git a/tls_signer.c b/tls_signer.c index 9311cfe..76150fd 100644 --- a/tls_signer.c +++ b/tls_signer.c @@ -1,4 +1,4 @@ -/* $OpenBSD: tls_signer.c,v 1.4 2022/02/01 17:18:38 jsing Exp $ */ +/* $OpenBSD: tls_signer.c,v 1.9 2023/06/18 19:12:58 tb Exp $ */ /* * Copyright (c) 2021 Eric Faurot <eric@openbsd.org> * @@ -194,8 +194,6 @@ tls_sign_rsa(struct tls_signer *signer, struct tls_signer_key *skey, rsa_padding = RSA_NO_PADDING; } else if (padding_type == TLS_PADDING_RSA_PKCS1) { rsa_padding = RSA_PKCS1_PADDING; - } else if (padding_type == TLS_PADDING_RSA_X9_31) { - rsa_padding = RSA_X931_PADDING; } else { tls_error_setx(&signer->error, "invalid RSA padding type (%d)", padding_type); @@ -332,8 +330,6 @@ tls_rsa_priv_enc(int from_len, const unsigned char *from, unsigned char *to, padding_type = TLS_PADDING_NONE; } else if (rsa_padding == RSA_PKCS1_PADDING) { padding_type = TLS_PADDING_RSA_PKCS1; - } else if (rsa_padding == RSA_X931_PADDING) { - padding_type = TLS_PADDING_RSA_X9_31; } else { goto err; } @@ -428,17 +424,26 @@ EC_KEY_METHOD * tls_signer_ecdsa_method(void) { static EC_KEY_METHOD *ecdsa_method = NULL; + const EC_KEY_METHOD *default_method; + int (*sign)(int type, const unsigned char *dgst, int dlen, + unsigned char *sig, unsigned int *siglen, + const BIGNUM *kinv, const BIGNUM *r, EC_KEY *eckey); + int (*sign_setup)(EC_KEY *eckey, BN_CTX *ctx_in, + BIGNUM **kinvp, BIGNUM **rp); pthread_mutex_lock(&signer_method_lock); if (ecdsa_method != NULL) goto out; - ecdsa_method = EC_KEY_METHOD_new(NULL); + default_method = EC_KEY_get_default_method(); + ecdsa_method = EC_KEY_METHOD_new(default_method); if (ecdsa_method == NULL) goto out; - EC_KEY_METHOD_set_sign(ecdsa_method, NULL, NULL, tls_ecdsa_do_sign); + EC_KEY_METHOD_get_sign(default_method, &sign, &sign_setup, NULL); + EC_KEY_METHOD_set_sign(ecdsa_method, sign, sign_setup, + tls_ecdsa_do_sign); out: pthread_mutex_unlock(&signer_method_lock); diff --git a/tls_util.c b/tls_util.c index 782d6fc..79efc53 100644 --- a/tls_util.c +++ b/tls_util.c @@ -1,4 +1,4 @@ -/* $OpenBSD: tls_util.c,v 1.15 2021/08/16 13:54:38 tb Exp $ */ +/* $OpenBSD: tls_util.c,v 1.16 2023/05/14 07:26:25 op Exp $ */ /* * Copyright (c) 2014 Joel Sing <jsing@openbsd.org> * Copyright (c) 2014 Ted Unangst <tedu@openbsd.org> diff --git a/tls_verify.c b/tls_verify.c index dbc37d8..c588f02 100644 --- a/tls_verify.c +++ b/tls_verify.c @@ -1,4 +1,4 @@ -/* $OpenBSD: tls_verify.c,v 1.20 2018/02/05 00:52:24 jsing Exp $ */ +/* $OpenBSD: tls_verify.c,v 1.28 2023/06/01 07:32:25 tb Exp $ */ /* * Copyright (c) 2014 Jeremie Courreges-Anglas <jca@openbsd.org> * @@ -92,15 +92,21 @@ tls_check_subject_altname(struct tls *ctx, X509 *cert, const char *name, union tls_addr addrbuf; int addrlen, type; int count, i; - int rv = 0; + int critical = 0; + int rv = -1; *alt_match = 0; *alt_exists = 0; - altname_stack = X509_get_ext_d2i(cert, NID_subject_alt_name, - NULL, NULL); - if (altname_stack == NULL) - return 0; + altname_stack = X509_get_ext_d2i(cert, NID_subject_alt_name, &critical, + NULL); + if (altname_stack == NULL) { + if (critical != -1) { + tls_set_errorx(ctx, "error decoding subjectAltName"); + goto err; + } + goto done; + } if (inet_pton(AF_INET, name, &addrbuf) == 1) { type = GEN_IPADD; @@ -115,7 +121,7 @@ tls_check_subject_altname(struct tls *ctx, X509 *cert, const char *name, count = sk_GENERAL_NAME_num(altname_stack); for (i = 0; i < count; i++) { - GENERAL_NAME *altname; + GENERAL_NAME *altname; altname = sk_GENERAL_NAME_value(altname_stack, i); @@ -126,8 +132,8 @@ tls_check_subject_altname(struct tls *ctx, X509 *cert, const char *name, continue; if (type == GEN_DNS) { - const unsigned char *data; - int format, len; + const unsigned char *data; + int format, len; format = ASN1_STRING_type(altname->d.dNSName); if (format == V_ASN1_IA5STRING) { @@ -140,8 +146,7 @@ tls_check_subject_altname(struct tls *ctx, X509 *cert, const char *name, "NUL byte in subjectAltName, " "probably a malicious certificate", name); - rv = -1; - break; + goto err; } /* @@ -154,13 +159,12 @@ tls_check_subject_altname(struct tls *ctx, X509 *cert, const char *name, "error verifying name '%s': " "a dNSName of \" \" must not be " "used", name); - rv = -1; - break; + goto err; } if (tls_match_name(data, name) == 0) { *alt_match = 1; - break; + goto done; } } else { #ifdef DEBUG @@ -171,8 +175,8 @@ tls_check_subject_altname(struct tls *ctx, X509 *cert, const char *name, } } else if (type == GEN_IPADD) { - const unsigned char *data; - int datalen; + const unsigned char *data; + int datalen; datalen = ASN1_STRING_length(altname->d.iPAddress); data = ASN1_STRING_get0_data(altname->d.iPAddress); @@ -181,8 +185,7 @@ tls_check_subject_altname(struct tls *ctx, X509 *cert, const char *name, tls_set_errorx(ctx, "Unexpected negative length for an " "IP address: %d", datalen); - rv = -1; - break; + goto err; } /* @@ -192,11 +195,15 @@ tls_check_subject_altname(struct tls *ctx, X509 *cert, const char *name, if (datalen == addrlen && memcmp(data, &addrbuf, addrlen) == 0) { *alt_match = 1; - break; + goto done; } } } + done: + rv = 0; + + err: sk_GENERAL_NAME_pop_free(altname_stack, GENERAL_NAME_free); return rv; } @@ -205,11 +212,14 @@ static int tls_check_common_name(struct tls *ctx, X509 *cert, const char *name, int *cn_match) { + unsigned char *utf8_bytes = NULL; X509_NAME *subject_name; char *common_name = NULL; union tls_addr addrbuf; int common_name_len; - int rv = 0; + ASN1_STRING *data; + int lastpos = -1; + int rv = -1; *cn_match = 0; @@ -217,26 +227,63 @@ tls_check_common_name(struct tls *ctx, X509 *cert, const char *name, if (subject_name == NULL) goto done; - common_name_len = X509_NAME_get_text_by_NID(subject_name, - NID_commonName, NULL, 0); - if (common_name_len < 0) - goto done; - - common_name = calloc(common_name_len + 1, 1); - if (common_name == NULL) + lastpos = X509_NAME_get_index_by_NID(subject_name, + NID_commonName, lastpos); + if (lastpos == -1) goto done; + if (lastpos < 0) + goto err; + if (X509_NAME_get_index_by_NID(subject_name, NID_commonName, lastpos) + != -1) { + /* + * Having multiple CN's is possible, and even happened back in + * the glory days of mullets and Hammer pants. In anything like + * a modern TLS cert, CN is as close to deprecated as it gets, + * and having more than one is bad. We therefore fail if we have + * more than one CN fed to us in the subject, treating the + * certificate as hostile. + */ + tls_set_errorx(ctx, "error verifying name '%s': " + "Certificate subject contains mutiple Common Name fields, " + "probably a malicious or malformed certificate", name); + goto err; + } - X509_NAME_get_text_by_NID(subject_name, NID_commonName, common_name, - common_name_len + 1); - - /* NUL bytes in CN? */ - if (common_name_len < 0 || - (size_t)common_name_len != strlen(common_name)) { + data = X509_NAME_ENTRY_get_data(X509_NAME_get_entry(subject_name, + lastpos)); + /* + * Fail if we cannot encode the CN bytes as UTF-8. + */ + if ((common_name_len = ASN1_STRING_to_UTF8(&utf8_bytes, data)) < 0) { + tls_set_errorx(ctx, "error verifying name '%s': " + "Common Name field cannot be encoded as a UTF-8 string, " + "probably a malicious certificate", name); + goto err; + } + /* + * Fail if the CN is of invalid length. RFC 5280 specifies that a CN + * must be between 1 and 64 bytes long. + */ + if (common_name_len < 1 || common_name_len > 64) { + tls_set_errorx(ctx, "error verifying name '%s': " + "Common Name field has invalid length, " + "probably a malicious certificate", name); + goto err; + } + /* + * Fail if the resulting text contains a NUL byte. + */ + if (memchr(utf8_bytes, 0, common_name_len) != NULL) { tls_set_errorx(ctx, "error verifying name '%s': " "NUL byte in Common Name field, " "probably a malicious certificate", name); - rv = -1; - goto done; + goto err; + } + + common_name = strndup(utf8_bytes, common_name_len); + if (common_name == NULL) { + tls_set_error(ctx, "out of memory"); + goto err; } /* @@ -254,6 +301,10 @@ tls_check_common_name(struct tls *ctx, X509 *cert, const char *name, *cn_match = 1; done: + rv = 0; + + err: + free(utf8_bytes); free(common_name); return rv; } |