blob: 14a07ab90efa9ce3cbb730026cf0fdddf1fa7215 [file] [log] [blame]
developer02e65912023-08-17 16:33:10 +08001/* sa_builder_extended_ipsec.c
2 *
3 * IPsec specific functions (for initialization of SABuilder_Params_t
4 * structures and for building the IPSec specifc part of an SA.) in the
5 * Extended use case.
6 */
7
8/*****************************************************************************
9* Copyright (c) 2011-2022 by Rambus, Inc. and/or its subsidiaries.
10*
11* This program is free software: you can redistribute it and/or modify
12* it under the terms of the GNU General Public License as published by
13* the Free Software Foundation, either version 2 of the License, or
14* any later version.
15*
16* This program is distributed in the hope that it will be useful,
17* but WITHOUT ANY WARRANTY; without even the implied warranty of
18* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19* GNU General Public License for more details.
20*
21* You should have received a copy of the GNU General Public License
22* along with this program. If not, see <http://www.gnu.org/licenses/>.
23*****************************************************************************/
24
25/*----------------------------------------------------------------------------
26 * This module implements (provides) the following interface(s):
27 */
28#include "c_sa_builder.h"
29
30#ifdef SAB_ENABLE_IPSEC_EXTENDED
31#include "sa_builder_extended_internal.h"
32
33/*----------------------------------------------------------------------------
34 * This module uses (requires) the following interface(s):
35 */
36#include "basic_defs.h"
37#include "log.h"
38#include "sa_builder_internal.h" /* SABuilder_SetIpsecParams */
39#include "sa_builder_ipsec.h"
40
41/*----------------------------------------------------------------------------
42 * Definitions and macros
43 */
44#define ESP_HDR_LEN 8
45#define IPV4_HDR_LEN 20
46#define IPV6_HDR_LEN 40
47
48/*----------------------------------------------------------------------------
49 * Local variables
50 */
51
52
53#ifdef SAB_ENABLE_EXTENDED_TUNNEL_HEADER
54/*----------------------------------------------------------------------------
55 * get16
56 *
57 * Read 16-bit value from byte array not changing the byte order.
58 */
59static uint16_t
60get16no(
61 uint8_t *p,
62 unsigned int offs)
63{
64 return (p[offs+1]<<8) | p[offs];
65}
66#endif
67
68/*----------------------------------------------------------------------------
69 * SABuilder_SetExtendedIPsecParams
70 *
71 * Fill in IPsec-specific extensions into the SA.for Extended.
72 *
73 * SAParams_p (input)
74 * The SA parameters structure from which the SA is derived.
75 * SAState_p (input, output)
76 * Variables containing information about the SA being generated/
77 * SABuffer_p (input, output).
78 * The buffer in which the SA is built. If NULL, no SA will be built, but
79 * state variables in SAState_p will still be updated.
80 *
81 * Return:
82 * SAB_STATUS_OK on success
83 * SAB_INVALID_PARAMETER when SAParams_p is invalid, or if any of
84 * the buffer arguments is a null pointer while the corresponding buffer
85 * would be required for the operation.
86 * SAB_UNSUPPORTED_FEATURE when SAParams_p describes an operations that
87 * is not supported on the hardware for which this SA builder
88 * is configured.
89 */
90SABuilder_Status_t
91SABuilder_SetExtendedIPsecParams(SABuilder_Params_t *const SAParams_p,
92 SABuilder_State_t * const SAState_p,
93 uint32_t * const SABuffer_p)
94{
95 SABuilder_Params_IPsec_t *SAParamsIPsec_p =
96 (SABuilder_Params_IPsec_t *)(SAParams_p->ProtocolExtension_p);
97 uint32_t TokenHeaderWord = SAB_HEADER_DEFAULT;
98 SABuilder_ESPProtocol_t ESPProto;
99 SABuilder_HeaderProtocol_t HeaderProto;
100 uint8_t PadBlockByteCount;
101 uint8_t IVByteCount;
102 uint8_t ICVByteCount;
103 uint8_t SeqOffset;
104 uint8_t ExtSeq = 0;
105 uint8_t AntiReplay;
106 uint32_t CCMSalt = 0;
107 uint32_t flags = 0;
108 uint32_t VerifyInstructionWord, CtxInstructionWord;
109#ifdef SAB_ENABLE_EXTENDED_TUNNEL_HEADER
110 uint32_t MTUDiscount = 0;
111 uint32_t CheckSum = 0;
112#endif
113 IDENTIFIER_NOT_USED(SAState_p);
114
115 if (SAParamsIPsec_p == NULL)
116 {
117 LOG_CRIT("SABuilder: IPsec extension pointer is null\n");
118 return SAB_INVALID_PARAMETER;
119 }
120
121 if ((SAParamsIPsec_p->IPsecFlags & SAB_IPSEC_ESP) == 0)
122 {
123 LOG_CRIT("SABuilder: IPsec only supports ESP.\n");
124 return SAB_INVALID_PARAMETER;
125 }
126
127 if ((SAParamsIPsec_p->IPsecFlags & SAB_IPSEC_XFRM_API) != 0)
128 {
129 if(SAParams_p->CryptoMode != SAB_CRYPTO_MODE_CBC &&
130 SAParams_p->CryptoMode != SAB_CRYPTO_MODE_GCM)
131 {
132 LOG_CRIT("SABuilder: IPsec for XFRM only supports CBC and GCM modes.\n");
133 return SAB_INVALID_PARAMETER;
134 }
135 if ((SAParamsIPsec_p->IPsecFlags & SAB_IPSEC_NATT) != 0)
136 {
137 LOG_CRIT("SABuilder: IPsec for XFRM does not support NATT\n");
138 return SAB_INVALID_PARAMETER;
139 }
140
141 }
142 if ((SAParamsIPsec_p->IPsecFlags & SAB_IPSEC_NO_ANTI_REPLAY) != 0)
143 AntiReplay = 0;
144 else
145 AntiReplay = 1;
146
147 if (SAParams_p->direction == SAB_DIRECTION_OUTBOUND)
148 {
149 if ((SAParamsIPsec_p->IPsecFlags & SAB_IPSEC_XFRM_API) != 0)
150 ESPProto = SAB_ESP_PROTO_OUT_XFRM_CBC;
151 else
152 ESPProto = SAB_ESP_PROTO_OUT_CBC;
153 PadBlockByteCount = 4;
154 if ((SAParamsIPsec_p->IPsecFlags & SAB_IPSEC_IPV6) !=0)
155 {
156 if ((SAParamsIPsec_p->IPsecFlags & SAB_IPSEC_XFRM_API) != 0)
157 {
158 HeaderProto = SAB_HDR_IPV6_OUT_XFRM;
159 }
160 else if ((SAParamsIPsec_p->IPsecFlags & SAB_IPSEC_PROCESS_IP_HEADERS) !=0)
161 {
162 if ((SAParamsIPsec_p->IPsecFlags & SAB_IPSEC_TUNNEL) !=0)
163 {
164 HeaderProto = SAB_HDR_IPV6_OUT_TUNNEL;
165 }
166 else
167 {
168 HeaderProto = SAB_HDR_IPV6_OUT_TRANSP;
169 }
170 }
171 else
172 {
173 HeaderProto = SAB_HDR_IPV6_OUT_TRANSP_HDRBYPASS;
174 }
175 }
176 else
177 {
178 if ((SAParamsIPsec_p->IPsecFlags & SAB_IPSEC_XFRM_API) != 0)
179 {
180 HeaderProto = SAB_HDR_IPV4_OUT_XFRM;
181 }
182 else if ((SAParamsIPsec_p->IPsecFlags & SAB_IPSEC_PROCESS_IP_HEADERS) !=0)
183 {
184 if ((SAParamsIPsec_p->IPsecFlags & SAB_IPSEC_TUNNEL) !=0)
185 {
186 HeaderProto = SAB_HDR_IPV4_OUT_TUNNEL;
187 }
188 else
189 {
190 HeaderProto = SAB_HDR_IPV4_OUT_TRANSP;
191 }
192 }
193 else
194 {
195 HeaderProto = SAB_HDR_IPV4_OUT_TRANSP_HDRBYPASS;
196 }
197 }
198
199 if ((SAParamsIPsec_p->IPsecFlags & SAB_IPSEC_LONG_SEQ) != 0)
200 ExtSeq = 1;
201 }
202 else
203 {
204 if ((SAParamsIPsec_p->IPsecFlags & SAB_IPSEC_XFRM_API) != 0)
205 ESPProto = SAB_ESP_PROTO_IN_XFRM_CBC;
206 else
207 ESPProto = SAB_ESP_PROTO_IN_CBC;
208 PadBlockByteCount = 4;
209 TokenHeaderWord |= SAB_HEADER_PAD_VERIFY;
210
211 if ((SAParamsIPsec_p->IPsecFlags & SAB_IPSEC_IPV6) !=0)
212 {
213 if ((SAParamsIPsec_p->IPsecFlags & SAB_IPSEC_XFRM_API) != 0)
214 {
215 HeaderProto = SAB_HDR_IPV6_IN_XFRM;
216 }
217 else if ((SAParamsIPsec_p->IPsecFlags & SAB_IPSEC_PROCESS_IP_HEADERS) !=0)
218 {
219 if ((SAParamsIPsec_p->IPsecFlags & SAB_IPSEC_TUNNEL) !=0)
220 {
221 HeaderProto = SAB_HDR_IPV6_IN_TUNNEL;
222 }
223 else
224 {
225 HeaderProto = SAB_HDR_IPV6_IN_TRANSP;
226 TokenHeaderWord |= SAB_HEADER_UPD_HDR;
227 }
228 }
229 else
230 {
231 HeaderProto = SAB_HDR_IPV6_IN_TRANSP_HDRBYPASS;
232 }
233 }
234 else
235 {
236 if ((SAParamsIPsec_p->IPsecFlags & SAB_IPSEC_XFRM_API) != 0)
237 {
238 HeaderProto = SAB_HDR_IPV4_IN_XFRM;
239 }
240 else if ((SAParamsIPsec_p->IPsecFlags & SAB_IPSEC_PROCESS_IP_HEADERS) !=0)
241 {
242 if ((SAParamsIPsec_p->IPsecFlags & SAB_IPSEC_TUNNEL) !=0)
243 {
244 HeaderProto = SAB_HDR_IPV4_IN_TUNNEL;
245 }
246 else
247 {
248 HeaderProto = SAB_HDR_IPV4_IN_TRANSP;
249 TokenHeaderWord |= SAB_HEADER_UPD_HDR;
250 }
251 }
252 else
253 {
254 HeaderProto = SAB_HDR_IPV4_IN_TRANSP_HDRBYPASS;
255 }
256 }
257
258 if ((SAParamsIPsec_p->IPsecFlags & SAB_IPSEC_LONG_SEQ) != 0)
259 ExtSeq = 1;
260 AntiReplay *= SAParamsIPsec_p->SequenceMaskBitCount / 32;
261 }
262 SeqOffset = SAParams_p->OffsetSeqNum;
263
264 switch (SAParams_p->CryptoAlgo)
265 {
266 case SAB_CRYPTO_NULL:
267 IVByteCount = 0;
268 break;
269 case SAB_CRYPTO_DES:
270 case SAB_CRYPTO_3DES:
271 IVByteCount = 8;
272 PadBlockByteCount = 8;
273 break;
274 case SAB_CRYPTO_AES:
275 case SAB_CRYPTO_SM4:
276 case SAB_CRYPTO_BC0:
277 if (SAParams_p->CryptoMode == SAB_CRYPTO_MODE_CBC)
278 {
279 IVByteCount = 16;
280 PadBlockByteCount = 16;
281 }
282 else
283 {
284 if (SAParams_p->direction == SAB_DIRECTION_OUTBOUND)
285 ESPProto = SAB_ESP_PROTO_OUT_CTR;
286 else
287 ESPProto = SAB_ESP_PROTO_IN_CTR;
288
289 if (SAParams_p->IVSrc == SAB_IV_SRC_IMPLICIT)
290 IVByteCount = 0;
291 else
292 IVByteCount = 8;
293 }
294 break;
295 case SAB_CRYPTO_CHACHA20:
296 if (SAParams_p->direction == SAB_DIRECTION_OUTBOUND)
297 ESPProto = SAB_ESP_PROTO_OUT_CHACHAPOLY;
298 else
299 ESPProto = SAB_ESP_PROTO_IN_CHACHAPOLY;
300
301 if (SAParams_p->IVSrc == SAB_IV_SRC_IMPLICIT)
302 IVByteCount = 0;
303 else
304 IVByteCount = 8;
305 break;
306 default:
307 LOG_CRIT("SABuilder_BuildSA:"
308 "Unsupported Crypto algorithm\n");
309 return SAB_INVALID_PARAMETER;
310 ;
311 }
312
313 /* For all inbound and CTR mode outbound packets there is
314 only one supported way to obtain the IV, which is already
315 taken care of. Now handle outbound CBC. */
316 if(SAParams_p->CryptoMode == SAB_CRYPTO_MODE_CBC &&
317 SAParams_p->direction == SAB_DIRECTION_OUTBOUND &&
318 SAParams_p->CryptoAlgo != SAB_CRYPTO_NULL)
319 {
320 switch (SAParams_p->IVSrc)
321 {
322 case SAB_IV_SRC_PRNG:
323 TokenHeaderWord |=
324 SAB_HEADER_IV_PRNG;
325 break;
326 case SAB_IV_SRC_DEFAULT:
327 case SAB_IV_SRC_SA: /* No action required */
328 case SAB_IV_SRC_TOKEN:
329 break;
330 default:
331 LOG_CRIT("SABuilder_BuildSA:"
332 "Unsupported IV source\n");
333 return SAB_INVALID_PARAMETER;
334 }
335 }
336
337 if (SAParams_p->direction == SAB_DIRECTION_OUTBOUND &&
338 SAParamsIPsec_p->PadAlignment >
339 PadBlockByteCount &&
340 SAParamsIPsec_p->PadAlignment <= 256)
341 PadBlockByteCount =
342 SAParamsIPsec_p->PadAlignment;
343
344 switch(SAParams_p->AuthAlgo)
345 {
346 case SAB_AUTH_NULL:
347 ICVByteCount = 0;
348 ExtSeq = 0;
349 if (SAParams_p->direction == SAB_DIRECTION_OUTBOUND)
350 ESPProto = SAB_ESP_PROTO_OUT_NULLAUTH;
351 else
352 ESPProto = SAB_ESP_PROTO_IN_NULLAUTH;
353
354 break;
355 case SAB_AUTH_HMAC_MD5:
356 case SAB_AUTH_HMAC_SHA1:
357 case SAB_AUTH_AES_XCBC_MAC:
358 case SAB_AUTH_AES_CMAC_128:
359 ICVByteCount = 12;
360 break;
361 case SAB_AUTH_HMAC_SHA2_224:
362 case SAB_AUTH_HMAC_SHA2_256:
363 case SAB_AUTH_HMAC_SM3:
364 ICVByteCount = 16;
365 break;
366 case SAB_AUTH_HMAC_SHA2_384:
367 ICVByteCount = 24;
368 break;
369 case SAB_AUTH_HMAC_SHA2_512:
370 ICVByteCount = 32;
371 break;
372 case SAB_AUTH_AES_CCM:
373 case SAB_AUTH_AES_GCM:
374 case SAB_AUTH_AES_GMAC:
375 // All these protocols have a selectable ICV length.
376 if (SAParamsIPsec_p->ICVByteCount == 8 ||
377 SAParamsIPsec_p->ICVByteCount == 12 ||
378 SAParamsIPsec_p->ICVByteCount == 16)
379 {
380 ICVByteCount =
381 SAParamsIPsec_p->ICVByteCount;
382 }
383 else
384 {
385 ICVByteCount = 16;
386 }
387 switch (SAParams_p->AuthAlgo)
388 {
389 /* These protocols need specialized protocol codes
390 for the token generator.*/
391 case SAB_AUTH_AES_CCM:
392 if (SAParams_p->direction == SAB_DIRECTION_OUTBOUND)
393 ESPProto = SAB_ESP_PROTO_OUT_CCM;
394 else
395 ESPProto = SAB_ESP_PROTO_IN_CCM;
396
397 CCMSalt =
398 (SAParams_p->Nonce_p[0] << 8) |
399 (SAParams_p->Nonce_p[1] << 16) |
400 (SAParams_p->Nonce_p[2] << 24) |
401 SAB_CCM_FLAG_ADATA_L4 |
402 ((ICVByteCount-2)*4);
403 break;
404 case SAB_AUTH_AES_GCM:
405 if (SAParams_p->direction == SAB_DIRECTION_OUTBOUND)
406 {
407 if ((SAParamsIPsec_p->IPsecFlags & SAB_IPSEC_XFRM_API) != 0)
408 ESPProto = SAB_ESP_PROTO_OUT_XFRM_GCM;
409 else
410 ESPProto = SAB_ESP_PROTO_OUT_GCM;
411 }
412 else
413 {
414 if ((SAParamsIPsec_p->IPsecFlags & SAB_IPSEC_XFRM_API) != 0)
415 ESPProto = SAB_ESP_PROTO_IN_XFRM_GCM;
416 else
417 ESPProto = SAB_ESP_PROTO_IN_GCM;
418 }
419 break;
420 case SAB_AUTH_AES_GMAC:
421 if (SAParams_p->direction == SAB_DIRECTION_OUTBOUND)
422 ESPProto = SAB_ESP_PROTO_OUT_GMAC;
423 else
424 ESPProto = SAB_ESP_PROTO_IN_GMAC;
425 break;
426 default:
427 ;
428 }
429 break;
430 case SAB_AUTH_POLY1305:
431 ICVByteCount = 16;
432 break;
433 default:
434 LOG_CRIT("SABuilder_BuildSA: unsupported authentication algorithm\n");
435 return SAB_UNSUPPORTED_FEATURE;
436 }
437
438
439 /* Flags variable */
440 if ((SAParamsIPsec_p->IPsecFlags & SAB_IPSEC_IPV6) !=0)
441 flags |= BIT_8;
442 if ((SAParamsIPsec_p->IPsecFlags & SAB_IPSEC_PROCESS_IP_HEADERS) !=0)
443 flags |= BIT_19;
444 if (ExtSeq !=0)
445 flags |= BIT_29;
446 if ((SAParamsIPsec_p->IPsecFlags & SAB_IPSEC_DEC_TTL) != 0)
447 flags |= BIT_27;
448 if ((SAParamsIPsec_p->IPsecFlags & SAB_IPSEC_CLEAR_DF) != 0)
449 flags |= BIT_20;
450 if ((SAParamsIPsec_p->IPsecFlags & SAB_IPSEC_SET_DF) != 0)
451 flags |= BIT_21;
452 if ((SAParamsIPsec_p->IPsecFlags & SAB_IPSEC_REPLACE_DSCP) != 0)
453 flags |= BIT_22;
454 if ((SAParamsIPsec_p->IPsecFlags & SAB_IPSEC_CLEAR_ECN) != 0)
455 flags |= BIT_23;
456 if ((SAParamsIPsec_p->IPsecFlags & SAB_IPSEC_APPEND_SEQNUM) != 0)
457 {
458 if ((SAParamsIPsec_p->IPsecFlags & SAB_IPSEC_LONG_SEQ) != 0)
459 flags |= BIT_25;
460 else
461 flags |= BIT_24;
462 }
463 if ((SAParamsIPsec_p->IPsecFlags & SAB_IPSEC_TRANSPORT_NAT) != 0)
464 {
465 if ((SAParamsIPsec_p->IPsecFlags & SAB_IPSEC_TUNNEL) != 0)
466 {
467 LOG_CRIT("NAT only for transport\n");
468 return SAB_INVALID_PARAMETER;
469 }
470 if (SAParams_p->direction==SAB_DIRECTION_INBOUND &&
471 SAParamsIPsec_p->SequenceMaskBitCount > 128)
472 {
473 if (SAState_p->fLarge && LargeTransformOffset == 16)
474 {
475 LOG_CRIT(
476 "SABuilder_BuildSA: Inbound NAT cannot be combined with \n"
477 " anti-replay mask > 128\n and HMAC-SHA384/512\n");
478 return SAB_UNSUPPORTED_FEATURE;
479 }
480 else if (SAParams_p->OffsetSeqNum == SAB_SEQNUM_HI_FIX_OFFSET &&
481 SAParamsIPsec_p->SequenceMaskBitCount > 384)
482 {
483 LOG_CRIT(
484 "SABuilder_BuildSA: Inbound NAT cannot be combined with \n"
485 " anti-replay mask > 384\n and HMAC-SHA384/512\n");
486 return SAB_UNSUPPORTED_FEATURE;
487 }
488 else
489 {
490 SAState_p->fLarge = true;
491 }
492 }
493 flags |= BIT_28;
494 }
495
496 /* Take care of the VERIFY and CTX token instructions */
497 if (SAParams_p->direction == SAB_DIRECTION_OUTBOUND)
498 {
499 VerifyInstructionWord = SAB_VERIFY_NONE;
500#ifdef SAB_ENABLE_TWO_FIXED_RECORD_SIZES
501 if ((SAParamsIPsec_p->IPsecFlags & SAB_IPSEC_XFRM_API) != 0)
502 {
503 if (SAState_p->fLarge)
504 {
505 CtxInstructionWord = SAB_CTX_NONE + FIRMWARE_EIP207_CS_FLOW_TRC_RECORD_WORD_COUNT + LargeTransformOffset - 1;
506 }
507 else
508#endif
509 {
510 CtxInstructionWord = SAB_CTX_NONE + FIRMWARE_EIP207_CS_FLOW_TRC_RECORD_WORD_COUNT - 1;
511 }
512 }
513 else
514 {
515 CtxInstructionWord = SAB_CTX_OUT_SEQNUM +
516 ((unsigned int)(ExtSeq+1)<<24) + SeqOffset;
517 }
518 }
519 else
520 {
521 VerifyInstructionWord = SAB_VERIFY_PADSPI;
522 if (ICVByteCount > 0)
523 {
524 VerifyInstructionWord += SAB_VERIFY_BIT_H + ICVByteCount;
525 }
526 if (AntiReplay > 0 &&
527 (SAParamsIPsec_p->IPsecFlags & SAB_IPSEC_APPEND_SEQNUM) == 0 &&
528 (SAParamsIPsec_p->IPsecFlags & SAB_IPSEC_XFRM_API) == 0)
529 {
530 /* Skip verification of sequence number in sequence number append
531 mode. */
532 VerifyInstructionWord += SAB_VERIFY_BIT_SEQ;
533 }
534 if (ICVByteCount == 0 || AntiReplay == 0 ||
535 (SAParamsIPsec_p->IPsecFlags & SAB_IPSEC_XFRM_API) != 0)
536 {
537#ifdef SAB_ENABLE_TWO_FIXED_RECORD_SIZES
538 if (SAState_p->fLarge)
539 {
540 CtxInstructionWord = SAB_CTX_NONE + FIRMWARE_EIP207_CS_FLOW_TRC_RECORD_WORD_COUNT + LargeTransformOffset - 1;
541 }
542 else
543#endif
544 {
545 CtxInstructionWord = SAB_CTX_NONE + FIRMWARE_EIP207_CS_FLOW_TRC_RECORD_WORD_COUNT - 1;
546 }
547 }
548 else if (ExtSeq != 0 ||
549 (AntiReplay != 0 &&
550 SAParams_p->OffsetSeqNum + 2 == SAParams_p->OffsetSeqMask))
551 {
552 if (AntiReplay > 12)
553 CtxInstructionWord = SAB_CTX_SEQNUM +
554 + SeqOffset;
555 else
556 CtxInstructionWord = SAB_CTX_SEQNUM +
557 ((unsigned int)(2+AntiReplay)<<24) + SeqOffset;
558 }
559 else
560 {
561 CtxInstructionWord = SAB_CTX_INSEQNUM +
562 ((unsigned int)(1+AntiReplay)<<24) + SeqOffset;
563 }
564 }
565
566#ifdef SAB_ENABLE_EXTENDED_TUNNEL_HEADER
567 /* Compute the maximum amount by which the packet can be enlarged,
568 so discount that from the output MTU to judge whether a packet can
569 be processed without fragmentation. */
570 if (SAParams_p->direction == SAB_DIRECTION_OUTBOUND)
571 {
572 MTUDiscount = ESP_HDR_LEN + 1 + PadBlockByteCount +
573 IVByteCount + ICVByteCount;
574
575 if ((SAParamsIPsec_p->IPsecFlags & SAB_IPSEC_TUNNEL) !=0)
576 {
577 if ((SAParamsIPsec_p->IPsecFlags & SAB_IPSEC_IPV4) !=0)
578 MTUDiscount += IPV4_HDR_LEN;
579 else
580 MTUDiscount += IPV6_HDR_LEN;
581
582 // for IPv4 tunnel, pre-calculate checksum on IP addresses and store them in the transform record
583 // this checksum does not include the final inversion and is performed on data
584 // as they stored in the memory
585 if ((SAParamsIPsec_p->IPsecFlags & SAB_IPSEC_IPV4) !=0)
586 {
587 // protection against NULL pointers
588 if ((SAParamsIPsec_p->SrcIPAddr_p != NULL)&&
589 (SAParamsIPsec_p->DestIPAddr_p != NULL))
590 {
591 // add the addresses (in order they are stored in the memory)
592 CheckSum += get16no(SAParamsIPsec_p->SrcIPAddr_p, 0);
593 CheckSum += get16no(SAParamsIPsec_p->SrcIPAddr_p, 2);
594 CheckSum += get16no(SAParamsIPsec_p->DestIPAddr_p, 0);
595 CheckSum += get16no(SAParamsIPsec_p->DestIPAddr_p, 2);
596
597 // process the carries
598 while ((CheckSum>>16) != 0)
599 CheckSum = (CheckSum>>16) + (CheckSum & 0xffff);
600 }
601 }
602 }
603 }
604 /* Compute the checksum delta for internal NAT operations and for inbound
605 transport NAT-T checksum fixup */
606 if ((SAParamsIPsec_p->IPsecFlags & SAB_IPSEC_TUNNEL) == 0 &&
607 (SAParamsIPsec_p->IPsecFlags & SAB_IPSEC_CHECKSUM_FIX) != 0)
608 {
609 uint8_t IPLen = SAParamsIPsec_p->IPsecFlags & SAB_IPSEC_IPV4?4:16;
610 unsigned int i;
611 // Compute source address delta only if both original and new source
612 // addresses are provided, otherwise assume source address is unchanged.
613 if (SAParamsIPsec_p->SrcIPAddr_p != NULL &&
614 SAParamsIPsec_p->OrigSrcIPAddr_p != NULL)
615 {
616 for (i=0; i<IPLen; i+=2)
617 {
618 CheckSum += get16no(SAParamsIPsec_p->SrcIPAddr_p, i);
619 CheckSum += get16no(SAParamsIPsec_p->OrigSrcIPAddr_p, i) ^ 0xffff;
620 }
621 }
622 // Compute destination address delta only if both original and
623 // new destination addresses are provided, otherwise assume
624 // destination address is unchanged.
625 if (SAParamsIPsec_p->DestIPAddr_p != NULL &&
626 SAParamsIPsec_p->OrigDestIPAddr_p != NULL)
627 {
628 for (i=0; i<IPLen; i+=2)
629 {
630 CheckSum += get16no(SAParamsIPsec_p->DestIPAddr_p, i);
631 CheckSum += get16no(SAParamsIPsec_p->OrigDestIPAddr_p, i) ^ 0xffff;
632 }
633 }
634 // process the carries
635 while ((CheckSum>>16) != 0)
636 CheckSum = (CheckSum>>16) + (CheckSum & 0xffff);
637 }
638
639#endif
640
641 /* If NAT-T selected, select other header protocol range */
642 if ((SAParamsIPsec_p->IPsecFlags & SAB_IPSEC_NATT) != 0)
643 HeaderProto += (SAB_HDR_IPV4_OUT_TRANSP_HDRBYPASS_NATT -
644 SAB_HDR_IPV4_OUT_TRANSP_HDRBYPASS);
645
646 /* Write all parameters to their respective offsets */
647 if (SABuffer_p != NULL)
648 {
649#ifdef SAB_ENABLE_TWO_FIXED_RECORD_SIZES
650 if (SAState_p->fLarge)
651 {
652 SABuffer_p[FIRMWARE_EIP207_CS_FLOW_TR_FLAGS_WORD_OFFSET +
653 LargeTransformOffset] = flags;
654 SABuffer_p[FIRMWARE_EIP207_CS_FLOW_TR_HDRPROC_CTX_WORD_OFFSET +
655 LargeTransformOffset] =
656 SAParamsIPsec_p->ContextRef;
657 SABuffer_p[FIRMWARE_EIP207_CS_FLOW_TR_BYTE_PARAM_WORD_OFFSET +
658 LargeTransformOffset] =
659 SAB_PACKBYTES(IVByteCount,ICVByteCount,HeaderProto,ESPProto);
660 SABuffer_p[FIRMWARE_EIP207_CS_FLOW_TR_TK_HDR_WORD_OFFSET +
661 LargeTransformOffset] = TokenHeaderWord;
662 if ((SAParamsIPsec_p->IPsecFlags & SAB_IPSEC_CHECKSUM_FIX) != 0 &&
663 (SAParamsIPsec_p->IPsecFlags & SAB_IPSEC_TUNNEL) == 0)
664 SABuffer_p[FIRMWARE_EIP207_CS_FLOW_TR_PAD_ALIGN_WORD_OFFSET +
665 LargeTransformOffset] =
666 SAB_PACKBYTES(PadBlockByteCount/2,
667 0,
668 CheckSum & 0xff,
669 CheckSum >> 8);
670 else if ((SAParamsIPsec_p->IPsecFlags & SAB_IPSEC_TUNNEL) != 0)
671 SABuffer_p[FIRMWARE_EIP207_CS_FLOW_TR_PAD_ALIGN_WORD_OFFSET +
672 LargeTransformOffset] =
673 SAB_PACKBYTES(PadBlockByteCount/2,
674 0,
675 SAParamsIPsec_p->TTL,
676 SAParamsIPsec_p->DSCP);
677 else
678 SABuffer_p[FIRMWARE_EIP207_CS_FLOW_TR_PAD_ALIGN_WORD_OFFSET
679 + LargeTransformOffset] =
680 SAB_PACKBYTES(PadBlockByteCount/2,
681 0,
682 0,
683 0);
684
685 SABuffer_p[FIRMWARE_EIP207_CS_FLOW_TR_CCM_SALT_WORD_OFFSET +
686 LargeTransformOffset] = CCMSalt;
687 SABuffer_p[FIRMWARE_EIP207_CS_FLOW_TR_TK_VFY_INST_WORD_OFFSET +
688 LargeTransformOffset] =
689 VerifyInstructionWord;
690 SABuffer_p[FIRMWARE_EIP207_CS_FLOW_TR_TK_CTX_INST_WORD_OFFSET +
691 LargeTransformOffset] =
692 CtxInstructionWord;
693 SABuffer_p[FIRMWARE_EIP207_CS_FLOW_TR_TIME_STAMP_LO_WORD_OFFSET +
694 LargeTransformOffset] = 0;
695 SABuffer_p[FIRMWARE_EIP207_CS_FLOW_TR_TIME_STAMP_HI_WORD_OFFSET +
696 LargeTransformOffset] = 0;
697 SABuffer_p[FIRMWARE_EIP207_CS_FLOW_TR_STAT_OCT_LO_WORD_OFFSET +
698 LargeTransformOffset] = 0;
699 SABuffer_p[FIRMWARE_EIP207_CS_FLOW_TR_STAT_OCT_HI_WORD_OFFSET +
700 LargeTransformOffset] = 0;
701 SABuffer_p[FIRMWARE_EIP207_CS_FLOW_TR_STAT_PKT_WORD_OFFSET +
702 LargeTransformOffset] = 0;
703#ifdef SAB_ENABLE_EXTENDED_TUNNEL_HEADER
704 SABuffer_p[FIMRWARE_EIP207_CS_FLOW_TR_NATT_PORTS_WORD_OFFSET +
705 LargeTransformOffset] =
706 SAB_PACKBYTES(SAParamsIPsec_p->NATTSrcPort >> 8,
707 SAParamsIPsec_p->NATTSrcPort & 0xff,
708 SAParamsIPsec_p->NATTDestPort >> 8,
709 SAParamsIPsec_p->NATTDestPort & 0xff);
710
711 if (HeaderProto == SAB_HDR_IPV4_OUT_TUNNEL ||
712 HeaderProto == SAB_HDR_IPV6_OUT_TUNNEL ||
713 HeaderProto == SAB_HDR_IPV4_OUT_TUNNEL_NATT ||
714 HeaderProto == SAB_HDR_IPV6_OUT_TUNNEL_NATT ||
715 (SAParamsIPsec_p->IPsecFlags & SAB_IPSEC_TRANSPORT_NAT) != 0)
716 {
717#ifdef SAB_STRICT_ARGS_CHECK
718 if (SAParamsIPsec_p->SrcIPAddr_p == NULL ||
719 SAParamsIPsec_p->DestIPAddr_p == NULL)
720 {
721 LOG_CRIT("SABuilder: NULL pointer tunnel address.\n");
722 return SAB_INVALID_PARAMETER;
723 }
724#endif
725 SABuilderLib_CopyKeyMat(SABuffer_p,
726 FIRMWARE_EIP207_CS_FLOW_TR_TUNNEL_SRC_WORD_OFFSET + LargeTransformOffset,
727 SAParamsIPsec_p->SrcIPAddr_p,
728 (SAParamsIPsec_p->IPsecFlags&SAB_IPSEC_IPV4)!=0?4:16);
729 SABuilderLib_CopyKeyMat(SABuffer_p,
730 FIRMWARE_EIP207_CS_FLOW_TR_TUNNEL_DST_WORD_OFFSET + LargeTransformOffset,
731 SAParamsIPsec_p->DestIPAddr_p,
732 (SAParamsIPsec_p->IPsecFlags&SAB_IPSEC_IPV4)!=0?4:16);
733
734#ifdef FIRMWARE_EIP207_CS_FLOW_TR_CHECKSUM_WORD_OFFSET
735 // checksum (only for IPv4)
736 if ((SAParamsIPsec_p->IPsecFlags & SAB_IPSEC_IPV4) !=0)
737 SABuffer_p[FIRMWARE_EIP207_CS_FLOW_TR_CHECKSUM_WORD_OFFSET +
738 LargeTransformOffset] = CheckSum;
739#endif
740 }
741
742 SABuffer_p[FIRMWARE_EIP207_CS_FLOW_TR_PATH_MTU_WORD_OFFSET +
743 LargeTransformOffset] = MTUDiscount;
744#endif /* SAB_ENABLE_EXTENDED_TUNNEL_HEADER */
745 }
746 else
747#endif /* SAB_ENABLE_TWO_FIXED_RECORD_SIZES */
748 {
749 SABuffer_p[FIRMWARE_EIP207_CS_FLOW_TR_FLAGS_WORD_OFFSET] = flags;
750 SABuffer_p[FIRMWARE_EIP207_CS_FLOW_TR_HDRPROC_CTX_WORD_OFFSET] =
751 SAParamsIPsec_p->ContextRef;
752 SABuffer_p[FIRMWARE_EIP207_CS_FLOW_TR_BYTE_PARAM_WORD_OFFSET] =
753 SAB_PACKBYTES(IVByteCount,ICVByteCount,HeaderProto,ESPProto);
754 SABuffer_p[FIRMWARE_EIP207_CS_FLOW_TR_TK_HDR_WORD_OFFSET] = TokenHeaderWord;
755 if ((SAParamsIPsec_p->IPsecFlags & SAB_IPSEC_CHECKSUM_FIX) != 0 &&
756 (SAParamsIPsec_p->IPsecFlags & SAB_IPSEC_TUNNEL) == 0)
757 SABuffer_p[FIRMWARE_EIP207_CS_FLOW_TR_PAD_ALIGN_WORD_OFFSET] =
758 SAB_PACKBYTES(PadBlockByteCount/2,
759 0,
760 CheckSum & 0xff,
761 CheckSum >> 8);
762 else if ((SAParamsIPsec_p->IPsecFlags & SAB_IPSEC_TUNNEL) != 0)
763 SABuffer_p[FIRMWARE_EIP207_CS_FLOW_TR_PAD_ALIGN_WORD_OFFSET] =
764 SAB_PACKBYTES(PadBlockByteCount/2,
765 0,
766 SAParamsIPsec_p->TTL,
767 SAParamsIPsec_p->DSCP);
768 else
769 SABuffer_p[FIRMWARE_EIP207_CS_FLOW_TR_PAD_ALIGN_WORD_OFFSET] =
770 SAB_PACKBYTES(PadBlockByteCount/2,
771 0,
772 0,
773 0);
774 SABuffer_p[FIRMWARE_EIP207_CS_FLOW_TR_CCM_SALT_WORD_OFFSET] = CCMSalt;
775 SABuffer_p[FIRMWARE_EIP207_CS_FLOW_TR_TK_VFY_INST_WORD_OFFSET] =
776 VerifyInstructionWord;
777 SABuffer_p[FIRMWARE_EIP207_CS_FLOW_TR_TK_CTX_INST_WORD_OFFSET] =
778 CtxInstructionWord;
779 SABuffer_p[FIRMWARE_EIP207_CS_FLOW_TR_TIME_STAMP_LO_WORD_OFFSET] = 0;
780 SABuffer_p[FIRMWARE_EIP207_CS_FLOW_TR_TIME_STAMP_HI_WORD_OFFSET] = 0;
781 SABuffer_p[FIRMWARE_EIP207_CS_FLOW_TR_STAT_OCT_LO_WORD_OFFSET] = 0;
782 SABuffer_p[FIRMWARE_EIP207_CS_FLOW_TR_STAT_OCT_HI_WORD_OFFSET] = 0;
783 SABuffer_p[FIRMWARE_EIP207_CS_FLOW_TR_STAT_PKT_WORD_OFFSET] = 0;
784#ifdef SAB_ENABLE_EXTENDED_TUNNEL_HEADER
785 SABuffer_p[FIMRWARE_EIP207_CS_FLOW_TR_NATT_PORTS_WORD_OFFSET] =
786 SAB_PACKBYTES(SAParamsIPsec_p->NATTSrcPort >> 8,
787 SAParamsIPsec_p->NATTSrcPort & 0xff,
788 SAParamsIPsec_p->NATTDestPort >> 8,
789 SAParamsIPsec_p->NATTDestPort & 0xff);
790
791 if (HeaderProto == SAB_HDR_IPV4_OUT_TUNNEL ||
792 HeaderProto == SAB_HDR_IPV6_OUT_TUNNEL ||
793 HeaderProto == SAB_HDR_IPV4_OUT_TUNNEL_NATT ||
794 HeaderProto == SAB_HDR_IPV6_OUT_TUNNEL_NATT ||
795 (SAParamsIPsec_p->IPsecFlags & SAB_IPSEC_TRANSPORT_NAT) != 0)
796 {
797#ifdef SAB_STRICT_ARGS_CHECK
798 if (SAParamsIPsec_p->SrcIPAddr_p == NULL ||
799 SAParamsIPsec_p->DestIPAddr_p == NULL)
800 {
801 LOG_CRIT("SABuilder: NULL pointer tunnel address.\n");
802 return SAB_INVALID_PARAMETER;
803 }
804#endif
805 SABuilderLib_CopyKeyMat(SABuffer_p,
806 FIRMWARE_EIP207_CS_FLOW_TR_TUNNEL_SRC_WORD_OFFSET,
807 SAParamsIPsec_p->SrcIPAddr_p,
808 (SAParamsIPsec_p->IPsecFlags&SAB_IPSEC_IPV4)!=0?4:16);
809 SABuilderLib_CopyKeyMat(SABuffer_p,
810 FIRMWARE_EIP207_CS_FLOW_TR_TUNNEL_DST_WORD_OFFSET,
811 SAParamsIPsec_p->DestIPAddr_p,
812 (SAParamsIPsec_p->IPsecFlags&SAB_IPSEC_IPV4)!=0?4:16);
813
814#ifdef FIRMWARE_EIP207_CS_FLOW_TR_CHECKSUM_WORD_OFFSET
815 // checksum (only for IPv4)
816 if ((SAParamsIPsec_p->IPsecFlags & SAB_IPSEC_IPV4) !=0)
817 SABuffer_p[FIRMWARE_EIP207_CS_FLOW_TR_CHECKSUM_WORD_OFFSET] = CheckSum;
818#endif
819
820 }
821 SABuffer_p[FIRMWARE_EIP207_CS_FLOW_TR_PATH_MTU_WORD_OFFSET] = MTUDiscount;
822#endif /* SAB_ENABLE_EXTENDED_TUNNEL_HEADER */
823 }
824 }
825 return SAB_STATUS_OK;
826}
827
828
829#endif /* SAB_ENABLE_IPSEC_EXTENDED */
830
831
832/* end of file sa_builder_extended_ipsec.c */