As promised, here are updated patches, which fully replace the earlier
one. This is more extensive than I was expecting, but I was able to
build the entire package successfully.
Subject: Port ossl_srv.c copies to OpenSSL 4
Author: Karl Smeltzer <[email protected]>
Forwarded: https://github.com/cisco/libest/pull/136
Last-Update: 2026-07-23

Both ossl_srv.c copies (example/server, test/util) fail to build
against OpenSSL 4.0 due to relying on removed functionality.

Fixes:
- Add a shim mapping ASN1_STRING_get0_data() to ASN1_STRING_data() on
  OpenSSL < 1.1.0, then use the ASN1_STRING_type/length/get0_data
  accessors unconditionally. These files do not include config.h, so
  HAVE_OLD_OPENSSL is never defined here; keying on
  OPENSSL_VERSION_NUMBER is what actually keeps 1.0.x building.
- Retag DN entries in the msie_hack path with
  X509_NAME_ENTRY_set_data() instead of writing str->type, which has
  no setter once the type is opaque.
- Replace BN_pseudo_rand() with BN_rand(), available on all versions.
- Ifdef out the FORMAT_ENGINE branch on OpenSSL >= 4.0.

Index: b/example/server/ossl_srv.c
===================================================================
--- a/example/server/ossl_srv.c	2026-07-21 13:23:32.246765637 -0700
+++ b/example/server/ossl_srv.c	2026-07-23 12:28:41.666971667 -0700
@@ -90,6 +90,10 @@
 #include <openssl/bio.h>
 #include "apps.h"  //taken from openssl/apps/apps.h
 
+#if OPENSSL_VERSION_NUMBER < 0x10100000L
+#define ASN1_STRING_get0_data ASN1_STRING_data
+#endif
+
 extern BIO *bio_err;
 BIO *cacerts = NULL;
 static int msie_hack = 0;
@@ -317,6 +321,7 @@
         BIO_printf(err, "no keyfile specified\n");
         goto end;
     }
+#if OPENSSL_VERSION_NUMBER < 0x40000000L
     if (format == FORMAT_ENGINE) {
         if (!e)
             BIO_printf(err, "no engine specified\n");
@@ -330,6 +335,7 @@
         }
         goto end;
     }
