From 40f40973c01bf0c99930d3adf73c59272fb528ef Mon Sep 17 00:00:00 2001 From: Tobias Brunner Date: Sun, 12 Jul 2026 17:53:10 +0200 Subject: [PATCH] pem: Properly handle encrypted PEM files without DEK-Info Since `key_size` remained zero, this caused a buffer overflow when the derived key in `pem_decrypt()` was copied to the zero-length local buffer. Also fixed two potential memory leaks if hashing fails and make sure the decryption key is wiped. Fixes: 160f4c225db0 ("moved PEM parsing functionality to its own plugin") --- src/libstrongswan/plugins/pem/pem_builder.c | 18 +++++++++++++++++- 1 file changed, 17 insertions(+), 1 deletion(-) diff --git a/src/libstrongswan/plugins/pem/pem_builder.c b/src/libstrongswan/plugins/pem/pem_builder.c index 09eaa9215..2a7cdb55d 100644 --- a/src/libstrongswan/plugins/pem/pem_builder.c +++ b/src/libstrongswan/plugins/pem/pem_builder.c @@ -96,6 +96,11 @@ static status_t pem_decrypt(chunk_t *blob, encryption_algorithm_t alg, chunk_t key = {alloca(key_size), key_size}; uint8_t padding, *last_padding_pos, *first_padding_pos; + if (!key_size) + { + return FAILED; + } + /* build key from passphrase and IV */ hasher = lib->crypto->create_hasher(lib->crypto, HASH_MD5); if (hasher == NULL) @@ -108,6 +113,7 @@ static status_t pem_decrypt(chunk_t *blob, encryption_algorithm_t alg, if (!hasher->get_hash(hasher, passphrase, NULL) || !hasher->get_hash(hasher, salt, hash.ptr)) { + hasher->destroy(hasher); return FAILED; } memcpy(key.ptr, hash.ptr, hash.len); @@ -118,6 +124,7 @@ static status_t pem_decrypt(chunk_t *blob, encryption_algorithm_t alg, !hasher->get_hash(hasher, passphrase, NULL) || !hasher->get_hash(hasher, salt, hash.ptr)) { + hasher->destroy(hasher); return FAILED; } memcpy(key.ptr + hash.len, hash.ptr, key.len - hash.len); @@ -130,25 +137,29 @@ static status_t pem_decrypt(chunk_t *blob, encryption_algorithm_t alg, { DBG1(DBG_ASN, " %N encryption algorithm not available", encryption_algorithm_names, alg); + memwipe(key.ptr, key.len); return NOT_SUPPORTED; } if (iv.len != crypter->get_iv_size(crypter) || blob->len % crypter->get_block_size(crypter)) { - crypter->destroy(crypter); DBG1(DBG_ASN, " data size is not multiple of block size"); + crypter->destroy(crypter); + memwipe(key.ptr, key.len); return PARSE_ERROR; } if (!crypter->set_key(crypter, key) || !crypter->decrypt(crypter, *blob, iv, &decrypted)) { crypter->destroy(crypter); + memwipe(key.ptr, key.len); return FAILED; } crypter->destroy(crypter); memcpy(blob->ptr, decrypted.ptr, blob->len); chunk_clear(&decrypted); + memwipe(key.ptr, key.len); /* determine amount of padding */ last_padding_pos = blob->ptr + blob->len - 1; @@ -340,6 +351,11 @@ static status_t pem_to_bin(chunk_t *blob, bool *pgp) { return SUCCESS; } + if (alg == ENCR_UNDEFINED || !key_size) + { + DBG1(DBG_ASN, " encrypted PEM file has no valid DEK-Info"); + return PARSE_ERROR; + } enumerator = lib->credmgr->create_shared_enumerator(lib->credmgr, SHARED_PRIVATE_KEY_PASS, NULL, NULL);