#include <vnet/vnet.h>
#include <vnet/pg/pg.h>
#include <vppinfra/error.h>
+#include <vppinfra/random.h>
#include <vnet/udp/udp.h>
#include <vnet/ipsec/ipsec.h>
#include <vnet/ipsec/ikev2.h>
#include <vnet/ipsec/ikev2_priv.h>
#include <openssl/sha.h>
+ikev2_main_t ikev2_main;
+
static int ikev2_delete_tunnel_interface (vnet_main_t * vnm,
ikev2_sa_t * sa,
ikev2_child_sa_t * child);
ikev2_delete_sa (ikev2_sa_t * sa)
{
ikev2_main_t *km = &ikev2_main;
- u32 cpu_index = os_get_cpu_number ();
+ u32 thread_index = vlib_get_thread_index ();
uword *p;
ikev2_sa_free_all_vec (sa);
- p = hash_get (km->per_thread_data[cpu_index].sa_by_rspi, sa->rspi);
+ p = hash_get (km->per_thread_data[thread_index].sa_by_rspi, sa->rspi);
if (p)
{
- hash_unset (km->per_thread_data[cpu_index].sa_by_rspi, sa->rspi);
- pool_put (km->per_thread_data[cpu_index].sas, sa);
+ hash_unset (km->per_thread_data[thread_index].sa_by_rspi, sa->rspi);
+ pool_put (km->per_thread_data[thread_index].sas, sa);
}
}
ikev2_sa_t *tmp;
u32 i, *delete = 0;
ikev2_child_sa_t *c;
- u32 cpu_index = os_get_cpu_number ();
+ u32 thread_index = vlib_get_thread_index ();
if (!sa->initial_contact)
return;
/* find old IKE SAs with the same authenticated identity */
/* *INDENT-OFF* */
- pool_foreach (tmp, km->per_thread_data[cpu_index].sas, ({
+ pool_foreach (tmp, km->per_thread_data[thread_index].sas, ({
if (tmp->i_id.type != sa->i_id.type ||
vec_len(tmp->i_id.data) != vec_len(sa->i_id.data) ||
memcmp(sa->i_id.data, tmp->i_id.data, vec_len(sa->i_id.data)))
continue;
if (sa->rspi != tmp->rspi)
- vec_add1(delete, tmp - km->per_thread_data[cpu_index].sas);
+ vec_add1(delete, tmp - km->per_thread_data[thread_index].sas);
}));
/* *INDENT-ON* */
for (i = 0; i < vec_len (delete); i++)
{
- tmp = pool_elt_at_index (km->per_thread_data[cpu_index].sas, delete[i]);
- vec_foreach (c, tmp->childs)
- ikev2_delete_tunnel_interface (km->vnet_main, tmp, c);
+ tmp =
+ pool_elt_at_index (km->per_thread_data[thread_index].sas, delete[i]);
+ vec_foreach (c,
+ tmp->childs) ikev2_delete_tunnel_interface (km->vnet_main,
+ tmp, c);
ikev2_delete_sa (tmp);
}
first_child_sa->i_proposals = ikev2_parse_sa_payload (ikep);
}
}
- else if (payload == IKEV2_PAYLOAD_IDI || payload == IKEV2_PAYLOAD_IDR) /* 35, 36 */
+ else if (payload == IKEV2_PAYLOAD_IDI) /* 35 */
{
ike_id_payload_header_t *id = (ike_id_payload_header_t *) ikep;
- if (sa->is_initiator)
- {
- sa->r_id.type = id->id_type;
- vec_free (sa->r_id.data);
- vec_add (sa->r_id.data, id->payload, plen - sizeof (*id));
- }
- else
- {
- sa->i_id.type = id->id_type;
- vec_free (sa->i_id.data);
- vec_add (sa->i_id.data, id->payload, plen - sizeof (*id));
- }
+ sa->i_id.type = id->id_type;
+ vec_free (sa->i_id.data);
+ vec_add (sa->i_id.data, id->payload, plen - sizeof (*id));
- clib_warning ("received payload %s, len %u id_type %u",
- (payload == IKEV2_PAYLOAD_IDI ? "IDi" : "IDr"),
+ clib_warning ("received payload IDi, len %u id_type %u",
+ plen - sizeof (*id), id->id_type);
+ }
+ else if (payload == IKEV2_PAYLOAD_IDR) /* 36 */
+ {
+ ike_id_payload_header_t *id = (ike_id_payload_header_t *) ikep;
+
+ sa->r_id.type = id->id_type;
+ vec_free (sa->r_id.data);
+ vec_add (sa->r_id.data, id->payload, plen - sizeof (*id));
+
+ clib_warning ("received payload IDr len %u id_type %u",
plen - sizeof (*id), id->id_type);
}
else if (payload == IKEV2_PAYLOAD_AUTH) /* 39 */
+ sa->profile->lifetime;
if (sa->profile->lifetime_jitter)
{
+ // This is not much better than rand(3), which Coverity warns
+ // is unsuitable for security applications; random_u32 is
+ // however fast. If this perturbance to the expiration time
+ // needs to use a better RNG then we may need to use something
+ // like /dev/urandom which has significant overhead.
+ u32 rnd = (u32) (vlib_time_now (vnm->vlib_main) * 1e6);
+ rnd = random_u32 (&rnd);
+
child->time_to_expiration +=
- 1 + (rand () % sa->profile->lifetime_jitter);
+ 1 + (rnd % sa->profile->lifetime_jitter);
}
}
{
ikev2_main_t *km = &ikev2_main;
ikev2_sa_t *sa;
- u32 cpu_index = os_get_cpu_number ();
+ u32 thread_index = vlib_get_thread_index ();
/* *INDENT-OFF* */
- pool_foreach (sa, km->per_thread_data[cpu_index].sas, ({
+ pool_foreach (sa, km->per_thread_data[thread_index].sas, ({
if (sa->ispi == clib_net_to_host_u64(ike->ispi) &&
sa->iaddr.as_u32 == iaddr.as_u32 &&
sa->raddr.as_u32 == raddr.as_u32)
u32 n_left_from, *from, *to_next;
ikev2_next_t next_index;
ikev2_main_t *km = &ikev2_main;
- u32 cpu_index = os_get_cpu_number ();
+ u32 thread_index = vlib_get_thread_index ();
from = vlib_frame_vector_args (frame);
n_left_from = frame->n_vectors;
if (sa0->state == IKEV2_STATE_SA_INIT)
{
/* add SA to the pool */
- pool_get (km->per_thread_data[cpu_index].sas, sa0);
+ pool_get (km->per_thread_data[thread_index].sas,
+ sa0);
clib_memcpy (sa0, &sa, sizeof (*sa0));
- hash_set (km->per_thread_data[cpu_index].sa_by_rspi,
+ hash_set (km->
+ per_thread_data[thread_index].sa_by_rspi,
sa0->rspi,
- sa0 - km->per_thread_data[cpu_index].sas);
+ sa0 -
+ km->per_thread_data[thread_index].sas);
}
else
{
if (sa0->state == IKEV2_STATE_SA_INIT)
{
/* add SA to the pool */
- pool_get (km->per_thread_data[cpu_index].sas, sa0);
+ pool_get (km->per_thread_data[thread_index].sas, sa0);
clib_memcpy (sa0, &sa, sizeof (*sa0));
- hash_set (km->per_thread_data[cpu_index].sa_by_rspi,
+ hash_set (km->per_thread_data[thread_index].sa_by_rspi,
sa0->rspi,
- sa0 - km->per_thread_data[cpu_index].sas);
+ sa0 - km->per_thread_data[thread_index].sas);
}
else
{
else if (ike0->exchange == IKEV2_EXCHANGE_IKE_AUTH)
{
uword *p;
- p = hash_get (km->per_thread_data[cpu_index].sa_by_rspi,
+ p = hash_get (km->per_thread_data[thread_index].sa_by_rspi,
clib_net_to_host_u64 (ike0->rspi));
if (p)
{
- sa0 = pool_elt_at_index (km->per_thread_data[cpu_index].sas,
- p[0]);
+ sa0 =
+ pool_elt_at_index (km->per_thread_data[thread_index].sas,
+ p[0]);
r = ikev2_retransmit_resp (sa0, ike0);
if (r == 1)
else if (ike0->exchange == IKEV2_EXCHANGE_INFORMATIONAL)
{
uword *p;
- p = hash_get (km->per_thread_data[cpu_index].sa_by_rspi,
+ p = hash_get (km->per_thread_data[thread_index].sa_by_rspi,
clib_net_to_host_u64 (ike0->rspi));
if (p)
{
- sa0 = pool_elt_at_index (km->per_thread_data[cpu_index].sas,
- p[0]);
+ sa0 =
+ pool_elt_at_index (km->per_thread_data[thread_index].sas,
+ p[0]);
r = ikev2_retransmit_resp (sa0, ike0);
if (r == 1)
else if (ike0->exchange == IKEV2_EXCHANGE_CREATE_CHILD_SA)
{
uword *p;
- p = hash_get (km->per_thread_data[cpu_index].sa_by_rspi,
+ p = hash_get (km->per_thread_data[thread_index].sa_by_rspi,
clib_net_to_host_u64 (ike0->rspi));
if (p)
{
- sa0 = pool_elt_at_index (km->per_thread_data[cpu_index].sas,
- p[0]);
+ sa0 =
+ pool_elt_at_index (km->per_thread_data[thread_index].sas,
+ p[0]);
r = ikev2_retransmit_resp (sa0, ike0);
if (r == 1)
sa.i_auth.method = p->auth.method;
sa.i_auth.hex = p->auth.hex;
sa.i_auth.data = vec_dup (p->auth.data);
+#if OPENSSL_VERSION_NUMBER >= 0x10100000L
+ clib_memcpy (sa.i_auth.key, p->auth.key, EVP_PKEY_size (p->auth.key));
+#else
sa.i_auth.key = vec_dup (p->auth.key);
+#endif
vec_add (sa.childs[0].tsi, &p->loc_ts, 1);
vec_add (sa.childs[0].tsr, &p->rem_ts, 1);