+#endif
     key = BIO_new(BIO_s_file());
     if (key == NULL) {
         ERR_print_errors(err);
@@ -883,7 +889,7 @@
     if (!btmp)
         return 0;
 
-    if (!BN_pseudo_rand(btmp, SERIAL_RAND_BITS, 0, 0))
+    if (!BN_rand(btmp, SERIAL_RAND_BITS, 0, 0))
         goto error;
     if (ai && !BN_to_ASN1_INTEGER(btmp, ai))
         goto error;
@@ -1304,14 +1310,14 @@
 
     /* get actual time and make a string */
     a_tm = X509_gmtime_adj(a_tm, 0);
-    a_tm_s = (char *) OPENSSL_malloc(a_tm->length+1);
+    a_tm_s = (char *) OPENSSL_malloc(ASN1_STRING_length(a_tm)+1);
     if (a_tm_s == NULL) {
         cnt = -1;
         goto err;
     }
 
-    memcpy(a_tm_s, a_tm->data, a_tm->length);
-    a_tm_s[a_tm->length] = '\0';
+    memcpy(a_tm_s, ASN1_STRING_get0_data(a_tm), ASN1_STRING_length(a_tm));
+    a_tm_s[ASN1_STRING_length(a_tm)] = '\0';
 
     if (strncmp(a_tm_s, "49", 2) <= 0)
         a_y2k = 1;
@@ -1367,19 +1373,19 @@
     *(pbuf++) = '\0';
     BIO_puts(bp, buf);
 
-    if (str->type == V_ASN1_PRINTABLESTRING)
+    if (ASN1_STRING_type(str) == V_ASN1_PRINTABLESTRING)
         BIO_printf(bp, "PRINTABLE:'");
-    else if (str->type == V_ASN1_T61STRING)
+    else if (ASN1_STRING_type(str) == V_ASN1_T61STRING)
         BIO_printf(bp, "T61STRING:'");
-    else if (str->type == V_ASN1_IA5STRING)
+    else if (ASN1_STRING_type(str) == V_ASN1_IA5STRING)
         BIO_printf(bp, "IA5STRING:'");
-    else if (str->type == V_ASN1_UNIVERSALSTRING)
+    else if (ASN1_STRING_type(str) == V_ASN1_UNIVERSALSTRING)
         BIO_printf(bp, "UNIVERSALSTRING:'");
     else
-        BIO_printf(bp, "ASN.1 %2d:'", str->type);
+        BIO_printf(bp, "ASN.1 %2d:'", ASN1_STRING_type(str));
 
-    p = (char *) str->data;
-    for (j = str->length; j > 0; j--) {
+    p = (char *) ASN1_STRING_get0_data(str);
+    for (j = ASN1_STRING_length(str); j > 0; j--) {
         if ((*p >= ' ') && (*p <= '~'))
             BIO_printf(bp, "%c", *p);
         else if (*p & 0x80)
@@ -1505,16 +1511,22 @@
             nid = OBJ_obj2nid(X509_NAME_ENTRY_get_object(ne));
 #endif
             
-            if (str->type == V_ASN1_UNIVERSALSTRING)
+            if (ASN1_STRING_type(str) == V_ASN1_UNIVERSALSTRING)
                 ASN1_UNIVERSALSTRING_to_string(str);
 
-            if ((str->type == V_ASN1_IA5STRING)
-                    && (nid != NID_pkcs9_emailAddress))
-                str->type = V_ASN1_T61STRING;
+            if ((ASN1_STRING_type(str) == V_ASN1_IA5STRING)
+                    && (nid != NID_pkcs9_emailAddress)) {
+                X509_NAME_ENTRY_set_data(ne, V_ASN1_T61STRING,
+                        ASN1_STRING_get0_data(str), ASN1_STRING_length(str));
+                str = X509_NAME_ENTRY_get_data(ne);
+            }
 
             if ((nid == NID_pkcs9_emailAddress)
-                    && (str->type == V_ASN1_PRINTABLESTRING))
-                str->type = V_ASN1_IA5STRING;
+                    && (ASN1_STRING_type(str) == V_ASN1_PRINTABLESTRING)) {
+                X509_NAME_ENTRY_set_data(ne, V_ASN1_IA5STRING,
+                        ASN1_STRING_get0_data(str), ASN1_STRING_length(str));
+                str = X509_NAME_ENTRY_get_data(ne);
+            }
         }
 
         /* If no EMAIL is wanted in the subject */
@@ -1523,17 +1535,18 @@
 
         /* check some things */
         if ((OBJ_obj2nid(obj) == NID_pkcs9_emailAddress)
-                && (str->type != V_ASN1_IA5STRING)) {
+                && (ASN1_STRING_type(str) != V_ASN1_IA5STRING)) {
             BIO_printf(bio_err,
                     "\nemailAddress type needs to be of type IA5STRING\n");
             goto err;
         }
-        if ((str->type != V_ASN1_BMPSTRING)
-                && (str->type != V_ASN1_UTF8STRING)) {
-            j = ASN1_PRINTABLE_type(str->data, str->length);
-            if (((j == V_ASN1_T61STRING) && (str->type != V_ASN1_T61STRING))
+        if ((ASN1_STRING_type(str) != V_ASN1_BMPSTRING)
+                && (ASN1_STRING_type(str) != V_ASN1_UTF8STRING)) {
+            j = ASN1_PRINTABLE_type(ASN1_STRING_get0_data(str),
+                    ASN1_STRING_length(str));
+            if (((j == V_ASN1_T61STRING) && (ASN1_STRING_type(str) != V_ASN1_T61STRING))
                     || ((j == V_ASN1_IA5STRING)
-                            && (str->type == V_ASN1_PRINTABLESTRING))) {
+                            && (ASN1_STRING_type(str) == V_ASN1_PRINTABLESTRING))) {
                 BIO_printf(bio_err,
                         "\nThe string contains characters that are illegal for the ASN.1 type\n");
                 goto err;
@@ -1631,8 +1644,8 @@
                     BIO_printf(bio_err,
                             "The %s field needed to be the same in the\nCA certificate (%s) and the request (%s)\n",
                             cv->name,
-                            ((str2 == NULL) ? "NULL" : (char *) str2->data),
-                            ((str == NULL) ? "NULL" : (char *) str->data));
+                            ((str2 == NULL) ? "NULL" : (char *) ASN1_STRING_get0_data(str2)),
+                            ((str == NULL) ? "NULL" : (char *) ASN1_STRING_get0_data(str)));
                     goto err;
                 }
             } else {
@@ -1935,9 +1948,9 @@
     row[DB_type] = (char *) OPENSSL_malloc(2);
 
     tm = X509_get_notAfter(ret);
-    row[DB_exp_date] = (char *) OPENSSL_malloc(tm->length+1);
-    memcpy(row[DB_exp_date], tm->data, tm->length);
-    row[DB_exp_date][tm->length] = '\0';
+    row[DB_exp_date] = (char *) OPENSSL_malloc(ASN1_STRING_length(tm)+1);
+    memcpy(row[DB_exp_date], ASN1_STRING_get0_data(tm), ASN1_STRING_length(tm));
+    row[DB_exp_date][ASN1_STRING_length(tm)] = '\0';
 
     row[DB_rev_date] = NULL;
 
Index: b/test/util/ossl_srv.c
===================================================================
--- a/test/util/ossl_srv.c	2026-07-22 11:40:51.000000000 -0700
+++ b/test/util/ossl_srv.c	2026-07-23 12:41:43.000000000 -0700
@@ -91,6 +91,10 @@
 #include <openssl/bio.h>
 #include "apps.h"  //taken from openssl/apps/apps.h
 
+#if OPENSSL_VERSION_NUMBER < 0x10100000L
+#define ASN1_STRING_get0_data ASN1_STRING_data
+#endif
+
 extern BIO *bio_err;
 BIO *cacerts = NULL;
 static int msie_hack=0;
@@ -345,6 +349,7 @@
 		BIO_printf(err,"no keyfile specified\n");
 		goto end;
 		}
+#if OPENSSL_VERSION_NUMBER < 0x40000000L
 	if (format == FORMAT_ENGINE)
 		{
 		if (!e)
@@ -361,6 +366,7 @@
 			}
 		goto end;
 		}
