2 * ah_decrypt.c : ipsecmb AH decrypt node
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:
9 * http://www.apache.org/licenses/LICENSE-2.0
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.
18 #include <vnet/vnet.h>
19 #include <vnet/api_errno.h>
20 #include <vnet/ip/ip.h>
22 #include <vnet/ipsec/ipsec.h>
23 #include <vnet/ipsec/esp.h>
24 #include <vnet/ipsec/ah.h>
26 #include <ipsecmb/ipsecmb.h>
28 #define foreach_ah_decrypt_next \
29 _ (DROP, "error-drop") \
30 _ (IP4_INPUT, "ip4-input") \
31 _ (IP6_INPUT, "ip6-input") \
32 _ (IPSEC_GRE_INPUT, "ipsec-gre-input")
34 #define _(v, s) AH_DECRYPT_NEXT_##v,
37 foreach_ah_decrypt_next
42 #define foreach_ah_decrypt_error \
43 _ (RX_PKTS, "AH pkts received") \
44 _ (DECRYPTION_FAILED, "AH decryption failed") \
45 _ (INTEG_ERROR, "Integrity check failed") \
46 _ (REPLAY, "SA replayed packet") \
47 _ (NOT_IP, "Not IP packet (dropped)")
51 #define _(sym, str) AH_DECRYPT_ERROR_##sym,
52 foreach_ah_decrypt_error
57 static char *ah_decrypt_error_strings[] = {
58 #define _(sym, string) string,
59 foreach_ah_decrypt_error
65 ipsec_integ_alg_t integ_alg;
68 /* packet trace format function */
70 format_ah_decrypt_trace (u8 * s, va_list * args)
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 *);
76 s = format (s, "ah: integrity %U", format_ipsec_integ_alg, t->integ_alg);
84 u32 ip_version_traffic_class_and_flow_label;
88 #ifdef CLIB_MARCH_VARIANT
90 remove_ah (vlib_main_t * vm, vlib_node_runtime_t * node, u32 * bi0,
91 u32 * next0, ipsec_sa_t * sa0, u32 ip_hdr_size, u32 icv_size,
92 u8 icv_padding_len, ah_header_t * ah0, int is_ip6)
94 vlib_buffer_t *b0 = vlib_get_buffer (vm, *bi0);
98 vlib_buffer_advance (b0, ip_hdr_size + sizeof (ah_header_t) + icv_size +
100 if (ah0->nexthdr == IP_PROTOCOL_IP_IN_IP)
101 *next0 = AH_DECRYPT_NEXT_IP4_INPUT;
102 else if (ah0->nexthdr == IP_PROTOCOL_IPV6)
103 *next0 = AH_DECRYPT_NEXT_IP6_INPUT;
106 clib_warning ("next header: 0x%x", ah0->nexthdr);
107 vlib_node_increment_counter (vm, node->node_index,
108 AH_DECRYPT_ERROR_DECRYPTION_FAILED, 1);
109 *next0 = AH_DECRYPT_NEXT_DROP;
114 { /* transport mode */
115 const size_t ip_hdr_offset =
116 sizeof (ah_header_t) + icv_size + icv_padding_len;
120 (ip6_header_t *) ((u8 *) vlib_buffer_get_current (b0) +
122 u8 nexthdr = ah0->nexthdr;
123 memmove (ih6, vlib_buffer_get_current (b0), sizeof (ip6_header_t));
124 vlib_buffer_advance (b0, ip_hdr_offset);
126 *next0 = AH_DECRYPT_NEXT_IP6_INPUT;
127 ih6->protocol = nexthdr;
128 ih6->payload_length =
129 clib_host_to_net_u16 (vlib_buffer_length_in_chain (vm, b0) -
130 sizeof (ip6_header_t));
135 (ip4_header_t *) ((u8 *) vlib_buffer_get_current (b0) +
137 u8 nexthdr = ah0->nexthdr;
138 memmove (ih4, vlib_buffer_get_current (b0), sizeof (ip4_header_t));
139 vlib_buffer_advance (b0, ip_hdr_offset);
141 *next0 = AH_DECRYPT_NEXT_IP4_INPUT;
142 ih4->ip_version_and_header_length = 0x45;
143 ih4->fragment_id = 0;
144 ih4->flags_and_fragment_offset = 0;
145 ih4->protocol = nexthdr;
147 clib_host_to_net_u16 (vlib_buffer_length_in_chain (vm, b0));
148 ih4->checksum = ip4_header_checksum (ih4);
152 /* for IPSec-GRE tunnel next node is ipsec-gre-input */
154 ((vnet_buffer (b0)->ipsec.flags & IPSEC_FLAG_IPSEC_GRE_TUNNEL)))
156 *next0 = AH_DECRYPT_NEXT_IPSEC_GRE_INPUT;
161 ah_finish_decrypt (vlib_main_t * vm, vlib_node_runtime_t * node,
162 JOB_AES_HMAC * job, u32 * bi0, u32 * next0, int is_ip6)
164 ipsec_main_t *im = &ipsec_main;
165 *bi0 = (uintptr_t) job->user_data;
166 vlib_buffer_t *b0 = vlib_get_buffer (vm, *bi0);
168 pool_elt_at_index (im->sad, vnet_buffer (b0)->ipsec.sad_index);
169 ipsec_proto_main_t *em = &ipsec_proto_main;
170 u32 icv_size = em->ipsec_proto_main_integ_algs[sa0->integ_alg].trunc_size;
172 ip4_header_t *ih4 = vlib_buffer_get_current (b0);
174 if (PREDICT_TRUE (sa0->use_esn))
176 seq_size = sizeof (u32);
178 ip_mutable_data_t *md =
179 (ip_mutable_data_t *) ((u8 *) vlib_buffer_get_current (b0) +
180 b0->current_length + seq_size + icv_size);
183 ip_hdr_size = sizeof (ip6_header_t);
184 ip6_header_t *ih6 = vlib_buffer_get_current (b0);
185 ih6->ip_version_traffic_class_and_flow_label =
186 md->ip_version_traffic_class_and_flow_label;
187 ih6->hop_limit = md->hop_limit;
191 ip_hdr_size = ip4_header_bytes (ih4);
196 u8 icv_padding_len = ah_calc_icv_padding_len (icv_size, is_ip6);
198 (ah_header_t *) ((u8 *) vlib_buffer_get_current (b0) + ip_hdr_size);
199 void *digest = ah0 + 1;
200 void *sig = vlib_buffer_get_current (b0) + b0->current_length + seq_size;
202 if (PREDICT_FALSE (memcmp (digest, sig, icv_size)))
204 vlib_node_increment_counter (vm, node->node_index,
205 AH_DECRYPT_ERROR_INTEG_ERROR, 1);
206 *next0 = AH_DECRYPT_NEXT_DROP;
210 if (PREDICT_TRUE (sa0->use_anti_replay))
212 if (PREDICT_TRUE (sa0->use_esn))
213 esp_replay_advance_esn (sa0, clib_host_to_net_u32 (ah0->seq_no));
215 esp_replay_advance (sa0, clib_host_to_net_u32 (ah0->seq_no));
217 remove_ah (vm, node, bi0, next0, sa0, ip_hdr_size, icv_size,
218 icv_padding_len, ah0, is_ip6);
219 vnet_buffer (b0)->sw_if_index[VLIB_TX] = (u32) ~ 0;
223 ah_decrypt_ipsecmb_inline (vlib_main_t * vm,
224 vlib_node_runtime_t * node,
225 vlib_frame_t * from_frame, int is_ip6)
227 u32 n_left_from, *from, next_index, *to_next;
228 ipsec_main_t *im = &ipsec_main;
229 ipsecmb_main_t *imbm = &ipsecmb_main;
230 ipsec_proto_main_t *em = &ipsec_proto_main;
231 from = vlib_frame_vector_args (from_frame);
232 n_left_from = from_frame->n_vectors;
234 u32 thread_index = vlib_get_thread_index ();
235 MB_MGR *mgr = imbm->mb_mgr[thread_index];
236 u32 packets_in_flight = 0;
238 next_index = node->cached_next_index;
240 while (n_left_from > 0 || packets_in_flight > 0)
244 vlib_get_next_frame (vm, node, next_index, to_next, n_left_to_next);
246 while (n_left_from > 0 && n_left_to_next > 0)
256 ip4_header_t *ih4 = 0;
257 ip6_header_t *ih6 = 0;
264 next0 = AH_DECRYPT_NEXT_DROP;
266 b0 = vlib_get_buffer (vm, bi0);
267 ih4 = vlib_buffer_get_current (b0);
268 ih6 = vlib_buffer_get_current (b0);
270 sa_index0 = vnet_buffer (b0)->ipsec.sad_index;
271 sa0 = pool_elt_at_index (im->sad, sa_index0);
272 samb0 = pool_elt_at_index (imbm->sad, sa_index0);
276 ip6_ext_header_t *prev = NULL;
277 ip6_ext_header_find_t (ih6, prev, ah0, IP_PROTOCOL_IPSEC_AH);
278 ip_hdr_size = sizeof (ip6_header_t);
279 ASSERT ((u8 *) ah0 - (u8 *) ih6 == ip_hdr_size);
283 ip_hdr_size = ip4_header_bytes (ih4);
284 ah0 = (ah_header_t *) (ih4 + 1);
287 seq = clib_host_to_net_u32 (ah0->seq_no);
288 /* anti-replay check */
290 if (sa0->use_anti_replay)
294 if (PREDICT_TRUE (sa0->use_esn))
295 rv = esp_replay_check_esn (sa0, seq);
297 rv = esp_replay_check (sa0, seq);
299 if (PREDICT_FALSE (rv))
301 clib_warning ("anti-replay SPI %u seq %u", sa0->spi, seq);
302 vlib_node_increment_counter (vm, node->node_index,
303 AH_DECRYPT_ERROR_REPLAY, 1);
308 sa0->total_data_size += b0->current_length;
310 em->ipsec_proto_main_integ_algs[sa0->integ_alg].trunc_size;
311 if (PREDICT_TRUE (sa0->integ_alg != IPSEC_INTEG_ALG_NONE))
313 u8 *icv = (u8 *) vlib_buffer_get_current (b0) + ip_hdr_size +
314 sizeof (ah_header_t);
316 if (PREDICT_TRUE (sa0->use_esn))
318 *(u32 *) (vlib_buffer_get_current (b0) +
319 b0->current_length) = sa0->seq_hi;
320 seq_size = sizeof (u32);
322 clib_memcpy (vlib_buffer_get_current (b0) + b0->current_length +
323 seq_size, icv, icv_size);
324 memset (icv, 0, icv_size);
326 ip_mutable_data_t *md =
327 (ip_mutable_data_t *) ((u8 *) vlib_buffer_get_current (b0) +
328 b0->current_length + seq_size +
332 md->ip_version_traffic_class_and_flow_label =
333 ih6->ip_version_traffic_class_and_flow_label;
334 md->hop_limit = ih6->hop_limit;
335 ih6->ip_version_traffic_class_and_flow_label = 0x60;
345 ih4->flags_and_fragment_offset = 0;
348 JOB_AES_HMAC *job = IPSECMB_FUNC (get_next_job) (mgr);
349 job->src = vlib_buffer_get_current (b0);
350 job->hash_start_src_offset_in_bytes = 0;
351 job->cipher_mode = NULL_CIPHER;
352 job->hash_alg = imbm->integ_algs[sa0->integ_alg].hash_alg;
353 job->auth_tag_output_len_in_bytes =
354 imbm->integ_algs[sa0->integ_alg].hash_output_length;
355 job->auth_tag_output = icv;
356 job->msg_len_to_hash_in_bytes = b0->current_length + seq_size;
357 job->cipher_direction = DECRYPT;
358 job->chain_order = HASH_CIPHER;
359 job->u.HMAC._hashed_auth_key_xor_ipad = samb0->ipad_hash;
360 job->u.HMAC._hashed_auth_key_xor_opad = samb0->opad_hash;
362 job->user_data = (void *) (uintptr_t) bi0;
363 job->user_data2 = (void *) (uintptr_t) next0;
364 vnet_buffer (b0)->ipsec.sad_index = sa_index0;
365 job = IPSECMB_FUNC (submit_job) (mgr);
373 ASSERT (STS_COMPLETED == job->status);
374 ah_finish_decrypt (vm, node, job, &bi0, &next0, is_ip6);
378 remove_ah (vm, node, &bi0, &next0, sa0, ip_hdr_size, icv_size,
385 if (PREDICT_FALSE (b0->flags & VLIB_BUFFER_IS_TRACED))
387 b0->flags |= VLIB_BUFFER_IS_TRACED;
388 ah_decrypt_trace_t *tr =
389 vlib_add_trace (vm, node, b0, sizeof (*tr));
390 tr->integ_alg = sa0->integ_alg;
392 vlib_validate_buffer_enqueue_x1 (vm, node, next_index, to_next,
393 n_left_to_next, bi0, next0);
396 if (0 == n_left_from)
398 JOB_AES_HMAC *job = NULL;
399 while (n_left_to_next > 0 && (job = IPSECMB_FUNC (flush_job) (mgr)))
402 ASSERT (STS_COMPLETED == job->status);
404 ah_finish_decrypt (vm, node, job, &bi0, &next0, is_ip6);
408 vlib_buffer_t *b0 = vlib_get_buffer (vm, bi0);
409 if (PREDICT_FALSE (b0->flags & VLIB_BUFFER_IS_TRACED))
411 ipsec_sa_t *sa0 = pool_elt_at_index (im->sad,
413 (b0)->ipsec.sad_index);
414 b0->flags |= VLIB_BUFFER_IS_TRACED;
415 ah_decrypt_trace_t *tr =
416 vlib_add_trace (vm, node, b0, sizeof (*tr));
417 tr->integ_alg = sa0->integ_alg;
419 vlib_validate_buffer_enqueue_x1 (vm, node, next_index, to_next,
420 n_left_to_next, bi0, next0);
424 vlib_put_next_frame (vm, node, next_index, n_left_to_next);
426 vlib_node_increment_counter (vm, node->node_index, AH_DECRYPT_ERROR_RX_PKTS,
427 from_frame->n_vectors);
429 return from_frame->n_vectors;
432 VLIB_NODE_FN (ah4_decrypt_ipsecmb_node) (vlib_main_t * vm,
433 vlib_node_runtime_t * node,
434 vlib_frame_t * from_frame)
436 return ah_decrypt_ipsecmb_inline (vm, node, from_frame, 0 /*is_ip6 */ );
439 VLIB_NODE_FN (ah6_decrypt_ipsecmb_node) (vlib_main_t * vm,
440 vlib_node_runtime_t * node,
441 vlib_frame_t * from_frame)
443 return ah_decrypt_ipsecmb_inline (vm, node, from_frame, 1 /*is_ip6 */ );
448 VLIB_REGISTER_NODE (ah4_decrypt_ipsecmb_node) = {
449 .name = "ah4-decrypt-ipsecmb",
450 .vector_size = sizeof (u32),
451 .format_trace = format_ah_decrypt_trace,
452 .type = VLIB_NODE_TYPE_INTERNAL,
454 .n_errors = ARRAY_LEN (ah_decrypt_error_strings),
455 .error_strings = ah_decrypt_error_strings,
457 .n_next_nodes = AH_DECRYPT_N_NEXT,
460 #define _(s, n) [AH_DECRYPT_NEXT_##s] = n,
461 foreach_ah_decrypt_next
468 VLIB_REGISTER_NODE (ah6_decrypt_ipsecmb_node) = {
469 .name = "ah6-decrypt-ipsecmb",
470 .vector_size = sizeof (u32),
471 .format_trace = format_ah_decrypt_trace,
472 .type = VLIB_NODE_TYPE_INTERNAL,
474 .n_errors = ARRAY_LEN (ah_decrypt_error_strings),
475 .error_strings = ah_decrypt_error_strings,
477 .n_next_nodes = AH_DECRYPT_N_NEXT,
480 #define _(s, n) [AH_DECRYPT_NEXT_##s] = n,
481 foreach_ah_decrypt_next
488 * fd.io coding-style-patch-verification: ON
491 * eval: (c-set-style "gnu")