ikev2: add SA dump API

Type: feature
Ticket: VPP-1897

Change-Id: I0245aceeb344efd29b1f9217c35889a8bbe1f744
Signed-off-by: jan_cavojsky <Jan.Cavojsky@pantheon.tech>
Signed-off-by: Filip Tehlar <ftehlar@cisco.com>
This commit is contained in:
jan_cavojsky
2020-07-08 09:24:12 +02:00
committed by Benoît Ganne
parent 7fc88cf3a1
commit a340fe1ac6
5 changed files with 907 additions and 6 deletions

@ -1,6 +1,6 @@
/* Hey Emacs use -*- mode: C -*- */
/*
* Copyright (c) 2015-2016 Cisco and/or its affiliates.
* Copyright (c) 2015-2020 Cisco and/or its affiliates.
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at:
@ -64,6 +64,129 @@ define ikev2_profile_details
option status="in_progress";
};
/** \brief Dump all SAs
@param client_index - opaque cookie to identify the sender
@param context - sender context, to match reply w/ request
*/
define ikev2_sa_dump
{
u32 client_index;
u32 context;
option status = "in_progress";
};
/** \brief Details about IKE SA
@param context - sender context, to match reply w/ request
@param retval - return code
@param sa - SA data
*/
define ikev2_sa_details
{
u32 context;
i32 retval;
vl_api_ikev2_sa_t sa;
option status = "in_progress";
};
/** \brief Dump child SA of specific SA
@param client_index - opaque cookie to identify the sender
@param context - sender context, to match reply w/ request
@param sa_index - index of specific sa
*/
define ikev2_child_sa_dump
{
u32 client_index;
u32 context;
u32 sa_index;
option vat_help = "sa_index <index>";
option status = "in_progress";
};
/** \brief Child SA details
@param context - sender context, to match reply w/ request
@param retval - return code
@param child_sa - child SA data
*/
define ikev2_child_sa_details
{
u32 context;
i32 retval;
vl_api_ikev2_child_sa_t child_sa;
option status = "in_progress";
};
/** \brief get specific nonce
@param client_index - opaque cookie to identify the sender
@param context - sender context, to match reply w/ request
@param is_initiator - specify type initiator|responder of nonce
@param sa_index - index of specific sa
*/
define ikev2_nonce_get
{
u32 client_index;
u32 context;
bool is_initiator;
u32 sa_index;
option vat_help = "initiator|responder sa_index <index>";
option status = "in_progress";
};
/** \brief reply on specific nonce
@param context - sender context, to match reply w/ request
@param retval - return code
@param data_len - nonce length
@param nonce - nonce data
*/
define ikev2_nonce_get_reply
{
u32 context;
i32 retval;
u32 data_len;
u8 nonce[data_len];
option status = "in_progress";
};
/** \brief dump traffic selectors
@param client_index - opaque cookie to identify the sender
@param context - sender context, to match reply w/ request
@param is_initiator - specify type initiator|responder of nonce
@param sa_index - index of specific sa
@param child_sa_index - index of specific sa child of specific sa
*/
define ikev2_traffic_selector_dump
{
u32 client_index;
u32 context;
bool is_initiator;
u32 sa_index;
u32 child_sa_index;
option vat_help = "initiator|responder sa_index <index> child_sa_index <index>";
option status = "in_progress";
};
/** \brief details on specific traffic selector
@param context - sender context, to match reply w/ request
@param retval - return code
@param ts - traffic selector data
*/
define ikev2_traffic_selector_details
{
u32 context;
i32 retval;
vl_api_ikev2_ts_t ts;
option status = "in_progress";
};
/** \brief IKEv2: Add/delete profile
@param client_index - opaque cookie to identify the sender

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

@ -1,6 +1,6 @@
/* Hey Emacs use -*- mode: C -*- */
/*
* Copyright (c) 2015-2016 Cisco and/or its affiliates.
* Copyright (c) 2015-2020 Cisco and/or its affiliates.
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at:
@ -27,6 +27,9 @@ typedef ikev2_id
typedef ikev2_ts
{
u32 sa_index;
u32 child_sa_index;
bool is_local;
u8 protocol_id;
u16 start_port;
@ -83,3 +86,65 @@ typedef ikev2_profile
bool udp_encap;
vl_api_ikev2_auth_t auth;
};
typedef ikev2_sa_transform
{
u8 transform_type;
u16 transform_id;
u16 key_len;
u16 key_trunc;
u16 block_size;
u8 dh_group;
};
typedef ikev2_keys
{
u8 sk_d[64];
u8 sk_d_len;
u8 sk_ai[64];
u8 sk_ai_len;
u8 sk_ar[64];
u8 sk_ar_len;
u8 sk_ei[64];
u8 sk_ei_len;
u8 sk_er[64];
u8 sk_er_len;
u8 sk_pi[64];
u8 sk_pi_len;
u8 sk_pr[64];
u8 sk_pr_len;
};
typedef ikev2_child_sa
{
u32 sa_index;
u32 child_sa_index;
u32 i_spi;
u32 r_spi;
vl_api_ikev2_keys_t keys;
vl_api_ikev2_sa_transform_t encryption;
vl_api_ikev2_sa_transform_t integrity;
vl_api_ikev2_sa_transform_t esn;
};
typedef ikev2_sa
{
u32 sa_index;
u32 profile_index;
u64 ispi;
u64 rspi;
vl_api_ip4_address_t iaddr;
vl_api_ip4_address_t raddr;
vl_api_ikev2_keys_t keys;
/* ID */
vl_api_ikev2_id_t i_id;
vl_api_ikev2_id_t r_id;
vl_api_ikev2_sa_transform_t encryption;
vl_api_ikev2_sa_transform_t integrity;
vl_api_ikev2_sa_transform_t prf;
vl_api_ikev2_sa_transform_t dh;
};

