Commit f9cd483cd9 for strongswan.org
commit f9cd483cd97182def563e17b86e4fbd3a90c03d2
Author: raghu netrakar <raghu@security.bugqore.com>
Date: Thu Oct 15 21:06:45 2026 +0530
simaka: Reject AT_MAC, AT_IV and AT_ENCR_DATA inside encrypted attributes
parse_attributes() rejects attributes that must be encrypted when they
appear in the clear, but there was no symmetric check for attributes that
must never be encrypted. AT_MAC, AT_IV and AT_ENCR_DATA are stored by
reference (this->mac/iv/encr point into the buffer being parsed). When
one of them is placed inside AT_ENCR_DATA, decrypt() parses it out of the
temporary plaintext buffer and then frees that buffer, leaving the pointer
dangling. For AT_MAC this is then used in verify(), which reads 16 bytes
from the freed buffer and zeroes it, a heap use-after-free.
Add is_unencrypted_attribute() as the counterpart to
is_encrypted_attribute() and reject these attributes when encountered
inside encrypted data. In addition to the attributes mentioned,
AT_RESULT_IND is also rejected because the RFCs explicitly state that
it MUST NOT be sent encrypted.
Closes strongswan/strongswan#3179
Fixes: f81760dcd1ba ("A SIM/AKA message can be parsed twice, without and with decryption")
diff --git a/src/libsimaka/simaka_message.c b/src/libsimaka/simaka_message.c
index 97f0954f7a..fb38104705 100644
--- a/src/libsimaka/simaka_message.c
+++ b/src/libsimaka/simaka_message.c
@@ -280,6 +280,23 @@ static bool is_encrypted_attribute(simaka_attribute_t type)
}
}
+/**
+ * Determine if an attribute is never sent encrypted
+ */
+static bool is_unencrypted_attribute(simaka_attribute_t type)
+{
+ switch (type)
+ {
+ case AT_MAC:
+ case AT_IV:
+ case AT_ENCR_DATA:
+ case AT_RESULT_IND:
+ return TRUE;
+ default:
+ return FALSE;
+ }
+}
+
/**
* Error handling for invalid length
*/
@@ -329,7 +346,16 @@ static bool parse_attributes(private_simaka_message_t *this, chunk_t in)
}
hdr = (attr_hdr_t*)in.ptr;
- if (is_encrypted_attribute(hdr->type) && !this->encrypted)
+ if (this->encrypted)
+ {
+ if (is_unencrypted_attribute(hdr->type))
+ {
+ DBG1(DBG_LIB, "received encrypted %N", simaka_attribute_names,
+ hdr->type);
+ return FALSE;
+ }
+ }
+ else if (is_encrypted_attribute(hdr->type))
{
DBG1(DBG_LIB, "received unencrypted %N", simaka_attribute_names,
hdr->type);