message: Add method to generate data to authenticate IKE_INTERMEDIATE exchanges

This commit is contained in:
Tobias Brunner 2019-08-20 14:57:30 +02:00
parent 5c439bb8a3
commit b9c69f9080
2 changed files with 92 additions and 0 deletions

View File

@ -1984,6 +1984,82 @@ METHOD(message_t, generate, status_t,
return SUCCESS; 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 */
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);
/* flags are currently no copied, but the critical bit and the reserved
* bits MUST be zero for encrypted payloads, so that's what we assume */
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 * Creates a (basic) clone of the given message
*/ */
@ -3131,6 +3207,7 @@ message_t *message_create_from_packet(packet_t *packet)
.get_fragments = _get_fragments, .get_fragments = _get_fragments,
.get_metadata = _get_metadata, .get_metadata = _get_metadata,
.set_metadata = _set_metadata, .set_metadata = _set_metadata,
.get_plain = _get_plain,
.destroy = _destroy, .destroy = _destroy,
}, },
.exchange_type = EXCHANGE_TYPE_UNDEFINED, .exchange_type = EXCHANGE_TYPE_UNDEFINED,

View File

@ -258,6 +258,21 @@ struct message_t {
*/ */
status_t (*generate) (message_t *this, keymat_t *keymat, packet_t **packet); 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(). * Check if the message has already been encoded using generate().
* *