[wpa_supplicant] Read certificates from keystore in DER format

Read Root CA and user certificates from keystore in DER format.
Only if it fails, try to use PEM format for backward
compatibility.

Bug: 184298873
Test: Connect to Wi-Fi networks with EAP-TLS and EAP-TTLS and
verify logs.

Change-Id: I599e55485a89b2d18e29df0f347cfe4c1d9dba15
diff --git a/src/crypto/tls_openssl.c b/src/crypto/tls_openssl.c
index 928cc97..013ea30 100644
--- a/src/crypto/tls_openssl.c
+++ b/src/crypto/tls_openssl.c
@@ -163,12 +163,33 @@
 	BIO *bio = BIO_from_keystore(key_alias);
 	STACK_OF(X509_INFO) *stack = NULL;
 	stack_index_t i;
+	int ret = 0;
 
-	if (bio) {
-		stack = PEM_X509_INFO_read_bio(bio, NULL, NULL, NULL);
-		BIO_free(bio);
+	if (!bio) {
+		wpa_printf(MSG_ERROR, "TLS: Failed to parse certificate: %s",
+			   key_alias);
+		return -1;
 	}
 
+	// Try DER encoding first
+	X509 *x509 = d2i_X509_bio(bio, NULL);
+	if (x509) {
+		while (x509) {
+			if (!X509_STORE_add_cert(ctx, x509)) {
+				wpa_printf(MSG_ERROR, "TLS: Failed to add Root CA certificate");
+				ret = -1;
+				break;
+			}
+			x509 = d2i_X509_bio(bio, NULL);
+		}
+		BIO_free(bio);
+		return ret;
+	}
+
+	// Try PEM encoding
+	stack = PEM_X509_INFO_read_bio(bio, NULL, NULL, NULL);
+	BIO_free(bio);
+
 	if (!stack) {
 		wpa_printf(MSG_WARNING, "TLS: Failed to parse certificate: %s",
 			   key_alias);
@@ -179,14 +200,17 @@
 		X509_INFO *info = sk_X509_INFO_value(stack, i);
 
 		if (info->x509)
-			X509_STORE_add_cert(ctx, info->x509);
+			if (!X509_STORE_add_cert(ctx, info->x509)) {
+				wpa_printf(MSG_ERROR, "TLS: Failed to add Root CA certificate");
+				ret = -1;
+				break;
+			}
 		if (info->crl)
 			X509_STORE_add_crl(ctx, info->crl);
 	}
 
 	sk_X509_INFO_pop_free(stack, X509_INFO_free);
-
-	return 0;
+	return ret;
 }
 
 
@@ -3321,7 +3345,16 @@
 		X509 *x509 = NULL;
 		int ret = -1;
 		if (bio) {
-			x509 = PEM_read_bio_X509(bio, NULL, NULL, NULL);
+			// Try DER encoding first
+			x509 = d2i_X509_bio(bio, NULL);
+			if (!x509) {
+				// Maybe this bio is actually PEM encoded.
+				x509 = PEM_read_bio_X509(bio, NULL, NULL, NULL);
+				if (!x509) {
+					wpa_printf(MSG_ERROR, "tls_connection_client_cert: "
+							"Unknown certificate encoding.");
+				}
+			}
 		}
 		if (x509) {
 			if (SSL_use_certificate(conn->ssl, x509) == 1)
@@ -5171,8 +5204,10 @@
 					     params->altsubject_match,
 					     params->suffix_match,
 					     params->domain_match,
-					     params->check_cert_subject))
+					     params->check_cert_subject)) {
+		wpa_printf(MSG_ERROR, "TLS: Failed to set subject match");
 		return -1;
+	}
 
 	if (engine_id && ca_cert_id) {
 		if (tls_connection_engine_ca_cert(data, conn, ca_cert_id))
@@ -5180,16 +5215,20 @@
 	} else if (tls_connection_ca_cert(data, conn, params->ca_cert,
 					  params->ca_cert_blob,
 					  params->ca_cert_blob_len,
-					  params->ca_path))
+					  params->ca_path)) {
+		wpa_printf(MSG_ERROR, "TLS: Failed to parse Root CA certificate");
 		return -1;
+	}
 
 	if (engine_id && cert_id) {
 		if (tls_connection_engine_client_cert(conn, cert_id))
 			return TLS_SET_PARAMS_ENGINE_PRV_VERIFY_FAILED;
 	} else if (tls_connection_client_cert(conn, params->client_cert,
 					      params->client_cert_blob,
-					      params->client_cert_blob_len))
+					      params->client_cert_blob_len)) {
+		wpa_printf(MSG_ERROR, "TLS: Failed to parse client certificate");
 		return -1;
+	}
 
 	if (engine_id && key_id) {
 		wpa_printf(MSG_DEBUG, "TLS: Using private key from engine");
@@ -5264,8 +5303,10 @@
 	}
 
 	if (tls_set_conn_flags(conn, params->flags,
-			       params->openssl_ciphers) < 0)
+			       params->openssl_ciphers) < 0) {
+		wpa_printf(MSG_ERROR, "TLS: Failed to set connection flags");
 		return -1;
+	}
 
 #ifdef OPENSSL_IS_BORINGSSL
 	if (params->flags & TLS_CONN_REQUEST_OCSP) {