2 * Copyright (c) 2015 Cisco and/or its affiliates.
3 * Licensed under the Apache License, Version 2.0 (the "License");
4 * you may not use this file except in compliance with the License.
5 * You may obtain a copy of the License at:
7 * http://www.apache.org/licenses/LICENSE-2.0
9 * Unless required by applicable law or agreed to in writing, software
10 * distributed under the License is distributed on an "AS IS" BASIS,
11 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 * See the License for the specific language governing permissions and
13 * limitations under the License.
18 #include <vnet/vnet.h>
19 #include <vnet/api_errno.h>
20 #include <vnet/ip/ip.h>
21 #include <vnet/interface.h>
23 #include <vnet/ipsec/ipsec.h>
24 #include <plugins/ikev2/ikev2.h>
25 #include <plugins/ikev2/ikev2_priv.h>
28 typedef CLIB_PACKED (struct {
36 }) ike_notify_payload_header_t;
40 typedef CLIB_PACKED (struct {
46 ip4_address_t start_addr;
47 ip4_address_t end_addr;
48 }) ikev2_ts_payload_entry_t;
52 typedef CLIB_PACKED (struct {
58 ikev2_ts_payload_entry_t ts[0];
59 }) ike_ts_payload_header_t;
63 typedef CLIB_PACKED (struct {
70 u8 num_transforms; u32 spi[0];
71 }) ike_sa_proposal_data_t;
75 typedef CLIB_PACKED (struct {
83 }) ike_sa_transform_data_t;
87 typedef CLIB_PACKED (struct {
95 }) ike_delete_payload_header_t;
98 static ike_payload_header_t *
99 ikev2_payload_add_hdr (ikev2_payload_chain_t * c, u8 payload_type, int len)
101 ike_payload_header_t *hdr =
102 (ike_payload_header_t *) & c->data[c->last_hdr_off];
106 hdr->nextpayload = payload_type;
108 c->first_payload_type = payload_type;
110 c->last_hdr_off = vec_len (c->data);
111 vec_add2 (c->data, tmp, len);
112 hdr = (ike_payload_header_t *) tmp;
113 clib_memset (hdr, 0, len);
115 hdr->length = clib_host_to_net_u16 (len);
121 ikev2_payload_add_data (ikev2_payload_chain_t * c, u8 * data)
124 ike_payload_header_t *hdr;
126 vec_append (c->data, data);
127 hdr = (ike_payload_header_t *) & c->data[c->last_hdr_off];
128 len = clib_net_to_host_u16 (hdr->length);
129 hdr->length = clib_host_to_net_u16 (len + vec_len (data));
133 ikev2_payload_add_notify (ikev2_payload_chain_t * c, u16 msg_type, u8 * data)
135 ikev2_payload_add_notify_2(c, msg_type, data, 0);
139 ikev2_payload_add_notify_2 (ikev2_payload_chain_t * c, u16 msg_type,
140 u8 * data, ikev2_notify_t * notify)
142 ike_notify_payload_header_t *n;
145 (ike_notify_payload_header_t *) ikev2_payload_add_hdr (c,
146 IKEV2_PAYLOAD_NOTIFY,
148 n->msg_type = clib_host_to_net_u16 (msg_type);
151 n->protocol_id = notify->protocol_id;
157 ikev2_payload_add_data (c, data);
161 ikev2_payload_add_sa (ikev2_payload_chain_t * c,
162 ikev2_sa_proposal_t * proposals)
164 ike_payload_header_t *ph;
165 ike_sa_proposal_data_t *prop;
166 ike_sa_transform_data_t *tr;
167 ikev2_sa_proposal_t *p;
168 ikev2_sa_transform_t *t;
174 ikev2_payload_add_hdr (c, IKEV2_PAYLOAD_SA, sizeof (*ph));
176 vec_foreach (p, proposals)
178 int spi_size = (p->protocol_id == IKEV2_PROTOCOL_ESP) ? 4 : 0;
179 pr_data = vec_new (u8, sizeof (ike_sa_proposal_data_t) + spi_size);
180 prop = (ike_sa_proposal_data_t *) pr_data;
181 prop->last_or_more = proposals - p + 1 < vec_len (proposals) ? 2 : 0;
182 prop->protocol_id = p->protocol_id;
183 prop->proposal_num = p->proposal_num;
184 prop->spi_size = spi_size;
185 prop->num_transforms = vec_len (p->transforms);
188 prop->spi[0] = clib_host_to_net_u32 (p->spi);
190 vec_foreach (t, p->transforms)
192 vec_add2 (tr_data, tmp, sizeof (*tr) + vec_len (t->attrs));
193 tr = (ike_sa_transform_data_t *) tmp;
195 ((t - p->transforms) + 1 < vec_len (p->transforms)) ? 3 : 0;
196 tr->transform_type = t->type;
197 tr->transform_id = clib_host_to_net_u16 (t->transform_id);
199 clib_host_to_net_u16 (sizeof (*tr) + vec_len (t->attrs));
201 if (vec_len (t->attrs) > 0)
202 clib_memcpy_fast (tr->attributes, t->attrs, vec_len (t->attrs));
206 clib_host_to_net_u16 (vec_len (tr_data) + vec_len (pr_data));
207 ikev2_payload_add_data (c, pr_data);
208 ikev2_payload_add_data (c, tr_data);
215 ikev2_payload_add_ke (ikev2_payload_chain_t * c, u16 dh_group, u8 * dh_data)
217 ike_ke_payload_header_t *ke;
218 ke = (ike_ke_payload_header_t *) ikev2_payload_add_hdr (c, IKEV2_PAYLOAD_KE,
221 ke->dh_group = clib_host_to_net_u16 (dh_group);
222 ikev2_payload_add_data (c, dh_data);
226 ikev2_payload_add_nonce (ikev2_payload_chain_t * c, u8 * nonce)
228 ikev2_payload_add_hdr (c, IKEV2_PAYLOAD_NONCE,
229 sizeof (ike_payload_header_t));
230 ikev2_payload_add_data (c, nonce);
234 ikev2_payload_add_id (ikev2_payload_chain_t * c, ikev2_id_t * id, u8 type)
236 ike_id_payload_header_t *idp;
238 (ike_id_payload_header_t *) ikev2_payload_add_hdr (c, type,
241 idp->id_type = id->type;
242 ikev2_payload_add_data (c, id->data);
246 ikev2_payload_add_delete (ikev2_payload_chain_t * c, ikev2_delete_t * d)
248 ike_delete_payload_header_t *dp;
249 u16 num_of_spi = vec_len (d);
252 (ike_delete_payload_header_t *) ikev2_payload_add_hdr (c,
253 IKEV2_PAYLOAD_DELETE,
256 if (d[0].protocol_id == IKEV2_PROTOCOL_IKE)
262 dp->protocol_id = d[0].protocol_id;
264 dp->num_of_spi = clib_host_to_net_u16 (num_of_spi);
267 u8 *data = vec_new (u8, 4);
268 u32 spi = clib_host_to_net_u32 (d2->spi);
269 clib_memcpy (data, &spi, 4);
270 ikev2_payload_add_data (c, data);
277 ikev2_payload_add_auth (ikev2_payload_chain_t * c, ikev2_auth_t * auth)
279 ike_auth_payload_header_t *ap;
281 (ike_auth_payload_header_t *) ikev2_payload_add_hdr (c,
285 ap->auth_method = auth->method;
286 ikev2_payload_add_data (c, auth->data);
290 ikev2_payload_add_ts (ikev2_payload_chain_t * c, ikev2_ts_t * ts, u8 type)
292 ike_ts_payload_header_t *tsh;
297 (ike_ts_payload_header_t *) ikev2_payload_add_hdr (c, type,
299 tsh->num_ts = vec_len (ts);
301 vec_foreach (ts2, ts)
303 ASSERT (ts2->ts_type == 7); /*TS_IPV4_ADDR_RANGE */
304 ikev2_ts_payload_entry_t *entry;
305 vec_add2 (data, tmp, sizeof (*entry));
306 entry = (ikev2_ts_payload_entry_t *) tmp;
307 entry->ts_type = ts2->ts_type;
308 entry->protocol_id = ts2->protocol_id;
309 entry->selector_len = clib_host_to_net_u16 (16);
310 entry->start_port = clib_host_to_net_u16 (ts2->start_port);
311 entry->end_port = clib_host_to_net_u16 (ts2->end_port);
312 entry->start_addr.as_u32 = ts2->start_addr.as_u32;
313 entry->end_addr.as_u32 = ts2->end_addr.as_u32;
316 ikev2_payload_add_data (c, data);
321 ikev2_payload_chain_add_padding (ikev2_payload_chain_t * c, int bs)
323 u8 *tmp __attribute__ ((unused));
324 u8 pad_len = (vec_len (c->data) / bs + 1) * bs - vec_len (c->data);
325 vec_add2 (c->data, tmp, pad_len);
326 c->data[vec_len (c->data) - 1] = pad_len - 1;
329 ikev2_sa_proposal_t *
330 ikev2_parse_sa_payload (ike_payload_header_t * ikep)
332 ikev2_sa_proposal_t *v = 0;
333 ikev2_sa_proposal_t *proposal;
334 ikev2_sa_transform_t *transform;
336 u32 plen = clib_net_to_host_u16 (ikep->length);
338 ike_sa_proposal_data_t *sap;
339 int proposal_ptr = 0;
343 sap = (ike_sa_proposal_data_t *) & ikep->payload[proposal_ptr];
347 /* IKE proposal should not have SPI */
348 if (sap->protocol_id == IKEV2_PROTOCOL_IKE && sap->spi_size != 0)
351 /* IKE proposal should not have SPI */
352 if (sap->protocol_id == IKEV2_PROTOCOL_ESP && sap->spi_size != 4)
355 transform_ptr = proposal_ptr + sizeof (*sap) + sap->spi_size;
357 vec_add2 (v, proposal, 1);
358 proposal->proposal_num = sap->proposal_num;
359 proposal->protocol_id = sap->protocol_id;
361 if (sap->spi_size == 4)
363 proposal->spi = clib_net_to_host_u32 (sap->spi[0]);
366 for (i = 0; i < sap->num_transforms; i++)
368 ike_sa_transform_data_t *tr =
369 (ike_sa_transform_data_t *) & ikep->payload[transform_ptr];
370 u16 tlen = clib_net_to_host_u16 (tr->transform_len);
372 if (tlen < sizeof (*tr))
375 vec_add2 (proposal->transforms, transform, 1);
377 transform->type = tr->transform_type;
378 transform->transform_id = clib_net_to_host_u16 (tr->transform_id);
379 if (tlen > sizeof (*tr))
380 vec_add (transform->attrs, tr->attributes, tlen - sizeof (*tr));
381 transform_ptr += tlen;
384 proposal_ptr += clib_net_to_host_u16 (sap->proposal_len);
386 while (proposal_ptr < (plen - sizeof (*ikep)) && sap->last_or_more == 2);
388 /* data validation */
389 if (proposal_ptr != (plen - sizeof (*ikep)) || sap->last_or_more)
395 ikev2_elog_detail ("SA payload data corrupted");
396 ikev2_sa_free_proposal_vector (&v);
401 ikev2_parse_ts_payload (ike_payload_header_t * ikep)
403 ike_ts_payload_header_t *tsp = (ike_ts_payload_header_t *) ikep;
404 ikev2_ts_t *r = 0, *ts;
407 for (i = 0; i < tsp->num_ts; i++)
409 if (tsp->ts[i].ts_type != 7) /* TS_IPV4_ADDR_RANGE */
411 ikev2_elog_uint (IKEV2_LOG_ERROR,
412 "unsupported TS type received (%u)", tsp->ts[i].ts_type);
417 ts->ts_type = tsp->ts[i].ts_type;
418 ts->protocol_id = tsp->ts[i].protocol_id;
419 ts->start_port = tsp->ts[i].start_port;
420 ts->end_port = tsp->ts[i].end_port;
421 ts->start_addr.as_u32 = tsp->ts[i].start_addr.as_u32;
422 ts->end_addr.as_u32 = tsp->ts[i].end_addr.as_u32;
428 ikev2_parse_notify_payload (ike_payload_header_t * ikep)
430 ike_notify_payload_header_t *n = (ike_notify_payload_header_t *) ikep;
431 u32 plen = clib_net_to_host_u16 (ikep->length);
432 ikev2_notify_t *r = 0;
435 r = vec_new (ikev2_notify_t, 1);
436 r->msg_type = clib_net_to_host_u16 (n->msg_type);
437 r->protocol_id = n->protocol_id;
439 if (n->spi_size == 4)
441 clib_memcpy (&spi, n->payload, n->spi_size);
442 r->spi = clib_net_to_host_u32 (spi);
444 else if (n->spi_size == 0)
450 clib_warning ("invalid SPI Size %d", n->spi_size);
453 if (plen > (sizeof (*n) + n->spi_size))
455 vec_add (r->data, n->payload + n->spi_size,
456 plen - sizeof (*n) - n->spi_size);
463 ikev2_parse_vendor_payload (ike_payload_header_t * ikep)
465 u32 plen = clib_net_to_host_u16 (ikep->length);
466 ikev2_elog_uint (IKEV2_LOG_DEBUG, "vendor payload skipped, len %d", plen);
470 ikev2_parse_delete_payload (ike_payload_header_t * ikep)
472 ike_delete_payload_header_t *d = (ike_delete_payload_header_t *) ikep;
473 ikev2_delete_t *r = 0, *del;
474 u16 num_of_spi = clib_net_to_host_u16 (d->num_of_spi);
477 if (d->protocol_id == IKEV2_PROTOCOL_IKE)
479 r = vec_new (ikev2_delete_t, 1);
484 r = vec_new (ikev2_delete_t, num_of_spi);
487 del->protocol_id = d->protocol_id;
488 del->spi = clib_net_to_host_u32 (d->spi[i++]);
496 * fd.io coding-style-patch-verification: ON
499 * eval: (c-set-style "gnu")