+#endif
 	key=BIO_new(BIO_s_file());
 	if (key == NULL)
 		{
@@ -971,7 +977,7 @@
 	if (!btmp)
 		return 0;
 
-	if (!BN_pseudo_rand(btmp, SERIAL_RAND_BITS, 0, 0))
+	if (!BN_rand(btmp, SERIAL_RAND_BITS, 0, 0))
 		goto error;
 	if (ai && !BN_to_ASN1_INTEGER(btmp, ai))
 		goto error;
@@ -1434,15 +1440,15 @@
 
 	/* get actual time and make a string */
 	a_tm = X509_gmtime_adj(a_tm, 0);
-	a_tm_s = (char *) OPENSSL_malloc(a_tm->length+1);
+	a_tm_s = (char *) OPENSSL_malloc(ASN1_STRING_length(a_tm)+1);
 	if (a_tm_s == NULL)
 		{
 		cnt = -1;
 		goto err;
 		}
 
-	memcpy(a_tm_s, a_tm->data, a_tm->length);
-	a_tm_s[a_tm->length] = '\0';
+	memcpy(a_tm_s, ASN1_STRING_get0_data(a_tm), ASN1_STRING_length(a_tm));
+	a_tm_s[ASN1_STRING_length(a_tm)] = '\0';
 
 	if (strncmp(a_tm_s, "49", 2) <= 0)
 		a_y2k = 1;
@@ -1508,19 +1514,19 @@
 	*(pbuf++)='\0';
 	BIO_puts(bp,buf);
 
-	if (str->type == V_ASN1_PRINTABLESTRING)
+	if (ASN1_STRING_type(str) == V_ASN1_PRINTABLESTRING)
 		BIO_printf(bp,"PRINTABLE:'");
-	else if (str->type == V_ASN1_T61STRING)
+	else if (ASN1_STRING_type(str) == V_ASN1_T61STRING)
 		BIO_printf(bp,"T61STRING:'");
-	else if (str->type == V_ASN1_IA5STRING)
+	else if (ASN1_STRING_type(str) == V_ASN1_IA5STRING)
 		BIO_printf(bp,"IA5STRING:'");
-	else if (str->type == V_ASN1_UNIVERSALSTRING)
+	else if (ASN1_STRING_type(str) == V_ASN1_UNIVERSALSTRING)
 		BIO_printf(bp,"UNIVERSALSTRING:'");
 	else
-		BIO_printf(bp,"ASN.1 %2d:'",str->type);
-			
-	p=(char *)str->data;
-	for (j=str->length; j>0; j--)
+		BIO_printf(bp,"ASN.1 %2d:'",ASN1_STRING_type(str));
+
+	p=(char *)ASN1_STRING_get0_data(str);
+	for (j=ASN1_STRING_length(str); j>0; j--)
 		{
 		if ((*p >= ' ') && (*p <= '~'))
 			BIO_printf(bp,"%c",*p);
@@ -1658,16 +1664,24 @@
 #else            
                             nid = OBJ_obj2nid(X509_NAME_ENTRY_get_object(ne));
 #endif
-			if (str->type == V_ASN1_UNIVERSALSTRING)
+			if (ASN1_STRING_type(str) == V_ASN1_UNIVERSALSTRING)
 				ASN1_UNIVERSALSTRING_to_string(str);
 
-			if ((str->type == V_ASN1_IA5STRING) &&
+			if ((ASN1_STRING_type(str) == V_ASN1_IA5STRING) &&
 				(nid != NID_pkcs9_emailAddress))
-				str->type=V_ASN1_T61STRING;
+				{
+				X509_NAME_ENTRY_set_data(ne, V_ASN1_T61STRING,
+					ASN1_STRING_get0_data(str), ASN1_STRING_length(str));
+				str=X509_NAME_ENTRY_get_data(ne);
+				}
 
 			if ((nid == NID_pkcs9_emailAddress) &&
-				(str->type == V_ASN1_PRINTABLESTRING))
-				str->type=V_ASN1_IA5STRING;
+				(ASN1_STRING_type(str) == V_ASN1_PRINTABLESTRING))
+				{
+				X509_NAME_ENTRY_set_data(ne, V_ASN1_IA5STRING,
+					ASN1_STRING_get0_data(str), ASN1_STRING_length(str));
+				str=X509_NAME_ENTRY_get_data(ne);
+				}
 			}
 
 		/* If no EMAIL is wanted in the subject */
@@ -1676,18 +1690,18 @@
 
 		/* check some things */
 		if ((OBJ_obj2nid(obj) == NID_pkcs9_emailAddress) &&
-			(str->type != V_ASN1_IA5STRING))
+			(ASN1_STRING_type(str) != V_ASN1_IA5STRING))
 			{
 			BIO_printf(bio_err,"\nemailAddress type needs to be of type IA5STRING\n");
 			goto err;
 			}
