Skip to content

openssl: x509: allow build with OpenSSL 4.x#3560

Open
heitbaum wants to merge 38 commits intowarmcat:mainfrom
heitbaum:openssl
Open

openssl: x509: allow build with OpenSSL 4.x#3560
heitbaum wants to merge 38 commits intowarmcat:mainfrom
heitbaum:openssl

Conversation

@heitbaum
Copy link
Copy Markdown
Contributor

ASN1_STRING are now opaque types — the internal data and length fields are no longer directly accessible. Use the accessor API instead. Accessors have been available since OpenSSL 1.1.0

Signatures of numerous API functions, including those that are related to X509 processing, are changed to include const qualifiers for argument and return types, where suitable. Add const qualifer to variables.

fixes:

../lib/tls/openssl/openssl-x509.c: In function 'lws_tls_openssl_asn1time_to_unix':
../lib/tls/openssl/openssl-x509.c:42:41: error: invalid use of incomplete typedef 'ASN1_TIME' {aka 'struct asn1_string_st'}
   42 |         const char *p = (const char *)as->data;
      |                                         ^~
../lib/tls/openssl/openssl-x509.c: In function 'lws_tls_openssl_cert_info':
../lib/tls/openssl/openssl-x509.c:129:20: error: assignment discards 'const' qualifier from pointer target type [-Werror=discarded-qualifiers]
  129 |                 xn = X509_get_subject_name(x509);
      |                    ^
../lib/tls/openssl/openssl-x509.c:148:20: error: assignment discards 'const' qualifier from pointer target type [-Werror=discarded-qualifiers]
  148 |                 xn = X509_get_issuer_name(x509);
      |                    ^
../lib/tls/openssl/openssl-x509.c:218:21: error: assignment discards 'const' qualifier from pointer target type [-Werror=discarded-qualifiers]
  218 |                 ext = X509_get_ext(x509, (int)loc);
      |                     ^
../lib/tls/openssl/openssl-x509.c:229:48: error: invalid use of incomplete typedef 'ASN1_OCTET_STRING' {aka 'struct asn1_string_st'}
  229 |                 dp = (const unsigned char *)val->data;
      |                                                ^~
../lib/tls/openssl/openssl-x509.c:230:27: error: invalid use of incomplete typedef 'ASN1_OCTET_STRING' {aka 'struct asn1_string_st'}
  230 |                 xlen = val->length;
      |                           ^~
../lib/tls/openssl/openssl-x509.c:246:21: error: assignment discards 'const' qualifier from pointer target type [-Werror=discarded-qualifiers]
  246 |                 ext = X509_get_ext(x509, (int)loc);
      |                     ^
../lib/tls/openssl/openssl-x509.c:303:21: error: assignment discards 'const' qualifier from pointer target type [-Werror=discarded-qualifiers]
  303 |                 ext = X509_get_ext(x509, (int)loc);
      |                     ^
../lib/tls/openssl/openssl-x509.c:329:21: error: assignment discards 'const' qualifier from pointer target type [-Werror=discarded-qualifiers]
  329 |                 ext = X509_get_ext(x509, (int)loc);
      |                     ^
../lib/tls/openssl/openssl-x509.c:333:21: error: assignment discards 'const' qualifier from pointer target type [-Werror=discarded-qualifiers]
  333 |                 val = X509_EXTENSION_get_data(ext);
      |                     ^
../lib/tls/openssl/openssl-x509.c:340:48: error: invalid use of incomplete typedef 'ASN1_OCTET_STRING' {aka 'struct asn1_string_st'}
  340 |                 dp = (const unsigned char *)val->data;
      |                                                ^~
../lib/tls/openssl/openssl-x509.c:343:55: error: invalid use of incomplete typedef 'ASN1_OCTET_STRING' {aka 'struct asn1_string_st'}
  343 |                                     &tag, &xclass, val->length) & 0x80)
      |                                                       ^~
../lib/tls/openssl/openssl-x509.c: In function 'lws_x509_verify':
../lib/tls/openssl/openssl-x509.c:459:33: error: initialization discards 'const' qualifier from pointer target type [-Werror=discarded-qualifiers]
  459 |                 X509_NAME *xn = X509_get_subject_name(x509->cert);
      |                                 ^~~~~~~~~~~~~~~~~~~~~

lws-team added 30 commits March 14, 2026 18:01
Add a generic DTLS wrapper to lws that is able to work using any of the
supported tls libraries as the backed: openssl (and variants), mbedtls,
gnutls, schannel

