]> git.ipfire.org Git - thirdparty/strongswan.git/commitdiff
message: Add method to generate data to authenticate IKE_INTERMEDIATE exchanges
authorTobias Brunner <tobias@strongswan.org>
Tue, 20 Aug 2019 12:57:30 +0000 (14:57 +0200)
committerTobias Brunner <tobias@strongswan.org>
Wed, 22 Mar 2023 10:35:10 +0000 (11:35 +0100)
src/libcharon/encoding/message.c
src/libcharon/encoding/message.h

index 8e9cdd30fc3bdebda9a7350725e4fb6d4a80346d..18f99ac4dd491c479f7a72c8ef4e45a6adc17ddb 100644 (file)
@@ -1980,6 +1980,80 @@ METHOD(message_t, generate, status_t,
        return SUCCESS;
 }
 
+METHOD(message_t, get_plain, bool,
+       private_message_t *this, chunk_t *plain)
+{
+       generator_t *generator, *enc_generator;
+       enumerator_t *enumerator;
+       ike_header_t *ike_header;
+       payload_t *payload;
+       encrypted_payload_t *encrypted;
+       chunk_t int_auth_a, enc_header, int_auth_p;
+       struct {
+               uint8_t next_payload;
+               uint8_t flags;
+               uint16_t length;
+       } __attribute__((packed)) header = {};
+       uint32_t *lenpos;
+
+       if (this->major_version == IKEV1_MAJOR_VERSION ||
+               this->exchange_type != IKE_INTERMEDIATE)
+       {
+               return FALSE;
+       }
+
+       /* we expect to be called after the message has either been parsed
+        * or already generated once, so we don't modify payload order */
+       generator = generator_create_no_dbg();
+       ike_header = create_header(this);
+       payload = (payload_t*)ike_header;
+       /* for parsed messages the payloads were already extracted from the
+        * encrypted payload, if there were any unprotected paylaods we wouldn't
+        * know. lets assume there aren't any (also for sent messages) */
+       payload->set_next_type(payload, PLV2_ENCRYPTED);
+
+       generator->generate_payload(generator, payload);
+       int_auth_a = generator->get_chunk(generator, &lenpos);
+
+       enc_generator = generator_create_no_dbg();
+       this->payloads->get_first(this->payloads, (void**)&payload);
+       if (payload && payload->get_type(payload) == PLV2_ENCRYPTED)
+       {       /* we have to generate only the contents of this payload,
+                * not the payload itself, the header is added manually */
+               this->payloads->get_first(this->payloads, (void**)&payload);
+               encrypted = (encrypted_payload_t*)payload;
+
+               encrypted->generate_payloads(encrypted, enc_generator);
+
+               header.next_payload = payload->get_next_type(payload);
+       }
+       else
+       {       /* as mentioned above, assume all received payloads were contained in an
+                * encrypted payload */
+               enumerator = create_payload_enumerator(this);
+               while (enumerator->enumerate(enumerator, &payload))
+               {
+                       enc_generator->generate_payload(enc_generator, payload);
+               }
+               enumerator->destroy(enumerator);
+
+               header.next_payload = this->first_payload;
+       }
+       int_auth_p = enc_generator->get_chunk(enc_generator, NULL);
+
+       /* FIXME: copy flags */
+       enc_header = chunk_from_thing(header);
+       header.length = htons(enc_header.len + int_auth_p.len);
+
+       htoun32(lenpos, int_auth_a.len + enc_header.len + int_auth_p.len);
+       *plain = chunk_cat("ccc", int_auth_a, enc_header, int_auth_p);
+
+       enc_generator->destroy(enc_generator);
+       generator->destroy(generator);
+       ike_header->destroy(ike_header);
+       return TRUE;
+}
+
 /**
  * Creates a (basic) clone of the given message
  */
@@ -3127,6 +3201,7 @@ message_t *message_create_from_packet(packet_t *packet)
                        .get_fragments = _get_fragments,
                        .get_metadata = _get_metadata,
                        .set_metadata = _set_metadata,
+                       .get_plain = _get_plain,
                        .destroy = _destroy,
                },
                .exchange_type = EXCHANGE_TYPE_UNDEFINED,
index a31fce60b37af6b091a84fd511a41d9bc8ffab26..229ee12253ffc2fe1b9c784286d36b9603e04a8b 100644 (file)
@@ -258,6 +258,21 @@ struct message_t {
         */
        status_t (*generate) (message_t *this, keymat_t *keymat, packet_t **packet);
 
+       /**
+        * Generate the plaintext encoding of this message as needed to authenticate
+        * IKE_INTERMEDIATE exchanges.
+        *
+        * The data returned is the concatenation of the IKE header and plaintext
+        * payloads (if any) up until the end of the header of the Encrypted
+        * Payload followed by the plaintext data of the Encrypted Payload (if any).
+        * Lenght fields are adjusted to only contain that of returned data (e.g.
+        * IV or padding is ignored).
+        *
+        * @param[out] plain    plaintext encoding (allocated)
+        * @return                              TRUE if generated successfully
+        */
+       bool (*get_plain)(message_t *this, chunk_t *plain);
+
        /**
         * Check if the message has already been encoded using generate().
         *