X-Git-Url: https://gerrit.fd.io/r/gitweb?a=blobdiff_plain;f=src%2Fvnet%2Fipsec%2Fikev2.c;h=bb6818e311c50909bfc0fcb06be8076c3bec23ac;hb=bdc0e6b7204ea0211d4f7881497e4306586fb9ef;hp=092093346fdb7fdbe87fdbb883f7e489866c4eba;hpb=cb33dc2d7a566d571c86b950b4aa92dd7ae01c3c;p=vpp.git diff --git a/src/vnet/ipsec/ikev2.c b/src/vnet/ipsec/ikev2.c index 092093346fd..bb6818e311c 100644 --- a/src/vnet/ipsec/ikev2.c +++ b/src/vnet/ipsec/ikev2.c @@ -17,12 +17,15 @@ #include #include #include -#include +#include +#include #include #include #include #include +ikev2_main_t ikev2_main; + static int ikev2_delete_tunnel_interface (vnet_main_t * vnm, ikev2_sa_t * sa, ikev2_child_sa_t * child); @@ -303,16 +306,16 @@ static void 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); } } @@ -776,29 +779,31 @@ ikev2_initial_contact_cleanup (ikev2_sa_t * 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); } @@ -873,25 +878,26 @@ ikev2_process_auth_req (vlib_main_t * vm, ikev2_sa_t * sa, ike_header_t * ike) 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 */ @@ -1474,6 +1480,7 @@ ikev2_create_tunnel_interface (vnet_main_t * vnm, ikev2_sa_t * sa, ikev2_sa_transform_t *tr; ikev2_sa_proposal_t *proposals; u8 encr_type = 0; + u8 integ_type = 0; if (!child->r_proposals) { @@ -1544,8 +1551,21 @@ ikev2_create_tunnel_interface (vnet_main_t * vnm, ikev2_sa_t * sa, tr = ikev2_sa_get_td_for_type (proposals, IKEV2_TRANSFORM_TYPE_INTEG); if (tr) { - if (tr->integ_type != IKEV2_TRANSFORM_INTEG_TYPE_AUTH_HMAC_SHA1_96) - { + switch (tr->integ_type) + { + case IKEV2_TRANSFORM_INTEG_TYPE_AUTH_HMAC_SHA2_256_128: + integ_type = IPSEC_INTEG_ALG_SHA_256_128; + break; + case IKEV2_TRANSFORM_INTEG_TYPE_AUTH_HMAC_SHA2_384_192: + integ_type = IPSEC_INTEG_ALG_SHA_384_192; + break; + case IKEV2_TRANSFORM_INTEG_TYPE_AUTH_HMAC_SHA2_512_256: + integ_type = IPSEC_INTEG_ALG_SHA_512_256; + break; + case IKEV2_TRANSFORM_INTEG_TYPE_AUTH_HMAC_SHA1_96: + integ_type = IPSEC_INTEG_ALG_SHA1_96; + break; + default: ikev2_set_state (sa, IKEV2_STATE_NO_PROPOSAL_CHOSEN); return 1; } @@ -1574,7 +1594,7 @@ ikev2_create_tunnel_interface (vnet_main_t * vnm, ikev2_sa_t * sa, rem_ckey = child->sk_ei; } - a.integ_alg = IPSEC_INTEG_ALG_SHA1_96; + a.integ_alg = integ_type; a.local_integ_key_len = vec_len (loc_ikey); clib_memcpy (a.local_integ_key, loc_ikey, a.local_integ_key_len); a.remote_integ_key_len = vec_len (rem_ikey); @@ -1592,8 +1612,16 @@ ikev2_create_tunnel_interface (vnet_main_t * vnm, ikev2_sa_t * sa, + 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); } } @@ -1922,10 +1950,10 @@ ikev2_retransmit_sa_init (ike_header_t * ike, { 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) @@ -2029,6 +2057,7 @@ ikev2_retransmit_resp (ikev2_sa_t * sa, ike_header_t * ike) } } + static uword ikev2_node_fn (vlib_main_t * vm, vlib_node_runtime_t * node, vlib_frame_t * frame) @@ -2036,7 +2065,7 @@ ikev2_node_fn (vlib_main_t * vm, 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; @@ -2134,11 +2163,14 @@ ikev2_node_fn (vlib_main_t * vm, 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 { @@ -2146,7 +2178,7 @@ ikev2_node_fn (vlib_main_t * vm, } } } - else + else //received sa_init without initiator flag { ikev2_process_sa_init_resp (vm, sa0, ike0); @@ -2169,11 +2201,11 @@ ikev2_node_fn (vlib_main_t * vm, 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 { @@ -2184,12 +2216,13 @@ ikev2_node_fn (vlib_main_t * vm, 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) @@ -2240,12 +2273,13 @@ ikev2_node_fn (vlib_main_t * vm, 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) @@ -2305,12 +2339,13 @@ ikev2_node_fn (vlib_main_t * vm, 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) @@ -2438,7 +2473,7 @@ VLIB_REGISTER_NODE (ikev2_node,static) = { }; /* *INDENT-ON* */ - +// set ikev2 proposals when vpp is used as initiator static clib_error_t * ikev2_set_initiator_proposals (vlib_main_t * vm, ikev2_sa_t * sa, ikev2_transforms_set * ts, @@ -2456,7 +2491,7 @@ ikev2_set_initiator_proposals (vlib_main_t * vm, ikev2_sa_t * sa, vec_foreach (td, km->supported_transforms) { if (td->type == IKEV2_TRANSFORM_TYPE_ENCR - && td->encr_type == IKEV2_TRANSFORM_ENCR_TYPE_AES_CBC + && td->encr_type == ts->crypto_alg && td->key_len == ts->crypto_key_size / 8) { u16 attr[2]; @@ -2481,7 +2516,7 @@ ikev2_set_initiator_proposals (vlib_main_t * vm, ikev2_sa_t * sa, vec_foreach (td, km->supported_transforms) { if (td->type == IKEV2_TRANSFORM_TYPE_INTEG - && td->integ_type == IKEV2_TRANSFORM_INTEG_TYPE_AUTH_HMAC_SHA1_96) + && td->integ_type == ts->integ_alg) { vec_add1 (proposal->transforms, *td); error = 0; @@ -2490,6 +2525,8 @@ ikev2_set_initiator_proposals (vlib_main_t * vm, ikev2_sa_t * sa, } if (error) { + clib_warning + ("Didn't find any supported algorithm for IKEV2_TRANSFORM_TYPE_INTEG"); r = clib_error_return (0, "Unsupported algorithm"); return r; } @@ -2501,7 +2538,7 @@ ikev2_set_initiator_proposals (vlib_main_t * vm, ikev2_sa_t * sa, vec_foreach (td, km->supported_transforms) { if (td->type == IKEV2_TRANSFORM_TYPE_PRF - && td->prf_type == IKEV2_TRANSFORM_PRF_TYPE_PRF_HMAC_SHA1) + && td->prf_type == IKEV2_TRANSFORM_PRF_TYPE_PRF_HMAC_SHA2_256) { vec_add1 (proposal->transforms, *td); error = 0; @@ -2986,7 +3023,7 @@ ikev2_initiate_sa_init (vlib_main_t * vm, u8 * name) vec_free (sig_hash_algo); - /* Buffer update and bolierplate */ + /* Buffer update and boilerplate */ len += vec_len (chain->data); ike0->nextpayload = chain->first_payload_type; ike0->length = clib_host_to_net_u32 (len); @@ -3010,7 +3047,11 @@ ikev2_initiate_sa_init (vlib_main_t * vm, u8 * name) 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); @@ -3305,7 +3346,7 @@ ikev2_mngr_process_child_sa (ikev2_sa_t * sa, ikev2_child_sa_t * csa) else if (csa->rekey_retries > 0) { csa->rekey_retries--; - clib_warning ("Rekeing Child SA 0x%x, retries left %d", + clib_warning ("Rekeying Child SA 0x%x, retries left %d", csa->i_proposals->spi, csa->rekey_retries); if (csa->rekey_retries == 0) {