Note that schannel is not able to work with webrtc due to schannel api's
own limitations.  You must use openssl or mbedtls for windows if you want
to use dtls for webrtc.
This adds support for webrtc serving along with ALSA, OPUS, V4L2, TRANSCODE
and other critical pieces
Having added a member to lws_plugin_protocol, it's a good time to change
the old struct initializer format to C9, since we'll have to visit them all
anyway.

Also modernize the event lib struct while we're at it.
Various things that Sai identified needed fixing
This changes the approach of Async DNS vs multiple DNS servers...

 - we will take all the platform tells us about
 - initially we will broadside the queries on all the servers
 - we'll measure the response performce over time, with decay
 - nonresponsive servers will get ignored and responsive ones
   will round-robin
@lws-team
Copy link
Copy Markdown
Member

Thanks for the patch. Unfortunately more contortions are needed, since existing openssl3 doesn't have const, simply making things const fixes what's in front of you, and kills it for older openssl. I modified your patch so it still works on older openssl, can you confirm it's OK for your openssl4 case?

diff --git a/lib/tls/openssl/openssl-x509.c b/lib/tls/openssl/openssl-x509.c
index d8b5637c0..15c853ca9 100644
--- a/lib/tls/openssl/openssl-x509.c
+++ b/lib/tls/openssl/openssl-x509.c
@@ -1,7 +1,7 @@
 /*
  * libwebsockets - small server side websockets and web server implementation
  *
- * Copyright (C) 2010 - 2019 Andy Green <andy@warmcat.com>
+ * Copyright (C) 2010 - 2026 Andy Green <andy@warmcat.com>
  *
  * Permission is hereby granted, free of charge, to any person obtaining a copy
  * of this software and associated documentation files (the "Software"), to
@@ -26,6 +26,12 @@
 #include "private-lib-core.h"
 #include "private-lib-tls-openssl.h"
 
+#if OPENSSL_VERSION_NUMBER >= 0x40000000L
+#define CAST_X509_EXTENSION(x)	(x)
+#else
+#define CAST_X509_EXTENSION(x)	((X509_EXTENSION *)(x))
+#endif
+
 #if !defined(LWS_PLAT_OPTEE)
 static int
 dec(char c)
@@ -39,7 +45,7 @@ lws_tls_openssl_asn1time_to_unix(ASN1_TIME *as)
 {
 #if !defined(LWS_PLAT_OPTEE)
 
-	const char *p = (const char *)as->data;
+	const char *p = (const char *)ASN1_STRING_get0_data(as);
 	struct tm t;
 
 	/* [YY]YYMMDDHHMMSSZ */