@ -415,6 +415,8 @@ class IKEv2SA(object):
c = self.child_sas[0]
ts1 = ikev2.IPv4TrafficSelector(
IP_protocol_ID=0,
start_port=0,
end_port=0xffff,
starting_address_v4=c.local_ts['start_addr'],
ending_address_v4=c.local_ts['end_addr'])
ts2 = ikev2.IPv4TrafficSelector(
@ -692,7 +694,7 @@ class TemplateResponder(VppTestCase):
plain = self.sa.hmac_and_decrypt(ike)
self.sa.calc_child_keys()
def verify_child_sas(self):
def verify_ipsec_sas(self):
sas = self.vapi.ipsec_sa_dump()
self.assertEqual(len(sas), 2)
sa0 = sas[0].entry
@ -726,10 +728,97 @@ class TemplateResponder(VppTestCase):
self.assertEqual(sa0.salt.to_bytes(4, 'little'), c.salt_er)
self.assertEqual(sa1.salt.to_bytes(4, 'little'), c.salt_ei)
def verify_keymat(self, api_keys, keys, name):
km = getattr(keys, name)
api_km = getattr(api_keys, name)
api_km_len = getattr(api_keys, name + '_len')
self.assertEqual(len(km), api_km_len)
self.assertEqual(km, api_km[:api_km_len])
def verify_id(self, api_id, exp_id):
self.assertEqual(api_id.type, IDType.value(exp_id.type))
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):
r = self.vapi.ikev2_sa_dump()
self.assertEqual(len(r), 1)
sa = r[0].sa
self.assertEqual(self.sa.ispi, (sa.ispi).to_bytes(8, 'little'))
self.assertEqual(self.sa.rspi, (sa.rspi).to_bytes(8, 'big'))
self.assertEqual(sa.iaddr, IPv4Address(self.pg0.remote_ip4))
self.assertEqual(sa.raddr, IPv4Address(self.pg0.local_ip4))
self.verify_keymat(sa.keys, self.sa, 'sk_d')
self.verify_keymat(sa.keys, self.sa, 'sk_ai')
self.verify_keymat(sa.keys, self.sa, 'sk_ar')
self.verify_keymat(sa.keys, self.sa, 'sk_ei')
self.verify_keymat(sa.keys, self.sa, 'sk_er')
self.verify_keymat(sa.keys, self.sa, 'sk_pi')
self.verify_keymat(sa.keys, self.sa, 'sk_pr')
self.assertEqual(sa.i_id.type, self.sa.id_type)
self.assertEqual(sa.r_id.type, self.sa.id_type)
self.assertEqual(sa.i_id.data_len, len(self.sa.i_id))
self.assertEqual(sa.r_id.data_len, len(self.sa.r_id))
self.assertEqual(bytes(sa.i_id.data, 'ascii'), self.sa.i_id)
self.assertEqual(bytes(sa.r_id.data, 'ascii'), self.sa.r_id)
r = self.vapi.ikev2_child_sa_dump(sa_index=sa.sa_index)
self.assertEqual(len(r), 1)
csa = r[0].child_sa
self.assertEqual(csa.sa_index, sa.sa_index)
c = self.sa.child_sas[0]
if hasattr(c, 'sk_ai'):
self.verify_keymat(csa.keys, c, 'sk_ai')
self.verify_keymat(csa.keys, c, 'sk_ar')
self.verify_keymat(csa.keys, c, 'sk_ei')
self.verify_keymat(csa.keys, c, 'sk_er')
tsi, tsr = self.sa.generate_ts()
tsi = tsi[0]
tsr = tsr[0]
r = self.vapi.ikev2_traffic_selector_dump(
is_initiator=True, sa_index=sa.sa_index,
child_sa_index=csa.child_sa_index)
self.assertEqual(len(r), 1)
ts = r[0].ts
self.verify_ts(r[0].ts, tsi[0], True)
r = self.vapi.ikev2_traffic_selector_dump(
is_initiator=False, sa_index=sa.sa_index,
child_sa_index=csa.child_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)
def verify_ts(self, api_ts, ts, is_initiator):
if is_initiator:
self.assertTrue(api_ts.is_local)
else:
self.assertFalse(api_ts.is_local)
self.assertEqual(api_ts.start_addr,
IPv4Address(ts.starting_address_v4))
self.assertEqual(api_ts.end_addr,
IPv4Address(ts.ending_address_v4))
self.assertEqual(api_ts.start_port, ts.start_port)
self.assertEqual(api_ts.end_port, ts.end_port)
self.assertEqual(api_ts.protocol_id, ts.IP_protocol_ID)
def test_responder(self):
self.send_sa_init(self.sa.natt)
self.send_sa_auth()
self.verify_child_sas()
self.verify_ipsec_sas()
self.verify_ike_sas()
class Ikev2Params(object):