From b4bac5d39b56140756f49d1afca2ec2166d07fa1 Mon Sep 17 00:00:00 2001 From: Ilia Shipitsin Date: Tue, 22 Sep 2026 18:46:24 +0200 Subject: [PATCH] Mayaqua: Fix OpenSSL 4.0 build failures due to opaque ASN.1 structures In OpenSSL 4.0, `struct asn1_string_st` was made opaque (an incomplete type), causing compiler errors when directly accessing members such as `data`, `length`, and `type` on `ASN1_INTEGER`, `ASN1_TIME`, and `ASN1_STRING` pointers. Update `src/Mayaqua/Encrypt.c` to use standard OpenSSL accessor and helper functions when compiling against OpenSSL >= 1.1.0: - NewX509 / NewRootX509: Replace direct manipulation of `s->data` and `s->length` with `ASN1_INTEGER_set(s, 0)` and `BN_bin2bn` + `BN_to_ASN1_INTEGER`. - SystemToAsn1Time: Replace direct access to `t->data`, `t->length`, and `t->type` with `ASN1_TIME_set_string(t, tmp)`. - Asn1TimeToSystem: Read time strings using `ASN1_STRING_get0_data` and `ASN1_STRING_length` into a stack buffer, and check type with `ASN1_STRING_type`. - GetUniStrFromX509Name: Change `data` to `const ASN1_STRING *` and check the type via `ASN1_STRING_type(data)`. - X509ToX: Extract serial number bytes and length using `ASN1_STRING_get0_data` and `ASN1_STRING_length`. --- src/Mayaqua/Encrypt.c | 85 ++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 83 insertions(+), 2 deletions(-) diff --git a/src/Mayaqua/Encrypt.c b/src/Mayaqua/Encrypt.c index c52ed16a..f13557dc 100644 --- a/src/Mayaqua/Encrypt.c +++ b/src/Mayaqua/Encrypt.c @@ -1796,6 +1796,21 @@ X509 *NewX509(K *pub, K *priv, X *ca, NAME *name, UINT days, X_SERIAL *serial) // Set the Serial Number s = X509_get_serialNumber(x509); +#if OPENSSL_VERSION_NUMBER >= 0x10100000L + if (serial == NULL) + { + ASN1_INTEGER_set(s, 0); + } + else + { + BIGNUM *bn = BN_bin2bn(serial->data, serial->size, NULL); + if (bn != NULL) + { + BN_to_ASN1_INTEGER(bn, s); + BN_free(bn); + } + } +#else OPENSSL_free(s->data); if (serial == NULL) { @@ -1810,6 +1825,7 @@ X509 *NewX509(K *pub, K *priv, X *ca, NAME *name, UINT days, X_SERIAL *serial) Copy(s->data, serial->data, serial->size); s->length = serial->size; } +#endif /* // Extensions @@ -1939,6 +1955,21 @@ X509 *NewRootX509(K *pub, K *priv, NAME *name, UINT days, X_SERIAL *serial) // Set a Serial Number s = X509_get_serialNumber(x509); +#if OPENSSL_VERSION_NUMBER >= 0x10100000L + if (serial == NULL) + { + ASN1_INTEGER_set(s, 0); + } + else + { + BIGNUM *bn = BN_bin2bn(serial->data, serial->size, NULL); + if (bn != NULL) + { + BN_to_ASN1_INTEGER(bn, s); + BN_free(bn); + } + } +#else OPENSSL_free(s->data); if (serial == NULL) { @@ -1953,6 +1984,7 @@ X509 *NewRootX509(K *pub, K *priv, NAME *name, UINT days, X_SERIAL *serial) Copy(s->data, serial->data, serial->size); s->length = serial->size; } +#endif // Extensions ex = X509V3_EXT_conf_nid(NULL, NULL, NID_basic_constraints, "critical,CA:TRUE"); @@ -2180,6 +2212,9 @@ bool SystemToAsn1Time(void *asn1_time, SYSTEMTIME *s) return false; } t = (ASN1_TIME *)asn1_time; +#if OPENSSL_VERSION_NUMBER >= 0x10000000L + return ASN1_TIME_set_string(t, tmp) != 0; +#else if (t->data == NULL || t->length < sizeof(tmp)) { t->data = OPENSSL_malloc(sizeof(tmp)); @@ -2189,6 +2224,7 @@ bool SystemToAsn1Time(void *asn1_time, SYSTEMTIME *s) t->type = V_ASN1_UTCTIME; return true; +#endif } // Convert the system time to a string @@ -2228,6 +2264,12 @@ UINT64 Asn1TimeToUINT64(void *asn1_time) bool Asn1TimeToSystem(SYSTEMTIME *s, void *asn1_time) { ASN1_TIME *t; +#if OPENSSL_VERSION_NUMBER >= 0x10100000L + char tmp[32]; + int len; + const char *src; + int type; +#endif // Validate arguments if (s == NULL || asn1_time == NULL) { @@ -2235,6 +2277,29 @@ bool Asn1TimeToSystem(SYSTEMTIME *s, void *asn1_time) } t = (ASN1_TIME *)asn1_time; +#if OPENSSL_VERSION_NUMBER >= 0x10100000L + len = ASN1_STRING_length((const ASN1_STRING *)t); + src = (const char *)ASN1_STRING_get0_data((const ASN1_STRING *)t); + type = ASN1_STRING_type((const ASN1_STRING *)t); + + if (src == NULL || len <= 0 || len >= (int)sizeof(tmp)) + { + return false; + } + + Copy(tmp, src, len); + tmp[len] = '\0'; + + if (StrToSystem(s, tmp) == false) + { + return false; + } + + if (type == V_ASN1_GENERALIZEDTIME) + { + LocalToSystem(s, s); + } +#else if (StrToSystem(s, (char *)t->data) == false) { return false; @@ -2244,6 +2309,7 @@ bool Asn1TimeToSystem(SYSTEMTIME *s, void *asn1_time) { LocalToSystem(s, s); } +#endif return true; } @@ -2803,7 +2869,7 @@ wchar_t *GetUniStrFromX509Name(void *xn, int nid) bool unicode = false; bool is_utf_8 = false; ASN1_OBJECT *obj; - ASN1_STRING *data; + const ASN1_STRING *data; // Validate arguments if (xn == NULL || nid == 0) { @@ -2831,6 +2897,16 @@ wchar_t *GetUniStrFromX509Name(void *xn, int nid) { return NULL; } +#if OPENSSL_VERSION_NUMBER >= 0x10100000L + if (ASN1_STRING_type(data) == V_ASN1_BMPSTRING) + { + unicode = true; + } + if (ASN1_STRING_type(data) == V_ASN1_UTF8STRING || ASN1_STRING_type(data) == V_ASN1_T61STRING) + { + is_utf_8 = true; + } +#else if (data->type == V_ASN1_BMPSTRING) { unicode = true; @@ -2839,6 +2915,7 @@ wchar_t *GetUniStrFromX509Name(void *xn, int nid) { is_utf_8 = true; } +#endif size = UniStrLen((wchar_t *)txt) * 4 + 8; for (i = 0;i < size;i++) @@ -3742,7 +3819,11 @@ X *X509ToX(X509 *x509) // Get the Serial Number s = X509_get_serialNumber(x509); - x->serial = NewXSerial(s->data, s->length); +#if OPENSSL_VERSION_NUMBER >= 0x10100000L + x->serial = (s != NULL) ? NewXSerial((void *)ASN1_STRING_get0_data((const ASN1_STRING *)s), ASN1_STRING_length((const ASN1_STRING *)s)) : NULL; +#else + x->serial = (s != NULL) ? NewXSerial(s->data, s->length) : NULL; +#endif if (x->serial == NULL) { char zero = 0;