new file mode 100644
@@ -0,0 +1,285 @@
+From 5e4e8452328804948d042235bbf58ca457795857 Mon Sep 17 00:00:00 2001
+From: Bob Beck <beck@openssl.org>
+Date: Mon, 16 Feb 2026 15:15:55 -0700
+Subject: [PATCH] Improve future OpenSSL compatibility
+
+Avoid calling deprecated OpenSSL functions when compiling against
+versions of OpenSSL where they are deprecated. Add
+-DOPENSSL_NO_DEPRECATED to the linux-clang-openssl CI build to help
+detect calls to deprecated functions in the future.
+
+Use const pointer variables to hold values retrieved by accessors
+which will return const pointers in OpenSSL 4.0. Define macros to
+make certain functions accept these const pointers in versions of
+OpenSSL where they don't already do so.
+
+Use accessor functions instead of direct field access for ASN1_STRING
+values, as the type will become opaque in OpenSSL 4.0.
+
+The PKINIT code is written to assume that DHX support was not present
+until OpenSSL 1.1, but it was added in release 1.0.2, causing a
+compilation error against 1.0.2 from a double definition of
+EVP_PKEY_DHX. Minimally fix the compilation error. (The custom DHX
+marshalling code to support 1.0.x could be removed, as 1.0.2 is the
+minimum version after commit f5bbfa4821cf590a4748f96d0e016bc0485e95c4,
+but the plan is to remove 1.0.x compatibility shortly.)
+
+Contains work by Frederik Wedel-Heinen
+<frederik.wedel-heinen@dencrypt.dk> and Dimitri John Ledkov
+<dimitri.ledkov@surgut.co.uk>.
+
+[ghudson@mit.edu: combined numerous commits; added compatibility
+macros; rewrote commit message; fixed 1.0.2 compatibility issue]
+Upstream-Status: Backport [https://github.com/krb5/krb5/commit/5e4e84523288]
+
+Note: .github/workflows/build.yml hunk dropped (CI-only, not relevant
+for OE builds).
+Signed-off-by: Jaipaul Cheernam <jaipaul.cheernam@est.tech>
+---
+ .github/workflows/build.yml | 10 ++--
+ .../preauth/pkinit/pkinit_crypto_openssl.c | 54 ++++++++++++++-----
+ src/plugins/tls/k5tls/openssl.c | 26 +++++++--
+ 3 files changed, 68 insertions(+), 22 deletions(-)
+
+diff --git a/src/plugins/preauth/pkinit/pkinit_crypto_openssl.c b/src/plugins/preauth/pkinit/pkinit_crypto_openssl.c
+index d1fe18e5ab..aa969aa37c 100644
+--- a/src/plugins/preauth/pkinit/pkinit_crypto_openssl.c
++++ b/src/plugins/preauth/pkinit/pkinit_crypto_openssl.c
+@@ -209,13 +209,20 @@ create_identifiers_from_stack(STACK_OF(X509) *sk,
+ #define EVP_MD_CTX_new EVP_MD_CTX_create
+ #define EVP_MD_CTX_free EVP_MD_CTX_destroy
+ #define ASN1_STRING_get0_data ASN1_STRING_data
++#define X509_STORE_CTX_set0_trusted_stack X509_STORE_CTX_trusted_stack
+
+ /*
+- * 1.1 adds DHX support, which uses the RFC 3279 DomainParameters encoding we
++ * 1.0.2 adds DHX support, which uses the RFC 3279 DomainParameters encoding we
+ * need for PKINIT. For 1.0 we must use the original DH type when creating
+ * EVP_PKEY objects.
+ */
++#ifndef EVP_PKEY_DHX
+ #define EVP_PKEY_DHX EVP_PKEY_DH
++#endif
++
++/* Make X509_NAME_print_ex() accept a const name pointer by adding a cast. */
++#define X509_NAME_print_ex(a, b, c, d) \
++ X509_NAME_print_ex(a, (X509_NAME *)b, c, d)
+
+ /* 1.1 makes many handle types opaque and adds accessors. Add compatibility
+ * versions of the new accessors we use for pre-1.1. */
+@@ -295,6 +302,10 @@ compat_ECDSA_SIG_set0(ECDSA_SIG *sig, BIGNUM *r, BIGNUM *s)
+ #define EVP_PKEY_get_bits EVP_PKEY_bits
+ #define EVP_PKEY_get_base_id EVP_PKEY_base_id
+
++/* Make X509_dup() accept a const pointer by adding a cast. */
++#define X509_dup(a) X509_dup((X509 *)a)
++#define i2d_X509_NAME(a, b) i2d_X509_NAME((X509_NAME *)a, b)
++
+ /*
+ * Convert *dh to an EVP_PKEY object, taking ownership of *dh and setting it to
+ * NULL. On error, return NULL and do not take ownership of or change *dh.
+@@ -318,6 +329,11 @@ dh_to_pkey(DH **dh)
+ }
+ #endif /* OPENSSL_VERSION_NUMBER < 0x30000000L */
+
++#if OPENSSL_VERSION_NUMBER < 0x40000000L
++/* Make X509V3_EXT_d2i() accept a const pointer by adding a cast. */
++#define X509V3_EXT_d2i(a) X509V3_EXT_d2i((X509_EXTENSION *)a)
++#endif
++
+ /* Encode a bignum as an ASN.1 integer in DER. */
+ static int
+ encode_bn_der(const BIGNUM *bn, uint8_t **der_out, int *len_out)
+@@ -1134,6 +1150,13 @@ oerr_cert(krb5_context context, krb5_error_code code, X509_STORE_CTX *certctx,
+ return oerr(context, code, _("%s (depth %d): %s"), msg, depth, errstr);
+ }
+
++/* Convert an OpenSSL ASN.1 string value to krb5_data, without copying. */
++static inline krb5_data
++asn1string_to_data(ASN1_STRING *s)
++{
++ return make_data((char *)ASN1_STRING_get0_data(s), ASN1_STRING_length(s));
++}
++
+ krb5_error_code
+ pkinit_init_plg_crypto(krb5_context context,
+ pkinit_plg_crypto_context *cryptoctx)
+@@ -1775,7 +1798,7 @@ cms_signeddata_create(krb5_context context,
+ goto cleanup;
+ X509_STORE_CTX_init(certctx, certstore, id_cryptoctx->my_cert,
+ id_cryptoctx->intermediateCAs);
+- X509_STORE_CTX_trusted_stack(certctx, id_cryptoctx->trustedCAs);
++ X509_STORE_CTX_set0_trusted_stack(certctx, id_cryptoctx->trustedCAs);
+ if (!X509_verify_cert(certctx)) {
+ retval = oerr_cert(context, 0, certctx,
+ _("Failed to verify own certificate"));
+@@ -2002,7 +2025,7 @@ cms_signeddata_verify(krb5_context context,
+ unsigned char *d;
+ *is_signed = 0;
+ octets = CMS_get0_content(cms);
+- if (!octets || ((*octets)->type != V_ASN1_OCTET_STRING)) {
++ if (!octets || (ASN1_STRING_type(*octets) != V_ASN1_OCTET_STRING)) {
+ retval = KRB5KDC_ERR_PREAUTH_FAILED;
+ krb5_set_error_message(context, retval,
+ _("Invalid pkinit packet: octet string "
+@@ -2058,7 +2081,8 @@ cms_signeddata_verify(krb5_context context,
+ /* We cannot use CMS_dataInit because there may be no digest */
+ octets = CMS_get0_content(cms);
+ if (octets)
+- out = BIO_new_mem_buf((*octets)->data, (*octets)->length);
++ out = BIO_new_mem_buf(ASN1_STRING_get0_data(*octets),
++ ASN1_STRING_length(*octets));
+ if (out == NULL)
+ goto cleanup;
+ } else {
+@@ -2118,7 +2142,7 @@ cms_signeddata_verify(krb5_context context,
+
+ /* add trusted CAs certificates for cert verification */
+ if (idctx->trustedCAs != NULL)
+- X509_STORE_CTX_trusted_stack(cert_ctx, idctx->trustedCAs);
++ X509_STORE_CTX_set0_trusted_stack(cert_ctx, idctx->trustedCAs);
+ else {
+ pkiDebug("unable to find any trusted CAs\n");
+ goto cleanup;
+@@ -2156,7 +2180,7 @@ cms_signeddata_verify(krb5_context context,
+ i = X509_verify_cert(cert_ctx);
+ if (i <= 0) {
+ int j = X509_STORE_CTX_get_error(cert_ctx);
+- X509 *cert;
++ const X509 *cert;
+
+ cert = X509_STORE_CTX_get_current_cert(cert_ctx);
+ reqctx->received_cert = X509_dup(cert);
+@@ -2316,7 +2340,7 @@ crypto_retrieve_X509_sans(krb5_context context,
+ krb5_principal *princs = NULL;
+ char **upns = NULL;
+ unsigned char **dnss = NULL;
+- X509_EXTENSION *ext = NULL;
++ const X509_EXTENSION *ext = NULL;
+ GENERAL_NAMES *ialt = NULL;
+ GENERAL_NAME *gen = NULL;
+
+@@ -2379,8 +2403,7 @@ crypto_retrieve_X509_sans(krb5_context context,
+ gen = sk_GENERAL_NAME_value(ialt, i);
+ switch (gen->type) {
+ case GEN_OTHERNAME:
+- name.length = gen->d.otherName->value->value.sequence->length;
+- name.data = (char *)gen->d.otherName->value->value.sequence->data;
++ name = asn1string_to_data(gen->d.otherName->value->value.sequence);
+ if (princs != NULL &&
+ OBJ_cmp(plgctx->id_pkinit_san,
+ gen->d.otherName->type_id) == 0) {
+@@ -2414,12 +2437,13 @@ crypto_retrieve_X509_sans(krb5_context context,
+ case GEN_DNS:
+ if (dnss != NULL) {
+ /* Prevent abuse of embedded null characters. */
+- if (memchr(gen->d.dNSName->data, '\0', gen->d.dNSName->length))
++ if (memchr(ASN1_STRING_get0_data(gen->d.dNSName), '\0',
++ ASN1_STRING_length(gen->d.dNSName)))
+ break;
+ pkiDebug("%s: found dns name = %s\n", __FUNCTION__,
+- gen->d.dNSName->data);
++ ASN1_STRING_get0_data(gen->d.dNSName));
+ dnss[d] = (unsigned char *)
+- strdup((char *)gen->d.dNSName->data);
++ strdup((char *)ASN1_STRING_get0_data(gen->d.dNSName));
+ if (dnss[d] == NULL) {
+ pkiDebug("%s: failed to duplicate dns name\n",
+ __FUNCTION__);
+@@ -3094,8 +3118,10 @@ int
+ pkinit_openssl_init(void)
+ {
+ /* Initialize OpenSSL. */
++#if OPENSSL_VERSION_NUMBER < 0x10100000L
+ ERR_load_crypto_strings();
+ OpenSSL_add_all_algorithms();
++#endif
+ return 0;
+ }
+
+@@ -4766,7 +4792,7 @@ crypto_retrieve_X509_key_usage(krb5_context context,
+ }
+
+ static krb5_error_code
+-rfc2253_name(X509_NAME *name, char **str_out)
++rfc2253_name(const X509_NAME *name, char **str_out)
+ {
+ BIO *b = NULL;
+ char *str;
+@@ -5227,7 +5253,7 @@ create_identifiers_from_stack(STACK_OF(X509) *sk,
+ int i = 0, sk_size = sk_X509_num(sk);
+ krb5_external_principal_identifier **krb5_cas = NULL;
+ X509 *x = NULL;
+- X509_NAME *xn = NULL;
++ const X509_NAME *xn = NULL;
+ unsigned char *p = NULL;
+ int len = 0;
+ PKCS7_ISSUER_AND_SERIAL *is = NULL;
+diff --git a/src/plugins/tls/k5tls/openssl.c b/src/plugins/tls/k5tls/openssl.c
+index 42d72dc9ec..7763327b7a 100644
+--- a/src/plugins/tls/k5tls/openssl.c
++++ b/src/plugins/tls/k5tls/openssl.c
+@@ -38,6 +38,24 @@
+ #include <openssl/x509v3.h>
+ #include <dirent.h>
+
++#if OPENSSL_VERSION_NUMBER < 0x10100000L
++/* Make X509_get_subject_name() accept a const pointer by adding a cast. */
++#define X509_get_subject_name(a) X509_get_subject_name((X509 *)a)
++
++/* OpenSSL 1.0 did not have TLS_client_method(); use the best alternative. */
++#define TLS_client_method() SSLv23_client_method()
++#endif
++
++#if OPENSSL_VERSION_NUMBER < 0x40000000L
++/*
++ * OpenSSL 4.0 constifies the result of X509_STORE_CTX_get_current_cert() and
++ * the input of X509_check_host() and X509_check_ip_asc(). For prior versions,
++ * make the latter two functions accept const pointers via a cast.
++ */
++#define X509_check_host(a, b, c, d, e) X509_check_host((X509 *)a, b, c, d, e)
++#define X509_check_ip_asc(a, b, c) X509_check_ip_asc((X509 *)a, b, c)
++#endif
++
+ struct k5_tls_handle_st {
+ SSL *ssl;
+ char *servername;
+@@ -51,9 +69,11 @@ MAKE_INIT_FUNCTION(init_openssl);
+ int
+ init_openssl(void)
+ {
++#if OPENSSL_VERSION_NUMBER < 0x10100000L
+ SSL_library_init();
+ SSL_load_error_strings();
+ OpenSSL_add_all_algorithms();
++#endif
+ ex_context_id = SSL_get_ex_new_index(0, NULL, NULL, NULL, NULL);
+ ex_handle_id = SSL_get_ex_new_index(0, NULL, NULL, NULL, NULL);
+ return 0;
+@@ -72,7 +92,7 @@ flush_errors(krb5_context context)
+ }
+
+ static krb5_boolean
+-check_cert_name_or_ip(X509 *x, const char *expected_name)
++check_cert_name_or_ip(const X509 *x, const char *expected_name)
+ {
+ struct in_addr in;
+ struct in6_addr in6;
+@@ -89,7 +109,7 @@ check_cert_name_or_ip(X509 *x, const char *expected_name)
+ static int
+ verify_callback(int preverify_ok, X509_STORE_CTX *store_ctx)
+ {
+- X509 *x;
++ const X509 *x;
+ SSL *ssl;
+ BIO *bio;
+ krb5_context context;
+@@ -246,7 +266,7 @@ setup(krb5_context context, SOCKET fd, const char *servername,
+ return KRB5_PLUGIN_OP_NOTSUPP;
+
+ /* Do general SSL library setup. */
+- ctx = SSL_CTX_new(SSLv23_client_method());
++ ctx = SSL_CTX_new(TLS_client_method());
+ if (ctx == NULL)
+ goto error;
+
new file mode 100644
@@ -0,0 +1,627 @@
+From 736397a909005913b09c1d84a32255de71aadeca Mon Sep 17 00:00:00 2001
+From: Greg Hudson <ghudson@mit.edu>
+Date: Tue, 10 Mar 2026 23:06:59 -0400
+Subject: [PATCH] Remove OpenSSL 1.0 support
+
+Upstream-Status: Backport [https://github.com/krb5/krb5/commit/f8a47bf037af]
+
+Note: Context adjusted for krb5 1.22.2 (one hunk in
+pkinit_crypto_openssl.c had offset due to earlier patches).
+doc/mitK5features.rst hunk dropped (documentation only, outside src/).
+
+Signed-off-by: Jaipaul Cheernam <jaipaul.cheernam@est.tech>
+---
+ src/configure.ac | 4 +-
+ .../crypto/openssl/hash_provider/hash_evp.c | 7 -
+ src/lib/crypto/openssl/hmac.c | 27 --
+ src/lib/crypto/openssl/sha256.c | 7 -
+ .../preauth/pkinit/pkinit_crypto_openssl.c | 372 +-----------------
+ src/plugins/preauth/spake/openssl.c | 7 -
+ src/plugins/tls/k5tls/openssl.c | 13 -
+ 7 files changed, 4 insertions(+), 433 deletions(-)
+
+diff --git a/src/configure.ac b/src/configure.ac
+index 4325fae..9074a9f 100644
+--- a/src/configure.ac
++++ b/src/configure.ac
+@@ -1141,8 +1141,8 @@ enable_pkinit=try)
+ if test "$enable_pkinit" = yes || test "$enable_pkinit" = try; then
+ AC_CACHE_CHECK(for a recent enough OpenSSL, k5_cv_openssl_version_okay,
+ [AC_COMPILE_IFELSE([AC_LANG_SOURCE([#include <openssl/opensslv.h>
+-#if OPENSSL_VERSION_NUMBER < 0x10000000L
+-# error openssl is too old, need 1.0.0
++#if OPENSSL_VERSION_NUMBER < 0x10100000L
++# error openssl is too old, need 1.1.0
+ #endif
+ int i = 1;
+ ])], k5_cv_openssl_version_okay=yes, k5_cv_openssl_version_okay=no)])
+diff --git a/src/lib/crypto/openssl/hash_provider/hash_evp.c b/src/lib/crypto/openssl/hash_provider/hash_evp.c
+index f2fbffd..2269daa 100644
+--- a/src/lib/crypto/openssl/hash_provider/hash_evp.c
++++ b/src/lib/crypto/openssl/hash_provider/hash_evp.c
+@@ -37,13 +37,6 @@
+
+ #include <openssl/evp.h>
+
+-/* 1.1 standardizes constructor and destructor names, renaming
+- * EVP_MD_CTX_create and EVP_MD_CTX_destroy. */
+-#if OPENSSL_VERSION_NUMBER < 0x10100000L
+-#define EVP_MD_CTX_new EVP_MD_CTX_create
+-#define EVP_MD_CTX_free EVP_MD_CTX_destroy
+-#endif
+-
+ static krb5_error_code
+ hash_evp(const EVP_MD *type, const krb5_crypto_iov *data, size_t num_data,
+ krb5_data *output)
+diff --git a/src/lib/crypto/openssl/hmac.c b/src/lib/crypto/openssl/hmac.c
+index 799d700..6e91017 100644
+--- a/src/lib/crypto/openssl/hmac.c
++++ b/src/lib/crypto/openssl/hmac.c
+@@ -63,33 +63,6 @@
+ #include <openssl/hmac.h>
+ #endif
+
+-#if OPENSSL_VERSION_NUMBER < 0x10100000L
+-
+-/* OpenSSL 1.1 makes HMAC_CTX opaque, while 1.0 does not have pointer
+- * constructors or destructors. */
+-
+-#define HMAC_CTX_new compat_hmac_ctx_new
+-static HMAC_CTX *
+-compat_hmac_ctx_new(void)
+-{
+- HMAC_CTX *ctx;
+-
+- ctx = calloc(1, sizeof(*ctx));
+- if (ctx != NULL)
+- HMAC_CTX_init(ctx);
+- return ctx;
+-}
+-
+-#define HMAC_CTX_free compat_hmac_ctx_free
+-static void
+-compat_hmac_ctx_free(HMAC_CTX *ctx)
+-{
+- HMAC_CTX_cleanup(ctx);
+- free(ctx);
+-}
+-
+-#endif /* OPENSSL_VERSION_NUMBER < 0x10100000L */
+-
+ /*
+ * the HMAC transform looks like:
+ *
+diff --git a/src/lib/crypto/openssl/sha256.c b/src/lib/crypto/openssl/sha256.c
+index 855ebd7..6f2c5d9 100644
+--- a/src/lib/crypto/openssl/sha256.c
++++ b/src/lib/crypto/openssl/sha256.c
+@@ -36,13 +36,6 @@
+
+ #include <openssl/evp.h>
+
+-/* 1.1 standardizes constructor and destructor names, renaming
+- * EVP_MD_CTX_create and EVP_MD_CTX_destroy. */
+-#if OPENSSL_VERSION_NUMBER < 0x10100000L
+-#define EVP_MD_CTX_new EVP_MD_CTX_create
+-#define EVP_MD_CTX_free EVP_MD_CTX_destroy
+-#endif
+-
+ krb5_error_code
+ k5_sha256(const krb5_data *in, size_t n, uint8_t out[K5_SHA256_HASHLEN])
+ {
+diff --git a/src/plugins/preauth/pkinit/pkinit_crypto_openssl.c b/src/plugins/preauth/pkinit/pkinit_crypto_openssl.c
+index e70106f..2dd34dc 100644
+--- a/src/plugins/preauth/pkinit/pkinit_crypto_openssl.c
++++ b/src/plugins/preauth/pkinit/pkinit_crypto_openssl.c
+@@ -201,100 +201,9 @@ static krb5_error_code
+ create_identifiers_from_stack(STACK_OF(X509) *sk,
+ krb5_external_principal_identifier *** ids);
+
+-#if OPENSSL_VERSION_NUMBER < 0x10100000L
+-
+-/* 1.1 standardizes constructor and destructor names, renaming
+- * EVP_MD_CTX_{create,destroy} and deprecating ASN1_STRING_data. */
+-
+-#define EVP_MD_CTX_new EVP_MD_CTX_create
+-#define EVP_MD_CTX_free EVP_MD_CTX_destroy
+-#define ASN1_STRING_get0_data ASN1_STRING_data
+-#define X509_STORE_CTX_set0_trusted_stack X509_STORE_CTX_trusted_stack
+-
+-/*
+- * 1.0.2 adds DHX support, which uses the RFC 3279 DomainParameters encoding we
+- * need for PKINIT. For 1.0 we must use the original DH type when creating
+- * EVP_PKEY objects.
+- */
+-#ifndef EVP_PKEY_DHX
+-#define EVP_PKEY_DHX EVP_PKEY_DH
+-#endif
+-
+-/* Make X509_NAME_print_ex() accept a const name pointer by adding a cast. */
+-#define X509_NAME_print_ex(a, b, c, d) \
+- X509_NAME_print_ex(a, (X509_NAME *)b, c, d)
+-
+-/* 1.1 makes many handle types opaque and adds accessors. Add compatibility
+- * versions of the new accessors we use for pre-1.1. */
+-
+-#define OBJ_get0_data(o) ((o)->data)
+-#define OBJ_length(o) ((o)->length)
+-
+-#define DH_set0_key compat_dh_set0_key
+-static int
+-compat_dh_set0_key(DH *dh, BIGNUM *pub, BIGNUM *priv)
+-{
+- if (pub != NULL) {
+- BN_clear_free(dh->pub_key);
+- dh->pub_key = pub;
+- }
+- if (priv != NULL) {
+- BN_clear_free(dh->priv_key);
+- dh->priv_key = priv;
+- }
+- return 1;
+-}
+-
+-#define DH_get0_key compat_dh_get0_key
+-static void compat_dh_get0_key(const DH *dh, const BIGNUM **pub,
+- const BIGNUM **priv)
+-{
+- if (pub != NULL)
+- *pub = dh->pub_key;
+- if (priv != NULL)
+- *priv = dh->priv_key;
+-}
+-
+-#define EVP_PKEY_get0_DH compat_get0_DH
+-static DH *
+-compat_get0_DH(const EVP_PKEY *pkey)
+-{
+- if (pkey->type != EVP_PKEY_DH)
+- return NULL;
+- return pkey->pkey.dh;
+-
+-}
+-
+-#define EVP_PKEY_get0_EC_KEY compat_get0_EC
+-static EC_KEY *
+-compat_get0_EC(const EVP_PKEY *pkey)
+-{
+- if (pkey->type != EVP_PKEY_EC)
+- return NULL;
+- return pkey->pkey.ec;
+-}
+-
+-#define ECDSA_SIG_set0 compat_ECDSA_SIG_set0
+-static int
+-compat_ECDSA_SIG_set0(ECDSA_SIG *sig, BIGNUM *r, BIGNUM *s)
+-{
+- sig->r = r;
+- sig->s = s;
+- return 1;
+-}
+-
+-/* Return true if the cert c includes a key usage which doesn't include u.
+- * Define using direct member access for pre-1.1. */
+-#define ku_reject(c, u) \
+- (((c)->ex_flags & EXFLAG_KUSAGE) && !((c)->ex_kusage & (u)))
+-
+-#else /* OPENSSL_VERSION_NUMBER >= 0x10100000L */
+-
+ /* Return true if the cert x includes a key usage which doesn't include u. */
+ #define ku_reject(c, u) (!(X509_get_key_usage(c) & (u)))
+
+-#endif
+-
+ #if OPENSSL_VERSION_NUMBER < 0x30000000L
+ /* OpenSSL 3.0 changes several preferred function names. */
+ #define EVP_PKEY_parameters_eq EVP_PKEY_cmp_parameters
+@@ -371,8 +280,6 @@ decode_bn_der(const uint8_t *der, size_t len)
+ return bn;
+ }
+
+-#if OPENSSL_VERSION_NUMBER >= 0x10100000L
+-
+ #if OPENSSL_VERSION_NUMBER >= 0x30000000L
+ static EVP_PKEY *
+ decode_params(const krb5_data *params_der, const char *type)
+@@ -442,195 +349,6 @@ decode_spki(const krb5_data *spki)
+ return d2i_PUBKEY(NULL, &inptr, spki->length);
+ }
+
+-#else /* OPENSSL_VERSION_NUMBER < 0x10100000L */
+-
+-/*
+- * OpenSSL 1.0 has no DHX support, so we need a custom decoder for RFC 3279
+- * DomainParameters, and we need to use X509_PUBKEY values to marshal
+- * SubjectPublicKeyInfo.
+- */
+-
+-typedef struct {
+- ASN1_BIT_STRING *seed;
+- BIGNUM *counter;
+-} int_dhvparams;
+-
+-typedef struct {
+- BIGNUM *p;
+- BIGNUM *q;
+- BIGNUM *g;
+- BIGNUM *j;
+- int_dhvparams *vparams;
+-} int_dhxparams;
+-
+-ASN1_SEQUENCE(int_dhvparams) = {
+- ASN1_SIMPLE(int_dhvparams, seed, ASN1_BIT_STRING),
+- ASN1_SIMPLE(int_dhvparams, counter, BIGNUM)
+-} ASN1_SEQUENCE_END(int_dhvparams);
+-
+-ASN1_SEQUENCE(int_dhxparams) = {
+- ASN1_SIMPLE(int_dhxparams, p, BIGNUM),
+- ASN1_SIMPLE(int_dhxparams, g, BIGNUM),
+- ASN1_SIMPLE(int_dhxparams, q, BIGNUM),
+- ASN1_OPT(int_dhxparams, j, BIGNUM),
+- ASN1_OPT(int_dhxparams, vparams, int_dhvparams)
+-} ASN1_SEQUENCE_END(int_dhxparams);
+-
+-static EVP_PKEY *
+-decode_dh_params(const krb5_data *params_der)
+-{
+- int_dhxparams *params;
+- DH *dh;
+- EVP_PKEY *pkey;
+- const uint8_t *p;
+-
+- dh = DH_new();
+- if (dh == NULL)
+- return NULL;
+-
+- p = (uint8_t *)params_der->data;
+- params = (int_dhxparams *)ASN1_item_d2i(NULL, &p, params_der->length,
+- ASN1_ITEM_rptr(int_dhxparams));
+- if (params == NULL) {
+- DH_free(dh);
+- return NULL;
+- }
+-
+- /* Steal p, q, and g from dhparams for dh. Ignore j and vparams. */
+- dh->p = params->p;
+- dh->q = params->q;
+- dh->g = params->g;
+- params->p = params->q = params->g = NULL;
+- ASN1_item_free((ASN1_VALUE *)params, ASN1_ITEM_rptr(int_dhxparams));
+- pkey = dh_to_pkey(&dh);
+- DH_free(dh);
+- return pkey;
+-}
+-
+-static krb5_error_code
+-encode_spki(EVP_PKEY *pkey, krb5_data *spki_out)
+-{
+- krb5_error_code ret = ENOMEM;
+- const DH *dh;
+- uint8_t *param_der = NULL, *pubkey_der = NULL, *outptr;
+- int param_der_len, pubkey_der_len, len;
+- X509_PUBKEY pubkey;
+- int_dhxparams dhxparams;
+- X509_ALGOR algor;
+- ASN1_OBJECT algorithm;
+- ASN1_TYPE parameter;
+- ASN1_STRING param_str, pubkey_str;
+-
+- if (EVP_PKEY_base_id(pkey) != EVP_PKEY_DH) {
+- /* Only DH keys require special encoding. */
+- len = i2d_PUBKEY(pkey, NULL);
+- ret = alloc_data(spki_out, len);
+- if (ret)
+- goto cleanup;
+- outptr = (uint8_t *)spki_out->data;
+- (void)i2d_PUBKEY(pkey, &outptr);
+- return 0;
+- }
+-
+- dh = EVP_PKEY_get0_DH(pkey);
+- if (dh == NULL)
+- goto cleanup;
+-
+- dhxparams.p = dh->p;
+- dhxparams.q = dh->q;
+- dhxparams.g = dh->g;
+- dhxparams.j = NULL;
+- dhxparams.vparams = NULL;
+- param_der_len = ASN1_item_i2d((ASN1_VALUE *)&dhxparams, ¶m_der,
+- ASN1_ITEM_rptr(int_dhxparams));
+- if (param_der_len < 0)
+- goto cleanup;
+- param_str.length = param_der_len;
+- param_str.type = V_ASN1_SEQUENCE;
+- param_str.data = param_der;
+- param_str.flags = 0;
+- parameter.type = V_ASN1_SEQUENCE;
+- parameter.value.sequence = ¶m_str;
+-
+- memset(&algorithm, 0, sizeof(algorithm));
+- algorithm.data = (uint8_t *)dh_oid.data;
+- algorithm.length = dh_oid.length;
+-
+- algor.algorithm = &algorithm;
+- algor.parameter = ¶meter;
+-
+- if (!encode_bn_der(dh->pub_key, &pubkey_der, &pubkey_der_len))
+- goto cleanup;
+- pubkey_str.length = pubkey_der_len;
+- pubkey_str.type = V_ASN1_BIT_STRING;
+- pubkey_str.data = pubkey_der;
+- pubkey_str.flags = ASN1_STRING_FLAG_BITS_LEFT;
+-
+- pubkey.algor = &algor;
+- pubkey.public_key = &pubkey_str;
+- len = i2d_X509_PUBKEY(&pubkey, NULL);
+- if (len < 0)
+- goto cleanup;
+- ret = alloc_data(spki_out, len);
+- if (ret)
+- goto cleanup;
+- outptr = (uint8_t *)spki_out->data;
+- i2d_X509_PUBKEY(&pubkey, &outptr);
+-
+-cleanup:
+- OPENSSL_free(param_der);
+- free(pubkey_der);
+- return ret;
+-}
+-
+-static EVP_PKEY *
+-decode_spki(const krb5_data *spki)
+-{
+- X509_PUBKEY *pubkey = NULL;
+- const uint8_t *inptr;
+- DH *dh;
+- EVP_PKEY *pkey = NULL, *pkey_ret = NULL;
+- const ASN1_STRING *params;
+- const ASN1_BIT_STRING *public_key;
+- krb5_data d;
+-
+- inptr = (uint8_t *)spki->data;
+- pubkey = d2i_X509_PUBKEY(NULL, &inptr, spki->length);
+- if (pubkey == NULL)
+- goto cleanup;
+-
+- if (OBJ_cmp(pubkey->algor->algorithm, OBJ_nid2obj(NID_dhKeyAgreement))) {
+- /* This is not a DH key, so we don't need special decoding. */
+- X509_PUBKEY_free(pubkey);
+- inptr = (uint8_t *)spki->data;
+- return d2i_PUBKEY(NULL, &inptr, spki->length);
+- }
+-
+- if (pubkey->algor->parameter->type != V_ASN1_SEQUENCE)
+- goto cleanup;
+- params = pubkey->algor->parameter->value.sequence;
+- d = make_data(params->data, params->length);
+- pkey = decode_dh_params(&d);
+- if (pkey == NULL)
+- goto cleanup;
+- dh = EVP_PKEY_get0_DH(pkey);
+- if (dh == NULL)
+- goto cleanup;
+- public_key = pubkey->public_key;
+- dh->pub_key = decode_bn_der(public_key->data, public_key->length);
+- if (dh->pub_key == NULL)
+- goto cleanup;
+-
+- pkey_ret = pkey;
+- pkey = NULL;
+-
+-cleanup:
+- X509_PUBKEY_free(pubkey);
+- EVP_PKEY_free(pkey);
+- return pkey_ret;
+-}
+-
+-#endif /* OPENSSL_VERSION_NUMBER < 0x10100000L */
+
+ #if OPENSSL_VERSION_NUMBER >= 0x30000000L
+
+@@ -673,7 +391,7 @@ set_padded_derivation(EVP_PKEY_CTX *ctx)
+ {
+ EVP_PKEY_CTX_set_dh_pad(ctx, 1);
+ }
+-#elif OPENSSL_VERSION_NUMBER >= 0x10100000L
++#else
+ static void
+ set_padded_derivation(EVP_PKEY_CTX *ctx)
+ {
+@@ -681,12 +399,6 @@ set_padded_derivation(EVP_PKEY_CTX *ctx)
+ EVP_PKEY_CTX_ctrl(ctx, EVP_PKEY_DHX, EVP_PKEY_OP_DERIVE,
+ EVP_PKEY_CTRL_DH_PAD, 1, NULL);
+ }
+-#else
+-static void
+-set_padded_derivation(EVP_PKEY_CTX *ctx)
+-{
+- /* There's no support for padded derivation in 1.0. */
+-}
+ #endif
+
+ static int
+@@ -809,29 +521,6 @@ dh_pubkey_der(EVP_PKEY *pkey, uint8_t **pubkey_out, unsigned int *len_out)
+ }
+ #endif
+
+-#if OPENSSL_VERSION_NUMBER >= 0x10100000L
+-/* OpenSSL 1.1 and later will copy the q parameter when generating keys. */
+-static int
+-copy_q_openssl10(EVP_PKEY *src, EVP_PKEY *dest)
+-{
+- return 1;
+-}
+-#else
+-/* OpenSSL 1.0 won't copy the q parameter, so we have to do it. */
+-static int
+-copy_q_openssl10(EVP_PKEY *src, EVP_PKEY *dest)
+-{
+- DH *dhsrc = EVP_PKEY_get0_DH(src), *dhdest = EVP_PKEY_get0_DH(dest);
+-
+- if (dhsrc == NULL || dhsrc->q == NULL || dhdest == NULL)
+- return 0;
+- if (dhdest->q != NULL)
+- return 1;
+- dhdest->q = BN_dup(dhsrc->q);
+- return dhdest->q != NULL;
+-}
+-#endif
+-
+ static EVP_PKEY *
+ generate_dh_pkey(EVP_PKEY *params)
+ {
+@@ -845,11 +534,6 @@ generate_dh_pkey(EVP_PKEY *params)
+ goto cleanup;
+ if (EVP_PKEY_keygen(ctx, &pkey) <= 0)
+ goto cleanup;
+- if (EVP_PKEY_get_base_id(pkey) == EVP_PKEY_DH &&
+- !copy_q_openssl10(params, pkey)) {
+- EVP_PKEY_free(pkey);
+- pkey = NULL;
+- }
+
+ cleanup:
+ EVP_PKEY_CTX_free(ctx);
+@@ -900,33 +584,6 @@ cleanup:
+
+ #else /* OPENSSL_VERSION_NUMBER < 0x30000000L */
+
+-#if OPENSSL_VERSION_NUMBER >= 0x10100000L
+-static DH *
+-dup_dh_params(DH *src)
+-{
+- return DHparams_dup(src);
+-}
+-#else
+-/* DHparams_dup() won't copy q in OpenSSL 1.0. */
+-static DH *
+-dup_dh_params(DH *src)
+-{
+- DH *dh;
+-
+- dh = DH_new();
+- if (dh == NULL)
+- return NULL;
+- dh->p = BN_dup(src->p);
+- dh->q = BN_dup(src->q);
+- dh->g = BN_dup(src->g);
+- if (dh->p == NULL || dh->q == NULL || dh->g == NULL) {
+- DH_free(dh);
+- return NULL;
+- }
+- return dh;
+-}
+-#endif
+-
+ static EVP_PKEY *
+ compose_dh_pkey(EVP_PKEY *params, const uint8_t *pubkey_der, size_t der_len)
+ {
+@@ -966,7 +623,7 @@ compose_dh_pkey(EVP_PKEY *params, const uint8_t *pubkey_der, size_t der_len)
+ dhparams = EVP_PKEY_get0_DH(params);
+ if (dhparams == NULL)
+ goto cleanup;
+- dh = dup_dh_params(dhparams);
++ dh = DHparams_dup(dhparams);
+ if (dh == NULL)
+ goto cleanup;
+ if (!DH_set0_key(dh, pubkey_bn, NULL))
+@@ -1083,8 +740,6 @@ static struct pkcs11_errstrings {
+ };
+ #endif
+
+-MAKE_INIT_FUNCTION(pkinit_openssl_init);
+-
+ static krb5_error_code oerr(krb5_context context, krb5_error_code code,
+ const char *fmt, ...)
+ #if !defined(__cplusplus) && (__GNUC__ > 2)
+@@ -1164,8 +819,6 @@ pkinit_init_plg_crypto(krb5_context context,
+ krb5_error_code retval = ENOMEM;
+ pkinit_plg_crypto_context ctx = NULL;
+
+- (void)CALL_INIT_FUNCTION(pkinit_openssl_init);
+-
+ ctx = malloc(sizeof(*ctx));
+ if (ctx == NULL)
+ goto out;
+@@ -3114,17 +2767,6 @@ cleanup:
+ return retval;
+ }
+
+-int
+-pkinit_openssl_init(void)
+-{
+- /* Initialize OpenSSL. */
+-#if OPENSSL_VERSION_NUMBER < 0x10100000L
+- ERR_load_crypto_strings();
+- OpenSSL_add_all_algorithms();
+-#endif
+- return 0;
+-}
+-
+ static krb5_error_code
+ pkinit_create_sequence_of_principal_identifiers(
+ krb5_context context,
+@@ -5834,13 +5476,3 @@ crypto_verify_checksums(krb5_context context, krb5_data *body,
+
+ return 0;
+ }
+-
+-#ifdef _WIN32
+-BOOL WINAPI
+-DllMain(HANDLE hModule, DWORD fdwReason, LPVOID lpvReserved)
+-{
+- if (fdwReason == DLL_PROCESS_ATTACH)
+- pkinit_openssl_init__auxinit();
+- return TRUE;
+-}
+-#endif /* _WIN32 */
+diff --git a/src/plugins/preauth/spake/openssl.c b/src/plugins/preauth/spake/openssl.c
+index f2e4b53..fbaa65e 100644
+--- a/src/plugins/preauth/spake/openssl.c
++++ b/src/plugins/preauth/spake/openssl.c
+@@ -41,13 +41,6 @@
+ #include <openssl/obj_mac.h>
+ #include <openssl/evp.h>
+
+-/* OpenSSL 1.1 standardizes constructor and destructor names, renaming
+- * EVP_MD_CTX_create and EVP_MD_CTX_destroy. */
+-#if OPENSSL_VERSION_NUMBER < 0x10100000L
+-#define EVP_MD_CTX_new EVP_MD_CTX_create
+-#define EVP_MD_CTX_free EVP_MD_CTX_destroy
+-#endif
+-
+ struct groupdata_st {
+ const groupdef *gdef;
+ EC_GROUP *group;
+diff --git a/src/plugins/tls/k5tls/openssl.c b/src/plugins/tls/k5tls/openssl.c
+index cc8fc70..bbfa37f 100644
+--- a/src/plugins/tls/k5tls/openssl.c
++++ b/src/plugins/tls/k5tls/openssl.c
+@@ -38,14 +38,6 @@
+ #include <openssl/x509v3.h>
+ #include <dirent.h>
+
+-#if OPENSSL_VERSION_NUMBER < 0x10100000L
+-/* Make X509_get_subject_name() accept a const pointer by adding a cast. */
+-#define X509_get_subject_name(a) X509_get_subject_name((X509 *)a)
+-
+-/* OpenSSL 1.0 did not have TLS_client_method(); use the best alternative. */
+-#define TLS_client_method() SSLv23_client_method()
+-#endif
+-
+ #if OPENSSL_VERSION_NUMBER < 0x40000000L
+ /*
+ * OpenSSL 4.0 constifies the result of X509_STORE_CTX_get_current_cert() and
+@@ -69,11 +61,6 @@ MAKE_INIT_FUNCTION(init_openssl);
+ int
+ init_openssl(void)
+ {
+-#if OPENSSL_VERSION_NUMBER < 0x10100000L
+- SSL_library_init();
+- SSL_load_error_strings();
+- OpenSSL_add_all_algorithms();
+-#endif
+ ex_context_id = SSL_get_ex_new_index(0, NULL, NULL, NULL, NULL);
+ ex_handle_id = SSL_get_ex_new_index(0, NULL, NULL, NULL, NULL);
+ return 0;
new file mode 100644
@@ -0,0 +1,67 @@
+From 29a6ab9be8a5af0a683eb0e89ce9b094b74ae8cf Mon Sep 17 00:00:00 2001
+From: Jaipaul Cheernam <jaipaul.cheernam@est.tech>
+Date: Wed, 26 Aug 2026 11:30:58 +0000
+Subject: [PATCH] k5tls: fix remaining const qualifiers for OpenSSL 4.0
+
+OpenSSL 4.0 returns const pointers from X509_get_subject_name(),
+X509_get_ext(), and X509_STORE_CTX_get_current_cert(). Update
+function signatures and local variables to accept const pointers.
+
+Upstream-Status: Inappropriate [functions removed on trunk, fix only needed for 1.22.x]
+
+Note: Upstream fixed this by removing OpenSSL 1.0 support entirely
+(commit f8a47bf037af), but 1.22.2 still has code paths that need
+these additional const qualifiers.
+
+Signed-off-by: Jaipaul Cheernam <jaipaul.cheernam@est.tech>
+---
+ plugins/tls/k5tls/openssl.c | 12 ++++++------
+ 1 file changed, 6 insertions(+), 6 deletions(-)
+
+diff --git a/src/plugins/tls/k5tls/openssl.c b/src/plugins/tls/k5tls/openssl.c
+index bbfa37f..6efe613 100644
+--- a/src/plugins/tls/k5tls/openssl.c
++++ b/src/plugins/tls/k5tls/openssl.c
+@@ -146,10 +146,10 @@ domain_match(const char *presented, size_t plen, const char *expected)
+
+ /* Fetch the list of subjectAltNames from a certificate. */
+ static GENERAL_NAMES *
+-get_cert_sans(X509 *x)
++get_cert_sans(const X509 *x)
+ {
+ int ext;
+- X509_EXTENSION *san_ext;
++ const X509_EXTENSION *san_ext;
+
+ ext = X509_get_ext_by_NID(x, NID_subject_alt_name, -1);
+ if (ext < 0)
+@@ -163,9 +163,9 @@ get_cert_sans(X509 *x)
+ /* Fetch a CN value from the subjct name field, returning its length, or -1 if
+ * there is no subject name or it contains no CN value. */
+ static int
+-get_cert_cn(X509 *x, char *buf, size_t bufsize)
++get_cert_cn(const X509 *x, char *buf, size_t bufsize)
+ {
+- X509_NAME *name;
++ const X509_NAME *name;
+
+ name = X509_get_subject_name(x);
+ if (name == NULL)
+@@ -175,7 +175,7 @@ get_cert_cn(X509 *x, char *buf, size_t bufsize)
+
+ /* Return true if text matches any of the addresses we can recover from x. */
+ static krb5_boolean
+-check_cert_address(X509 *x, const char *text)
++check_cert_address(const X509 *x, const char *text)
+ {
+ char buf[1024];
+ GENERAL_NAMES *sans;
+@@ -234,7 +234,7 @@ check_cert_address(X509 *x, const char *text)
+
+ /* Return true if expected matches any of the names we can recover from x. */
+ static krb5_boolean
+-check_cert_servername(X509 *x, const char *expected)
++check_cert_servername(const X509 *x, const char *expected)
+ {
+ char buf[1024];
+ GENERAL_NAMES *sans;
@@ -24,6 +24,9 @@ SRC_URI = "http://web.mit.edu/kerberos/dist/${BPN}/${SHRT_VER}/${BP}.tar.gz \
file://fix-strchr-conformance-to-C23.patch;striplevel=2 \
file://crosscompile_nm.patch \
file://0001-configure.ac-replace-K5_AC_INIT-with-explicit-AC_INI.patch;striplevel=2 \
+ file://0001-Improve-future-OpenSSL-compatibility.patch;striplevel=2 \
+ file://0002-Remove-OpenSSL-1.0-support.patch;striplevel=2 \
+ file://0003-k5tls-fix-remaining-const-qualifiers-for-OpenSSL-4.0.patch;striplevel=2 \
file://etc/init.d/krb5-kdc \
file://etc/init.d/krb5-admin-server \
file://etc/default/krb5-kdc \
OpenSSL 4.0 adds const qualifiers to X509 accessor return types, makes ASN1_STRING opaque, and removes OpenSSL 1.0 compatibility functions. Backport three patches: - Improve future OpenSSL compatibility (upstream 5e4e84523288) - Remove OpenSSL 1.0 support (upstream f8a47bf037af, context adjusted) - Fix remaining const qualifiers in k5tls for 1.22.x (functions removed on trunk, fix only needed for this version) Upstream-Status: Backport / Inappropriate (patch 3) Signed-off-by: Jaipaul Cheernam <jaipaul.cheernam@est.tech> --- ...Improve-future-OpenSSL-compatibility.patch | 285 ++++++++ .../0002-Remove-OpenSSL-1.0-support.patch | 627 ++++++++++++++++++ ...ing-const-qualifiers-for-OpenSSL-4.0.patch | 67 ++ .../recipes-connectivity/krb5/krb5_1.22.2.bb | 3 + 4 files changed, 982 insertions(+) create mode 100644 meta-oe/recipes-connectivity/krb5/krb5/0001-Improve-future-OpenSSL-compatibility.patch create mode 100644 meta-oe/recipes-connectivity/krb5/krb5/0002-Remove-OpenSSL-1.0-support.patch create mode 100644 meta-oe/recipes-connectivity/krb5/krb5/0003-k5tls-fix-remaining-const-qualifiers-for-OpenSSL-4.0.patch