ipsec: efficient layout of ESP per thread data
[vpp.git] / src / vnet / ipsec / esp_decrypt.c
1 /*
2  * esp_decrypt.c : IPSec ESP decrypt node
3  *
4  * Copyright (c) 2015 Cisco and/or its affiliates.
5  * Licensed under the Apache License, Version 2.0 (the "License");
6  * you may not use this file except in compliance with the License.
7  * You may obtain a copy of the License at:
8  *
9  *     http://www.apache.org/licenses/LICENSE-2.0
10  *
11  * Unless required by applicable law or agreed to in writing, software
12  * distributed under the License is distributed on an "AS IS" BASIS,
13  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14  * See the License for the specific language governing permissions and
15  * limitations under the License.
16  */
17
18 #include <vnet/vnet.h>
19 #include <vnet/api_errno.h>
20 #include <vnet/ip/ip.h>
21 #include <vnet/l2/l2_input.h>
22
23 #include <vnet/ipsec/ipsec.h>
24 #include <vnet/ipsec/esp.h>
25 #include <vnet/ipsec/ipsec_io.h>
26 #include <vnet/ipsec/ipsec_tun.h>
27
28 #include <vnet/gre/gre.h>
29
30 #define foreach_esp_decrypt_next                \
31 _(DROP, "error-drop")                           \
32 _(IP4_INPUT, "ip4-input-no-checksum")           \
33 _(IP6_INPUT, "ip6-input")                       \
34 _(L2_INPUT, "l2-input")                         \
35 _(HANDOFF, "handoff")
36
37 #define _(v, s) ESP_DECRYPT_NEXT_##v,
38 typedef enum
39 {
40   foreach_esp_decrypt_next
41 #undef _
42     ESP_DECRYPT_N_NEXT,
43 } esp_decrypt_next_t;
44
45
46 #define foreach_esp_decrypt_error                               \
47  _(RX_PKTS, "ESP pkts received")                                \
48  _(DECRYPTION_FAILED, "ESP decryption failed")                  \
49  _(INTEG_ERROR, "Integrity check failed")                       \
50  _(CRYPTO_ENGINE_ERROR, "crypto engine error (packet dropped)") \
51  _(REPLAY, "SA replayed packet")                                \
52  _(RUNT, "undersized packet")                                   \
53  _(NO_BUFFERS, "no buffers (packet dropped)")                   \
54  _(OVERSIZED_HEADER, "buffer with oversized header (dropped)")  \
55  _(NO_TAIL_SPACE, "no enough buffer tail space (dropped)")      \
56  _(TUN_NO_PROTO, "no tunnel protocol")                          \
57  _(UNSUP_PAYLOAD, "unsupported payload")                        \
58
59
60 typedef enum
61 {
62 #define _(sym,str) ESP_DECRYPT_ERROR_##sym,
63   foreach_esp_decrypt_error
64 #undef _
65     ESP_DECRYPT_N_ERROR,
66 } esp_decrypt_error_t;
67
68 static char *esp_decrypt_error_strings[] = {
69 #define _(sym,string) string,
70   foreach_esp_decrypt_error
71 #undef _
72 };
73
74 typedef struct
75 {
76   u32 seq;
77   u32 sa_seq;
78   u32 sa_seq_hi;
79   ipsec_crypto_alg_t crypto_alg;
80   ipsec_integ_alg_t integ_alg;
81 } esp_decrypt_trace_t;
82
83 /* packet trace format function */
84 static u8 *
85 format_esp_decrypt_trace (u8 * s, va_list * args)
86 {
87   CLIB_UNUSED (vlib_main_t * vm) = va_arg (*args, vlib_main_t *);
88   CLIB_UNUSED (vlib_node_t * node) = va_arg (*args, vlib_node_t *);
89   esp_decrypt_trace_t *t = va_arg (*args, esp_decrypt_trace_t *);
90
91   s =
92     format (s,
93             "esp: crypto %U integrity %U pkt-seq %d sa-seq %u sa-seq-hi %u",
94             format_ipsec_crypto_alg, t->crypto_alg, format_ipsec_integ_alg,
95             t->integ_alg, t->seq, t->sa_seq, t->sa_seq_hi);
96   return s;
97 }
98
99 typedef struct
100 {
101   vlib_buffer_t *lb;
102   union
103   {
104     struct
105     {
106       u8 icv_sz;
107       u8 iv_sz;
108       ipsec_sa_flags_t flags;
109       u32 sa_index;
110     };
111     u64 sa_data;
112   };
113
114   u32 seq;
115   u32 free_buffer_index;
116   i16 current_data;
117   i16 current_length;
118   u16 hdr_sz;
119   u8 icv_removed;
120   u8 __unused;
121 } esp_decrypt_packet_data_t;
122
123 STATIC_ASSERT_SIZEOF (esp_decrypt_packet_data_t, 4 * sizeof (u64));
124
125 #define ESP_ENCRYPT_PD_F_FD_TRANSPORT (1 << 2)
126
127 static_always_inline void
128 esp_process_ops (vlib_main_t * vm, vlib_node_runtime_t * node,
129                  vnet_crypto_op_t * ops, vlib_buffer_t * b[], u16 * nexts,
130                  int e)
131 {
132   vnet_crypto_op_t *op = ops;
133   u32 n_fail, n_ops = vec_len (ops);
134
135   if (n_ops == 0)
136     return;
137
138   n_fail = n_ops - vnet_crypto_process_ops (vm, op, n_ops);
139
140   while (n_fail)
141     {
142       ASSERT (op - ops < n_ops);
143       if (op->status != VNET_CRYPTO_OP_STATUS_COMPLETED)
144         {
145           u32 err, bi = op->user_data;
146           if (op->status == VNET_CRYPTO_OP_STATUS_FAIL_BAD_HMAC)
147             err = e;
148           else
149             err = ESP_DECRYPT_ERROR_CRYPTO_ENGINE_ERROR;
150           b[bi]->error = node->errors[err];
151           nexts[bi] = ESP_DECRYPT_NEXT_DROP;
152           n_fail--;
153         }
154       op++;
155     }
156 }
157
158 static_always_inline void
159 esp_process_chained_ops (vlib_main_t * vm, vlib_node_runtime_t * node,
160                          vnet_crypto_op_t * ops, vlib_buffer_t * b[],
161                          u16 * nexts, vnet_crypto_op_chunk_t * chunks, int e)
162 {
163
164   vnet_crypto_op_t *op = ops;
165   u32 n_fail, n_ops = vec_len (ops);
166
167   if (n_ops == 0)
168     return;
169
170   n_fail = n_ops - vnet_crypto_process_chained_ops (vm, op, chunks, n_ops);
171
172   while (n_fail)
173     {
174       ASSERT (op - ops < n_ops);
175       if (op->status != VNET_CRYPTO_OP_STATUS_COMPLETED)
176         {
177           u32 err, bi = op->user_data;
178           if (op->status == VNET_CRYPTO_OP_STATUS_FAIL_BAD_HMAC)
179             err = e;
180           else
181             err = ESP_DECRYPT_ERROR_CRYPTO_ENGINE_ERROR;
182           b[bi]->error = node->errors[err];
183           nexts[bi] = ESP_DECRYPT_NEXT_DROP;
184           n_fail--;
185         }
186       op++;
187     }
188 }
189
190 always_inline void
191 esp_remove_tail (vlib_main_t * vm, vlib_buffer_t * b, vlib_buffer_t * last,
192                  u16 tail)
193 {
194   vlib_buffer_t *before_last = b;
195
196   if (last->current_length > tail)
197     {
198       last->current_length -= tail;
199       return;
200     }
201   ASSERT (b->flags & VLIB_BUFFER_NEXT_PRESENT);
202
203   while (b->flags & VLIB_BUFFER_NEXT_PRESENT)
204     {
205       before_last = b;
206       b = vlib_get_buffer (vm, b->next_buffer);
207     }
208   before_last->current_length -= tail - last->current_length;
209   vlib_buffer_free_one (vm, before_last->next_buffer);
210   before_last->flags &= ~VLIB_BUFFER_NEXT_PRESENT;
211 }
212
213 /* ICV is splitted in last two buffers so move it to the last buffer and
214    return pointer to it */
215 static_always_inline u8 *
216 esp_move_icv (vlib_main_t * vm, vlib_buffer_t * first,
217               esp_decrypt_packet_data_t * pd, u16 icv_sz)
218 {
219   vlib_buffer_t *before_last, *bp;
220   u16 last_sz = pd->lb->current_length;
221   u16 first_sz = icv_sz - last_sz;
222
223   bp = before_last = first;
224   while (bp->flags & VLIB_BUFFER_NEXT_PRESENT)
225     {
226       before_last = bp;
227       bp = vlib_get_buffer (vm, bp->next_buffer);
228     }
229
230   u8 *lb_curr = vlib_buffer_get_current (pd->lb);
231   memmove (lb_curr + first_sz, lb_curr, last_sz);
232   clib_memcpy_fast (lb_curr, vlib_buffer_get_tail (before_last) - first_sz,
233                     first_sz);
234   before_last->current_length -= first_sz;
235   pd->lb = before_last;
236   pd->icv_removed = 1;
237   pd->free_buffer_index = before_last->next_buffer;
238   before_last->flags &= ~VLIB_BUFFER_NEXT_PRESENT;
239   return lb_curr;
240 }
241
242 always_inline uword
243 esp_decrypt_inline (vlib_main_t * vm,
244                     vlib_node_runtime_t * node, vlib_frame_t * from_frame,
245                     int is_ip6, int is_tun)
246 {
247   ipsec_main_t *im = &ipsec_main;
248   u32 thread_index = vm->thread_index;
249   u16 buffer_data_size = vlib_buffer_get_default_data_size (vm);
250   u16 len;
251   ipsec_per_thread_data_t *ptd = vec_elt_at_index (im->ptd, thread_index);
252   u32 *from = vlib_frame_vector_args (from_frame);
253   u32 n_left = from_frame->n_vectors;
254   vlib_buffer_t *bufs[VLIB_FRAME_SIZE], **b = bufs;
255   u16 nexts[VLIB_FRAME_SIZE], *next = nexts;
256   esp_decrypt_packet_data_t pkt_data[VLIB_FRAME_SIZE], *pd = pkt_data;
257   esp_decrypt_packet_data_t cpd = { };
258   u32 current_sa_index = ~0, current_sa_bytes = 0, current_sa_pkts = 0;
259   const u8 esp_sz = sizeof (esp_header_t);
260   ipsec_sa_t *sa0 = 0;
261   vnet_crypto_op_chunk_t *ch;
262   vnet_crypto_op_t **crypto_ops = &ptd->crypto_ops;
263   vnet_crypto_op_t **integ_ops = &ptd->integ_ops;
264
265   vlib_get_buffers (vm, from, b, n_left);
266   vec_reset_length (ptd->crypto_ops);
267   vec_reset_length (ptd->integ_ops);
268   vec_reset_length (ptd->chained_crypto_ops);
269   vec_reset_length (ptd->chained_integ_ops);
270   vec_reset_length (ptd->chunks);
271   clib_memset_u16 (nexts, -1, n_left);
272
273   while (n_left > 0)
274     {
275       u8 *payload;
276
277       if (n_left > 2)
278         {
279           u8 *p;
280           vlib_prefetch_buffer_header (b[2], LOAD);
281           p = vlib_buffer_get_current (b[1]);
282           CLIB_PREFETCH (p, CLIB_CACHE_LINE_BYTES, LOAD);
283           p -= CLIB_CACHE_LINE_BYTES;
284           CLIB_PREFETCH (p, CLIB_CACHE_LINE_BYTES, LOAD);
285         }
286
287       u32 n_bufs = vlib_buffer_chain_linearize (vm, b[0]);
288       if (n_bufs == 0)
289         {
290           b[0]->error = node->errors[ESP_DECRYPT_ERROR_NO_BUFFERS];
291           next[0] = ESP_DECRYPT_NEXT_DROP;
292           goto next;
293         }
294
295       if (vnet_buffer (b[0])->ipsec.sad_index != current_sa_index)
296         {
297           if (current_sa_pkts)
298             vlib_increment_combined_counter (&ipsec_sa_counters, thread_index,
299                                              current_sa_index,
300                                              current_sa_pkts,
301                                              current_sa_bytes);
302           current_sa_bytes = current_sa_pkts = 0;
303
304           current_sa_index = vnet_buffer (b[0])->ipsec.sad_index;
305           sa0 = pool_elt_at_index (im->sad, current_sa_index);
306           cpd.icv_sz = sa0->integ_icv_size;
307           cpd.iv_sz = sa0->crypto_iv_size;
308           cpd.flags = sa0->flags;
309           cpd.sa_index = current_sa_index;
310         }
311
312       if (PREDICT_FALSE (~0 == sa0->decrypt_thread_index))
313         {
314           /* this is the first packet to use this SA, claim the SA
315            * for this thread. this could happen simultaneously on
316            * another thread */
317           clib_atomic_cmp_and_swap (&sa0->decrypt_thread_index, ~0,
318                                     ipsec_sa_assign_thread (thread_index));
319         }
320
321       if (PREDICT_TRUE (thread_index != sa0->decrypt_thread_index))
322         {
323           next[0] = ESP_DECRYPT_NEXT_HANDOFF;
324           goto next;
325         }
326
327       /* store packet data for next round for easier prefetch */
328       pd->sa_data = cpd.sa_data;
329       pd->current_data = b[0]->current_data;
330       pd->current_length = b[0]->current_length;
331       pd->hdr_sz = pd->current_data - vnet_buffer (b[0])->l3_hdr_offset;
332       payload = b[0]->data + pd->current_data;
333       pd->seq = clib_host_to_net_u32 (((esp_header_t *) payload)->seq);
334       pd->free_buffer_index = 0;
335       pd->icv_removed = 0;
336
337       pd->lb = b[0];
338       if (n_bufs > 1)
339         {
340           /* find last buffer in the chain */
341           while (pd->lb->flags & VLIB_BUFFER_NEXT_PRESENT)
342             pd->lb = vlib_get_buffer (vm, pd->lb->next_buffer);
343
344           crypto_ops = &ptd->chained_crypto_ops;
345           integ_ops = &ptd->chained_integ_ops;
346         }
347       pd->current_length = b[0]->current_length;
348
349       /* we need 4 extra bytes for HMAC calculation when ESN are used */
350       /* Chained buffers can process ESN as a separate chunk */
351       if (pd->lb == b[0] && ipsec_sa_is_set_USE_ESN (sa0) && cpd.icv_sz &&
352           (pd->lb->current_data + pd->lb->current_length + 4
353            > buffer_data_size))
354         {
355           b[0]->error = node->errors[ESP_DECRYPT_ERROR_NO_TAIL_SPACE];
356           next[0] = ESP_DECRYPT_NEXT_DROP;
357           goto next;
358         }
359
360       /* anti-reply check */
361       if (ipsec_sa_anti_replay_check (sa0, pd->seq))
362         {
363           b[0]->error = node->errors[ESP_DECRYPT_ERROR_REPLAY];
364           next[0] = ESP_DECRYPT_NEXT_DROP;
365           goto next;
366         }
367
368       if (pd->current_length < cpd.icv_sz + esp_sz + cpd.iv_sz)
369         {
370           b[0]->error = node->errors[ESP_DECRYPT_ERROR_RUNT];
371           next[0] = ESP_DECRYPT_NEXT_DROP;
372           goto next;
373         }
374
375       len = pd->current_length - cpd.icv_sz;
376       current_sa_pkts += 1;
377       current_sa_bytes += vlib_buffer_length_in_chain (vm, b[0]);
378
379       if (PREDICT_TRUE (sa0->integ_op_id != VNET_CRYPTO_OP_NONE))
380         {
381           vnet_crypto_op_t *op;
382           vec_add2_aligned (integ_ops[0], op, 1, CLIB_CACHE_LINE_BYTES);
383
384           vnet_crypto_op_init (op, sa0->integ_op_id);
385           op->key_index = sa0->integ_key_index;
386           op->src = payload;
387           op->flags = VNET_CRYPTO_OP_FLAG_HMAC_CHECK;
388           op->user_data = b - bufs;
389           op->digest = payload + len;
390           op->digest_len = cpd.icv_sz;
391           op->len = len;
392
393           if (pd->lb != b[0])
394             {
395               /* buffer is chained */
396               vlib_buffer_t *cb = b[0];
397               op->flags |= VNET_CRYPTO_OP_FLAG_CHAINED_BUFFERS;
398               op->chunk_index = vec_len (ptd->chunks);
399
400               if (pd->lb->current_length < cpd.icv_sz)
401                 op->digest = esp_move_icv (vm, b[0], pd, cpd.icv_sz);
402               else
403                 op->digest = vlib_buffer_get_tail (pd->lb) - cpd.icv_sz;
404
405               vec_add2 (ptd->chunks, ch, 1);
406               ch->len = pd->current_length;
407               ch->src = payload;
408               cb = vlib_get_buffer (vm, cb->next_buffer);
409               op->n_chunks = 1;
410               while (1)
411                 {
412                   vec_add2 (ptd->chunks, ch, 1);
413                   op->n_chunks += 1;
414                   ch->src = vlib_buffer_get_current (cb);
415                   if (pd->lb == cb)
416                     {
417                       if (pd->icv_removed)
418                         ch->len = cb->current_length;
419                       else
420                         ch->len = cb->current_length - cpd.icv_sz;
421                       if (ipsec_sa_is_set_USE_ESN (sa0))
422                         {
423                           u32 seq_hi = clib_host_to_net_u32 (sa0->seq_hi);
424                           u8 tmp[ESP_MAX_ICV_SIZE], sz = sizeof (sa0->seq_hi);
425                           u8 *esn;
426                           vlib_buffer_t *tmp_b;
427                           u16 space_left = vlib_buffer_space_left_at_end
428                             (vm, pd->lb);
429                           if (space_left < sz)
430                             {
431                               if (pd->icv_removed)
432                                 {
433                                   /* use pre-data area from the last bufer
434                                      that was removed from the chain */
435                                   tmp_b =
436                                     vlib_get_buffer (vm,
437                                                      pd->free_buffer_index);
438                                   esn = tmp_b->data - sz;
439                                 }
440                               else
441                                 {
442                                   /* no space, need to allocate new buffer */
443                                   u32 tmp_bi = 0;
444                                   vlib_buffer_alloc (vm, &tmp_bi, 1);
445                                   tmp_b = vlib_get_buffer (vm, tmp_bi);
446                                   esn = tmp_b->data;
447                                   pd->free_buffer_index = tmp_bi;
448                                 }
449                               clib_memcpy_fast (esn, &seq_hi, sz);
450
451                               vec_add2 (ptd->chunks, ch, 1);
452                               op->n_chunks += 1;
453                               ch->src = esn;
454                               ch->len = sz;
455                             }
456                           else
457                             {
458                               if (pd->icv_removed)
459                                 {
460                                   clib_memcpy_fast (vlib_buffer_get_tail
461                                                     (pd->lb), &seq_hi, sz);
462                                 }
463                               else
464                                 {
465                                   clib_memcpy_fast (tmp, op->digest,
466                                                     ESP_MAX_ICV_SIZE);
467                                   clib_memcpy_fast (op->digest, &seq_hi, sz);
468                                   clib_memcpy_fast (op->digest + sz, tmp,
469                                                     ESP_MAX_ICV_SIZE);
470                                   op->digest += sz;
471                                 }
472                               ch->len += sz;
473                             }
474                         }
475                     }
476                   else
477                     ch->len = cb->current_length;
478
479                   if (!(cb->flags & VLIB_BUFFER_NEXT_PRESENT))
480                     break;
481
482                   cb = vlib_get_buffer (vm, cb->next_buffer);
483                 }
484             }
485           else if (ipsec_sa_is_set_USE_ESN (sa0))
486             {
487               /* shift ICV by 4 bytes to insert ESN */
488               u32 seq_hi = clib_host_to_net_u32 (sa0->seq_hi);
489               u8 tmp[ESP_MAX_ICV_SIZE], sz = sizeof (sa0->seq_hi);
490               clib_memcpy_fast (tmp, payload + len, ESP_MAX_ICV_SIZE);
491               clib_memcpy_fast (payload + len, &seq_hi, sz);
492               clib_memcpy_fast (payload + len + sz, tmp, ESP_MAX_ICV_SIZE);
493               op->len += sz;
494               op->digest += sz;
495             }
496         }
497
498       payload += esp_sz;
499       len -= esp_sz;
500
501       if (sa0->crypto_dec_op_id != VNET_CRYPTO_OP_NONE)
502         {
503           vnet_crypto_op_t *op;
504           vec_add2_aligned (crypto_ops[0], op, 1, CLIB_CACHE_LINE_BYTES);
505           vnet_crypto_op_init (op, sa0->crypto_dec_op_id);
506           op->key_index = sa0->crypto_key_index;
507           op->iv = payload;
508
509           if (ipsec_sa_is_set_IS_AEAD (sa0))
510             {
511               esp_header_t *esp0;
512               esp_aead_t *aad;
513               u8 *scratch;
514
515               /*
516                * construct the AAD and the nonce (Salt || IV) in a scratch
517                * space in front of the IP header.
518                */
519               scratch = payload - esp_sz;
520               esp0 = (esp_header_t *) (scratch);
521
522               scratch -= (sizeof (*aad) + pd->hdr_sz);
523               op->aad = scratch;
524
525               esp_aad_fill (op, esp0, sa0);
526
527               /*
528                * we don't need to refer to the ESP header anymore so we
529                * can overwrite it with the salt and use the IV where it is
530                * to form the nonce = (Salt + IV)
531                */
532               op->iv -= sizeof (sa0->salt);
533               clib_memcpy_fast (op->iv, &sa0->salt, sizeof (sa0->salt));
534
535               op->tag = payload + len;
536               op->tag_len = 16;
537             }
538           op->src = op->dst = payload += cpd.iv_sz;
539           op->len = len - cpd.iv_sz;
540           op->user_data = b - bufs;
541
542           if (pd->lb != b[0])
543             {
544               /* buffer is chained */
545               vlib_buffer_t *cb = b[0];
546               op->flags |= VNET_CRYPTO_OP_FLAG_CHAINED_BUFFERS;
547               op->chunk_index = vec_len (ptd->chunks);
548               vec_add2 (ptd->chunks, ch, 1);
549               ch->len = len - cpd.iv_sz + cpd.icv_sz;
550               ch->src = ch->dst = payload;
551               cb = vlib_get_buffer (vm, cb->next_buffer);
552               op->n_chunks = 1;
553
554               while (1)
555                 {
556                   vec_add2 (ptd->chunks, ch, 1);
557                   op->n_chunks += 1;
558                   ch->src = ch->dst = vlib_buffer_get_current (cb);
559                   if (pd->lb == cb)
560                     {
561                       if (ipsec_sa_is_set_IS_AEAD (sa0))
562                         {
563                           if (pd->lb->current_length < cpd.icv_sz)
564                             {
565                               op->tag =
566                                 esp_move_icv (vm, b[0], pd, cpd.icv_sz);
567
568                               /* this chunk does not contain crypto data */
569                               op->n_chunks -= 1;
570
571                               /* and fix previous chunk's length as it might have
572                                  been changed */
573                               ASSERT (op->n_chunks > 0);
574                               ch[-1].len = pd->lb->current_length;
575                               break;
576                             }
577                           else
578                             op->tag =
579                               vlib_buffer_get_tail (pd->lb) - cpd.icv_sz;
580                         }
581
582                       if (pd->icv_removed)
583                         ch->len = cb->current_length;
584                       else
585                         ch->len = cb->current_length - cpd.icv_sz;
586                     }
587                   else
588                     ch->len = cb->current_length;
589
590                   if (!(cb->flags & VLIB_BUFFER_NEXT_PRESENT))
591                     break;
592
593                   cb = vlib_get_buffer (vm, cb->next_buffer);
594                 }
595             }
596         }
597
598       /* next */
599     next:
600       n_left -= 1;
601       next += 1;
602       pd += 1;
603       b += 1;
604     }
605
606   if (PREDICT_TRUE (~0 != current_sa_index))
607     vlib_increment_combined_counter (&ipsec_sa_counters, thread_index,
608                                      current_sa_index, current_sa_pkts,
609                                      current_sa_bytes);
610
611   esp_process_ops (vm, node, ptd->integ_ops, bufs, nexts,
612                    ESP_DECRYPT_ERROR_INTEG_ERROR);
613   esp_process_chained_ops (vm, node, ptd->chained_integ_ops, bufs, nexts,
614                            ptd->chunks, ESP_DECRYPT_ERROR_INTEG_ERROR);
615
616   esp_process_ops (vm, node, ptd->crypto_ops, bufs, nexts,
617                    ESP_DECRYPT_ERROR_DECRYPTION_FAILED);
618   esp_process_chained_ops (vm, node, ptd->chained_crypto_ops, bufs, nexts,
619                            ptd->chunks, ESP_DECRYPT_ERROR_DECRYPTION_FAILED);
620
621   /* Post decryption ronud - adjust packet data start and length and next
622      node */
623
624   n_left = from_frame->n_vectors;
625   next = nexts;
626   pd = pkt_data;
627   b = bufs;
628
629   while (n_left)
630     {
631       const u8 tun_flags = IPSEC_SA_FLAG_IS_TUNNEL |
632         IPSEC_SA_FLAG_IS_TUNNEL_V6;
633
634       if (n_left >= 2)
635         {
636           void *data = b[1]->data + pd[1].current_data;
637
638           /* buffer metadata */
639           vlib_prefetch_buffer_header (b[1], LOAD);
640
641           /* esp_footer_t */
642           CLIB_PREFETCH (data + pd[1].current_length - pd[1].icv_sz - 2,
643                          CLIB_CACHE_LINE_BYTES, LOAD);
644
645           /* packet headers */
646           CLIB_PREFETCH (data - CLIB_CACHE_LINE_BYTES,
647                          CLIB_CACHE_LINE_BYTES * 2, LOAD);
648         }
649
650       if (next[0] < ESP_DECRYPT_N_NEXT)
651         goto trace;
652
653       sa0 = vec_elt_at_index (im->sad, pd->sa_index);
654
655       /*
656        * redo the anti-reply check
657        * in this frame say we have sequence numbers, s, s+1, s+1, s+1
658        * and s and s+1 are in the window. When we did the anti-replay
659        * check above we did so against the state of the window (W),
660        * after packet s-1. So each of the packets in the sequence will be
661        * accepted.
662        * This time s will be cheked against Ws-1, s+1 chceked against Ws
663        * (i.e. the window state is updated/advnaced)
664        * so this time the successive s+! packet will be dropped.
665        * This is a consequence of batching the decrypts. If the
666        * check-dcrypt-advance process was done for each packet it would
667        * be fine. But we batch the decrypts because it's much more efficient
668        * to do so in SW and if we offload to HW and the process is async.
669        *
670        * You're probably thinking, but this means an attacker can send the
671        * above sequence and cause VPP to perform decrpyts that will fail,
672        * and that's true. But if the attacker can determine s (a valid
673        * sequence number in the window) which is non-trivial, it can generate
674        * a sequence s, s+1, s+2, s+3, ... s+n and nothing will prevent any
675        * implementation, sequential or batching, from decrypting these.
676        */
677       if (ipsec_sa_anti_replay_check (sa0, pd->seq))
678         {
679           b[0]->error = node->errors[ESP_DECRYPT_ERROR_REPLAY];
680           next[0] = ESP_DECRYPT_NEXT_DROP;
681           goto trace;
682         }
683
684       ipsec_sa_anti_replay_advance (sa0, pd->seq);
685
686       u8 pad_length = 0, next_header = 0;
687       u16 icv_sz = pd->icv_removed ? 0 : pd->icv_sz;
688
689       if (pd->free_buffer_index)
690         vlib_buffer_free_one (vm, pd->free_buffer_index);
691
692       if (pd->lb->current_length < sizeof (esp_footer_t) + icv_sz)
693         {
694           /* esp footer is either splitted in two buffers or in the before
695            * last buffer */
696
697           vlib_buffer_t *before_last = b[0], *bp = b[0];
698           while (bp->flags & VLIB_BUFFER_NEXT_PRESENT)
699             {
700               before_last = bp;
701               bp = vlib_get_buffer (vm, bp->next_buffer);
702             }
703           u8 *bt = vlib_buffer_get_tail (before_last);
704
705           if (pd->lb->current_length == icv_sz)
706             {
707               esp_footer_t *f = (esp_footer_t *) (bt - sizeof (*f));
708               pad_length = f->pad_length;
709               next_header = f->next_header;
710             }
711           else
712             {
713               pad_length = (bt - 1)[0];
714               next_header = ((u8 *) vlib_buffer_get_current (pd->lb))[0];
715             }
716         }
717       else
718         {
719           esp_footer_t *f =
720             (esp_footer_t *) (pd->lb->data + pd->lb->current_data +
721                               pd->lb->current_length - sizeof (esp_footer_t) -
722                               icv_sz);
723           pad_length = f->pad_length;
724           next_header = f->next_header;
725         }
726
727       u16 adv = pd->iv_sz + esp_sz;
728       u16 tail = sizeof (esp_footer_t) + pad_length + icv_sz;
729       u16 tail_orig = sizeof (esp_footer_t) + pad_length + pd->icv_sz;
730       b[0]->flags &= ~VLIB_BUFFER_TOTAL_LENGTH_VALID;
731
732       if ((pd->flags & tun_flags) == 0 && !is_tun)      /* transport mode */
733         {
734           u8 udp_sz = (is_ip6 == 0 && pd->flags & IPSEC_SA_FLAG_UDP_ENCAP) ?
735             sizeof (udp_header_t) : 0;
736           u16 ip_hdr_sz = pd->hdr_sz - udp_sz;
737           u8 *old_ip = b[0]->data + pd->current_data - ip_hdr_sz - udp_sz;
738           u8 *ip = old_ip + adv + udp_sz;
739
740           if (is_ip6 && ip_hdr_sz > 64)
741             memmove (ip, old_ip, ip_hdr_sz);
742           else
743             clib_memcpy_le64 (ip, old_ip, ip_hdr_sz);
744
745           b[0]->current_data = pd->current_data + adv - ip_hdr_sz;
746           b[0]->current_length = pd->current_length + ip_hdr_sz - adv;
747           esp_remove_tail (vm, b[0], pd->lb, tail);
748
749           if (is_ip6)
750             {
751               ip6_header_t *ip6 = (ip6_header_t *) ip;
752               u16 len = clib_net_to_host_u16 (ip6->payload_length);
753               len -= adv + tail_orig;
754               ip6->payload_length = clib_host_to_net_u16 (len);
755               ip6->protocol = next_header;
756               next[0] = ESP_DECRYPT_NEXT_IP6_INPUT;
757             }
758           else
759             {
760               ip4_header_t *ip4 = (ip4_header_t *) ip;
761               ip_csum_t sum = ip4->checksum;
762               u16 len = clib_net_to_host_u16 (ip4->length);
763               len = clib_host_to_net_u16 (len - adv - tail_orig - udp_sz);
764               sum = ip_csum_update (sum, ip4->protocol, next_header,
765                                     ip4_header_t, protocol);
766               sum = ip_csum_update (sum, ip4->length, len,
767                                     ip4_header_t, length);
768               ip4->checksum = ip_csum_fold (sum);
769               ip4->protocol = next_header;
770               ip4->length = len;
771               next[0] = ESP_DECRYPT_NEXT_IP4_INPUT;
772             }
773         }
774       else
775         {
776           if (PREDICT_TRUE (next_header == IP_PROTOCOL_IP_IN_IP))
777             {
778               next[0] = ESP_DECRYPT_NEXT_IP4_INPUT;
779               b[0]->current_data = pd->current_data + adv;
780               b[0]->current_length = pd->current_length - adv;
781               esp_remove_tail (vm, b[0], pd->lb, tail);
782             }
783           else if (next_header == IP_PROTOCOL_IPV6)
784             {
785               next[0] = ESP_DECRYPT_NEXT_IP6_INPUT;
786               b[0]->current_data = pd->current_data + adv;
787               b[0]->current_length = pd->current_length - adv;
788               esp_remove_tail (vm, b[0], pd->lb, tail);
789             }
790           else
791             {
792               if (is_tun && next_header == IP_PROTOCOL_GRE)
793                 {
794                   gre_header_t *gre;
795
796                   b[0]->current_data = pd->current_data + adv;
797                   b[0]->current_length = pd->current_length - adv - tail;
798
799                   gre = vlib_buffer_get_current (b[0]);
800
801                   vlib_buffer_advance (b[0], sizeof (*gre));
802
803                   switch (clib_net_to_host_u16 (gre->protocol))
804                     {
805                     case GRE_PROTOCOL_teb:
806                       vnet_update_l2_len (b[0]);
807                       next[0] = ESP_DECRYPT_NEXT_L2_INPUT;
808                       break;
809                     case GRE_PROTOCOL_ip4:
810                       next[0] = ESP_DECRYPT_NEXT_IP4_INPUT;
811                       break;
812                     case GRE_PROTOCOL_ip6:
813                       next[0] = ESP_DECRYPT_NEXT_IP6_INPUT;
814                       break;
815                     default:
816                       b[0]->error =
817                         node->errors[ESP_DECRYPT_ERROR_UNSUP_PAYLOAD];
818                       next[0] = ESP_DECRYPT_NEXT_DROP;
819                       break;
820                     }
821                 }
822               else
823                 {
824                   next[0] = ESP_DECRYPT_NEXT_DROP;
825                   b[0]->error = node->errors[ESP_DECRYPT_ERROR_UNSUP_PAYLOAD];
826                   goto trace;
827                 }
828             }
829           if (is_tun)
830             {
831               if (ipsec_sa_is_set_IS_PROTECT (sa0))
832                 {
833                   /*
834                    * There are two encap possibilities
835                    * 1) the tunnel and ths SA are prodiving encap, i.e. it's
836                    *   MAC | SA-IP | TUN-IP | ESP | PAYLOAD
837                    * implying the SA is in tunnel mode (on a tunnel interface)
838                    * 2) only the tunnel provides encap
839                    *   MAC | TUN-IP | ESP | PAYLOAD
840                    * implying the SA is in transport mode.
841                    *
842                    * For 2) we need only strip the tunnel encap and we're good.
843                    *  since the tunnel and crypto ecnap (int the tun=protect
844                    * object) are the same and we verified above that these match
845                    * for 1) we need to strip the SA-IP outer headers, to
846                    * reveal the tunnel IP and then check that this matches
847                    * the configured tunnel.
848                    */
849                   const ipsec_tun_protect_t *itp;
850
851                   itp = ipsec_tun_protect_get
852                     (vnet_buffer (b[0])->ipsec.protect_index);
853
854                   if (PREDICT_TRUE (next_header == IP_PROTOCOL_IP_IN_IP))
855                     {
856                       const ip4_header_t *ip4;
857
858                       ip4 = vlib_buffer_get_current (b[0]);
859
860                       if (!ip46_address_is_equal_v4 (&itp->itp_tun.src,
861                                                      &ip4->dst_address) ||
862                           !ip46_address_is_equal_v4 (&itp->itp_tun.dst,
863                                                      &ip4->src_address))
864                         {
865                           next[0] = ESP_DECRYPT_NEXT_DROP;
866                           b[0]->error =
867                             node->errors[ESP_DECRYPT_ERROR_TUN_NO_PROTO];
868                         }
869                     }
870                   else if (next_header == IP_PROTOCOL_IPV6)
871                     {
872                       const ip6_header_t *ip6;
873
874                       ip6 = vlib_buffer_get_current (b[0]);
875
876                       if (!ip46_address_is_equal_v6 (&itp->itp_tun.src,
877                                                      &ip6->dst_address) ||
878                           !ip46_address_is_equal_v6 (&itp->itp_tun.dst,
879                                                      &ip6->src_address))
880                         {
881                           next[0] = ESP_DECRYPT_NEXT_DROP;
882                           b[0]->error =
883                             node->errors[ESP_DECRYPT_ERROR_TUN_NO_PROTO];
884                         }
885                     }
886                 }
887             }
888         }
889
890     trace:
891       if (PREDICT_FALSE (b[0]->flags & VLIB_BUFFER_IS_TRACED))
892         {
893           esp_decrypt_trace_t *tr;
894           tr = vlib_add_trace (vm, node, b[0], sizeof (*tr));
895           sa0 = pool_elt_at_index (im->sad,
896                                    vnet_buffer (b[0])->ipsec.sad_index);
897           tr->crypto_alg = sa0->crypto_alg;
898           tr->integ_alg = sa0->integ_alg;
899           tr->seq = pd->seq;
900           tr->sa_seq = sa0->last_seq;
901           tr->sa_seq_hi = sa0->seq_hi;
902         }
903
904       /* next */
905       n_left -= 1;
906       next += 1;
907       pd += 1;
908       b += 1;
909     }
910
911   n_left = from_frame->n_vectors;
912   vlib_node_increment_counter (vm, node->node_index,
913                                ESP_DECRYPT_ERROR_RX_PKTS, n_left);
914
915   vlib_buffer_enqueue_to_next (vm, node, from, nexts, n_left);
916
917   return n_left;
918 }
919
920 VLIB_NODE_FN (esp4_decrypt_node) (vlib_main_t * vm,
921                                   vlib_node_runtime_t * node,
922                                   vlib_frame_t * from_frame)
923 {
924   return esp_decrypt_inline (vm, node, from_frame, 0, 0);
925 }
926
927 VLIB_NODE_FN (esp4_decrypt_tun_node) (vlib_main_t * vm,
928                                       vlib_node_runtime_t * node,
929                                       vlib_frame_t * from_frame)
930 {
931   return esp_decrypt_inline (vm, node, from_frame, 0, 1);
932 }
933
934 VLIB_NODE_FN (esp6_decrypt_node) (vlib_main_t * vm,
935                                   vlib_node_runtime_t * node,
936                                   vlib_frame_t * from_frame)
937 {
938   return esp_decrypt_inline (vm, node, from_frame, 1, 0);
939 }
940
941 VLIB_NODE_FN (esp6_decrypt_tun_node) (vlib_main_t * vm,
942                                       vlib_node_runtime_t * node,
943                                       vlib_frame_t * from_frame)
944 {
945   return esp_decrypt_inline (vm, node, from_frame, 1, 1);
946 }
947
948 /* *INDENT-OFF* */
949 VLIB_REGISTER_NODE (esp4_decrypt_node) = {
950   .name = "esp4-decrypt",
951   .vector_size = sizeof (u32),
952   .format_trace = format_esp_decrypt_trace,
953   .type = VLIB_NODE_TYPE_INTERNAL,
954
955   .n_errors = ARRAY_LEN(esp_decrypt_error_strings),
956   .error_strings = esp_decrypt_error_strings,
957
958   .n_next_nodes = ESP_DECRYPT_N_NEXT,
959   .next_nodes = {
960     [ESP_DECRYPT_NEXT_DROP] = "ip4-drop",
961     [ESP_DECRYPT_NEXT_IP4_INPUT] = "ip4-input-no-checksum",
962     [ESP_DECRYPT_NEXT_IP6_INPUT] = "ip6-input",
963     [ESP_DECRYPT_NEXT_L2_INPUT] = "l2-input",
964     [ESP_DECRYPT_NEXT_HANDOFF] = "esp4-decrypt-handoff",
965   },
966 };
967
968 VLIB_REGISTER_NODE (esp6_decrypt_node) = {
969   .name = "esp6-decrypt",
970   .vector_size = sizeof (u32),
971   .format_trace = format_esp_decrypt_trace,
972   .type = VLIB_NODE_TYPE_INTERNAL,
973
974   .n_errors = ARRAY_LEN(esp_decrypt_error_strings),
975   .error_strings = esp_decrypt_error_strings,
976
977   .n_next_nodes = ESP_DECRYPT_N_NEXT,
978   .next_nodes = {
979     [ESP_DECRYPT_NEXT_DROP] = "ip6-drop",
980     [ESP_DECRYPT_NEXT_IP4_INPUT] = "ip4-input-no-checksum",
981     [ESP_DECRYPT_NEXT_IP6_INPUT] = "ip6-input",
982     [ESP_DECRYPT_NEXT_L2_INPUT] = "l2-input",
983     [ESP_DECRYPT_NEXT_HANDOFF]=  "esp6-decrypt-handoff",
984   },
985 };
986
987 VLIB_REGISTER_NODE (esp4_decrypt_tun_node) = {
988   .name = "esp4-decrypt-tun",
989   .vector_size = sizeof (u32),
990   .format_trace = format_esp_decrypt_trace,
991   .type = VLIB_NODE_TYPE_INTERNAL,
992   .n_errors = ARRAY_LEN(esp_decrypt_error_strings),
993   .error_strings = esp_decrypt_error_strings,
994   .n_next_nodes = ESP_DECRYPT_N_NEXT,
995   .next_nodes = {
996     [ESP_DECRYPT_NEXT_DROP] = "ip4-drop",
997     [ESP_DECRYPT_NEXT_IP4_INPUT] = "ip4-input-no-checksum",
998     [ESP_DECRYPT_NEXT_IP6_INPUT] = "ip6-input",
999     [ESP_DECRYPT_NEXT_L2_INPUT] = "l2-input",
1000     [ESP_DECRYPT_NEXT_HANDOFF] = "esp4-decrypt-tun-handoff",
1001   },
1002 };
1003
1004 VLIB_REGISTER_NODE (esp6_decrypt_tun_node) = {
1005   .name = "esp6-decrypt-tun",
1006   .vector_size = sizeof (u32),
1007   .format_trace = format_esp_decrypt_trace,
1008   .type = VLIB_NODE_TYPE_INTERNAL,
1009   .n_errors = ARRAY_LEN(esp_decrypt_error_strings),
1010   .error_strings = esp_decrypt_error_strings,
1011   .n_next_nodes = ESP_DECRYPT_N_NEXT,
1012   .next_nodes = {
1013     [ESP_DECRYPT_NEXT_DROP] = "ip6-drop",
1014     [ESP_DECRYPT_NEXT_IP4_INPUT] = "ip4-input-no-checksum",
1015     [ESP_DECRYPT_NEXT_IP6_INPUT] = "ip6-input",
1016     [ESP_DECRYPT_NEXT_L2_INPUT] = "l2-input",
1017     [ESP_DECRYPT_NEXT_HANDOFF]=  "esp6-decrypt-tun-handoff",
1018   },
1019 };
1020 /* *INDENT-ON* */
1021
1022 /*
1023  * fd.io coding-style-patch-verification: ON
1024  *
1025  * Local Variables:
1026  * eval: (c-set-style "gnu")
1027  * End:
1028  */