git: ae3d4a75ab05 - main - security/openssl30: Resurrect OpenSSL 3.0 port

From: Bernard Spil <brnrd_at_FreeBSD.org>
Date: Wed, 30 Sep 2026 11:11:53 UTC
The branch main has been updated by brnrd:

URL: https://cgit.FreeBSD.org/ports/commit/?id=ae3d4a75ab0550f4e4496f728ae451a996d79ec2

commit ae3d4a75ab0550f4e4496f728ae451a996d79ec2
Author:     Bernard Spil <brnrd@FreeBSD.org>
AuthorDate: 2026-09-30 11:10:54 +0000
Commit:     Bernard Spil <brnrd@FreeBSD.org>
CommitDate: 2026-09-30 11:10:54 +0000

    security/openssl30: Resurrect OpenSSL 3.0 port
    
    For FreeBSD 14, expires 2028-11-30
    Has known vulnerabilities, users are encouraged to move
    to OpenSSL 3.5 from security/openssl
---
 security/Makefile                                  |   1 +
 security/openssl30/Makefile                        | 179 +++++++
 security/openssl30/distinfo                        |   3 +
 security/openssl30/files/extra-patch-ktls          | 540 +++++++++++++++++++++
 .../openssl30/files/extra-patch-util_find-doc-nits |  20 +
 .../files/patch-Configurations_10-main.conf        |  35 ++
 security/openssl30/files/patch-Configure           |  11 +
 .../files/patch-crypto_async_arch_async__posix.h   |  32 ++
 security/openssl30/files/patch-crypto_ppccap.c     |  34 ++
 .../files/patch-crypto_threads__pthread.c          |  13 +
 .../files/patch-util_perl_OpenSSL_config.pm        |  14 +
 security/openssl30/pkg-descr                       |  13 +
 security/openssl30/pkg-message                     |  22 +
 security/openssl30/pkg-plist                       | 275 +++++++++++
 security/openssl30/version.mk                      |   1 +
 15 files changed, 1193 insertions(+)

diff --git a/security/Makefile b/security/Makefile
index 34614c8df275..13d52b6b8152 100644
--- a/security/Makefile
+++ b/security/Makefile
@@ -461,6 +461,7 @@
     SUBDIR += openssl-oqsprovider
     SUBDIR += openssl-pkcs11provider
     SUBDIR += openssl-unsafe
+    SUBDIR += openssl30
     SUBDIR += openssl34
     SUBDIR += openssl35
     SUBDIR += openssl36
