diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/libcharon/encoding/message.c | 45 | ||||
-rw-r--r-- | src/libcharon/plugins/ha/ha_dispatcher.c | 6 | ||||
-rw-r--r-- | src/libcharon/plugins/ha/ha_ike.c | 16 | ||||
-rw-r--r-- | src/libcharon/sa/ikev1/keymat_v1.c | 32 | ||||
-rw-r--r-- | src/libcharon/sa/ikev1/keymat_v1.h | 12 |
5 files changed, 80 insertions, 31 deletions
diff --git a/src/libcharon/encoding/message.c b/src/libcharon/encoding/message.c index 1aef7c243..7e4c6e0e3 100644 --- a/src/libcharon/encoding/message.c +++ b/src/libcharon/encoding/message.c @@ -1568,7 +1568,11 @@ METHOD(message_t, generate, status_t, encryption->set_transform(encryption, aead); if (this->is_encrypted) { /* for IKEv1 instead of associated data we provide the IV */ - chunk = keymat_v1->get_iv(keymat_v1, this->message_id); + if (!keymat_v1->get_iv(keymat_v1, this->message_id, &chunk)) + { + generator->destroy(generator); + return FAILED; + } } else { /* build associated data (without header of encryption payload) */ @@ -1579,9 +1583,17 @@ METHOD(message_t, generate, status_t, this->payloads->insert_last(this->payloads, encryption); if (!encryption->encrypt(encryption, chunk)) { + if (this->is_encrypted) + { + free(chunk.ptr); + } generator->destroy(generator); return INVALID_STATE; } + if (this->is_encrypted) + { + free(chunk.ptr); + } generator->generate_payload(generator, &encryption->payload_interface); } chunk = generator->get_chunk(generator, &lenpos); @@ -1595,8 +1607,12 @@ METHOD(message_t, generate, status_t, bs = aead->get_block_size(aead); last_block = chunk_create(chunk.ptr + chunk.len - bs, bs); - keymat_v1->update_iv(keymat_v1, this->message_id, last_block); - keymat_v1->confirm_iv(keymat_v1, this->message_id); + if (!keymat_v1->update_iv(keymat_v1, this->message_id, last_block) || + !keymat_v1->confirm_iv(keymat_v1, this->message_id)) + { + generator->destroy(generator); + return FAILED; + } } generator->destroy(generator); *packet = this->packet->clone(this->packet); @@ -1846,17 +1862,25 @@ static status_t decrypt_payloads(private_message_t *this, keymat_t *keymat) { /* instead of associated data we provide the IV, we also update * the IV with the last encrypted block */ keymat_v1_t *keymat_v1 = (keymat_v1_t*)keymat; - chunk_t last_block; + chunk_t iv = chunk_empty; - last_block = chunk_create(chunk.ptr + chunk.len - bs, bs); - chunk = keymat_v1->get_iv(keymat_v1, this->message_id); - keymat_v1->update_iv(keymat_v1, this->message_id, last_block); + if (keymat_v1->get_iv(keymat_v1, this->message_id, &iv) && + keymat_v1->update_iv(keymat_v1, this->message_id, + chunk_create(chunk.ptr + chunk.len - bs, bs))) + { + status = encryption->decrypt(encryption, iv); + } + else + { + status = FAILED; + } + free(chunk.ptr); } else { chunk.len -= encryption->get_length(encryption); + status = encryption->decrypt(encryption, chunk); } - status = encryption->decrypt(encryption, chunk); if (status != SUCCESS) { break; @@ -2035,7 +2059,10 @@ METHOD(message_t, parse_body, status_t, } if (this->is_encrypted) { /* message verified, confirm IV */ - keymat_v1->confirm_iv(keymat_v1, this->message_id); + if (!keymat_v1->confirm_iv(keymat_v1, this->message_id)) + { + return FAILED; + } } } return SUCCESS; diff --git a/src/libcharon/plugins/ha/ha_dispatcher.c b/src/libcharon/plugins/ha/ha_dispatcher.c index 98055fa7e..8b6ec9180 100644 --- a/src/libcharon/plugins/ha/ha_dispatcher.c +++ b/src/libcharon/plugins/ha/ha_dispatcher.c @@ -525,8 +525,10 @@ static void process_ike_iv(private_ha_dispatcher_t *this, ha_message_t *message) keymat_v1_t *keymat; keymat = (keymat_v1_t*)ike_sa->get_keymat(ike_sa); - keymat->update_iv(keymat, 0, iv); - keymat->confirm_iv(keymat, 0); + if (keymat->update_iv(keymat, 0, iv)) + { + keymat->confirm_iv(keymat, 0); + } } } this->cache->cache(this->cache, ike_sa, message); diff --git a/src/libcharon/plugins/ha/ha_ike.c b/src/libcharon/plugins/ha/ha_ike.c index 2819b9dd5..2d02917e5 100644 --- a/src/libcharon/plugins/ha/ha_ike.c +++ b/src/libcharon/plugins/ha/ha_ike.c @@ -302,13 +302,15 @@ METHOD(listener_t, message_hook, bool, if (mid == 0) { keymat = (keymat_v1_t*)ike_sa->get_keymat(ike_sa); - iv = keymat->get_iv(keymat, mid); - m = ha_message_create(HA_IKE_IV); - m->add_attribute(m, HA_IKE_ID, ike_sa->get_id(ike_sa)); - m->add_attribute(m, HA_IV, iv); - free(iv.ptr); - this->socket->push(this->socket, m); - this->cache->cache(this->cache, ike_sa, m); + if (keymat->get_iv(keymat, mid, &iv)) + { + m = ha_message_create(HA_IKE_IV); + m->add_attribute(m, HA_IKE_ID, ike_sa->get_id(ike_sa)); + m->add_attribute(m, HA_IV, iv); + free(iv.ptr); + this->socket->push(this->socket, m); + this->cache->cache(this->cache, ike_sa, m); + } } if (!incoming && message->get_exchange_type(message) == TRANSACTION) { diff --git a/src/libcharon/sa/ikev1/keymat_v1.c b/src/libcharon/sa/ikev1/keymat_v1.c index 9540075d6..8f6da3ca4 100644 --- a/src/libcharon/sa/ikev1/keymat_v1.c +++ b/src/libcharon/sa/ikev1/keymat_v1.c @@ -964,7 +964,7 @@ METHOD(keymat_v1_t, get_hash_phase2, bool, /** * Generate an IV */ -static void generate_iv(private_keymat_v1_t *this, iv_data_t *iv) +static bool generate_iv(private_keymat_v1_t *this, iv_data_t *iv) { if (iv->mid == 0 || iv->iv.ptr) { /* use last block of previous encrypted message */ @@ -985,6 +985,7 @@ static void generate_iv(private_keymat_v1_t *this, iv_data_t *iv) } } DBG4(DBG_IKE, "next IV for MID %u %B", iv->mid, &iv->iv); + return TRUE; } /** @@ -1016,7 +1017,11 @@ static iv_data_t *lookup_iv(private_keymat_v1_t *this, u_int32_t mid) INIT(found, .mid = mid, ); - generate_iv(this, found); + if (!generate_iv(this, found)) + { + iv_data_destroy(found); + return NULL; + } } this->ivs->insert_first(this->ivs, found); /* remove least recently used IV if maximum reached */ @@ -1028,13 +1033,21 @@ static iv_data_t *lookup_iv(private_keymat_v1_t *this, u_int32_t mid) return found; } -METHOD(keymat_v1_t, get_iv, chunk_t, - private_keymat_v1_t *this, u_int32_t mid) +METHOD(keymat_v1_t, get_iv, bool, + private_keymat_v1_t *this, u_int32_t mid, chunk_t *out) { - return chunk_clone(lookup_iv(this, mid)->iv); + iv_data_t *iv; + + iv = lookup_iv(this, mid); + if (iv) + { + *out = iv->iv; + return TRUE; + } + return FALSE; } -METHOD(keymat_v1_t, update_iv, void, +METHOD(keymat_v1_t, update_iv, bool, private_keymat_v1_t *this, u_int32_t mid, chunk_t last_block) { iv_data_t *iv = lookup_iv(this, mid); @@ -1042,17 +1055,20 @@ METHOD(keymat_v1_t, update_iv, void, { /* update last block */ chunk_free(&iv->last_block); iv->last_block = chunk_clone(last_block); + return TRUE; } + return FALSE; } -METHOD(keymat_v1_t, confirm_iv, void, +METHOD(keymat_v1_t, confirm_iv, bool, private_keymat_v1_t *this, u_int32_t mid) { iv_data_t *iv = lookup_iv(this, mid); if (iv) { - generate_iv(this, iv); + return generate_iv(this, iv); } + return FALSE; } METHOD(keymat_t, get_version, ike_version_t, diff --git a/src/libcharon/sa/ikev1/keymat_v1.h b/src/libcharon/sa/ikev1/keymat_v1.h index 8acbf582f..a25bc98b2 100644 --- a/src/libcharon/sa/ikev1/keymat_v1.h +++ b/src/libcharon/sa/ikev1/keymat_v1.h @@ -121,9 +121,10 @@ struct keymat_v1_t { * Returns the IV for a message with the given message ID. * * @param mid message ID - * @return IV (needs to be freed) + * @param iv chunk receiving allocated IV + * @return TRUE if IV allocated successfully */ - chunk_t (*get_iv)(keymat_v1_t *this, u_int32_t mid); + bool (*get_iv)(keymat_v1_t *this, u_int32_t mid, chunk_t *iv); /** * Updates the IV for the next message with the given message ID. @@ -135,8 +136,9 @@ struct keymat_v1_t { * * @param mid message ID * @param last_block last block of encrypted message (gets cloned) + * @return TRUE if IV updated successfully */ - void (*update_iv)(keymat_v1_t *this, u_int32_t mid, chunk_t last_block); + bool (*update_iv)(keymat_v1_t *this, u_int32_t mid, chunk_t last_block); /** * Confirms the updated IV for the given message ID. @@ -145,9 +147,9 @@ struct keymat_v1_t { * be called after update_iv. * * @param mid message ID + * @return TRUE if IV confirmed successfully */ - void (*confirm_iv)(keymat_v1_t *this, u_int32_t mid); - + bool (*confirm_iv)(keymat_v1_t *this, u_int32_t mid); }; /** |