rv->proposal_num = proposal->proposal_num;
rv->protocol_id = proposal->protocol_id;
RAND_bytes ((u8 *) & rv->spi, sizeof (rv->spi));
+ if (rv->protocol_id != IKEV2_PROTOCOL_IKE)
+ rv->spi &= 0xffffffff;
goto done;
}
else
}
static void
-ikev2_calc_keys (ikev2_sa_t * sa)
+ikev2_calc_keys_internal (ikev2_sa_t *sa, u8 *skeyseed)
{
u8 *tmp;
/* calculate SKEYSEED = prf(Ni | Nr, g^ir) */
- u8 *skeyseed = 0;
u8 *s = 0;
u16 integ_key_len = 0, salt_len = 0;
ikev2_sa_transform_t *tr_encr, *tr_prf, *tr_integ;
vec_append (s, sa->i_nonce);
vec_append (s, sa->r_nonce);
- skeyseed = ikev2_calc_prf (tr_prf, s, sa->dh_shared_key);
/* Calculate S = Ni | Nr | SPIi | SPIr */
u64 *spi;
salt_len * 2;
keymat = ikev2_calc_prfplus (tr_prf, skeyseed, s, len);
- vec_free (skeyseed);
vec_free (s);
int pos = 0;
sa->keys_generated = 1;
}
+static void
+ikev2_calc_keys_rekey (ikev2_sa_t *sa_new, ikev2_sa_t *sa_old)
+{
+ u8 *s = 0, *skeyseed = 0;
+ ikev2_sa_transform_t *tr_prf =
+ ikev2_sa_get_td_for_type (sa_old->r_proposals, IKEV2_TRANSFORM_TYPE_PRF);
+
+ vec_append (s, sa_new->dh_shared_key);
+ vec_append (s, sa_new->i_nonce);
+ vec_append (s, sa_new->r_nonce);
+ skeyseed = ikev2_calc_prf (tr_prf, sa_old->sk_d, s);
+
+ ikev2_calc_keys_internal (sa_new, skeyseed);
+
+ vec_free (skeyseed);
+ vec_free (s);
+}
+
+static void
+ikev2_calc_keys (ikev2_sa_t *sa)
+{
+ u8 *s = 0, *skeyseed = 0;
+ ikev2_sa_transform_t *tr_prf =
+ ikev2_sa_get_td_for_type (sa->r_proposals, IKEV2_TRANSFORM_TYPE_PRF);
+
+ vec_append (s, sa->i_nonce);
+ vec_append (s, sa->r_nonce);
+ skeyseed = ikev2_calc_prf (tr_prf, s, sa->dh_shared_key);
+
+ ikev2_calc_keys_internal (sa, skeyseed);
+
+ vec_free (skeyseed);
+ vec_free (s);
+}
+
static void
ikev2_calc_child_keys (ikev2_sa_t *sa, ikev2_child_sa_t *child, u8 kex)
{
return 1;
}
+static void
+ikev2_complete_sa_rekey (ikev2_sa_t *sa_new, ikev2_sa_t *sa_old,
+ ikev2_sa_rekey_t *sa_rekey)
+{
+ sa_new->del = 0;
+ sa_new->rekey = 0;
+ sa_new->new_child = 0;
+ sa_new->sa_rekey = 0;
+ sa_new->last_sa_init_req_packet_data = 0;
+ sa_new->last_sa_init_res_packet_data = 0;
+ sa_new->last_msg_id = ~0;
+ sa_new->last_res_packet_data = 0;
+ sa_new->last_init_msg_id = 0;
+ clib_memset (&sa_new->stats, 0, sizeof (sa_new->stats));
+
+ sa_new->ispi = sa_rekey->ispi;
+ sa_new->rspi = sa_rekey->rspi;
+ sa_new->i_nonce = sa_rekey->i_nonce;
+ sa_new->r_nonce = sa_rekey->r_nonce;
+ sa_new->dh_group = sa_rekey->dh_group;
+ sa_new->dh_shared_key = sa_rekey->dh_shared_key;
+ sa_new->dh_private_key = sa_rekey->dh_private_key;
+ sa_new->i_dh_data = sa_rekey->i_dh_data;
+ sa_new->r_dh_data = sa_rekey->r_dh_data;
+ sa_new->i_proposals = sa_rekey->i_proposals;
+ sa_new->r_proposals = sa_rekey->r_proposals;
+
+ sa_new->sk_d = 0;
+ sa_new->sk_ai = 0;
+ sa_new->sk_ar = 0;
+ sa_new->sk_ei = 0;
+ sa_new->sk_er = 0;
+ sa_new->sk_pi = 0;
+ sa_new->sk_pr = 0;
+ ikev2_calc_keys_rekey (sa_new, sa_old);
+
+ sa_new->i_auth.data = vec_dup (sa_old->i_auth.data);
+ sa_new->i_auth.key = sa_old->i_auth.key;
+ if (sa_new->i_auth.key)
+ EVP_PKEY_up_ref (sa_new->i_auth.key);
+
+ sa_new->r_auth.data = vec_dup (sa_old->r_auth.data);
+ sa_new->r_auth.key = sa_old->r_auth.key;
+ if (sa_new->r_auth.key)
+ EVP_PKEY_up_ref (sa_new->r_auth.key);
+
+ sa_new->i_id.data = vec_dup (sa_old->i_id.data);
+ sa_new->r_id.data = vec_dup (sa_old->r_id.data);
+
+ sa_old->is_tun_itf_set = 0;
+ sa_old->tun_itf = ~0;
+ sa_old->old_id_expiration = 0;
+ sa_old->current_remote_id_mask = 0;
+ sa_old->old_remote_id = 0;
+ sa_old->old_remote_id_present = 0;
+ sa_old->childs = 0;
+ sa_old->sw_if_index = ~0;
+}
+
+static void
+ikev2_process_sa_rekey (ikev2_sa_t *sa_new, ikev2_sa_t *sa_old,
+ ikev2_sa_rekey_t *sa_rekey)
+{
+ ikev2_sa_transform_t *tr;
+
+ if (ikev2_generate_sa_init_data (sa_new) != IKEV2_GENERATE_SA_INIT_OK)
+ {
+ sa_rekey->notify_type = IKEV2_NOTIFY_MSG_INVALID_KE_PAYLOAD;
+ return;
+ }
+
+ sa_new->r_proposals =
+ ikev2_select_proposal (sa_new->i_proposals, IKEV2_PROTOCOL_IKE);
+
+ tr = ikev2_sa_get_td_for_type (sa_new->r_proposals, IKEV2_TRANSFORM_TYPE_DH);
+ if (!tr || tr->dh_type != sa_new->dh_group)
+ {
+ sa_rekey->notify_type = IKEV2_NOTIFY_MSG_INVALID_KE_PAYLOAD;
+ return;
+ }
+
+ sa_rekey->notify_type = 0;
+ sa_rekey->ispi = sa_new->i_proposals[0].spi;
+ sa_rekey->rspi = sa_new->r_proposals[0].spi;
+ sa_rekey->i_nonce = sa_new->i_nonce;
+ sa_rekey->r_nonce = sa_new->r_nonce;
+ sa_rekey->dh_group = sa_new->dh_group;
+ sa_rekey->dh_shared_key = sa_new->dh_shared_key;
+ sa_rekey->dh_private_key = sa_new->dh_private_key;
+ sa_rekey->i_dh_data = sa_new->i_dh_data;
+ sa_rekey->r_dh_data = sa_new->r_dh_data;
+ sa_rekey->i_proposals = sa_new->i_proposals;
+ sa_rekey->r_proposals = sa_new->r_proposals;
+
+ sa_new->i_nonce = 0;
+ sa_new->r_nonce = 0;
+ sa_new->dh_shared_key = 0;
+ sa_new->dh_private_key = 0;
+ sa_new->i_dh_data = 0;
+ sa_new->r_dh_data = 0;
+ sa_new->i_proposals = 0;
+ sa_new->r_proposals = 0;
+}
+
static int
ikev2_process_create_child_sa_req (vlib_main_t * vm,
ikev2_sa_t * sa, ike_header_t * ike,
p += plen;
}
- if (!proposal || proposal->protocol_id != IKEV2_PROTOCOL_ESP || !nonce)
+ if (!proposal || !nonce ||
+ (proposal->protocol_id != IKEV2_PROTOCOL_ESP &&
+ proposal->protocol_id != IKEV2_PROTOCOL_IKE))
goto cleanup_and_exit;
if (sa->is_initiator)
vec_free (tsi);
}
}
+ else if (proposal[0].protocol_id == IKEV2_PROTOCOL_IKE)
+ {
+ ikev2_sa_rekey_t *sa_rekey;
+ if (tsi || tsr)
+ goto cleanup_and_exit;
+ sar.i_proposals = proposal;
+ vec_add (sar.i_nonce, nonce, nonce_len);
+ vec_add2 (sa->sa_rekey, sa_rekey, 1);
+ ikev2_process_sa_rekey (&sar, sa, sa_rekey);
+ }
else
{
/* create new child SA */
vec_free (data);
}
+static void
+ikev2_add_notify_payload (ikev2_sa_t *sa, ikev2_payload_chain_t *chain,
+ u16 notify_type)
+{
+ if (notify_type == IKEV2_NOTIFY_MSG_INVALID_KE_PAYLOAD)
+ ikev2_add_invalid_ke_payload (sa, chain);
+ else
+ ikev2_payload_add_notify (chain, notify_type, 0);
+}
+
static void
ikev2_add_create_child_resp (ikev2_sa_t *sa, ikev2_rekey_t *rekey,
ikev2_payload_chain_t *chain)
{
if (rekey->notify_type)
{
- if (rekey->notify_type == IKEV2_NOTIFY_MSG_INVALID_KE_PAYLOAD)
- ikev2_add_invalid_ke_payload (sa, chain);
- else
- ikev2_payload_add_notify (chain, rekey->notify_type, 0);
+ ikev2_add_notify_payload (sa, chain, rekey->notify_type);
return;
}
- ikev2_payload_add_sa (chain, rekey->r_proposal);
+ ikev2_payload_add_sa (chain, rekey->r_proposal, 0);
ikev2_payload_add_nonce (chain, sa->r_nonce);
if (rekey->kex)
ikev2_payload_add_ke (chain, sa->dh_group, sa->r_dh_data);
ASSERT (udp);
ike->rspi = clib_host_to_net_u64 (sa->rspi);
- ikev2_payload_add_sa (chain, sa->r_proposals);
+ ikev2_payload_add_sa (chain, sa->r_proposals, 0);
ikev2_payload_add_ke (chain, sa->dh_group, sa->r_dh_data);
ikev2_payload_add_nonce (chain, sa->r_nonce);
{
ikev2_payload_add_id (chain, &sa->r_id, IKEV2_PAYLOAD_IDR);
ikev2_payload_add_auth (chain, &sa->r_auth);
- ikev2_payload_add_sa (chain, sa->childs[0].r_proposals);
+ ikev2_payload_add_sa (chain, sa->childs[0].r_proposals, 0);
ikev2_payload_add_ts (chain, sa->childs[0].tsi, IKEV2_PAYLOAD_TSI);
ikev2_payload_add_ts (chain, sa->childs[0].tsr, IKEV2_PAYLOAD_TSR);
}
if (sa->r_id.type != 0)
ikev2_payload_add_id (chain, &sa->r_id, IKEV2_PAYLOAD_IDR);
ikev2_payload_add_auth (chain, &sa->i_auth);
- ikev2_payload_add_sa (chain, sa->childs[0].i_proposals);
+ ikev2_payload_add_sa (chain, sa->childs[0].i_proposals, 0);
ikev2_payload_add_ts (chain, sa->childs[0].tsi, IKEV2_PAYLOAD_TSI);
ikev2_payload_add_ts (chain, sa->childs[0].tsr, IKEV2_PAYLOAD_TSR);
ikev2_payload_add_notify (chain, IKEV2_NOTIFY_MSG_INITIAL_CONTACT,
notify.spi = sa->childs[0].i_proposals->spi;
*(u32 *) data = clib_host_to_net_u32 (notify.spi);
- ikev2_payload_add_sa (chain, proposals);
+ ikev2_payload_add_sa (chain, proposals, 0);
ikev2_payload_add_nonce (chain, sa->i_nonce);
ikev2_payload_add_ts (chain, sa->childs[0].tsi, IKEV2_PAYLOAD_TSI);
ikev2_payload_add_ts (chain, sa->childs[0].tsr, IKEV2_PAYLOAD_TSR);
ikev2_add_create_child_resp (sa, &sa->new_child[0], chain);
vec_del1 (sa->new_child, 0);
}
+ else if (vec_len (sa->sa_rekey) > 0)
+ {
+ if (sa->sa_rekey[0].notify_type)
+ ikev2_add_notify_payload (sa, chain, sa->sa_rekey[0].notify_type);
+ else
+ {
+ ikev2_payload_add_sa (chain, sa->sa_rekey[0].r_proposals, 1);
+ ikev2_payload_add_nonce (chain, sa->sa_rekey[0].r_nonce);
+ ikev2_payload_add_ke (chain, sa->sa_rekey[0].dh_group,
+ sa->sa_rekey[0].r_dh_data);
+ }
+ vec_del1 (sa->sa_rekey, 0);
+ }
else if (sa->unsupported_cp)
{
u8 *data = vec_new (u8, 1);
vm, node->node_index, IKEV2_ERROR_NO_BUFF_SPACE, 1);
}
}
+ else if (vec_len (sa0->sa_rekey) > 0)
+ {
+ if (!sa0->sa_rekey[0].notify_type)
+ {
+ ikev2_sa_t *sar, *tmp = 0;
+ pool_get (ptd->sas, tmp);
+ sa0 = pool_elt_at_index (ptd->sas, p[0]);
+ /* swap old/new SAs to keep index and inherit IPsec SA */
+ clib_memcpy_fast (tmp, sa0, sizeof (*tmp));
+ sar = sa0;
+ sa0 = tmp;
+ hash_set (ptd->sa_by_rspi, sa0->rspi, sa0 - ptd->sas);
+ p = hash_get (ptd->sa_by_rspi, sa0->rspi);
+ ikev2_complete_sa_rekey (sar, sa0, &sa0->sa_rekey[0]);
+ hash_set (ptd->sa_by_rspi, sar->rspi, sar - ptd->sas);
+ }
+ if (ike_hdr_is_response (ike0))
+ {
+ vec_free (sa0->sa_rekey);
+ }
+ else
+ {
+ stats->n_rekey_req++;
+ sa0->stats.n_rekey_req++;
+ ike0->flags = IKEV2_HDR_FLAG_RESPONSE;
+ slen =
+ ikev2_generate_message (b0, sa0, ike0, 0, udp0, stats);
+ if (~0 == slen)
+ vlib_node_increment_counter (
+ vm, node->node_index, IKEV2_ERROR_NO_BUFF_SPACE, 1);
+ }
+ }
}
}
else
proposals[0].protocol_id = IKEV2_PROTOCOL_IKE;
/* Add and then cleanup proposal data */
- ikev2_payload_add_sa (chain, proposals);
+ ikev2_payload_add_sa (chain, proposals, 0);
ikev2_sa_free_proposal_vector (&proposals);
sa.is_initiator = 1;
sa.childs[0].i_proposals[0].protocol_id = IKEV2_PROTOCOL_ESP;
RAND_bytes ((u8 *) & sa.childs[0].i_proposals[0].spi,
sizeof (sa.childs[0].i_proposals[0].spi));
+ sa.childs[0].i_proposals[0].spi &= 0xffffffff;
/* Add NAT detection notification messages (mandatory) */
u8 *nat_detection_sha1 = ikev2_compute_nat_sha1 (
/*need new ispi */
RAND_bytes ((u8 *) & proposals[0].spi, sizeof (proposals[0].spi));
+ proposals[0].spi &= 0xffffffff;
rekey->spi = proposals[0].spi;
rekey->ispi = csa->i_proposals->spi;
len = ikev2_generate_message (b0, sa, ike0, proposals, 0, 0);
h.update(data)
return h.finalize()
- def calc_keys(self):
+ def calc_keys(self, sk_d=None):
prf = self.ike_prf_alg.mod()
- # SKEYSEED = prf(Ni | Nr, g^ir)
- s = self.i_nonce + self.r_nonce
- self.skeyseed = self.calc_prf(prf, s, self.dh_shared_secret)
+ if sk_d is None:
+ # SKEYSEED = prf(Ni | Nr, g^ir)
+ self.skeyseed = self.calc_prf(
+ prf, self.i_nonce + self.r_nonce, self.dh_shared_secret
+ )
+ else:
+ # SKEYSEED = prf(SK_d (old), g^ir (new) | Ni | Nr)
+ self.skeyseed = self.calc_prf(
+ prf, sk_d, self.dh_shared_secret + self.i_nonce + self.r_nonce
+ )
# calculate S = Ni | Nr | SPIi SPIr
- s = s + self.ispi + self.rspi
+ s = self.i_nonce + self.r_nonce + self.ispi + self.rspi
prf_key_trunc = self.ike_prf_alg.trunc_len
encr_key_len = self.ike_crypto_key_len
digest.update(data)
return digest.finalize()
+ def clone(self, test, **kwargs):
+ if "spi" not in kwargs:
+ kwargs["spi"] = self.ispi if self.is_initiator else self.rspi
+ if "nonce" not in kwargs:
+ kwargs["nonce"] = self.i_nonce if self.is_initiator else self.r_nonce
+ if self.child_sas:
+ if "local_ts" not in kwargs:
+ kwargs["local_ts"] = self.child_sas[0].local_ts
+ if "remote_ts" not in kwargs:
+ kwargs["remote_ts"] = self.child_sas[0].remote_ts
+ sa = type(self)(
+ test,
+ is_initiator=self.is_initiator,
+ i_id=self.i_id,
+ r_id=self.r_id,
+ id_type=self.id_type,
+ auth_data=self.auth_data,
+ auth_method=self.auth_method,
+ priv_key=self.priv_key,
+ i_natt=self.i_natt,
+ r_natt=self.r_natt,
+ udp_encap=self.udp_encap,
+ **kwargs,
+ )
+ if sa.is_initiator:
+ sa.set_ike_props(
+ crypto=self.ike_crypto,
+ crypto_key_len=self.ike_crypto_key_len,
+ integ=self.ike_integ,
+ prf=self.ike_prf,
+ dh=self.ike_dh,
+ )
+ sa.set_esp_props(
+ crypto=self.esp_crypto,
+ crypto_key_len=self.esp_crypto_key_len,
+ integ=self.esp_integ,
+ )
+ return sa
+
@unittest.skipIf("ikev2" in config.excluded_plugins, "Exclude IKEv2 plugin tests")
class IkePeer(VppTestCase):
self.pg0, ike_msg, self.sa.sport, self.sa.dport, self.sa.natt, self.ip6
)
+ def create_sa_rekey_request(self, **kwargs):
+ sa = self.generate_sa_init_payload(**kwargs)
+ header = ikev2.IKEv2(
+ init_SPI=self.sa.ispi,
+ resp_SPI=self.sa.rspi,
+ id=self.sa.new_msg_id(),
+ flags="Initiator",
+ exch_type="CREATE_CHILD_SA",
+ )
+ ike_msg = self.encrypt_ike_msg(header, sa, "SA")
+ return self.create_packet(
+ self.pg0, ike_msg, self.sa.sport, self.sa.dport, self.sa.natt, self.ip6
+ )
+
def create_empty_request(self):
header = ikev2.IKEv2(
init_SPI=self.sa.ispi,
self.assertEqual(api_id.data_len, exp_id.data_len)
self.assertEqual(bytes(api_id.data, "ascii"), exp_id.type)
- def verify_ike_sas(self):
+ def verify_ike_sas(self, is_rekey=False):
r = self.vapi.ikev2_sa_dump()
- self.assertEqual(len(r), 1)
- sa = r[0].sa
+ if is_rekey:
+ sa_count = 2
+ sa = r[1].sa
+ else:
+ sa_count = 1
+ sa = r[0].sa
+ self.assertEqual(len(r), sa_count)
self.assertEqual(self.sa.ispi, (sa.ispi).to_bytes(8, "big"))
self.assertEqual(self.sa.rspi, (sa.rspi).to_bytes(8, "big"))
if self.ip6:
self.assertEqual(bytes(sa.i_id.data, "ascii"), self.sa.i_id)
self.assertEqual(bytes(sa.r_id.data, "ascii"), self.idr)
+ n = self.vapi.ikev2_nonce_get(is_initiator=True, sa_index=sa.sa_index)
+ self.verify_nonce(n, self.sa.i_nonce)
+ n = self.vapi.ikev2_nonce_get(is_initiator=False, sa_index=sa.sa_index)
+ self.verify_nonce(n, self.sa.r_nonce)
+
r = self.vapi.ikev2_child_sa_dump(sa_index=sa.sa_index)
+ if is_rekey:
+ self.assertEqual(len(r), 0)
+ return
+
self.assertEqual(len(r), 1)
csa = r[0].child_sa
self.assertEqual(csa.sa_index, sa.sa_index)
self.assertEqual(len(r), 1)
self.verify_ts(r[0].ts, tsr[0], False)
- n = self.vapi.ikev2_nonce_get(is_initiator=True, sa_index=sa.sa_index)
- self.verify_nonce(n, self.sa.i_nonce)
- n = self.vapi.ikev2_nonce_get(is_initiator=False, sa_index=sa.sa_index)
- self.verify_nonce(n, self.sa.r_nonce)
-
def verify_nonce(self, api_nonce, nonce):
self.assertEqual(api_nonce.data_len, len(nonce))
self.assertEqual(api_nonce.nonce, nonce)
capture = self.pg0.get_capture(1)
self.verify_del_sa(capture[0])
- def send_sa_init_req(self):
+ def generate_sa_init_payload(
+ self, spi=None, dh_pub_key=None, nonce=None, next_payload=None
+ ):
tr_attr = self.sa.ike_crypto_attr()
trans = (
ikev2.IKEv2_payload_Transform(
)
)
+ if spi is None:
+ pargs = {}
+ else:
+ pargs = {"SPI": spi, "SPIsize": len(spi)}
props = ikev2.IKEv2_payload_Proposal(
- proposal=1, proto="IKEv2", trans_nb=4, trans=trans
+ proposal=1,
+ proto="IKEv2",
+ trans_nb=4,
+ trans=trans,
+ **pargs,
)
- next_payload = None if self.ip6 else "Notify"
-
- self.sa.init_req_packet = (
- ikev2.IKEv2(
- init_SPI=self.sa.ispi, flags="Initiator", exch_type="IKE_SA_INIT"
- )
- / ikev2.IKEv2_payload_SA(next_payload="KE", prop=props)
+ return (
+ ikev2.IKEv2_payload_SA(next_payload="KE", prop=props)
/ ikev2.IKEv2_payload_KE(
- next_payload="Nonce", group=self.sa.ike_dh, load=self.sa.my_dh_pub_key
+ next_payload="Nonce",
+ group=self.sa.ike_dh,
+ load=self.sa.my_dh_pub_key if dh_pub_key is None else dh_pub_key,
+ )
+ / ikev2.IKEv2_payload_Nonce(
+ next_payload=next_payload,
+ load=self.sa.i_nonce if nonce is None else nonce,
)
- / ikev2.IKEv2_payload_Nonce(next_payload=next_payload, load=self.sa.i_nonce)
)
+ def send_sa_init_req(self):
+ self.sa.init_req_packet = ikev2.IKEv2(
+ init_SPI=self.sa.ispi, flags="Initiator", exch_type="IKE_SA_INIT"
+ ) / self.generate_sa_init_payload(next_payload=None if self.ip6 else "Notify")
+
if not self.ip6:
if self.sa.i_natt:
src_address = b"\x0a\x0a\x0a\x01"
WITH_KEX = True
+@tag_fixme_vpp_workers
+class TestResponderRekeySA(TestResponderPsk):
+ """test ikev2 responder - rekey IKE SA"""
+
+ def send_rekey_from_initiator(self, newsa):
+ packet = self.create_sa_rekey_request(
+ spi=newsa.ispi,
+ dh_pub_key=newsa.my_dh_pub_key,
+ nonce=newsa.i_nonce,
+ )
+ self.pg0.add_stream(packet)
+ self.pg0.enable_capture()
+ self.pg_start()
+ capture = self.pg0.get_capture(1)
+ return capture
+
+ def process_rekey_response(self, newsa, capture):
+ ih = self.get_ike_header(capture[0])
+ plain = self.sa.hmac_and_decrypt(ih)
+ sa = ikev2.IKEv2_payload_SA(plain)
+ prop = sa[ikev2.IKEv2_payload_Proposal]
+ newsa.rspi = prop.SPI
+ newsa.r_nonce = sa[ikev2.IKEv2_payload_Nonce].load
+ newsa.r_dh_data = sa[ikev2.IKEv2_payload_KE].load
+ newsa.complete_dh_data()
+ newsa.calc_keys(sk_d=self.sa.sk_d)
+ newsa.child_sas = self.sa.child_sas
+ self.sa.child_sas = []
+
+ def test_responder(self):
+ super(TestResponderRekeySA, self).test_responder()
+ newsa = self.sa.clone(self, spi=os.urandom(8))
+ newsa.generate_dh_data()
+ capture = self.send_rekey_from_initiator(newsa)
+ self.process_rekey_response(newsa, capture)
+ self.verify_ike_sas(is_rekey=True)
+ self.assert_counter(1, "rekey_req", "ip4")
+ r = self.vapi.ikev2_sa_dump()
+ self.assertEqual(r[1].sa.stats.n_rekey_req, 1)
+ self.initiate_del_sa_from_initiator()
+ self.sa = newsa
+ self.verify_ike_sas()
+
+
@tag_fixme_ubuntu2204
@tag_fixme_debian11
class TestResponderVrf(TestResponderPsk, Ikev2Params):