-		if ((str->type != V_ASN1_BMPSTRING) && (str->type != V_ASN1_UTF8STRING))
+		if ((ASN1_STRING_type(str) != V_ASN1_BMPSTRING) && (ASN1_STRING_type(str) != V_ASN1_UTF8STRING))
 			{
-			j=ASN1_PRINTABLE_type(str->data,str->length);
+			j=ASN1_PRINTABLE_type(ASN1_STRING_get0_data(str),ASN1_STRING_length(str));
 			if (	((j == V_ASN1_T61STRING) &&
-				 (str->type != V_ASN1_T61STRING)) ||
+				 (ASN1_STRING_type(str) != V_ASN1_T61STRING)) ||
 				((j == V_ASN1_IA5STRING) &&
-				 (str->type == V_ASN1_PRINTABLESTRING)))
+				 (ASN1_STRING_type(str) == V_ASN1_PRINTABLESTRING)))
 				{
 				BIO_printf(bio_err,"\nThe string contains characters that are illegal for the ASN.1 type\n");
 				goto err;
@@ -1791,7 +1805,8 @@
 					}
 				if (j < 0)
 					{
-					BIO_printf(bio_err,"The %s field needed to be the same in the\nCA certificate (%s) and the request (%s)\n",cv->name,((str2 == NULL)?"NULL":(char *)str2->data),((str == NULL)?"NULL":(char *)str->data));
+					BIO_printf(bio_err,"The %s field needed to be the same in the\nCA certificate (%s) and the request (%s)\n",cv->name,
+						((str2 == NULL)?"NULL":(char *)ASN1_STRING_get0_data(str2)),((str == NULL)?"NULL":(char *)ASN1_STRING_get0_data(str)));
 					goto err;
 					}
 				}
@@ -2098,9 +2113,9 @@
 	row[DB_type]=(char *)OPENSSL_malloc(2);
 
 	tm=X509_get_notAfter(ret);
-	row[DB_exp_date]=(char *)OPENSSL_malloc(tm->length+1);
-	memcpy(row[DB_exp_date],tm->data,tm->length);
-	row[DB_exp_date][tm->length]='\0';
+	row[DB_exp_date]=(char *)OPENSSL_malloc(ASN1_STRING_length(tm)+1);
+	memcpy(row[DB_exp_date],ASN1_STRING_get0_data(tm),ASN1_STRING_length(tm));
+	row[DB_exp_date][ASN1_STRING_length(tm)]='\0';
 
 	row[DB_rev_date]=NULL;
 
Subject: Use accessors for opaque ASN1_STRING (OpenSSL 4 compatibility)
Author: Karl Smeltzer <[email protected]>
Forwarded: https://github.com/cisco/libest/pull/136
Last-Update: 2026-07-22

