Skip to content

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

Open
heitbaum wants to merge 1 commit intowarmcat:mainfrom
heitbaum:openssl
Open

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

Conversation

@heitbaum
Copy link
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
Copy link
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
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
Contributor Author

Force pushed updated commit.

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