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.
16 #include <vnet/vnet.h>
17 #include <vnet/api_errno.h>
18 #include <vnet/ip/ip.h>
19 #include <vnet/interface.h>
21 #include <vnet/ipsec/ipsec.h>
22 #include <vnet/ipsec/ikev2.h>
23 #include <vnet/ipsec/ikev2_priv.h>
25 typedef CLIB_PACKED (struct {
33 }) ike_notify_payload_header_t;
35 typedef CLIB_PACKED (struct {
41 ip4_address_t start_addr;
42 ip4_address_t end_addr;
43 }) ikev2_ts_payload_entry_t;
45 typedef CLIB_PACKED (struct {
51 ikev2_ts_payload_entry_t ts[0];
52 }) ike_ts_payload_header_t;
54 typedef CLIB_PACKED (struct {
63 }) ike_sa_proposal_data_t;
65 typedef CLIB_PACKED (struct {
73 }) ike_sa_transform_data_t;
75 typedef CLIB_PACKED (struct {
83 }) ike_delete_payload_header_t;
85 static ike_payload_header_t *
86 ikev2_payload_add_hdr(ikev2_payload_chain_t * c, u8 payload_type, int len)
88 ike_payload_header_t * hdr = (ike_payload_header_t *) &c->data[c->last_hdr_off];
92 hdr->nextpayload = payload_type;
94 c->first_payload_type = payload_type;
96 c->last_hdr_off = vec_len(c->data);
97 vec_add2(c->data, tmp, len);
98 hdr = (ike_payload_header_t *) tmp;
101 hdr->length = clib_host_to_net_u16(len);
107 ikev2_payload_add_data(ikev2_payload_chain_t * c, u8 * data)
110 ike_payload_header_t * hdr;
112 vec_append(c->data, data);
113 hdr = (ike_payload_header_t *) &c->data[c->last_hdr_off];
114 len = clib_net_to_host_u16(hdr->length);
115 hdr->length = clib_host_to_net_u16(len + vec_len(data));
119 ikev2_payload_add_notify(ikev2_payload_chain_t * c, u16 msg_type, u8 * data)
121 ike_notify_payload_header_t * n;
123 n = (ike_notify_payload_header_t *) ikev2_payload_add_hdr(c, IKEV2_PAYLOAD_NOTIFY, sizeof (*n));
124 n->msg_type = clib_host_to_net_u16(msg_type);
125 ikev2_payload_add_data(c, data);
129 ikev2_payload_add_sa(ikev2_payload_chain_t * c, ikev2_sa_proposal_t * proposals)
131 ike_payload_header_t * ph;
132 ike_sa_proposal_data_t * prop;
133 ike_sa_transform_data_t * tr;
134 ikev2_sa_proposal_t * p;
135 ikev2_sa_transform_t * t;
141 ikev2_payload_add_hdr(c, IKEV2_PAYLOAD_SA, sizeof (*ph));
143 vec_foreach(p, proposals)
145 int spi_size = (p->protocol_id == IKEV2_PROTOCOL_ESP) ? 4 : 0;
146 pr_data = vec_new(u8, sizeof(ike_sa_proposal_data_t) + spi_size);
147 prop = (ike_sa_proposal_data_t *) pr_data;
148 prop->last_or_more = proposals - p + 1 < vec_len(proposals) ? 2 : 0;
149 prop->protocol_id = p->protocol_id;
150 prop->proposal_num = p->proposal_num;
151 prop->spi_size = spi_size;
152 prop->num_transforms = vec_len(p->transforms);
155 prop->spi[0] = clib_host_to_net_u32(p->spi);
157 DBG_PLD("proposal num %u protocol_id %u last_or_more %u spi_size %u%s%U",
158 prop->proposal_num, prop->protocol_id, prop->last_or_more,
159 prop->spi_size, prop->spi_size ? " spi_data " : "",
160 format_hex_bytes, prop->spi, prop->spi_size);
162 vec_foreach(t, p->transforms)
164 vec_add2(tr_data, tmp, sizeof(*tr) + vec_len(t->attrs));
165 tr = (ike_sa_transform_data_t *) tmp;
166 tr->last_or_more = ((t - p->transforms) + 1 < vec_len(p->transforms)) ? 3 : 0;
167 tr->transform_type = t->type;
168 tr->transform_id = clib_host_to_net_u16(t->transform_id);
169 tr->transform_len = clib_host_to_net_u16(sizeof(*tr) + vec_len(t->attrs));
171 if (vec_len(t->attrs) > 0)
172 memcpy(tr->attributes, t->attrs, vec_len(t->attrs));
174 DBG_PLD("transform type %U transform_id %u last_or_more %u attr_size %u%s%U",
175 format_ikev2_transform_type, tr->transform_type,
176 t->transform_id, tr->last_or_more, vec_len(t->attrs),
177 vec_len(t->attrs) ? " attrs " : "",
178 format_hex_bytes, tr->attributes, vec_len(t->attrs));
181 prop->proposal_len = clib_host_to_net_u16(vec_len(tr_data) + vec_len(pr_data));
182 ikev2_payload_add_data(c, pr_data);
183 ikev2_payload_add_data(c, tr_data);
190 ikev2_payload_add_ke(ikev2_payload_chain_t * c, u16 dh_group, u8 * dh_data)
192 ike_ke_payload_header_t * ke;
193 ke = (ike_ke_payload_header_t *) ikev2_payload_add_hdr(c, IKEV2_PAYLOAD_KE,
196 ke->dh_group = clib_host_to_net_u16(dh_group);
197 ikev2_payload_add_data(c, dh_data);
201 ikev2_payload_add_nonce(ikev2_payload_chain_t * c, u8 * nonce)
203 ikev2_payload_add_hdr(c, IKEV2_PAYLOAD_NONCE, sizeof (ike_payload_header_t));
204 ikev2_payload_add_data(c, nonce);
208 ikev2_payload_add_id(ikev2_payload_chain_t *c, ikev2_id_t * id, u8 type)
210 ike_id_payload_header_t * idp;
211 idp = (ike_id_payload_header_t *) ikev2_payload_add_hdr(c, type, sizeof (*idp));
213 idp->id_type = id->type;
214 ikev2_payload_add_data(c, id->data);
218 ikev2_payload_add_delete(ikev2_payload_chain_t *c, ikev2_delete_t * d)
220 ike_delete_payload_header_t * dp;
221 u16 num_of_spi = vec_len(d);
223 dp = (ike_delete_payload_header_t *) ikev2_payload_add_hdr(c, IKEV2_PAYLOAD_DELETE,
226 if (d[0].protocol_id == IKEV2_PROTOCOL_IKE)
232 dp->protocol_id = d[0].protocol_id;
234 dp->num_of_spi = clib_host_to_net_u16(num_of_spi);
237 u8 * data = vec_new(u8, 4);
238 u32 spi = clib_host_to_net_u32(d2->spi);
239 memcpy(data, &spi, 4);
240 ikev2_payload_add_data(c, data);
247 ikev2_payload_add_auth(ikev2_payload_chain_t *c, ikev2_auth_t * auth)
249 ike_auth_payload_header_t * ap;
250 ap = (ike_auth_payload_header_t *) ikev2_payload_add_hdr(c, IKEV2_PAYLOAD_AUTH,
253 ap->auth_method = auth->method;
254 ikev2_payload_add_data(c, auth->data);
258 ikev2_payload_add_ts(ikev2_payload_chain_t * c, ikev2_ts_t * ts, u8 type)
260 ike_ts_payload_header_t * tsh;
262 u8 * data = 0, * tmp;
264 tsh = (ike_ts_payload_header_t *) ikev2_payload_add_hdr(c, type, sizeof (*tsh));
265 tsh->num_ts = vec_len(ts);
269 ASSERT(ts2->ts_type == 7); /*TS_IPV4_ADDR_RANGE */
270 ikev2_ts_payload_entry_t * entry;
271 vec_add2(data, tmp, sizeof(*entry));
272 entry = (ikev2_ts_payload_entry_t *) tmp;
273 entry->ts_type = ts2->ts_type;
274 entry->protocol_id = ts2->protocol_id;
275 entry->selector_len = clib_host_to_net_u16(16);
276 entry->start_port = clib_host_to_net_u16(ts2->start_port);
277 entry->end_port = clib_host_to_net_u16(ts2->end_port);
278 entry->start_addr.as_u32 = ts2->start_addr.as_u32;
279 entry->end_addr.as_u32 = ts2->end_addr.as_u32;
282 ikev2_payload_add_data(c, data);
287 ikev2_payload_chain_add_padding(ikev2_payload_chain_t * c, int bs)
289 u8 * tmp __attribute__((unused));
290 u8 pad_len = (vec_len(c->data) / bs + 1) * bs - vec_len(c->data);
291 vec_add2(c->data, tmp, pad_len);
292 c->data[vec_len(c->data)-1] = pad_len - 1;
295 ikev2_sa_proposal_t *
296 ikev2_parse_sa_payload(ike_payload_header_t * ikep)
298 ikev2_sa_proposal_t * v = 0;
299 ikev2_sa_proposal_t * proposal;
300 ikev2_sa_transform_t * transform;
302 u32 plen = clib_net_to_host_u16(ikep->length);
304 ike_sa_proposal_data_t * sap;
305 int proposal_ptr = 0;
309 sap = (ike_sa_proposal_data_t *) &ikep->payload[proposal_ptr];
313 DBG_PLD("proposal num %u len %u last_or_more %u id %u "
314 "spi_size %u num_transforms %u",
315 sap->proposal_num, clib_net_to_host_u16(sap->proposal_len),
316 sap->last_or_more, sap->protocol_id, sap->spi_size,
317 sap->num_transforms);
319 /* IKE proposal should not have SPI */
320 if (sap->protocol_id == IKEV2_PROTOCOL_IKE && sap->spi_size != 0)
323 /* IKE proposal should not have SPI */
324 if (sap->protocol_id == IKEV2_PROTOCOL_ESP && sap->spi_size != 4)
327 transform_ptr = proposal_ptr + sizeof(*sap) + sap->spi_size;
329 vec_add2(v, proposal, 1);
330 proposal->proposal_num = sap->proposal_num;
331 proposal->protocol_id = sap->protocol_id;
333 if (sap->spi_size == 4) {
334 proposal->spi = clib_net_to_host_u32(sap->spi[0]);
337 for(i=0; i< sap->num_transforms; i++)
339 ike_sa_transform_data_t * tr = (ike_sa_transform_data_t *) &ikep->payload[transform_ptr];
340 u16 tlen = clib_net_to_host_u16(tr->transform_len);
342 if (tlen < sizeof(*tr))
345 vec_add2(proposal->transforms, transform, 1);
347 transform->type = tr->transform_type;
348 transform->transform_id = clib_net_to_host_u16(tr->transform_id);
349 if (tlen > sizeof(*tr))
350 vec_add(transform->attrs, tr->attributes, tlen - sizeof(*tr));
352 DBG_PLD("transform num %u len %u last_or_more %u type %U id %u%s%U",
353 i, tlen, tr->last_or_more,
354 format_ikev2_sa_transform, transform,
355 clib_net_to_host_u16(tr->transform_id),
356 tlen > sizeof(*tr) ? " attrs " : "",
357 format_hex_bytes, tr->attributes, tlen - sizeof (*tr));
359 transform_ptr += tlen;
362 proposal_ptr += clib_net_to_host_u16(sap->proposal_len);
364 while (proposal_ptr < (plen - sizeof(*ikep)) && sap->last_or_more == 2);
366 /* data validation */
367 if (proposal_ptr != (plen - sizeof(*ikep)) || sap->last_or_more)
373 DBG_PLD("SA payload data corrupted");
374 ikev2_sa_free_proposal_vector(&v);
379 ikev2_parse_ts_payload(ike_payload_header_t * ikep)
381 ike_ts_payload_header_t * tsp = (ike_ts_payload_header_t *) ikep;
382 ikev2_ts_t * r = 0, *ts;
385 for (i = 0; i < tsp->num_ts; i++)
387 if (tsp->ts[i].ts_type != 7) /* TS_IPV4_ADDR_RANGE */
389 DBG_PLD("unsupported TS type received (%u)", tsp->ts[i].ts_type);
394 ts->ts_type = tsp->ts[i].ts_type;
395 ts->protocol_id = tsp->ts[i].protocol_id;
396 ts->start_port = tsp->ts[i].start_port;
397 ts->end_port = tsp->ts[i].end_port;
398 ts->start_addr.as_u32 = tsp->ts[i].start_addr.as_u32;
399 ts->end_addr.as_u32 = tsp->ts[i].end_addr.as_u32;
405 ikev2_parse_notify_payload(ike_payload_header_t * ikep)
407 ike_notify_payload_header_t * n = (ike_notify_payload_header_t *) ikep;
408 u32 plen = clib_net_to_host_u16(ikep->length);
409 ikev2_notify_t * r = 0;
412 DBG_PLD("msg_type %U len %u%s%U",
413 format_ikev2_notify_msg_type, clib_net_to_host_u16(n->msg_type),
414 plen, plen > sizeof(*n) ? " data ":"",
415 format_hex_bytes, n->payload, plen - sizeof(*n));
417 r = vec_new(ikev2_notify_t, 1);
418 r->msg_type = clib_net_to_host_u16(n->msg_type);
419 r->protocol_id = n->protocol_id;
421 if (n->spi_size == 4)
423 memcpy(&spi, n->payload, n->spi_size);
424 r->spi = clib_net_to_host_u32(spi);
425 DBG_PLD("spi %lx", r->spi);
427 else if (n->spi_size == 0)
433 clib_warning("invalid SPI Size %d", n->spi_size);
436 if (plen > (sizeof(*n) + n->spi_size))
438 vec_add(r->data, n->payload + n->spi_size, plen - sizeof(*n) - n->spi_size);
445 ikev2_parse_vendor_payload(ike_payload_header_t * ikep)
447 u32 plen = clib_net_to_host_u16(ikep->length);
451 for(i=0; i < plen - 4; i++)
452 if (!isprint(ikep->payload[i]))
455 DBG_PLD("len %u data %s:%U",
457 is_string ? "string":"hex",
458 is_string ? format_ascii_bytes : format_hex_bytes,
459 ikep->payload, plen - sizeof(*ikep));
463 ikev2_parse_delete_payload(ike_payload_header_t * ikep)
465 ike_delete_payload_header_t * d = (ike_delete_payload_header_t *) ikep;
466 u32 plen = clib_net_to_host_u16(ikep->length);
467 ikev2_delete_t * r = 0, * del;
468 u16 num_of_spi = clib_net_to_host_u16(d->num_of_spi);
471 DBG_PLD("protocol_id %u spi_size %u num_of_spi %u len %u%s%U",
472 d->protocol_id, d->spi_size, num_of_spi,
473 plen, plen > sizeof(d) ? " data ":"",
474 format_hex_bytes, d->spi, plen - sizeof(*d));
476 if (d->protocol_id == IKEV2_PROTOCOL_IKE)
478 r = vec_new(ikev2_delete_t, 1);
483 r = vec_new(ikev2_delete_t, num_of_spi);
486 del->protocol_id = d->protocol_id;
487 del->spi = clib_net_to_host_u32(d->spi[i++]);