diff --git a/src/charon-tkm/tests/keymat_tests.c b/src/charon-tkm/tests/keymat_tests.c index 8aa719727b..ae3ebb1a15 100644 --- a/src/charon-tkm/tests/keymat_tests.c +++ b/src/charon-tkm/tests/keymat_tests.c @@ -80,6 +80,121 @@ START_TEST(test_derive_ike_keys) } END_TEST +START_TEST(test_derive_ike_keys_multi_ke) +{ + proposal_t *proposal = proposal_create_from_string(PROTO_IKE, + "aes256-sha512-modp3072-ke1_modp4096"); + fail_if(!proposal, "Unable to create proposal"); + ike_sa_id_t *ike_sa_id = ike_sa_id_create(IKEV2_MAJOR_VERSION, + 123912312312, 32312313122, TRUE); + fail_if(!ike_sa_id, "Unable to create IKE SA ID"); + + tkm_keymat_t *keymat = tkm_keymat_create(TRUE); + fail_if(!keymat, "Unable to create keymat"); + fail_if(!keymat->get_isa_id(keymat), "Invalid ISA context id (0)"); + + chunk_t nonce; + tkm_nonceg_t *ng = tkm_nonceg_create(); + fail_if(!ng, "Unable to create nonce generator"); + fail_unless(ng->nonce_gen.allocate_nonce(&ng->nonce_gen, 32, &nonce), + "Unable to allocate nonce"); + + tkm_key_exchange_t *ke = tkm_key_exchange_create(MODP_3072_BIT); + fail_if(!ke, "Unable to create first KE"); + + /* Use the same pubvalue for both sides */ + chunk_t pubvalue; + ck_assert(ke->ke.get_public_key(&ke->ke, &pubvalue)); + ck_assert(ke->ke.set_public_key(&ke->ke, pubvalue)); + chunk_free(&pubvalue); + + array_t *kes = NULL; + array_insert_create(&kes, ARRAY_TAIL, ke); + fail_unless(keymat->keymat_v2.derive_ike_keys(&keymat->keymat_v2, proposal, + kes, nonce, nonce, ike_sa_id, PRF_UNDEFINED, chunk_empty), + "Key derivation failed"); + array_destroy(kes); + ke->ke.destroy(&ke->ke); + + const aead_t *aead = keymat->keymat_v2.keymat.get_aead(&keymat->keymat_v2.keymat, TRUE); + fail_if(!aead, "AEAD is NULL"); + + /* single KE during IKE_INTERMEDIATE on the same keymat with same nonces */ + pseudo_random_function_t prf; + chunk_t skd; + prf = keymat->keymat_v2.get_skd(&keymat->keymat_v2, &skd); + fail_if(prf != PRF_HMAC_SHA2_512, "PRF incorrect"); + + ke = tkm_key_exchange_create(MODP_4096_BIT); + fail_if(!ke, "Unable to create second KE"); + ck_assert(ke->ke.get_public_key(&ke->ke, &pubvalue)); + ck_assert(ke->ke.set_public_key(&ke->ke, pubvalue)); + chunk_free(&pubvalue); + + kes = NULL; + array_insert_create(&kes, ARRAY_TAIL, ke); + fail_unless(keymat->keymat_v2.derive_ike_keys(&keymat->keymat_v2, proposal, + kes, nonce, nonce, ike_sa_id, prf, skd), + "Second key derivation failed"); + array_destroy(kes); + ke->ke.destroy(&ke->ke); + chunk_free(&nonce); + + aead = keymat->keymat_v2.keymat.get_aead(&keymat->keymat_v2.keymat, TRUE); + fail_if(!aead, "AEAD is NULL"); + ng->nonce_gen.destroy(&ng->nonce_gen); + ike_sa_id->destroy(ike_sa_id); + + /* rekeying uses a new keymat/SA/nonce and multiple KEs */ + ike_sa_id = ike_sa_id_create(IKEV2_MAJOR_VERSION, + 34912312312, 612313122, TRUE); + fail_if(!ike_sa_id, "Unable to create IKE SA ID"); + + tkm_keymat_t *keymat2 = tkm_keymat_create(TRUE); + fail_if(!keymat2, "Unable to create keymat"); + fail_if(!keymat2->get_isa_id(keymat2), "Invalid ISA context id (0)"); + + ng = tkm_nonceg_create(); + fail_if(!ng, "Unable to create nonce generator"); + fail_unless(ng->nonce_gen.allocate_nonce(&ng->nonce_gen, 32, &nonce), + "Unable to allocate nonce"); + + tkm_key_exchange_t *ke1 = tkm_key_exchange_create(MODP_3072_BIT); + fail_if(!ke1, "Unable to create first KE"); + ck_assert(ke1->ke.get_public_key(&ke1->ke, &pubvalue)); + ck_assert(ke1->ke.set_public_key(&ke1->ke, pubvalue)); + chunk_free(&pubvalue); + tkm_key_exchange_t *ke2 = tkm_key_exchange_create(MODP_4096_BIT); + fail_if(!ke2, "Unable to create second KE"); + ck_assert(ke2->ke.get_public_key(&ke2->ke, &pubvalue)); + ck_assert(ke2->ke.set_public_key(&ke2->ke, pubvalue)); + chunk_free(&pubvalue); + + prf = keymat->keymat_v2.get_skd(&keymat->keymat_v2, &skd); + fail_if(prf != PRF_HMAC_SHA2_512, "PRF incorrect"); + + kes = NULL; + array_insert_create(&kes, ARRAY_TAIL, ke1); + array_insert_create(&kes, ARRAY_TAIL, ke2); + fail_unless(keymat2->keymat_v2.derive_ike_keys(&keymat2->keymat_v2, proposal, + kes, nonce, nonce, ike_sa_id, prf, skd), + "Rekey key derivation failed"); + array_destroy(kes); + ke1->ke.destroy(&ke1->ke); + ke2->ke.destroy(&ke2->ke); + chunk_free(&nonce); + + aead = keymat2->keymat_v2.keymat.get_aead(&keymat2->keymat_v2.keymat, TRUE); + fail_if(!aead, "AEAD is NULL"); + + ng->nonce_gen.destroy(&ng->nonce_gen); + proposal->destroy(proposal); + ike_sa_id->destroy(ike_sa_id); + keymat->keymat_v2.keymat.destroy(&keymat->keymat_v2.keymat); + keymat2->keymat_v2.keymat.destroy(&keymat2->keymat_v2.keymat); +} +END_TEST + START_TEST(test_derive_child_keys) { tkm_key_exchange_t *ke = tkm_key_exchange_create(MODP_4096_BIT); @@ -93,12 +208,13 @@ START_TEST(test_derive_child_keys) fail_if(!keymat, "Unable to create keymat"); chunk_t encr_i, encr_r, integ_i, integ_r; - chunk_t nonce = chunk_from_chars("test chunk"); + chunk_t nonce_i = chunk_from_chars("test chunk 1"), + nonce_r = chunk_from_chars("test chunk 2"); array_t *kes = NULL; array_insert_create(&kes, ARRAY_TAIL, ke); fail_unless(keymat->keymat_v2.derive_child_keys(&keymat->keymat_v2, proposal, - kes, nonce, nonce, &encr_i, + kes, nonce_i, nonce_r, &encr_i, &integ_i, &encr_r, &integ_r), "Child key derivation failed"); array_destroy(kes); @@ -109,9 +225,9 @@ START_TEST(test_derive_child_keys) "Isa context id mismatch (encr_i)"); fail_if(info->spi_l != 42, "SPI mismatch (encr_i)"); - fail_unless(chunk_equals(info->nonce_i, nonce), + fail_unless(chunk_equals(info->nonce_i, nonce_i), "nonce_i mismatch (encr_i)"); - fail_unless(chunk_equals(info->nonce_r, nonce), + fail_unless(chunk_equals(info->nonce_r, nonce_r), "nonce_r mismatch (encr_i)"); fail_if(info->is_encr_r, "Flag is_encr_r set for encr_i"); @@ -128,9 +244,9 @@ START_TEST(test_derive_child_keys) "Isa context id mismatch (encr_r)"); fail_if(info->spi_l != 42, "SPI mismatch (encr_r)"); - fail_unless(chunk_equals(info->nonce_i, nonce), + fail_unless(chunk_equals(info->nonce_i, nonce_i), "nonce_i mismatch (encr_r)"); - fail_unless(chunk_equals(info->nonce_r, nonce), + fail_unless(chunk_equals(info->nonce_r, nonce_r), "nonce_r mismatch (encr_r)"); fail_unless(info->is_encr_r, "Flag is_encr_r set for encr_r"); @@ -149,6 +265,84 @@ START_TEST(test_derive_child_keys) } END_TEST +START_TEST(test_derive_child_keys_multi_ke) +{ + tkm_key_exchange_t *ke1 = tkm_key_exchange_create(MODP_3072_BIT); + fail_if(!ke1, "Unable to create DH object"); + tkm_key_exchange_t *ke2 = tkm_key_exchange_create(MODP_4096_BIT); + fail_if(!ke2, "Unable to create DH object"); + proposal_t *proposal = proposal_create_from_string(PROTO_ESP, + "aes256-sha512-modp4096"); + fail_if(!proposal, "Unable to create proposal"); + proposal->set_spi(proposal, 42); + + tkm_keymat_t *keymat = tkm_keymat_create(TRUE); + fail_if(!keymat, "Unable to create keymat"); + + chunk_t encr_i, encr_r, integ_i, integ_r; + chunk_t nonce_i = chunk_from_chars("test chunk 1"), + nonce_r = chunk_from_chars("test chunk 2"); + + array_t *kes = NULL; + array_insert_create(&kes, ARRAY_TAIL, ke1); + array_insert_create(&kes, ARRAY_TAIL, ke2); + fail_unless(keymat->keymat_v2.derive_child_keys(&keymat->keymat_v2, proposal, + kes, nonce_i, nonce_r, &encr_i, + &integ_i, &encr_r, &integ_r), + "Child key derivation failed"); + array_destroy(kes); + + esa_info_t *info = (esa_info_t *)encr_i.ptr; + fail_if(!info, "encr_i does not contain esa information"); + fail_if(info->isa_id != keymat->get_isa_id(keymat), + "Isa context id mismatch (encr_i)"); + fail_if(info->spi_l != 42, + "SPI mismatch (encr_i)"); + fail_unless(chunk_equals(info->nonce_i, nonce_i), + "nonce_i mismatch (encr_i)"); + fail_unless(chunk_equals(info->nonce_r, nonce_r), + "nonce_r mismatch (encr_i)"); + fail_if(info->is_encr_r, + "Flag is_encr_r set for encr_i"); + fail_if(info->ke_ids.size != 2, + "KE context number mismatch (encr_i)"); + fail_if(info->ke_ids.data[0] != ke1->get_id(ke1), + "KE context id mismatch (encr_i)"); + fail_if(info->ke_ids.data[1] != ke2->get_id(ke2), + "KE context id mismatch (encr_i)"); + chunk_free(&info->nonce_i); + chunk_free(&info->nonce_r); + + info = (esa_info_t *)encr_r.ptr; + fail_if(!info, "encr_r does not contain esa information"); + fail_if(info->isa_id != keymat->get_isa_id(keymat), + "Isa context id mismatch (encr_r)"); + fail_if(info->spi_l != 42, + "SPI mismatch (encr_r)"); + fail_unless(chunk_equals(info->nonce_i, nonce_i), + "nonce_i mismatch (encr_r)"); + fail_unless(chunk_equals(info->nonce_r, nonce_r), + "nonce_r mismatch (encr_r)"); + fail_unless(info->is_encr_r, + "Flag is_encr_r set for encr_r"); + fail_if(info->ke_ids.size != 2, + "KE context number mismatch (encr_i)"); + fail_if(info->ke_ids.data[0] != ke1->get_id(ke1), + "KE context id mismatch (encr_i)"); + fail_if(info->ke_ids.data[1] != ke2->get_id(ke2), + "KE context id mismatch (encr_i)"); + chunk_free(&info->nonce_i); + chunk_free(&info->nonce_r); + + proposal->destroy(proposal); + ke1->ke.destroy(&ke1->ke); + ke2->ke.destroy(&ke2->ke); + keymat->keymat_v2.keymat.destroy(&keymat->keymat_v2.keymat); + chunk_free(&encr_i); + chunk_free(&encr_r); +} +END_TEST + Suite *make_keymat_tests() { Suite *s; @@ -158,10 +352,12 @@ Suite *make_keymat_tests() tc = tcase_create("derive IKE keys"); tcase_add_test(tc, test_derive_ike_keys); + tcase_add_test(tc, test_derive_ike_keys_multi_ke); suite_add_tcase(s, tc); tc = tcase_create("derive CHILD keys"); tcase_add_test(tc, test_derive_child_keys); + tcase_add_test(tc, test_derive_child_keys_multi_ke); suite_add_tcase(s, tc); return s;