diff --git a/security/openssl30/Makefile b/security/openssl30/Makefile
new file mode 100644
index 000000000000..66ed527e3b45
--- /dev/null
+++ b/security/openssl30/Makefile
@@ -0,0 +1,179 @@
+PORTNAME=	openssl
+PORTVERSION=	3.0.22
+CATEGORIES=	security devel
+MASTER_SITES=	https://github.com/openssl/openssl/releases/download/${DISTNAME}/
+
+MAINTAINER=	brnrd@FreeBSD.org
+COMMENT=	TLSv1.3 capable SSL and crypto library
+WWW=		https://www.openssl.org/
+
+LICENSE=	APACHE20
+LICENSE_FILE=	${WRKSRC}/LICENSE.txt
+
+# Expire together with FreeBSD 14
+EXPIRATION_DATE=	2028-11-30
+
+CONFLICTS_INSTALL=	boringssl libressl libressl-devel openssl[134]*
+
+USES=		cpe perl5
+USE_PERL5=	build
+TEST_TARGET=	test
+
+HAS_CONFIGURE=	yes
+CONFIGURE_SCRIPT=	config
+CONFIGURE_ENV=	PERL="${PERL}"
+CONFIGURE_ARGS=	--openssldir=${OPENSSLDIR} \
+		--prefix=${PREFIX}
+
+LDFLAGS_i386=	-Wl,-znotext
+
+MAKE_ARGS+=	WHOLE_ARCHIVE_FLAG=--whole-archive CNF_LDFLAGS="${LDFLAGS}"
+MAKE_ENV+=	LIBRPATH="${PREFIX}/lib" GREP_OPTIONS=
+
+OPTIONS_GROUP=		CIPHERS HASHES MODULES OPTIMIZE PROTOCOLS
+OPTIONS_GROUP_CIPHERS=	ARIA DES GOST IDEA SM4 RC2 RC4 RC5 WEAK-SSL-CIPHERS
+OPTIONS_GROUP_HASHES=	MD2 MD4 MDC2 RMD160 SM2 SM3
+OPTIONS_GROUP_OPTIMIZE=	ASM SSE2 THREADS
+OPTIONS_GROUP_MODULES=	FIPS LEGACY
+OPTIONS_DEFINE_i386=	I386
+OPTIONS_GROUP_PROTOCOLS=NEXTPROTONEG SCTP SSL3 TLS1 TLS1_1 TLS1_2
+
+OPTIONS_DEFINE=	ASYNC CT KTLS MAN3 RFC3779 SHARED ZLIB
+
+OPTIONS_DEFAULT=ASM ASYNC CT DES EC FIPS GOST KTLS MAN3 MD4 NEXTPROTONEG \
+		RFC3779 RC2 RC4 RMD160 SCTP SHARED SSE2 THREADS TLS1 TLS1_1 TLS1_2
+
+.if ${MACHINE_ARCH} == "amd64"
+OPTIONS_GROUP_OPTIMIZE+=	EC
+.endif
+
+OPTIONS_SUB=	yes
+
+ARIA_DESC=	ARIA (South Korean standard)
+ASM_DESC=	Assembler code
+ASYNC_DESC=	Asynchronous mode
+CIPHERS_DESC=	Block Cipher Support
+CT_DESC=	Certificate Transparency Support
+DES_DESC=	(Triple) Data Encryption Standard
+EC_DESC=	Optimize NIST elliptic curves
+FIPS_DESC=	Build FIPS provider
+GOST_DESC=	GOST (Russian standard)
+HASHES_DESC=	Hash Function Support
+I386_DESC=	i386 (instead of i486+)
+IDEA_DESC=	International Data Encryption Algorithm
+KTLS_DESC=	Use in-kernel TLS (FreeBSD >13)
+LEGACY_DESC=	Older algorithms
+MAN3_DESC=	Install API manpages (section 3, 7)
+MD2_DESC=	MD2 (obsolete) (requires LEGACY)
+MD4_DESC=	MD4 (unsafe)
+MDC2_DESC=	MDC-2 (patented, requires DES)
+MODULES_DESC=	Provider modules
+NEXTPROTONEG_DESC=	Next Protocol Negotiation (SPDY)
+OPTIMIZE_DESC=	Optimizations
+PROTOCOLS_DESC=	Protocol Support
+RC2_DESC=	RC2 (unsafe)
+RC4_DESC=	RC4 (unsafe)
+RC5_DESC=	RC5 (patented)
+RMD160_DESC=	RIPEMD-160
+RFC3779_DESC=	RFC3779 support (BGP)
+SCTP_DESC=	SCTP (Stream Control Transmission)
+SHARED_DESC=	Build shared libraries
+SM2_DESC=	SM2 Elliptic Curve DH (Chinese standard)
+SM3_DESC=	SM3 256bit (Chinese standard)
+SM4_DESC=	SM4 128bit (Chinese standard)
+SSE2_DESC=	Runtime SSE2 detection
+SSL3_DESC=	SSLv3 (unsafe)
+TLS1_DESC=	TLSv1.0 (requires TLS1_1, TLS1_2)
+TLS1_1_DESC=	TLSv1.1 (requires TLS1_2)
+TLS1_2_DESC=	TLSv1.2
+WEAK-SSL-CIPHERS_DESC=	Weak cipher support (unsafe)
+
+# Upstream default disabled options
+.for _option in fips md2 ktls rc5 sctp ssl3 weak-ssl-ciphers zlib
+${_option:tu}_CONFIGURE_ON=	enable-${_option}
+.endfor
+
+# Upstream default enabled options
+.for _option in aria asm async ct des gost idea md4 mdc2 legacy \
+	nextprotoneg rc2 rc4 rfc3779 rmd160 shared sm2 sm3 sm4 sse2 \
+	threads tls1 tls1_1 tls1_2
+${_option:tu}_CONFIGURE_OFF=	no-${_option}
+.endfor
+
+MD2_IMPLIES=	LEGACY
+MDC2_IMPLIES=	DES
+TLS1_IMPLIES=	TLS1_1
+TLS1_1_IMPLIES=	TLS1_2
+
+EC_CONFIGURE_ON=	enable-ec_nistp_64_gcc_128
+FIPS_VARS=		shlibs+=lib/ossl-modules/fips.so
+I386_CONFIGURE_ON=	386
+KTLS_EXTRA_PATCHES=	${FILESDIR}/extra-patch-ktls
+LEGACY_VARS=		shlibs+=lib/ossl-modules/legacy.so
+MAN3_EXTRA_PATCHES_OFF=	${FILESDIR}/extra-patch-util_find-doc-nits
+SHARED_MAKE_ENV=	SHLIBVER=${OPENSSL_SHLIBVER}
+SHARED_PLIST_SUB=	SHLIBVER=${OPENSSL_SHLIBVER}
+SHARED_USE=		ldconfig=yes
+SHARED_VARS=		shlibs+="lib/libcrypto.so.${OPENSSL_SHLIBVER} \
+				lib/libssl.so.${OPENSSL_SHLIBVER} \
+				lib/engines-${OPENSSL_SHLIBVER}/capi.so \
+				lib/engines-${OPENSSL_SHLIBVER}/devcrypto.so \
+				lib/engines-${OPENSSL_SHLIBVER}/padlock.so"
+SSL3_CONFIGURE_ON+=	enable-ssl3-method
+ZLIB_CONFIGURE_ON=	zlib-dynamic
+
+SHLIBS=			lib/engines-${OPENSSL_SHLIBVER}/loader_attic.so
+
+PORTSCOUT=		limit:^${PORTVERSION:R:S/./\./g}\.
+
+.include <bsd.port.options.mk>
+
+.if ${ARCH} == powerpc64
+CONFIGURE_ARGS+=	BSD-ppc64
+.elif ${ARCH} == powerpc64le
+CONFIGURE_ARGS+=	BSD-ppc64le
+.elif ${ARCH} == riscv64
+CONFIGURE_ARGS+=	BSD-riscv64
+.endif
+
+.include <bsd.port.pre.mk>
+.if ${PREFIX} == /usr
+IGNORE=	the OpenSSL port can not be installed over the base version
+.endif
+
+OPENSSLDIR?=	${PREFIX}/openssl
+PLIST_SUB+=	OPENSSLDIR=${OPENSSLDIR:S=^${PREFIX}/==}
+
+.include "version.mk"
+
+post-patch:
+	${REINPLACE_CMD} -Ee 's|^(build\|install)_docs: .*|\1_docs: \1_man_docs|' \
+		${WRKSRC}/Configurations/unix-Makefile.tmpl
+	${REINPLACE_CMD} 's|SHLIB_VERSION=3|SHLIB_VERSION=${OPENSSL_SHLIBVER}|' \
+		${WRKSRC}/VERSION.dat
+
+post-configure:
+	( cd ${WRKSRC} ; ${PERL} configdata.pm --dump )
+
+post-configure-MAN3-off:
+	${REINPLACE_CMD} \
+		-e 's|^build_man_docs:.*|build_man_docs: $$(MANDOCS1) $$(MANDOCS5)|' \
+		-e 's|dummy $$(MANDOCS[37]); do |dummy; do |' \
+		${WRKSRC}/Makefile
+
+post-install-SHARED-on:
+.for i in ${SHLIBS}
+	-@${STRIP_CMD} ${STAGEDIR}${PREFIX}/$i
+.endfor
+
+post-install-SHARED-off:
+	${RMDIR} ${STAGEDIR}${PREFIX}/lib/engines-12
+
+post-install:
+	${STRIP_CMD} ${STAGEDIR}${PREFIX}/bin/openssl
+
+post-install-MAN3-on:
+	( cd ${STAGEDIR}/${PREFIX} ; ${FIND} share/man/man3 -not -type d ; \
+		${FIND} share/man/man7 -not -type d ) | ${SED} 's/$$/.gz/' >> ${TMPPLIST}
+
+.include <bsd.port.post.mk>
diff --git a/security/openssl30/distinfo b/security/openssl30/distinfo
new file mode 100644
index 000000000000..4050bedd4c0b
--- /dev/null
+++ b/security/openssl30/distinfo
@@ -0,0 +1,3 @@
+TIMESTAMP = 1787680996
+SHA256 (openssl-3.0.22.tar.gz) = 67ebca7e50d17383028045486653492195b83db95f8558709701bb47b5c1ef81
+SIZE (openssl-3.0.22.tar.gz) = 15330396
diff --git a/security/openssl30/files/extra-patch-ktls b/security/openssl30/files/extra-patch-ktls
new file mode 100644
index 000000000000..48a5dd43a972
--- /dev/null
+++ b/security/openssl30/files/extra-patch-ktls
@@ -0,0 +1,540 @@
+diff --git include/internal/ktls.h include/internal/ktls.h
+index 95492fd065..3c82cae26b 100644
+--- include/internal/ktls.h
++++ include/internal/ktls.h
+@@ -40,6 +40,11 @@
+ #define OPENSSL_KTLS_AES_GCM_128
+ #define OPENSSL_KTLS_AES_GCM_256
+ #define OPENSSL_KTLS_TLS13
++#ifdef TLS_CHACHA20_IV_LEN
++# ifndef OPENSSL_NO_CHACHA
++#  define OPENSSL_KTLS_CHACHA20_POLY1305
++# endif
++#endif
+ 
+ typedef struct tls_enable ktls_crypto_info_t;
+ 
+diff --git ssl/ktls.c ssl/ktls.c
+index 79d980959e..e343d382cc 100644
+--- ssl/ktls.c
++++ ssl/ktls.c
+@@ -10,6 +10,67 @@
+ #include "ssl_local.h"
+ #include "internal/ktls.h"
+ 
++#ifndef OPENSSL_NO_KTLS_RX
++ /*
++  * Count the number of records that were not processed yet from record boundary.
++  *
++  * This function assumes that there are only fully formed records read in the
++  * record layer. If read_ahead is enabled, then this might be false and this
++  * function will fail.
++  */
++static int count_unprocessed_records(SSL *s)
++{
++    SSL3_BUFFER *rbuf = RECORD_LAYER_get_rbuf(&s->rlayer);
++    PACKET pkt, subpkt;
++    int count = 0;
++
++    if (!PACKET_buf_init(&pkt, rbuf->buf + rbuf->offset, rbuf->left))
++        return -1;
++
++    while (PACKET_remaining(&pkt) > 0) {
++        /* Skip record type and version */
++        if (!PACKET_forward(&pkt, 3))
++            return -1;
++
++        /* Read until next record */
++        if (!PACKET_get_length_prefixed_2(&pkt, &subpkt))
++            return -1;
++
++        count += 1;
++    }
++
++    return count;
++}
++
++/*
++ * The kernel cannot offload receive if a partial TLS record has been read.
++ * Check the read buffer for unprocessed records.  If the buffer contains a
++ * partial record, fail and return 0.  Otherwise, update the sequence
++ * number at *rec_seq for the count of unprocessed records and return 1.
++ */
++static int check_rx_read_ahead(SSL *s, unsigned char *rec_seq)
++{
++    int bit, count_unprocessed;
++
++    count_unprocessed = count_unprocessed_records(s);
++    if (count_unprocessed < 0)
++        return 0;
++
++    /* increment the crypto_info record sequence */
++    while (count_unprocessed) {
++        for (bit = 7; bit >= 0; bit--) { /* increment */
++            ++rec_seq[bit];
++            if (rec_seq[bit] != 0)
++                break;
++        }
++        count_unprocessed--;
++
++    }
++
++    return 1;
++}
++#endif
++
+ #if defined(__FreeBSD__)
+ # include "crypto/cryptodev.h"
+ 
+@@ -37,6 +98,10 @@ int ktls_check_supported_cipher(const SSL *s, const EVP_CIPHER *c,
+     case SSL_AES128GCM:
+     case SSL_AES256GCM:
+         return 1;
++# ifdef OPENSSL_KTLS_CHACHA20_POLY1305
++    case SSL_CHACHA20POLY1305:
++        return 1;
++# endif
+     case SSL_AES128:
+     case SSL_AES256:
+         if (s->ext.use_etm)
+@@ -55,9 +120,9 @@ int ktls_check_supported_cipher(const SSL *s, const EVP_CIPHER *c,
+ }
+ 
+ /* Function to configure kernel TLS structure */
+-int ktls_configure_crypto(const SSL *s, const EVP_CIPHER *c, EVP_CIPHER_CTX *dd,
++int ktls_configure_crypto(SSL *s, const EVP_CIPHER *c, EVP_CIPHER_CTX *dd,
+     void *rl_sequence, ktls_crypto_info_t *crypto_info,
+-    unsigned char **rec_seq, unsigned char *iv,
++    int is_tx, unsigned char *iv,
+     unsigned char *key, unsigned char *mac_key,
+     size_t mac_secret_size)
+ {
+@@ -71,6 +136,12 @@ int ktls_configure_crypto(const SSL *s, const EVP_CIPHER *c, EVP_CIPHER_CTX *dd,
+         else
+             crypto_info->iv_len = EVP_GCM_TLS_FIXED_IV_LEN;
+         break;
++# ifdef OPENSSL_KTLS_CHACHA20_POLY1305
++    case SSL_CHACHA20POLY1305:
++        crypto_info->cipher_algorithm = CRYPTO_CHACHA20_POLY1305;
++        crypto_info->iv_len = EVP_CIPHER_CTX_get_iv_length(dd);
++        break;
++# endif
+     case SSL_AES128:
+     case SSL_AES256:
+         switch (s->s3.tmp.new_cipher->algorithm_mac) {
+@@ -101,11 +172,11 @@ int ktls_configure_crypto(const SSL *s, const EVP_CIPHER *c, EVP_CIPHER_CTX *dd,
+     crypto_info->tls_vminor = (s->version & 0x000000ff);
+ #ifdef TCP_RXTLS_ENABLE
+     memcpy(crypto_info->rec_seq, rl_sequence, sizeof(crypto_info->rec_seq));
+-    if (rec_seq != NULL)
+-        *rec_seq = crypto_info->rec_seq;
++    if (!is_tx && !check_rx_read_ahead(s, crypto_info->rec_seq))
++        return 0;
+ #else
+-    if (rec_seq != NULL)
+-        *rec_seq = NULL;
++    if (!is_tx)
++        return 0;
+ #endif
+     return 1;
+ };
+@@ -154,15 +227,20 @@ int ktls_check_supported_cipher(const SSL *s, const EV
+ }
+ 
+ /* Function to configure kernel TLS structure */
+-int ktls_configure_crypto(const SSL *s, const EVP_CIPHER *c, EVP_CIPHER_CTX *dd,
++int ktls_configure_crypto(SSL *s, const EVP_CIPHER *c, EVP_CIPHER_CTX *dd,
+     void *rl_sequence, ktls_crypto_info_t *crypto_info,
+-    unsigned char **rec_seq, unsigned char *iv,
++    int is_tx, unsigned char *iv,
+     unsigned char *key, unsigned char *mac_key,
+     size_t mac_secret_size)
+ {
+     unsigned char geniv[12];
+     unsigned char *iiv = iv;
+ 
++# ifdef OPENSSL_NO_KTLS_RX
++    if (!is_tx)
++        return 0;
++# endif
++
+     if (s->version == TLS1_2_VERSION && EVP_CIPHER_get_mode(c) == EVP_CIPH_GCM_MODE) {
+         if (!EVP_CIPHER_CTX_get_updated_iv(dd, geniv,
+                 EVP_GCM_TLS_FIXED_IV_LEN
+@@ -186,8 +262,8 @@ int ktls_configure_crypto(const SSL *s, const EVP_CIPH
+         memcpy(crypto_info->gcm128.key, key, EVP_CIPHER_get_key_length(c));
+         memcpy(crypto_info->gcm128.rec_seq, rl_sequence,
+             TLS_CIPHER_AES_GCM_128_REC_SEQ_SIZE);
+-        if (rec_seq != NULL)
+-            *rec_seq = crypto_info->gcm128.rec_seq;
++        if (!is_tx && !check_rx_read_ahead(s, crypto_info->gcm128.rec_seq))
++            return 0;
+         return 1;
+ #endif
+ #ifdef OPENSSL_KTLS_AES_GCM_256
+@@ -201,8 +277,8 @@ int ktls_configure_crypto(const SSL *s, const EVP_CIPH
+         memcpy(crypto_info->gcm256.key, key, EVP_CIPHER_get_key_length(c));
+         memcpy(crypto_info->gcm256.rec_seq, rl_sequence,
+             TLS_CIPHER_AES_GCM_256_REC_SEQ_SIZE);
+-        if (rec_seq != NULL)
+-            *rec_seq = crypto_info->gcm256.rec_seq;
++        if (!is_tx && !check_rx_read_ahead(s, crypto_info->ccm128.rec_seq))
++            return 0;
+         return 1;
+ #endif
+ #ifdef OPENSSL_KTLS_AES_CCM_128
+@@ -216,8 +292,8 @@ int ktls_configure_crypto(const SSL *s, const EVP_CIPH
+         memcpy(crypto_info->ccm128.key, key, EVP_CIPHER_get_key_length(c));
+         memcpy(crypto_info->ccm128.rec_seq, rl_sequence,
+             TLS_CIPHER_AES_CCM_128_REC_SEQ_SIZE);
+-        if (rec_seq != NULL)
+-            *rec_seq = crypto_info->ccm128.rec_seq;
++        if (!is_tx && !check_rx_read_ahead(s, crypto_info->ccm128.rec_seq))
++            return 0;
+         return 1;
+ #endif
+ #ifdef OPENSSL_KTLS_CHACHA20_POLY1305
+@@ -231,7 +309,11 @@ int ktls_configure_crypto(const SSL *s, const EVP_CIPH
+             TLS_CIPHER_CHACHA20_POLY1305_REC_SEQ_SIZE);
+         if (rec_seq != NULL)
+             *rec_seq = crypto_info->chacha20poly1305.rec_seq;
+-        return 1;
++        if (!is_tx
++                && !check_rx_read_ahead(s,
++                                        crypto_info->chacha20poly1305.rec_seq))
++            return 0;
++        return 1;
+ #endif
+     default:
+         return 0;
+diff --git ssl/record/ssl3_record.c ssl/record/ssl3_record.c
+index d8ef018741..63caac080f 100644
+--- ssl/record/ssl3_record.c
++++ ssl/record/ssl3_record.c
+@@ -186,18 +186,23 @@ int ssl3_get_record(SSL *s)
+     int imac_size;
+     size_t num_recs = 0, max_recs, j;
+     PACKET pkt, sslv2pkt;
+-    int is_ktls_left;
++    int using_ktls;
+     SSL_MAC_BUF *macbufs = NULL;
+     int ret = -1;
+ 
+     rr = RECORD_LAYER_get_rrec(&s->rlayer);
+     rbuf = RECORD_LAYER_get_rbuf(&s->rlayer);
+-    is_ktls_left = (SSL3_BUFFER_get_left(rbuf) > 0);
+     max_recs = s->max_pipelines;
+     if (max_recs == 0)
+         max_recs = 1;
+     sess = s->session;
+ 
++    /*
++     * KTLS reads full records. If there is any data left,
++     * then it is from before enabling ktls.
++     */
++    using_ktls = BIO_get_ktls_recv(s->rbio) && SSL3_BUFFER_get_left(rbuf) == 0;
++
+     do {
+         thisrr = &rr[num_recs];
+ 
+@@ -357,7 +362,9 @@ int ssl3_get_record(SSL *s)
+                     }
+                 }
+ 
+-                if (SSL_IS_TLS13(s) && s->enc_read_ctx != NULL) {
++                if (SSL_IS_TLS13(s)
++                        && s->enc_read_ctx != NULL
++                        && !using_ktls) {
+                     if (thisrr->type != SSL3_RT_APPLICATION_DATA
+                         && (thisrr->type != SSL3_RT_CHANGE_CIPHER_SPEC
+                             || !SSL_IS_FIRST_HANDSHAKE(s))
+@@ -386,7 +393,13 @@ int ssl3_get_record(SSL *s)
+         }
+ 
+         if (SSL_IS_TLS13(s)) {
+-            if (thisrr->length > SSL3_RT_MAX_TLS13_ENCRYPTED_LENGTH) {
++            size_t len = SSL3_RT_MAX_TLS13_ENCRYPTED_LENGTH;
++
++            /* KTLS strips the inner record type. */
++            if (using_ktls)
++                len = SSL3_RT_MAX_ENCRYPTED_LENGTH;
++
++            if (thisrr->length > len) {
+                 SSLfatal(s, SSL_AD_RECORD_OVERFLOW,
+                     SSL_R_ENCRYPTED_LENGTH_TOO_LONG);
+                 return -1;
+@@ -404,7 +417,7 @@ int ssl3_get_record(SSL *s)
+ #endif
+ 
+             /* KTLS may use all of the buffer */
+-            if (BIO_get_ktls_recv(s->rbio) && !is_ktls_left)
++            if (using_ktls)
+                 len = SSL3_BUFFER_get_left(rbuf);
+ 
+             if (thisrr->length > len) {
+@@ -512,11 +525,7 @@ int ssl3_get_record(SSL *s)
+         return 1;
+     }
+ 
+-    /*
+-     * KTLS reads full records. If there is any data left,
+-     * then it is from before enabling ktls
+-     */
+-    if (BIO_get_ktls_recv(s->rbio) && !is_ktls_left)
++    if (using_ktls)
+         goto skip_decryption;
+ 
+     if (s->read_hash != NULL) {
+@@ -684,21 +693,29 @@ skip_decryption:
+         if (SSL_IS_TLS13(s)
+             && s->enc_read_ctx != NULL
+             && thisrr->type != SSL3_RT_ALERT) {
+-            size_t end;
++            /*
++             * The following logic are irrelevant in KTLS: the kernel provides
++             * unprotected record and thus record type represent the actual
++             * content type, and padding is already removed and thisrr->type and
++             * thisrr->length should have the correct values.
++             */
++            if (!using_ktls) {
++                size_t end;
++                if (thisrr->length == 0
++                        || thisrr->type != SSL3_RT_APPLICATION_DATA) {
++                    SSLfatal(s, SSL_AD_UNEXPECTED_MESSAGE, SSL_R_BAD_RECORD_TYPE);
++                    goto end;
++                }
+ 
+-            if (thisrr->length == 0
+-                || thisrr->type != SSL3_RT_APPLICATION_DATA) {
+-                SSLfatal(s, SSL_AD_UNEXPECTED_MESSAGE, SSL_R_BAD_RECORD_TYPE);
+-                goto end;
++                /* Strip trailing padding */
++                for (end = thisrr->length - 1; end > 0 && thisrr->data[end] == 0;
++                     end--)
++                    continue;
++
++                thisrr->length = end;
++                thisrr->type = thisrr->data[end];
+             }
+ 
+-            /* Strip trailing padding */
+-            for (end = thisrr->length - 1; end > 0 && thisrr->data[end] == 0;
+-                end--)
+-                continue;
+-
+-            thisrr->length = end;
+-            thisrr->type = thisrr->data[end];
+             if (thisrr->type != SSL3_RT_APPLICATION_DATA
+                 && thisrr->type != SSL3_RT_ALERT
+                 && thisrr->type != SSL3_RT_HANDSHAKE) {
+@@ -707,7 +724,7 @@ skip_decryption:
+             }
+             if (s->msg_callback)
+                 s->msg_callback(0, s->version, SSL3_RT_INNER_CONTENT_TYPE,
+-                    &thisrr->data[end], 1, s, s->msg_callback_arg);
++                    &thisrr->type, 1, s, s->msg_callback_arg);
+         }
+ 
+         /*
+@@ -730,9 +747,8 @@ skip_decryption:
+          * Therefore we have to rely on KTLS to check the plaintext length
+          * limit in the kernel.
+          */
+-        if (thisrr->length > SSL3_RT_MAX_PLAIN_LENGTH
+-            && (!BIO_get_ktls_recv(s->rbio) || is_ktls_left)) {
+-            SSLfatal(s, SSL_AD_RECORD_OVERFLOW, SSL_R_DATA_LENGTH_TOO_LONG);
++        if (thisrr->length > SSL3_RT_MAX_PLAIN_LENGTH && !using_ktls) {
++            SSLfatal(s, SSL_AD_RECORD_OVERFLOW, SSL_R_DATA_LENGTH_TOO_LONG);
+             goto end;
+         }
+ 
+diff --git ssl/ssl_local.h ssl/ssl_local.h
+index 5471e900b8..79ced2f468 100644
+--- ssl/ssl_local.h
++++ ssl/ssl_local.h
+@@ -2774,9 +2774,9 @@ int ktls_check_supported_cipher(const SSL *s, const EV
+ /* ktls.c */
+ int ktls_check_supported_cipher(const SSL *s, const EVP_CIPHER *c,
+     const EVP_CIPHER_CTX *dd);
+-int ktls_configure_crypto(const SSL *s, const EVP_CIPHER *c, EVP_CIPHER_CTX *dd,
++int ktls_configure_crypto(SSL *s, const EVP_CIPHER *c, EVP_CIPHER_CTX *dd,
+     void *rl_sequence, ktls_crypto_info_t *crypto_info,
+-    unsigned char **rec_seq, unsigned char *iv,
++    int is_tx, unsigned char *iv,
+     unsigned char *key, unsigned char *mac_key,
+     size_t mac_secret_size);
+ #endif
+diff --git ssl/t1_enc.c ssl/t1_enc.c
+index 237a19cd93..900ba14fbd 100644
+--- ssl/t1_enc.c
++++ ssl/t1_enc.c
+@@ -98,41 +98,6 @@ static int tls1_generate_key_block(SSL *s, unsigned ch
+     return ret;
+ }
+
+-#ifndef OPENSSL_NO_KTLS
+-/*
+- * Count the number of records that were not processed yet from record boundary.
+- *
+- * This function assumes that there are only fully formed records read in the
+- * record layer. If read_ahead is enabled, then this might be false and this
+- * function will fail.
+- */
+-#ifndef OPENSSL_NO_KTLS_RX
+-static int count_unprocessed_records(SSL *s)
+-{
+-    SSL3_BUFFER *rbuf = RECORD_LAYER_get_rbuf(&s->rlayer);
+-    PACKET pkt, subpkt;
+-    int count = 0;
+-
+-    if (!PACKET_buf_init(&pkt, rbuf->buf + rbuf->offset, rbuf->left))
+-        return -1;
+-
+-    while (PACKET_remaining(&pkt) > 0) {
+-        /* Skip record type and version */
+-        if (!PACKET_forward(&pkt, 3))
+-            return -1;
+-
+-        /* Read until next record */
+-        if (!PACKET_get_length_prefixed_2(&pkt, &subpkt))
+-            return -1;
+-
+-        count += 1;
+-    }
+-
+-    return count;
+-}
+-#endif
+-#endif
+-
+ int tls_provider_set_tls_params(SSL *s, EVP_CIPHER_CTX *ctx,
+     const EVP_CIPHER *ciph,
+     const EVP_MD *md)
+@@ -199,12 +164,7 @@ int tls1_change_cipher_state(SSL *s, int which)
+     int reuse_dd = 0;
+ #ifndef OPENSSL_NO_KTLS
+     ktls_crypto_info_t crypto_info;
+-    unsigned char *rec_seq;
+     void *rl_sequence;
+-#ifndef OPENSSL_NO_KTLS_RX
+-    int count_unprocessed;
+-    int bit;
+-#endif
+     BIO *bio;
+ #endif
+
+@@ -478,29 +438,10 @@ int tls1_change_cipher_state(SSL *s, int which)
+     else
+         rl_sequence = RECORD_LAYER_get_read_sequence(&s->rlayer);
+
+-    if (!ktls_configure_crypto(s, c, dd, rl_sequence, &crypto_info, &rec_seq,
+-            iv, key, ms, *mac_secret_size))
+-        goto skip_ktls;
+-
+-    if (which & SSL3_CC_READ) {
+-#ifndef OPENSSL_NO_KTLS_RX
+-        count_unprocessed = count_unprocessed_records(s);
+-        if (count_unprocessed < 0)
+-            goto skip_ktls;
+-
+-        /* increment the crypto_info record sequence */
+-        while (count_unprocessed) {
+-            for (bit = 7; bit >= 0; bit--) { /* increment */
+-                ++rec_seq[bit];
+-                if (rec_seq[bit] != 0)
+-                    break;
+-            }
+-            count_unprocessed--;
+-        }
+-#else
+-        goto skip_ktls;
+-#endif
+-    }
++    if (!ktls_configure_crypto(s, c, dd, rl_sequence, &crypto_info,
++            which & SSL3_CC_WRITE, iv, key, ms,
++            *mac_secret_size))
++      goto skip_ktls;
+
+     /* ktls works with user provided buffers directly */
+     if (BIO_set_ktls(bio, &crypto_info, which & SSL3_CC_WRITE)) {
+diff --git ssl/tls13_enc.c ssl/tls13_enc.c
+index 12388922e3..eaab0e2a74 100644
+--- ssl/tls13_enc.c
++++ ssl/tls13_enc.c
+@@ -434,6 +434,7 @@ int tls13_change_cipher_state(SSL *s, int which)
+     const EVP_CIPHER *cipher = NULL;
+ #if !defined(OPENSSL_NO_KTLS) && defined(OPENSSL_KTLS_TLS13)
+     ktls_crypto_info_t crypto_info;
++    void *rl_sequence;
+     BIO *bio;
+ #endif
+ 
+@@ -690,8 +691,7 @@ int tls13_change_cipher_state(SSL *s, int which)
+         s->statem.enc_write_state = ENC_WRITE_STATE_VALID;
+ #ifndef OPENSSL_NO_KTLS
+ #if defined(OPENSSL_KTLS_TLS13)
+-    if (!(which & SSL3_CC_WRITE)
+-        || !(which & SSL3_CC_APPLICATION)
++    if (!(which & SSL3_CC_APPLICATION)
+         || (s->options & SSL_OP_ENABLE_KTLS) == 0)
+         goto skip_ktls;
+
+@@ -705,7 +705,10 @@ int tls13_change_cipher_state(SSL *s, int which)
+     if (!ktls_check_supported_cipher(s, cipher, ciph_ctx))
+         goto skip_ktls;
+ 
+-    bio = s->wbio;
++    if (which & SSL3_CC_WRITE)
++        bio = s->wbio;
++    else
++        bio = s->rbio;
+ 
+     if (!ossl_assert(bio != NULL)) {
+         SSLfatal(s, SSL_AD_INTERNAL_ERROR, ERR_R_INTERNAL_ERROR);
+@@ -715,18 +718,26 @@ int tls13_change_cipher_state(SSL *s, int which)
+     }
+
+     /* All future data will get encrypted by ktls. Flush the BIO or skip ktls */
+-    if (BIO_flush(bio) <= 0)
+-        goto skip_ktls;
++    if (which & SSL3_CC_WRITE) {
++       if (BIO_flush(bio) <= 0)
++            goto skip_ktls;
++    }
+
+     /* configure kernel crypto structure */
+-    if (!ktls_configure_crypto(s, cipher, ciph_ctx,
+-            RECORD_LAYER_get_write_sequence(&s->rlayer),
+-            &crypto_info, NULL, iv, key, NULL, 0))
++    if (which & SSL3_CC_WRITE)
++        rl_sequence = RECORD_LAYER_get_write_sequence(&s->rlayer);
++    else
++        rl_sequence = RECORD_LAYER_get_read_sequence(&s->rlayer);
++
++    if (!ktls_configure_crypto(s, cipher, ciph_ctx, rl_sequence, &crypto_info,
++                               which & SSL3_CC_WRITE, iv, key, NULL, 0))
+         goto skip_ktls;
+
+     /* ktls works with user provided buffers directly */
+-    if (BIO_set_ktls(bio, &crypto_info, which & SSL3_CC_WRITE))
+-        ssl3_release_write_buffer(s);
++    if (BIO_set_ktls(bio, &crypto_info, which & SSL3_CC_WRITE)) {
++        if (which & SSL3_CC_WRITE)
++            ssl3_release_write_buffer(s);
++    }
+ skip_ktls:
+ #endif
+ #endif
+diff --git test/sslapitest.c test/sslapitest.c
+index 2911d6e94b..faf2eec2bc 100644
+--- test/sslapitest.c
++++ test/sslapitest.c
+@@ -1243,7 +1243,7 @@ static int execute_test_ktls(int cis_ktls, int sis_ktls,
+ #if defined(OPENSSL_NO_KTLS_RX)
+     rx_supported = 0;
+ #else
+-    rx_supported = (tls_version != TLS1_3_VERSION);
++    rx_supported = 1;
+ #endif
+     if (!cis_ktls || !rx_supported) {
+         if (!TEST_false(BIO_get_ktls_recv(clientssl->rbio)))
diff --git a/security/openssl30/files/extra-patch-util_find-doc-nits b/security/openssl30/files/extra-patch-util_find-doc-nits
new file mode 100644
index 000000000000..e4fc20a06252
--- /dev/null
+++ b/security/openssl30/files/extra-patch-util_find-doc-nits
@@ -0,0 +1,20 @@
+--- util/find-doc-nits.orig	2023-08-01 13:47:24 UTC
++++ util/find-doc-nits
+@@ -80,7 +80,7 @@ my $temp = '/tmp/docnits.txt';
+ my $OUT;
+ my $status = 0;
+ 
+-$opt_m = "man1,man3,man5,man7" unless $opt_m;
++$opt_m = "man1,man5" unless $opt_m;
+ die "Argument of -m option may contain only man1, man3, man5, and/or man7"
+     unless $opt_m =~ /^(man[1357][, ]?)*$/;
+ my @sections = ( split /[, ]/, $opt_m );
+@@ -725,7 +725,7 @@ sub check {
+         next if $target eq '';                  # Skip if links within page, or
+         next if $target =~ /::/;                #   links to a Perl module, or
+         next if $target =~ /^https?:/;          #   is a URL link, or
+-        next if $target =~ /\([1357]\)$/;       #   it has a section
++        next if $target =~ /\([15]\)$/;       #   it has a section
+         err($id, "Missing man section number (likely, $mansect) in L<$target>")
+     }
+     # Check for proper links to commands.
diff --git a/security/openssl30/files/patch-Configurations_10-main.conf b/security/openssl30/files/patch-Configurations_10-main.conf
new file mode 100644
index 000000000000..82503c0ff90c
--- /dev/null
+++ b/security/openssl30/files/patch-Configurations_10-main.conf
@@ -0,0 +1,35 @@
+--- Configurations/10-main.conf.orig	2022-04-12 16:29:42 UTC
++++ Configurations/10-main.conf
+@@ -1069,6 +1069,32 @@ my %targets = (
+         perlasm_scheme   => "linux64",
+     },
+ 
++    "BSD-ppc" => {
++        inherit_from     => [ "BSD-generic32" ],
++        asm_arch         => 'ppc32',
++        perlasm_scheme   => "linux32",
++        lib_cppflags     => add("-DB_ENDIAN"),
++    },
++
++    "BSD-ppc64" => {
++        inherit_from     => [ "BSD-generic64" ],
++        cflags           => add("-m64"),
++        cxxflags         => add("-m64"),
++        lib_cppflags     => add("-DB_ENDIAN"),
++        asm_arch         => 'ppc64',
++        perlasm_scheme   => "linux64",
++    },
++
++    "BSD-ppc64le" => {
++        inherit_from     => [ "BSD-generic64" ],
++        cflags           => add("-m64"),
++        cxxflags         => add("-m64"),
++        lib_cppflags     => add("-DL_ENDIAN"),
++        asm_arch         => 'ppc64',
++        perlasm_scheme   => "linux64le",
++    },
++
++
+     "bsdi-elf-gcc" => {
+         inherit_from     => [ "BASE_unix" ],
+         CC               => "gcc",
diff --git a/security/openssl30/files/patch-Configure b/security/openssl30/files/patch-Configure
new file mode 100644
index 000000000000..c26823c674f3
--- /dev/null
+++ b/security/openssl30/files/patch-Configure
@@ -0,0 +1,11 @@
+--- Configure.orig	2022-04-12 16:30:34 UTC
++++ Configure
+@@ -1549,7 +1549,7 @@ my %predefined_CXX = $config{CXX}
+ 
+ unless ($disabled{asm}) {
+     # big endian systems can use ELFv2 ABI
+-    if ($target eq "linux-ppc64") {
++    if ($target eq "linux-ppc64" || $target eq "BSD-ppc64") {
+         $target{perlasm_scheme} = "linux64v2" if ($predefined_C{_CALL_ELF} == 2);
+     }
+ }
diff --git a/security/openssl30/files/patch-crypto_async_arch_async__posix.h b/security/openssl30/files/patch-crypto_async_arch_async__posix.h
new file mode 100644
index 000000000000..8690f951fa42
--- /dev/null
+++ b/security/openssl30/files/patch-crypto_async_arch_async__posix.h
@@ -0,0 +1,32 @@
+commit e883812f463c1623249e038698ccaddf2baa34d8
+Author: Warner Losh <imp@FreeBSD.org>
+Date:   Mon Mar 18 19:48:22 2024 -0600
+
+    posix_async: FreeBSD also defines {make|swap|get|set}context
+
+    FreeBSD also defines {make|swap|get|set}context for backward
+    compatibility, despite also exposing POSIX_VERSION 200809L
+    in FreeBSD 15-current.
+
+    Note: There's no fallback for POSIX_VERSION 200809 without these
+    routines, so maybe that should be a #error? ... But that's a questionf
+    or upstream.
+
+    FreeBSD has defined these interfaces since FreeBSD 4.7, released over 20
+    years ago, so no further nuance in FreeBSD version number is necessary.
+
+    Pull Request:           https://github.com/openssl/openssl/pull/23885
+
+diff --git a/crypto/async/arch/async_posix.h b/crypto/async/arch/async_posix.h
+index a17c6b8e68af..2d97ec3acc9b 100644
+--- crypto/async/arch/async_posix.h
++++ crypto/async/arch/async_posix.h
+@@ -19,7 +19,7 @@
+ #include <unistd.h>
+ 
+ #if _POSIX_VERSION >= 200112L \
+-    && (_POSIX_VERSION < 200809L || defined(__GLIBC__))
++    && (_POSIX_VERSION < 200809L || defined(__GLIBC__) || defined(__FreeBSD__))
+ 
+ #include <pthread.h>
+ 
diff --git a/security/openssl30/files/patch-crypto_ppccap.c b/security/openssl30/files/patch-crypto_ppccap.c
new file mode 100644
index 000000000000..6783e0b13c2d
--- /dev/null
+++ b/security/openssl30/files/patch-crypto_ppccap.c
@@ -0,0 +1,34 @@
+--- crypto/ppccap.c.orig	2022-04-12 16:31:27 UTC
++++ crypto/ppccap.c
+@@ -117,14 +117,18 @@ static unsigned long getauxval(unsigned long key)
+ #endif
+ 
+ /* I wish <sys/auxv.h> was universally available */
+-#define HWCAP 16 /* AT_HWCAP */
++#ifndef AT_HWCAP
++# define AT_HWCAP 16 /* AT_HWCAP */
++#endif
+ #define HWCAP_PPC64 (1U << 30)
+ #define HWCAP_ALTIVEC (1U << 28)
+ #define HWCAP_FPU (1U << 27)
+ #define HWCAP_POWER6_EXT (1U << 9)
+ #define HWCAP_VSX (1U << 7)
+ 
+-#define HWCAP2 26 /* AT_HWCAP2 */
++#ifndef AT_HWCAP2
++#define AT_HWCAP2 26 /* AT_HWCAP2 */
++#endif
+ #define HWCAP_VEC_CRYPTO (1U << 25)
+ #define HWCAP_ARCH_3_00 (1U << 23)
+ 
+@@ -215,8 +219,8 @@ void OPENSSL_cpuid_setup(void)
+ 
+ #ifdef OSSL_IMPLEMENT_GETAUXVAL
+     {
+-        unsigned long hwcap = getauxval(HWCAP);
+-        unsigned long hwcap2 = getauxval(HWCAP2);
++        unsigned long hwcap = getauxval(AT_HWCAP);
++        unsigned long hwcap2 = getauxval(AT_HWCAP2);
+ 
+         if (hwcap & HWCAP_FPU) {
+             OPENSSL_ppccap_P |= PPC_FPU;
diff --git a/security/openssl30/files/patch-crypto_threads__pthread.c b/security/openssl30/files/patch-crypto_threads__pthread.c
new file mode 100644
index 000000000000..3347170e0bd0
--- /dev/null
+++ b/security/openssl30/files/patch-crypto_threads__pthread.c
@@ -0,0 +1,13 @@
+--- crypto/threads_pthread.c.orig	2022-11-01 14:14:36 UTC
++++ crypto/threads_pthread.c
+@@ -29,6 +29,10 @@
+ #define BROKEN_CLANG_ATOMICS
+ #endif
+ 
++#if defined(__FreeBSD__) && defined(__i386__)
++#define BROKEN_CLANG_ATOMICS
++#endif
++
+ #if defined(OPENSSL_THREADS) && !defined(CRYPTO_TDEBUG) && !defined(OPENSSL_SYS_WINDOWS)
+ 
+ # if defined(OPENSSL_SYS_UNIX)
diff --git a/security/openssl30/files/patch-util_perl_OpenSSL_config.pm b/security/openssl30/files/patch-util_perl_OpenSSL_config.pm
new file mode 100644
index 000000000000..9c669372a4f1
--- /dev/null
+++ b/security/openssl30/files/patch-util_perl_OpenSSL_config.pm
@@ -0,0 +1,14 @@
+--- util/perl/OpenSSL/config.pm.orig	2022-04-12 16:34:06 UTC
++++ util/perl/OpenSSL/config.pm
+@@ -747,8 +747,9 @@ EOF
+                                     disable => [ 'sse2' ] } ],
+       [ 'alpha.*-.*-.*bsd.*',     { target => "BSD-generic64",
+                                     defines => [ 'L_ENDIAN' ] } ],
+-      [ 'powerpc64-.*-.*bsd.*',   { target => "BSD-generic64",
+-                                    defines => [ 'B_ENDIAN' ] } ],
++      [ 'powerpc-.*-.*bsd.*',     { target => "BSD-ppc" } ],
++      [ 'powerpc64-.*-.*bsd.*',   { target => "BSD-ppc64" } ],
++      [ 'powerpc64le-.*-.*bsd.*', { target => "BSD-ppc64le" } ],
+       [ 'riscv64-.*-.*bsd.*',     { target => "BSD-riscv64" } ],
+       [ 'sparc64-.*-.*bsd.*',     { target => "BSD-sparc64" } ],
+       [ 'ia64-.*-.*bsd.*',        { target => "BSD-ia64" } ],
diff --git a/security/openssl30/pkg-descr b/security/openssl30/pkg-descr
*** 334 LINES SKIPPED ***