1 /* SPDX-License-Identifier: (BSD-3-Clause OR GPL-2.0)
2 *
3 * Copyright 2008-2016 Freescale Semiconductor Inc.
4 * Copyright 2016,2019-2020 NXP
5 *
6 */
7
8 #ifndef __DESC_IPSEC_H__
9 #define __DESC_IPSEC_H__
10
11 #include "rta.h"
12 #include "common.h"
13
14 /**
15 * DOC: IPsec Shared Descriptor Constructors
16 *
17 * Shared descriptors for IPsec protocol.
18 */
19
20 /* General IPSec ESP encap / decap PDB options */
21
22 /**
23 * PDBOPTS_ESP_ESN - Extended sequence included
24 */
25 #define PDBOPTS_ESP_ESN 0x10
26
27 /**
28 * PDBOPTS_ESP_IPVSN - Process IPv6 header
29 *
30 * Valid only for IPsec legacy mode.
31 */
32 #define PDBOPTS_ESP_IPVSN 0x02
33
34 /**
35 * PDBOPTS_ESP_TUNNEL - Tunnel mode next-header byte
36 *
37 * Valid only for IPsec legacy mode.
38 */
39 #define PDBOPTS_ESP_TUNNEL 0x01
40
41 /* IPSec ESP Encap PDB options */
42
43 /**
44 * PDBOPTS_ESP_UPDATE_CSUM - Update ip header checksum
45 *
46 * Valid only for IPsec legacy mode.
47 */
48 #define PDBOPTS_ESP_UPDATE_CSUM 0x80
49
50 /**
51 * PDBOPTS_ESP_DIFFSERV - Copy TOS/TC from inner iphdr
52 *
53 * Valid only for IPsec legacy mode.
54 */
55 #define PDBOPTS_ESP_DIFFSERV 0x40
56
57 /**
58 * PDBOPTS_ESP_IVSRC - IV comes from internal random gen
59 */
60 #define PDBOPTS_ESP_IVSRC 0x20
61
62 /**
63 * PDBOPTS_ESP_IPHDRSRC - IP header comes from PDB
64 *
65 * Valid only for IPsec legacy mode.
66 */
67 #define PDBOPTS_ESP_IPHDRSRC 0x08
68
69 /**
70 * PDBOPTS_ESP_INCIPHDR - Prepend IP header to output frame
71 *
72 * Valid only for IPsec legacy mode.
73 */
74 #define PDBOPTS_ESP_INCIPHDR 0x04
75
76 /**
77 * PDBOPTS_ESP_OIHI_MASK - Mask for Outer IP Header Included
78 *
79 * Valid only for IPsec new mode.
80 */
81 #define PDBOPTS_ESP_OIHI_MASK 0x0c
82
83 /**
84 * PDBOPTS_ESP_OIHI_PDB_INL - Prepend IP header to output frame from PDB (where
85 * it is inlined).
86 *
87 * Valid only for IPsec new mode.
88 */
89 #define PDBOPTS_ESP_OIHI_PDB_INL 0x0c
90
91 /**
92 * PDBOPTS_ESP_OIHI_PDB_REF - Prepend IP header to output frame from PDB
93 * (referenced by pointer).
94 *
95 * Vlid only for IPsec new mode.
96 */
97 #define PDBOPTS_ESP_OIHI_PDB_REF 0x08
98
99 /**
100 * PDBOPTS_ESP_OIHI_IF - Prepend IP header to output frame from input frame
101 *
102 * Valid only for IPsec new mode.
103 */
104 #define PDBOPTS_ESP_OIHI_IF 0x04
105
106 /**
107 * PDBOPTS_ESP_NAT - Enable RFC 3948 UDP-encapsulated-ESP
108 *
109 * Valid only for IPsec new mode.
110 */
111 #define PDBOPTS_ESP_NAT 0x02
112
113 /**
114 * PDBOPTS_ESP_NUC - Enable NAT UDP Checksum
115 *
116 * Valid only for IPsec new mode.
117 */
118 #define PDBOPTS_ESP_NUC 0x01
119
120 /* IPSec ESP Decap PDB options */
121
122 /**
123 * PDBOPTS_ESP_ARS_MASK_ERA10 - antireplay window mask
124 * for SEC_ERA >= 10
125 */
126 #define PDBOPTS_ESP_ARS_MASK_ERA10 0xc8
127
128 /**
129 * PDBOPTS_ESP_ARS_MASK - antireplay window mask
130 * for SEC_ERA < 10
131 */
132 #define PDBOPTS_ESP_ARS_MASK 0xc0
133
134 /**
135 * PDBOPTS_ESP_ARSNONE - No antireplay window
136 */
137 #define PDBOPTS_ESP_ARSNONE 0x00
138
139 /**
140 * PDBOPTS_ESP_ARS64 - 64-entry antireplay window
141 */
142 #define PDBOPTS_ESP_ARS64 0xc0
143
144 /**
145 * PDBOPTS_ESP_ARS128 - 128-entry antireplay window
146 *
147 * Valid only for IPsec new mode.
148 */
149 #define PDBOPTS_ESP_ARS128 0x80
150
151 /**
152 * PDBOPTS_ESP_ARS256 - 256-entry antireplay window
153 *
154 * Valid only for IPsec new mode.
155 */
156 #define PDBOPTS_ESP_ARS256 0x08
157
158 /**
159 * PDBOPTS_ESP_ARS512 - 512-entry antireplay window
160 *
161 * Valid only for IPsec new mode.
162 */
163 #define PDBOPTS_ESP_ARS512 0x48
164
165 /**
166 * PDBOPTS_ESP_ARS1024 - 1024-entry antireplay window
167 *
168 * Valid only for IPsec new mode.
169 */
170 #define PDBOPTS_ESP_ARS1024 0x88
171
172 /**
173 * PDBOPTS_ESP_ARS32 - 32-entry antireplay window
174 */
175 #define PDBOPTS_ESP_ARS32 0x40
176
177 /**
178 * PDBOPTS_ESP_VERIFY_CSUM - Validate ip header checksum
179 *
180 * Valid only for IPsec legacy mode.
181 */
182 #define PDBOPTS_ESP_VERIFY_CSUM 0x20
183
184 /**
185 * PDBOPTS_ESP_TECN - Implement RRFC6040 ECN tunneling from outer header to
186 * inner header.
187 *
188 * Valid only for IPsec new mode.
189 */
190 #define PDBOPTS_ESP_TECN 0x20
191
192 /**
193 * PDBOPTS_ESP_OUTFMT - Output only decapsulation
194 *
195 * Valid only for IPsec legacy mode.
196 */
197 #define PDBOPTS_ESP_OUTFMT 0x08
198
199 /**
200 * PDBOPTS_ESP_AOFL - Adjust out frame len
201 *
202 * Valid only for IPsec legacy mode and for SEC >= 5.3.
203 */
204 #define PDBOPTS_ESP_AOFL 0x04
205
206 /**
207 * PDBOPTS_ESP_ETU - EtherType Update
208 *
209 * Add corresponding ethertype (0x0800 for IPv4, 0x86dd for IPv6) in the output
210 * frame.
211 * Valid only for IPsec new mode.
212 */
213 #define PDBOPTS_ESP_ETU 0x01
214
215 #define PDBHMO_ESP_DECAP_SHIFT 28
216 #define PDBHMO_ESP_ENCAP_SHIFT 28
217 #define PDBNH_ESP_ENCAP_SHIFT 16
218 #define PDBNH_ESP_ENCAP_MASK (0xff << PDBNH_ESP_ENCAP_SHIFT)
219 #define PDBHDRLEN_ESP_DECAP_SHIFT 16
220 #define PDBHDRLEN_MASK (0x0fff << PDBHDRLEN_ESP_DECAP_SHIFT)
221 #define PDB_NH_OFFSET_SHIFT 8
222 #define PDB_NH_OFFSET_MASK (0xff << PDB_NH_OFFSET_SHIFT)
223
224 /**
225 * PDBHMO_ESP_DECAP_DTTL - IPsec ESP decrement TTL (IPv4) / Hop limit (IPv6)
226 * HMO option.
227 */
228 #define PDBHMO_ESP_DECAP_DTTL (0x02 << PDBHMO_ESP_DECAP_SHIFT)
229
230 /**
231 * PDBHMO_ESP_ENCAP_DTTL - IPsec ESP increment TTL (IPv4) / Hop limit (IPv6)
232 * HMO option.
233 */
234 #define PDBHMO_ESP_ENCAP_DTTL (0x02 << PDBHMO_ESP_ENCAP_SHIFT)
235
236 /**
237 * PDBHMO_ESP_DIFFSERV - (Decap) DiffServ Copy - Copy the IPv4 TOS or IPv6
238 * Traffic Class byte from the outer IP header to the
239 * inner IP header.
240 */
241 #define PDBHMO_ESP_DIFFSERV (0x01 << PDBHMO_ESP_DECAP_SHIFT)
242
243 /**
244 * PDBHMO_ESP_SNR - (Encap) - Sequence Number Rollover control
245 *
246 * Configures behaviour in case of SN / ESN rollover:
247 * error if SNR = 1, rollover allowed if SNR = 0.
248 * Valid only for IPsec new mode.
249 */
250 #define PDBHMO_ESP_SNR (0x01 << PDBHMO_ESP_ENCAP_SHIFT)
251
252 /**
253 * PDBHMO_ESP_DFBIT - (Encap) Copy DF bit - if an IPv4 tunnel mode outer IP
254 * header is coming from the PDB, copy the DF bit from the
255 * inner IP header to the outer IP header.
256 */
257 #define PDBHMO_ESP_DFBIT (0x04 << PDBHMO_ESP_ENCAP_SHIFT)
258
259 /**
260 * PDBHMO_ESP_DFV - (Decap) - DF bit value
261 *
262 * If ODF = 1, DF bit in output frame is replaced by DFV.
263 * Valid only from SEC Era 5 onwards.
264 */
265 #define PDBHMO_ESP_DFV (0x04 << PDBHMO_ESP_DECAP_SHIFT)
266
267 /**
268 * PDBHMO_ESP_ODF - (Decap) Override DF bit in IPv4 header of decapsulated
269 * output frame.
270 *
271 * If ODF = 1, DF is replaced with the value of DFV bit.
272 * Valid only from SEC Era 5 onwards.
273 */
274 #define PDBHMO_ESP_ODF (0x08 << PDBHMO_ESP_DECAP_SHIFT)
275
276 /**
277 * struct ipsec_encap_cbc - PDB part for IPsec CBC encapsulation
278 * @iv: 16-byte array initialization vector
279 */
280 struct ipsec_encap_cbc {
281 uint8_t iv[16];
282 };
283
284
285 /**
286 * struct ipsec_encap_ctr - PDB part for IPsec CTR encapsulation
287 * @ctr_nonce: 4-byte nonce
288 * @ctr_initial: initial count constant
289 * @iv: initialization vector
290 */
291 struct ipsec_encap_ctr {
292 uint32_t ctr_nonce;
293 uint32_t ctr_initial;
294 uint8_t iv[8];
295 };
296
297 /**
298 * struct ipsec_encap_ccm - PDB part for IPsec CCM encapsulation
299 * @salt: 3-byte array salt (lower 24 bits)
300 * @ccm_opt: CCM algorithm options - MSB-LSB description:
301 * b0_flags (8b) - CCM B0; use 0x5B for 8-byte ICV, 0x6B for 12-byte ICV,
302 * 0x7B for 16-byte ICV (cf. RFC4309, RFC3610)
303 * ctr_flags (8b) - counter flags; constant equal to 0x3
304 * ctr_initial (16b) - initial count constant
305 * @iv: initialization vector
306 */
307 struct ipsec_encap_ccm {
308 uint8_t salt[4];
309 uint32_t ccm_opt;
310 uint64_t iv;
311 };
312
313 /**
314 * struct ipsec_encap_gcm - PDB part for IPsec GCM encapsulation
315 * @salt: 3-byte array salt (lower 24 bits)
316 * @rsvd: reserved, do not use
317 * @iv: initialization vector
318 */
319 struct ipsec_encap_gcm {
320 uint8_t salt[4];
321 uint32_t rsvd;
322 uint64_t iv;
323 };
324
325 /**
326 * struct ipsec_encap_pdb - PDB for IPsec encapsulation
327 * @options: MSB-LSB description (both for legacy and new modes)
328 * hmo (header manipulation options) - 4b
329 * reserved - 4b
330 * next header (legacy) / reserved (new) - 8b
331 * next header offset (legacy) / AOIPHO (actual outer IP header offset) - 8b
332 * option flags (depend on selected algorithm) - 8b
333 * @seq_num_ext_hi: (optional) IPsec Extended Sequence Number (ESN)
334 * @seq_num: IPsec sequence number
335 * @spi: IPsec SPI (Security Parameters Index)
336 * @ip_hdr_len: optional IP Header length (in bytes)
337 * reserved - 16b
338 * Opt. IP Hdr Len - 16b
339 * @ip_hdr: optional IP Header content (only for IPsec legacy mode)
340 */
341 struct ipsec_encap_pdb {
342 uint32_t options;
343 uint32_t seq_num_ext_hi;
344 uint32_t seq_num;
345 union {
346 struct ipsec_encap_cbc cbc;
347 struct ipsec_encap_ctr ctr;
348 struct ipsec_encap_ccm ccm;
349 struct ipsec_encap_gcm gcm;
350 };
351 uint32_t spi;
352 uint32_t ip_hdr_len;
353 uint8_t ip_hdr[0];
354 };
355
356 static inline unsigned int
__rta_copy_ipsec_encap_pdb(struct program * program,struct ipsec_encap_pdb * pdb,uint32_t algtype)357 __rta_copy_ipsec_encap_pdb(struct program *program,
358 struct ipsec_encap_pdb *pdb,
359 uint32_t algtype)
360 {
361 unsigned int start_pc = program->current_pc;
362
363 __rta_out32(program, pdb->options);
364 __rta_out32(program, pdb->seq_num_ext_hi);
365 __rta_out32(program, pdb->seq_num);
366
367 switch (algtype & OP_PCL_IPSEC_CIPHER_MASK) {
368 case OP_PCL_IPSEC_DES_IV64:
369 case OP_PCL_IPSEC_DES:
370 case OP_PCL_IPSEC_3DES:
371 case OP_PCL_IPSEC_AES_CBC:
372 case OP_PCL_IPSEC_NULL:
373 rta_copy_data(program, pdb->cbc.iv, sizeof(pdb->cbc.iv));
374 break;
375
376 case OP_PCL_IPSEC_AES_CTR:
377 rta_copy_data(program, (uint8_t *)&pdb->ctr.ctr_nonce, 4);
378 __rta_out32(program, pdb->ctr.ctr_initial);
379 rta_copy_data(program, pdb->ctr.iv, sizeof(pdb->ctr.iv));
380 break;
381
382 case OP_PCL_IPSEC_AES_CCM8:
383 case OP_PCL_IPSEC_AES_CCM12:
384 case OP_PCL_IPSEC_AES_CCM16:
385 rta_copy_data(program, pdb->ccm.salt, sizeof(pdb->ccm.salt));
386 __rta_out32(program, pdb->ccm.ccm_opt);
387 __rta_out64(program, true, pdb->ccm.iv);
388 break;
389
390 case OP_PCL_IPSEC_AES_GCM8:
391 case OP_PCL_IPSEC_AES_GCM12:
392 case OP_PCL_IPSEC_AES_GCM16:
393 case OP_PCL_IPSEC_AES_NULL_WITH_GMAC:
394 rta_copy_data(program, pdb->gcm.salt, sizeof(pdb->gcm.salt));
395 __rta_out32(program, pdb->gcm.rsvd);
396 __rta_out64(program, true, pdb->gcm.iv);
397 break;
398 }
399
400 __rta_out32(program, pdb->spi);
401 __rta_out32(program, pdb->ip_hdr_len);
402
403 return start_pc;
404 }
405
406 /**
407 * struct ipsec_decap_cbc - PDB part for IPsec CBC decapsulation
408 * @rsvd: reserved, do not use
409 */
410 struct ipsec_decap_cbc {
411 uint32_t rsvd[2];
412 };
413
414 /**
415 * struct ipsec_decap_ctr - PDB part for IPsec CTR decapsulation
416 * @ctr_nonce: 4-byte nonce
417 * @ctr_initial: initial count constant
418 */
419 struct ipsec_decap_ctr {
420 uint32_t ctr_nonce;
421 uint32_t ctr_initial;
422 };
423
424 /**
425 * struct ipsec_decap_ccm - PDB part for IPsec CCM decapsulation
426 * @salt: 3-byte salt (lower 24 bits)
427 * @ccm_opt: CCM algorithm options - MSB-LSB description:
428 * b0_flags (8b) - CCM B0; use 0x5B for 8-byte ICV, 0x6B for 12-byte ICV,
429 * 0x7B for 16-byte ICV (cf. RFC4309, RFC3610)
430 * ctr_flags (8b) - counter flags; constant equal to 0x3
431 * ctr_initial (16b) - initial count constant
432 */
433 struct ipsec_decap_ccm {
434 uint8_t salt[4];
435 uint32_t ccm_opt;
436 };
437
438 /**
439 * struct ipsec_decap_gcm - PDB part for IPsec GCN decapsulation
440 * @salt: 4-byte salt
441 * @rsvd: reserved, do not use
442 */
443 struct ipsec_decap_gcm {
444 uint8_t salt[4];
445 uint32_t rsvd;
446 };
447
448 /**
449 * struct ipsec_decap_pdb - PDB for IPsec decapsulation
450 * @options: MSB-LSB description (both for legacy and new modes)
451 * hmo (header manipulation options) - 4b
452 * IP header length - 12b
453 * next header offset (legacy) / AOIPHO (actual outer IP header offset) - 8b
454 * option flags (depend on selected algorithm) - 8b
455 * @seq_num_ext_hi: (optional) IPsec Extended Sequence Number (ESN)
456 * @seq_num: IPsec sequence number
457 * @anti_replay: Anti-replay window; size depends on ARS (option flags);
458 * format must be Big Endian, irrespective of platform
459 */
460 struct ipsec_decap_pdb {
461 uint32_t options;
462 union {
463 struct ipsec_decap_cbc cbc;
464 struct ipsec_decap_ctr ctr;
465 struct ipsec_decap_ccm ccm;
466 struct ipsec_decap_gcm gcm;
467 };
468 uint32_t seq_num_ext_hi;
469 uint32_t seq_num;
470 uint32_t anti_replay[32];
471 };
472
473 static inline unsigned int
__rta_copy_ipsec_decap_pdb(struct program * program,struct ipsec_decap_pdb * pdb,uint32_t algtype)474 __rta_copy_ipsec_decap_pdb(struct program *program,
475 struct ipsec_decap_pdb *pdb,
476 uint32_t algtype)
477 {
478 unsigned int start_pc = program->current_pc;
479 unsigned int i, ars;
480 uint8_t mask;
481
482 __rta_out32(program, pdb->options);
483
484 switch (algtype & OP_PCL_IPSEC_CIPHER_MASK) {
485 case OP_PCL_IPSEC_DES_IV64:
486 case OP_PCL_IPSEC_DES:
487 case OP_PCL_IPSEC_3DES:
488 case OP_PCL_IPSEC_AES_CBC:
489 case OP_PCL_IPSEC_NULL:
490 __rta_out32(program, pdb->cbc.rsvd[0]);
491 __rta_out32(program, pdb->cbc.rsvd[1]);
492 break;
493
494 case OP_PCL_IPSEC_AES_CTR:
495 rta_copy_data(program, (uint8_t *)&pdb->ctr.ctr_nonce, 4);
496 __rta_out32(program, pdb->ctr.ctr_initial);
497 break;
498
499 case OP_PCL_IPSEC_AES_CCM8:
500 case OP_PCL_IPSEC_AES_CCM12:
501 case OP_PCL_IPSEC_AES_CCM16:
502 rta_copy_data(program, pdb->ccm.salt, sizeof(pdb->ccm.salt));
503 __rta_out32(program, pdb->ccm.ccm_opt);
504 break;
505
506 case OP_PCL_IPSEC_AES_GCM8:
507 case OP_PCL_IPSEC_AES_GCM12:
508 case OP_PCL_IPSEC_AES_GCM16:
509 case OP_PCL_IPSEC_AES_NULL_WITH_GMAC:
510 rta_copy_data(program, pdb->gcm.salt, sizeof(pdb->gcm.salt));
511 __rta_out32(program, pdb->gcm.rsvd);
512 break;
513 }
514
515 __rta_out32(program, pdb->seq_num_ext_hi);
516 __rta_out32(program, pdb->seq_num);
517
518 if (rta_sec_era < RTA_SEC_ERA_10)
519 mask = PDBOPTS_ESP_ARS_MASK;
520 else
521 mask = PDBOPTS_ESP_ARS_MASK_ERA10;
522 switch (pdb->options & mask) {
523 case PDBOPTS_ESP_ARS1024:
524 ars = 32;
525 break;
526 case PDBOPTS_ESP_ARS512:
527 ars = 16;
528 break;
529 case PDBOPTS_ESP_ARS256:
530 ars = 8;
531 break;
532 case PDBOPTS_ESP_ARS128:
533 ars = 4;
534 break;
535 case PDBOPTS_ESP_ARS64:
536 ars = 2;
537 break;
538 case PDBOPTS_ESP_ARS32:
539 ars = 1;
540 break;
541 case PDBOPTS_ESP_ARSNONE:
542 default:
543 ars = 0;
544 break;
545 }
546
547 for (i = 0; i < ars; i++)
548 __rta_out_be32(program, pdb->anti_replay[i]);
549
550 return start_pc;
551 }
552
553 /**
554 * enum ipsec_icv_size - Type selectors for icv size in IPsec protocol
555 * @IPSEC_ICV_MD5_SIZE: full-length MD5 ICV
556 * @IPSEC_ICV_MD5_TRUNC_SIZE: truncated MD5 ICV
557 */
558 enum ipsec_icv_size {
559 IPSEC_ICV_MD5_SIZE = 16,
560 IPSEC_ICV_MD5_TRUNC_SIZE = 12
561 };
562
563 /*
564 * IPSec ESP Datapath Protocol Override Register (DPOVRD)
565 * IPSEC_N_* defines are for IPsec new mode.
566 */
567
568 /**
569 * IPSEC_DPOVRD_USE - DPOVRD will override values specified in the PDB
570 */
571 #define IPSEC_DPOVRD_USE BIT(31)
572
573 /**
574 * IPSEC_DPOVRD_ECN_SHIFT - Explicit Congestion Notification
575 *
576 * If set, MSB of the 4 bits indicates that the 2 LSBs will replace the ECN bits
577 * in the IP header.
578 */
579 #define IPSEC_DPOVRD_ECN_SHIFT 24
580
581 /**
582 * IPSEC_DPOVRD_ECN_MASK - See IPSEC_DPOVRD_ECN_SHIFT
583 */
584 #define IPSEC_DPOVRD_ECN_MASK (0xf << IPSEC_ENCAP_DPOVRD_ECN_SHIFT)
585
586 /**
587 * IPSEC_DPOVRD_IP_HDR_LEN_SHIFT - The length (in bytes) of the portion of the
588 * IP header that is not encrypted
589 */
590 #define IPSEC_DPOVRD_IP_HDR_LEN_SHIFT 16
591
592 /**
593 * IPSEC_DPOVRD_IP_HDR_LEN_MASK - See IPSEC_DPOVRD_IP_HDR_LEN_SHIFT
594 */
595 #define IPSEC_DPOVRD_IP_HDR_LEN_MASK (0xff << IPSEC_DPOVRD_IP_HDR_LEN_SHIFT)
596
597 /**
598 * IPSEC_DPOVRD_NH_OFFSET_SHIFT - The location of the next header field within
599 * the IP header of the transport mode packet
600 *
601 * Encap:
602 * ESP_Trailer_NH <-- IP_Hdr[DPOVRD[NH_OFFSET]]
603 * IP_Hdr[DPOVRD[NH_OFFSET]] <-- DPOVRD[NH]
604 *Decap:
605 * IP_Hdr[DPOVRD[NH_OFFSET]] <-- ESP_Trailer_NH
606 */
607 #define IPSEC_DPOVRD_NH_OFFSET_SHIFT 8
608
609 /**
610 * IPSEC_DPOVRD_NH_OFFSET_MASK - See IPSEC_DPOVRD_NH_OFFSET_SHIFT
611 */
612 #define IPSEC_DPOVRD_NH_OFFSET_MASK (0xff << IPSEC_DPOVRD_NH_OFFSET_SHIFT)
613
614 /**
615 * IPSEC_DPOVRD_NH_MASK - See IPSEC_DPOVRD_NH_OFFSET_SHIFT
616 * Valid only for encapsulation.
617 */
618 #define IPSEC_DPOVRD_NH_MASK 0xff
619
620 /**
621 * IPSEC_N_ENCAP_DPOVRD_OIM_LEN_SHIFT - Outer IP header Material length (encap)
622 * Valid only if L2_COPY is not set.
623 */
624 #define IPSEC_N_ENCAP_DPOVRD_OIM_LEN_SHIFT 16
625
626 /**
627 * IPSEC_N_ENCAP_DPOVRD_OIM_LEN_MASK - See IPSEC_N_ENCAP_DPOVRD_OIM_LEN_SHIFT
628 */
629 #define IPSEC_N_ENCAP_DPOVRD_OIM_LEN_MASK \
630 (0xfff << IPSEC_N_ENCAP_DPOVRD_OIM_LEN_SHIFT)
631
632 /**
633 * IPSEC_N_ENCAP_DPOVRD_L2_LEN_SHIFT - L2 header length
634 * Valid only if L2_COPY is set.
635 */
636 #define IPSEC_N_ENCAP_DPOVRD_L2_LEN_SHIFT 16
637
638 /**
639 * IPSEC_N_ENCAP_DPOVRD_L2_LEN_MASK - See IPSEC_N_ENCAP_DPOVRD_L2_LEN_SHIFT
640 */
641 #define IPSEC_N_ENCAP_DPOVRD_L2_LEN_MASK \
642 (0xff << IPSEC_N_ENCAP_DPOVRD_L2_LEN_SHIFT)
643
644 /**
645 * IPSEC_N_ENCAP_DPOVRD_OIMIF - Outer IP header Material in Input Frame
646 */
647 #define IPSEC_N_ENCAP_DPOVRD_OIMIF BIT(15)
648
649 /**
650 * IPSEC_N_ENCAP_DPOVRD_L2_COPY - L2 header present in input frame
651 *
652 * Note: For Era <= 8, this bit is reserved (not used) by HW.
653 */
654 #define IPSEC_N_ENCAP_DPOVRD_L2_COPY BIT(14)
655
656 /**
657 * IPSEC_N_ENCAP_DPOVRD_AOIPHO_SHIFT - Actual Outer IP Header Offset (encap)
658 */
659 #define IPSEC_N_ENCAP_DPOVRD_AOIPHO_SHIFT 8
660
661 /**
662 * IPSEC_N_ENCAP_DPOVRD_AOIPHO_MASK - See IPSEC_N_ENCAP_DPOVRD_AOIPHO_SHIFT
663 */
664 #define IPSEC_N_ENCAP_DPOVRD_AOIPHO_MASK \
665 (0x3c << IPSEC_N_ENCAP_DPOVRD_AOIPHO_SHIFT)
666
667 /**
668 * IPSEC_N_ENCAP_DPOVRD_NH_MASK - Next Header
669 *
670 * Used in the Next Header field of the encapsulated payload.
671 */
672 #define IPSEC_N_ENCAP_DPOVRD_NH_MASK 0xff
673
674 /**
675 * IPSEC_N_DECAP_DPOVRD_AOIPHO_SHIFT - Actual Outer IP Header Offset (decap)
676 */
677 #define IPSEC_N_DECAP_DPOVRD_AOIPHO_SHIFT 12
678
679 /**
680 * IPSEC_N_DECAP_DPOVRD_AOIPHO_MASK - See IPSEC_N_DECAP_DPOVRD_AOIPHO_SHIFT
681 */
682 #define IPSEC_N_DECAP_DPOVRD_AOIPHO_MASK \
683 (0xff << IPSEC_N_DECAP_DPOVRD_AOIPHO_SHIFT)
684
685 /**
686 * IPSEC_N_DECAP_DPOVRD_OIM_LEN_MASK - Outer IP header Material length (decap)
687 */
688 #define IPSEC_N_DECAP_DPOVRD_OIM_LEN_MASK 0xfff
689
__gen_auth_key(struct program * program,struct alginfo * authdata)690 static inline void __gen_auth_key(struct program *program,
691 struct alginfo *authdata)
692 {
693 uint32_t dkp_protid;
694
695 switch (authdata->algtype & OP_PCL_IPSEC_AUTH_MASK) {
696 case OP_PCL_IPSEC_HMAC_MD5_96:
697 case OP_PCL_IPSEC_HMAC_MD5_128:
698 dkp_protid = OP_PCLID_DKP_MD5;
699 break;
700 case OP_PCL_IPSEC_HMAC_SHA1_96:
701 case OP_PCL_IPSEC_HMAC_SHA1_160:
702 dkp_protid = OP_PCLID_DKP_SHA1;
703 break;
704 case OP_PCL_IPSEC_HMAC_SHA2_256_128:
705 dkp_protid = OP_PCLID_DKP_SHA256;
706 break;
707 case OP_PCL_IPSEC_HMAC_SHA2_384_192:
708 dkp_protid = OP_PCLID_DKP_SHA384;
709 break;
710 case OP_PCL_IPSEC_HMAC_SHA2_512_256:
711 dkp_protid = OP_PCLID_DKP_SHA512;
712 break;
713 default:
714 KEY(program, KEY2, authdata->key_enc_flags, authdata->key,
715 authdata->keylen, INLINE_KEY(authdata));
716 return;
717 }
718
719 if (authdata->key_type == RTA_DATA_PTR)
720 DKP_PROTOCOL(program, dkp_protid, OP_PCL_DKP_SRC_PTR,
721 OP_PCL_DKP_DST_PTR, (uint16_t)authdata->keylen,
722 authdata->key, authdata->key_type);
723 else
724 DKP_PROTOCOL(program, dkp_protid, OP_PCL_DKP_SRC_IMM,
725 OP_PCL_DKP_DST_IMM, (uint16_t)authdata->keylen,
726 authdata->key, authdata->key_type);
727 }
728
729 /**
730 * cnstr_shdsc_ipsec_encap - IPSec ESP encapsulation protocol-level shared
731 * descriptor.
732 * @descbuf: pointer to buffer used for descriptor construction
733 * @ps: if 36/40bit addressing is desired, this parameter must be true
734 * @swap: if true, perform descriptor byte swapping on a 4-byte boundary
735 * @share: sharing type of shared descriptor
736 * @pdb: pointer to the PDB to be used with this descriptor
737 * This structure will be copied inline to the descriptor under
738 * construction. No error checking will be made. Refer to the
739 * block guide for a details of the encapsulation PDB.
740 * @cipherdata: pointer to block cipher transform definitions
741 * Valid algorithm values - one of OP_PCL_IPSEC_*
742 * @authdata: pointer to authentication transform definitions
743 * If an authentication key is required by the protocol:
744 * -For SEC Eras 1-5, an MDHA split key must be provided;
745 * Note that the size of the split key itself must be specified.
746 * -For SEC Eras 6+, a "normal" key must be provided; DKP (Derived
747 * Key Protocol) will be used to compute MDHA on the fly in HW.
748 * Valid algorithm values - one of OP_PCL_IPSEC_*
749 *
750 * Return: size of descriptor written in words or negative number on error
751 */
752 static inline int
cnstr_shdsc_ipsec_encap(uint32_t * descbuf,bool ps,bool swap,enum rta_share_type share,struct ipsec_encap_pdb * pdb,struct alginfo * cipherdata,struct alginfo * authdata)753 cnstr_shdsc_ipsec_encap(uint32_t *descbuf, bool ps, bool swap,
754 enum rta_share_type share,
755 struct ipsec_encap_pdb *pdb,
756 struct alginfo *cipherdata,
757 struct alginfo *authdata)
758 {
759 struct program prg;
760 struct program *p = &prg;
761
762 LABEL(keyjmp);
763 REFERENCE(pkeyjmp);
764 LABEL(hdr);
765 REFERENCE(phdr);
766
767 PROGRAM_CNTXT_INIT(p, descbuf, 0);
768 if (swap)
769 PROGRAM_SET_BSWAP(p);
770 if (ps)
771 PROGRAM_SET_36BIT_ADDR(p);
772 phdr = SHR_HDR(p, share, hdr, 0);
773 __rta_copy_ipsec_encap_pdb(p, pdb, cipherdata->algtype);
774 COPY_DATA(p, pdb->ip_hdr, pdb->ip_hdr_len);
775 SET_LABEL(p, hdr);
776 pkeyjmp = JUMP(p, keyjmp, LOCAL_JUMP, ALL_TRUE, BOTH|SHRD);
777 if (authdata->keylen)
778 __gen_auth_key(p, authdata);
779
780 if (cipherdata->keylen)
781 KEY(p, KEY1, cipherdata->key_enc_flags, cipherdata->key,
782 cipherdata->keylen, INLINE_KEY(cipherdata));
783 SET_LABEL(p, keyjmp);
784 PROTOCOL(p, OP_TYPE_ENCAP_PROTOCOL,
785 OP_PCLID_IPSEC,
786 (uint16_t)(cipherdata->algtype | authdata->algtype));
787 PATCH_JUMP(p, pkeyjmp, keyjmp);
788 PATCH_HDR(p, phdr, hdr);
789 return PROGRAM_FINALIZE(p);
790 }
791
792 /**
793 * cnstr_shdsc_ipsec_decap - IPSec ESP decapsulation protocol-level shared
794 * descriptor.
795 * @descbuf: pointer to buffer used for descriptor construction
796 * @ps: if 36/40bit addressing is desired, this parameter must be true
797 * @swap: if true, perform descriptor byte swapping on a 4-byte boundary
798 * @share: sharing type of shared descriptor
799 * @pdb: pointer to the PDB to be used with this descriptor
800 * This structure will be copied inline to the descriptor under
801 * construction. No error checking will be made. Refer to the
802 * block guide for details about the decapsulation PDB.
803 * @cipherdata: pointer to block cipher transform definitions.
804 * Valid algorithm values - one of OP_PCL_IPSEC_*
805 * @authdata: pointer to authentication transform definitions
806 * If an authentication key is required by the protocol:
807 * -For SEC Eras 1-5, an MDHA split key must be provided;
808 * Note that the size of the split key itself must be specified.
809 * -For SEC Eras 6+, a "normal" key must be provided; DKP (Derived
810 * Key Protocol) will be used to compute MDHA on the fly in HW.
811 * Valid algorithm values - one of OP_PCL_IPSEC_*
812 *
813 * Return: size of descriptor written in words or negative number on error
814 */
815 static inline int
cnstr_shdsc_ipsec_decap(uint32_t * descbuf,bool ps,bool swap,enum rta_share_type share,struct ipsec_decap_pdb * pdb,struct alginfo * cipherdata,struct alginfo * authdata)816 cnstr_shdsc_ipsec_decap(uint32_t *descbuf, bool ps, bool swap,
817 enum rta_share_type share,
818 struct ipsec_decap_pdb *pdb,
819 struct alginfo *cipherdata,
820 struct alginfo *authdata)
821 {
822 struct program prg;
823 struct program *p = &prg;
824
825 LABEL(keyjmp);
826 REFERENCE(pkeyjmp);
827 LABEL(hdr);
828 REFERENCE(phdr);
829
830 PROGRAM_CNTXT_INIT(p, descbuf, 0);
831 if (swap)
832 PROGRAM_SET_BSWAP(p);
833 if (ps)
834 PROGRAM_SET_36BIT_ADDR(p);
835 phdr = SHR_HDR(p, share, hdr, 0);
836 __rta_copy_ipsec_decap_pdb(p, pdb, cipherdata->algtype);
837 SET_LABEL(p, hdr);
838 pkeyjmp = JUMP(p, keyjmp, LOCAL_JUMP, ALL_TRUE, BOTH|SHRD);
839 if (authdata->keylen)
840 __gen_auth_key(p, authdata);
841
842 if (cipherdata->keylen)
843 KEY(p, KEY1, cipherdata->key_enc_flags, cipherdata->key,
844 cipherdata->keylen, INLINE_KEY(cipherdata));
845 SET_LABEL(p, keyjmp);
846 PROTOCOL(p, OP_TYPE_DECAP_PROTOCOL,
847 OP_PCLID_IPSEC,
848 (uint16_t)(cipherdata->algtype | authdata->algtype));
849 PATCH_JUMP(p, pkeyjmp, keyjmp);
850 PATCH_HDR(p, phdr, hdr);
851 return PROGRAM_FINALIZE(p);
852 }
853
854 /**
855 * cnstr_shdsc_ipsec_encap_des_aes_xcbc - IPSec DES-CBC/3DES-CBC and
856 * AES-XCBC-MAC-96 ESP encapsulation shared descriptor.
857 * @descbuf: pointer to buffer used for descriptor construction
858 * @share: sharing type of shared descriptor
859 * @pdb: pointer to the PDB to be used with this descriptor
860 * This structure will be copied inline to the descriptor under
861 * construction. No error checking will be made. Refer to the
862 * block guide for a details of the encapsulation PDB.
863 * @cipherdata: pointer to block cipher transform definitions
864 * Valid algorithm values - OP_PCL_IPSEC_DES, OP_PCL_IPSEC_3DES.
865 * @authdata: pointer to authentication transform definitions
866 * Valid algorithm value: OP_PCL_IPSEC_AES_XCBC_MAC_96.
867 *
868 * Supported only for platforms with 32-bit address pointers and SEC ERA 4 or
869 * higher. The tunnel/transport mode of the IPsec ESP is supported only if the
870 * Outer/Transport IP Header is present in the encapsulation output packet.
871 * The descriptor performs DES-CBC/3DES-CBC & HMAC-MD5-96 and then rereads
872 * the input packet to do the AES-XCBC-MAC-96 calculation and to overwrite
873 * the MD5 ICV.
874 * The descriptor uses all the benefits of the built-in protocol by computing
875 * the IPsec ESP with a hardware supported algorithms combination
876 * (DES-CBC/3DES-CBC & HMAC-MD5-96). The HMAC-MD5 authentication algorithm
877 * was chosen in order to speed up the computational time for this intermediate
878 * step.
879 * Warning: The user must allocate at least 32 bytes for the authentication key
880 * (in order to use it also with HMAC-MD5-96),even when using a shorter key
881 * for the AES-XCBC-MAC-96.
882 *
883 * Return: size of descriptor written in words or negative number on error
884 */
885 static inline int
cnstr_shdsc_ipsec_encap_des_aes_xcbc(uint32_t * descbuf,enum rta_share_type share,struct ipsec_encap_pdb * pdb,struct alginfo * cipherdata,struct alginfo * authdata)886 cnstr_shdsc_ipsec_encap_des_aes_xcbc(uint32_t *descbuf,
887 enum rta_share_type share,
888 struct ipsec_encap_pdb *pdb,
889 struct alginfo *cipherdata,
890 struct alginfo *authdata)
891 {
892 struct program prg;
893 struct program *p = &prg;
894
895 LABEL(hdr);
896 LABEL(shd_ptr);
897 LABEL(keyjump);
898 LABEL(outptr);
899 LABEL(swapped_seqin_fields);
900 LABEL(swapped_seqin_ptr);
901 REFERENCE(phdr);
902 REFERENCE(pkeyjump);
903 REFERENCE(move_outlen);
904 REFERENCE(move_seqout_ptr);
905 REFERENCE(swapped_seqin_ptr_jump);
906 REFERENCE(write_swapped_seqin_ptr);
907
908 PROGRAM_CNTXT_INIT(p, descbuf, 0);
909 phdr = SHR_HDR(p, share, hdr, 0);
910 __rta_copy_ipsec_encap_pdb(p, pdb, cipherdata->algtype);
911 COPY_DATA(p, pdb->ip_hdr, pdb->ip_hdr_len);
912 SET_LABEL(p, hdr);
913 pkeyjump = JUMP(p, keyjump, LOCAL_JUMP, ALL_TRUE, SHRD | SELF);
914 /*
915 * Hard-coded KEY arguments. The descriptor uses all the benefits of
916 * the built-in protocol by computing the IPsec ESP with a hardware
917 * supported algorithms combination (DES-CBC/3DES-CBC & HMAC-MD5-96).
918 * The HMAC-MD5 authentication algorithm was chosen with
919 * the keys options from below in order to speed up the computational
920 * time for this intermediate step.
921 * Warning: The user must allocate at least 32 bytes for
922 * the authentication key (in order to use it also with HMAC-MD5-96),
923 * even when using a shorter key for the AES-XCBC-MAC-96.
924 */
925 KEY(p, MDHA_SPLIT_KEY, 0, authdata->key, 32, INLINE_KEY(authdata));
926 SET_LABEL(p, keyjump);
927 LOAD(p, LDST_SRCDST_WORD_CLRW | CLRW_CLR_C1MODE | CLRW_CLR_C1DATAS |
928 CLRW_CLR_C1CTX | CLRW_CLR_C1KEY | CLRW_RESET_CLS1_CHA, CLRW, 0, 4,
929 IMMED);
930 KEY(p, KEY1, cipherdata->key_enc_flags, cipherdata->key,
931 cipherdata->keylen, INLINE_KEY(cipherdata));
932 PROTOCOL(p, OP_TYPE_ENCAP_PROTOCOL, OP_PCLID_IPSEC,
933 (uint16_t)(cipherdata->algtype | OP_PCL_IPSEC_HMAC_MD5_96));
934 /* Swap SEQINPTR to SEQOUTPTR. */
935 move_seqout_ptr = MOVE(p, DESCBUF, 0, MATH1, 0, 16, WAITCOMP | IMMED);
936 MATHB(p, MATH1, AND, ~(CMD_SEQ_IN_PTR ^ CMD_SEQ_OUT_PTR), MATH1,
937 8, IFB | IMMED2);
938 /*
939 * TODO: RTA currently doesn't support creating a LOAD command
940 * with another command as IMM.
941 * To be changed when proper support is added in RTA.
942 */
943 LOAD(p, 0xa00000e5, MATH3, 4, 4, IMMED);
944 MATHB(p, MATH3, SHLD, MATH3, MATH3, 8, 0);
945 write_swapped_seqin_ptr = MOVE(p, MATH1, 0, DESCBUF, 0, 20, WAITCOMP |
946 IMMED);
947 swapped_seqin_ptr_jump = JUMP(p, swapped_seqin_ptr, LOCAL_JUMP,
948 ALL_TRUE, 0);
949 LOAD(p, LDST_SRCDST_WORD_CLRW | CLRW_CLR_C1MODE | CLRW_CLR_C1DATAS |
950 CLRW_CLR_C1CTX | CLRW_CLR_C1KEY | CLRW_RESET_CLS1_CHA, CLRW, 0, 4,
951 0);
952 SEQOUTPTR(p, 0, 65535, RTO);
953 move_outlen = MOVE(p, DESCBUF, 0, MATH0, 4, 8, WAITCOMP | IMMED);
954 MATHB(p, MATH0, SUB,
955 (uint64_t)(pdb->ip_hdr_len + IPSEC_ICV_MD5_TRUNC_SIZE),
956 VSEQINSZ, 4, IMMED2);
957 MATHB(p, MATH0, SUB, IPSEC_ICV_MD5_TRUNC_SIZE, VSEQOUTSZ, 4, IMMED2);
958 KEY(p, KEY1, authdata->key_enc_flags, authdata->key, authdata->keylen,
959 0);
960 ALG_OPERATION(p, OP_ALG_ALGSEL_AES, OP_ALG_AAI_XCBC_MAC,
961 OP_ALG_AS_INITFINAL, ICV_CHECK_DISABLE, DIR_ENC);
962 SEQFIFOLOAD(p, SKIP, pdb->ip_hdr_len, 0);
963 SEQFIFOLOAD(p, MSG1, 0, VLF | FLUSH1 | LAST1);
964 SEQFIFOSTORE(p, SKIP, 0, 0, VLF);
965 SEQSTORE(p, CONTEXT1, 0, IPSEC_ICV_MD5_TRUNC_SIZE, 0);
966 /*
967 * TODO: RTA currently doesn't support adding labels in or after Job Descriptor.
968 * To be changed when proper support is added in RTA.
969 */
970 /* Label the Shared Descriptor Pointer */
971 SET_LABEL(p, shd_ptr);
972 shd_ptr += 1;
973 /* Label the Output Pointer */
974 SET_LABEL(p, outptr);
975 outptr += 3;
976 /* Label the first word after JD */
977 SET_LABEL(p, swapped_seqin_fields);
978 swapped_seqin_fields += 8;
979 /* Label the second word after JD */
980 SET_LABEL(p, swapped_seqin_ptr);
981 swapped_seqin_ptr += 9;
982
983 PATCH_HDR(p, phdr, hdr);
984 PATCH_JUMP(p, pkeyjump, keyjump);
985 PATCH_JUMP(p, swapped_seqin_ptr_jump, swapped_seqin_ptr);
986 PATCH_MOVE(p, move_outlen, outptr);
987 PATCH_MOVE(p, move_seqout_ptr, shd_ptr);
988 PATCH_MOVE(p, write_swapped_seqin_ptr, swapped_seqin_fields);
989 return PROGRAM_FINALIZE(p);
990 }
991
992 /**
993 * cnstr_shdsc_ipsec_decap_des_aes_xcbc - IPSec DES-CBC/3DES-CBC and
994 * AES-XCBC-MAC-96 ESP decapsulation shared descriptor.
995 * @descbuf: pointer to buffer used for descriptor construction
996 * @share: sharing type of shared descriptor
997 * @pdb: pointer to the PDB to be used with this descriptor
998 * This structure will be copied inline to the descriptor under
999 * construction. No error checking will be made. Refer to the
1000 * block guide for a details of the encapsulation PDB.
1001 * @cipherdata: pointer to block cipher transform definitions
1002 * Valid algorithm values - OP_PCL_IPSEC_DES, OP_PCL_IPSEC_3DES.
1003 * @authdata: pointer to authentication transform definitions
1004 * Valid algorithm value: OP_PCL_IPSEC_AES_XCBC_MAC_96.
1005 *
1006 * Supported only for platforms with 32-bit address pointers and SEC ERA 4 or
1007 * higher. The tunnel/transport mode of the IPsec ESP is supported only if the
1008 * Outer/Transport IP Header is present in the decapsulation input packet.
1009 * The descriptor computes the AES-XCBC-MAC-96 to check if the received ICV
1010 * is correct, rereads the input packet to compute the MD5 ICV, overwrites
1011 * the XCBC ICV, and then sends the modified input packet to the
1012 * DES-CBC/3DES-CBC & HMAC-MD5-96 IPsec.
1013 * The descriptor uses all the benefits of the built-in protocol by computing
1014 * the IPsec ESP with a hardware supported algorithms combination
1015 * (DES-CBC/3DES-CBC & HMAC-MD5-96). The HMAC-MD5 authentication algorithm
1016 * was chosen in order to speed up the computational time for this intermediate
1017 * step.
1018 * Warning: The user must allocate at least 32 bytes for the authentication key
1019 * (in order to use it also with HMAC-MD5-96),even when using a shorter key
1020 * for the AES-XCBC-MAC-96.
1021 *
1022 * Return: size of descriptor written in words or negative number on error
1023 */
1024 static inline int
cnstr_shdsc_ipsec_decap_des_aes_xcbc(uint32_t * descbuf,enum rta_share_type share,struct ipsec_decap_pdb * pdb,struct alginfo * cipherdata,struct alginfo * authdata)1025 cnstr_shdsc_ipsec_decap_des_aes_xcbc(uint32_t *descbuf,
1026 enum rta_share_type share,
1027 struct ipsec_decap_pdb *pdb,
1028 struct alginfo *cipherdata,
1029 struct alginfo *authdata)
1030 {
1031 struct program prg;
1032 struct program *p = &prg;
1033 uint32_t ip_hdr_len = (pdb->options & PDBHDRLEN_MASK) >>
1034 PDBHDRLEN_ESP_DECAP_SHIFT;
1035
1036 LABEL(hdr);
1037 LABEL(jump_cmd);
1038 LABEL(keyjump);
1039 LABEL(outlen);
1040 LABEL(seqin_ptr);
1041 LABEL(seqout_ptr);
1042 LABEL(swapped_seqout_fields);
1043 LABEL(swapped_seqout_ptr);
1044 REFERENCE(seqout_ptr_jump);
1045 REFERENCE(phdr);
1046 REFERENCE(pkeyjump);
1047 REFERENCE(move_jump);
1048 REFERENCE(move_jump_back);
1049 REFERENCE(move_seqin_ptr);
1050 REFERENCE(swapped_seqout_ptr_jump);
1051 REFERENCE(write_swapped_seqout_ptr);
1052
1053 PROGRAM_CNTXT_INIT(p, descbuf, 0);
1054 phdr = SHR_HDR(p, share, hdr, 0);
1055 __rta_copy_ipsec_decap_pdb(p, pdb, cipherdata->algtype);
1056 SET_LABEL(p, hdr);
1057 pkeyjump = JUMP(p, keyjump, LOCAL_JUMP, ALL_TRUE, SHRD | SELF);
1058 /*
1059 * Hard-coded KEY arguments. The descriptor uses all the benefits of
1060 * the built-in protocol by computing the IPsec ESP with a hardware
1061 * supported algorithms combination (DES-CBC/3DES-CBC & HMAC-MD5-96).
1062 * The HMAC-MD5 authentication algorithm was chosen with
1063 * the keys options from bellow in order to speed up the computational
1064 * time for this intermediate step.
1065 * Warning: The user must allocate at least 32 bytes for
1066 * the authentication key (in order to use it also with HMAC-MD5-96),
1067 * even when using a shorter key for the AES-XCBC-MAC-96.
1068 */
1069 KEY(p, MDHA_SPLIT_KEY, 0, authdata->key, 32, INLINE_KEY(authdata));
1070 SET_LABEL(p, keyjump);
1071 LOAD(p, LDST_SRCDST_WORD_CLRW | CLRW_CLR_C1MODE | CLRW_CLR_C1DATAS |
1072 CLRW_CLR_C1CTX | CLRW_CLR_C1KEY | CLRW_RESET_CLS1_CHA, CLRW, 0, 4,
1073 0);
1074 KEY(p, KEY1, authdata->key_enc_flags, authdata->key, authdata->keylen,
1075 INLINE_KEY(authdata));
1076 MATHB(p, SEQINSZ, SUB,
1077 (uint64_t)(ip_hdr_len + IPSEC_ICV_MD5_TRUNC_SIZE), MATH0, 4,
1078 IMMED2);
1079 MATHB(p, MATH0, SUB, ZERO, VSEQINSZ, 4, 0);
1080 ALG_OPERATION(p, OP_ALG_ALGSEL_MD5, OP_ALG_AAI_HMAC_PRECOMP,
1081 OP_ALG_AS_INITFINAL, ICV_CHECK_DISABLE, DIR_ENC);
1082 ALG_OPERATION(p, OP_ALG_ALGSEL_AES, OP_ALG_AAI_XCBC_MAC,
1083 OP_ALG_AS_INITFINAL, ICV_CHECK_ENABLE, DIR_DEC);
1084 SEQFIFOLOAD(p, SKIP, ip_hdr_len, 0);
1085 SEQFIFOLOAD(p, MSG1, 0, VLF | FLUSH1);
1086 SEQFIFOLOAD(p, ICV1, IPSEC_ICV_MD5_TRUNC_SIZE, FLUSH1 | LAST1);
1087 /* Swap SEQOUTPTR to SEQINPTR. */
1088 move_seqin_ptr = MOVE(p, DESCBUF, 0, MATH1, 0, 16, WAITCOMP | IMMED);
1089 MATHB(p, MATH1, OR, CMD_SEQ_IN_PTR ^ CMD_SEQ_OUT_PTR, MATH1, 8,
1090 IFB | IMMED2);
1091 /*
1092 * TODO: RTA currently doesn't support creating a LOAD command
1093 * with another command as IMM.
1094 * To be changed when proper support is added in RTA.
1095 */
1096 LOAD(p, 0xA00000e1, MATH3, 4, 4, IMMED);
1097 MATHB(p, MATH3, SHLD, MATH3, MATH3, 8, 0);
1098 write_swapped_seqout_ptr = MOVE(p, MATH1, 0, DESCBUF, 0, 20, WAITCOMP |
1099 IMMED);
1100 swapped_seqout_ptr_jump = JUMP(p, swapped_seqout_ptr, LOCAL_JUMP,
1101 ALL_TRUE, 0);
1102 /*
1103 * TODO: To be changed when proper support is added in RTA (can't load
1104 * a command that is also written by RTA).
1105 * Change when proper RTA support is added.
1106 */
1107 SET_LABEL(p, jump_cmd);
1108 WORD(p, 0xA00000f3);
1109 SEQINPTR(p, 0, 65535, RTO);
1110 MATHB(p, MATH0, SUB, ZERO, VSEQINSZ, 4, 0);
1111 MATHB(p, MATH0, ADD, ip_hdr_len, VSEQOUTSZ, 4, IMMED2);
1112 move_jump = MOVE(p, DESCBUF, 0, OFIFO, 0, 8, WAITCOMP | IMMED);
1113 move_jump_back = MOVE(p, OFIFO, 0, DESCBUF, 0, 8, IMMED);
1114 SEQFIFOLOAD(p, SKIP, ip_hdr_len, 0);
1115 SEQFIFOLOAD(p, MSG2, 0, VLF | LAST2);
1116 SEQFIFOSTORE(p, SKIP, 0, 0, VLF);
1117 SEQSTORE(p, CONTEXT2, 0, IPSEC_ICV_MD5_TRUNC_SIZE, 0);
1118 seqout_ptr_jump = JUMP(p, seqout_ptr, LOCAL_JUMP, ALL_TRUE, CALM);
1119
1120 LOAD(p, LDST_SRCDST_WORD_CLRW | CLRW_CLR_C1MODE | CLRW_CLR_C1DATAS |
1121 CLRW_CLR_C1CTX | CLRW_CLR_C1KEY | CLRW_CLR_C2MODE |
1122 CLRW_CLR_C2DATAS | CLRW_CLR_C2CTX | CLRW_RESET_CLS1_CHA, CLRW, 0,
1123 4, 0);
1124 SEQINPTR(p, 0, 65535, RTO);
1125 MATHB(p, MATH0, ADD,
1126 (uint64_t)(ip_hdr_len + IPSEC_ICV_MD5_TRUNC_SIZE), SEQINSZ, 4,
1127 IMMED2);
1128 KEY(p, KEY1, cipherdata->key_enc_flags, cipherdata->key,
1129 cipherdata->keylen, INLINE_KEY(cipherdata));
1130 PROTOCOL(p, OP_TYPE_DECAP_PROTOCOL, OP_PCLID_IPSEC,
1131 (uint16_t)(cipherdata->algtype | OP_PCL_IPSEC_HMAC_MD5_96));
1132 /*
1133 * TODO: RTA currently doesn't support adding labels in or after Job Descriptor.
1134 * To be changed when proper support is added in RTA.
1135 */
1136 /* Label the SEQ OUT PTR */
1137 SET_LABEL(p, seqout_ptr);
1138 seqout_ptr += 2;
1139 /* Label the Output Length */
1140 SET_LABEL(p, outlen);
1141 outlen += 4;
1142 /* Label the SEQ IN PTR */
1143 SET_LABEL(p, seqin_ptr);
1144 seqin_ptr += 5;
1145 /* Label the first word after JD */
1146 SET_LABEL(p, swapped_seqout_fields);
1147 swapped_seqout_fields += 8;
1148 /* Label the second word after JD */
1149 SET_LABEL(p, swapped_seqout_ptr);
1150 swapped_seqout_ptr += 9;
1151
1152 PATCH_HDR(p, phdr, hdr);
1153 PATCH_JUMP(p, pkeyjump, keyjump);
1154 PATCH_JUMP(p, seqout_ptr_jump, seqout_ptr);
1155 PATCH_JUMP(p, swapped_seqout_ptr_jump, swapped_seqout_ptr);
1156 PATCH_MOVE(p, move_jump, jump_cmd);
1157 PATCH_MOVE(p, move_jump_back, seqin_ptr);
1158 PATCH_MOVE(p, move_seqin_ptr, outlen);
1159 PATCH_MOVE(p, write_swapped_seqout_ptr, swapped_seqout_fields);
1160 return PROGRAM_FINALIZE(p);
1161 }
1162
1163 /**
1164 * IPSEC_NEW_ENC_BASE_DESC_LEN - IPsec new mode encap shared descriptor length
1165 *
1166 * Accounts only for the "base" commands and is intended to be used by upper
1167 * layers to determine whether Outer IP Header and/or keys can be inlined or
1168 * not. To be used as first parameter of rta_inline_query().
1169 */
1170 #define IPSEC_NEW_ENC_BASE_DESC_LEN (12 * CAAM_CMD_SZ + \
1171 sizeof(struct ipsec_encap_pdb))
1172
1173 /**
1174 * IPSEC_NEW_NULL_ENC_BASE_DESC_LEN - IPsec new mode encap shared descriptor
1175 * length for the case of
1176 * NULL encryption / authentication
1177 *
1178 * Accounts only for the "base" commands and is intended to be used by upper
1179 * layers to determine whether Outer IP Header and/or key can be inlined or
1180 * not. To be used as first parameter of rta_inline_query().
1181 */
1182 #define IPSEC_NEW_NULL_ENC_BASE_DESC_LEN (11 * CAAM_CMD_SZ + \
1183 sizeof(struct ipsec_encap_pdb))
1184
1185 /**
1186 * cnstr_shdsc_ipsec_new_encap - IPSec new mode ESP encapsulation
1187 * protocol-level shared descriptor.
1188 * @descbuf: pointer to buffer used for descriptor construction
1189 * @ps: if 36/40bit addressing is desired, this parameter must be true
1190 * @swap: must be true when core endianness doesn't match SEC endianness
1191 * @share: sharing type of shared descriptor
1192 * @pdb: pointer to the PDB to be used with this descriptor
1193 * This structure will be copied inline to the descriptor under
1194 * construction. No error checking will be made. Refer to the
1195 * block guide for details about the encapsulation PDB.
1196 * @opt_ip_hdr: pointer to Optional IP Header
1197 * -if OIHI = PDBOPTS_ESP_OIHI_PDB_INL, opt_ip_hdr points to the buffer to
1198 * be inlined in the PDB. Number of bytes (buffer size) copied is provided
1199 * in pdb->ip_hdr_len.
1200 * -if OIHI = PDBOPTS_ESP_OIHI_PDB_REF, opt_ip_hdr points to the address of
1201 * the Optional IP Header. The address will be inlined in the PDB verbatim.
1202 * -for other values of OIHI options field, opt_ip_hdr is not used.
1203 * @cipherdata: pointer to block cipher transform definitions
1204 * Valid algorithm values - one of OP_PCL_IPSEC_*
1205 * @authdata: pointer to authentication transform definitions.
1206 * If an authentication key is required by the protocol, a "normal"
1207 * key must be provided; DKP (Derived Key Protocol) will be used to
1208 * compute MDHA on the fly in HW.
1209 * Valid algorithm values - one of OP_PCL_IPSEC_*
1210 *
1211 * Note: L2 header copy functionality is implemented assuming that bits 14
1212 * (currently reserved) and 16-23 (part of Outer IP Header Material Length)
1213 * in DPOVRD register are not used (which is usually the case when L3 header
1214 * is provided in PDB).
1215 * When DPOVRD[14] is set, frame starts with an L2 header; in this case, the
1216 * L2 header length is found at DPOVRD[23:16]. SEC uses this length to copy
1217 * the header and then it deletes DPOVRD[23:16] (so there is no side effect
1218 * when later running IPsec protocol).
1219 *
1220 * Return: size of descriptor written in words or negative number on error
1221 */
1222 static inline int
cnstr_shdsc_ipsec_new_encap(uint32_t * descbuf,bool ps,bool swap,enum rta_share_type share,struct ipsec_encap_pdb * pdb,uint8_t * opt_ip_hdr,struct alginfo * cipherdata,struct alginfo * authdata)1223 cnstr_shdsc_ipsec_new_encap(uint32_t *descbuf, bool ps,
1224 bool swap,
1225 enum rta_share_type share,
1226 struct ipsec_encap_pdb *pdb,
1227 uint8_t *opt_ip_hdr,
1228 struct alginfo *cipherdata,
1229 struct alginfo *authdata)
1230 {
1231 struct program prg;
1232 struct program *p = &prg;
1233
1234 LABEL(keyjmp);
1235 REFERENCE(pkeyjmp);
1236 LABEL(hdr);
1237 REFERENCE(phdr);
1238 LABEL(l2copy);
1239 REFERENCE(pl2copy);
1240
1241 PROGRAM_CNTXT_INIT(p, descbuf, 0);
1242 if (swap)
1243 PROGRAM_SET_BSWAP(p);
1244 if (ps)
1245 PROGRAM_SET_36BIT_ADDR(p);
1246 phdr = SHR_HDR(p, share, hdr, 0);
1247
1248 __rta_copy_ipsec_encap_pdb(p, pdb, cipherdata->algtype);
1249
1250 switch (pdb->options & PDBOPTS_ESP_OIHI_MASK) {
1251 case PDBOPTS_ESP_OIHI_PDB_INL:
1252 COPY_DATA(p, opt_ip_hdr, pdb->ip_hdr_len);
1253 break;
1254 case PDBOPTS_ESP_OIHI_PDB_REF:
1255 if (ps)
1256 COPY_DATA(p, opt_ip_hdr, 8);
1257 else
1258 COPY_DATA(p, opt_ip_hdr, 4);
1259 break;
1260 default:
1261 break;
1262 }
1263 SET_LABEL(p, hdr);
1264
1265 MATHB(p, DPOVRD, AND, IPSEC_N_ENCAP_DPOVRD_L2_COPY, NONE, 4, IMMED2);
1266 pl2copy = JUMP(p, l2copy, LOCAL_JUMP, ALL_TRUE, MATH_Z);
1267 MATHI(p, DPOVRD, RSHIFT, IPSEC_N_ENCAP_DPOVRD_L2_LEN_SHIFT, VSEQOUTSZ,
1268 1, 0);
1269 MATHB(p, DPOVRD, AND, ~IPSEC_N_ENCAP_DPOVRD_L2_LEN_MASK, DPOVRD, 4,
1270 IMMED2);
1271 /* TODO: CLASS2 corresponds to AUX=2'b10; add more intuitive defines */
1272 SEQFIFOSTORE(p, METADATA, 0, 0, CLASS2 | VLF);
1273 SET_LABEL(p, l2copy);
1274
1275 pkeyjmp = JUMP(p, keyjmp, LOCAL_JUMP, ALL_TRUE, SHRD);
1276 if (authdata->keylen)
1277 __gen_auth_key(p, authdata);
1278 if (cipherdata->keylen)
1279 KEY(p, KEY1, cipherdata->key_enc_flags, cipherdata->key,
1280 cipherdata->keylen, INLINE_KEY(cipherdata));
1281 SET_LABEL(p, keyjmp);
1282 PROTOCOL(p, OP_TYPE_ENCAP_PROTOCOL,
1283 OP_PCLID_IPSEC_NEW,
1284 (uint16_t)(cipherdata->algtype | authdata->algtype));
1285 PATCH_JUMP(p, pl2copy, l2copy);
1286 PATCH_JUMP(p, pkeyjmp, keyjmp);
1287 PATCH_HDR(p, phdr, hdr);
1288 return PROGRAM_FINALIZE(p);
1289 }
1290
1291 /**
1292 * IPSEC_NEW_DEC_BASE_DESC_LEN - IPsec new mode decap shared descriptor length
1293 *
1294 * Accounts only for the "base" commands and is intended to be used by upper
1295 * layers to determine whether keys can be inlined or not. To be used as first
1296 * parameter of rta_inline_query().
1297 */
1298 #define IPSEC_NEW_DEC_BASE_DESC_LEN (5 * CAAM_CMD_SZ + \
1299 sizeof(struct ipsec_decap_pdb))
1300
1301 /**
1302 * IPSEC_NEW_NULL_DEC_BASE_DESC_LEN - IPsec new mode decap shared descriptor
1303 * length for the case of
1304 * NULL decryption / authentication
1305 *
1306 * Accounts only for the "base" commands and is intended to be used by upper
1307 * layers to determine whether key can be inlined or not. To be used as first
1308 * parameter of rta_inline_query().
1309 */
1310 #define IPSEC_NEW_NULL_DEC_BASE_DESC_LEN (4 * CAAM_CMD_SZ + \
1311 sizeof(struct ipsec_decap_pdb))
1312
1313 /**
1314 * cnstr_shdsc_ipsec_new_decap - IPSec new mode ESP decapsulation protocol-level
1315 * shared descriptor.
1316 * @descbuf: pointer to buffer used for descriptor construction
1317 * @ps: if 36/40bit addressing is desired, this parameter must be true
1318 * @swap: must be true when core endianness doesn't match SEC endianness
1319 * @share: sharing type of shared descriptor
1320 * @pdb: pointer to the PDB to be used with this descriptor
1321 * This structure will be copied inline to the descriptor under
1322 * construction. No error checking will be made. Refer to the
1323 * block guide for details about the decapsulation PDB.
1324 * @cipherdata: pointer to block cipher transform definitions
1325 * Valid algorithm values 0 one of OP_PCL_IPSEC_*
1326 * @authdata: pointer to authentication transform definitions.
1327 * If an authentication key is required by the protocol, a "normal"
1328 * key must be provided; DKP (Derived Key Protocol) will be used to
1329 * compute MDHA on the fly in HW.
1330 * Valid algorithm values - one of OP_PCL_IPSEC_*
1331 *
1332 * Return: size of descriptor written in words or negative number on error
1333 */
1334 static inline int
cnstr_shdsc_ipsec_new_decap(uint32_t * descbuf,bool ps,bool swap,enum rta_share_type share,struct ipsec_decap_pdb * pdb,struct alginfo * cipherdata,struct alginfo * authdata)1335 cnstr_shdsc_ipsec_new_decap(uint32_t *descbuf, bool ps,
1336 bool swap,
1337 enum rta_share_type share,
1338 struct ipsec_decap_pdb *pdb,
1339 struct alginfo *cipherdata,
1340 struct alginfo *authdata)
1341 {
1342 struct program prg;
1343 struct program *p = &prg;
1344
1345 LABEL(keyjmp);
1346 REFERENCE(pkeyjmp);
1347 LABEL(hdr);
1348 REFERENCE(phdr);
1349
1350 PROGRAM_CNTXT_INIT(p, descbuf, 0);
1351 if (swap)
1352 PROGRAM_SET_BSWAP(p);
1353 if (ps)
1354 PROGRAM_SET_36BIT_ADDR(p);
1355 phdr = SHR_HDR(p, share, hdr, 0);
1356 __rta_copy_ipsec_decap_pdb(p, pdb, cipherdata->algtype);
1357 SET_LABEL(p, hdr);
1358 pkeyjmp = JUMP(p, keyjmp, LOCAL_JUMP, ALL_TRUE, SHRD);
1359 if (authdata->keylen)
1360 __gen_auth_key(p, authdata);
1361 if (cipherdata->keylen)
1362 KEY(p, KEY1, cipherdata->key_enc_flags, cipherdata->key,
1363 cipherdata->keylen, INLINE_KEY(cipherdata));
1364 SET_LABEL(p, keyjmp);
1365 PROTOCOL(p, OP_TYPE_DECAP_PROTOCOL,
1366 OP_PCLID_IPSEC_NEW,
1367 (uint16_t)(cipherdata->algtype | authdata->algtype));
1368 PATCH_JUMP(p, pkeyjmp, keyjmp);
1369 PATCH_HDR(p, phdr, hdr);
1370 return PROGRAM_FINALIZE(p);
1371 }
1372
1373 /**
1374 * IPSEC_AUTH_VAR_BASE_DESC_LEN - IPsec encap/decap shared descriptor length
1375 * for the case of variable-length authentication
1376 * only data.
1377 * Note: Only for SoCs with SEC_ERA >= 3.
1378 *
1379 * Accounts only for the "base" commands and is intended to be used by upper
1380 * layers to determine whether keys can be inlined or not. To be used as first
1381 * parameter of rta_inline_query().
1382 */
1383 #define IPSEC_AUTH_VAR_BASE_DESC_LEN (27 * CAAM_CMD_SZ)
1384
1385 /**
1386 * IPSEC_AUTH_VAR_AES_DEC_BASE_DESC_LEN - IPsec AES decap shared descriptor
1387 * length for variable-length authentication only
1388 * data.
1389 * Note: Only for SoCs with SEC_ERA >= 3.
1390 *
1391 * Accounts only for the "base" commands and is intended to be used by upper
1392 * layers to determine whether key can be inlined or not. To be used as first
1393 * parameter of rta_inline_query().
1394 */
1395 #define IPSEC_AUTH_VAR_AES_DEC_BASE_DESC_LEN \
1396 (IPSEC_AUTH_VAR_BASE_DESC_LEN + CAAM_CMD_SZ)
1397
1398 /**
1399 * IPSEC_AUTH_BASE_DESC_LEN - IPsec encap/decap shared descriptor length
1400 *
1401 * Accounts only for the "base" commands and is intended to be used by upper
1402 * layers to determine whether key can be inlined or not. To be used as first
1403 * parameter of rta_inline_query().
1404 */
1405 #define IPSEC_AUTH_BASE_DESC_LEN (19 * CAAM_CMD_SZ)
1406
1407 /**
1408 * IPSEC_AUTH_AES_DEC_BASE_DESC_LEN - IPsec AES decap shared descriptor length
1409 *
1410 * Accounts only for the "base" commands and is intended to be used by upper
1411 * layers to determine whether key can be inlined or not. To be used as first
1412 * parameter of rta_inline_query().
1413 */
1414 #define IPSEC_AUTH_AES_DEC_BASE_DESC_LEN (IPSEC_AUTH_BASE_DESC_LEN + \
1415 CAAM_CMD_SZ)
1416
1417 /**
1418 * cnstr_shdsc_authenc - authenc-like descriptor
1419 * @descbuf: pointer to buffer used for descriptor construction
1420 * @ps: if 36/40bit addressing is desired, this parameter must be true
1421 * @swap: if true, perform descriptor byte swapping on a 4-byte boundary
1422 * @share: sharing type of shared descriptor
1423 * @cipherdata: pointer to block cipher transform definitions.
1424 * Valid algorithm values one of OP_ALG_ALGSEL_* {DES, 3DES, AES}
1425 * Valid modes for:
1426 * AES: OP_ALG_AAI_* {CBC, CTR}
1427 * DES, 3DES: OP_ALG_AAI_CBC
1428 * @authdata: pointer to authentication transform definitions.
1429 * Valid algorithm values - one of OP_ALG_ALGSEL_* {MD5, SHA1,
1430 * SHA224, SHA256, SHA384, SHA512}
1431 * Note: The key for authentication is supposed to be given as plain text.
1432 * Note: There's no support for keys longer than the block size of the
1433 * underlying hash function, according to the selected algorithm.
1434 *
1435 * @ivlen: length of the IV to be read from the input frame, before any data
1436 * to be processed
1437 *
1438 * @trunc_len: the length of the ICV to be written to the output frame. If 0,
1439 * then the corresponding length of the digest, according to the
1440 * selected algorithm shall be used.
1441 * @dir: Protocol direction, encapsulation or decapsulation (DIR_ENC/DIR_DEC)
1442 *
1443 * Note: Here's how the input frame needs to be formatted so that the processing
1444 * will be done correctly:
1445 * For encapsulation:
1446 * Input:
1447 * +----+----------------+-----------------------------------------------+
1448 * | IV | Auth-only head | Padded data to be auth & Enc | Auth-only tail |
1449 * +----+----------------+-----------------------------------------------+
1450 * Output:
1451 * +--------------------------------------+
1452 * | Authenticated & Encrypted data | ICV |
1453 * +--------------------------------+-----+
1454 *
1455 * For decapsulation:
1456 * Input:
1457 * +----+----------------+-----------------+----------------------+
1458 * | IV | Auth-only head | Auth & Enc data | Auth-only tail | ICV |
1459 * +----+----------------+-----------------+----------------------+
1460 * Output:
1461 * +----+---------------------------+
1462 * | Decrypted & authenticated data |
1463 * +----+---------------------------+
1464 *
1465 * Note: This descriptor can use per-packet commands, encoded as below in the
1466 * DPOVRD register:
1467 * 32 28 16 1
1468 * +------+------------------------------+
1469 * | 0x8 | auth_tail_len | auth_hdr_len |
1470 * +------+------------------------------+
1471 *
1472 * This mechanism is available only for SoCs having SEC ERA >= 3. In other
1473 * words, this will not work for P4080TO2
1474 *
1475 * Note: The descriptor does not add any kind of padding to the input data,
1476 * so the upper layer needs to ensure that the data is padded properly,
1477 * according to the selected cipher. Failure to do so will result in
1478 * the descriptor failing with a data-size error.
1479 *
1480 * Return: size of descriptor written in words or negative number on error
1481 */
1482 static inline int
cnstr_shdsc_authenc(uint32_t * descbuf,bool ps,bool swap,enum rta_share_type share,struct alginfo * cipherdata,struct alginfo * authdata,uint16_t ivlen,uint8_t trunc_len,uint8_t dir)1483 cnstr_shdsc_authenc(uint32_t *descbuf, bool ps, bool swap,
1484 enum rta_share_type share,
1485 struct alginfo *cipherdata,
1486 struct alginfo *authdata,
1487 uint16_t ivlen,
1488 uint8_t trunc_len, uint8_t dir)
1489 {
1490 struct program prg;
1491 struct program *p = &prg;
1492 const bool need_dk = (dir == DIR_DEC) &&
1493 (cipherdata->algtype == OP_ALG_ALGSEL_AES) &&
1494 (cipherdata->algmode == OP_ALG_AAI_CBC);
1495 int data_type;
1496
1497 LABEL(keyjmp);
1498 LABEL(skipkeys);
1499 LABEL(proc_icv);
1500 LABEL(no_auth_tail);
1501 REFERENCE(pkeyjmp);
1502 REFERENCE(pskipkeys);
1503 REFERENCE(p_proc_icv);
1504 REFERENCE(p_no_auth_tail);
1505
1506 PROGRAM_CNTXT_INIT(p, descbuf, 0);
1507
1508 if (swap)
1509 PROGRAM_SET_BSWAP(p);
1510 if (ps)
1511 PROGRAM_SET_36BIT_ADDR(p);
1512
1513 /*
1514 * Since we currently assume that key length is equal to hash digest
1515 * size, it's ok to truncate keylen value.
1516 */
1517 trunc_len = trunc_len && (trunc_len < authdata->keylen) ?
1518 trunc_len : (uint8_t)authdata->keylen;
1519
1520 SHR_HDR(p, share, 1, SC);
1521
1522 /* Collect the (auth_tail || auth_hdr) len from DPOVRD */
1523 MATHB(p, DPOVRD, ADD, 0x80000000, MATH2, 4, IMMED2);
1524
1525 /* Get auth_hdr len in MATH0 */
1526 MATHB(p, MATH2, AND, 0xFFFF, MATH0, 4, IMMED2);
1527
1528 /* Get auth_tail len in MATH2 */
1529 MATHB(p, MATH2, AND, 0xFFF0000, MATH2, 4, IMMED2);
1530 MATHI(p, MATH2, RSHIFT, 16, MATH2, 4, IMMED2);
1531
1532 pkeyjmp = JUMP(p, keyjmp, LOCAL_JUMP, ALL_TRUE, SHRD);
1533
1534 KEY(p, KEY2, authdata->key_enc_flags, authdata->key, authdata->keylen,
1535 INLINE_KEY(authdata));
1536
1537 /* Insert Key */
1538 KEY(p, KEY1, cipherdata->key_enc_flags, cipherdata->key,
1539 cipherdata->keylen, INLINE_KEY(cipherdata));
1540
1541 /* Do operation */
1542 ALG_OPERATION(p, authdata->algtype, authdata->algmode,
1543 OP_ALG_AS_INITFINAL,
1544 dir == DIR_ENC ? ICV_CHECK_DISABLE : ICV_CHECK_ENABLE,
1545 dir);
1546
1547 if (need_dk)
1548 ALG_OPERATION(p, OP_ALG_ALGSEL_AES, cipherdata->algmode,
1549 OP_ALG_AS_INITFINAL, ICV_CHECK_DISABLE, dir);
1550 pskipkeys = JUMP(p, skipkeys, LOCAL_JUMP, ALL_TRUE, 0);
1551
1552 SET_LABEL(p, keyjmp);
1553
1554 if (authdata->algmode == OP_ALG_AAI_HMAC)
1555 ALG_OPERATION(p, authdata->algtype, OP_ALG_AAI_HMAC_PRECOMP,
1556 OP_ALG_AS_INITFINAL,
1557 dir == DIR_ENC ? ICV_CHECK_DISABLE : ICV_CHECK_ENABLE,
1558 dir);
1559 else
1560 ALG_OPERATION(p, authdata->algtype, authdata->algmode,
1561 OP_ALG_AS_INITFINAL,
1562 dir == DIR_ENC ? ICV_CHECK_DISABLE : ICV_CHECK_ENABLE,
1563 dir);
1564
1565 if (need_dk) {
1566 ALG_OPERATION(p, OP_ALG_ALGSEL_AES, cipherdata->algmode |
1567 OP_ALG_AAI_DK, OP_ALG_AS_INITFINAL,
1568 ICV_CHECK_DISABLE, dir);
1569 SET_LABEL(p, skipkeys);
1570 } else {
1571 SET_LABEL(p, skipkeys);
1572 ALG_OPERATION(p, cipherdata->algtype, cipherdata->algmode,
1573 OP_ALG_AS_INITFINAL, ICV_CHECK_DISABLE, dir);
1574 }
1575
1576 /* Read IV */
1577 if (cipherdata->algmode == OP_ALG_AAI_CTR)
1578 SEQLOAD(p, CONTEXT1, 16, ivlen, 0);
1579 else
1580 SEQLOAD(p, CONTEXT1, 0, ivlen, 0);
1581
1582 /*
1583 * authenticate auth_hdr data
1584 */
1585 MATHB(p, MATH0, ADD, ZERO, VSEQINSZ, 4, 0);
1586 SEQFIFOLOAD(p, MSG2, 0, VLF);
1587
1588 /*
1589 * Prepare the length of the data to be both encrypted/decrypted
1590 * and authenticated/checked
1591 */
1592 MATHB(p, SEQINSZ, SUB, MATH2, VSEQINSZ, 4, 0);
1593 if (dir == DIR_DEC) {
1594 MATHB(p, VSEQINSZ, SUB, trunc_len, VSEQINSZ, 4, IMMED2);
1595 data_type = MSGINSNOOP;
1596 } else {
1597 data_type = MSGOUTSNOOP;
1598 }
1599
1600 MATHB(p, VSEQINSZ, ADD, ZERO, VSEQOUTSZ, 4, 0);
1601
1602 /* Prepare for writing the output frame */
1603 SEQFIFOSTORE(p, MSG, 0, 0, VLF);
1604
1605
1606 /* Check if there is no auth-tail */
1607 MATHB(p, MATH2, ADD, ZERO, MATH2, 4, 0);
1608 p_no_auth_tail = JUMP(p, no_auth_tail, LOCAL_JUMP, ALL_TRUE, MATH_Z);
1609
1610 /*
1611 * Read input plain/cipher text, encrypt/decrypt & auth & write
1612 * to output
1613 */
1614 SEQFIFOLOAD(p, data_type, 0, VLF | LAST1 | FLUSH1);
1615
1616 /* Authenticate auth tail */
1617 MATHB(p, MATH2, ADD, ZERO, VSEQINSZ, 4, 0);
1618 SEQFIFOLOAD(p, MSG2, 0, VLF | LAST2);
1619
1620 /* Jump to process icv */
1621 p_proc_icv = JUMP(p, proc_icv, LOCAL_JUMP, ALL_FALSE, MATH_Z);
1622
1623 SET_LABEL(p, no_auth_tail);
1624
1625 SEQFIFOLOAD(p, data_type, 0, VLF | LAST1 | LAST2 | FLUSH1);
1626
1627 SET_LABEL(p, proc_icv);
1628
1629 if (dir == DIR_ENC)
1630 /* Finally, write the ICV */
1631 SEQSTORE(p, CONTEXT2, 0, trunc_len, 0);
1632 else
1633 /* Read the ICV to check */
1634 SEQFIFOLOAD(p, ICV2, trunc_len, LAST2);
1635
1636 PATCH_JUMP(p, pkeyjmp, keyjmp);
1637 PATCH_JUMP(p, pskipkeys, skipkeys);
1638 PATCH_JUMP(p, p_no_auth_tail, no_auth_tail);
1639 PATCH_JUMP(p, p_proc_icv, proc_icv);
1640 return PROGRAM_FINALIZE(p);
1641 }
1642
1643 #endif /* __DESC_IPSEC_H__ */
1644