1 /* SPDX-License-Identifier: (BSD-3-Clause OR GPL-2.0)
2 *
3 * Copyright 2008-2016 Freescale Semiconductor Inc.
4 * Copyright 2016,2019-2022 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 * IP header must follow directly after ipsec_encap_pdb
338 */
339 struct ipsec_encap_pdb {
340 uint32_t options;
341 uint32_t seq_num_ext_hi;
342 uint32_t seq_num;
343 union {
344 struct ipsec_encap_cbc cbc;
345 struct ipsec_encap_ctr ctr;
346 struct ipsec_encap_ccm ccm;
347 struct ipsec_encap_gcm gcm;
348 };
349 uint32_t spi;
350 uint32_t ip_hdr_len;
351 };
352
353 static inline unsigned int
__rta_copy_ipsec_encap_pdb(struct program * program,struct ipsec_encap_pdb * pdb,uint32_t algtype)354 __rta_copy_ipsec_encap_pdb(struct program *program,
355 struct ipsec_encap_pdb *pdb,
356 uint32_t algtype)
357 {
358 unsigned int start_pc = program->current_pc;
359
360 __rta_out32(program, pdb->options);
361 __rta_out32(program, pdb->seq_num_ext_hi);
362 __rta_out32(program, pdb->seq_num);
363
364 switch (algtype & OP_PCL_IPSEC_CIPHER_MASK) {
365 case OP_PCL_IPSEC_DES_IV64:
366 case OP_PCL_IPSEC_DES:
367 case OP_PCL_IPSEC_3DES:
368 case OP_PCL_IPSEC_AES_CBC:
369 case OP_PCL_IPSEC_NULL:
370 rta_copy_data(program, pdb->cbc.iv, sizeof(pdb->cbc.iv));
371 break;
372
373 case OP_PCL_IPSEC_AES_CTR:
374 rta_copy_data(program, (uint8_t *)&pdb->ctr.ctr_nonce, 4);
375 __rta_out32(program, pdb->ctr.ctr_initial);
376 rta_copy_data(program, pdb->ctr.iv, sizeof(pdb->ctr.iv));
377 break;
378
379 case OP_PCL_IPSEC_AES_CCM8:
380 case OP_PCL_IPSEC_AES_CCM12:
381 case OP_PCL_IPSEC_AES_CCM16:
382 rta_copy_data(program, pdb->ccm.salt, sizeof(pdb->ccm.salt));
383 __rta_out32(program, pdb->ccm.ccm_opt);
384 __rta_out64(program, true, pdb->ccm.iv);
385 break;
386
387 case OP_PCL_IPSEC_AES_GCM8:
388 case OP_PCL_IPSEC_AES_GCM12:
389 case OP_PCL_IPSEC_AES_GCM16:
390 case OP_PCL_IPSEC_AES_NULL_WITH_GMAC:
391 rta_copy_data(program, pdb->gcm.salt, sizeof(pdb->gcm.salt));
392 __rta_out32(program, pdb->gcm.rsvd);
393 __rta_out64(program, true, pdb->gcm.iv);
394 break;
395 }
396
397 __rta_out32(program, pdb->spi);
398 __rta_out32(program, pdb->ip_hdr_len);
399
400 return start_pc;
401 }
402
403 /**
404 * struct ipsec_decap_cbc - PDB part for IPsec CBC decapsulation
405 * @rsvd: reserved, do not use
406 */
407 struct ipsec_decap_cbc {
408 uint32_t rsvd[2];
409 };
410
411 /**
412 * struct ipsec_decap_ctr - PDB part for IPsec CTR decapsulation
413 * @ctr_nonce: 4-byte nonce
414 * @ctr_initial: initial count constant
415 */
416 struct ipsec_decap_ctr {
417 uint32_t ctr_nonce;
418 uint32_t ctr_initial;
419 };
420
421 /**
422 * struct ipsec_decap_ccm - PDB part for IPsec CCM decapsulation
423 * @salt: 3-byte salt (lower 24 bits)
424 * @ccm_opt: CCM algorithm options - MSB-LSB description:
425 * b0_flags (8b) - CCM B0; use 0x5B for 8-byte ICV, 0x6B for 12-byte ICV,
426 * 0x7B for 16-byte ICV (cf. RFC4309, RFC3610)
427 * ctr_flags (8b) - counter flags; constant equal to 0x3
428 * ctr_initial (16b) - initial count constant
429 */
430 struct ipsec_decap_ccm {
431 uint8_t salt[4];
432 uint32_t ccm_opt;
433 };
434
435 /**
436 * struct ipsec_decap_gcm - PDB part for IPsec GCN decapsulation
437 * @salt: 4-byte salt
438 * @rsvd: reserved, do not use
439 */
440 struct ipsec_decap_gcm {
441 uint8_t salt[4];
442 uint32_t rsvd;
443 };
444
445 /**
446 * struct ipsec_decap_pdb - PDB for IPsec decapsulation
447 * @options: MSB-LSB description (both for legacy and new modes)
448 * hmo (header manipulation options) - 4b
449 * IP header length - 12b
450 * next header offset (legacy) / AOIPHO (actual outer IP header offset) - 8b
451 * option flags (depend on selected algorithm) - 8b
452 * @seq_num_ext_hi: (optional) IPsec Extended Sequence Number (ESN)
453 * @seq_num: IPsec sequence number
454 * @anti_replay: Anti-replay window; size depends on ARS (option flags);
455 * format must be Big Endian, irrespective of platform
456 */
457 struct ipsec_decap_pdb {
458 uint32_t options;
459 union {
460 struct ipsec_decap_cbc cbc;
461 struct ipsec_decap_ctr ctr;
462 struct ipsec_decap_ccm ccm;
463 struct ipsec_decap_gcm gcm;
464 };
465 uint32_t seq_num_ext_hi;
466 uint32_t seq_num;
467 uint32_t anti_replay[32];
468 };
469
470 static inline unsigned int
__rta_copy_ipsec_decap_pdb(struct program * program,struct ipsec_decap_pdb * pdb,uint32_t algtype)471 __rta_copy_ipsec_decap_pdb(struct program *program,
472 struct ipsec_decap_pdb *pdb,
473 uint32_t algtype)
474 {
475 unsigned int start_pc = program->current_pc;
476 unsigned int i, ars;
477 uint8_t mask;
478
479 __rta_out32(program, pdb->options);
480
481 switch (algtype & OP_PCL_IPSEC_CIPHER_MASK) {
482 case OP_PCL_IPSEC_DES_IV64:
483 case OP_PCL_IPSEC_DES:
484 case OP_PCL_IPSEC_3DES:
485 case OP_PCL_IPSEC_AES_CBC:
486 case OP_PCL_IPSEC_NULL:
487 __rta_out32(program, pdb->cbc.rsvd[0]);
488 __rta_out32(program, pdb->cbc.rsvd[1]);
489 break;
490
491 case OP_PCL_IPSEC_AES_CTR:
492 rta_copy_data(program, (uint8_t *)&pdb->ctr.ctr_nonce, 4);
493 __rta_out32(program, pdb->ctr.ctr_initial);
494 break;
495
496 case OP_PCL_IPSEC_AES_CCM8:
497 case OP_PCL_IPSEC_AES_CCM12:
498 case OP_PCL_IPSEC_AES_CCM16:
499 rta_copy_data(program, pdb->ccm.salt, sizeof(pdb->ccm.salt));
500 __rta_out32(program, pdb->ccm.ccm_opt);
501 break;
502
503 case OP_PCL_IPSEC_AES_GCM8:
504 case OP_PCL_IPSEC_AES_GCM12:
505 case OP_PCL_IPSEC_AES_GCM16:
506 case OP_PCL_IPSEC_AES_NULL_WITH_GMAC:
507 rta_copy_data(program, pdb->gcm.salt, sizeof(pdb->gcm.salt));
508 __rta_out32(program, pdb->gcm.rsvd);
509 break;
510 }
511
512 __rta_out32(program, pdb->seq_num_ext_hi);
513 __rta_out32(program, pdb->seq_num);
514
515 if (rta_sec_era < RTA_SEC_ERA_10)
516 mask = PDBOPTS_ESP_ARS_MASK;
517 else
518 mask = PDBOPTS_ESP_ARS_MASK_ERA10;
519 switch (pdb->options & mask) {
520 case PDBOPTS_ESP_ARS1024:
521 ars = 32;
522 break;
523 case PDBOPTS_ESP_ARS512:
524 ars = 16;
525 break;
526 case PDBOPTS_ESP_ARS256:
527 ars = 8;
528 break;
529 case PDBOPTS_ESP_ARS128:
530 ars = 4;
531 break;
532 case PDBOPTS_ESP_ARS64:
533 ars = 2;
534 break;
535 case PDBOPTS_ESP_ARS32:
536 ars = 1;
537 break;
538 case PDBOPTS_ESP_ARSNONE:
539 default:
540 ars = 0;
541 break;
542 }
543
544 for (i = 0; i < ars; i++)
545 __rta_out_be32(program, pdb->anti_replay[i]);
546
547 return start_pc;
548 }
549
550 /**
551 * enum ipsec_icv_size - Type selectors for icv size in IPsec protocol
552 * @IPSEC_ICV_MD5_SIZE: full-length MD5 ICV
553 * @IPSEC_ICV_MD5_TRUNC_SIZE: truncated MD5 ICV
554 */
555 enum ipsec_icv_size {
556 IPSEC_ICV_MD5_SIZE = 16,
557 IPSEC_ICV_MD5_TRUNC_SIZE = 12
558 };
559
560 /*
561 * IPSec ESP Datapath Protocol Override Register (DPOVRD)
562 * IPSEC_N_* defines are for IPsec new mode.
563 */
564
565 /**
566 * IPSEC_DPOVRD_USE - DPOVRD will override values specified in the PDB
567 */
568 #define IPSEC_DPOVRD_USE BIT(31)
569
570 /**
571 * IPSEC_DPOVRD_ECN_SHIFT - Explicit Congestion Notification
572 *
573 * If set, MSB of the 4 bits indicates that the 2 LSBs will replace the ECN bits
574 * in the IP header.
575 */
576 #define IPSEC_DPOVRD_ECN_SHIFT 24
577
578 /**
579 * IPSEC_DPOVRD_ECN_MASK - See IPSEC_DPOVRD_ECN_SHIFT
580 */
581 #define IPSEC_DPOVRD_ECN_MASK (0xf << IPSEC_ENCAP_DPOVRD_ECN_SHIFT)
582
583 /**
584 * IPSEC_DPOVRD_IP_HDR_LEN_SHIFT - The length (in bytes) of the portion of the
585 * IP header that is not encrypted
586 */
587 #define IPSEC_DPOVRD_IP_HDR_LEN_SHIFT 16
588
589 /**
590 * IPSEC_DPOVRD_IP_HDR_LEN_MASK - See IPSEC_DPOVRD_IP_HDR_LEN_SHIFT
591 */
592 #define IPSEC_DPOVRD_IP_HDR_LEN_MASK (0xff << IPSEC_DPOVRD_IP_HDR_LEN_SHIFT)
593
594 /**
595 * IPSEC_DPOVRD_NH_OFFSET_SHIFT - The location of the next header field within
596 * the IP header of the transport mode packet
597 *
598 * Encap:
599 * ESP_Trailer_NH <-- IP_Hdr[DPOVRD[NH_OFFSET]]
600 * IP_Hdr[DPOVRD[NH_OFFSET]] <-- DPOVRD[NH]
601 *Decap:
602 * IP_Hdr[DPOVRD[NH_OFFSET]] <-- ESP_Trailer_NH
603 */
604 #define IPSEC_DPOVRD_NH_OFFSET_SHIFT 8
605
606 /**
607 * IPSEC_DPOVRD_NH_OFFSET_MASK - See IPSEC_DPOVRD_NH_OFFSET_SHIFT
608 */
609 #define IPSEC_DPOVRD_NH_OFFSET_MASK (0xff << IPSEC_DPOVRD_NH_OFFSET_SHIFT)
610
611 /**
612 * IPSEC_DPOVRD_NH_MASK - See IPSEC_DPOVRD_NH_OFFSET_SHIFT
613 * Valid only for encapsulation.
614 */
615 #define IPSEC_DPOVRD_NH_MASK 0xff
616
617 /**
618 * IPSEC_N_ENCAP_DPOVRD_OIM_LEN_SHIFT - Outer IP header Material length (encap)
619 * Valid only if L2_COPY is not set.
620 */
621 #define IPSEC_N_ENCAP_DPOVRD_OIM_LEN_SHIFT 16
622
623 /**
624 * IPSEC_N_ENCAP_DPOVRD_OIM_LEN_MASK - See IPSEC_N_ENCAP_DPOVRD_OIM_LEN_SHIFT
625 */
626 #define IPSEC_N_ENCAP_DPOVRD_OIM_LEN_MASK \
627 (0xfff << IPSEC_N_ENCAP_DPOVRD_OIM_LEN_SHIFT)
628
629 /**
630 * IPSEC_N_ENCAP_DPOVRD_L2_LEN_SHIFT - L2 header length
631 * Valid only if L2_COPY is set.
632 */
633 #define IPSEC_N_ENCAP_DPOVRD_L2_LEN_SHIFT 16
634
635 /**
636 * IPSEC_N_ENCAP_DPOVRD_L2_LEN_MASK - See IPSEC_N_ENCAP_DPOVRD_L2_LEN_SHIFT
637 */
638 #define IPSEC_N_ENCAP_DPOVRD_L2_LEN_MASK \
639 (0xff << IPSEC_N_ENCAP_DPOVRD_L2_LEN_SHIFT)
640
641 /**
642 * IPSEC_N_ENCAP_DPOVRD_OIMIF - Outer IP header Material in Input Frame
643 */
644 #define IPSEC_N_ENCAP_DPOVRD_OIMIF BIT(15)
645
646 /**
647 * IPSEC_N_ENCAP_DPOVRD_L2_COPY - L2 header present in input frame
648 *
649 * Note: For Era <= 8, this bit is reserved (not used) by HW.
650 */
651 #define IPSEC_N_ENCAP_DPOVRD_L2_COPY BIT(14)
652
653 /**
654 * IPSEC_N_ENCAP_DPOVRD_AOIPHO_SHIFT - Actual Outer IP Header Offset (encap)
655 */
656 #define IPSEC_N_ENCAP_DPOVRD_AOIPHO_SHIFT 8
657
658 /**
659 * IPSEC_N_ENCAP_DPOVRD_AOIPHO_MASK - See IPSEC_N_ENCAP_DPOVRD_AOIPHO_SHIFT
660 */
661 #define IPSEC_N_ENCAP_DPOVRD_AOIPHO_MASK \
662 (0x3c << IPSEC_N_ENCAP_DPOVRD_AOIPHO_SHIFT)
663
664 /**
665 * IPSEC_N_ENCAP_DPOVRD_NH_MASK - Next Header
666 *
667 * Used in the Next Header field of the encapsulated payload.
668 */
669 #define IPSEC_N_ENCAP_DPOVRD_NH_MASK 0xff
670
671 /**
672 * IPSEC_N_DECAP_DPOVRD_AOIPHO_SHIFT - Actual Outer IP Header Offset (decap)
673 */
674 #define IPSEC_N_DECAP_DPOVRD_AOIPHO_SHIFT 12
675
676 /**
677 * IPSEC_N_DECAP_DPOVRD_AOIPHO_MASK - See IPSEC_N_DECAP_DPOVRD_AOIPHO_SHIFT
678 */
679 #define IPSEC_N_DECAP_DPOVRD_AOIPHO_MASK \
680 (0xff << IPSEC_N_DECAP_DPOVRD_AOIPHO_SHIFT)
681
682 /**
683 * IPSEC_N_DECAP_DPOVRD_OIM_LEN_MASK - Outer IP header Material length (decap)
684 */
685 #define IPSEC_N_DECAP_DPOVRD_OIM_LEN_MASK 0xfff
686
__gen_auth_key(struct program * program,struct alginfo * authdata)687 static inline void __gen_auth_key(struct program *program,
688 struct alginfo *authdata)
689 {
690 uint32_t dkp_protid;
691
692 switch (authdata->algtype & OP_PCL_IPSEC_AUTH_MASK) {
693 case OP_PCL_IPSEC_HMAC_MD5_96:
694 case OP_PCL_IPSEC_HMAC_MD5_128:
695 dkp_protid = OP_PCLID_DKP_MD5;
696 break;
697 case OP_PCL_IPSEC_HMAC_SHA1_96:
698 case OP_PCL_IPSEC_HMAC_SHA1_160:
699 dkp_protid = OP_PCLID_DKP_SHA1;
700 break;
701 case OP_PCL_IPSEC_HMAC_SHA2_256_128:
702 dkp_protid = OP_PCLID_DKP_SHA256;
703 break;
704 case OP_PCL_IPSEC_HMAC_SHA2_384_192:
705 dkp_protid = OP_PCLID_DKP_SHA384;
706 break;
707 case OP_PCL_IPSEC_HMAC_SHA2_512_256:
708 dkp_protid = OP_PCLID_DKP_SHA512;
709 break;
710 case OP_PCL_IPSEC_HMAC_SHA2_224_96:
711 case OP_PCL_IPSEC_HMAC_SHA2_224_112:
712 case OP_PCL_IPSEC_HMAC_SHA2_224_224:
713 dkp_protid = OP_PCLID_DKP_SHA224;
714 break;
715 default:
716 KEY(program, KEY2, authdata->key_enc_flags, authdata->key,
717 authdata->keylen, INLINE_KEY(authdata));
718 return;
719 }
720
721 if (authdata->key_type == RTA_DATA_PTR)
722 DKP_PROTOCOL(program, dkp_protid, OP_PCL_DKP_SRC_PTR,
723 OP_PCL_DKP_DST_PTR, (uint16_t)authdata->keylen,
724 authdata->key, authdata->key_type);
725 else
726 DKP_PROTOCOL(program, dkp_protid, OP_PCL_DKP_SRC_IMM,
727 OP_PCL_DKP_DST_IMM, (uint16_t)authdata->keylen,
728 authdata->key, authdata->key_type);
729 }
730
731 /**
732 * rta_inline_ipsec_query() - Provide indications on which data items can be inlined
733 * and which shall be referenced in IPsec shared descriptor.
734 * @sd_base_len: Shared descriptor base length - bytes consumed by the commands,
735 * excluding the data items to be inlined (or corresponding
736 * pointer if an item is not inlined). Each cnstr_* function that
737 * generates descriptors should have a define mentioning
738 * corresponding length.
739 * @jd_len: Maximum length of the job descriptor(s) that will be used
740 * together with the shared descriptor.
741 * @data_len: Array of lengths of the data items trying to be inlined
742 * @inl_mask: 32bit mask with bit x = 1 if data item x can be inlined, 0
743 * otherwise.
744 * @count: Number of data items (size of @data_len array); must be <= 32
745 * @auth_algtype: Authentication algorithm type.
746 * @auth_index: Index value of data_len for authentication key length.
747 * -1 if authentication key length is not present in data_len.
748 *
749 * Return: 0 if data can be inlined / referenced, negative value if not. If 0,
750 * check @inl_mask for details.
751 */
752 static inline int
rta_inline_ipsec_query(unsigned int sd_base_len,unsigned int jd_len,unsigned int * data_len,uint32_t * inl_mask,unsigned int count,uint32_t auth_algtype,int32_t auth_index)753 rta_inline_ipsec_query(unsigned int sd_base_len,
754 unsigned int jd_len,
755 unsigned int *data_len,
756 uint32_t *inl_mask,
757 unsigned int count,
758 uint32_t auth_algtype,
759 int32_t auth_index)
760 {
761 uint32_t dkp_protid;
762
763 switch (auth_algtype & OP_PCL_IPSEC_AUTH_MASK) {
764 case OP_PCL_IPSEC_HMAC_MD5_96:
765 case OP_PCL_IPSEC_HMAC_MD5_128:
766 dkp_protid = OP_PCLID_DKP_MD5;
767 break;
768 case OP_PCL_IPSEC_HMAC_SHA1_96:
769 case OP_PCL_IPSEC_HMAC_SHA1_160:
770 dkp_protid = OP_PCLID_DKP_SHA1;
771 break;
772 case OP_PCL_IPSEC_HMAC_SHA2_256_128:
773 dkp_protid = OP_PCLID_DKP_SHA256;
774 break;
775 case OP_PCL_IPSEC_HMAC_SHA2_384_192:
776 dkp_protid = OP_PCLID_DKP_SHA384;
777 break;
778 case OP_PCL_IPSEC_HMAC_SHA2_512_256:
779 dkp_protid = OP_PCLID_DKP_SHA512;
780 break;
781 case OP_PCL_IPSEC_HMAC_SHA2_224_96:
782 case OP_PCL_IPSEC_HMAC_SHA2_224_112:
783 case OP_PCL_IPSEC_HMAC_SHA2_224_224:
784 dkp_protid = OP_PCLID_DKP_SHA224;
785 break;
786 default:
787 return rta_inline_query(sd_base_len,
788 jd_len,
789 data_len,
790 inl_mask, count);
791 }
792
793 /* Updating the maximum supported inline key length */
794 if (auth_index != -1) {
795 if (split_key_len(dkp_protid) > data_len[auth_index])
796 data_len[auth_index] = split_key_len(dkp_protid);
797 }
798 return rta_inline_query(sd_base_len,
799 jd_len,
800 data_len,
801 inl_mask, count);
802 }
803
804 /**
805 * cnstr_shdsc_ipsec_encap - IPSec ESP encapsulation protocol-level shared
806 * descriptor.
807 * @descbuf: pointer to buffer used for descriptor construction
808 * @ps: if 36/40bit addressing is desired, this parameter must be true
809 * @swap: if true, perform descriptor byte swapping on a 4-byte boundary
810 * @share: sharing type of shared descriptor
811 * @pdb: pointer to the PDB to be used with this descriptor
812 * This structure will be copied inline to the descriptor under
813 * construction. No error checking will be made. Refer to the
814 * block guide for a details of the encapsulation PDB.
815 * @cipherdata: pointer to block cipher transform definitions
816 * Valid algorithm values - one of OP_PCL_IPSEC_*
817 * @authdata: pointer to authentication transform definitions
818 * If an authentication key is required by the protocol:
819 * -For SEC Eras 1-5, an MDHA split key must be provided;
820 * Note that the size of the split key itself must be specified.
821 * -For SEC Eras 6+, a "normal" key must be provided; DKP (Derived
822 * Key Protocol) will be used to compute MDHA on the fly in HW.
823 * Valid algorithm values - one of OP_PCL_IPSEC_*
824 *
825 * Return: size of descriptor written in words or negative number on error
826 */
827 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)828 cnstr_shdsc_ipsec_encap(uint32_t *descbuf, bool ps, bool swap,
829 enum rta_share_type share,
830 struct ipsec_encap_pdb *pdb,
831 struct alginfo *cipherdata,
832 struct alginfo *authdata)
833 {
834 struct program prg;
835 struct program *p = &prg;
836
837 LABEL(keyjmp);
838 REFERENCE(pkeyjmp);
839 LABEL(hdr);
840 REFERENCE(phdr);
841
842 PROGRAM_CNTXT_INIT(p, descbuf, 0);
843 if (swap)
844 PROGRAM_SET_BSWAP(p);
845 if (ps)
846 PROGRAM_SET_36BIT_ADDR(p);
847 phdr = SHR_HDR(p, share, hdr, 0);
848 __rta_copy_ipsec_encap_pdb(p, pdb, cipherdata->algtype);
849
850 /* IP header if any follows the encap_pdb */
851 if (pdb->ip_hdr_len > 0) {
852 void *ip_hdr = pdb + 1;
853 COPY_DATA(p, ip_hdr, pdb->ip_hdr_len);
854 }
855 SET_LABEL(p, hdr);
856 pkeyjmp = JUMP(p, keyjmp, LOCAL_JUMP, ALL_TRUE, BOTH|SHRD);
857 if (authdata->keylen)
858 __gen_auth_key(p, authdata);
859
860 if (cipherdata->keylen)
861 KEY(p, KEY1, cipherdata->key_enc_flags, cipherdata->key,
862 cipherdata->keylen, INLINE_KEY(cipherdata));
863 SET_LABEL(p, keyjmp);
864 PROTOCOL(p, OP_TYPE_ENCAP_PROTOCOL,
865 OP_PCLID_IPSEC,
866 (uint16_t)(cipherdata->algtype | authdata->algtype));
867 PATCH_JUMP(p, pkeyjmp, keyjmp);
868 PATCH_HDR(p, phdr, hdr);
869 return PROGRAM_FINALIZE(p);
870 }
871
872 /**
873 * cnstr_shdsc_ipsec_decap - IPSec ESP decapsulation protocol-level shared
874 * descriptor.
875 * @descbuf: pointer to buffer used for descriptor construction
876 * @ps: if 36/40bit addressing is desired, this parameter must be true
877 * @swap: if true, perform descriptor byte swapping on a 4-byte boundary
878 * @share: sharing type of shared descriptor
879 * @pdb: pointer to the PDB to be used with this descriptor
880 * This structure will be copied inline to the descriptor under
881 * construction. No error checking will be made. Refer to the
882 * block guide for details about the decapsulation PDB.
883 * @cipherdata: pointer to block cipher transform definitions.
884 * Valid algorithm values - one of OP_PCL_IPSEC_*
885 * @authdata: pointer to authentication transform definitions
886 * If an authentication key is required by the protocol:
887 * -For SEC Eras 1-5, an MDHA split key must be provided;
888 * Note that the size of the split key itself must be specified.
889 * -For SEC Eras 6+, a "normal" key must be provided; DKP (Derived
890 * Key Protocol) will be used to compute MDHA on the fly in HW.
891 * Valid algorithm values - one of OP_PCL_IPSEC_*
892 *
893 * Return: size of descriptor written in words or negative number on error
894 */
895 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)896 cnstr_shdsc_ipsec_decap(uint32_t *descbuf, bool ps, bool swap,
897 enum rta_share_type share,
898 struct ipsec_decap_pdb *pdb,
899 struct alginfo *cipherdata,
900 struct alginfo *authdata)
901 {
902 struct program prg;
903 struct program *p = &prg;
904
905 LABEL(keyjmp);
906 REFERENCE(pkeyjmp);
907 LABEL(hdr);
908 REFERENCE(phdr);
909
910 PROGRAM_CNTXT_INIT(p, descbuf, 0);
911 if (swap)
912 PROGRAM_SET_BSWAP(p);
913 if (ps)
914 PROGRAM_SET_36BIT_ADDR(p);
915 phdr = SHR_HDR(p, share, hdr, 0);
916 __rta_copy_ipsec_decap_pdb(p, pdb, cipherdata->algtype);
917 SET_LABEL(p, hdr);
918 pkeyjmp = JUMP(p, keyjmp, LOCAL_JUMP, ALL_TRUE, BOTH|SHRD);
919 if (authdata->keylen)
920 __gen_auth_key(p, authdata);
921
922 if (cipherdata->keylen)
923 KEY(p, KEY1, cipherdata->key_enc_flags, cipherdata->key,
924 cipherdata->keylen, INLINE_KEY(cipherdata));
925 SET_LABEL(p, keyjmp);
926 PROTOCOL(p, OP_TYPE_DECAP_PROTOCOL,
927 OP_PCLID_IPSEC,
928 (uint16_t)(cipherdata->algtype | authdata->algtype));
929 PATCH_JUMP(p, pkeyjmp, keyjmp);
930 PATCH_HDR(p, phdr, hdr);
931 return PROGRAM_FINALIZE(p);
932 }
933
934 /**
935 * cnstr_shdsc_ipsec_encap_des_aes_xcbc - IPSec DES-CBC/3DES-CBC and
936 * AES-XCBC-MAC-96 ESP encapsulation shared descriptor.
937 * @descbuf: pointer to buffer used for descriptor construction
938 * @share: sharing type of shared descriptor
939 * @pdb: pointer to the PDB to be used with this descriptor
940 * This structure will be copied inline to the descriptor under
941 * construction. No error checking will be made. Refer to the
942 * block guide for a details of the encapsulation PDB.
943 * @cipherdata: pointer to block cipher transform definitions
944 * Valid algorithm values - OP_PCL_IPSEC_DES, OP_PCL_IPSEC_3DES.
945 * @authdata: pointer to authentication transform definitions
946 * Valid algorithm value: OP_PCL_IPSEC_AES_XCBC_MAC_96.
947 *
948 * Supported only for platforms with 32-bit address pointers and SEC ERA 4 or
949 * higher. The tunnel/transport mode of the IPsec ESP is supported only if the
950 * Outer/Transport IP Header is present in the encapsulation output packet.
951 * The descriptor performs DES-CBC/3DES-CBC & HMAC-MD5-96 and then rereads
952 * the input packet to do the AES-XCBC-MAC-96 calculation and to overwrite
953 * the MD5 ICV.
954 * The descriptor uses all the benefits of the built-in protocol by computing
955 * the IPsec ESP with a hardware supported algorithms combination
956 * (DES-CBC/3DES-CBC & HMAC-MD5-96). The HMAC-MD5 authentication algorithm
957 * was chosen in order to speed up the computational time for this intermediate
958 * step.
959 * Warning: The user must allocate at least 32 bytes for the authentication key
960 * (in order to use it also with HMAC-MD5-96),even when using a shorter key
961 * for the AES-XCBC-MAC-96.
962 *
963 * Return: size of descriptor written in words or negative number on error
964 */
965 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)966 cnstr_shdsc_ipsec_encap_des_aes_xcbc(uint32_t *descbuf,
967 enum rta_share_type share,
968 struct ipsec_encap_pdb *pdb,
969 struct alginfo *cipherdata,
970 struct alginfo *authdata)
971 {
972 struct program prg;
973 struct program *p = &prg;
974
975 LABEL(hdr);
976 LABEL(shd_ptr);
977 LABEL(keyjump);
978 LABEL(outptr);
979 LABEL(swapped_seqin_fields);
980 LABEL(swapped_seqin_ptr);
981 REFERENCE(phdr);
982 REFERENCE(pkeyjump);
983 REFERENCE(move_outlen);
984 REFERENCE(move_seqout_ptr);
985 REFERENCE(swapped_seqin_ptr_jump);
986 REFERENCE(write_swapped_seqin_ptr);
987
988 PROGRAM_CNTXT_INIT(p, descbuf, 0);
989 phdr = SHR_HDR(p, share, hdr, 0);
990 __rta_copy_ipsec_encap_pdb(p, pdb, cipherdata->algtype);
991
992 /* IP header if any follows the encap_pdb */
993 if (pdb->ip_hdr_len > 0) {
994 void *ip_hdr = pdb + 1;
995 COPY_DATA(p, ip_hdr, pdb->ip_hdr_len);
996 }
997
998 SET_LABEL(p, hdr);
999 pkeyjump = JUMP(p, keyjump, LOCAL_JUMP, ALL_TRUE, SHRD | SELF);
1000 /*
1001 * Hard-coded KEY arguments. The descriptor uses all the benefits of
1002 * the built-in protocol by computing the IPsec ESP with a hardware
1003 * supported algorithms combination (DES-CBC/3DES-CBC & HMAC-MD5-96).
1004 * The HMAC-MD5 authentication algorithm was chosen with
1005 * the keys options from below in order to speed up the computational
1006 * time for this intermediate step.
1007 * Warning: The user must allocate at least 32 bytes for
1008 * the authentication key (in order to use it also with HMAC-MD5-96),
1009 * even when using a shorter key for the AES-XCBC-MAC-96.
1010 */
1011 KEY(p, MDHA_SPLIT_KEY, 0, authdata->key, 32, INLINE_KEY(authdata));
1012 SET_LABEL(p, keyjump);
1013 LOAD(p, LDST_SRCDST_WORD_CLRW | CLRW_CLR_C1MODE | CLRW_CLR_C1DATAS |
1014 CLRW_CLR_C1CTX | CLRW_CLR_C1KEY | CLRW_RESET_CLS1_CHA, CLRW, 0, 4,
1015 IMMED);
1016 KEY(p, KEY1, cipherdata->key_enc_flags, cipherdata->key,
1017 cipherdata->keylen, INLINE_KEY(cipherdata));
1018 PROTOCOL(p, OP_TYPE_ENCAP_PROTOCOL, OP_PCLID_IPSEC,
1019 (uint16_t)(cipherdata->algtype | OP_PCL_IPSEC_HMAC_MD5_96));
1020 /* Swap SEQINPTR to SEQOUTPTR. */
1021 move_seqout_ptr = MOVE(p, DESCBUF, 0, MATH1, 0, 16, WAITCOMP | IMMED);
1022 MATHB(p, MATH1, AND, ~(CMD_SEQ_IN_PTR ^ CMD_SEQ_OUT_PTR), MATH1,
1023 8, IFB | IMMED2);
1024 /*
1025 * TODO: RTA currently doesn't support creating a LOAD command
1026 * with another command as IMM.
1027 * To be changed when proper support is added in RTA.
1028 */
1029 LOAD(p, 0xa00000e5, MATH3, 4, 4, IMMED);
1030 MATHB(p, MATH3, SHLD, MATH3, MATH3, 8, 0);
1031 write_swapped_seqin_ptr = MOVE(p, MATH1, 0, DESCBUF, 0, 20, WAITCOMP |
1032 IMMED);
1033 swapped_seqin_ptr_jump = JUMP(p, swapped_seqin_ptr, LOCAL_JUMP,
1034 ALL_TRUE, 0);
1035 LOAD(p, LDST_SRCDST_WORD_CLRW | CLRW_CLR_C1MODE | CLRW_CLR_C1DATAS |
1036 CLRW_CLR_C1CTX | CLRW_CLR_C1KEY | CLRW_RESET_CLS1_CHA, CLRW, 0, 4,
1037 0);
1038 SEQOUTPTR(p, 0, 65535, RTO);
1039 move_outlen = MOVE(p, DESCBUF, 0, MATH0, 4, 8, WAITCOMP | IMMED);
1040 MATHB(p, MATH0, SUB,
1041 (uint64_t)(pdb->ip_hdr_len + IPSEC_ICV_MD5_TRUNC_SIZE),
1042 VSEQINSZ, 4, IMMED2);
1043 MATHB(p, MATH0, SUB, IPSEC_ICV_MD5_TRUNC_SIZE, VSEQOUTSZ, 4, IMMED2);
1044 KEY(p, KEY1, authdata->key_enc_flags, authdata->key, authdata->keylen,
1045 0);
1046 ALG_OPERATION(p, OP_ALG_ALGSEL_AES, OP_ALG_AAI_XCBC_MAC,
1047 OP_ALG_AS_INITFINAL, ICV_CHECK_DISABLE, DIR_ENC);
1048 SEQFIFOLOAD(p, SKIP, pdb->ip_hdr_len, 0);
1049 SEQFIFOLOAD(p, MSG1, 0, VLF | FLUSH1 | LAST1);
1050 SEQFIFOSTORE(p, SKIP, 0, 0, VLF);
1051 SEQSTORE(p, CONTEXT1, 0, IPSEC_ICV_MD5_TRUNC_SIZE, 0);
1052 /*
1053 * TODO: RTA currently doesn't support adding labels in or after Job Descriptor.
1054 * To be changed when proper support is added in RTA.
1055 */
1056 /* Label the Shared Descriptor Pointer */
1057 SET_LABEL(p, shd_ptr);
1058 shd_ptr += 1;
1059 /* Label the Output Pointer */
1060 SET_LABEL(p, outptr);
1061 outptr += 3;
1062 /* Label the first word after JD */
1063 SET_LABEL(p, swapped_seqin_fields);
1064 swapped_seqin_fields += 8;
1065 /* Label the second word after JD */
1066 SET_LABEL(p, swapped_seqin_ptr);
1067 swapped_seqin_ptr += 9;
1068
1069 PATCH_HDR(p, phdr, hdr);
1070 PATCH_JUMP(p, pkeyjump, keyjump);
1071 PATCH_JUMP(p, swapped_seqin_ptr_jump, swapped_seqin_ptr);
1072 PATCH_MOVE(p, move_outlen, outptr);
1073 PATCH_MOVE(p, move_seqout_ptr, shd_ptr);
1074 PATCH_MOVE(p, write_swapped_seqin_ptr, swapped_seqin_fields);
1075 return PROGRAM_FINALIZE(p);
1076 }
1077
1078 /**
1079 * cnstr_shdsc_ipsec_decap_des_aes_xcbc - IPSec DES-CBC/3DES-CBC and
1080 * AES-XCBC-MAC-96 ESP decapsulation shared descriptor.
1081 * @descbuf: pointer to buffer used for descriptor construction
1082 * @share: sharing type of shared descriptor
1083 * @pdb: pointer to the PDB to be used with this descriptor
1084 * This structure will be copied inline to the descriptor under
1085 * construction. No error checking will be made. Refer to the
1086 * block guide for a details of the encapsulation PDB.
1087 * @cipherdata: pointer to block cipher transform definitions
1088 * Valid algorithm values - OP_PCL_IPSEC_DES, OP_PCL_IPSEC_3DES.
1089 * @authdata: pointer to authentication transform definitions
1090 * Valid algorithm value: OP_PCL_IPSEC_AES_XCBC_MAC_96.
1091 *
1092 * Supported only for platforms with 32-bit address pointers and SEC ERA 4 or
1093 * higher. The tunnel/transport mode of the IPsec ESP is supported only if the
1094 * Outer/Transport IP Header is present in the decapsulation input packet.
1095 * The descriptor computes the AES-XCBC-MAC-96 to check if the received ICV
1096 * is correct, rereads the input packet to compute the MD5 ICV, overwrites
1097 * the XCBC ICV, and then sends the modified input packet to the
1098 * DES-CBC/3DES-CBC & HMAC-MD5-96 IPsec.
1099 * The descriptor uses all the benefits of the built-in protocol by computing
1100 * the IPsec ESP with a hardware supported algorithms combination
1101 * (DES-CBC/3DES-CBC & HMAC-MD5-96). The HMAC-MD5 authentication algorithm
1102 * was chosen in order to speed up the computational time for this intermediate
1103 * step.
1104 * Warning: The user must allocate at least 32 bytes for the authentication key
1105 * (in order to use it also with HMAC-MD5-96),even when using a shorter key
1106 * for the AES-XCBC-MAC-96.
1107 *
1108 * Return: size of descriptor written in words or negative number on error
1109 */
1110 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)1111 cnstr_shdsc_ipsec_decap_des_aes_xcbc(uint32_t *descbuf,
1112 enum rta_share_type share,
1113 struct ipsec_decap_pdb *pdb,
1114 struct alginfo *cipherdata,
1115 struct alginfo *authdata)
1116 {
1117 struct program prg;
1118 struct program *p = &prg;
1119 uint32_t ip_hdr_len = (pdb->options & PDBHDRLEN_MASK) >>
1120 PDBHDRLEN_ESP_DECAP_SHIFT;
1121
1122 LABEL(hdr);
1123 LABEL(jump_cmd);
1124 LABEL(keyjump);
1125 LABEL(outlen);
1126 LABEL(seqin_ptr);
1127 LABEL(seqout_ptr);
1128 LABEL(swapped_seqout_fields);
1129 LABEL(swapped_seqout_ptr);
1130 REFERENCE(seqout_ptr_jump);
1131 REFERENCE(phdr);
1132 REFERENCE(pkeyjump);
1133 REFERENCE(move_jump);
1134 REFERENCE(move_jump_back);
1135 REFERENCE(move_seqin_ptr);
1136 REFERENCE(swapped_seqout_ptr_jump);
1137 REFERENCE(write_swapped_seqout_ptr);
1138
1139 PROGRAM_CNTXT_INIT(p, descbuf, 0);
1140 phdr = SHR_HDR(p, share, hdr, 0);
1141 __rta_copy_ipsec_decap_pdb(p, pdb, cipherdata->algtype);
1142 SET_LABEL(p, hdr);
1143 pkeyjump = JUMP(p, keyjump, LOCAL_JUMP, ALL_TRUE, SHRD | SELF);
1144 /*
1145 * Hard-coded KEY arguments. The descriptor uses all the benefits of
1146 * the built-in protocol by computing the IPsec ESP with a hardware
1147 * supported algorithms combination (DES-CBC/3DES-CBC & HMAC-MD5-96).
1148 * The HMAC-MD5 authentication algorithm was chosen with
1149 * the keys options from bellow in order to speed up the computational
1150 * time for this intermediate step.
1151 * Warning: The user must allocate at least 32 bytes for
1152 * the authentication key (in order to use it also with HMAC-MD5-96),
1153 * even when using a shorter key for the AES-XCBC-MAC-96.
1154 */
1155 KEY(p, MDHA_SPLIT_KEY, 0, authdata->key, 32, INLINE_KEY(authdata));
1156 SET_LABEL(p, keyjump);
1157 LOAD(p, LDST_SRCDST_WORD_CLRW | CLRW_CLR_C1MODE | CLRW_CLR_C1DATAS |
1158 CLRW_CLR_C1CTX | CLRW_CLR_C1KEY | CLRW_RESET_CLS1_CHA, CLRW, 0, 4,
1159 0);
1160 KEY(p, KEY1, authdata->key_enc_flags, authdata->key, authdata->keylen,
1161 INLINE_KEY(authdata));
1162 MATHB(p, SEQINSZ, SUB,
1163 (uint64_t)(ip_hdr_len + IPSEC_ICV_MD5_TRUNC_SIZE), MATH0, 4,
1164 IMMED2);
1165 MATHB(p, MATH0, SUB, ZERO, VSEQINSZ, 4, 0);
1166 ALG_OPERATION(p, OP_ALG_ALGSEL_MD5, OP_ALG_AAI_HMAC_PRECOMP,
1167 OP_ALG_AS_INITFINAL, ICV_CHECK_DISABLE, DIR_ENC);
1168 ALG_OPERATION(p, OP_ALG_ALGSEL_AES, OP_ALG_AAI_XCBC_MAC,
1169 OP_ALG_AS_INITFINAL, ICV_CHECK_ENABLE, DIR_DEC);
1170 SEQFIFOLOAD(p, SKIP, ip_hdr_len, 0);
1171 SEQFIFOLOAD(p, MSG1, 0, VLF | FLUSH1);
1172 SEQFIFOLOAD(p, ICV1, IPSEC_ICV_MD5_TRUNC_SIZE, FLUSH1 | LAST1);
1173 /* Swap SEQOUTPTR to SEQINPTR. */
1174 move_seqin_ptr = MOVE(p, DESCBUF, 0, MATH1, 0, 16, WAITCOMP | IMMED);
1175 MATHB(p, MATH1, OR, CMD_SEQ_IN_PTR ^ CMD_SEQ_OUT_PTR, MATH1, 8,
1176 IFB | IMMED2);
1177 /*
1178 * TODO: RTA currently doesn't support creating a LOAD command
1179 * with another command as IMM.
1180 * To be changed when proper support is added in RTA.
1181 */
1182 LOAD(p, 0xA00000e1, MATH3, 4, 4, IMMED);
1183 MATHB(p, MATH3, SHLD, MATH3, MATH3, 8, 0);
1184 write_swapped_seqout_ptr = MOVE(p, MATH1, 0, DESCBUF, 0, 20, WAITCOMP |
1185 IMMED);
1186 swapped_seqout_ptr_jump = JUMP(p, swapped_seqout_ptr, LOCAL_JUMP,
1187 ALL_TRUE, 0);
1188 /*
1189 * TODO: To be changed when proper support is added in RTA (can't load
1190 * a command that is also written by RTA).
1191 * Change when proper RTA support is added.
1192 */
1193 SET_LABEL(p, jump_cmd);
1194 WORD(p, 0xA00000f3);
1195 SEQINPTR(p, 0, 65535, RTO);
1196 MATHB(p, MATH0, SUB, ZERO, VSEQINSZ, 4, 0);
1197 MATHB(p, MATH0, ADD, ip_hdr_len, VSEQOUTSZ, 4, IMMED2);
1198 move_jump = MOVE(p, DESCBUF, 0, OFIFO, 0, 8, WAITCOMP | IMMED);
1199 move_jump_back = MOVE(p, OFIFO, 0, DESCBUF, 0, 8, IMMED);
1200 SEQFIFOLOAD(p, SKIP, ip_hdr_len, 0);
1201 SEQFIFOLOAD(p, MSG2, 0, VLF | LAST2);
1202 SEQFIFOSTORE(p, SKIP, 0, 0, VLF);
1203 SEQSTORE(p, CONTEXT2, 0, IPSEC_ICV_MD5_TRUNC_SIZE, 0);
1204 seqout_ptr_jump = JUMP(p, seqout_ptr, LOCAL_JUMP, ALL_TRUE, CALM);
1205
1206 LOAD(p, LDST_SRCDST_WORD_CLRW | CLRW_CLR_C1MODE | CLRW_CLR_C1DATAS |
1207 CLRW_CLR_C1CTX | CLRW_CLR_C1KEY | CLRW_CLR_C2MODE |
1208 CLRW_CLR_C2DATAS | CLRW_CLR_C2CTX | CLRW_RESET_CLS1_CHA, CLRW, 0,
1209 4, 0);
1210 SEQINPTR(p, 0, 65535, RTO);
1211 MATHB(p, MATH0, ADD,
1212 (uint64_t)(ip_hdr_len + IPSEC_ICV_MD5_TRUNC_SIZE), SEQINSZ, 4,
1213 IMMED2);
1214 KEY(p, KEY1, cipherdata->key_enc_flags, cipherdata->key,
1215 cipherdata->keylen, INLINE_KEY(cipherdata));
1216 PROTOCOL(p, OP_TYPE_DECAP_PROTOCOL, OP_PCLID_IPSEC,
1217 (uint16_t)(cipherdata->algtype | OP_PCL_IPSEC_HMAC_MD5_96));
1218 /*
1219 * TODO: RTA currently doesn't support adding labels in or after Job Descriptor.
1220 * To be changed when proper support is added in RTA.
1221 */
1222 /* Label the SEQ OUT PTR */
1223 SET_LABEL(p, seqout_ptr);
1224 seqout_ptr += 2;
1225 /* Label the Output Length */
1226 SET_LABEL(p, outlen);
1227 outlen += 4;
1228 /* Label the SEQ IN PTR */
1229 SET_LABEL(p, seqin_ptr);
1230 seqin_ptr += 5;
1231 /* Label the first word after JD */
1232 SET_LABEL(p, swapped_seqout_fields);
1233 swapped_seqout_fields += 8;
1234 /* Label the second word after JD */
1235 SET_LABEL(p, swapped_seqout_ptr);
1236 swapped_seqout_ptr += 9;
1237
1238 PATCH_HDR(p, phdr, hdr);
1239 PATCH_JUMP(p, pkeyjump, keyjump);
1240 PATCH_JUMP(p, seqout_ptr_jump, seqout_ptr);
1241 PATCH_JUMP(p, swapped_seqout_ptr_jump, swapped_seqout_ptr);
1242 PATCH_MOVE(p, move_jump, jump_cmd);
1243 PATCH_MOVE(p, move_jump_back, seqin_ptr);
1244 PATCH_MOVE(p, move_seqin_ptr, outlen);
1245 PATCH_MOVE(p, write_swapped_seqout_ptr, swapped_seqout_fields);
1246 return PROGRAM_FINALIZE(p);
1247 }
1248
1249 /**
1250 * IPSEC_NEW_ENC_BASE_DESC_LEN - IPsec new mode encap shared descriptor length
1251 *
1252 * Accounts only for the "base" commands and is intended to be used by upper
1253 * layers to determine whether Outer IP Header and/or keys can be inlined or
1254 * not. To be used as first parameter of rta_inline_query().
1255 */
1256 #define IPSEC_NEW_ENC_BASE_DESC_LEN (12 * CAAM_CMD_SZ + \
1257 sizeof(struct ipsec_encap_pdb))
1258
1259 /**
1260 * IPSEC_NEW_NULL_ENC_BASE_DESC_LEN - IPsec new mode encap shared descriptor
1261 * length for the case of
1262 * NULL encryption / authentication
1263 *
1264 * Accounts only for the "base" commands and is intended to be used by upper
1265 * layers to determine whether Outer IP Header and/or key can be inlined or
1266 * not. To be used as first parameter of rta_inline_query().
1267 */
1268 #define IPSEC_NEW_NULL_ENC_BASE_DESC_LEN (11 * CAAM_CMD_SZ + \
1269 sizeof(struct ipsec_encap_pdb))
1270
1271 /**
1272 * cnstr_shdsc_ipsec_new_encap - IPSec new mode ESP encapsulation
1273 * protocol-level shared descriptor.
1274 * @descbuf: pointer to buffer used for descriptor construction
1275 * @ps: if 36/40bit addressing is desired, this parameter must be true
1276 * @swap: must be true when core endianness doesn't match SEC endianness
1277 * @share: sharing type of shared descriptor
1278 * @pdb: pointer to the PDB to be used with this descriptor
1279 * This structure will be copied inline to the descriptor under
1280 * construction. No error checking will be made. Refer to the
1281 * block guide for details about the encapsulation PDB.
1282 * @opt_ip_hdr: pointer to Optional IP Header
1283 * -if OIHI = PDBOPTS_ESP_OIHI_PDB_INL, opt_ip_hdr points to the buffer to
1284 * be inlined in the PDB. Number of bytes (buffer size) copied is provided
1285 * in pdb->ip_hdr_len.
1286 * -if OIHI = PDBOPTS_ESP_OIHI_PDB_REF, opt_ip_hdr points to the address of
1287 * the Optional IP Header. The address will be inlined in the PDB verbatim.
1288 * -for other values of OIHI options field, opt_ip_hdr is not used.
1289 * @cipherdata: pointer to block cipher transform definitions
1290 * Valid algorithm values - one of OP_PCL_IPSEC_*
1291 * @authdata: pointer to authentication transform definitions.
1292 * If an authentication key is required by the protocol, a "normal"
1293 * key must be provided; DKP (Derived Key Protocol) will be used to
1294 * compute MDHA on the fly in HW.
1295 * Valid algorithm values - one of OP_PCL_IPSEC_*
1296 *
1297 * Note: L2 header copy functionality is implemented assuming that bits 14
1298 * (currently reserved) and 16-23 (part of Outer IP Header Material Length)
1299 * in DPOVRD register are not used (which is usually the case when L3 header
1300 * is provided in PDB).
1301 * When DPOVRD[14] is set, frame starts with an L2 header; in this case, the
1302 * L2 header length is found at DPOVRD[23:16]. SEC uses this length to copy
1303 * the header and then it deletes DPOVRD[23:16] (so there is no side effect
1304 * when later running IPsec protocol).
1305 *
1306 * Return: size of descriptor written in words or negative number on error
1307 */
1308 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)1309 cnstr_shdsc_ipsec_new_encap(uint32_t *descbuf, bool ps,
1310 bool swap,
1311 enum rta_share_type share,
1312 struct ipsec_encap_pdb *pdb,
1313 uint8_t *opt_ip_hdr,
1314 struct alginfo *cipherdata,
1315 struct alginfo *authdata)
1316 {
1317 struct program prg;
1318 struct program *p = &prg;
1319
1320 LABEL(keyjmp);
1321 REFERENCE(pkeyjmp);
1322 LABEL(hdr);
1323 REFERENCE(phdr);
1324 LABEL(l2copy);
1325 REFERENCE(pl2copy);
1326
1327 PROGRAM_CNTXT_INIT(p, descbuf, 0);
1328 if (swap)
1329 PROGRAM_SET_BSWAP(p);
1330 if (ps)
1331 PROGRAM_SET_36BIT_ADDR(p);
1332 phdr = SHR_HDR(p, share, hdr, 0);
1333
1334 __rta_copy_ipsec_encap_pdb(p, pdb, cipherdata->algtype);
1335
1336 switch (pdb->options & PDBOPTS_ESP_OIHI_MASK) {
1337 case PDBOPTS_ESP_OIHI_PDB_INL:
1338 COPY_DATA(p, opt_ip_hdr, pdb->ip_hdr_len);
1339 break;
1340 case PDBOPTS_ESP_OIHI_PDB_REF:
1341 if (ps)
1342 COPY_DATA(p, opt_ip_hdr, 8);
1343 else
1344 COPY_DATA(p, opt_ip_hdr, 4);
1345 break;
1346 default:
1347 break;
1348 }
1349 SET_LABEL(p, hdr);
1350
1351 MATHB(p, DPOVRD, AND, IPSEC_N_ENCAP_DPOVRD_L2_COPY, NONE, 4, IMMED2);
1352 pl2copy = JUMP(p, l2copy, LOCAL_JUMP, ALL_TRUE, MATH_Z);
1353 MATHI(p, DPOVRD, RSHIFT, IPSEC_N_ENCAP_DPOVRD_L2_LEN_SHIFT, VSEQOUTSZ,
1354 1, 0);
1355 MATHB(p, DPOVRD, AND, ~IPSEC_N_ENCAP_DPOVRD_L2_LEN_MASK, DPOVRD, 4,
1356 IMMED2);
1357 /* TODO: CLASS2 corresponds to AUX=2'b10; add more intuitive defines */
1358 SEQFIFOSTORE(p, METADATA, 0, 0, CLASS2 | VLF);
1359 SET_LABEL(p, l2copy);
1360
1361 pkeyjmp = JUMP(p, keyjmp, LOCAL_JUMP, ALL_TRUE, SHRD);
1362 if (authdata->keylen)
1363 __gen_auth_key(p, authdata);
1364 if (cipherdata->keylen)
1365 KEY(p, KEY1, cipherdata->key_enc_flags, cipherdata->key,
1366 cipherdata->keylen, INLINE_KEY(cipherdata));
1367 SET_LABEL(p, keyjmp);
1368 PROTOCOL(p, OP_TYPE_ENCAP_PROTOCOL,
1369 OP_PCLID_IPSEC_NEW,
1370 (uint16_t)(cipherdata->algtype | authdata->algtype));
1371 PATCH_JUMP(p, pl2copy, l2copy);
1372 PATCH_JUMP(p, pkeyjmp, keyjmp);
1373 PATCH_HDR(p, phdr, hdr);
1374 return PROGRAM_FINALIZE(p);
1375 }
1376
1377 /**
1378 * IPSEC_NEW_DEC_BASE_DESC_LEN - IPsec new mode decap shared descriptor length
1379 *
1380 * Accounts only for the "base" commands and is intended to be used by upper
1381 * layers to determine whether keys can be inlined or not. To be used as first
1382 * parameter of rta_inline_query().
1383 */
1384 #define IPSEC_NEW_DEC_BASE_DESC_LEN (5 * CAAM_CMD_SZ + \
1385 sizeof(struct ipsec_decap_pdb))
1386
1387 /**
1388 * IPSEC_NEW_NULL_DEC_BASE_DESC_LEN - IPsec new mode decap shared descriptor
1389 * length for the case of
1390 * NULL decryption / authentication
1391 *
1392 * Accounts only for the "base" commands and is intended to be used by upper
1393 * layers to determine whether key can be inlined or not. To be used as first
1394 * parameter of rta_inline_query().
1395 */
1396 #define IPSEC_NEW_NULL_DEC_BASE_DESC_LEN (4 * CAAM_CMD_SZ + \
1397 sizeof(struct ipsec_decap_pdb))
1398
1399 /**
1400 * cnstr_shdsc_ipsec_new_decap - IPSec new mode ESP decapsulation protocol-level
1401 * shared descriptor.
1402 * @descbuf: pointer to buffer used for descriptor construction
1403 * @ps: if 36/40bit addressing is desired, this parameter must be true
1404 * @swap: must be true when core endianness doesn't match SEC endianness
1405 * @share: sharing type of shared descriptor
1406 * @pdb: pointer to the PDB to be used with this descriptor
1407 * This structure will be copied inline to the descriptor under
1408 * construction. No error checking will be made. Refer to the
1409 * block guide for details about the decapsulation PDB.
1410 * @cipherdata: pointer to block cipher transform definitions
1411 * Valid algorithm values 0 one of OP_PCL_IPSEC_*
1412 * @authdata: pointer to authentication transform definitions.
1413 * If an authentication key is required by the protocol, a "normal"
1414 * key must be provided; DKP (Derived Key Protocol) will be used to
1415 * compute MDHA on the fly in HW.
1416 * Valid algorithm values - one of OP_PCL_IPSEC_*
1417 *
1418 * Return: size of descriptor written in words or negative number on error
1419 */
1420 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)1421 cnstr_shdsc_ipsec_new_decap(uint32_t *descbuf, bool ps,
1422 bool swap,
1423 enum rta_share_type share,
1424 struct ipsec_decap_pdb *pdb,
1425 struct alginfo *cipherdata,
1426 struct alginfo *authdata)
1427 {
1428 struct program prg;
1429 struct program *p = &prg;
1430
1431 LABEL(keyjmp);
1432 REFERENCE(pkeyjmp);
1433 LABEL(hdr);
1434 REFERENCE(phdr);
1435
1436 PROGRAM_CNTXT_INIT(p, descbuf, 0);
1437 if (swap)
1438 PROGRAM_SET_BSWAP(p);
1439 if (ps)
1440 PROGRAM_SET_36BIT_ADDR(p);
1441 phdr = SHR_HDR(p, share, hdr, 0);
1442 __rta_copy_ipsec_decap_pdb(p, pdb, cipherdata->algtype);
1443 SET_LABEL(p, hdr);
1444 pkeyjmp = JUMP(p, keyjmp, LOCAL_JUMP, ALL_TRUE, SHRD);
1445 if (authdata->keylen)
1446 __gen_auth_key(p, authdata);
1447 if (cipherdata->keylen)
1448 KEY(p, KEY1, cipherdata->key_enc_flags, cipherdata->key,
1449 cipherdata->keylen, INLINE_KEY(cipherdata));
1450 SET_LABEL(p, keyjmp);
1451 PROTOCOL(p, OP_TYPE_DECAP_PROTOCOL,
1452 OP_PCLID_IPSEC_NEW,
1453 (uint16_t)(cipherdata->algtype | authdata->algtype));
1454 PATCH_JUMP(p, pkeyjmp, keyjmp);
1455 PATCH_HDR(p, phdr, hdr);
1456 return PROGRAM_FINALIZE(p);
1457 }
1458
1459 /**
1460 * IPSEC_AUTH_VAR_BASE_DESC_LEN - IPsec encap/decap shared descriptor length
1461 * for the case of variable-length authentication
1462 * only data.
1463 * Note: Only for SoCs with SEC_ERA >= 3.
1464 *
1465 * Accounts only for the "base" commands and is intended to be used by upper
1466 * layers to determine whether keys can be inlined or not. To be used as first
1467 * parameter of rta_inline_query().
1468 */
1469 #define IPSEC_AUTH_VAR_BASE_DESC_LEN (31 * CAAM_CMD_SZ)
1470
1471 /**
1472 * IPSEC_AUTH_VAR_AES_DEC_BASE_DESC_LEN - IPsec AES decap shared descriptor
1473 * length for variable-length authentication only
1474 * data.
1475 * Note: Only for SoCs with SEC_ERA >= 3.
1476 *
1477 * Accounts only for the "base" commands and is intended to be used by upper
1478 * layers to determine whether key can be inlined or not. To be used as first
1479 * parameter of rta_inline_query().
1480 */
1481 #define IPSEC_AUTH_VAR_AES_DEC_BASE_DESC_LEN \
1482 (IPSEC_AUTH_VAR_BASE_DESC_LEN + CAAM_CMD_SZ)
1483
1484 /**
1485 * IPSEC_AUTH_BASE_DESC_LEN - IPsec encap/decap shared descriptor length
1486 *
1487 * Accounts only for the "base" commands and is intended to be used by upper
1488 * layers to determine whether key can be inlined or not. To be used as first
1489 * parameter of rta_inline_query().
1490 */
1491 #define IPSEC_AUTH_BASE_DESC_LEN (19 * CAAM_CMD_SZ)
1492
1493 /**
1494 * IPSEC_AUTH_AES_DEC_BASE_DESC_LEN - IPsec AES decap shared descriptor length
1495 *
1496 * Accounts only for the "base" commands and is intended to be used by upper
1497 * layers to determine whether key can be inlined or not. To be used as first
1498 * parameter of rta_inline_query().
1499 */
1500 #define IPSEC_AUTH_AES_DEC_BASE_DESC_LEN (IPSEC_AUTH_BASE_DESC_LEN + \
1501 CAAM_CMD_SZ)
1502
1503 /**
1504 * cnstr_shdsc_authenc - authenc-like descriptor
1505 * @descbuf: pointer to buffer used for descriptor construction
1506 * @ps: if 36/40bit addressing is desired, this parameter must be true
1507 * @swap: if true, perform descriptor byte swapping on a 4-byte boundary
1508 * @share: sharing type of shared descriptor
1509 * @cipherdata: pointer to block cipher transform definitions.
1510 * Valid algorithm values one of OP_ALG_ALGSEL_* {DES, 3DES, AES}
1511 * Valid modes for:
1512 * AES: OP_ALG_AAI_* {CBC, CTR}
1513 * DES, 3DES: OP_ALG_AAI_CBC
1514 * @authdata: pointer to authentication transform definitions.
1515 * Valid algorithm values - one of OP_ALG_ALGSEL_* {MD5, SHA1,
1516 * SHA224, SHA256, SHA384, SHA512}
1517 * Note: The key for authentication is supposed to be given as plain text.
1518 * Note: There's no support for keys longer than the block size of the
1519 * underlying hash function, according to the selected algorithm.
1520 *
1521 * @ivlen: length of the IV to be read from the input frame, before any data
1522 * to be processed
1523 *
1524 * @trunc_len: the length of the ICV to be written to the output frame. If 0,
1525 * then the corresponding length of the digest, according to the
1526 * selected algorithm shall be used.
1527 * @dir: Protocol direction, encapsulation or decapsulation (DIR_ENC/DIR_DEC)
1528 *
1529 * Note: Here's how the input frame needs to be formatted so that the processing
1530 * will be done correctly:
1531 * For encapsulation:
1532 * Input:
1533 * +----+----------------+-----------------------------------------------+
1534 * | IV | Auth-only head | Padded data to be auth & Enc | Auth-only tail |
1535 * +----+----------------+-----------------------------------------------+
1536 * Output:
1537 * +--------------------------------------+
1538 * | Authenticated & Encrypted data | ICV |
1539 * +--------------------------------+-----+
1540 *
1541 * For decapsulation:
1542 * Input:
1543 * +----+----------------+-----------------+----------------------+
1544 * | IV | Auth-only head | Auth & Enc data | Auth-only tail | ICV |
1545 * +----+----------------+-----------------+----------------------+
1546 * Output:
1547 * +----+---------------------------+
1548 * | Decrypted & authenticated data |
1549 * +----+---------------------------+
1550 *
1551 * Note: This descriptor can use per-packet commands, encoded as below in the
1552 * DPOVRD register:
1553 * 32 28 16 1
1554 * +------+------------------------------+
1555 * | 0x8 | auth_tail_len | auth_hdr_len |
1556 * +------+------------------------------+
1557 *
1558 * This mechanism is available only for SoCs having SEC ERA >= 3. In other
1559 * words, this will not work for P4080TO2
1560 *
1561 * Note: The descriptor does not add any kind of padding to the input data,
1562 * so the upper layer needs to ensure that the data is padded properly,
1563 * according to the selected cipher. Failure to do so will result in
1564 * the descriptor failing with a data-size error.
1565 *
1566 * Return: size of descriptor written in words or negative number on error
1567 */
1568 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)1569 cnstr_shdsc_authenc(uint32_t *descbuf, bool ps, bool swap,
1570 enum rta_share_type share,
1571 struct alginfo *cipherdata,
1572 struct alginfo *authdata,
1573 uint16_t ivlen,
1574 uint8_t trunc_len, uint8_t dir)
1575 {
1576 struct program prg;
1577 struct program *p = &prg;
1578 const bool need_dk = (dir == DIR_DEC) &&
1579 (cipherdata->algtype == OP_ALG_ALGSEL_AES) &&
1580 (cipherdata->algmode == OP_ALG_AAI_CBC);
1581 int data_type;
1582
1583 LABEL(keyjmp);
1584 LABEL(skipkeys);
1585 LABEL(proc_icv);
1586 LABEL(no_auth_tail);
1587 REFERENCE(pkeyjmp);
1588 REFERENCE(pskipkeys);
1589 REFERENCE(p_proc_icv);
1590 REFERENCE(p_no_auth_tail);
1591
1592 PROGRAM_CNTXT_INIT(p, descbuf, 0);
1593
1594 if (swap)
1595 PROGRAM_SET_BSWAP(p);
1596 if (ps)
1597 PROGRAM_SET_36BIT_ADDR(p);
1598
1599 /*
1600 * Since we currently assume that key length is equal to hash digest
1601 * size, it's ok to truncate keylen value.
1602 */
1603 trunc_len = trunc_len && (trunc_len < authdata->keylen) ?
1604 trunc_len : (uint8_t)authdata->keylen;
1605
1606 SHR_HDR(p, share, 1, SC);
1607
1608 /* Collect the (auth_tail || auth_hdr) len from DPOVRD */
1609 MATHB(p, DPOVRD, ADD, 0x80000000, MATH2, 4, IMMED2);
1610
1611 /* Get auth_hdr len in MATH0 */
1612 MATHB(p, MATH2, AND, 0xFFFF, MATH0, 4, IMMED2);
1613
1614 /* Get auth_tail len in MATH2 */
1615 MATHB(p, MATH2, AND, 0xFFF0000, MATH2, 4, IMMED2);
1616 MATHI(p, MATH2, RSHIFT, 16, MATH2, 4, IMMED2);
1617
1618 pkeyjmp = JUMP(p, keyjmp, LOCAL_JUMP, ALL_TRUE, SHRD);
1619
1620 KEY(p, KEY2, authdata->key_enc_flags, authdata->key, authdata->keylen,
1621 INLINE_KEY(authdata));
1622
1623 /* Insert Key */
1624 KEY(p, KEY1, cipherdata->key_enc_flags, cipherdata->key,
1625 cipherdata->keylen, INLINE_KEY(cipherdata));
1626
1627 /* Do operation */
1628 ALG_OPERATION(p, authdata->algtype, authdata->algmode,
1629 OP_ALG_AS_INITFINAL,
1630 dir == DIR_ENC ? ICV_CHECK_DISABLE : ICV_CHECK_ENABLE,
1631 dir);
1632
1633 if (need_dk)
1634 ALG_OPERATION(p, OP_ALG_ALGSEL_AES, cipherdata->algmode,
1635 OP_ALG_AS_INITFINAL, ICV_CHECK_DISABLE, dir);
1636 pskipkeys = JUMP(p, skipkeys, LOCAL_JUMP, ALL_TRUE, 0);
1637
1638 SET_LABEL(p, keyjmp);
1639
1640 if (authdata->algmode == OP_ALG_AAI_HMAC)
1641 ALG_OPERATION(p, authdata->algtype, OP_ALG_AAI_HMAC_PRECOMP,
1642 OP_ALG_AS_INITFINAL,
1643 dir == DIR_ENC ? ICV_CHECK_DISABLE : ICV_CHECK_ENABLE,
1644 dir);
1645 else
1646 ALG_OPERATION(p, authdata->algtype, authdata->algmode,
1647 OP_ALG_AS_INITFINAL,
1648 dir == DIR_ENC ? ICV_CHECK_DISABLE : ICV_CHECK_ENABLE,
1649 dir);
1650
1651 if (need_dk) {
1652 ALG_OPERATION(p, OP_ALG_ALGSEL_AES, cipherdata->algmode |
1653 OP_ALG_AAI_DK, OP_ALG_AS_INITFINAL,
1654 ICV_CHECK_DISABLE, dir);
1655 SET_LABEL(p, skipkeys);
1656 } else {
1657 SET_LABEL(p, skipkeys);
1658 ALG_OPERATION(p, cipherdata->algtype, cipherdata->algmode,
1659 OP_ALG_AS_INITFINAL, ICV_CHECK_DISABLE, dir);
1660 }
1661
1662 /* Read IV */
1663 if (cipherdata->algmode == OP_ALG_AAI_CTR)
1664 SEQLOAD(p, CONTEXT1, 16, ivlen, 0);
1665 else
1666 SEQLOAD(p, CONTEXT1, 0, ivlen, 0);
1667
1668 /*
1669 * authenticate auth_hdr data
1670 */
1671 MATHB(p, MATH0, ADD, ZERO, VSEQINSZ, 4, 0);
1672 SEQFIFOLOAD(p, MSG2, 0, VLF);
1673
1674 /*
1675 * Prepare the length of the data to be both encrypted/decrypted
1676 * and authenticated/checked
1677 */
1678 MATHB(p, SEQINSZ, SUB, MATH2, VSEQINSZ, 4, 0);
1679 if (dir == DIR_DEC) {
1680 MATHB(p, VSEQINSZ, SUB, trunc_len, VSEQINSZ, 4, IMMED2);
1681 data_type = MSGINSNOOP;
1682 } else {
1683 data_type = MSGOUTSNOOP;
1684 }
1685
1686 MATHB(p, VSEQINSZ, ADD, ZERO, VSEQOUTSZ, 4, 0);
1687
1688 /* Prepare for writing the output frame */
1689 SEQFIFOSTORE(p, MSG, 0, 0, VLF);
1690
1691
1692 /* Check if there is no auth-tail */
1693 MATHB(p, MATH2, ADD, ZERO, MATH2, 4, 0);
1694 p_no_auth_tail = JUMP(p, no_auth_tail, LOCAL_JUMP, ALL_TRUE, MATH_Z);
1695
1696 /*
1697 * Read input plain/cipher text, encrypt/decrypt & auth & write
1698 * to output
1699 */
1700 SEQFIFOLOAD(p, data_type, 0, VLF | LAST1 | FLUSH1);
1701
1702 /* Authenticate auth tail */
1703 MATHB(p, MATH2, ADD, ZERO, VSEQINSZ, 4, 0);
1704 SEQFIFOLOAD(p, MSG2, 0, VLF | LAST2);
1705
1706 /* Jump to process icv */
1707 p_proc_icv = JUMP(p, proc_icv, LOCAL_JUMP, ALL_FALSE, MATH_Z);
1708
1709 SET_LABEL(p, no_auth_tail);
1710
1711 SEQFIFOLOAD(p, data_type, 0, VLF | LAST1 | LAST2 | FLUSH1);
1712
1713 SET_LABEL(p, proc_icv);
1714
1715 if (dir == DIR_ENC)
1716 /* Finally, write the ICV */
1717 SEQSTORE(p, CONTEXT2, 0, trunc_len, 0);
1718 else
1719 /* Read the ICV to check */
1720 SEQFIFOLOAD(p, ICV2, trunc_len, LAST2);
1721
1722 PATCH_JUMP(p, pkeyjmp, keyjmp);
1723 PATCH_JUMP(p, pskipkeys, skipkeys);
1724 PATCH_JUMP(p, p_no_auth_tail, no_auth_tail);
1725 PATCH_JUMP(p, p_proc_icv, proc_icv);
1726 return PROGRAM_FINALIZE(p);
1727 }
1728
1729 #endif /* __DESC_IPSEC_H__ */
1730