]> 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)
committerAndreas Steffen <andreas.steffen@strongswan.org>
Sun, 29 Mar 2020 11:47:22 +0000 (13:47 +0200)
src/libcharon/encoding/message.c
src/libcharon/encoding/message.h

index 299a0d75b18ae3f7d98a9a97bf254cf6dad4ba05..f4654f4b4610632d405b5af182f076e8c8dbd2c6 100644 (file)
@@ -1941,6 +1941,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 */
+       header.length = htons(int_auth_p.len);
+       enc_header = chunk_from_thing(header);
+
+       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
  */
@@ -3078,6 +3152,7 @@ message_t *message_create_from_packet(packet_t *packet)
                        .get_packet = _get_packet,
                        .get_packet_data = _get_packet_data,
                        .get_fragments = _get_fragments,
+                       .get_plain = _get_plain,
                        .destroy = _destroy,
                },
                .exchange_type = EXCHANGE_TYPE_UNDEFINED,
index 10ffbed56d5e265e7d82d032349eddfbcd5152a0..2a90ccbb7fa095f71b7cf8bd4b2eaf5a82953f30 100644 (file)
@@ -257,6 +257,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().
         *