[PATCH] crypto: Treat ASN1_STRING as an opaque type
Xiangfei Ding
xfding at google.com
Thu Oct 22 03:02:44 PDT 2026
OpenSSL has published migration guide mentioning that the type is
turning opaque. One should use accessor functions instead.
See migration guide [1] [2].
[1] https://docs.openssl.org/master/man7/ossl-guide-migration/#asn1_string-values-have-never-been-nul-byte-terminated
[2] https://docs.openssl.org/master/man7/ossl-guide-migration/#the-asn1_string-type-is-now-opaque
Signed-off-by: Xiangfei Ding <xfding at google.com>
---
src/crypto/crypto_openssl.c | 8 +---
src/crypto/tls_openssl.c | 82 ++++++++++++++++++++++-------------
src/crypto/tls_openssl_ocsp.c | 15 ++++---
3 files changed, 64 insertions(+), 41 deletions(-)
diff --git a/src/crypto/crypto_openssl.c b/src/crypto/crypto_openssl.c
index f67d46e9e..29a391ab7 100644
--- a/src/crypto/crypto_openssl.c
+++ b/src/crypto/crypto_openssl.c
@@ -3784,14 +3784,8 @@ struct wpabuf * crypto_ec_key_get_subject_public_key(struct crypto_ec_key *key)
len = EC_POINT_point2oct(group, point, POINT_CONVERSION_COMPRESSED,
der, len, ctx);
- OPENSSL_free(pubkey->pub_key->data);
- pubkey->pub_key->data = der;
+ ASN1_STRING_set0(pubkey->pub_key, der, len);
der = NULL;
- pubkey->pub_key->length = len;
- /* No unused bits */
- pubkey->pub_key->flags &= ~(ASN1_STRING_FLAG_BITS_LEFT | 0x07);
- pubkey->pub_key->flags |= ASN1_STRING_FLAG_BITS_LEFT;
-
der_len = i2d_EC_COMP_PUBKEY(pubkey, &der);
if (der_len <= 0) {
wpa_printf(MSG_ERROR,
diff --git a/src/crypto/tls_openssl.c b/src/crypto/tls_openssl.c
index 032bf05f2..0c7eb60c8 100644
--- a/src/crypto/tls_openssl.c
+++ b/src/crypto/tls_openssl.c
@@ -2088,6 +2088,8 @@ char * tls_connection_peer_serial_num(void *tls_ctx,
struct tls_connection *conn)
{
ASN1_INTEGER *ser;
+ const unsigned char *ser_data;
+ int ser_len;
char *serial_num;
size_t len;
@@ -2098,13 +2100,13 @@ char * tls_connection_peer_serial_num(void *tls_ctx,
if (!ser)
return NULL;
- len = ASN1_STRING_length(ser) * 2 + 1;
+ ser_data = ASN1_STRING_get0_data(ser);
+ ser_len = ASN1_STRING_length(ser);
+ len = (size_t) ser_len * 2 + 1;
serial_num = os_malloc(len);
if (!serial_num)
return NULL;
- wpa_snprintf_hex_uppercase(serial_num, len,
- ASN1_STRING_get0_data(ser),
- ASN1_STRING_length(ser));
+ wpa_snprintf_hex_uppercase(serial_num, len, ser_data, ser_len);
return serial_num;
}
@@ -2296,6 +2298,8 @@ static int match_dn_field(const X509 *cert, int nid, const char *field,
i)) > -1;) {
const X509_NAME_ENTRY *e;
const ASN1_STRING *cn;
+ const unsigned char *cn_data;
+ int cn_len;
e = X509_NAME_get_entry(name, i);
if (!e)
@@ -2311,6 +2315,9 @@ static int match_dn_field(const X509 *cert, int nid, const char *field,
if (match_index != config_dn_field_index)
continue;
+ cn_data = ASN1_STRING_get0_data(cn);
+ cn_len = ASN1_STRING_length(cn);
+
/* Check wildcard at the right end side */
/* E.g., if OU=develop* mentioned in configuration, allow 'OU'
* of the subject in the client certificate to start with
@@ -2319,20 +2326,18 @@ static int match_dn_field(const X509 *cert, int nid, const char *field,
/* Compare actual certificate DN field value with
* configuration DN field value up to the specified
* length. */
- ret = ASN1_STRING_length(cn) >= len - 1 &&
- os_memcmp(ASN1_STRING_get0_data(cn), value,
- len - 1) == 0;
+ ret = (size_t) cn_len >= len - 1 &&
+ os_memcmp(cn_data, value, len - 1) == 0;
} else {
/* Compare actual certificate DN field value with
* configuration DN field value */
- ret = ASN1_STRING_length(cn) == len &&
- os_memcmp(ASN1_STRING_get0_data(cn), value,
- len) == 0;
+ ret = (size_t) cn_len == len && os_memcmp(cn_data, value, len) == 0;
}
if (!ret) {
wpa_printf(MSG_ERROR,
- "OpenSSL: Failed to match %s '%s' with certificate DN field value '%s'",
- field, value, ASN1_STRING_get0_data(cn));
+ "OpenSSL: Failed to match %s '%s' with certificate DN field"
+ " value '%.*s'",
+ field, value, cn_len, (const char *) cn_data);
}
break;
}
@@ -2458,15 +2463,22 @@ static int tls_match_suffix_helper(X509 *cert, const char *match,
ext = X509_get_ext_d2i(cert, NID_subject_alt_name, NULL, NULL);
for (j = 0; ext && j < sk_GENERAL_NAME_num(ext); j++) {
+ const unsigned char *dns_data;
+ int dns_len;
+
gen = sk_GENERAL_NAME_value(ext, j);
- if (gen->type != GEN_DNS)
+ if (gen->type != GEN_DNS || !gen->d.dNSName)
+ continue;
+
+ dns_data = ASN1_STRING_get0_data(gen->d.dNSName);
+ dns_len = ASN1_STRING_length(gen->d.dNSName);
+ if (!dns_data)
continue;
+
dns_name++;
wpa_hexdump_ascii(MSG_DEBUG, "TLS: Certificate dNSName",
- ASN1_STRING_get0_data(gen->d.dNSName),
- ASN1_STRING_length(gen->d.dNSName));
- if (domain_suffix_match(ASN1_STRING_get0_data(gen->d.dNSName),
- ASN1_STRING_length(gen->d.dNSName),
+ dns_data, dns_len);
+ if (domain_suffix_match(dns_data, dns_len,
match, match_len, full) == 1) {
wpa_printf(MSG_DEBUG, "TLS: %s in dNSName found",
full ? "Match" : "Suffix match");
@@ -2486,6 +2498,8 @@ static int tls_match_suffix_helper(X509 *cert, const char *match,
for (;;) {
const X509_NAME_ENTRY *e;
const ASN1_STRING *cn;
+ const unsigned char *cn_data;
+ int cn_len;
i = X509_NAME_get_index_by_NID((X509_NAME *) name,
NID_commonName, i);
@@ -2497,11 +2511,11 @@ static int tls_match_suffix_helper(X509 *cert, const char *match,
cn = X509_NAME_ENTRY_get_data(e);
if (cn == NULL)
continue;
+ cn_data = ASN1_STRING_get0_data(cn);
+ cn_len = ASN1_STRING_length(cn);
wpa_hexdump_ascii(MSG_DEBUG, "TLS: Certificate commonName",
- ASN1_STRING_get0_data(cn),
- ASN1_STRING_length(cn));
- if (domain_suffix_match(ASN1_STRING_get0_data(cn),
- ASN1_STRING_length(cn),
+ cn_data, cn_len);
+ if (domain_suffix_match(cn_data, cn_len,
match, match_len, full) == 1) {
wpa_printf(MSG_DEBUG, "TLS: %s in commonName found",
full ? "Match" : "Suffix match");
@@ -2701,6 +2715,8 @@ static void openssl_tls_cert_event(struct tls_connection *conn,
ext = X509_get_ext_d2i(err_cert, NID_subject_alt_name, NULL, NULL);
for (i = 0; ext && i < sk_GENERAL_NAME_num(ext); i++) {
char *pos;
+ const unsigned char *ia5_data;
+ int ia5_len;
if (num_altsubject == TLS_MAX_ALT_SUBJECT)
break;
@@ -2710,7 +2726,15 @@ static void openssl_tls_cert_event(struct tls_connection *conn,
gen->type != GEN_URI)
continue;
- pos = os_malloc(10 + ASN1_STRING_length(gen->d.ia5) + 1);
+ if (!gen->d.ia5)
+ continue;
+
+ ia5_data = ASN1_STRING_get0_data(gen->d.ia5);
+ ia5_len = ASN1_STRING_length(gen->d.ia5);
+ if (!ia5_data)
+ continue;
+
+ pos = os_malloc(10 + ia5_len + 1);
if (pos == NULL)
break;
altsubject[num_altsubject++] = pos;
@@ -2730,9 +2754,8 @@ static void openssl_tls_cert_event(struct tls_connection *conn,
break;
}
- os_memcpy(pos, ASN1_STRING_get0_data(gen->d.ia5),
- ASN1_STRING_length(gen->d.ia5));
- pos += ASN1_STRING_length(gen->d.ia5);
+ os_memcpy(pos, ia5_data, ia5_len);
+ pos += ia5_len;
*pos = '\0';
}
sk_GENERAL_NAME_pop_free(ext, GENERAL_NAME_free);
@@ -6063,11 +6086,12 @@ static void openssl_debug_dump_certificate(int i, X509 *cert)
X509_NAME_oneline(X509_get_subject_name(cert), buf, sizeof(buf));
ser = X509_get_serialNumber(cert);
- if (ser)
+ if (ser) {
+ const unsigned char *ser_data = ASN1_STRING_get0_data(ser);
+ int ser_len = ASN1_STRING_length(ser);
wpa_snprintf_hex_uppercase(serial_num, sizeof(serial_num),
- ASN1_STRING_get0_data(ser),
- ASN1_STRING_length(ser));
- else
+ ser_data, ser_len);
+ } else
serial_num[0] = '\0';
pkey = X509_get_pubkey(cert);
diff --git a/src/crypto/tls_openssl_ocsp.c b/src/crypto/tls_openssl_ocsp.c
index 7780b71fd..5c9bd8113 100644
--- a/src/crypto/tls_openssl_ocsp.c
+++ b/src/crypto/tls_openssl_ocsp.c
@@ -428,7 +428,8 @@ static int issuer_match(X509 *cert, X509 *issuer, CertID *certid)
ikey = X509_get0_pubkey_bitstr(issuer);
if (!ikey ||
- !EVP_Digest(ikey->data, ikey->length, md, &len, dgst, NULL) ||
+ !EVP_Digest(ASN1_STRING_get0_data(ikey), ASN1_STRING_length(ikey),
+ md, &len, dgst, NULL) ||
!ASN1_OCTET_STRING_set(hash, md, len)) {
ASN1_OCTET_STRING_free(hash);
return -1;
@@ -455,6 +456,7 @@ static X509 * ocsp_find_signer(STACK_OF(X509) *certs, ResponderID *rid)
{
int i;
unsigned char hash[SHA_DIGEST_LENGTH];
+ const unsigned char *key_data;
if (rid->type == 0) {
/* byName */
@@ -462,14 +464,17 @@ static X509 * ocsp_find_signer(STACK_OF(X509) *certs, ResponderID *rid)
}
/* byKey */
- if (rid->value.byKey->length != SHA_DIGEST_LENGTH)
+ if (!rid->value.byKey ||
+ ASN1_STRING_length(rid->value.byKey) != SHA_DIGEST_LENGTH)
+ return NULL;
+ key_data = ASN1_STRING_get0_data(rid->value.byKey);
+ if (!key_data)
return NULL;
for (i = 0; i < sk_X509_num(certs); i++) {
X509 *x = sk_X509_value(certs, i);
X509_pubkey_digest(x, EVP_sha1(), hash, NULL);
- if (os_memcmp(rid->value.byKey->data, hash,
- SHA_DIGEST_LENGTH) == 0)
+ if (os_memcmp(key_data, hash, SHA_DIGEST_LENGTH) == 0)
return x;
}
@@ -540,7 +545,7 @@ enum ocsp_result check_ocsp_resp(SSL_CTX *ssl_ctx, SSL *ssl, X509 *cert,
return OCSP_INVALID;
}
- basic_data = ASN1_STRING_data(bytes->response);
+ basic_data = ASN1_STRING_get0_data(bytes->response);
basic_len = ASN1_STRING_length(bytes->response);
wpa_hexdump(MSG_DEBUG, "OpenSSL: BasicOCSPResponse",
basic_data, basic_len);
--
2.56.0.218.g1ec904b173-goog
More information about the Hostap
mailing list