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 <vnet/ipsec/ikev2.h>
25 #include <vnet/ipsec/ikev2_priv.h>
27 typedef CLIB_PACKED (struct {
35 }) ike_notify_payload_header_t;
37 typedef CLIB_PACKED (struct {
43 ip4_address_t start_addr;
44 ip4_address_t end_addr;
45 }) ikev2_ts_payload_entry_t;
47 typedef CLIB_PACKED (struct {
53 ikev2_ts_payload_entry_t ts[0];
54 }) ike_ts_payload_header_t;
56 typedef CLIB_PACKED (struct {
65 }) ike_sa_proposal_data_t;
67 typedef CLIB_PACKED (struct {
75 }) ike_sa_transform_data_t;
77 typedef CLIB_PACKED (struct {
85 }) ike_delete_payload_header_t;
87 static ike_payload_header_t *
88 ikev2_payload_add_hdr(ikev2_payload_chain_t * c, u8 payload_type, int len)
90 ike_payload_header_t * hdr = (ike_payload_header_t *) &c->data[c->last_hdr_off];
94 hdr->nextpayload = payload_type;
96 c->first_payload_type = payload_type;
98 c->last_hdr_off = vec_len(c->data);
99 vec_add2(c->data, tmp, len);
100 hdr = (ike_payload_header_t *) tmp;
103 hdr->length = clib_host_to_net_u16(len);
109 ikev2_payload_add_data(ikev2_payload_chain_t * c, u8 * data)
112 ike_payload_header_t * hdr;
114 vec_append(c->data, data);
115 hdr = (ike_payload_header_t *) &c->data[c->last_hdr_off];
116 len = clib_net_to_host_u16(hdr->length);
117 hdr->length = clib_host_to_net_u16(len + vec_len(data));
121 ikev2_payload_add_notify(ikev2_payload_chain_t * c, u16 msg_type, u8 * data)
123 ike_notify_payload_header_t * n;
125 n = (ike_notify_payload_header_t *) ikev2_payload_add_hdr(c, IKEV2_PAYLOAD_NOTIFY, sizeof (*n));
126 n->msg_type = clib_host_to_net_u16(msg_type);
127 ikev2_payload_add_data(c, data);
131 ikev2_payload_add_sa(ikev2_payload_chain_t * c, ikev2_sa_proposal_t * proposals)
133 ike_payload_header_t * ph;
134 ike_sa_proposal_data_t * prop;
135 ike_sa_transform_data_t * tr;
136 ikev2_sa_proposal_t * p;
137 ikev2_sa_transform_t * t;
143 ikev2_payload_add_hdr(c, IKEV2_PAYLOAD_SA, sizeof (*ph));
145 vec_foreach(p, proposals)
147 int spi_size = (p->protocol_id == IKEV2_PROTOCOL_ESP) ? 4 : 0;
148 pr_data = vec_new(u8, sizeof(ike_sa_proposal_data_t) + spi_size);
149 prop = (ike_sa_proposal_data_t *) pr_data;
150 prop->last_or_more = proposals - p + 1 < vec_len(proposals) ? 2 : 0;
151 prop->protocol_id = p->protocol_id;
152 prop->proposal_num = p->proposal_num;
153 prop->spi_size = spi_size;
154 prop->num_transforms = vec_len(p->transforms);
157 prop->spi[0] = clib_host_to_net_u32(p->spi);
159 DBG_PLD("proposal num %u protocol_id %u last_or_more %u spi_size %u%s%U",
160 prop->proposal_num, prop->protocol_id, prop->last_or_more,
161 prop->spi_size, prop->spi_size ? " spi_data " : "",
162 format_hex_bytes, prop->spi, prop->spi_size);
164 vec_foreach(t, p->transforms)
166 vec_add2(tr_data, tmp, sizeof(*tr) + vec_len(t->attrs));
167 tr = (ike_sa_transform_data_t *) tmp;
168 tr->last_or_more = ((t - p->transforms) + 1 < vec_len(p->transforms)) ? 3 : 0;
169 tr->transform_type = t->type;
170 tr->transform_id = clib_host_to_net_u16(t->transform_id);
171 tr->transform_len = clib_host_to_net_u16(sizeof(*tr) + vec_len(t->attrs));
173 if (vec_len(t->attrs) > 0)
174 clib_memcpy(tr->attributes, t->attrs, vec_len(t->attrs));
176 DBG_PLD("transform type %U transform_id %u last_or_more %u attr_size %u%s%U",
177 format_ikev2_transform_type, tr->transform_type,
178 t->transform_id, tr->last_or_more, vec_len(t->attrs),
179 vec_len(t->attrs) ? " attrs " : "",
180 format_hex_bytes, tr->attributes, vec_len(t->attrs));
183 prop->proposal_len = clib_host_to_net_u16(vec_len(tr_data) + vec_len(pr_data));
184 ikev2_payload_add_data(c, pr_data);
185 ikev2_payload_add_data(c, tr_data);
192 ikev2_payload_add_ke(ikev2_payload_chain_t * c, u16 dh_group, u8 * dh_data)
194 ike_ke_payload_header_t * ke;
195 ke = (ike_ke_payload_header_t *) ikev2_payload_add_hdr(c, IKEV2_PAYLOAD_KE,
198 ke->dh_group = clib_host_to_net_u16(dh_group);
199 ikev2_payload_add_data(c, dh_data);
203 ikev2_payload_add_nonce(ikev2_payload_chain_t * c, u8 * nonce)
205 ikev2_payload_add_hdr(c, IKEV2_PAYLOAD_NONCE, sizeof (ike_payload_header_t));
206 ikev2_payload_add_data(c, nonce);
210 ikev2_payload_add_id(ikev2_payload_chain_t *c, ikev2_id_t * id, u8 type)
212 ike_id_payload_header_t * idp;
213 idp = (ike_id_payload_header_t *) ikev2_payload_add_hdr(c, type, sizeof (*idp));
215 idp->id_type = id->type;
216 ikev2_payload_add_data(c, id->data);
220 ikev2_payload_add_delete(ikev2_payload_chain_t *c, ikev2_delete_t * d)
222 ike_delete_payload_header_t * dp;
223 u16 num_of_spi = vec_len(d);
225 dp = (ike_delete_payload_header_t *) ikev2_payload_add_hdr(c, IKEV2_PAYLOAD_DELETE,
228 if (d[0].protocol_id == IKEV2_PROTOCOL_IKE)
234 dp->protocol_id = d[0].protocol_id;
236 dp->num_of_spi = clib_host_to_net_u16(num_of_spi);
239 u8 * data = vec_new(u8, 4);
240 u32 spi = clib_host_to_net_u32(d2->spi);
241 clib_memcpy(data, &spi, 4);
242 ikev2_payload_add_data(c, data);
249 ikev2_payload_add_auth(ikev2_payload_chain_t *c, ikev2_auth_t * auth)
251 ike_auth_payload_header_t * ap;
252 ap = (ike_auth_payload_header_t *) ikev2_payload_add_hdr(c, IKEV2_PAYLOAD_AUTH,
255 ap->auth_method = auth->method;
256 ikev2_payload_add_data(c, auth->data);
260 ikev2_payload_add_ts(ikev2_payload_chain_t * c, ikev2_ts_t * ts, u8 type)
262 ike_ts_payload_header_t * tsh;
264 u8 * data = 0, * tmp;
266 tsh = (ike_ts_payload_header_t *) ikev2_payload_add_hdr(c, type, sizeof (*tsh));
267 tsh->num_ts = vec_len(ts);
271 ASSERT(ts2->ts_type == 7); /*TS_IPV4_ADDR_RANGE */
272 ikev2_ts_payload_entry_t * entry;
273 vec_add2(data, tmp, sizeof(*entry));
274 entry = (ikev2_ts_payload_entry_t *) tmp;
275 entry->ts_type = ts2->ts_type;
276 entry->protocol_id = ts2->protocol_id;
277 entry->selector_len = clib_host_to_net_u16(16);
278 entry->start_port = clib_host_to_net_u16(ts2->start_port);
279 entry->end_port = clib_host_to_net_u16(ts2->end_port);
280 entry->start_addr.as_u32 = ts2->start_addr.as_u32;
281 entry->end_addr.as_u32 = ts2->end_addr.as_u32;
284 ikev2_payload_add_data(c, data);
289 ikev2_payload_chain_add_padding(ikev2_payload_chain_t * c, int bs)
291 u8 * tmp __attribute__((unused));
292 u8 pad_len = (vec_len(c->data) / bs + 1) * bs - vec_len(c->data);
293 vec_add2(c->data, tmp, pad_len);
294 c->data[vec_len(c->data)-1] = pad_len - 1;
297 ikev2_sa_proposal_t *
298 ikev2_parse_sa_payload(ike_payload_header_t * ikep)
300 ikev2_sa_proposal_t * v = 0;
301 ikev2_sa_proposal_t * proposal;
302 ikev2_sa_transform_t * transform;
304 u32 plen = clib_net_to_host_u16(ikep->length);
306 ike_sa_proposal_data_t * sap;
307 int proposal_ptr = 0;
311 sap = (ike_sa_proposal_data_t *) &ikep->payload[proposal_ptr];
315 DBG_PLD("proposal num %u len %u last_or_more %u id %u "
316 "spi_size %u num_transforms %u",
317 sap->proposal_num, clib_net_to_host_u16(sap->proposal_len),
318 sap->last_or_more, sap->protocol_id, sap->spi_size,
319 sap->num_transforms);
321 /* IKE proposal should not have SPI */
322 if (sap->protocol_id == IKEV2_PROTOCOL_IKE && sap->spi_size != 0)
325 /* IKE proposal should not have SPI */
326 if (sap->protocol_id == IKEV2_PROTOCOL_ESP && sap->spi_size != 4)
329 transform_ptr = proposal_ptr + sizeof(*sap) + sap->spi_size;
331 vec_add2(v, proposal, 1);
332 proposal->proposal_num = sap->proposal_num;
333 proposal->protocol_id = sap->protocol_id;
335 if (sap->spi_size == 4) {
336 proposal->spi = clib_net_to_host_u32(sap->spi[0]);
339 for(i=0; i< sap->num_transforms; i++)
341 ike_sa_transform_data_t * tr = (ike_sa_transform_data_t *) &ikep->payload[transform_ptr];
342 u16 tlen = clib_net_to_host_u16(tr->transform_len);
344 if (tlen < sizeof(*tr))
347 vec_add2(proposal->transforms, transform, 1);
349 transform->type = tr->transform_type;
350 transform->transform_id = clib_net_to_host_u16(tr->transform_id);
351 if (tlen > sizeof(*tr))
352 vec_add(transform->attrs, tr->attributes, tlen - sizeof(*tr));
354 DBG_PLD("transform num %u len %u last_or_more %u type %U id %u%s%U",
355 i, tlen, tr->last_or_more,
356 format_ikev2_sa_transform, transform,
357 clib_net_to_host_u16(tr->transform_id),
358 tlen > sizeof(*tr) ? " attrs " : "",
359 format_hex_bytes, tr->attributes, tlen - sizeof (*tr));
361 transform_ptr += tlen;
364 proposal_ptr += clib_net_to_host_u16(sap->proposal_len);
366 while (proposal_ptr < (plen - sizeof(*ikep)) && sap->last_or_more == 2);
368 /* data validation */
369 if (proposal_ptr != (plen - sizeof(*ikep)) || sap->last_or_more)
375 DBG_PLD("SA payload data corrupted");
376 ikev2_sa_free_proposal_vector(&v);
381 ikev2_parse_ts_payload(ike_payload_header_t * ikep)
383 ike_ts_payload_header_t * tsp = (ike_ts_payload_header_t *) ikep;
384 ikev2_ts_t * r = 0, *ts;
387 for (i = 0; i < tsp->num_ts; i++)
389 if (tsp->ts[i].ts_type != 7) /* TS_IPV4_ADDR_RANGE */
391 DBG_PLD("unsupported TS type received (%u)", tsp->ts[i].ts_type);
396 ts->ts_type = tsp->ts[i].ts_type;
397 ts->protocol_id = tsp->ts[i].protocol_id;
398 ts->start_port = tsp->ts[i].start_port;
399 ts->end_port = tsp->ts[i].end_port;
400 ts->start_addr.as_u32 = tsp->ts[i].start_addr.as_u32;
401 ts->end_addr.as_u32 = tsp->ts[i].end_addr.as_u32;
407 ikev2_parse_notify_payload(ike_payload_header_t * ikep)
409 ike_notify_payload_header_t * n = (ike_notify_payload_header_t *) ikep;
410 u32 plen = clib_net_to_host_u16(ikep->length);
411 ikev2_notify_t * r = 0;
414 DBG_PLD("msg_type %U len %u%s%U",
415 format_ikev2_notify_msg_type, clib_net_to_host_u16(n->msg_type),
416 plen, plen > sizeof(*n) ? " data ":"",
417 format_hex_bytes, n->payload, plen - sizeof(*n));
419 r = vec_new(ikev2_notify_t, 1);
420 r->msg_type = clib_net_to_host_u16(n->msg_type);
421 r->protocol_id = n->protocol_id;
423 if (n->spi_size == 4)
425 clib_memcpy(&spi, n->payload, n->spi_size);
426 r->spi = clib_net_to_host_u32(spi);
427 DBG_PLD("spi %lx", r->spi);
429 else if (n->spi_size == 0)
435 clib_warning("invalid SPI Size %d", n->spi_size);
438 if (plen > (sizeof(*n) + n->spi_size))
440 vec_add(r->data, n->payload + n->spi_size, plen - sizeof(*n) - n->spi_size);
447 ikev2_parse_vendor_payload(ike_payload_header_t * ikep)
449 u32 plen = clib_net_to_host_u16(ikep->length);
453 for(i=0; i < plen - 4; i++)
454 if (!isprint(ikep->payload[i]))
457 DBG_PLD("len %u data %s:%U",
459 is_string ? "string":"hex",
460 is_string ? format_ascii_bytes : format_hex_bytes,
461 ikep->payload, plen - sizeof(*ikep));
465 ikev2_parse_delete_payload(ike_payload_header_t * ikep)
467 ike_delete_payload_header_t * d = (ike_delete_payload_header_t *) ikep;
468 u32 plen = clib_net_to_host_u16(ikep->length);
469 ikev2_delete_t * r = 0, * del;
470 u16 num_of_spi = clib_net_to_host_u16(d->num_of_spi);
473 DBG_PLD("protocol_id %u spi_size %u num_of_spi %u len %u%s%U",
474 d->protocol_id, d->spi_size, num_of_spi,
475 plen, plen > sizeof(d) ? " data ":"",
476 format_hex_bytes, d->spi, plen - sizeof(*d));
478 if (d->protocol_id == IKEV2_PROTOCOL_IKE)
480 r = vec_new(ikev2_delete_t, 1);
485 r = vec_new(ikev2_delete_t, num_of_spi);
488 del->protocol_id = d->protocol_id;
489 del->spi = clib_net_to_host_u32(d->spi[i++]);