diff --git a/src/ssl_asn1.c b/src/ssl_asn1.c index ca3c699fef5..6a46c25d530 100644 --- a/src/ssl_asn1.c +++ b/src/ssl_asn1.c @@ -1000,6 +1000,60 @@ void wolfSSL_ASN1_INTEGER_free(WOLFSSL_ASN1_INTEGER* in) XFREE(in, NULL, DYNAMIC_TYPE_OPENSSL); } +/* Get the length of the raw integer value bytes, stripping the DER tag/length + * header if present. Required for OpenSSL compatibility where ASN1_INTEGER is + * typedef'd to ASN1_STRING and callers use ASN1_STRING_length() on integers. + * + * @param [in] ai ASN.1 INTEGER object. + * @return Length of the raw integer value on success. + * @return 0 when ai is NULL or data is invalid. + */ +int wolfSSL_ASN1_INTEGER_get_length(const WOLFSSL_ASN1_INTEGER* ai) +{ + if (ai == NULL || ai->data == NULL || ai->length <= 0) { + return 0; + } + if (ai->data[0] == ASN_INTEGER) { + word32 idx = 1; + int len = 0; + if (GetLength(ai->data, &idx, &len, (word32)ai->length) > 0 && + idx + (word32)len == (word32)ai->length) { + return len; + } + } + /* WOLFSSL_QT / WOLFSSL_HAPROXY format: raw bytes without DER header, + * or data that coincidentally starts with 0x02 but whose header+value + * boundaries do not span exactly ai->length. */ + return ai->length; +} + +/* Get a pointer to the raw integer value bytes, skipping the DER tag/length + * header if present. Required for OpenSSL compatibility where ASN1_INTEGER is + * typedef'd to ASN1_STRING and callers use ASN1_STRING_get0_data() on integers. + * + * @param [in] ai ASN.1 INTEGER object. + * @return Pointer to the raw integer value bytes on success. + * @return NULL when ai is NULL or data is invalid. + */ +const unsigned char* wolfSSL_ASN1_INTEGER_get0_data(const WOLFSSL_ASN1_INTEGER* ai) +{ + if (ai == NULL || ai->data == NULL || ai->length <= 0) { + return NULL; + } + if (ai->data[0] == ASN_INTEGER) { + word32 idx = 1; + int len = 0; + if (GetLength(ai->data, &idx, &len, (word32)ai->length) > 0 && + idx + (word32)len == (word32)ai->length) { + return ai->data + idx; + } + } + /* WOLFSSL_QT / WOLFSSL_HAPROXY format: raw bytes without DER header, + * or data that coincidentally starts with 0x02 but whose header+value + * boundaries do not span exactly ai->length. */ + return ai->data; +} + #if defined(OPENSSL_EXTRA) /* Reset the data of ASN.1 INTEGER object back to empty fixed array. * diff --git a/wolfssl/openssl/ssl.h b/wolfssl/openssl/ssl.h index 2d4d6aaadda..063500675e1 100644 --- a/wolfssl/openssl/ssl.h +++ b/wolfssl/openssl/ssl.h @@ -1022,8 +1022,27 @@ wolfSSL_X509_STORE_set_verify_cb((WOLFSSL_X509_STORE *)(s), (WOLFSSL_X509_STORE_ #define ASN1_STRING_cmp wolfSSL_ASN1_STRING_cmp #define ASN1_OCTET_STRING_cmp wolfSSL_ASN1_STRING_cmp #define ASN1_STRING_data wolfSSL_ASN1_STRING_data +/* In OpenSSL, ASN1_INTEGER is a typedef alias of ASN1_STRING (same struct), + * so ASN1_STRING_length/get0_data work on ASN1_INTEGER* as well. + * In wolfSSL they are distinct structs, so dispatch by type using _Generic. */ +#if !defined(__cplusplus) && defined(__STDC_VERSION__) && \ + __STDC_VERSION__ >= 201112L +#define ASN1_STRING_length(x) \ + _Generic((x), \ + WOLFSSL_ASN1_INTEGER*: wolfSSL_ASN1_INTEGER_get_length, \ + const WOLFSSL_ASN1_INTEGER*: wolfSSL_ASN1_INTEGER_get_length, \ + default: wolfSSL_ASN1_STRING_length \ + )(x) +#define ASN1_STRING_get0_data(x) \ + _Generic((x), \ + WOLFSSL_ASN1_INTEGER*: wolfSSL_ASN1_INTEGER_get0_data, \ + const WOLFSSL_ASN1_INTEGER*: wolfSSL_ASN1_INTEGER_get0_data, \ + default: wolfSSL_ASN1_STRING_get0_data \ + )(x) +#else #define ASN1_STRING_get0_data wolfSSL_ASN1_STRING_get0_data #define ASN1_STRING_length wolfSSL_ASN1_STRING_length +#endif #define ASN1_STRING_to_UTF8 wolfSSL_ASN1_STRING_to_UTF8 #define ASN1_UNIVERSALSTRING_to_string wolfSSL_ASN1_UNIVERSALSTRING_to_string #define ASN1_STRING_print_ex wolfSSL_ASN1_STRING_print_ex diff --git a/wolfssl/ssl.h b/wolfssl/ssl.h index 1c0301ab66e..df5e2723657 100644 --- a/wolfssl/ssl.h +++ b/wolfssl/ssl.h @@ -2356,6 +2356,9 @@ WOLFSSL_API unsigned char* wolfSSL_ASN1_STRING_data(WOLFSSL_ASN1_STRING* asn); WOLFSSL_API const unsigned char* wolfSSL_ASN1_STRING_get0_data( const WOLFSSL_ASN1_STRING* asn); WOLFSSL_API int wolfSSL_ASN1_STRING_length(const WOLFSSL_ASN1_STRING* asn); +WOLFSSL_API int wolfSSL_ASN1_INTEGER_get_length(const WOLFSSL_ASN1_INTEGER* ai); +WOLFSSL_API const unsigned char* wolfSSL_ASN1_INTEGER_get0_data( + const WOLFSSL_ASN1_INTEGER* ai); WOLFSSL_API int wolfSSL_ASN1_STRING_copy(WOLFSSL_ASN1_STRING* dst, const WOLFSSL_ASN1_STRING* src); WOLFSSL_API int wolfSSL_X509_verify_cert(WOLFSSL_X509_STORE_CTX* ctx);