FD.io VPP  v18.07.1-19-g511ce25
Vector Packet Processing
ah_decrypt.c
Go to the documentation of this file.
1 /*
2  * ah_decrypt.c : IPSec AH 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 
22 #include <vnet/ipsec/ipsec.h>
23 #include <vnet/ipsec/esp.h>
24 #include <vnet/ipsec/ah.h>
25 
26 #define foreach_ah_decrypt_next \
27 _(DROP, "error-drop") \
28 _(IP4_INPUT, "ip4-input") \
29 _(IP6_INPUT, "ip6-input") \
30 _(IPSEC_GRE_INPUT, "ipsec-gre-input")
31 
32 #define _(v, s) AH_DECRYPT_NEXT_##v,
33 typedef enum
34 {
36 #undef _
39 
40 
41 #define foreach_ah_decrypt_error \
42  _(RX_PKTS, "AH pkts received") \
43  _(DECRYPTION_FAILED, "AH decryption failed") \
44  _(INTEG_ERROR, "Integrity check failed") \
45  _(REPLAY, "SA replayed packet") \
46  _(NOT_IP, "Not IP packet (dropped)")
47 
48 
49 typedef enum
50 {
51 #define _(sym,str) AH_DECRYPT_ERROR_##sym,
53 #undef _
56 
57 static char *ah_decrypt_error_strings[] = {
58 #define _(sym,string) string,
60 #undef _
61 };
62 
63 typedef struct
64 {
67 
68 /* packet trace format function */
69 static u8 *
70 format_ah_decrypt_trace (u8 * s, va_list * args)
71 {
72  CLIB_UNUSED (vlib_main_t * vm) = va_arg (*args, vlib_main_t *);
73  CLIB_UNUSED (vlib_node_t * node) = va_arg (*args, vlib_node_t *);
74  ah_decrypt_trace_t *t = va_arg (*args, ah_decrypt_trace_t *);
75 
76  s = format (s, "ah: integrity %U", format_ipsec_integ_alg, t->integ_alg);
77  return s;
78 }
79 
80 static uword
82  vlib_node_runtime_t * node, vlib_frame_t * from_frame)
83 {
84  u32 n_left_from, *from, next_index, *to_next;
85  ipsec_main_t *im = &ipsec_main;
87  from = vlib_frame_vector_args (from_frame);
88  n_left_from = from_frame->n_vectors;
89  int icv_size = 0;
90 
91  next_index = node->cached_next_index;
92 
93  while (n_left_from > 0)
94  {
95  u32 n_left_to_next;
96 
97  vlib_get_next_frame (vm, node, next_index, to_next, n_left_to_next);
98 
99  while (n_left_from > 0 && n_left_to_next > 0)
100  {
101  u32 i_bi0;
102  u32 next0;
103  vlib_buffer_t *i_b0;
104  ah_header_t *ah0;
105  ipsec_sa_t *sa0;
106  u32 sa_index0 = ~0;
107  u32 seq;
108  ip4_header_t *ih4 = 0, *oh4 = 0;
109  ip6_header_t *ih6 = 0, *oh6 = 0;
110  u8 tunnel_mode = 1;
111  u8 transport_ip6 = 0;
112  u8 ip_hdr_size = 0;
113  u8 tos = 0;
114  u8 ttl = 0;
115 
116 
117  i_bi0 = from[0];
118  from += 1;
119  n_left_from -= 1;
120  n_left_to_next -= 1;
121 
122  next0 = AH_DECRYPT_NEXT_DROP;
123 
124  i_b0 = vlib_get_buffer (vm, i_bi0);
125  to_next[0] = i_bi0;
126  to_next += 1;
127  ih4 = vlib_buffer_get_current (i_b0);
128  ip_hdr_size = ip4_header_bytes (ih4);
129  ah0 = (ah_header_t *) ((u8 *) ih4 + ip_hdr_size);
130 
131  sa_index0 = vnet_buffer (i_b0)->ipsec.sad_index;
132  sa0 = pool_elt_at_index (im->sad, sa_index0);
133 
134  seq = clib_host_to_net_u32 (ah0->seq_no);
135  /* anti-replay check */
136  //TODO UT remaining
137  if (sa0->use_anti_replay)
138  {
139  int rv = 0;
140 
141  if (PREDICT_TRUE (sa0->use_esn))
142  rv = esp_replay_check_esn (sa0, seq);
143  else
144  rv = esp_replay_check (sa0, seq);
145 
146  if (PREDICT_FALSE (rv))
147  {
149  AH_DECRYPT_ERROR_REPLAY, 1);
150  goto trace;
151  }
152  }
153 
154 
155  sa0->total_data_size += i_b0->current_length;
156  icv_size =
158  if (PREDICT_TRUE (sa0->integ_alg != IPSEC_INTEG_ALG_NONE))
159  {
160  u8 sig[64];
161  u8 digest[64];
162  memset (sig, 0, sizeof (sig));
163  memset (digest, 0, sizeof (digest));
164  u8 *icv =
165  vlib_buffer_get_current (i_b0) + ip_hdr_size +
166  sizeof (ah_header_t);
167  memcpy (digest, icv, icv_size);
168  memset (icv, 0, icv_size);
169 
170  if ((ih4->ip_version_and_header_length & 0xF0) == 0x40)
171  {
172  tos = ih4->tos;
173  ttl = ih4->ttl;
174  ih4->tos = 0;
175  ih4->ttl = 0;
176  ih4->checksum = 0;
177  ih4->flags_and_fragment_offset = 0;
178  } //TODO else part for IPv6
179  hmac_calc (sa0->integ_alg, sa0->integ_key, sa0->integ_key_len,
180  (u8 *) ih4, i_b0->current_length, sig, sa0->use_esn,
181  sa0->seq_hi);
182 
183  if (PREDICT_FALSE (memcmp (digest, sig, icv_size)))
184  {
186  AH_DECRYPT_ERROR_INTEG_ERROR,
187  1);
188  goto trace;
189  }
190 
191  //TODO UT remaining
192  if (PREDICT_TRUE (sa0->use_anti_replay))
193  {
194  if (PREDICT_TRUE (sa0->use_esn))
195  esp_replay_advance_esn (sa0, seq);
196  else
197  esp_replay_advance (sa0, seq);
198  }
199 
200  }
201 
202 
203  vlib_buffer_advance (i_b0,
204  ip_hdr_size + sizeof (ah_header_t) + icv_size);
205  i_b0->flags |= VLIB_BUFFER_TOTAL_LENGTH_VALID;
206 
207  /* transport mode */
208  if (PREDICT_FALSE (!sa0->is_tunnel && !sa0->is_tunnel_ip6))
209  {
210  tunnel_mode = 0;
211 
212  if (PREDICT_TRUE
213  ((ih4->ip_version_and_header_length & 0xF0) != 0x40))
214  {
215  if (PREDICT_TRUE
216  ((ih4->ip_version_and_header_length & 0xF0) == 0x60))
217  transport_ip6 = 1;
218  else
219  {
220  clib_warning ("next header: 0x%x", ah0->nexthdr);
222  AH_DECRYPT_ERROR_NOT_IP,
223  1);
224  goto trace;
225  }
226  }
227  }
228 
229  if (PREDICT_TRUE (tunnel_mode))
230  {
231  if (PREDICT_TRUE (ah0->nexthdr == IP_PROTOCOL_IP_IN_IP))
232  next0 = AH_DECRYPT_NEXT_IP4_INPUT;
233  else if (ah0->nexthdr == IP_PROTOCOL_IPV6)
234  next0 = AH_DECRYPT_NEXT_IP6_INPUT;
235  else
236  {
237  clib_warning ("next header: 0x%x", ah0->nexthdr);
239  AH_DECRYPT_ERROR_DECRYPTION_FAILED,
240  1);
241  goto trace;
242  }
243  }
244  /* transport mode */
245  else
246  {
247  if (PREDICT_FALSE (transport_ip6))
248  {
249  ih6 =
250  (ip6_header_t *) (i_b0->data +
251  sizeof (ethernet_header_t));
252  vlib_buffer_advance (i_b0, -sizeof (ip6_header_t));
253  oh6 = vlib_buffer_get_current (i_b0);
254  memmove (oh6, ih6, sizeof (ip6_header_t));
255 
256  next0 = AH_DECRYPT_NEXT_IP6_INPUT;
257  oh6->protocol = ah0->nexthdr;
258  oh6->payload_length =
259  clib_host_to_net_u16 (vlib_buffer_length_in_chain
260  (vm, i_b0) - sizeof (ip6_header_t));
261  }
262  else
263  {
264  vlib_buffer_advance (i_b0, -sizeof (ip4_header_t));
265  oh4 = vlib_buffer_get_current (i_b0);
266  memmove (oh4, ih4, sizeof (ip4_header_t));
267 
268  next0 = AH_DECRYPT_NEXT_IP4_INPUT;
269  oh4->ip_version_and_header_length = 0x45;
270  oh4->fragment_id = 0;
271  oh4->flags_and_fragment_offset = 0;
272  oh4->protocol = ah0->nexthdr;
273  oh4->length =
274  clib_host_to_net_u16 (vlib_buffer_length_in_chain
275  (vm, i_b0));
276  oh4->ttl = ttl;
277  oh4->tos = tos;
278  oh4->checksum = ip4_header_checksum (oh4);
279  }
280  }
281 
282  /* for IPSec-GRE tunnel next node is ipsec-gre-input */
283  if (PREDICT_FALSE
284  ((vnet_buffer (i_b0)->ipsec.flags) &
286  next0 = AH_DECRYPT_NEXT_IPSEC_GRE_INPUT;
287 
288 
289  vnet_buffer (i_b0)->sw_if_index[VLIB_TX] = (u32) ~ 0;
290  trace:
291  if (PREDICT_FALSE (i_b0->flags & VLIB_BUFFER_IS_TRACED))
292  {
293  i_b0->flags |= VLIB_BUFFER_IS_TRACED;
294  ah_decrypt_trace_t *tr =
295  vlib_add_trace (vm, node, i_b0, sizeof (*tr));
296  tr->integ_alg = sa0->integ_alg;
297  }
298  vlib_validate_buffer_enqueue_x1 (vm, node, next_index, to_next,
299  n_left_to_next, i_bi0, next0);
300  }
301  vlib_put_next_frame (vm, node, next_index, n_left_to_next);
302  }
304  AH_DECRYPT_ERROR_RX_PKTS,
305  from_frame->n_vectors);
306 
307  return from_frame->n_vectors;
308 }
309 
310 
311 /* *INDENT-OFF* */
313  .function = ah_decrypt_node_fn,
314  .name = "ah-decrypt",
315  .vector_size = sizeof (u32),
316  .format_trace = format_ah_decrypt_trace,
317  .type = VLIB_NODE_TYPE_INTERNAL,
318 
319  .n_errors = ARRAY_LEN(ah_decrypt_error_strings),
320  .error_strings = ah_decrypt_error_strings,
321 
322  .n_next_nodes = AH_DECRYPT_N_NEXT,
323  .next_nodes = {
324 #define _(s,n) [AH_DECRYPT_NEXT_##s] = n,
326 #undef _
327  },
328 };
329 /* *INDENT-ON* */
330 
332 /*
333  * fd.io coding-style-patch-verification: ON
334  *
335  * Local Variables:
336  * eval: (c-set-style "gnu")
337  * End:
338  */
static char * ah_decrypt_error_strings[]
Definition: ah_decrypt.c:57
static vlib_cli_command_t trace
(constructor) VLIB_CLI_COMMAND (trace)
Definition: vlib_api_cli.c:862
#define CLIB_UNUSED(x)
Definition: clib.h:79
ipsec_proto_main_integ_alg_t * ipsec_proto_main_integ_algs
Definition: esp.h:101
#define PREDICT_TRUE(x)
Definition: clib.h:106
static void esp_replay_advance(ipsec_sa_t *sa, u32 seq)
Definition: esp.h:175
static int ip4_header_bytes(ip4_header_t *i)
Definition: ip4_packet.h:234
static unsigned int hmac_calc(ipsec_integ_alg_t alg, u8 *key, int key_len, u8 *data, int data_len, u8 *signature, u8 use_esn, u32 seq_hi)
Definition: esp.h:331
ipsec_integ_alg_t integ_alg
Definition: ipsec.h:121
u8 is_tunnel
Definition: ipsec.h:128
u8 * format(u8 *s, const char *fmt,...)
Definition: format.c:419
u16 flags_and_fragment_offset
Definition: ip4_packet.h:150
static uword vlib_buffer_length_in_chain(vlib_main_t *vm, vlib_buffer_t *b)
Get length in bytes of the buffer chain.
Definition: buffer_funcs.h:250
ah_decrypt_error_t
Definition: ah_decrypt.c:49
unsigned char u8
Definition: types.h:56
u32 seq_hi
Definition: ipsec.h:138
u8 integ_key[128]
Definition: ipsec.h:123
static void esp_replay_advance_esn(ipsec_sa_t *sa, u32 seq)
Definition: esp.h:196
ipsec_main_t ipsec_main
Definition: ipsec.c:30
unsigned int seq_no
Definition: ah.h:33
static uword ah_decrypt_node_fn(vlib_main_t *vm, vlib_node_runtime_t *node, vlib_frame_t *from_frame)
Definition: ah_decrypt.c:81
u8 use_esn
Definition: ipsec.h:125
vlib_node_registration_t ah_decrypt_node
(constructor) VLIB_REGISTER_NODE (ah_decrypt_node)
Definition: ah_decrypt.c:312
unsigned int u32
Definition: types.h:88
static u8 * format_ah_decrypt_trace(u8 *s, va_list *args)
Definition: ah_decrypt.c:70
#define foreach_ah_decrypt_error
Definition: ah_decrypt.c:41
#define VLIB_NODE_FUNCTION_MULTIARCH(node, fn)
Definition: node.h:194
#define pool_elt_at_index(p, i)
Returns pointer to element at given index.
Definition: pool.h:464
ipsec_integ_alg_t
Definition: ipsec.h:97
u16 current_length
Nbytes between current data and the end of this buffer.
Definition: buffer.h:108
u8 is_tunnel_ip6
Definition: ipsec.h:129
static int esp_replay_check_esn(ipsec_sa_t *sa, u32 seq)
Definition: esp.h:131
static void * vlib_buffer_get_current(vlib_buffer_t *b)
Get pointer to current data to process.
Definition: buffer.h:202
#define PREDICT_FALSE(x)
Definition: clib.h:105
unsigned char nexthdr
Definition: ah.h:29
#define vlib_validate_buffer_enqueue_x1(vm, node, next_index, to_next, n_left_to_next, bi0, next0)
Finish enqueueing one buffer forward in the graph.
Definition: buffer_node.h:218
#define vlib_get_next_frame(vm, node, next_index, vectors, n_vectors_left)
Get pointer to next frame vector data by (vlib_node_runtime_t, next_index).
Definition: node_funcs.h:364
static void vlib_node_increment_counter(vlib_main_t *vm, u32 node_index, u32 counter_index, u64 increment)
Definition: node_funcs.h:1168
#define VLIB_REGISTER_NODE(x,...)
Definition: node.h:153
u16 n_vectors
Definition: node.h:380
vlib_main_t * vm
Definition: buffer.c:294
#define clib_warning(format, args...)
Definition: error.h:59
#define ARRAY_LEN(x)
Definition: clib.h:59
void vlib_put_next_frame(vlib_main_t *vm, vlib_node_runtime_t *r, u32 next_index, u32 n_vectors_left)
Release pointer to next frame vector data.
Definition: main.c:454
#define foreach_ah_decrypt_next
Definition: ah_decrypt.c:26
u16 cached_next_index
Next frame index that vector arguments were last enqueued to last time this node ran.
Definition: node.h:492
static int esp_replay_check(ipsec_sa_t *sa, u32 seq)
Definition: esp.h:113
ipsec_sa_t * sad
Definition: ipsec.h:264
u64 total_data_size
Definition: ipsec.h:144
u8 integ_key_len
Definition: ipsec.h:122
static void vlib_buffer_advance(vlib_buffer_t *b, word l)
Advance current data pointer by the supplied (signed!) amount.
Definition: buffer.h:215
static void * vlib_add_trace(vlib_main_t *vm, vlib_node_runtime_t *r, vlib_buffer_t *b, u32 n_data_bytes)
Definition: trace_funcs.h:55
u8 * format_ipsec_integ_alg(u8 *s, va_list *args)
Definition: ipsec_format.c:90
Definition: defs.h:47
ah_decrypt_next_t
Definition: ah_decrypt.c:33
u64 uword
Definition: types.h:112
static void * vlib_frame_vector_args(vlib_frame_t *f)
Get pointer to frame vector data.
Definition: node_funcs.h:267
#define vnet_buffer(b)
Definition: buffer.h:360
Definition: ah.h:27
u8 data[0]
Packet data.
Definition: buffer.h:172
ipsec_proto_main_t ipsec_proto_main
Definition: esp_encrypt.c:26
u8 ip_version_and_header_length
Definition: ip4_packet.h:137
u32 flags
buffer flags: VLIB_BUFFER_FREE_LIST_INDEX_MASK: bits used to store free list index, VLIB_BUFFER_IS_TRACED: trace this buffer.
Definition: buffer.h:111
u8 use_anti_replay
Definition: ipsec.h:126
ipsec_integ_alg_t integ_alg
Definition: ah_decrypt.c:65
static vlib_buffer_t * vlib_get_buffer(vlib_main_t *vm, u32 buffer_index)
Translate buffer index into buffer pointer.
Definition: buffer_funcs.h:57
#define IPSEC_FLAG_IPSEC_GRE_TUNNEL
Definition: ipsec.h:21
static u16 ip4_header_checksum(ip4_header_t *i)
Definition: ip4_packet.h:246