Cast keymat safely, not based on external input
This commit is contained in:
@@ -1450,18 +1450,10 @@ METHOD(message_t, generate, status_t,
|
|||||||
{
|
{
|
||||||
order_payloads(this);
|
order_payloads(this);
|
||||||
}
|
}
|
||||||
|
if (keymat && keymat->get_version(keymat) == IKEV1)
|
||||||
if (this->major_version == IKEV2_MAJOR_VERSION)
|
|
||||||
{
|
|
||||||
encrypted = this->rule->encrypted;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
{
|
||||||
/* get a hash for this message, if any is required */
|
/* get a hash for this message, if any is required */
|
||||||
if (keymat_v1)
|
hash = keymat_v1->get_hash_phase2(keymat_v1, &this->public);
|
||||||
{
|
|
||||||
hash = keymat_v1->get_hash_phase2(keymat_v1, &this->public);
|
|
||||||
}
|
|
||||||
if (hash.ptr)
|
if (hash.ptr)
|
||||||
{ /* insert a HASH payload as first payload */
|
{ /* insert a HASH payload as first payload */
|
||||||
hash_payload_t *hash_payload;
|
hash_payload_t *hash_payload;
|
||||||
@@ -1475,24 +1467,28 @@ METHOD(message_t, generate, status_t,
|
|||||||
}
|
}
|
||||||
chunk_free(&hash);
|
chunk_free(&hash);
|
||||||
}
|
}
|
||||||
if (!encrypted)
|
}
|
||||||
|
if (this->major_version == IKEV2_MAJOR_VERSION)
|
||||||
|
{
|
||||||
|
encrypted = this->rule->encrypted;
|
||||||
|
}
|
||||||
|
else if (!encrypted)
|
||||||
|
{
|
||||||
|
/* If at least one payload requires encryption, encrypt the message.
|
||||||
|
* If no key material is available, the flag will be reset below. */
|
||||||
|
enumerator = this->payloads->create_enumerator(this->payloads);
|
||||||
|
while (enumerator->enumerate(enumerator, (void**)&payload))
|
||||||
{
|
{
|
||||||
/* If at least one payload requires encryption, encrypt the message.
|
payload_rule_t *rule;
|
||||||
* If no key material is available, the flag will be reset below. */
|
|
||||||
enumerator = this->payloads->create_enumerator(this->payloads);
|
|
||||||
while (enumerator->enumerate(enumerator, (void**)&payload))
|
|
||||||
{
|
|
||||||
payload_rule_t *rule;
|
|
||||||
|
|
||||||
rule = get_payload_rule(this, payload->get_type(payload));
|
rule = get_payload_rule(this, payload->get_type(payload));
|
||||||
if (rule && rule->encrypted)
|
if (rule && rule->encrypted)
|
||||||
{
|
{
|
||||||
this->is_encrypted = encrypted = TRUE;
|
this->is_encrypted = encrypted = TRUE;
|
||||||
break;
|
break;
|
||||||
}
|
|
||||||
}
|
}
|
||||||
enumerator->destroy(enumerator);
|
|
||||||
}
|
}
|
||||||
|
enumerator->destroy(enumerator);
|
||||||
}
|
}
|
||||||
|
|
||||||
DBG1(DBG_ENC, "generating %s", get_string(this, str, sizeof(str)));
|
DBG1(DBG_ENC, "generating %s", get_string(this, str, sizeof(str)));
|
||||||
@@ -1591,9 +1587,12 @@ METHOD(message_t, generate, status_t,
|
|||||||
htoun32(lenpos, chunk.len);
|
htoun32(lenpos, chunk.len);
|
||||||
this->packet->set_data(this->packet, chunk_clone(chunk));
|
this->packet->set_data(this->packet, chunk_clone(chunk));
|
||||||
if (this->is_encrypted)
|
if (this->is_encrypted)
|
||||||
{ /* update the IV for the next IKEv1 message */
|
{
|
||||||
|
/* update the IV for the next IKEv1 message */
|
||||||
chunk_t last_block;
|
chunk_t last_block;
|
||||||
size_t bs = aead->get_block_size(aead);
|
size_t bs;
|
||||||
|
|
||||||
|
bs = aead->get_block_size(aead);
|
||||||
last_block = chunk_create(chunk.ptr + chunk.len - bs, bs);
|
last_block = chunk_create(chunk.ptr + chunk.len - bs, bs);
|
||||||
keymat_v1->update_iv(keymat_v1, this->message_id, last_block);
|
keymat_v1->update_iv(keymat_v1, this->message_id, last_block);
|
||||||
keymat_v1->confirm_iv(keymat_v1, this->message_id);
|
keymat_v1->confirm_iv(keymat_v1, this->message_id);
|
||||||
@@ -1727,6 +1726,7 @@ static status_t parse_payloads(private_message_t *this)
|
|||||||
{ /* wrap the whole encrypted IKEv1 message in a special encryption
|
{ /* wrap the whole encrypted IKEv1 message in a special encryption
|
||||||
* payload which is then handled just like a regular payload */
|
* payload which is then handled just like a regular payload */
|
||||||
encryption_payload_t *encryption;
|
encryption_payload_t *encryption;
|
||||||
|
|
||||||
status = this->parser->parse_payload(this->parser, ENCRYPTED_V1,
|
status = this->parser->parse_payload(this->parser, ENCRYPTED_V1,
|
||||||
(payload_t**)&encryption);
|
(payload_t**)&encryption);
|
||||||
if (status != SUCCESS)
|
if (status != SUCCESS)
|
||||||
@@ -1817,7 +1817,19 @@ static status_t decrypt_payloads(private_message_t *this, keymat_t *keymat)
|
|||||||
status = VERIFY_ERROR;
|
status = VERIFY_ERROR;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
if (!keymat)
|
||||||
|
{
|
||||||
|
DBG1(DBG_ENC, "found encryption payload, but no keymat");
|
||||||
|
status = INVALID_ARG;
|
||||||
|
break;
|
||||||
|
}
|
||||||
aead = keymat->get_aead(keymat, TRUE);
|
aead = keymat->get_aead(keymat, TRUE);
|
||||||
|
if (!aead)
|
||||||
|
{
|
||||||
|
DBG1(DBG_ENC, "found encryption payload, but no transform set");
|
||||||
|
status = INVALID_ARG;
|
||||||
|
break;
|
||||||
|
}
|
||||||
bs = aead->get_block_size(aead);
|
bs = aead->get_block_size(aead);
|
||||||
encryption->set_transform(encryption, aead);
|
encryption->set_transform(encryption, aead);
|
||||||
chunk = this->packet->get_data(this->packet);
|
chunk = this->packet->get_data(this->packet);
|
||||||
@@ -1828,7 +1840,7 @@ static status_t decrypt_payloads(private_message_t *this, keymat_t *keymat)
|
|||||||
status = VERIFY_ERROR;
|
status = VERIFY_ERROR;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
if (type == ENCRYPTED_V1)
|
if (keymat->get_version(keymat) == IKEV1)
|
||||||
{ /* instead of associated data we provide the IV, we also update
|
{ /* instead of associated data we provide the IV, we also update
|
||||||
* the IV with the last encrypted block */
|
* the IV with the last encrypted block */
|
||||||
keymat_v1_t *keymat_v1 = (keymat_v1_t*)keymat;
|
keymat_v1_t *keymat_v1 = (keymat_v1_t*)keymat;
|
||||||
@@ -1982,7 +1994,7 @@ METHOD(message_t, parse_body, status_t,
|
|||||||
|
|
||||||
DBG1(DBG_ENC, "parsed %s", get_string(this, str, sizeof(str)));
|
DBG1(DBG_ENC, "parsed %s", get_string(this, str, sizeof(str)));
|
||||||
|
|
||||||
if (this->major_version == IKEV1_MAJOR_VERSION)
|
if (keymat && keymat->get_version(keymat) == IKEV1)
|
||||||
{
|
{
|
||||||
keymat_v1_t *keymat_v1 = (keymat_v1_t*)keymat;
|
keymat_v1_t *keymat_v1 = (keymat_v1_t*)keymat;
|
||||||
chunk_t hash;
|
chunk_t hash;
|
||||||
@@ -2019,15 +2031,11 @@ METHOD(message_t, parse_body, status_t,
|
|||||||
DBG2(DBG_ENC, "verified IKEv1 message with hash %B", &hash);
|
DBG2(DBG_ENC, "verified IKEv1 message with hash %B", &hash);
|
||||||
chunk_free(&hash);
|
chunk_free(&hash);
|
||||||
}
|
}
|
||||||
|
if (this->is_encrypted)
|
||||||
|
{ /* message verified, confirm IV */
|
||||||
|
keymat_v1->confirm_iv(keymat_v1, this->message_id);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (this->is_encrypted)
|
|
||||||
{ /* TODO-IKEv1: this should be done later when we know this is no
|
|
||||||
* retransmit */
|
|
||||||
keymat_v1_t *keymat_v1 = (keymat_v1_t*)keymat;
|
|
||||||
keymat_v1->confirm_iv(keymat_v1, this->message_id);
|
|
||||||
}
|
|
||||||
|
|
||||||
return SUCCESS;
|
return SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user