ikev2: accept rekey request for IKE SA
[vpp.git] / src / plugins / ikev2 / ikev2_payload.c
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 <plugins/ikev2/ikev2.h>
25 #include <plugins/ikev2/ikev2_priv.h>
26
27 /* *INDENT-OFF* */
28 typedef CLIB_PACKED (struct {
29   u8 nextpayload;
30   u8 flags;
31   u16 length;
32   u8 protocol_id;
33   u8 spi_size;
34   u16 msg_type;
35   u8 payload[0];
36 }) ike_notify_payload_header_t;
37 /* *INDENT-ON* */
38
39 /* *INDENT-OFF* */
40 typedef CLIB_PACKED (struct {
41   ip4_address_t start_addr;
42   ip4_address_t end_addr;
43 }) ikev2_ip4_addr_pair_t;
44
45 typedef CLIB_PACKED (struct {
46   ip6_address_t start_addr;
47   ip6_address_t end_addr;
48 }) ikev2_ip6_addr_pair_t;
49
50 typedef CLIB_PACKED (struct {
51   u8 ts_type;
52   u8 protocol_id;
53   u16 selector_len;
54   u16 start_port;
55   u16 end_port;
56   u8 addr_pair[0];
57 }) ikev2_ts_payload_entry_t;
58 /* *INDENT-OFF* */
59
60 /* *INDENT-OFF* */
61 typedef CLIB_PACKED (struct {
62   u8 nextpayload;
63   u8 flags;
64   u16 length;
65   u8 num_ts;
66   u8 reserved[3];
67   ikev2_ts_payload_entry_t ts[0];
68 }) ike_ts_payload_header_t;
69 /* *INDENT-OFF* */
70
71 /* *INDENT-OFF* */
72 typedef CLIB_PACKED (struct {
73   u8 last_or_more;
74   u8 reserved;
75   u16 proposal_len;
76   u8 proposal_num;
77   u8 protocol_id;
78   u8 spi_size;
79   u8 num_transforms; u32 spi[0];
80 }) ike_sa_proposal_data_t;
81 /* *INDENT-OFF* */
82
83 /* *INDENT-OFF* */
84 typedef CLIB_PACKED (struct {
85   u8 last_or_more;
86   u8 reserved;
87   u16 transform_len;
88   u8 transform_type;
89   u8 reserved2;
90   u16 transform_id;
91   u8 attributes[0];
92 }) ike_sa_transform_data_t;
93 /* *INDENT-OFF* */
94
95 /* *INDENT-OFF* */
96 typedef CLIB_PACKED (struct {
97   u8 nextpayload;
98   u8 flags;
99   u16 length;
100   u8 protocol_id;
101   u8 spi_size;
102   u16 num_of_spi;
103   u32 spi[0];
104 }) ike_delete_payload_header_t;
105 /* *INDENT-OFF* */
106
107 static ike_payload_header_t *
108 ikev2_payload_add_hdr (ikev2_payload_chain_t * c, u8 payload_type, int len)
109 {
110   ike_payload_header_t *hdr =
111     (ike_payload_header_t *) & c->data[c->last_hdr_off];
112   u8 *tmp;
113
114   if (c->data)
115     hdr->nextpayload = payload_type;
116   else
117     c->first_payload_type = payload_type;
118
119   c->last_hdr_off = vec_len (c->data);
120   vec_add2 (c->data, tmp, len);
121   hdr = (ike_payload_header_t *) tmp;
122   clib_memset (hdr, 0, len);
123
124   hdr->length = clib_host_to_net_u16 (len);
125
126   return hdr;
127 }
128
129 static void
130 ikev2_payload_add_data (ikev2_payload_chain_t * c, u8 * data)
131 {
132   u16 len;
133   ike_payload_header_t *hdr;
134
135   vec_append (c->data, data);
136   hdr = (ike_payload_header_t *) & c->data[c->last_hdr_off];
137   len = clib_net_to_host_u16 (hdr->length);
138   hdr->length = clib_host_to_net_u16 (len + vec_len (data));
139 }
140
141 void
142 ikev2_payload_add_notify (ikev2_payload_chain_t * c, u16 msg_type, u8 * data)
143 {
144   ikev2_payload_add_notify_2(c, msg_type, data, 0);
145 }
146
147 void
148 ikev2_payload_add_notify_2 (ikev2_payload_chain_t * c, u16 msg_type,
149                                u8 * data, ikev2_notify_t * notify)
150 {
151   ike_notify_payload_header_t *n;
152
153   n =
154     (ike_notify_payload_header_t *) ikev2_payload_add_hdr (c,
155                                                            IKEV2_PAYLOAD_NOTIFY,
156                                                            sizeof (*n));
157   n->msg_type = clib_host_to_net_u16 (msg_type);
158   if (notify)
159     {
160       n->protocol_id = notify->protocol_id;
161       if (notify->spi)
162         {
163           n->spi_size = 4;
164         }
165     }
166   ikev2_payload_add_data (c, data);
167 }
168
169 void
170 ikev2_payload_add_sa (ikev2_payload_chain_t *c, ikev2_sa_proposal_t *proposals,
171                       u8 force_spi)
172 {
173   ike_payload_header_t *ph;
174   ike_sa_proposal_data_t *prop;
175   ike_sa_transform_data_t *tr;
176   ikev2_sa_proposal_t *p;
177   ikev2_sa_transform_t *t;
178
179   u8 *tmp;
180   u8 *pr_data = 0;
181   u8 *tr_data = 0;
182
183   ikev2_payload_add_hdr (c, IKEV2_PAYLOAD_SA, sizeof (*ph));
184
185   vec_foreach (p, proposals)
186   {
187     int spi_size = 0;
188
189     if (p->protocol_id == IKEV2_PROTOCOL_ESP)
190       spi_size = 4;
191     else if (force_spi && p->protocol_id == IKEV2_PROTOCOL_IKE)
192       spi_size = 8;
193
194     pr_data = vec_new (u8, sizeof (ike_sa_proposal_data_t) + spi_size);
195     prop = (ike_sa_proposal_data_t *) pr_data;
196     prop->last_or_more = proposals - p + 1 < vec_len (proposals) ? 2 : 0;
197     prop->protocol_id = p->protocol_id;
198     prop->proposal_num = p->proposal_num;
199     prop->spi_size = spi_size;
200     prop->num_transforms = vec_len (p->transforms);
201
202     if (spi_size == 4)
203       prop->spi[0] = clib_host_to_net_u32 (p->spi);
204     else if (spi_size == 8)
205       {
206         u64 s = clib_host_to_net_u64 (p->spi);
207         clib_memcpy_fast (prop->spi, &s, sizeof (s));
208       }
209
210     vec_foreach (t, p->transforms)
211     {
212       vec_add2 (tr_data, tmp, sizeof (*tr) + vec_len (t->attrs));
213       tr = (ike_sa_transform_data_t *) tmp;
214       tr->last_or_more =
215         ((t - p->transforms) + 1 < vec_len (p->transforms)) ? 3 : 0;
216       tr->transform_type = t->type;
217       tr->transform_id = clib_host_to_net_u16 (t->transform_id);
218       tr->transform_len =
219         clib_host_to_net_u16 (sizeof (*tr) + vec_len (t->attrs));
220
221       if (vec_len (t->attrs) > 0)
222         clib_memcpy_fast (tr->attributes, t->attrs, vec_len (t->attrs));
223     }
224
225     prop->proposal_len =
226       clib_host_to_net_u16 (vec_len (tr_data) + vec_len (pr_data));
227     ikev2_payload_add_data (c, pr_data);
228     ikev2_payload_add_data (c, tr_data);
229     vec_free (pr_data);
230     vec_free (tr_data);
231   }
232 }
233
234 void
235 ikev2_payload_add_ke (ikev2_payload_chain_t * c, u16 dh_group, u8 * dh_data)
236 {
237   ike_ke_payload_header_t *ke;
238   ke = (ike_ke_payload_header_t *) ikev2_payload_add_hdr (c, IKEV2_PAYLOAD_KE,
239                                                           sizeof (*ke));
240
241   ke->dh_group = clib_host_to_net_u16 (dh_group);
242   ikev2_payload_add_data (c, dh_data);
243 }
244
245 void
246 ikev2_payload_add_nonce (ikev2_payload_chain_t * c, u8 * nonce)
247 {
248   ikev2_payload_add_hdr (c, IKEV2_PAYLOAD_NONCE,
249                          sizeof (ike_payload_header_t));
250   ikev2_payload_add_data (c, nonce);
251 }
252
253 void
254 ikev2_payload_add_id (ikev2_payload_chain_t * c, ikev2_id_t * id, u8 type)
255 {
256   ike_id_payload_header_t *idp;
257   idp =
258     (ike_id_payload_header_t *) ikev2_payload_add_hdr (c, type,
259                                                        sizeof (*idp));
260
261   idp->id_type = id->type;
262   ikev2_payload_add_data (c, id->data);
263 }
264
265 void
266 ikev2_payload_add_delete (ikev2_payload_chain_t * c, ikev2_delete_t * d)
267 {
268   ike_delete_payload_header_t *dp;
269   u16 num_of_spi = vec_len (d);
270   ikev2_delete_t *d2;
271   dp =
272     (ike_delete_payload_header_t *) ikev2_payload_add_hdr (c,
273                                                            IKEV2_PAYLOAD_DELETE,
274                                                            sizeof (*dp));
275
276   if (d[0].protocol_id == IKEV2_PROTOCOL_IKE)
277     {
278       dp->protocol_id = 1;
279     }
280   else
281     {
282       dp->protocol_id = d[0].protocol_id;
283       dp->spi_size = 4;
284       dp->num_of_spi = clib_host_to_net_u16 (num_of_spi);
285       vec_foreach (d2, d)
286       {
287         u8 *data = vec_new (u8, 4);
288         u32 spi = clib_host_to_net_u32 (d2->spi);
289         clib_memcpy (data, &spi, 4);
290         ikev2_payload_add_data (c, data);
291         vec_free (data);
292       }
293     }
294 }
295
296 void
297 ikev2_payload_add_auth (ikev2_payload_chain_t * c, ikev2_auth_t * auth)
298 {
299   ike_auth_payload_header_t *ap;
300   ap =
301     (ike_auth_payload_header_t *) ikev2_payload_add_hdr (c,
302                                                          IKEV2_PAYLOAD_AUTH,
303                                                          sizeof (*ap));
304
305   ap->auth_method = auth->method;
306   ikev2_payload_add_data (c, auth->data);
307 }
308
309 static void
310 ikev2_payload_add_ts_entry (u8 ** data, ikev2_ts_t * ts)
311 {
312   u8 * tmp;
313   ikev2_ts_payload_entry_t *entry;
314   int len = sizeof (*entry);
315
316   if (ts->ts_type == TS_IPV4_ADDR_RANGE)
317     len += sizeof (ikev2_ip4_addr_pair_t);
318   else
319     len += sizeof (ikev2_ip6_addr_pair_t);
320
321   vec_add2 (data[0], tmp, len);
322   entry = (ikev2_ts_payload_entry_t *) tmp;
323   entry->ts_type = ts->ts_type;
324   entry->protocol_id = ts->protocol_id;
325   entry->selector_len = clib_host_to_net_u16 (len);
326   entry->start_port = clib_host_to_net_u16 (ts->start_port);
327   entry->end_port = clib_host_to_net_u16 (ts->end_port);
328
329   if (ts->ts_type == TS_IPV4_ADDR_RANGE)
330   {
331     ikev2_ip4_addr_pair_t *pair = (ikev2_ip4_addr_pair_t*) entry->addr_pair;
332     ip_address_copy_addr (&pair->start_addr, &ts->start_addr);
333     ip_address_copy_addr (&pair->end_addr, &ts->end_addr);
334   }
335   else
336   {
337     ikev2_ip6_addr_pair_t *pair = (ikev2_ip6_addr_pair_t*) entry->addr_pair;
338     ip_address_copy_addr (&pair->start_addr, &ts->start_addr);
339     ip_address_copy_addr (&pair->end_addr, &ts->end_addr);
340   }
341 }
342
343 void
344 ikev2_payload_add_ts (ikev2_payload_chain_t * c, ikev2_ts_t * ts, u8 type)
345 {
346   ike_ts_payload_header_t *tsh;
347   ikev2_ts_t *ts2;
348   u8 *data = 0;
349
350   tsh =
351     (ike_ts_payload_header_t *) ikev2_payload_add_hdr (c, type,
352                                                        sizeof (*tsh));
353   tsh->num_ts = vec_len (ts);
354
355   vec_foreach (ts2, ts)
356   {
357     ASSERT (ts2->ts_type == TS_IPV4_ADDR_RANGE ||
358         ts2->ts_type == TS_IPV6_ADDR_RANGE);
359     ikev2_payload_add_ts_entry (&data, ts2);
360   }
361
362   ikev2_payload_add_data (c, data);
363   vec_free (data);
364 }
365
366 void
367 ikev2_payload_chain_add_padding (ikev2_payload_chain_t * c, int bs)
368 {
369   u8 *tmp __attribute__ ((unused));
370   u8 pad_len = (vec_len (c->data) / bs + 1) * bs - vec_len (c->data);
371   vec_add2 (c->data, tmp, pad_len);
372   c->data[vec_len (c->data) - 1] = pad_len - 1;
373 }
374
375 ikev2_sa_proposal_t *
376 ikev2_parse_sa_payload (ike_payload_header_t * ikep, u32 rlen)
377 {
378   ikev2_sa_proposal_t *v = 0;
379   ikev2_sa_proposal_t *proposal;
380   ikev2_sa_transform_t *transform;
381
382   u32 plen = clib_net_to_host_u16 (ikep->length);
383   ike_sa_proposal_data_t *sap;
384   int proposal_ptr = 0;
385
386   if (sizeof (*ikep) > rlen)
387     return 0;
388
389   rlen -= sizeof (*ikep);
390   do
391     {
392       if (proposal_ptr + sizeof (*sap) > rlen)
393         goto data_corrupted;
394
395       sap = (ike_sa_proposal_data_t *) & ikep->payload[proposal_ptr];
396       int i, transform_ptr;
397
398       /* IKE proposal should have 8 bytes or no SPI */
399       if (sap->protocol_id == IKEV2_PROTOCOL_IKE && sap->spi_size != 0 &&
400           sap->spi_size != 8)
401         goto data_corrupted;
402
403       /* IKE proposal should not have SPI */
404       if (sap->protocol_id == IKEV2_PROTOCOL_ESP && sap->spi_size != 4)
405         goto data_corrupted;
406
407       transform_ptr = proposal_ptr + sizeof (*sap) + sap->spi_size;
408       if (transform_ptr > rlen)
409         goto data_corrupted;
410
411       vec_add2 (v, proposal, 1);
412       proposal->proposal_num = sap->proposal_num;
413       proposal->protocol_id = sap->protocol_id;
414
415       if (sap->spi_size == 4)
416         {
417           proposal->spi = clib_net_to_host_u32 (sap->spi[0]);
418         }
419       else if (sap->spi_size == 8)
420         {
421           u64 s;
422           clib_memcpy_fast (&s, &sap->spi[0], sizeof (s));
423           proposal->spi = clib_net_to_host_u64 (s);
424         }
425
426       for (i = 0; i < sap->num_transforms; i++)
427         {
428           ike_sa_transform_data_t *tr =
429             (ike_sa_transform_data_t *) & ikep->payload[transform_ptr];
430           if (transform_ptr + sizeof (*tr) > rlen)
431             goto data_corrupted;
432           u16 tlen = clib_net_to_host_u16 (tr->transform_len);
433
434           if (tlen < sizeof (*tr))
435             goto data_corrupted;
436
437           vec_add2 (proposal->transforms, transform, 1);
438
439           transform->type = tr->transform_type;
440           transform->transform_id = clib_net_to_host_u16 (tr->transform_id);
441           if (transform_ptr + tlen > rlen)
442             goto data_corrupted;
443           if (tlen > sizeof (*tr))
444             vec_add (transform->attrs, tr->attributes, tlen - sizeof (*tr));
445           transform_ptr += tlen;
446         }
447
448       proposal_ptr += clib_net_to_host_u16 (sap->proposal_len);
449     }
450   while (proposal_ptr < (plen - sizeof (*ikep)) && sap->last_or_more == 2);
451
452   /* data validation */
453   if (proposal_ptr != (plen - sizeof (*ikep)) || sap->last_or_more)
454     goto data_corrupted;
455
456   return v;
457
458 data_corrupted:
459   ikev2_elog_detail ("SA payload data corrupted");
460   ikev2_sa_free_proposal_vector (&v);
461   return 0;
462 }
463
464 ikev2_ts_t *
465 ikev2_parse_ts_payload (ike_payload_header_t * ikep, u32 rlen)
466 {
467   ike_ts_payload_header_t *tsp = (ike_ts_payload_header_t *) ikep;
468   ikev2_ts_t *r = 0, *ts;
469   ikev2_ip4_addr_pair_t *pair4;
470   ikev2_ip6_addr_pair_t *pair6;
471   int p = 0, n_left;
472   ikev2_ts_payload_entry_t *pe;
473
474   if (sizeof (*tsp) > rlen)
475     return 0;
476
477   rlen -= sizeof (*tsp);
478   n_left = tsp->num_ts;
479
480   while (n_left && p + sizeof (*pe) < rlen)
481     {
482       pe = (ikev2_ts_payload_entry_t *) (((u8 *)tsp->ts) + p);
483       p += sizeof (*pe);
484
485       if (pe->ts_type != TS_IPV4_ADDR_RANGE &&
486           pe->ts_type != TS_IPV6_ADDR_RANGE)
487         {
488           ikev2_elog_uint (IKEV2_LOG_ERROR,
489               "unsupported TS type received (%u)", pe->ts_type);
490           return 0;
491         }
492
493       vec_add2 (r, ts, 1);
494       ts->ts_type = pe->ts_type;
495       ts->protocol_id = pe->protocol_id;
496       ts->start_port = pe->start_port;
497       ts->end_port = pe->end_port;
498
499       if (pe->ts_type == TS_IPV4_ADDR_RANGE)
500         {
501           pair4 = (ikev2_ip4_addr_pair_t*) pe->addr_pair;
502           ip_address_set (&ts->start_addr, &pair4->start_addr, AF_IP4);
503           ip_address_set (&ts->end_addr, &pair4->end_addr, AF_IP4);
504           p += sizeof (*pair4);
505         }
506       else
507         {
508           pair6 = (ikev2_ip6_addr_pair_t*) pe->addr_pair;
509           ip_address_set (&ts->start_addr, &pair6->start_addr, AF_IP6);
510           ip_address_set (&ts->end_addr, &pair6->end_addr, AF_IP6);
511           p += sizeof (*pair6);
512         }
513       n_left--;
514     }
515
516   if (n_left)
517     return 0;
518
519   return r;
520 }
521
522 ikev2_notify_t *
523 ikev2_parse_notify_payload (ike_payload_header_t * ikep, u32 rlen)
524 {
525   ike_notify_payload_header_t *n = (ike_notify_payload_header_t *) ikep;
526   u32 plen = clib_net_to_host_u16 (n->length);
527   ikev2_notify_t *r = 0;
528   u32 spi;
529
530   if (sizeof (*n) > rlen)
531     return 0;
532
533   r = vec_new (ikev2_notify_t, 1);
534   r->msg_type = clib_net_to_host_u16 (n->msg_type);
535   r->protocol_id = n->protocol_id;
536
537   if (n->spi_size == 4)
538     {
539       if (sizeof (spi) + sizeof (*n) > rlen)
540         goto cleanup;
541
542       clib_memcpy (&spi, n->payload, n->spi_size);
543       r->spi = clib_net_to_host_u32 (spi);
544     }
545   else if (n->spi_size == 0)
546     {
547       r->spi = 0;
548     }
549   else
550     {
551       clib_warning ("invalid SPI Size %d", n->spi_size);
552       goto cleanup;
553     }
554
555   if (plen > (sizeof (*n) + n->spi_size))
556     {
557       if (plen <= sizeof (*n) + n->spi_size)
558         goto cleanup;
559
560       u32 data_len = plen - sizeof (*n) - n->spi_size;
561       vec_add (r->data, n->payload + n->spi_size, data_len);
562     }
563   return r;
564
565 cleanup:
566   vec_free (r);
567   return 0;
568 }
569
570 void
571 ikev2_parse_vendor_payload (ike_payload_header_t * ikep)
572 {
573   u32 plen = clib_net_to_host_u16 (ikep->length);
574   ikev2_elog_uint (IKEV2_LOG_DEBUG, "vendor payload skipped, len %d", plen);
575 }
576
577 ikev2_delete_t *
578 ikev2_parse_delete_payload (ike_payload_header_t * ikep, u32 rlen)
579 {
580   ike_delete_payload_header_t * d = (ike_delete_payload_header_t *) ikep;
581   ikev2_delete_t *r = 0, *del;
582   u16 i, num_of_spi;
583
584   if (rlen < sizeof (*d))
585     return 0;
586
587   num_of_spi = clib_net_to_host_u16 (d->num_of_spi);
588   if (d->protocol_id == IKEV2_PROTOCOL_IKE)
589     {
590       r = vec_new (ikev2_delete_t, 1);
591       r->protocol_id = 1;
592     }
593   else
594     {
595       if (sizeof (*d) + num_of_spi * sizeof (u32) > rlen)
596         return 0;
597
598       for (i = 0; i < num_of_spi; i++)
599       {
600         vec_add2 (r, del, 1);
601         del->protocol_id = d->protocol_id;
602         del->spi = clib_net_to_host_u32 (d->spi[i]);
603       }
604     }
605
606   return r;
607 }
608
609 u8 *
610 ikev2_find_ike_notify_payload (ike_header_t * ike, u32 msg_type)
611 {
612   int p = 0;
613   ike_notify_payload_header_t *n;
614   ike_payload_header_t *ikep;
615   u32 payload = ike->nextpayload;
616
617   while (payload != IKEV2_PAYLOAD_NONE)
618     {
619       ikep = (ike_payload_header_t *) & ike->payload[p];
620       if (payload == IKEV2_PAYLOAD_NOTIFY)
621       {
622         n = (ike_notify_payload_header_t *)ikep;
623         if (n->msg_type == clib_net_to_host_u16 (msg_type))
624           return n->payload;
625       }
626       u16 plen = clib_net_to_host_u16 (ikep->length);
627       payload = ikep->nextpayload;
628       p += plen;
629     }
630   return 0;
631 }
632
633 /*
634  * fd.io coding-style-patch-verification: ON
635  *
636  * Local Variables:
637  * eval: (c-set-style "gnu")
638  * End:
639  */