FD.io VPP  v16.06
Vector Packet Processing
ikev2_payload.c
Go to the documentation of this file.
1 /*
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:
6  *
7  * http://www.apache.org/licenses/LICENSE-2.0
8  *
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.
14  */
15 
16 #include <ctype.h>
17 
18 #include <vnet/vnet.h>
19 #include <vnet/api_errno.h>
20 #include <vnet/ip/ip.h>
21 #include <vnet/interface.h>
22 
23 #include <vnet/ipsec/ipsec.h>
24 #include <vnet/ipsec/ikev2.h>
25 #include <vnet/ipsec/ikev2_priv.h>
26 
27 typedef CLIB_PACKED (struct {
28  u8 nextpayload;
29  u8 flags;
30  u16 length;
31  u8 protocol_id;
32  u8 spi_size;
33  u16 msg_type;
34  u8 payload[0];
35 }) ike_notify_payload_header_t;
36 
37 typedef CLIB_PACKED (struct {
38  u8 ts_type;
39  u8 protocol_id;
40  u16 selector_len;
41  u16 start_port;
42  u16 end_port;
43  ip4_address_t start_addr;
44  ip4_address_t end_addr;
46 
47 typedef CLIB_PACKED (struct {
48  u8 nextpayload;
49  u8 flags;
50  u16 length;
51  u8 num_ts;
52  u8 reserved[3];
54 }) ike_ts_payload_header_t;
55 
56 typedef CLIB_PACKED (struct {
57  u8 last_or_more;
58  u8 reserved;
59  u16 proposal_len;
60  u8 proposal_num;
61  u8 protocol_id;
62  u8 spi_size;
63  u8 num_transforms;
64  u32 spi[0];
66 
67 typedef CLIB_PACKED (struct {
68  u8 last_or_more;
69  u8 reserved;
70  u16 transform_len;
71  u8 transform_type;
72  u8 reserved2;
73  u16 transform_id;
74  u8 attributes[0];
75 }) ike_sa_transform_data_t;
76 
77 typedef CLIB_PACKED (struct {
78  u8 nextpayload;
79  u8 flags;
80  u16 length;
81  u8 protocol_id;
82  u8 spi_size;
83  u16 num_of_spi;
84  u32 spi[0];
86 
87 static ike_payload_header_t *
88 ikev2_payload_add_hdr(ikev2_payload_chain_t * c, u8 payload_type, int len)
89 {
90  ike_payload_header_t * hdr = (ike_payload_header_t *) &c->data[c->last_hdr_off];
91  u8 * tmp;
92 
93  if (c->data)
94  hdr->nextpayload = payload_type;
95  else
96  c->first_payload_type = payload_type;
97 
98  c->last_hdr_off = vec_len(c->data);
99  vec_add2(c->data, tmp, len);
100  hdr = (ike_payload_header_t *) tmp;
101  memset(hdr, 0, len);
102 
103  hdr->length = clib_host_to_net_u16(len);
104 
105  return hdr;
106 }
107 
108 static void
110 {
111  u16 len;
112  ike_payload_header_t * hdr;
113 
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));
118 }
119 
120 void
122 {
123  ike_notify_payload_header_t * n;
124 
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);
128 }
129 
130 void
132 {
133  ike_payload_header_t * ph;
134  ike_sa_proposal_data_t * prop;
135  ike_sa_transform_data_t * tr;
138 
139  u8 * tmp;
140  u8 * pr_data = 0;
141  u8 * tr_data = 0;
142 
143  ikev2_payload_add_hdr(c, IKEV2_PAYLOAD_SA, sizeof (*ph));
144 
145  vec_foreach(p, proposals)
146  {
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);
155 
156  if (spi_size)
157  prop->spi[0] = clib_host_to_net_u32(p->spi);
158 
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);
163 
164  vec_foreach(t, p->transforms)
165  {
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));
172 
173  if (vec_len(t->attrs) > 0)
174  clib_memcpy(tr->attributes, t->attrs, vec_len(t->attrs));
175 
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));
181  }
182 
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);
186  vec_free(pr_data);
187  vec_free(tr_data);
188  }
189 }
190 
191 void
193 {
194  ike_ke_payload_header_t * ke;
195  ke = (ike_ke_payload_header_t *) ikev2_payload_add_hdr(c, IKEV2_PAYLOAD_KE,
196  sizeof (*ke));
197 
198  ke->dh_group = clib_host_to_net_u16(dh_group);
199  ikev2_payload_add_data(c, dh_data);
200 }
201 
202 void
204 {
205  ikev2_payload_add_hdr(c, IKEV2_PAYLOAD_NONCE, sizeof (ike_payload_header_t));
206  ikev2_payload_add_data(c, nonce);
207 }
208 
209 void
211 {
212  ike_id_payload_header_t * idp;
213  idp = (ike_id_payload_header_t *) ikev2_payload_add_hdr(c, type, sizeof (*idp));
214 
215  idp->id_type = id->type;
217 }
218 
219 void
221 {
223  u16 num_of_spi = vec_len(d);
224  ikev2_delete_t * d2;
226  sizeof (*dp));
227 
228  if (d[0].protocol_id == IKEV2_PROTOCOL_IKE)
229  {
230  dp->protocol_id = 1;
231  }
232  else
233  {
234  dp->protocol_id = d[0].protocol_id;
235  dp->spi_size = 4;
236  dp->num_of_spi = clib_host_to_net_u16(num_of_spi);
237  vec_foreach(d2, d)
238  {
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);
243  vec_free(data);
244  }
245  }
246 }
247 
248 void
250 {
251  ike_auth_payload_header_t * ap;
252  ap = (ike_auth_payload_header_t *) ikev2_payload_add_hdr(c, IKEV2_PAYLOAD_AUTH,
253  sizeof (*ap));
254 
255  ap->auth_method = auth->method;
256  ikev2_payload_add_data(c, auth->data);
257 }
258 
259 void
261 {
262  ike_ts_payload_header_t * tsh;
263  ikev2_ts_t *ts2;
264  u8 * data = 0, * tmp;
265 
266  tsh = (ike_ts_payload_header_t *) ikev2_payload_add_hdr(c, type, sizeof (*tsh));
267  tsh->num_ts = vec_len(ts);
268 
269  vec_foreach(ts2, ts)
270  {
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;
282  }
283 
284  ikev2_payload_add_data(c, data);
285  vec_free(data);
286 }
287 
288 void
290 {
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;
295 }
296 
298 ikev2_parse_sa_payload(ike_payload_header_t * ikep)
299 {
300  ikev2_sa_proposal_t * v = 0;
301  ikev2_sa_proposal_t * proposal;
302  ikev2_sa_transform_t * transform;
303 
304  u32 plen = clib_net_to_host_u16(ikep->length);
305 
307  int proposal_ptr = 0;
308 
309  do
310  {
311  sap = (ike_sa_proposal_data_t *) &ikep->payload[proposal_ptr];
312  int i;
313  int transform_ptr;
314 
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);
320 
321  /* IKE proposal should not have SPI */
322  if (sap->protocol_id == IKEV2_PROTOCOL_IKE && sap->spi_size != 0)
323  goto data_corrupted;
324 
325  /* IKE proposal should not have SPI */
326  if (sap->protocol_id == IKEV2_PROTOCOL_ESP && sap->spi_size != 4)
327  goto data_corrupted;
328 
329  transform_ptr = proposal_ptr + sizeof(*sap) + sap->spi_size;
330 
331  vec_add2(v, proposal, 1);
332  proposal->proposal_num = sap->proposal_num;
333  proposal->protocol_id = sap->protocol_id;
334 
335  if (sap->spi_size == 4) {
336  proposal->spi = clib_net_to_host_u32(sap->spi[0]);
337  }
338 
339  for(i=0; i< sap->num_transforms; i++)
340  {
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);
343 
344  if (tlen < sizeof(*tr))
345  goto data_corrupted;
346 
347  vec_add2(proposal->transforms, transform, 1);
348 
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));
353 
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));
360 
361  transform_ptr += tlen;
362  }
363 
364  proposal_ptr += clib_net_to_host_u16(sap->proposal_len);
365  }
366  while (proposal_ptr < (plen - sizeof(*ikep)) && sap->last_or_more == 2);
367 
368  /* data validation */
369  if (proposal_ptr != (plen - sizeof(*ikep)) || sap->last_or_more)
370  goto data_corrupted;
371 
372  return v;
373 
374 data_corrupted:
375  DBG_PLD("SA payload data corrupted");
377  return 0;
378 }
379 
380 ikev2_ts_t *
381 ikev2_parse_ts_payload(ike_payload_header_t * ikep)
382 {
383  ike_ts_payload_header_t * tsp = (ike_ts_payload_header_t *) ikep;
384  ikev2_ts_t * r = 0, *ts;
385  u8 i;
386 
387  for (i = 0; i < tsp->num_ts; i++)
388  {
389  if (tsp->ts[i].ts_type != 7) /* TS_IPV4_ADDR_RANGE */
390  {
391  DBG_PLD("unsupported TS type received (%u)", tsp->ts[i].ts_type);
392  continue;
393  }
394 
395  vec_add2(r, ts, 1);
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;
402  }
403  return r;
404 }
405 
407 ikev2_parse_notify_payload(ike_payload_header_t * ikep)
408 {
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;
412  u32 spi;
413 
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));
418 
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;
422 
423  if (n->spi_size == 4)
424  {
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);
428  }
429  else if (n->spi_size == 0)
430  {
431  r->spi = 0;
432  }
433  else
434  {
435  clib_warning("invalid SPI Size %d", n->spi_size);
436  }
437 
438  if (plen > (sizeof(*n) + n->spi_size))
439  {
440  vec_add(r->data, n->payload + n->spi_size, plen - sizeof(*n) - n->spi_size);
441  }
442 
443  return r;
444 }
445 
446 void
447 ikev2_parse_vendor_payload(ike_payload_header_t * ikep)
448 {
449  u32 plen = clib_net_to_host_u16(ikep->length);
450  int i;
451  int is_string = 1;
452 
453  for(i=0; i < plen - 4; i++)
454  if (!isprint(ikep->payload[i]))
455  is_string = 0;
456 
457  DBG_PLD("len %u data %s:%U",
458  plen,
459  is_string ? "string":"hex",
460  is_string ? format_ascii_bytes : format_hex_bytes,
461  ikep->payload, plen - sizeof(*ikep));
462 }
463 
465 ikev2_parse_delete_payload(ike_payload_header_t * ikep)
466 {
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);
471  u16 i = 0;
472 
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));
477 
478  if (d->protocol_id == IKEV2_PROTOCOL_IKE)
479  {
480  r = vec_new(ikev2_delete_t, 1);
481  r->protocol_id = 1;
482  }
483  else
484  {
485  r = vec_new(ikev2_delete_t, num_of_spi);
486  vec_foreach(del, r)
487  {
488  del->protocol_id = d->protocol_id;
489  del->spi = clib_net_to_host_u32(d->spi[i++]);
490  }
491  }
492 
493  return r;
494 }
void ikev2_payload_add_nonce(ikev2_payload_chain_t *c, u8 *nonce)
ikev2_transform_type_t type
Definition: ikev2_priv.h:65
sll srl srl sll sra u16x4 i
Definition: vector_sse2.h:267
#define IKEV2_PAYLOAD_NONCE
Definition: ikev2.h:94
void ikev2_payload_add_notify(ikev2_payload_chain_t *c, u16 msg_type, u8 *data)
u8 * format_ascii_bytes(u8 *s, va_list *va)
Definition: std-formats.c:70
bad routing header type(not 4)") sr_error (NO_MORE_SEGMENTS
void ikev2_payload_add_sa(ikev2_payload_chain_t *c, ikev2_sa_proposal_t *proposals)
ikev2_sa_proposal_t * ikev2_parse_sa_payload(ike_payload_header_t *ikep)
ikev2_ts_t * ikev2_parse_ts_payload(ike_payload_header_t *ikep)
u8 * format_ikev2_sa_transform(u8 *s, va_list *args)
Definition: ikev2_format.c:24
typedef CLIB_PACKED(struct{u8 nextpayload;u8 flags;u16 length;u8 protocol_id;u8 spi_size;u16 msg_type;u8 payload[0];})
Definition: ikev2_payload.c:27
#define vec_add2(V, P, N)
Add N elements to end of vector V, return pointer to new elements in P.
Definition: vec.h:519
void ikev2_payload_add_ke(ikev2_payload_chain_t *c, u16 dh_group, u8 *dh_data)
ikev2_ts_payload_entry_t
Definition: ikev2_payload.c:45
ikev2_notify_t * ikev2_parse_notify_payload(ike_payload_header_t *ikep)
#define vec_add(V, E, N)
Add N elements to end of vector V (no header, unspecified alignment)
Definition: vec.h:557
#define IKEV2_PAYLOAD_DELETE
Definition: ikev2.h:96
#define vec_new(T, N)
Create new vector of given type and length (unspecified alignment, no header).
Definition: vec.h:268
void ikev2_parse_vendor_payload(ike_payload_header_t *ikep)
ip4_address_t start_addr
Definition: ikev2_priv.h:99
u8 * format_hex_bytes(u8 *s, va_list *va)
Definition: std-formats.c:79
void ikev2_payload_add_id(ikev2_payload_chain_t *c, ikev2_id_t *id, u8 type)
#define IKEV2_PAYLOAD_NOTIFY
Definition: ikev2.h:95
#define clib_warning(format, args...)
Definition: error.h:59
ikev2_sa_transform_t * transforms
Definition: ikev2_priv.h:90
#define IKEV2_PAYLOAD_SA
Definition: ikev2.h:89
ike_sa_proposal_data_t
Definition: ikev2_payload.c:65
u16 end_port
Definition: ikev2_priv.h:98
#define DBG_PLD(my_args...)
Definition: ikev2_priv.h:36
ip4_address_t end_addr
Definition: ikev2_priv.h:100
void ikev2_payload_add_delete(ikev2_payload_chain_t *c, ikev2_delete_t *d)
u8 * format_ikev2_notify_msg_type(u8 *s, va_list *args)
ikev2_auth_method_t method
Definition: ikev2_priv.h:53
#define vec_free(V)
Free vector&#39;s memory (no header).
Definition: vec.h:298
#define clib_memcpy(a, b, c)
Definition: string.h:63
static ike_payload_header_t * ikev2_payload_add_hdr(ikev2_payload_chain_t *c, u8 payload_type, int len)
Definition: ikev2_payload.c:88
#define IKEV2_PAYLOAD_KE
Definition: ikev2.h:90
void ikev2_payload_add_auth(ikev2_payload_chain_t *c, ikev2_auth_t *auth)
ikev2_protocol_id_t protocol_id
Definition: ikev2_priv.h:88
u8 protocol_id
Definition: ikev2_priv.h:95
#define ASSERT(truth)
unsigned int u32
Definition: types.h:88
ike_delete_payload_header_t
Definition: ikev2_payload.c:85
u8 * format_ikev2_transform_type(u8 *s, va_list *args)
void ikev2_sa_free_proposal_vector(ikev2_sa_proposal_t **v)
Definition: ikev2.c:214
#define IKEV2_PAYLOAD_AUTH
Definition: ikev2.h:93
#define vec_append(v1, v2)
Append v2 after v1.
Definition: vec.h:777
static void ikev2_payload_add_data(ikev2_payload_chain_t *c, u8 *data)
unsigned short u16
Definition: types.h:57
#define vec_len(v)
Number of elements in vector (rvalue-only, NULL tolerant)
u16 start_port
Definition: ikev2_priv.h:97
unsigned char u8
Definition: types.h:56
void ikev2_payload_chain_add_padding(ikev2_payload_chain_t *c, int bs)
#define vec_foreach(var, vec)
Vector iterator.
u32 flags
Definition: vhost-user.h:73
void ikev2_payload_add_ts(ikev2_payload_chain_t *c, ikev2_ts_t *ts, u8 type)
ikev2_delete_t * ikev2_parse_delete_payload(ike_payload_header_t *ikep)