Commit 37d1e13cd9 for strongswan.org

commit 37d1e13cd985d42884eb7cb46c4b22e1e7cebe8e
Author: Tobias Brunner <tobias@strongswan.org>
Date:   Fri Jul 31 10:07:52 2026 +0200

    pkcs7/pkcs12: Handle password-less PKCS#12 files differently

    This reverts bdd8f1435467 ("pkcs7: Add supported for unprotected PKCS#7
    encrypted-data").  The only use case for password-less PKCS#7 containers
    is PKCS#12 and because we verify the MAC first, we know exactly whether
    the password was empty or not.  So we store that password in a temporary
    local credential set so we don't have to guess what password to use for
    the decryption (also for the PKCS#8-encrypted private key).

    This rules out files that use two passwords (one for the MAC, one for the
    decryption).  While RFC 7292 explicitly allows that ("the privacy password
    and the integrity password may or may not be the same"), this seems like
    a rare edge case and `openssl pkcs12` explicitly discourages the use of
    the `-twopass` option ("most software always assumes these are the same
    so this option will render such PKCS#12 files unreadable").

    Similarly, the "no password" (vs. "empty password") distinction seems
    also like something that does not occur in practice (it does not seem to
    be possible to create such a file with `openssl pkcs12`).

diff --git a/src/libstrongswan/plugins/pkcs12/pkcs12_decode.c b/src/libstrongswan/plugins/pkcs12/pkcs12_decode.c
index a2cfcf9d9b..4147871c3f 100644
--- a/src/libstrongswan/plugins/pkcs12/pkcs12_decode.c
+++ b/src/libstrongswan/plugins/pkcs12/pkcs12_decode.c
@@ -349,7 +349,8 @@ static bool verify_mac_pw(signer_t *signer, hash_algorithm_t hash, chunk_t salt,
  * Verify the given MAC with available passwords.
  */
 static bool verify_mac(hash_algorithm_t hash, chunk_t salt,
-					   uint64_t iterations, chunk_t data, chunk_t mac)
+					   uint64_t iterations, chunk_t data, chunk_t mac,
+					   mem_cred_t *creds)
 {
 	enumerator_t *enumerator;
 	shared_key_t *shared;
@@ -363,10 +364,11 @@ static bool verify_mac(hash_algorithm_t hash, chunk_t salt,
 		return FALSE;
 	}

-	/* try without and with an empty password, which is not the same thing */
-	if (verify_mac_pw(signer, hash, salt, iterations, data, mac, chunk_empty) ||
-		verify_mac_pw(signer, hash, salt, iterations, data, mac, chunk_from_str("")))
+	if (verify_mac_pw(signer, hash, salt, iterations, data, mac, chunk_from_str("")))
 	{
+		shared = shared_key_create(SHARED_PRIVATE_KEY_PASS,
+								   chunk_clone(chunk_from_str("")));
+		creds->add_shared(creds, shared, NULL);
 		signer->destroy(signer);
 		return TRUE;
 	}
@@ -378,6 +380,7 @@ static bool verify_mac(hash_algorithm_t hash, chunk_t salt,
 		if (verify_mac_pw(signer, hash, salt, iterations, data, mac,
 						  shared->get_key(shared)))
 		{
+			creds->add_shared(creds, shared->get_ref(shared), NULL);
 			success = TRUE;
 			break;
 		}
@@ -470,6 +473,7 @@ static bool parse_PFX(private_pkcs12_t *this, chunk_t blob)
 			data = chunk_empty;
 	hash_algorithm_t hash = HASH_UNKNOWN;
 	container_t *container = NULL;
+	mem_cred_t *creds = NULL;
 	uint64_t iterations = 0;
 	bool success = FALSE;

@@ -526,11 +530,14 @@ end_parse:
 			{
 				goto end;
 			}
-			if (!verify_mac(hash, salt, iterations, data, digest))
+			creds = mem_cred_create();
+			if (!verify_mac(hash, salt, iterations, data, digest, creds))
 			{
 				DBG1(DBG_ASN, "  MAC verification of PKCS#12 container failed");
 				goto end;
 			}
+			/* only use the password that verified the MAC */
+			lib->credmgr->add_local_set(lib->credmgr, &creds->set, TRUE);
 		}
 		else
 		{
@@ -555,6 +562,11 @@ end_parse:
 	}
 end:
 	DBG2(DBG_ASN, "-- < --");
+	if (creds)
+	{
+		lib->credmgr->remove_local_set(lib->credmgr, &creds->set);
+		creds->destroy(creds);
+	}
 	DESTROY_IF(container);
 	chunk_free(&data);
 	return success;
diff --git a/src/libstrongswan/plugins/pkcs7/pkcs7_encrypted_data.c b/src/libstrongswan/plugins/pkcs7/pkcs7_encrypted_data.c
index cdcb0eb719..472e72e2a7 100644
--- a/src/libstrongswan/plugins/pkcs7/pkcs7_encrypted_data.c
+++ b/src/libstrongswan/plugins/pkcs7/pkcs7_encrypted_data.c
@@ -54,11 +54,6 @@ static bool decrypt(pkcs5_t *pkcs5, chunk_t data, chunk_t *decrypted)
 	shared_key_t *shared;
 	bool success = FALSE;

-	if (pkcs5->decrypt(pkcs5, chunk_empty, data, decrypted))
-	{
-		return TRUE;
-	}
-
 	enumerator = lib->credmgr->create_shared_enumerator(lib->credmgr,
 										SHARED_PRIVATE_KEY_PASS, NULL, NULL);
 	while (enumerator->enumerate(enumerator, &shared, NULL, NULL))