From 80853d8498dd93993a38b8128de50810676b34b4 Mon Sep 17 00:00:00 2001 From: Martin Willi Date: Wed, 29 Oct 2008 16:06:16 +0000 Subject: [PATCH] moved CHILD_SA key derivation to keymat_t passing key chunks to CHILD_SA, not the PRF --- src/charon/plugins/stroke/stroke_list.c | 62 ++- src/charon/sa/child_sa.c | 496 +++++++++--------------- src/charon/sa/child_sa.h | 43 +- src/charon/sa/keymat.c | 164 +++++++- src/charon/sa/keymat.h | 46 ++- src/charon/sa/tasks/child_create.c | 81 ++-- src/charon/sa/tasks/ike_init.c | 4 +- 7 files changed, 447 insertions(+), 449 deletions(-) diff --git a/src/charon/plugins/stroke/stroke_list.c b/src/charon/plugins/stroke/stroke_list.c index b4963a7ad..eb15e243c 100644 --- a/src/charon/plugins/stroke/stroke_list.c +++ b/src/charon/plugins/stroke/stroke_list.c @@ -136,9 +136,7 @@ static void log_child_sa(FILE *out, child_sa_t *child_sa, bool all) { u_int32_t rekey, now = time(NULL); u_int32_t use_in, use_out; - encryption_algorithm_t encr_alg; - integrity_algorithm_t int_alg; - chunk_t encr_key, int_key; + proposal_t *proposal; fprintf(out, "%12s{%d}: %N, %N", child_sa->get_name(child_sa), child_sa->get_reqid(child_sa), @@ -152,54 +150,46 @@ static void log_child_sa(FILE *out, child_sa_t *child_sa, bool all) child_sa->has_encap(child_sa) ? " in UDP": "", ntohl(child_sa->get_spi(child_sa, TRUE)), ntohl(child_sa->get_spi(child_sa, FALSE))); - + if (child_sa->get_ipcomp(child_sa) != IPCOMP_NONE) { fprintf(out, ", IPCOMP CPIs: %.4x_i %.4x_o", ntohs(child_sa->get_cpi(child_sa, TRUE)), ntohs(child_sa->get_cpi(child_sa, FALSE))); } - + if (all) { fprintf(out, "\n%12s{%d}: ", child_sa->get_name(child_sa), child_sa->get_reqid(child_sa)); - if (child_sa->get_protocol(child_sa) == PROTO_ESP) + proposal = child_sa->get_proposal(child_sa); + if (proposal) { - encr_alg = child_sa->get_encryption(child_sa, TRUE, &encr_key); - - switch (encr_alg) + u_int16_t encr_alg = ENCR_UNDEFINED, int_alg = AUTH_UNDEFINED; + u_int16_t encr_size = 0, int_size = 0; + + proposal->get_algorithm(proposal, ENCRYPTION_ALGORITHM, + &encr_alg, &encr_size); + proposal->get_algorithm(proposal, INTEGRITY_ALGORITHM, + &int_alg, &int_size); + + if (encr_alg != ENCR_UNDEFINED) { - /* Algorithms with variable key size. - * GCM/CCM keys are actually shorted than their key data. */ - case ENCR_AES_GCM_ICV8: - case ENCR_AES_GCM_ICV12: - case ENCR_AES_GCM_ICV16: - encr_key.len -= 1; - /* FALL */ - case ENCR_AES_CCM_ICV8: - case ENCR_AES_CCM_ICV12: - case ENCR_AES_CCM_ICV16: - encr_key.len -= 3; - /* FALL */ - case ENCR_AES_CBC: - fprintf(out, "%N-%d", encryption_algorithm_names, - encr_alg, encr_key.len * 8); - break; - default: - fprintf(out, "%N", encryption_algorithm_names, encr_alg); - break; + fprintf(out, "%N", encryption_algorithm_names, encr_alg); + if (encr_size) + { + fprintf(out, "-%d", encr_size); + } } - } - int_alg = child_sa->get_integrity(child_sa, TRUE, &int_key); - switch (int_alg) - { - case AUTH_UNDEFINED: - break; - default: + if (int_alg != AUTH_UNDEFINED) + { fprintf(out, "/%N", integrity_algorithm_names, int_alg); - break; + if (int_size) + { + fprintf(out, "-%d", int_size); + } + } } fprintf(out, ", rekeying "); diff --git a/src/charon/sa/child_sa.c b/src/charon/sa/child_sa.c index 4bc2c2cd4..1cc2ad0fa 100644 --- a/src/charon/sa/child_sa.c +++ b/src/charon/sa/child_sa.c @@ -47,14 +47,45 @@ struct private_child_sa_t { */ child_sa_t public; - struct { - /** address of peer */ - host_t *addr; - /** actual used SPI, 0 if unused */ - u_int32_t spi; - /** Compression Parameter Index (CPI) used, 0 if unused */ - u_int16_t cpi; - } me, other; + /** + * address of us + */ + host_t *my_addr; + + /** + * address of remote + */ + host_t *other_addr; + + /** + * our actually used SPI, 0 if unused + */ + u_int32_t my_spi; + + /** + * others used SPI, 0 if unused + */ + u_int32_t other_spi; + + /** + * our Compression Parameter Index (CPI) used, 0 if unused + */ + u_int16_t my_cpi; + + /** + * others Compression Parameter Index (CPI) used, 0 if unused + */ + u_int16_t other_cpi; + + /** + * List for local traffic selectors + */ + linked_list_t *my_ts; + + /** + * List for remote traffic selectors + */ + linked_list_t *other_ts; /** * Allocated SPI for a ESP proposal candidates @@ -71,41 +102,11 @@ struct private_child_sa_t { */ protocol_id_t protocol; - /** - * Separate list for local traffic selectors - */ - linked_list_t *my_ts; - - /** - * Separate list for remote traffic selectors - */ - linked_list_t *other_ts; - /** * reqid used for this child_sa */ u_int32_t reqid; - /** - * encryption algorithm used for this SA - */ - u_int16_t enc_alg; - - /** - * Encryption key data, inbound and outbound - */ - chunk_t enc_key[2]; - - /** - * integrity protection algorithm used for this SA - */ - u_int16_t int_alg; - - /** - * integrity key data, inbound and outbound - */ - chunk_t int_key[2]; - /** * absolute time when rekeying is scheduled */ @@ -141,66 +142,19 @@ struct private_child_sa_t { */ ipsec_mode_t mode; + /** + * selected proposal + */ + proposal_t *proposal; + /** * config used to create this child */ child_cfg_t *config; }; -typedef struct keylen_entry_t keylen_entry_t; - /** - * Implicit key length for an algorithm - */ -struct keylen_entry_t { - /** IKEv2 algorithm identifier */ - int algo; - /** key length in bits */ - int len; -}; - -#define END_OF_LIST -1 - -/** - * Keylen for encryption algos - */ -keylen_entry_t keylen_enc[] = { - {ENCR_DES, 64}, - {ENCR_3DES, 192}, - {END_OF_LIST, 0} -}; - -/** - * Keylen for integrity algos - */ -keylen_entry_t keylen_int[] = { - {AUTH_HMAC_MD5_96, 128}, - {AUTH_HMAC_SHA1_96, 160}, - {AUTH_HMAC_SHA2_256_128, 256}, - {AUTH_HMAC_SHA2_384_192, 384}, - {AUTH_HMAC_SHA2_512_256, 512}, - {AUTH_AES_XCBC_96, 128}, - {END_OF_LIST, 0} -}; - -/** - * Lookup key length of an algorithm - */ -static int lookup_keylen(keylen_entry_t *list, int algo) -{ - while (list->algo != END_OF_LIST) - { - if (algo == list->algo) - { - return list->len; - } - list++; - } - return 0; -} - -/** - * Implementation of child_sa_t.get_name. + * Implementation of child_sa_t.get_namy_ */ static char *get_name(private_child_sa_t *this) { @@ -220,11 +174,7 @@ static u_int32_t get_reqid(private_child_sa_t *this) */ u_int32_t get_spi(private_child_sa_t *this, bool inbound) { - if (inbound) - { - return this->me.spi; - } - return this->other.spi; + return inbound ? this->my_spi : this->other_spi; } /** @@ -232,11 +182,7 @@ u_int32_t get_spi(private_child_sa_t *this, bool inbound) */ u_int16_t get_cpi(private_child_sa_t *this, bool inbound) { - if (inbound) - { - return this->me.cpi; - } - return this->other.cpi; + return inbound ? this->my_cpi : this->other_cpi; } /** @@ -247,6 +193,14 @@ protocol_id_t get_protocol(private_child_sa_t *this) return this->protocol; } +/** + * Implementation of child_sa_t.get_mode + */ +static ipsec_mode_t get_mode(private_child_sa_t *this) +{ + return this->mode; +} + /** * Implementation of child_sa_t.has_encap */ @@ -403,39 +357,7 @@ static u_int32_t get_usetime(private_child_sa_t *this, bool inbound) */ static u_int32_t get_lifetime(private_child_sa_t *this, bool hard) { - if (hard) - { - return this->expire_time; - } - return this->rekey_time; -} - -/** - * Implementation of child_sa_t.get_integrity - */ -static integrity_algorithm_t get_integrity(private_child_sa_t *this, - bool inbound, chunk_t *key) -{ - *key = this->int_key[!!inbound]; - return this->int_alg; -} - -/** - * Implementation of child_sa_t.get_encryption - */ -static encryption_algorithm_t get_encryption(private_child_sa_t *this, - bool inbound, chunk_t *key) -{ - *key = this->enc_key[!!inbound]; - return this->enc_alg; -} - -/** - * Implementation of child_sa_t.get_mode - */ -static ipsec_mode_t get_mode(private_child_sa_t *this) -{ - return this->mode; + return hard ? this->expire_time : this->rekey_time; } /** @@ -461,7 +383,7 @@ static status_t alloc_proposal(private_child_sa_t *this, proposal_t *proposal) { if (charon->kernel_interface->get_spi( charon->kernel_interface, - this->other.addr, this->me.addr, + this->other_addr, this->my_addr, PROTO_AH, this->reqid, &this->alloc_ah_spi) != SUCCESS) { @@ -477,7 +399,7 @@ static status_t alloc_proposal(private_child_sa_t *this, proposal_t *proposal) { if (charon->kernel_interface->get_spi( charon->kernel_interface, - this->other.addr, this->me.addr, + this->other_addr, this->my_addr, PROTO_ESP, this->reqid, &this->alloc_esp_spi) != SUCCESS) { @@ -489,7 +411,6 @@ static status_t alloc_proposal(private_child_sa_t *this, proposal_t *proposal) return SUCCESS; } - /** * Implements child_sa_t.alloc */ @@ -512,138 +433,79 @@ static status_t alloc(private_child_sa_t *this, linked_list_t *proposals) return SUCCESS; } +/** + * Install an SA for one direction + */ static status_t install(private_child_sa_t *this, proposal_t *proposal, - ipsec_mode_t mode, prf_plus_t *prf_plus, bool mine) + ipsec_mode_t mode, chunk_t integ, chunk_t encr, bool in) { + u_int16_t enc_alg = ENCR_UNDEFINED, int_alg = AUTH_UNDEFINED, size; u_int32_t spi, cpi, soft, hard, now; host_t *src, *dst; status_t status; - int add_keymat; - u_int16_t enc_size, int_size; - this->protocol = proposal->get_protocol(proposal); - - /* now we have to decide which spi to use. Use self allocated, if "mine", - * or the one in the proposal, if not "mine" (others). Additionally, + /* now we have to decide which spi to use. Use self allocated, if "in", + * or the one in the proposal, if not "in" (others). Additionally, * source and dest host switch depending on the role */ - if (mine) + if (in) { /* if we have allocated SPIs for AH and ESP, we must delete the unused * one. */ if (this->protocol == PROTO_ESP) { - this->me.spi = this->alloc_esp_spi; + this->my_spi = this->alloc_esp_spi; if (this->alloc_ah_spi) { charon->kernel_interface->del_sa(charon->kernel_interface, - this->me.addr, this->alloc_ah_spi, PROTO_AH); + this->my_addr, this->alloc_ah_spi, PROTO_AH); } } else { - this->me.spi = this->alloc_ah_spi; + this->my_spi = this->alloc_ah_spi; if (this->alloc_esp_spi) { charon->kernel_interface->del_sa(charon->kernel_interface, - this->me.addr, this->alloc_esp_spi, PROTO_ESP); + this->my_addr, this->alloc_esp_spi, PROTO_ESP); } } - spi = this->me.spi; - dst = this->me.addr; - src = this->other.addr; + spi = this->my_spi; + dst = this->my_addr; + src = this->other_addr; } else { - this->other.spi = proposal->get_spi(proposal); - spi = this->other.spi; - src = this->me.addr; - dst = this->other.addr; + this->other_spi = proposal->get_spi(proposal); + spi = this->other_spi; + src = this->my_addr; + dst = this->other_addr; } - DBG2(DBG_CHD, "adding %s %N SA", mine ? "inbound" : "outbound", + DBG2(DBG_CHD, "adding %s %N SA", in ? "inbound" : "outbound", protocol_id_names, this->protocol); - /* select encryption algo, derive key */ - if (proposal->get_algorithm(proposal, ENCRYPTION_ALGORITHM, - &this->enc_alg, &enc_size)) - { - DBG2(DBG_CHD, " using %N for encryption", - encryption_algorithm_names, this->enc_alg); - } - if (this->enc_alg != ENCR_UNDEFINED) - { - if (!enc_size) - { - enc_size = lookup_keylen(keylen_enc, this->enc_alg); - } - if (!enc_size) - { - DBG1(DBG_CHD, "no keylenth defined for %N", - encryption_algorithm_names, this->enc_alg); - return FAILED; - } - /* CCM/GCM needs additional keymat */ - switch (this->enc_alg) - { - case ENCR_AES_CCM_ICV8: - case ENCR_AES_CCM_ICV12: - case ENCR_AES_CCM_ICV16: - enc_size += 24; - break; - case ENCR_AES_GCM_ICV8: - case ENCR_AES_GCM_ICV12: - case ENCR_AES_GCM_ICV16: - enc_size += 32; - break; - default: - add_keymat = 0; - break; - } - prf_plus->allocate_bytes(prf_plus, enc_size / 8, &this->enc_key[!!mine]); - } - - /* select integrity algo, derive key */ - if (proposal->get_algorithm(proposal, INTEGRITY_ALGORITHM, - &this->int_alg, &int_size)) - { - DBG2(DBG_CHD, " using %N for integrity", - integrity_algorithm_names, this->int_alg); - } - if (this->int_alg != AUTH_UNDEFINED) - { - if (!int_size) - { - int_size = lookup_keylen(keylen_int, this->int_alg); - } - if (!enc_size) - { - DBG1(DBG_CHD, "no keylenth defined for %N", - integrity_algorithm_names, this->int_alg); - return FAILED; - } - prf_plus->allocate_bytes(prf_plus, int_size / 8, &this->int_key[!!mine]); - } - /* send SA down to the kernel */ DBG2(DBG_CHD, " SPI 0x%.8x, src %H dst %H", ntohl(spi), src, dst); if (this->ipcomp != IPCOMP_NONE) { /* we install an additional IPComp SA */ - cpi = htonl(ntohs(mine ? this->me.cpi : this->other.cpi)); + cpi = htonl(ntohs(in ? this->my_cpi : this->other_cpi)); charon->kernel_interface->add_sa(charon->kernel_interface, src, dst, cpi, IPPROTO_COMP, this->reqid, 0, 0, ENCR_UNDEFINED, chunk_empty, AUTH_UNDEFINED, chunk_empty, - mode, this->ipcomp, FALSE, mine); + mode, this->ipcomp, FALSE, in); } + proposal->get_algorithm(proposal, ENCRYPTION_ALGORITHM, &enc_alg, &size); + proposal->get_algorithm(proposal, INTEGRITY_ALGORITHM, &int_alg, &size); + soft = this->config->get_lifetime(this->config, TRUE); hard = this->config->get_lifetime(this->config, FALSE); - status = charon->kernel_interface->add_sa(charon->kernel_interface, src, dst, - spi, this->protocol, this->reqid, mine ? soft : 0, hard, - this->enc_alg, this->enc_key[!!mine], - this->int_alg, this->int_key[!!mine], - mode, IPCOMP_NONE, this->encap, mine); + status = charon->kernel_interface->add_sa(charon->kernel_interface, + src, dst, spi, this->protocol, this->reqid, + in ? soft : 0, hard, enc_alg, encr, int_alg, integ, + mode, IPCOMP_NONE, this->encap, in); now = time(NULL); this->rekey_time = now + soft; @@ -651,63 +513,70 @@ static status_t install(private_child_sa_t *this, proposal_t *proposal, return status; } -static status_t add(private_child_sa_t *this, proposal_t *proposal, - ipsec_mode_t mode, prf_plus_t *prf_plus) +/** + * Implementation of child_sa_t.add + */ +static status_t add(private_child_sa_t *this, + proposal_t *proposal, ipsec_mode_t mode, + chunk_t integ_in, chunk_t integ_out, + chunk_t encr_in, chunk_t encr_out) { - u_int32_t outbound_spi, inbound_spi; + this->proposal = proposal->clone(proposal); + this->protocol = proposal->get_protocol(proposal); - /* backup outbound spi, as alloc overwrites it */ - outbound_spi = proposal->get_spi(proposal); - - /* get SPIs inbound SAs */ + /* get SPIs for inbound SAs, write to proposal */ if (alloc_proposal(this, proposal) != SUCCESS) { return FAILED; } - inbound_spi = proposal->get_spi(proposal); - - /* install inbound SAs */ - if (install(this, proposal, mode, prf_plus, TRUE) != SUCCESS) + /* install inbound SAs using allocated SPI */ + if (install(this, proposal, mode, integ_in, encr_in, TRUE) != SUCCESS) { return FAILED; } - - /* install outbound SAs, restore spi*/ - proposal->set_spi(proposal, outbound_spi); - if (install(this, proposal, mode, prf_plus, FALSE) != SUCCESS) + /* install outbound SAs using received SPI*/ + if (install(this, this->proposal, mode, integ_out, encr_out, FALSE) != SUCCESS) { return FAILED; } - proposal->set_spi(proposal, inbound_spi); - return SUCCESS; } -static status_t update(private_child_sa_t *this, proposal_t *proposal, - ipsec_mode_t mode, prf_plus_t *prf_plus) +/** + * Implementation of child_sa_t.update + */ +static status_t update(private_child_sa_t *this, + proposal_t *proposal, ipsec_mode_t mode, + chunk_t integ_in, chunk_t integ_out, + chunk_t encr_in, chunk_t encr_out) { - u_int32_t inbound_spi; - - /* backup received spi, as install() overwrites it */ - inbound_spi = proposal->get_spi(proposal); + this->proposal = proposal->clone(proposal); + this->protocol = proposal->get_protocol(proposal); /* install outbound SAs */ - if (install(this, proposal, mode, prf_plus, FALSE) != SUCCESS) + if (install(this, proposal, mode, integ_out, encr_out, FALSE) != SUCCESS) { return FAILED; } - - /* restore spi */ - proposal->set_spi(proposal, inbound_spi); /* install inbound SAs */ - if (install(this, proposal, mode, prf_plus, TRUE) != SUCCESS) + if (install(this, proposal, mode, integ_in, encr_in, TRUE) != SUCCESS) { return FAILED; } - return SUCCESS; } +/** + * Implementation of child_sa_t.get_proposal + */ +static proposal_t* get_proposal(private_child_sa_t *this) +{ + return this->proposal; +} + +/** + * Implementation of child_sa_t.add_policies + */ static status_t add_policies(private_child_sa_t *this, linked_list_t *my_ts_list, linked_list_t *other_ts_list, ipsec_mode_t mode, protocol_id_t proto) @@ -746,15 +615,15 @@ static status_t add_policies(private_child_sa_t *this, { /* install 3 policies: out, in and forward */ status |= charon->kernel_interface->add_policy(charon->kernel_interface, - this->me.addr, this->other.addr, my_ts, other_ts, POLICY_OUT, + this->my_addr, this->other_addr, my_ts, other_ts, POLICY_OUT, this->protocol, this->reqid, high_prio, mode, this->ipcomp); status |= charon->kernel_interface->add_policy(charon->kernel_interface, - this->other.addr, this->me.addr, other_ts, my_ts, POLICY_IN, + this->other_addr, this->my_addr, other_ts, my_ts, POLICY_IN, this->protocol, this->reqid, high_prio, mode, this->ipcomp); status |= charon->kernel_interface->add_policy(charon->kernel_interface, - this->other.addr, this->me.addr, other_ts, my_ts, POLICY_FWD, + this->other_addr, this->my_addr, other_ts, my_ts, POLICY_FWD, this->protocol, this->reqid, high_prio, mode, this->ipcomp); if (status != SUCCESS) @@ -782,11 +651,7 @@ static status_t add_policies(private_child_sa_t *this, */ static linked_list_t *get_traffic_selectors(private_child_sa_t *this, bool local) { - if (local) - { - return this->my_ts; - } - return this->other_ts; + return local ? this->my_ts : this->other_ts; } /** @@ -798,8 +663,8 @@ static status_t update_hosts(private_child_sa_t *this, child_sa_state_t old; /* anything changed at all? */ - if (me->equals(me, this->me.addr) && - other->equals(other, this->other.addr) && this->encap == encap) + if (me->equals(me, this->my_addr) && + other->equals(other, this->other_addr) && this->encap == encap) { return SUCCESS; } @@ -813,24 +678,24 @@ static status_t update_hosts(private_child_sa_t *this, { /* update our (initator) IPComp SA */ charon->kernel_interface->update_sa(charon->kernel_interface, - htonl(ntohs(this->me.cpi)), IPPROTO_COMP, - this->other.addr, this->me.addr, other, me, FALSE); + htonl(ntohs(this->my_cpi)), IPPROTO_COMP, + this->other_addr, this->my_addr, other, me, FALSE); /* update his (responder) IPComp SA */ charon->kernel_interface->update_sa(charon->kernel_interface, - htonl(ntohs(this->other.cpi)), IPPROTO_COMP, - this->me.addr, this->other.addr, me, other, FALSE); + htonl(ntohs(this->other_cpi)), IPPROTO_COMP, + this->my_addr, this->other_addr, me, other, FALSE); } /* update our (initator) SA */ - charon->kernel_interface->update_sa(charon->kernel_interface, this->me.spi, - this->protocol, this->other.addr, this->me.addr, other, me, encap); + charon->kernel_interface->update_sa(charon->kernel_interface, this->my_spi, + this->protocol, this->other_addr, this->my_addr, other, me, encap); /* update his (responder) SA */ - charon->kernel_interface->update_sa(charon->kernel_interface, this->other.spi, - this->protocol, this->me.addr, this->other.addr, me, other, encap); + charon->kernel_interface->update_sa(charon->kernel_interface, this->other_spi, + this->protocol, this->my_addr, this->other_addr, me, other, encap); /* update policies */ - if (!me->ip_equals(me, this->me.addr) || - !other->ip_equals(other, this->other.addr)) + if (!me->ip_equals(me, this->my_addr) || + !other->ip_equals(other, this->other_addr)) { enumerator_t *enumerator; traffic_selector_t *my_ts, *other_ts; @@ -848,13 +713,13 @@ static status_t update_hosts(private_child_sa_t *this, other_ts, my_ts, POLICY_FWD); /* check whether we have to update a "dynamic" traffic selector */ - if (!me->ip_equals(me, this->me.addr) && - my_ts->is_host(my_ts, this->me.addr)) + if (!me->ip_equals(me, this->my_addr) && + my_ts->is_host(my_ts, this->my_addr)) { my_ts->set_address(my_ts, me); } - if (!other->ip_equals(other, this->other.addr) && - other_ts->is_host(other_ts, this->other.addr)) + if (!other->ip_equals(other, this->other_addr) && + other_ts->is_host(other_ts, this->other_addr)) { other_ts->set_address(other_ts, other); } @@ -882,15 +747,15 @@ static status_t update_hosts(private_child_sa_t *this, } /* apply hosts */ - if (!me->equals(me, this->me.addr)) + if (!me->equals(me, this->my_addr)) { - this->me.addr->destroy(this->me.addr); - this->me.addr = me->clone(me); + this->my_addr->destroy(this->my_addr); + this->my_addr = me->clone(me); } - if (!other->equals(other, this->other.addr)) + if (!other->equals(other, this->other_addr)) { - this->other.addr->destroy(this->other.addr); - this->other.addr = other->clone(other); + this->other_addr->destroy(this->other_addr); + this->other_addr = other->clone(other); } set_state(this, old); @@ -905,7 +770,7 @@ static void activate_ipcomp(private_child_sa_t *this, ipcomp_transform_t ipcomp, u_int16_t other_cpi) { this->ipcomp = ipcomp; - this->other.cpi = other_cpi; + this->other_cpi = other_cpi; } /** @@ -916,10 +781,10 @@ static u_int16_t allocate_cpi(private_child_sa_t *this) if (!this->cpi_allocated) { charon->kernel_interface->get_cpi(charon->kernel_interface, - this->other.addr, this->me.addr, this->reqid, &this->me.cpi); + this->other_addr, this->my_addr, this->reqid, &this->my_cpi); this->cpi_allocated = TRUE; } - return this->me.cpi; + return this->my_cpi; } /** @@ -933,35 +798,35 @@ static void destroy(private_child_sa_t *this) set_state(this, CHILD_DESTROYING); /* delete SAs in the kernel, if they are set up */ - if (this->me.spi) + if (this->my_spi) { charon->kernel_interface->del_sa(charon->kernel_interface, - this->me.addr, this->me.spi, this->protocol); + this->my_addr, this->my_spi, this->protocol); } - if (this->alloc_esp_spi && this->alloc_esp_spi != this->me.spi) + if (this->alloc_esp_spi && this->alloc_esp_spi != this->my_spi) { charon->kernel_interface->del_sa(charon->kernel_interface, - this->me.addr, this->alloc_esp_spi, PROTO_ESP); + this->my_addr, this->alloc_esp_spi, PROTO_ESP); } - if (this->alloc_ah_spi && this->alloc_ah_spi != this->me.spi) + if (this->alloc_ah_spi && this->alloc_ah_spi != this->my_spi) { charon->kernel_interface->del_sa(charon->kernel_interface, - this->me.addr, this->alloc_ah_spi, PROTO_AH); + this->my_addr, this->alloc_ah_spi, PROTO_AH); } - if (this->other.spi) + if (this->other_spi) { charon->kernel_interface->del_sa(charon->kernel_interface, - this->other.addr, this->other.spi, this->protocol); + this->other_addr, this->other_spi, this->protocol); } - if (this->me.cpi) + if (this->my_cpi) { charon->kernel_interface->del_sa(charon->kernel_interface, - this->me.addr, htonl(ntohs(this->me.cpi)), IPPROTO_COMP); + this->my_addr, htonl(ntohs(this->my_cpi)), IPPROTO_COMP); } - if (this->other.cpi) + if (this->other_cpi) { charon->kernel_interface->del_sa(charon->kernel_interface, - this->other.addr, htonl(ntohs(this->other.cpi)), IPPROTO_COMP); + this->other_addr, htonl(ntohs(this->other_cpi)), IPPROTO_COMP); } /* delete all policies in the kernel */ @@ -977,14 +842,11 @@ static void destroy(private_child_sa_t *this) } enumerator->destroy(enumerator); - chunk_clear(&this->enc_key[0]); - chunk_clear(&this->enc_key[1]); - chunk_clear(&this->int_key[0]); - chunk_clear(&this->int_key[1]); this->my_ts->destroy_offset(this->my_ts, offsetof(traffic_selector_t, destroy)); this->other_ts->destroy_offset(this->other_ts, offsetof(traffic_selector_t, destroy)); - this->me.addr->destroy(this->me.addr); - this->other.addr->destroy(this->other.addr); + this->my_addr->destroy(this->my_addr); + this->other_addr->destroy(this->other_addr); + DESTROY_IF(this->proposal); this->config->destroy(this->config); free(this); } @@ -1007,13 +869,12 @@ child_sa_t * child_sa_create(host_t *me, host_t* other, this->public.get_mode = (ipsec_mode_t(*)(child_sa_t*))get_mode; this->public.get_ipcomp = (ipcomp_transform_t(*)(child_sa_t*))get_ipcomp; this->public.has_encap = (bool(*)(child_sa_t*))has_encap; - this->public.get_encryption = (encryption_algorithm_t(*)(child_sa_t*, bool, chunk_t*))get_encryption; - this->public.get_integrity = (integrity_algorithm_t(*)(child_sa_t*, bool, chunk_t*))get_integrity; this->public.get_lifetime = (u_int32_t(*)(child_sa_t*, bool))get_lifetime; this->public.get_usetime = (u_int32_t(*)(child_sa_t*, bool))get_usetime; this->public.alloc = (status_t(*)(child_sa_t*,linked_list_t*))alloc; - this->public.add = (status_t(*)(child_sa_t*,proposal_t*,ipsec_mode_t,prf_plus_t*))add; - this->public.update = (status_t(*)(child_sa_t*,proposal_t*,ipsec_mode_t,prf_plus_t*))update; + this->public.add = (status_t(*)(child_sa_t*,proposal_t*,ipsec_mode_t,chunk_t,chunk_t,chunk_t,chunk_t))add; + this->public.update = (status_t(*)(child_sa_t*,proposal_t*,ipsec_mode_t,chunk_t,chunk_t,chunk_t,chunk_t))update; + this->public.get_proposal = (proposal_t*(*)(child_sa_t*))get_proposal; this->public.update_hosts = (status_t (*)(child_sa_t*,host_t*,host_t*,host_t*,bool))update_hosts; this->public.add_policies = (status_t (*)(child_sa_t*, linked_list_t*,linked_list_t*,ipsec_mode_t,protocol_id_t))add_policies; this->public.get_traffic_selectors = (linked_list_t*(*)(child_sa_t*,bool))get_traffic_selectors; @@ -1026,12 +887,12 @@ child_sa_t * child_sa_create(host_t *me, host_t* other, this->public.destroy = (void(*)(child_sa_t*))destroy; /* private data */ - this->me.addr = me->clone(me); - this->other.addr = other->clone(other); - this->me.spi = 0; - this->me.cpi = 0; - this->other.spi = 0; - this->other.cpi = 0; + this->my_addr = me->clone(me); + this->other_addr = other->clone(other); + this->my_spi = 0; + this->my_cpi = 0; + this->other_spi = 0; + this->other_cpi = 0; this->alloc_ah_spi = 0; this->alloc_esp_spi = 0; this->encap = encap; @@ -1040,14 +901,11 @@ child_sa_t * child_sa_create(host_t *me, host_t* other, this->state = CHILD_CREATED; /* reuse old reqid if we are rekeying an existing CHILD_SA */ this->reqid = rekey ? rekey : ++reqid; - this->enc_alg = ENCR_UNDEFINED; - this->enc_key[0] = this->enc_key[1] = chunk_empty; - this->int_alg = AUTH_UNDEFINED; - this->int_key[0] = this->int_key[1] = chunk_empty; this->my_ts = linked_list_create(); this->other_ts = linked_list_create(); this->protocol = PROTO_NONE; this->mode = MODE_TUNNEL; + this->proposal = NULL; this->config = config; config->get_ref(config); diff --git a/src/charon/sa/child_sa.h b/src/charon/sa/child_sa.h index d76e23af7..3e138143d 100644 --- a/src/charon/sa/child_sa.h +++ b/src/charon/sa/child_sa.h @@ -168,24 +168,6 @@ struct child_sa_t { */ bool (*has_encap)(child_sa_t *this); - /** - * Get the IPsec encryption key. - * - * @param inbound TRUE for inbound, FALSE for outbound key - * @param key chunk where to write key pointer and length - * @return encryption algorithm - */ - encryption_algorithm_t (*get_encryption)(child_sa_t *this, bool inbound, - chunk_t *key); - /** - * Get the IPsec integrity. - * - * @param inbound TRUE for inbound, FALSE for outbound key - * @param key chunk where to write key pointer and length - * @return integrity algorithm - */ - integrity_algorithm_t (*get_integrity)(child_sa_t *this, bool inbound, - chunk_t *key); /** * Get the lifetime of the CHILD_SA. * @@ -220,12 +202,15 @@ struct child_sa_t { * * @param proposal proposal for which SPIs are allocated * @param mode mode for the CHILD_SA - * @param prf_plus key material to use for key derivation + * @param integ_in integrity key for inbound traffic + * @param integ_out integrity key for outbound traffic + * @param encr_in encryption key for inbound traffic + * @param enc_out encryption key for outbound traffic * @return SUCCESS or FAILED */ status_t (*add)(child_sa_t *this, proposal_t *proposal, ipsec_mode_t mode, - prf_plus_t *prf_plus); - + chunk_t integ_in, chunk_t integ_out, + chunk_t encr_in, chunk_t encr_out); /** * Install the kernel SAs for a proposal, after SPIs have been allocated. * @@ -233,12 +218,22 @@ struct child_sa_t { * * @param proposal proposal for which SPIs are allocated * @param mode mode for the CHILD_SA - * @param prf_plus key material to use for key derivation + * @param integ_in integrity key for inbound traffic + * @param integ_out integrity key for outbound traffic + * @param encr_in encryption key for inbound traffic + * @param enc_out encryption key for outbound traffic * @return SUCCESS or FAILED */ status_t (*update)(child_sa_t *this, proposal_t *proposal, ipsec_mode_t mode, - prf_plus_t *prf_plus); - + chunk_t integ_in, chunk_t integ_out, + chunk_t encr_in, chunk_t encr_out); + /** + * Get the selected proposal passed to add()/update(). + * + * @return selected proposal + */ + proposal_t* (*get_proposal)(child_sa_t *this); + /** * Update the hosts in the kernel SAs and policies. * diff --git a/src/charon/sa/keymat.c b/src/charon/sa/keymat.c index cc75a20a7..08bf55cff 100644 --- a/src/charon/sa/keymat.c +++ b/src/charon/sa/keymat.c @@ -83,6 +83,58 @@ struct private_keymat_t { proposal_t *proposal; }; +typedef struct keylen_entry_t keylen_entry_t; + +/** + * Implicit key length for an algorithm + */ +struct keylen_entry_t { + /** IKEv2 algorithm identifier */ + int algo; + /** key length in bits */ + int len; +}; + +#define END_OF_LIST -1 + +/** + * Keylen for encryption algos + */ +keylen_entry_t keylen_enc[] = { + {ENCR_DES, 64}, + {ENCR_3DES, 192}, + {END_OF_LIST, 0} +}; + +/** + * Keylen for integrity algos + */ +keylen_entry_t keylen_int[] = { + {AUTH_HMAC_MD5_96, 128}, + {AUTH_HMAC_SHA1_96, 160}, + {AUTH_HMAC_SHA2_256_128, 256}, + {AUTH_HMAC_SHA2_384_192, 384}, + {AUTH_HMAC_SHA2_512_256, 512}, + {AUTH_AES_XCBC_96, 128}, + {END_OF_LIST, 0} +}; + +/** + * Lookup key length of an algorithm + */ +static int lookup_keylen(keylen_entry_t *list, int algo) +{ + while (list->algo != END_OF_LIST) + { + if (algo == list->algo) + { + return list->len; + } + list++; + } + return 0; +} + /** * Implementation of keymat_t.create_dh */ @@ -95,9 +147,10 @@ static diffie_hellman_t* create_dh(private_keymat_t *this, /** * Implementation of keymat_t.derive_keys */ -static bool derive_keys(private_keymat_t *this, proposal_t *proposal, - diffie_hellman_t *dh, chunk_t nonce_i, chunk_t nonce_r, - ike_sa_id_t *id, private_keymat_t *rekey) +static bool derive_ike_keys(private_keymat_t *this, proposal_t *proposal, + diffie_hellman_t *dh, chunk_t nonce_i, + chunk_t nonce_r, ike_sa_id_t *id, + private_keymat_t *rekey) { chunk_t skeyseed, key, secret, full_nonce, fixed_nonce, prf_plus_seed; chunk_t spi_i, spi_r; @@ -307,6 +360,99 @@ static bool derive_keys(private_keymat_t *this, proposal_t *proposal, return TRUE; } +/** + * Implementation of keymat_t.derive_child_keys + */ +static bool derive_child_keys(private_keymat_t *this, + proposal_t *proposal, diffie_hellman_t *dh, + chunk_t nonce_i, chunk_t nonce_r, + chunk_t *encr_i, chunk_t *integ_i, + chunk_t *encr_r, chunk_t *integ_r) +{ + u_int16_t enc_alg, int_alg, enc_size, int_size; + chunk_t seed, secret = chunk_empty; + prf_plus_t *prf_plus; + + if (dh) + { + if (dh->get_shared_secret(dh, &secret) != SUCCESS) + { + return FALSE; + } + DBG4(DBG_CHD, "DH secret %B", &secret); + } + seed = chunk_cata("mcc", secret, nonce_i, nonce_r); + DBG4(DBG_CHD, "seed %B", &seed); + + if (proposal->get_algorithm(proposal, ENCRYPTION_ALGORITHM, + &enc_alg, &enc_size)) + { + DBG2(DBG_CHD, " using %N for encryption", + encryption_algorithm_names, enc_alg); + + if (!enc_size) + { + enc_size = lookup_keylen(keylen_enc, enc_alg); + } + if (!enc_size) + { + DBG1(DBG_CHD, "no keylenth defined for %N", + encryption_algorithm_names, enc_alg); + return FALSE; + } + /* to bytes */ + enc_size /= 8; + + /* CCM/GCM needs additional bytes */ + switch (enc_alg) + { + case ENCR_AES_CCM_ICV8: + case ENCR_AES_CCM_ICV12: + case ENCR_AES_CCM_ICV16: + enc_size += 3; + break; + case ENCR_AES_GCM_ICV8: + case ENCR_AES_GCM_ICV12: + case ENCR_AES_GCM_ICV16: + enc_size += 4; + break; + default: + break; + } + } + + if (proposal->get_algorithm(proposal, INTEGRITY_ALGORITHM, + &int_alg, &int_size)) + { + DBG2(DBG_CHD, " using %N for integrity", + integrity_algorithm_names, int_alg); + + if (!int_size) + { + int_size = lookup_keylen(keylen_int, int_alg); + } + if (!int_size) + { + DBG1(DBG_CHD, "no keylenth defined for %N", + integrity_algorithm_names, int_alg); + return FALSE; + } + /* to bytes */ + int_size /= 8; + } + + prf_plus = prf_plus_create(this->child_prf, seed); + + prf_plus->allocate_bytes(prf_plus, enc_size, encr_i); + prf_plus->allocate_bytes(prf_plus, int_size, integ_i); + prf_plus->allocate_bytes(prf_plus, enc_size, encr_r); + prf_plus->allocate_bytes(prf_plus, int_size, integ_r); + + prf_plus->destroy(prf_plus); + + return TRUE; +} + /** * Implementation of keymat_t.get_proposal */ @@ -331,14 +477,6 @@ static crypter_t* get_crypter(private_keymat_t *this, bool in) return in ? this->crypter_in : this->crypter_out; } -/** - * Implementation of keymat_t.get_child_prf - */ -static prf_t* get_child_prf(private_keymat_t *this) -{ - return this->child_prf; -} - /** * Implementation of keymat_t.get_auth_octets */ @@ -426,11 +564,11 @@ keymat_t *keymat_create(bool initiator) private_keymat_t *this = malloc_thing(private_keymat_t); this->public.create_dh = (diffie_hellman_t*(*)(keymat_t*, diffie_hellman_group_t group))create_dh; - this->public.derive_keys = (bool(*)(keymat_t*, proposal_t *proposal, diffie_hellman_t *dh, chunk_t nonce_i, chunk_t nonce_r, ike_sa_id_t *id, keymat_t *rekey))derive_keys; + this->public.derive_ike_keys = (bool(*)(keymat_t*, proposal_t *proposal, diffie_hellman_t *dh, chunk_t nonce_i, chunk_t nonce_r, ike_sa_id_t *id, keymat_t *rekey))derive_ike_keys; + this->public.derive_child_keys = (bool(*)(keymat_t*, proposal_t *proposal, diffie_hellman_t *dh, chunk_t nonce_i, chunk_t nonce_r, chunk_t *encr_i, chunk_t *integ_i, chunk_t *encr_r, chunk_t *integ_r))derive_child_keys; this->public.get_proposal = (proposal_t*(*)(keymat_t*))get_proposal; this->public.get_signer = (signer_t*(*)(keymat_t*, bool in))get_signer; this->public.get_crypter = (crypter_t*(*)(keymat_t*, bool in))get_crypter; - this->public.get_child_prf = (prf_t*(*)(keymat_t*))get_child_prf; this->public.get_auth_octets = (chunk_t(*)(keymat_t *, bool verify, chunk_t ike_sa_init, chunk_t nonce, identification_t *id))get_auth_octets; this->public.get_psk_sig = (chunk_t(*)(keymat_t*, bool verify, chunk_t ike_sa_init, chunk_t nonce, chunk_t secret, identification_t *id))get_psk_sig; this->public.destroy = (void(*)(keymat_t*))destroy; diff --git a/src/charon/sa/keymat.h b/src/charon/sa/keymat.h index d23486d9a..835ad4593 100644 --- a/src/charon/sa/keymat.h +++ b/src/charon/sa/keymat.h @@ -43,7 +43,7 @@ struct keymat_t { * * The diffie hellman is either for IKE negotiation/rekeying or * CHILD_SA rekeying (using PFS). The resulting DH object must be passed - * to derive_ike_keys or to derive_child_keys and destroyed after use + * to derive_keys or to derive_child_keys and destroyed after use * * @param group diffie hellman group * @return DH object, NULL if group not supported @@ -51,18 +51,45 @@ struct keymat_t { diffie_hellman_t* (*create_dh)(keymat_t *this, diffie_hellman_group_t group); /** - * Derive keys from the shared secret. + * Derive keys for the IKE_SA. + * + * These keys are not handed out, but are used by the associated signers, + * crypters and authentication functions. * * @param proposal selected algorithms + * @param dh diffie hellman key allocated by create_dh() * @param nonce_i initiators nonce value * @param nonce_r responders nonce value * @param id IKE_SA identifier * @param rekey keymat of old SA if we are rekeying * @return TRUE on success */ - bool (*derive_keys)(keymat_t *this, proposal_t *proposal, - diffie_hellman_t *dh, chunk_t nonce_i, chunk_t nonce_r, - ike_sa_id_t *id, keymat_t *rekey); + bool (*derive_ike_keys)(keymat_t *this, proposal_t *proposal, + diffie_hellman_t *dh, chunk_t nonce_i, + chunk_t nonce_r, ike_sa_id_t *id, keymat_t *rekey); + /** + * Derive keys for a CHILD_SA. + * + * The keys for the CHILD_SA are allocated in the integ and encr chunks. + * An implementation might hand out encrypted keys only, which are + * decrypted in the kernel before use. + * If no PFS is used for the CHILD_SA, dh can be NULL. + * + * @param proposal selected algorithms + * @param dh diffie hellman key allocated by create_dh(), or NULL + * @param nonce_i initiators nonce value + * @param nonce_r responders nonce value + * @param encr_i chunk to write initiators encryption key to + * @param integ_i chunk to write initiators integrity key to + * @param encr_r chunk to write responders encryption key to + * @param integ_r chunk to write responders integrity key to + * @return TRUE on success + */ + bool (*derive_child_keys)(keymat_t *this, + proposal_t *proposal, diffie_hellman_t *dh, + chunk_t nonce_i, chunk_t nonce_r, + chunk_t *encr_i, chunk_t *integ_i, + chunk_t *encr_r, chunk_t *integ_r); /** * Get a signer to sign/verify IKE messages. * @@ -80,14 +107,7 @@ struct keymat_t { crypter_t* (*get_crypter)(keymat_t *this, bool in); /** - * Get a keyed PRF to derive keymat for children. - * - * @return PRF to derive CHILD_SA keymat from - */ - prf_t* (*get_child_prf)(keymat_t *this); - - /** - * Get the selected proposal passed to derive_keys(). + * Get the selected proposal passed to derive_ike_keys(). * * @return selected proposal */ diff --git a/src/charon/sa/tasks/child_create.c b/src/charon/sa/tasks/child_create.c index 8f2329c3a..0f1a47bfe 100644 --- a/src/charon/sa/tasks/child_create.c +++ b/src/charon/sa/tasks/child_create.c @@ -96,6 +96,11 @@ struct private_child_create_t { */ diffie_hellman_group_t dh_group; + /** + * IKE_SAs keymat + */ + keymat_t *keymat; + /** * mode the new CHILD_SA uses (transport/tunnel/beet) */ @@ -191,12 +196,10 @@ static bool ts_list_is_host(linked_list_t *list, host_t *host) */ static status_t select_and_install(private_child_create_t *this, bool no_dh) { - prf_plus_t *prf_plus; status_t status; - chunk_t nonce_i, nonce_r, secret, seed; + chunk_t encr_i, integ_i, encr_r, integ_r; linked_list_t *my_ts, *other_ts; host_t *me, *other, *other_vip, *my_vip; - keymat_t *keymat; if (this->proposals == NULL) { @@ -209,21 +212,6 @@ static status_t select_and_install(private_child_create_t *this, bool no_dh) return NOT_FOUND; } - if (this->initiator) - { - nonce_i = this->my_nonce; - nonce_r = this->other_nonce; - my_ts = this->tsi; - other_ts = this->tsr; - } - else - { - nonce_r = this->my_nonce; - nonce_i = this->other_nonce; - my_ts = this->tsr; - other_ts = this->tsi; - } - me = this->ike_sa->get_my_host(this->ike_sa); other = this->ike_sa->get_other_host(this->ike_sa); my_vip = this->ike_sa->get_virtual_ip(this->ike_sa, TRUE); @@ -266,6 +254,16 @@ static status_t select_and_install(private_child_create_t *this, bool no_dh) other_vip = other; } + if (this->initiator) + { + my_ts = this->tsi; + other_ts = this->tsr; + } + else + { + my_ts = this->tsr; + other_ts = this->tsi; + } my_ts = this->config->get_traffic_selectors(this->config, TRUE, my_ts, my_vip); other_ts = this->config->get_traffic_selectors(this->config, FALSE, other_ts, @@ -323,21 +321,6 @@ static status_t select_and_install(private_child_create_t *this, bool no_dh) } } - if (this->dh) - { - if (this->dh->get_shared_secret(this->dh, &secret) != SUCCESS) - { - DBG1(DBG_IKE, "DH exchange incomplete"); - return FAILED; - } - DBG3(DBG_IKE, "DH secret %B", &secret); - seed = chunk_cata("mcc", secret, nonce_i, nonce_r); - } - else - { - seed = chunk_cata("cc", nonce_i, nonce_r); - } - if (this->ipcomp != IPCOMP_NONE) { this->child_sa->activate_ipcomp(this->child_sa, this->ipcomp, @@ -352,19 +335,32 @@ static status_t select_and_install(private_child_create_t *this, bool no_dh) return NOT_FOUND; } - keymat = this->ike_sa->get_keymat(this->ike_sa); - prf_plus = prf_plus_create(keymat->get_child_prf(keymat), seed); + status = FAILED; if (this->initiator) { - status = this->child_sa->update(this->child_sa, this->proposal, - this->mode, prf_plus); + if (this->keymat->derive_child_keys(this->keymat, this->proposal, + this->dh, this->my_nonce, this->other_nonce, + &encr_i, &integ_i, &encr_r, &integ_r)) + { + status = this->child_sa->update(this->child_sa, this->proposal, + this->mode, integ_r, integ_i, encr_r, encr_i); + } } else { - status = this->child_sa->add(this->child_sa, this->proposal, - this->mode, prf_plus); + if (this->keymat->derive_child_keys(this->keymat, this->proposal, + this->dh, this->other_nonce, this->my_nonce, + &encr_i, &integ_i, &encr_r, &integ_r)) + { + status = this->child_sa->add(this->child_sa, this->proposal, + this->mode, integ_i, integ_r, encr_i, encr_r); + } } - prf_plus->destroy(prf_plus); + /* TODO: invoke bus method with key mat */ + chunk_clear(&integ_i); + chunk_clear(&integ_r); + chunk_clear(&encr_i); + chunk_clear(&encr_r); if (status != SUCCESS) { @@ -494,7 +490,7 @@ static void process_payloads(private_child_create_t *this, message_t *message) if (!this->initiator) { this->dh_group = ke_payload->get_dh_group_number(ke_payload); - this->dh = lib->crypto->create_dh(lib->crypto, this->dh_group); + this->dh = this->keymat->create_dh(this->keymat, this->dh_group); } if (this->dh) { @@ -648,7 +644,7 @@ static status_t build_i(private_child_create_t *this, message_t *message) if (this->dh_group != MODP_NONE) { - this->dh = lib->crypto->create_dh(lib->crypto, this->dh_group); + this->dh = this->keymat->create_dh(this->keymat, this->dh_group); } if (this->config->use_ipcomp(this->config)) { @@ -1131,6 +1127,7 @@ child_create_t *child_create_create(ike_sa_t *ike_sa, child_cfg_t *config) this->tsr = NULL; this->dh = NULL; this->dh_group = MODP_NONE; + this->keymat = ike_sa->get_keymat(ike_sa); this->child_sa = NULL; this->mode = MODE_TUNNEL; this->ipcomp = IPCOMP_NONE; diff --git a/src/charon/sa/tasks/ike_init.c b/src/charon/sa/tasks/ike_init.c index bbeda15c6..522d1d70a 100644 --- a/src/charon/sa/tasks/ike_init.c +++ b/src/charon/sa/tasks/ike_init.c @@ -415,7 +415,7 @@ static status_t build_r(private_ike_init_t *this, message_t *message) id->set_initiator_spi(id, this->proposal->get_spi(this->proposal)); old_keymat = this->old_sa->get_keymat(this->old_sa); } - if (!this->keymat->derive_keys(this->keymat, this->proposal, this->dh, + if (!this->keymat->derive_ike_keys(this->keymat, this->proposal, this->dh, this->other_nonce, this->my_nonce, id, old_keymat)) { DBG1(DBG_IKE, "key derivation failed"); @@ -522,7 +522,7 @@ static status_t process_i(private_ike_init_t *this, message_t *message) id->set_responder_spi(id, this->proposal->get_spi(this->proposal)); old_keymat = this->old_sa->get_keymat(this->old_sa); } - if (!this->keymat->derive_keys(this->keymat, this->proposal, this->dh, + if (!this->keymat->derive_ike_keys(this->keymat, this->proposal, this->dh, this->my_nonce, this->other_nonce, id, old_keymat)) { DBG1(DBG_IKE, "key derivation failed");