From 626035bec7aa5cb46ec85e013fa8f1d964b55bdb Mon Sep 17 00:00:00 2001
From: Jouni Malinen <j@w1.fi>
Date: Fri, 12 Mar 2021 23:24:54 +0200
Subject: [PATCH] TLS: Use ASN.1 helper functions

Simplify ASN.1 parser operations by using the shared helper functions.

Signed-off-by: Jouni Malinen <j@w1.fi>
---
 src/tls/tlsv1_client_ocsp.c | 180 ++++++++++-----------------
 src/tls/tlsv1_cred.c        | 239 +++++++++++++-----------------------
 2 files changed, 154 insertions(+), 265 deletions(-)

diff --git a/src/tls/tlsv1_client_ocsp.c b/src/tls/tlsv1_client_ocsp.c
index 1d7b68ca2..128f4b5b9 100644
--- a/src/tls/tlsv1_client_ocsp.c
+++ b/src/tls/tlsv1_client_ocsp.c
@@ -138,12 +138,8 @@ static int tls_process_ocsp_single_response(struct tlsv1_client *conn,
 	 */
 
 	/* CertID ::= SEQUENCE */
-	if (asn1_get_next(resp, len, &hdr) < 0 ||
-	    hdr.class != ASN1_CLASS_UNIVERSAL ||
-	    hdr.tag != ASN1_TAG_SEQUENCE) {
-		wpa_printf(MSG_DEBUG,
-			   "OCSP: Expected SEQUENCE (CertID) - found class %d tag 0x%x",
-			   hdr.class, hdr.tag);
+	if (asn1_get_next(resp, len, &hdr) < 0 || !asn1_is_sequence(&hdr)) {
+		asn1_unexpected(&hdr, "OCSP: Expected SEQUENCE (CertID)");
 		return -1;
 	}
 	pos = hdr.payload;
@@ -163,11 +159,9 @@ static int tls_process_ocsp_single_response(struct tlsv1_client *conn,
 
 	/* issuerNameHash  OCTET STRING */
 	if (asn1_get_next(pos, end - pos, &hdr) < 0 ||
-	    hdr.class != ASN1_CLASS_UNIVERSAL ||
-	    hdr.tag != ASN1_TAG_OCTETSTRING) {
-		wpa_printf(MSG_DEBUG,
-			   "OCSP: Expected OCTET STRING (issuerNameHash) - found class %d tag 0x%x",
-			   hdr.class, hdr.tag);
+	    !asn1_is_octetstring(&hdr)) {
+		asn1_unexpected(&hdr,
+				"OCSP: Expected OCTET STRING (issuerNameHash)");
 		return -1;
 	}
 	name_hash = hdr.payload;
@@ -190,11 +184,9 @@ static int tls_process_ocsp_single_response(struct tlsv1_client *conn,
 
 	/* issuerKeyHash  OCTET STRING */
 	if (asn1_get_next(pos, end - pos, &hdr) < 0 ||
-	    hdr.class != ASN1_CLASS_UNIVERSAL ||
-	    hdr.tag != ASN1_TAG_OCTETSTRING) {
-		wpa_printf(MSG_DEBUG,
-			   "OCSP: Expected OCTET STRING (issuerKeyHash) - found class %d tag 0x%x",
-			   hdr.class, hdr.tag);
+	    !asn1_is_octetstring(&hdr)) {
+		asn1_unexpected(&hdr,
+				"OCSP: Expected OCTET STRING (issuerKeyHash)");
 		return -1;
 	}
 	key_hash = hdr.payload;
@@ -214,11 +206,10 @@ static int tls_process_ocsp_single_response(struct tlsv1_client *conn,
 
 	/* serialNumber CertificateSerialNumber ::= INTEGER */
 	if (asn1_get_next(pos, end - pos, &hdr) < 0 ||
-	    hdr.class != ASN1_CLASS_UNIVERSAL ||
-	    hdr.tag != ASN1_TAG_INTEGER ||
+	    !asn1_is_integer(&hdr) ||
 	    hdr.length < 1 || hdr.length > X509_MAX_SERIAL_NUM_LEN) {
-		wpa_printf(MSG_DEBUG, "OCSP: No INTEGER tag found for serialNumber; class=%d tag=0x%x length=%u",
-			   hdr.class, hdr.tag, hdr.length);
+		asn1_unexpected(&hdr,
+				"OCSP: No INTEGER tag found for serialNumber");
 		return -1;
 	}
 	serial_number = hdr.payload;
@@ -240,12 +231,16 @@ static int tls_process_ocsp_single_response(struct tlsv1_client *conn,
 	pos = end;
 	end = resp + len;
 
-	/* certStatus CertStatus ::= CHOICE */
+	/* certStatus CertStatus ::= CHOICE
+	 *
+	 * CertStatus ::= CHOICE {
+	 *     good        [0]     IMPLICIT NULL,
+	 *     revoked     [1]     IMPLICIT RevokedInfo,
+	 *     unknown     [2]     IMPLICIT UnknownInfo }
+	 */
 	if (asn1_get_next(pos, end - pos, &hdr) < 0 ||
 	    hdr.class != ASN1_CLASS_CONTEXT_SPECIFIC) {
-		wpa_printf(MSG_DEBUG,
-			   "OCSP: Expected CHOICE (CertStatus) - found class %d tag 0x%x",
-			   hdr.class, hdr.tag);
+		asn1_unexpected(&hdr, "OCSP: Expected CHOICE (CertStatus)");
 		return -1;
 	}
 	cert_status = hdr.tag;
@@ -257,8 +252,7 @@ static int tls_process_ocsp_single_response(struct tlsv1_client *conn,
 	os_get_time(&now);
 	/* thisUpdate  GeneralizedTime */
 	if (asn1_get_next(pos, end - pos, &hdr) < 0 ||
-	    hdr.class != ASN1_CLASS_UNIVERSAL ||
-	    hdr.tag != ASN1_TAG_GENERALIZEDTIME ||
+	    !asn1_is_generalizedtime(&hdr) ||
 	    x509_parse_time(hdr.payload, hdr.length, hdr.tag, &update) < 0) {
 		wpa_printf(MSG_DEBUG, "OCSP: Failed to parse thisUpdate");
 		return -1;
@@ -275,12 +269,11 @@ static int tls_process_ocsp_single_response(struct tlsv1_client *conn,
 	if (pos < end) {
 		if (asn1_get_next(pos, end - pos, &hdr) < 0)
 			return -1;
-		if (hdr.class == ASN1_CLASS_CONTEXT_SPECIFIC && hdr.tag == 0) {
+		if (asn1_is_cs_tag(&hdr, 0) && hdr.constructed) {
 			const u8 *next = hdr.payload + hdr.length;
 
 			if (asn1_get_next(hdr.payload, hdr.length, &hdr) < 0 ||
-			    hdr.class != ASN1_CLASS_UNIVERSAL ||
-			    hdr.tag != ASN1_TAG_GENERALIZEDTIME ||
+			    !asn1_is_generalizedtime(&hdr) ||
 			    x509_parse_time(hdr.payload, hdr.length, hdr.tag,
 					    &update) < 0) {
 				wpa_printf(MSG_DEBUG,
@@ -329,11 +322,9 @@ tls_process_ocsp_responses(struct tlsv1_client *conn,
 	while (pos < end) {
 		/* SingleResponse ::= SEQUENCE */
 		if (asn1_get_next(pos, end - pos, &hdr) < 0 ||
-		    hdr.class != ASN1_CLASS_UNIVERSAL ||
-		    hdr.tag != ASN1_TAG_SEQUENCE) {
-			wpa_printf(MSG_DEBUG,
-				   "OCSP: Expected SEQUENCE (SingleResponse) - found class %d tag 0x%x",
-				   hdr.class, hdr.tag);
+		    !asn1_is_sequence(&hdr)) {
+			asn1_unexpected(&hdr,
+					"OCSP: Expected SEQUENCE (SingleResponse)");
 			return TLS_OCSP_INVALID;
 		}
 		if (tls_process_ocsp_single_response(conn, cert, issuer,
@@ -381,12 +372,9 @@ tls_process_basic_ocsp_response(struct tlsv1_client *conn,
 	 *    certs            [0] EXPLICIT SEQUENCE OF Certificate OPTIONAL }
 	 */
 
-	if (asn1_get_next(resp, len, &hdr) < 0 ||
-	    hdr.class != ASN1_CLASS_UNIVERSAL ||
-	    hdr.tag != ASN1_TAG_SEQUENCE) {
-		wpa_printf(MSG_DEBUG,
-			   "OCSP: Expected SEQUENCE (BasicOCSPResponse) - found class %d tag 0x%x",
-			   hdr.class, hdr.tag);
+	if (asn1_get_next(resp, len, &hdr) < 0 || !asn1_is_sequence(&hdr)) {
+		asn1_unexpected(&hdr,
+				"OCSP: Expected SEQUENCE (BasicOCSPResponse)");
 		return TLS_OCSP_INVALID;
 	}
 	pos = hdr.payload;
@@ -394,11 +382,9 @@ tls_process_basic_ocsp_response(struct tlsv1_client *conn,
 
 	/* ResponseData ::= SEQUENCE */
 	if (asn1_get_next(pos, end - pos, &hdr) < 0 ||
-	    hdr.class != ASN1_CLASS_UNIVERSAL ||
-	    hdr.tag != ASN1_TAG_SEQUENCE) {
-		wpa_printf(MSG_DEBUG,
-			   "OCSP: Expected SEQUENCE (ResponseData) - found class %d tag 0x%x",
-			   hdr.class, hdr.tag);
+	    !asn1_is_sequence(&hdr)) {
+		asn1_unexpected(&hdr,
+				"OCSP: Expected SEQUENCE (ResponseData)");
 		return TLS_OCSP_INVALID;
 	}
 	resp_data = hdr.payload;
@@ -413,11 +399,9 @@ tls_process_basic_ocsp_response(struct tlsv1_client *conn,
 
 	/* signature  BIT STRING */
 	if (asn1_get_next(pos, end - pos, &hdr) < 0 ||
-	    hdr.class != ASN1_CLASS_UNIVERSAL ||
-	    hdr.tag != ASN1_TAG_BITSTRING) {
-		wpa_printf(MSG_DEBUG,
-			   "OCSP: Expected BITSTRING (signature) - found class %d tag 0x%x",
-			   hdr.class, hdr.tag);
+	    !asn1_is_bitstring(&hdr)) {
+		asn1_unexpected(&hdr,
+				"OCSP: Expected BITSTRING (signature)");
 		return TLS_OCSP_INVALID;
 	}
 	if (hdr.length < 1)
@@ -439,11 +423,9 @@ tls_process_basic_ocsp_response(struct tlsv1_client *conn,
 	/* certs  [0] EXPLICIT SEQUENCE OF Certificate OPTIONAL */
 	if (pos < end) {
 		if (asn1_get_next(pos, end - pos, &hdr) < 0 ||
-		    hdr.class != ASN1_CLASS_CONTEXT_SPECIFIC ||
-		    hdr.tag != 0) {
-			wpa_printf(MSG_DEBUG,
-				   "OCSP: Expected [0] EXPLICIT (certs) - found class %d tag 0x%x",
-				   hdr.class, hdr.tag);
+		    !hdr.constructed || !asn1_is_cs_tag(&hdr, 0)) {
+			asn1_unexpected(&hdr,
+					"OCSP: Expected [0] EXPLICIT (certs)");
 			return TLS_OCSP_INVALID;
 		}
 		wpa_hexdump(MSG_MSGDUMP, "OCSP: certs",
@@ -454,11 +436,9 @@ tls_process_basic_ocsp_response(struct tlsv1_client *conn,
 			struct x509_certificate *cert;
 
 			if (asn1_get_next(pos, end - pos, &hdr) < 0 ||
-			    hdr.class != ASN1_CLASS_UNIVERSAL ||
-			    hdr.tag != ASN1_TAG_SEQUENCE) {
-				wpa_printf(MSG_DEBUG,
-					   "OCSP: Expected SEQUENCE (Certificate) - found class %d tag 0x%x",
-					   hdr.class, hdr.tag);
+			    !asn1_is_sequence(&hdr)) {
+				asn1_unexpected(&hdr,
+						"OCSP: Expected SEQUENCE (Certificate)");
 				goto fail;
 			}
 
@@ -491,16 +471,12 @@ tls_process_basic_ocsp_response(struct tlsv1_client *conn,
 	 * version [0] EXPLICIT Version DEFAULT v1
 	 * Version ::= INTEGER { v1(0) }
 	 */
-	if (asn1_get_next(pos, end - pos, &hdr) < 0 &&
-	    hdr.class == ASN1_CLASS_CONTEXT_SPECIFIC &&
-	    hdr.tag == 0) {
+	if (asn1_get_next(pos, end - pos, &hdr) == 0 && hdr.constructed &&
+	    asn1_is_cs_tag(&hdr, 0)) {
 		if (asn1_get_next(pos, end - pos, &hdr) < 0 ||
-		    hdr.class != ASN1_CLASS_UNIVERSAL ||
-		    hdr.tag != ASN1_TAG_INTEGER ||
-		    hdr.length != 1) {
-			wpa_printf(MSG_DEBUG,
-				   "OCSP: No INTEGER (len=1) tag found for version field - found class %d tag 0x%x length %d",
-				   hdr.class, hdr.tag, hdr.length);
+		    !asn1_is_integer(&hdr) || hdr.length != 1) {
+			asn1_unexpected(&hdr,
+					"OCSP: No INTEGER (len=1) tag found for version field");
 			goto fail;
 		}
 		wpa_printf(MSG_DEBUG, "OCSP: ResponseData version %u",
@@ -524,9 +500,7 @@ tls_process_basic_ocsp_response(struct tlsv1_client *conn,
 	 */
 	if (asn1_get_next(pos, end - pos, &hdr) < 0 ||
 	    hdr.class != ASN1_CLASS_CONTEXT_SPECIFIC) {
-		wpa_printf(MSG_DEBUG,
-			   "OCSP: Expected CHOICE (ResponderID) - found class %d tag 0x%x",
-			   hdr.class, hdr.tag);
+		asn1_unexpected(&hdr, "OCSP: Expected CHOICE (ResponderID)");
 		goto fail;
 	}
 
@@ -539,11 +513,9 @@ tls_process_basic_ocsp_response(struct tlsv1_client *conn,
 	} else if (hdr.tag == 2) {
 		/* KeyHash ::= OCTET STRING */
 		if (asn1_get_next(hdr.payload, hdr.length, &hdr) < 0 ||
-		    hdr.class != ASN1_CLASS_UNIVERSAL ||
-		    hdr.tag != ASN1_TAG_OCTETSTRING) {
-			wpa_printf(MSG_DEBUG,
-				   "OCSP: Expected OCTET STRING (KeyHash) - found class %d tag 0x%x",
-				   hdr.class, hdr.tag);
+		    !asn1_is_octetstring(&hdr)) {
+			asn1_unexpected(&hdr,
+					"OCSP: Expected OCTET STRING (KeyHash)");
 			goto fail;
 		}
 		key_hash = hdr.payload;
@@ -564,8 +536,7 @@ tls_process_basic_ocsp_response(struct tlsv1_client *conn,
 
 	/* producedAt  GeneralizedTime */
 	if (asn1_get_next(pos, end - pos, &hdr) < 0 ||
-	    hdr.class != ASN1_CLASS_UNIVERSAL ||
-	    hdr.tag != ASN1_TAG_GENERALIZEDTIME ||
+	    !asn1_is_generalizedtime(&hdr) ||
 	    x509_parse_time(hdr.payload, hdr.length, hdr.tag,
 			    &produced_at) < 0) {
 		wpa_printf(MSG_DEBUG, "OCSP: Failed to parse producedAt");
@@ -577,11 +548,9 @@ tls_process_basic_ocsp_response(struct tlsv1_client *conn,
 
 	/* responses  SEQUENCE OF SingleResponse */
 	if (asn1_get_next(pos, end - pos, &hdr) < 0 ||
-	    hdr.class != ASN1_CLASS_UNIVERSAL ||
-	    hdr.tag != ASN1_TAG_SEQUENCE) {
-		wpa_printf(MSG_DEBUG,
-			   "OCSP: Expected SEQUENCE (responses) - found class %d tag 0x%x",
-			   hdr.class, hdr.tag);
+	    !asn1_is_sequence(&hdr)) {
+		asn1_unexpected(&hdr,
+				"OCSP: Expected SEQUENCE (responses)");
 		goto fail;
 	}
 	responses = hdr.payload;
@@ -697,12 +666,9 @@ enum tls_ocsp_result tls_process_ocsp_response(struct tlsv1_client *conn,
 	 *    responseBytes   [0] EXPLICIT ResponseBytes OPTIONAL }
 	 */
 
-	if (asn1_get_next(resp, len, &hdr) < 0 ||
-	    hdr.class != ASN1_CLASS_UNIVERSAL ||
-	    hdr.tag != ASN1_TAG_SEQUENCE) {
-		wpa_printf(MSG_DEBUG,
-			   "OCSP: Expected SEQUENCE (OCSPResponse) - found class %d tag 0x%x",
-			   hdr.class, hdr.tag);
+	if (asn1_get_next(resp, len, &hdr) < 0 || !asn1_is_sequence(&hdr)) {
+		asn1_unexpected(&hdr,
+				"OCSP: Expected SEQUENCE (OCSPResponse)");
 		return TLS_OCSP_INVALID;
 	}
 	pos = hdr.payload;
@@ -710,12 +676,9 @@ enum tls_ocsp_result tls_process_ocsp_response(struct tlsv1_client *conn,
 
 	/* OCSPResponseStatus ::= ENUMERATED */
 	if (asn1_get_next(pos, end - pos, &hdr) < 0 ||
-	    hdr.class != ASN1_CLASS_UNIVERSAL ||
-	    hdr.tag != ASN1_TAG_ENUMERATED ||
-	    hdr.length != 1) {
-		wpa_printf(MSG_DEBUG,
-			   "OCSP: Expected ENUMERATED (responseStatus) - found class %d tag 0x%x length %u",
-			   hdr.class, hdr.tag, hdr.length);
+	    !asn1_is_enumerated(&hdr) || hdr.length != 1) {
+		asn1_unexpected(&hdr,
+				"OCSP: Expected ENUMERATED (responseStatus)");
 		return TLS_OCSP_INVALID;
 	}
 	resp_status = hdr.payload[0];
@@ -730,12 +693,10 @@ enum tls_ocsp_result tls_process_ocsp_response(struct tlsv1_client *conn,
 	if (pos == end)
 		return TLS_OCSP_NO_RESPONSE;
 
-	if (asn1_get_next(pos, end - pos, &hdr) < 0 ||
-	    hdr.class != ASN1_CLASS_CONTEXT_SPECIFIC ||
-	    hdr.tag != 0) {
-		wpa_printf(MSG_DEBUG,
-			   "OCSP: Expected [0] EXPLICIT (responseBytes) - found class %d tag 0x%x",
-			   hdr.class, hdr.tag);
+	if (asn1_get_next(pos, end - pos, &hdr) < 0 || !hdr.constructed ||
+	    !asn1_is_cs_tag(&hdr, 0)) {
+		asn1_unexpected(&hdr,
+				"OCSP: Expected [0] EXPLICIT (responseBytes)");
 		return TLS_OCSP_INVALID;
 	}
 
@@ -746,11 +707,9 @@ enum tls_ocsp_result tls_process_ocsp_response(struct tlsv1_client *conn,
 	 */
 
 	if (asn1_get_next(hdr.payload, hdr.length, &hdr) < 0 ||
-	    hdr.class != ASN1_CLASS_UNIVERSAL ||
-	    hdr.tag != ASN1_TAG_SEQUENCE) {
-		wpa_printf(MSG_DEBUG,
-			   "OCSP: Expected SEQUENCE (ResponseBytes) - found class %d tag 0x%x",
-			   hdr.class, hdr.tag);
+	    !asn1_is_sequence(&hdr)) {
+		asn1_unexpected(&hdr,
+				"OCSP: Expected SEQUENCE (ResponseBytes)");
 		return TLS_OCSP_INVALID;
 	}
 	pos = hdr.payload;
@@ -771,11 +730,8 @@ enum tls_ocsp_result tls_process_ocsp_response(struct tlsv1_client *conn,
 
 	/* response       OCTET STRING */
 	if (asn1_get_next(pos, end - pos, &hdr) < 0 ||
-	    hdr.class != ASN1_CLASS_UNIVERSAL ||
-	    hdr.tag != ASN1_TAG_OCTETSTRING) {
-		wpa_printf(MSG_DEBUG,
-			   "OCSP: Expected OCTET STRING (response) - found class %d tag 0x%x",
-			   hdr.class, hdr.tag);
+	    !asn1_is_octetstring(&hdr)) {
+		asn1_unexpected(&hdr, "OCSP: Expected OCTET STRING (response)");
 		return TLS_OCSP_INVALID;
 	}
 
diff --git a/src/tls/tlsv1_cred.c b/src/tls/tlsv1_cred.c
index 01b2f8342..1310f4e10 100644
--- a/src/tls/tlsv1_cred.c
+++ b/src/tls/tlsv1_cred.c
@@ -455,12 +455,8 @@ static int pkcs12_certbag(struct tlsv1_credentials *cred,
 	 * }
 	 */
 
-	if (asn1_get_next(buf, len, &hdr) < 0 ||
-	    hdr.class != ASN1_CLASS_UNIVERSAL ||
-	    hdr.tag != ASN1_TAG_SEQUENCE) {
-		wpa_printf(MSG_DEBUG,
-			   "PKCS #12: Expected SEQUENCE (CertBag) - found class %d tag 0x%x",
-			   hdr.class, hdr.tag);
+	if (asn1_get_next(buf, len, &hdr) < 0 || !asn1_is_sequence(&hdr)) {
+		asn1_unexpected(&hdr, "PKCS #12: Expected SEQUENCE (CertBag)");
 		return -1;
 	}
 
@@ -482,21 +478,17 @@ static int pkcs12_certbag(struct tlsv1_credentials *cred,
 			   obuf);
 	}
 
-	if (asn1_get_next(pos, end - pos, &hdr) < 0 ||
-	    hdr.class != ASN1_CLASS_CONTEXT_SPECIFIC ||
-	    hdr.tag != 0) {
-		wpa_printf(MSG_DEBUG,
-			   "PKCS #12: Expected [0] EXPLICIT (certValue) - found class %d tag 0x%x",
-			   hdr.class, hdr.tag);
+	if (asn1_get_next(pos, end - pos, &hdr) < 0 || !hdr.constructed ||
+	    !asn1_is_cs_tag(&hdr, 0)) {
+		asn1_unexpected(&hdr,
+				"PKCS #12: Expected [0] EXPLICIT (certValue)");
 		return -1;
 	}
 
 	if (asn1_get_next(hdr.payload, hdr.length, &hdr) < 0 ||
-	    hdr.class != ASN1_CLASS_UNIVERSAL ||
-	    hdr.tag != ASN1_TAG_OCTETSTRING) {
-		wpa_printf(MSG_DEBUG,
-			   "PKCS #12: Expected OCTET STRING (x509Certificate) - found class %d tag 0x%x",
-			   hdr.class, hdr.tag);
+	    !asn1_is_octetstring(&hdr)) {
+		asn1_unexpected(&hdr,
+				"PKCS #12: Expected OCTET STRING (x509Certificate)");
 		return -1;
 	}
 
@@ -534,11 +526,9 @@ static int pkcs12_parse_attr_friendly_name(const u8 *pos, const u8 *end)
 	 * }
 	 */
 	if (asn1_get_next(pos, end - pos, &hdr) < 0 ||
-	    hdr.class != ASN1_CLASS_UNIVERSAL ||
-	    hdr.tag != ASN1_TAG_BMPSTRING) {
-		wpa_printf(MSG_DEBUG,
-			   "PKCS #12: Expected BMPSTRING (friendlyName) - found class %d tag 0x%x",
-			   hdr.class, hdr.tag);
+	    !asn1_is_bmpstring(&hdr)) {
+		asn1_unexpected(&hdr,
+				"PKCS #12: Expected BMPSTRING (friendlyName)");
 		return 0;
 	}
 	wpa_hexdump_ascii(MSG_DEBUG, "PKCS #12: friendlyName",
@@ -561,11 +551,9 @@ static int pkcs12_parse_attr_local_key_id(const u8 *pos, const u8 *end)
 	 * }
 	 */
 	if (asn1_get_next(pos, end - pos, &hdr) < 0 ||
-	    hdr.class != ASN1_CLASS_UNIVERSAL ||
-	    hdr.tag != ASN1_TAG_OCTETSTRING) {
-		wpa_printf(MSG_DEBUG,
-			   "PKCS #12: Expected OCTET STRING (localKeyID) - found class %d tag 0x%x",
-			   hdr.class, hdr.tag);
+	    !asn1_is_octetstring(&hdr)) {
+		asn1_unexpected(&hdr,
+				"PKCS #12: Expected OCTET STRING (localKeyID)");
 		return -1;
 	}
 	wpa_hexdump_key(MSG_DEBUG, "PKCS #12: localKeyID",
@@ -596,12 +584,8 @@ static int pkcs12_parse_attr(const u8 *pos, size_t len)
 	asn1_oid_to_str(&a_oid, obuf, sizeof(obuf));
 	wpa_printf(MSG_DEBUG, "PKCS #12: attrId %s", obuf);
 
-	if (asn1_get_next(pos, end - pos, &hdr) < 0 ||
-	    hdr.class != ASN1_CLASS_UNIVERSAL ||
-	    hdr.tag != ASN1_TAG_SET) {
-		wpa_printf(MSG_DEBUG,
-			   "PKCS #12: Expected SET (attrValues) - found class %d tag 0x%x",
-			   hdr.class, hdr.tag);
+	if (asn1_get_next(pos, end - pos, &hdr) < 0 || !asn1_is_set(&hdr)) {
+		asn1_unexpected(&hdr, "PKCS #12: Expected SET (attrValues)");
 		return -1;
 	}
 	wpa_hexdump_key(MSG_MSGDUMP, "PKCS #12: attrValues",
@@ -641,12 +625,10 @@ static int pkcs12_safebag(struct tlsv1_credentials *cred,
 	asn1_oid_to_str(&oid, obuf, sizeof(obuf));
 	wpa_printf(MSG_DEBUG, "PKCS #12: BAG-TYPE %s", obuf);
 
-	if (asn1_get_next(pos, end - pos, &hdr) < 0 ||
-	    hdr.class != ASN1_CLASS_CONTEXT_SPECIFIC ||
-	    hdr.tag != 0) {
-		wpa_printf(MSG_DEBUG,
-			   "PKCS #12: Expected [0] EXPLICIT (bagValue) - found class %d tag 0x%x",
-			   hdr.class, hdr.tag);
+	if (asn1_get_next(pos, end - pos, &hdr) < 0 || !hdr.constructed ||
+	    !asn1_is_cs_tag(&hdr, 0)) {
+		asn1_unexpected(&hdr,
+				"PKCS #12: Expected [0] EXPLICIT (bagValue)");
 		return 0;
 	}
 	value = hdr.payload;
@@ -657,11 +639,9 @@ static int pkcs12_safebag(struct tlsv1_credentials *cred,
 	if (pos < end) {
 		/* bagAttributes  SET OF PKCS12Attribute OPTIONAL */
 		if (asn1_get_next(pos, end - pos, &hdr) < 0 ||
-		    hdr.class != ASN1_CLASS_UNIVERSAL ||
-		    hdr.tag != ASN1_TAG_SET) {
-			wpa_printf(MSG_DEBUG,
-				   "PKCS #12: Expected SET (bagAttributes) - found class %d tag 0x%x",
-				   hdr.class, hdr.tag);
+		    !asn1_is_set(&hdr)) {
+			asn1_unexpected(&hdr,
+					"PKCS #12: Expected SET (bagAttributes)");
 			return -1;
 		}
 		wpa_hexdump_key(MSG_MSGDUMP, "PKCS #12: bagAttributes",
@@ -672,11 +652,9 @@ static int pkcs12_safebag(struct tlsv1_credentials *cred,
 		while (pos < end) {
 			/* PKCS12Attribute ::= SEQUENCE */
 			if (asn1_get_next(pos, end - pos, &hdr) < 0 ||
-			    hdr.class != ASN1_CLASS_UNIVERSAL ||
-			    hdr.tag != ASN1_TAG_SEQUENCE) {
-				wpa_printf(MSG_DEBUG,
-					   "PKCS #12: Expected SEQUENCE (PKCS12Attribute) - found class %d tag 0x%x",
-					   hdr.class, hdr.tag);
+			    !asn1_is_sequence(&hdr)) {
+				asn1_unexpected(&hdr,
+						"PKCS #12: Expected SEQUENCE (PKCS12Attribute)");
 				return -1;
 			}
 			if (pkcs12_parse_attr(hdr.payload, hdr.length) < 0)
@@ -705,12 +683,9 @@ static int pkcs12_safecontents(struct tlsv1_credentials *cred,
 	const u8 *pos, *end;
 
 	/* SafeContents ::= SEQUENCE OF SafeBag */
-	if (asn1_get_next(buf, len, &hdr) < 0 ||
-	    hdr.class != ASN1_CLASS_UNIVERSAL ||
-	    hdr.tag != ASN1_TAG_SEQUENCE) {
-		wpa_printf(MSG_DEBUG,
-			   "PKCS #12: Expected SEQUENCE (SafeContents) - found class %d tag 0x%x",
-			   hdr.class, hdr.tag);
+	if (asn1_get_next(buf, len, &hdr) < 0 || !asn1_is_sequence(&hdr)) {
+		asn1_unexpected(&hdr,
+				"PKCS #12: Expected SEQUENCE (SafeContents)");
 		return -1;
 	}
 	pos = hdr.payload;
@@ -726,11 +701,9 @@ static int pkcs12_safecontents(struct tlsv1_credentials *cred,
 
 	while (pos < end) {
 		if (asn1_get_next(pos, end - pos, &hdr) < 0 ||
-		    hdr.class != ASN1_CLASS_UNIVERSAL ||
-		    hdr.tag != ASN1_TAG_SEQUENCE) {
-			wpa_printf(MSG_DEBUG,
-				   "PKCS #12: Expected SEQUENCE (SafeBag) - found class %d tag 0x%x",
-				   hdr.class, hdr.tag);
+		    !asn1_is_sequence(&hdr)) {
+			asn1_unexpected(&hdr,
+					"PKCS #12: Expected SEQUENCE (SafeBag)");
 			return -1;
 		}
 		if (pkcs12_safebag(cred, hdr.payload, hdr.length, passwd) < 0)
@@ -750,11 +723,8 @@ static int pkcs12_parse_content_data(struct tlsv1_credentials *cred,
 
 	/* Data ::= OCTET STRING */
 	if (asn1_get_next(pos, end - pos, &hdr) < 0 ||
-	    hdr.class != ASN1_CLASS_UNIVERSAL ||
-	    hdr.tag != ASN1_TAG_OCTETSTRING) {
-		wpa_printf(MSG_DEBUG,
-			   "PKCS #12: Expected OCTET STRING (Data) - found class %d tag 0x%x",
-			   hdr.class, hdr.tag);
+	    !asn1_is_octetstring(&hdr)) {
+		asn1_unexpected(&hdr, "PKCS #12: Expected OCTET STRING (Data)");
 		return -1;
 	}
 
@@ -782,21 +752,17 @@ static int pkcs12_parse_content_enc_data(struct tlsv1_credentials *cred,
 	 *   encryptedContentInfo EncryptedContentInfo }
 	 */
 	if (asn1_get_next(pos, end - pos, &hdr) < 0 ||
-	    hdr.class != ASN1_CLASS_UNIVERSAL ||
-	    hdr.tag != ASN1_TAG_SEQUENCE) {
-		wpa_printf(MSG_DEBUG,
-			   "PKCS #12: Expected SEQUENCE (EncryptedData) - found class %d tag 0x%x",
-			   hdr.class, hdr.tag);
+	    !asn1_is_sequence(&hdr)) {
+		asn1_unexpected(&hdr,
+				"PKCS #12: Expected SEQUENCE (EncryptedData)");
 		return 0;
 	}
 	pos = hdr.payload;
 
 	/* Version ::= INTEGER */
-	if (asn1_get_next(pos, end - pos, &hdr) < 0 ||
-	    hdr.class != ASN1_CLASS_UNIVERSAL || hdr.tag != ASN1_TAG_INTEGER) {
-		wpa_printf(MSG_DEBUG,
-			   "PKCS #12: No INTEGER tag found for version; class=%d tag=0x%x",
-			   hdr.class, hdr.tag);
+	if (asn1_get_next(pos, end - pos, &hdr) < 0 || !asn1_is_integer(&hdr)) {
+		asn1_unexpected(&hdr,
+				"PKCS #12: No INTEGER tag found for version");
 		return -1;
 	}
 	if (hdr.length != 1 || hdr.payload[0] != 0) {
@@ -815,11 +781,9 @@ static int pkcs12_parse_content_enc_data(struct tlsv1_credentials *cred,
 	 *   encryptedContent [0] IMPLICIT EncryptedContent OPTIONAL }
 	 */
 	if (asn1_get_next(pos, end - pos, &hdr) < 0 ||
-	    hdr.class != ASN1_CLASS_UNIVERSAL ||
-	    hdr.tag != ASN1_TAG_SEQUENCE) {
-		wpa_printf(MSG_DEBUG,
-			   "PKCS #12: Expected SEQUENCE (EncryptedContentInfo) - found class %d tag 0x%x",
-			   hdr.class, hdr.tag);
+	    !asn1_is_sequence(&hdr)) {
+		asn1_unexpected(&hdr,
+				"PKCS #12: Expected SEQUENCE (EncryptedContentInfo)");
 		return -1;
 	}
 
@@ -845,22 +809,19 @@ static int pkcs12_parse_content_enc_data(struct tlsv1_credentials *cred,
 
 	/* ContentEncryptionAlgorithmIdentifier ::= AlgorithmIdentifier */
 	if (asn1_get_next(pos, end - pos, &hdr) < 0 ||
-	    hdr.class != ASN1_CLASS_UNIVERSAL ||
-	    hdr.tag != ASN1_TAG_SEQUENCE) {
-		wpa_printf(MSG_DEBUG, "PKCS #12: Expected SEQUENCE (ContentEncryptionAlgorithmIdentifier) - found class %d tag 0x%x",
-			   hdr.class, hdr.tag);
+	    !asn1_is_sequence(&hdr)) {
+		asn1_unexpected(&hdr,
+				"PKCS #12: Expected SEQUENCE (ContentEncryptionAlgorithmIdentifier)");
 		return -1;
 	}
 	enc_alg = hdr.payload;
 	enc_alg_len = hdr.length;
 	pos = hdr.payload + hdr.length;
 
-	if (asn1_get_next(pos, end - pos, &hdr) < 0 ||
-	    hdr.class != ASN1_CLASS_CONTEXT_SPECIFIC ||
-	    hdr.tag != 0) {
-		wpa_printf(MSG_DEBUG,
-			   "PKCS #12: Expected [0] IMPLICIT (encryptedContent) - found class %d tag 0x%x",
-			   hdr.class, hdr.tag);
+	if (asn1_get_next(pos, end - pos, &hdr) < 0 || hdr.constructed ||
+	    !asn1_is_cs_tag(&hdr, 0)) {
+		asn1_unexpected(&hdr,
+				"PKCS #12: Expected [0] IMPLICIT (encryptedContent)");
 		return -1;
 	}
 
@@ -900,12 +861,10 @@ static int pkcs12_parse_content(struct tlsv1_credentials *cred,
 	asn1_oid_to_str(&oid, txt, sizeof(txt));
 	wpa_printf(MSG_DEBUG, "PKCS #12: contentType %s", txt);
 
-	if (asn1_get_next(pos, end - pos, &hdr) < 0 ||
-	    hdr.class != ASN1_CLASS_CONTEXT_SPECIFIC ||
-	    hdr.tag != 0) {
-		wpa_printf(MSG_DEBUG,
-			   "PKCS #12: Expected [0] EXPLICIT (content) - found class %d tag 0x%x",
-			   hdr.class, hdr.tag);
+	if (asn1_get_next(pos, end - pos, &hdr) < 0 || !hdr.constructed ||
+	    !asn1_is_cs_tag(&hdr, 0)) {
+		asn1_unexpected(&hdr,
+				"PKCS #12: Expected [0] EXPLICIT (content)");
 		return 0;
 	}
 	pos = hdr.payload;
@@ -938,23 +897,18 @@ static int pkcs12_parse(struct tlsv1_credentials *cred,
 	 * }
 	 */
 
-	if (asn1_get_next(key, len, &hdr) < 0 ||
-	    hdr.class != ASN1_CLASS_UNIVERSAL ||
-	    hdr.tag != ASN1_TAG_SEQUENCE) {
-		wpa_printf(MSG_DEBUG,
-			   "PKCS #12: Expected SEQUENCE (PFX) - found class %d tag 0x%x; assume PKCS #12 not used",
-			   hdr.class, hdr.tag);
+	if (asn1_get_next(key, len, &hdr) < 0 || !asn1_is_sequence(&hdr)) {
+		asn1_unexpected(&hdr,
+				"PKCS #12: Expected SEQUENCE (PFX); assume PKCS #12 not used");
 		return -1;
 	}
 
 	pos = hdr.payload;
 	end = pos + hdr.length;
 
-	if (asn1_get_next(pos, end - pos, &hdr) < 0 ||
-	    hdr.class != ASN1_CLASS_UNIVERSAL || hdr.tag != ASN1_TAG_INTEGER) {
-		wpa_printf(MSG_DEBUG,
-			   "PKCS #12: No INTEGER tag found for version; class=%d tag=0x%x",
-			   hdr.class, hdr.tag);
+	if (asn1_get_next(pos, end - pos, &hdr) < 0 || !asn1_is_integer(&hdr)) {
+		asn1_unexpected(&hdr,
+				"PKCS #12: No INTEGER tag found for version");
 		return -1;
 	}
 	if (hdr.length != 1 || hdr.payload[0] != 3) {
@@ -970,11 +924,9 @@ static int pkcs12_parse(struct tlsv1_credentials *cred,
 	 */
 
 	if (asn1_get_next(pos, end - pos, &hdr) < 0 ||
-	    hdr.class != ASN1_CLASS_UNIVERSAL ||
-	    hdr.tag != ASN1_TAG_SEQUENCE) {
-		wpa_printf(MSG_DEBUG,
-			   "PKCS #12: Expected SEQUENCE (authSafe) - found class %d tag 0x%x; assume PKCS #12 not used",
-			   hdr.class, hdr.tag);
+	    !asn1_is_sequence(&hdr)) {
+		asn1_unexpected(&hdr,
+				"PKCS #12: Expected SEQUENCE (authSafe); assume PKCS #12 not used");
 		return -1;
 	}
 
@@ -995,12 +947,10 @@ static int pkcs12_parse(struct tlsv1_credentials *cred,
 		return -1;
 	}
 
-	if (asn1_get_next(pos, end - pos, &hdr) < 0 ||
-	    hdr.class != ASN1_CLASS_CONTEXT_SPECIFIC ||
-	    hdr.tag != 0) {
-		wpa_printf(MSG_DEBUG,
-			   "PKCS #12: Expected [0] EXPLICIT (content) - found class %d tag 0x%x; assume PKCS #12 not used",
-			   hdr.class, hdr.tag);
+	if (asn1_get_next(pos, end - pos, &hdr) < 0 || !hdr.constructed ||
+	    !asn1_is_cs_tag(&hdr, 0)) {
+		asn1_unexpected(&hdr,
+				"PKCS #12: Expected [0] EXPLICIT (content); assume PKCS #12 not used");
 		return -1;
 	}
 
@@ -1008,11 +958,9 @@ static int pkcs12_parse(struct tlsv1_credentials *cred,
 
 	/* Data ::= OCTET STRING */
 	if (asn1_get_next(pos, end - pos, &hdr) < 0 ||
-	    hdr.class != ASN1_CLASS_UNIVERSAL ||
-	    hdr.tag != ASN1_TAG_OCTETSTRING) {
-		wpa_printf(MSG_DEBUG,
-			   "PKCS #12: Expected OCTET STRING (Data) - found class %d tag 0x%x; assume PKCS #12 not used",
-			   hdr.class, hdr.tag);
+	    !asn1_is_octetstring(&hdr)) {
+		asn1_unexpected(&hdr,
+				"PKCS #12: Expected OCTET STRING (Data); assume PKCS #12 not used");
 		return -1;
 	}
 
@@ -1026,11 +974,9 @@ static int pkcs12_parse(struct tlsv1_credentials *cred,
 		    hdr.payload, hdr.length);
 
 	if (asn1_get_next(hdr.payload, hdr.length, &hdr) < 0 ||
-	    hdr.class != ASN1_CLASS_UNIVERSAL ||
-	    hdr.tag != ASN1_TAG_SEQUENCE) {
-		wpa_printf(MSG_DEBUG,
-			   "PKCS #12: Expected SEQUENCE within Data content - found class %d tag 0x%x; assume PKCS #12 not used",
-			   hdr.class, hdr.tag);
+	    !asn1_is_sequence(&hdr)) {
+		asn1_unexpected(&hdr,
+				"PKCS #12: Expected SEQUENCE within Data content; assume PKCS #12 not used");
 		return -1;
 	}
 
@@ -1039,11 +985,9 @@ static int pkcs12_parse(struct tlsv1_credentials *cred,
 
 	while (end > pos) {
 		if (asn1_get_next(pos, end - pos, &hdr) < 0 ||
-		    hdr.class != ASN1_CLASS_UNIVERSAL ||
-		    hdr.tag != ASN1_TAG_SEQUENCE) {
-			wpa_printf(MSG_DEBUG,
-				   "PKCS #12: Expected SEQUENCE (ContentInfo) - found class %d tag 0x%x; assume PKCS #12 not used",
-				   hdr.class, hdr.tag);
+		    !asn1_is_sequence(&hdr)) {
+			asn1_unexpected(&hdr,
+					"PKCS #12: Expected SEQUENCE (ContentInfo); assume PKCS #12 not used");
 			return -1;
 		}
 		if (pkcs12_parse_content(cred, hdr.payload, hdr.length,
@@ -1141,24 +1085,17 @@ static int tlsv1_set_dhparams_der(struct tlsv1_credentials *cred,
 	 */
 
 	/* DHParamer ::= SEQUENCE */
-	if (asn1_get_next(pos, len, &hdr) < 0 ||
-	    hdr.class != ASN1_CLASS_UNIVERSAL ||
-	    hdr.tag != ASN1_TAG_SEQUENCE) {
-		wpa_printf(MSG_DEBUG, "DH: DH parameters did not start with a "
-			   "valid SEQUENCE - found class %d tag 0x%x",
-			   hdr.class, hdr.tag);
+	if (asn1_get_next(pos, len, &hdr) < 0 || !asn1_is_sequence(&hdr)) {
+		asn1_unexpected(&hdr,
+				"DH: DH parameters did not start with a valid SEQUENCE");
 		return -1;
 	}
 	pos = hdr.payload;
 
 	/* prime INTEGER */
-	if (asn1_get_next(pos, end - pos, &hdr) < 0)
-		return -1;
-
-	if (hdr.class != ASN1_CLASS_UNIVERSAL ||
-	    hdr.tag != ASN1_TAG_INTEGER) {
-		wpa_printf(MSG_DEBUG, "DH: No INTEGER tag found for p; "
-			   "class=%d tag=0x%x", hdr.class, hdr.tag);
+	if (asn1_get_next(pos, end - pos, &hdr) < 0 ||
+	    !asn1_is_integer(&hdr)) {
+		asn1_unexpected(&hdr, "DH: No INTEGER tag found for p");
 		return -1;
 	}
 
@@ -1173,13 +1110,9 @@ static int tlsv1_set_dhparams_der(struct tlsv1_credentials *cred,
 	pos = hdr.payload + hdr.length;
 
 	/* base INTEGER */
-	if (asn1_get_next(pos, end - pos, &hdr) < 0)
-		return -1;
-
-	if (hdr.class != ASN1_CLASS_UNIVERSAL ||
-	    hdr.tag != ASN1_TAG_INTEGER) {
-		wpa_printf(MSG_DEBUG, "DH: No INTEGER tag found for g; "
-			   "class=%d tag=0x%x", hdr.class, hdr.tag);
+	if (asn1_get_next(pos, end - pos, &hdr) < 0 ||
+	    !asn1_is_integer(&hdr)) {
+		asn1_unexpected(&hdr, "DH: No INTEGER tag found for g");
 		return -1;
 	}