Commit 52b689c4f8 for strongswan.org
commit 52b689c4f84e52cab842aad70e71118239b06ce1
Author: Tobias Brunner <tobias@strongswan.org>
Date: Mon Jul 20 12:05:31 2026 +0200
pem: Avoid integer underflow when verifying padding after decryption
If the padding was larger than the whole blob, all available bytes were
checked for a match and the blob's length was eventually adjusted and
SUCCESS returned. Due to the underflow this could result in a huge size
that would then get copied. Zero-length padding was also incorrectly
accepted as was padding larger than the block size.
Fixes: 160f4c225db0 ("moved PEM parsing functionality to its own plugin")
diff --git a/src/libstrongswan/plugins/pem/pem_builder.c b/src/libstrongswan/plugins/pem/pem_builder.c
index 2a7cdb55d3..217849e89f 100644
--- a/src/libstrongswan/plugins/pem/pem_builder.c
+++ b/src/libstrongswan/plugins/pem/pem_builder.c
@@ -95,6 +95,7 @@ static status_t pem_decrypt(chunk_t *blob, encryption_algorithm_t alg,
chunk_t decrypted;
chunk_t key = {alloca(key_size), key_size};
uint8_t padding, *last_padding_pos, *first_padding_pos;
+ size_t block_size;
if (!key_size)
{
@@ -141,8 +142,8 @@ static status_t pem_decrypt(chunk_t *blob, encryption_algorithm_t alg,
return NOT_SUPPORTED;
}
- if (iv.len != crypter->get_iv_size(crypter) ||
- blob->len % crypter->get_block_size(crypter))
+ block_size = crypter->get_block_size(crypter);
+ if (iv.len != crypter->get_iv_size(crypter) || blob->len % block_size)
{
DBG1(DBG_ASN, " data size is not multiple of block size");
crypter->destroy(crypter);
@@ -164,14 +165,12 @@ static status_t pem_decrypt(chunk_t *blob, encryption_algorithm_t alg,
/* determine amount of padding */
last_padding_pos = blob->ptr + blob->len - 1;
padding = *last_padding_pos;
- if (padding > blob->len)
+ if (!padding || padding > block_size)
{
- first_padding_pos = blob->ptr;
- }
- else
- {
- first_padding_pos = last_padding_pos - padding;
+ DBG1(DBG_ASN, " invalid passphrase");
+ return INVALID_ARG;
}
+ first_padding_pos = last_padding_pos - padding;
/* check the padding pattern */
while (--last_padding_pos > first_padding_pos)
{