@@ -84,12 +90,13 @@ lws_tls_openssl_cert_info(X509 *x509, enum lws_tls_cert_info type,
 #ifndef USE_WOLFSSL
 	const unsigned char *dp;
 	ASN1_OCTET_STRING *val;
+	const ASN1_OCTET_STRING *val2;
 	AUTHORITY_KEYID *akid;
-	X509_EXTENSION *ext;
+	const X509_EXTENSION *ext;
 	int tag, xclass, r = 1;
 	long xlen, loc;
 #endif
-	X509_NAME *xn;
+	const X509_NAME *xn;
 #if !defined(LWS_PLAT_OPTEE)
 	char *p, *p1;
 	size_t rl;
@@ -219,15 +226,15 @@ lws_tls_openssl_cert_info(X509 *x509, enum lws_tls_cert_info type,
 		if (!ext)
 			return 1;
 #ifndef USE_WOLFSSL
-		akid = (AUTHORITY_KEYID *)X509V3_EXT_d2i(ext);
+		akid = (AUTHORITY_KEYID *)X509V3_EXT_d2i(CAST_X509_EXTENSION(ext));
 #else
 		akid = (AUTHORITY_KEYID *)wolfSSL_X509V3_EXT_d2i(ext);
 #endif
 		if (!akid || !akid->keyid)
 			return 1;
 		val = akid->keyid;
-		dp = (const unsigned char *)val->data;
-		xlen = val->length;
+		dp = ASN1_STRING_get0_data(val);
+		xlen = ASN1_STRING_length(val);
 
 		buf->ns.len = (int)xlen;
 		if (len < (size_t)buf->ns.len)
@@ -248,7 +255,7 @@ lws_tls_openssl_cert_info(X509 *x509, enum lws_tls_cert_info type,
 			return 1;
 
 #ifndef USE_WOLFSSL
-		akid = (AUTHORITY_KEYID *)X509V3_EXT_d2i(ext);
+		akid = (AUTHORITY_KEYID *)X509V3_EXT_d2i(CAST_X509_EXTENSION(ext));
 #else
 		akid = (AUTHORITY_KEYID *)wolfSSL_X509V3_EXT_d2i(ext);
 #endif
@@ -257,7 +264,7 @@ lws_tls_openssl_cert_info(X509 *x509, enum lws_tls_cert_info type,
 
 #if defined(LWS_HAVE_OPENSSL_STACK)
 		{
-			const X509V3_EXT_METHOD* method = X509V3_EXT_get(ext);
+			const X509V3_EXT_METHOD* method = X509V3_EXT_get(CAST_X509_EXTENSION(ext));
 			STACK_OF(CONF_VALUE) *cv;
 		#if defined(LWS_WITH_BORINGSSL) || defined(LWS_WITH_AWSLC)
 			size_t j;
@@ -303,7 +310,7 @@ bail_ak:
 		ext = X509_get_ext(x509, (int)loc);
 		if (!ext)
 			return 1;
-		akid = (AUTHORITY_KEYID *)X509V3_EXT_d2i(ext);
+		akid = (AUTHORITY_KEYID *)X509V3_EXT_d2i(CAST_X509_EXTENSION(ext));
 		if (!akid || !akid->serial)
 			return 1;
 
@@ -330,17 +337,17 @@ bail_ak:
 		if (!ext)
 			return 1;
 
-		val = X509_EXTENSION_get_data(ext);
-		if (!val)
+		val2 = X509_EXTENSION_get_data(CAST_X509_EXTENSION(ext));
+		if (!val2)
 			return 1;
 
 #if defined(USE_WOLFSSL)
 		return 1;
 #else
-		dp = (const unsigned char *)val->data;
+		dp = ASN1_STRING_get0_data(val2);
 
 		if (ASN1_get_object(&dp, &xlen,
-				    &tag, &xclass, val->length) & 0x80)
+				    &tag, &xclass, ASN1_STRING_length(val2)) & 0x80)
 			return -1;
 
 		if (tag != V_ASN1_OCTET_STRING) {
@@ -456,7 +463,7 @@ lws_x509_verify(struct lws_x509_cert *x509, struct lws_x509_cert *trusted,
 	int ret;
 
 	if (common_name) {
-		X509_NAME *xn = X509_get_subject_name(x509->cert);
+		const X509_NAME *xn = X509_get_subject_name(x509->cert);
 		if (!xn)
 			return -1;
 		X509_NAME_oneline(xn, c, (int)sizeof(c) - 2);

@heitbaum
Copy link
Copy Markdown
Contributor Author

Thanks for the patch. Unfortunately more contortions are needed, since existing openssl3 doesn't have const, simply making things const fixes what's in front of you, and kills it for older openssl. I modified your patch so it still works on older openssl, can you confirm it's OK for your openssl4 case?

diff --git a/lib/tls/openssl/openssl-x509.c b/lib/tls/openssl/openssl-x509.c
index d8b5637c0..15c853ca9 100644
--- a/lib/tls/openssl/openssl-x509.c
+++ b/lib/tls/openssl/openssl-x509.c
@@ -1,7 +1,7 @@
 /*
  * libwebsockets - small server side websockets and web server implementation
  *
- * Copyright (C) 2010 - 2019 Andy Green <andy@warmcat.com>
+ * Copyright (C) 2010 - 2026 Andy Green <andy@warmcat.com>
  *
  * Permission is hereby granted, free of charge, to any person obtaining a copy
  * of this software and associated documentation files (the "Software"), to
@@ -26,6 +26,12 @@
 #include "private-lib-core.h"
 #include "private-lib-tls-openssl.h"
 
+#if OPENSSL_VERSION_NUMBER >= 0x40000000L
+#define CAST_X509_EXTENSION(x)	(x)
+#else
+#define CAST_X509_EXTENSION(x)	((X509_EXTENSION *)(x))
+#endif
+
 #if !defined(LWS_PLAT_OPTEE)
 static int
 dec(char c)
@@ -39,7 +45,7 @@ lws_tls_openssl_asn1time_to_unix(ASN1_TIME *as)
 {
 #if !defined(LWS_PLAT_OPTEE)
 
-	const char *p = (const char *)as->data;
+	const char *p = (const char *)ASN1_STRING_get0_data(as);
 	struct tm t;
 
 	/* [YY]YYMMDDHHMMSSZ */
@@ -84,12 +90,13 @@ lws_tls_openssl_cert_info(X509 *x509, enum lws_tls_cert_info type,
 #ifndef USE_WOLFSSL
 	const unsigned char *dp;
 	ASN1_OCTET_STRING *val;
+	const ASN1_OCTET_STRING *val2;
 	AUTHORITY_KEYID *akid;
-	X509_EXTENSION *ext;
+	const X509_EXTENSION *ext;
 	int tag, xclass, r = 1;
 	long xlen, loc;
 #endif
-	X509_NAME *xn;
+	const X509_NAME *xn;
 #if !defined(LWS_PLAT_OPTEE)
 	char *p, *p1;
 	size_t rl;
@@ -219,15 +226,15 @@ lws_tls_openssl_cert_info(X509 *x509, enum lws_tls_cert_info type,
 		if (!ext)
 			return 1;
 #ifndef USE_WOLFSSL
-		akid = (AUTHORITY_KEYID *)X509V3_EXT_d2i(ext);
+		akid = (AUTHORITY_KEYID *)X509V3_EXT_d2i(CAST_X509_EXTENSION(ext));
 #else
 		akid = (AUTHORITY_KEYID *)wolfSSL_X509V3_EXT_d2i(ext);
 #endif
 		if (!akid || !akid->keyid)
 			return 1;
 		val = akid->keyid;
-		dp = (const unsigned char *)val->data;
-		xlen = val->length;
+		dp = ASN1_STRING_get0_data(val);
+		xlen = ASN1_STRING_length(val);
 
 		buf->ns.len = (int)xlen;
 		if (len < (size_t)buf->ns.len)
@@ -248,7 +255,7 @@ lws_tls_openssl_cert_info(X509 *x509, enum lws_tls_cert_info type,
 			return 1;
 
 #ifndef USE_WOLFSSL
-		akid = (AUTHORITY_KEYID *)X509V3_EXT_d2i(ext);
+		akid = (AUTHORITY_KEYID *)X509V3_EXT_d2i(CAST_X509_EXTENSION(ext));
 #else
 		akid = (AUTHORITY_KEYID *)wolfSSL_X509V3_EXT_d2i(ext);
 #endif
@@ -257,7 +264,7 @@ lws_tls_openssl_cert_info(X509 *x509, enum lws_tls_cert_info type,
 
 #if defined(LWS_HAVE_OPENSSL_STACK)
 		{
-			const X509V3_EXT_METHOD* method = X509V3_EXT_get(ext);
+			const X509V3_EXT_METHOD* method = X509V3_EXT_get(CAST_X509_EXTENSION(ext));
 			STACK_OF(CONF_VALUE) *cv;
 		#if defined(LWS_WITH_BORINGSSL) || defined(LWS_WITH_AWSLC)
 			size_t j;
@@ -303,7 +310,7 @@ bail_ak:
 		ext = X509_get_ext(x509, (int)loc);
 		if (!ext)
 			return 1;
-		akid = (AUTHORITY_KEYID *)X509V3_EXT_d2i(ext);
+		akid = (AUTHORITY_KEYID *)X509V3_EXT_d2i(CAST_X509_EXTENSION(ext));
 		if (!akid || !akid->serial)
 			return 1;
 
@@ -330,17 +337,17 @@ bail_ak:
 		if (!ext)
 			return 1;
 
-		val = X509_EXTENSION_get_data(ext);
-		if (!val)
+		val2 = X509_EXTENSION_get_data(CAST_X509_EXTENSION(ext));
+		if (!val2)
 			return 1;
 
 #if defined(USE_WOLFSSL)
 		return 1;
 #else
-		dp = (const unsigned char *)val->data;
+		dp = ASN1_STRING_get0_data(val2);
 
 		if (ASN1_get_object(&dp, &xlen,
-				    &tag, &xclass, val->length) & 0x80)
+				    &tag, &xclass, ASN1_STRING_length(val2)) & 0x80)
 			return -1;
 
 		if (tag != V_ASN1_OCTET_STRING) {
@@ -456,7 +463,7 @@ lws_x509_verify(struct lws_x509_cert *x509, struct lws_x509_cert *trusted,
 	int ret;
 
 	if (common_name) {
-		X509_NAME *xn = X509_get_subject_name(x509->cert);
+		const X509_NAME *xn = X509_get_subject_name(x509->cert);
 		if (!xn)
 			return -1;
 		X509_NAME_oneline(xn, c, (int)sizeof(c) - 2);

Your version works correctly with OpenSSL 4.0.0-alpha1 too.

ASN1_STRING are now opaque types — the internal data and length fields are
no longer directly accessible. Use the accessor API instead. Accessors
have been available since OpenSSL 1.1.0

Signatures of numerous API functions, including those that are related
to X509 processing, are changed to include const qualifiers for argument
and return types, where suitable. Add const qualifer to variables.

Co-authored-by: Andy Green <andy@warmcat.com>
Signed-off-by: Rudi Heitbaum <rudi@heitbaum.com>
@heitbaum
Copy link
Copy Markdown
Contributor Author

Force pushed updated commit.

@lws-team lws-team force-pushed the main branch 3 times, most recently from 6790fe8 to 609de65 Compare March 27, 2026 14:43
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants