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))