OpenSSL 4.0 makes ASN1_STRING (and its typedefs ASN1_OCTET_STRING /
ASN1_BIT_STRING) opaque. This uses the ASN1_STRING_get0_data() and
ASN1_STRING_length() accessors instead, while keeping the direct access under
HAVE_OLD_OPENSSL.
--- a/src/est/est_client.c
+++ b/src/est/est_client.c
@@ -5308,11 +5308,15 @@
         return (EST_ERR_CLIENT_BRSKI_VOUCHER_VERIFY_FAILED);
     }
 
+#ifdef HAVE_OLD_OPENSSL
     ctx->brski_retrieved_voucher = pkcs7->d.sign->contents->d.data->data;
-    ctx->brski_retrieved_voucher_len = pkcs7->d.sign->contents->d.data->length;
+#else
+    ctx->brski_retrieved_voucher = (unsigned char *)ASN1_STRING_get0_data(pkcs7->d.sign->contents->d.data);
+#endif
+    ctx->brski_retrieved_voucher_len = ASN1_STRING_length(pkcs7->d.sign->contents->d.data);
 
     EST_LOG_INFO("Voucher verify passed.  Voucher =\n %s",
-                 pkcs7->d.sign->contents->d.data->data);
+                 ctx->brski_retrieved_voucher);
     
     return (EST_ERR_NONE);
 }
--- a/src/est/est_server.c
+++ b/src/est/est_server.c
@@ -1134,7 +1134,11 @@
          */
         tls_uid = est_get_tls_uid(ssl, &uid_len, 0);
         if (tls_uid) {
+#ifdef HAVE_OLD_OPENSSL
 	    i = memcmp_s(tls_uid, uid_len, bs->data, uid_len, &diff);
+#else
+	    i = memcmp_s(tls_uid, uid_len, ASN1_STRING_get0_data(bs), uid_len, &diff);
+#endif
             if (i == EOK && !diff) {
                 EST_LOG_INFO("PoP is valid");
                 rv = EST_ERR_NONE;
Subject: Use providers instead of the ENGINE API on OpenSSL 4 (est.h)
Author: Karl Smeltzer <[email protected]>
Forwarded: https://github.com/cisco/libest/pull/136
Last-Update: 2026-07-23

OpenSSL 4.0 removes the ENGINE API, so the est_apps_startup() /
est_apps_shutdown() macros in est.h no longer link: they call
ENGINE_load_builtin_engines() / ENGINE_cleanup() and friends.

Add OpenSSL >= 4.0 variants of both macros that load the default
provider instead, keeping the existing variants for older versions,
matching the HAVE_OLD_OPENSSL pattern already used in this header.

The example/test program side of the ENGINE removal is in
port-ossl-srv-to-openssl4.patch.

Index: b/src/est/est.h
===================================================================
--- a/src/est/est.h	2026-07-21 13:23:32.254483418 -0700
+++ b/src/est/est.h	2026-07-23 12:23:25.480924351 -0700
@@ -25,6 +25,9 @@
 #include <openssl/engine.h>
 #include <openssl/conf.h>
 #include <openssl/srp.h>
+#if OPENSSL_VERSION_NUMBER >= 0x40000000L
+#include <openssl/provider.h>
+#endif
 
 #ifdef  __cplusplus
 extern "C" {
@@ -829,6 +832,13 @@
          ENGINE_load_builtin_engines(); \
          SSL_library_init(); \
          SSL_load_error_strings(); } while (0)
+#elif OPENSSL_VERSION_NUMBER >= 0x40000000L
+#define est_apps_startup()               \
+    do { ERR_load_crypto_strings();      \
+         OpenSSL_add_all_algorithms();   \
+         OSSL_PROVIDER_load(NULL, "default"); \
+         SSL_library_init();             \
+         SSL_load_error_strings(); } while (0)
 #else
 #define est_apps_startup()               \
     do { ERR_load_crypto_strings();      \
@@ -854,6 +864,12 @@
          CRYPTO_cleanup_all_ex_data(); \
          ERR_remove_thread_state(NULL); \
          ERR_free_strings(); } while (0)
+#elif OPENSSL_VERSION_NUMBER >= 0x40000000L
+#define est_apps_shutdown() \
+    do { CONF_modules_unload(1); \
+         OBJ_cleanup(); EVP_cleanup(); \
+         CRYPTO_cleanup_all_ex_data(); \
+         ERR_free_strings(); } while (0)
 #else
 #define est_apps_shutdown() \
     do { CONF_modules_unload(1); \

Reply via email to