Branch data Line data Source code
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
354 : 0 : __rta_copy_ipsec_encap_pdb(struct program *program,
355 : : struct ipsec_encap_pdb *pdb,
356 : : uint32_t algtype)
357 : : {
358 : 0 : unsigned int start_pc = program->current_pc;
359 : :
360 : 0 : __rta_out32(program, pdb->options);
361 : 0 : __rta_out32(program, pdb->seq_num_ext_hi);
362 : 0 : __rta_out32(program, pdb->seq_num);
363 : :
364 [ # # # # : 0 : switch (algtype & OP_PCL_IPSEC_CIPHER_MASK) {
# ]
365 : 0 : 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 : 0 : rta_copy_data(program, pdb->cbc.iv, sizeof(pdb->cbc.iv));
371 : : break;
372 : :
373 : 0 : case OP_PCL_IPSEC_AES_CTR:
374 : 0 : rta_copy_data(program, (uint8_t *)&pdb->ctr.ctr_nonce, 4);
375 : 0 : __rta_out32(program, pdb->ctr.ctr_initial);
376 : 0 : rta_copy_data(program, pdb->ctr.iv, sizeof(pdb->ctr.iv));
377 : : break;
378 : :
379 : 0 : case OP_PCL_IPSEC_AES_CCM8:
380 : : case OP_PCL_IPSEC_AES_CCM12:
381 : : case OP_PCL_IPSEC_AES_CCM16:
382 : 0 : rta_copy_data(program, pdb->ccm.salt, sizeof(pdb->ccm.salt));
383 : 0 : __rta_out32(program, pdb->ccm.ccm_opt);
384 : 0 : __rta_out64(program, true, pdb->ccm.iv);
385 : 0 : break;
386 : :
387 : 0 : 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 : 0 : rta_copy_data(program, pdb->gcm.salt, sizeof(pdb->gcm.salt));
392 : 0 : __rta_out32(program, pdb->gcm.rsvd);
393 : 0 : __rta_out64(program, true, pdb->gcm.iv);
394 : 0 : break;
395 : : }
396 : :
397 : 0 : __rta_out32(program, pdb->spi);
398 : 0 : __rta_out32(program, pdb->ip_hdr_len);
399 : :
400 : 0 : 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
471 : 0 : __rta_copy_ipsec_decap_pdb(struct program *program,
472 : : struct ipsec_decap_pdb *pdb,
473 : : uint32_t algtype)
474 : : {
475 : 0 : unsigned int start_pc = program->current_pc;
476 : : unsigned int i, ars;
477 : : uint8_t mask;
478 : :
479 : 0 : __rta_out32(program, pdb->options);
480 : :
481 [ # # # # : 0 : switch (algtype & OP_PCL_IPSEC_CIPHER_MASK) {
# ]
482 : 0 : 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 : 0 : __rta_out32(program, pdb->cbc.rsvd[0]);
488 : 0 : __rta_out32(program, pdb->cbc.rsvd[1]);
489 : 0 : break;
490 : :
491 : 0 : case OP_PCL_IPSEC_AES_CTR:
492 : 0 : rta_copy_data(program, (uint8_t *)&pdb->ctr.ctr_nonce, 4);
493 : 0 : __rta_out32(program, pdb->ctr.ctr_initial);
494 : 0 : break;
495 : :
496 : 0 : case OP_PCL_IPSEC_AES_CCM8:
497 : : case OP_PCL_IPSEC_AES_CCM12:
498 : : case OP_PCL_IPSEC_AES_CCM16:
499 : 0 : rta_copy_data(program, pdb->ccm.salt, sizeof(pdb->ccm.salt));
500 : 0 : __rta_out32(program, pdb->ccm.ccm_opt);
501 : 0 : break;
502 : :
503 : 0 : 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 : 0 : rta_copy_data(program, pdb->gcm.salt, sizeof(pdb->gcm.salt));
508 : 0 : __rta_out32(program, pdb->gcm.rsvd);
509 : 0 : break;
510 : : }
511 : :
512 : 0 : __rta_out32(program, pdb->seq_num_ext_hi);
513 : 0 : __rta_out32(program, pdb->seq_num);
514 : :
515 [ # # ]: 0 : if (rta_sec_era < RTA_SEC_ERA_10)
516 : : mask = PDBOPTS_ESP_ARS_MASK;
517 : : else
518 : : mask = PDBOPTS_ESP_ARS_MASK_ERA10;
519 [ # # # # : 0 : switch (pdb->options & mask) {
# # # ]
520 : : case PDBOPTS_ESP_ARS1024:
521 : : ars = 32;
522 : : break;
523 : 0 : case PDBOPTS_ESP_ARS512:
524 : : ars = 16;
525 : 0 : break;
526 : 0 : case PDBOPTS_ESP_ARS256:
527 : : ars = 8;
528 : 0 : break;
529 : 0 : case PDBOPTS_ESP_ARS128:
530 : : ars = 4;
531 : 0 : break;
532 : 0 : case PDBOPTS_ESP_ARS64:
533 : : ars = 2;
534 : 0 : break;
535 : 0 : case PDBOPTS_ESP_ARS32:
536 : : ars = 1;
537 : 0 : break;
538 : 0 : case PDBOPTS_ESP_ARSNONE:
539 : : default:
540 : : ars = 0;
541 : 0 : break;
542 : : }
543 : :
544 [ # # ]: 0 : for (i = 0; i < ars; i++)
545 : 0 : __rta_out_be32(program, pdb->anti_replay[i]);
546 : :
547 : 0 : 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 : :
687 : 0 : static inline void __gen_auth_key(struct program *program,
688 : : struct alginfo *authdata)
689 : : {
690 : : uint32_t dkp_protid;
691 : :
692 [ # # # # : 0 : 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 : 0 : case OP_PCL_IPSEC_HMAC_SHA1_96:
698 : : case OP_PCL_IPSEC_HMAC_SHA1_160:
699 : : dkp_protid = OP_PCLID_DKP_SHA1;
700 : 0 : break;
701 : 0 : case OP_PCL_IPSEC_HMAC_SHA2_256_128:
702 : : dkp_protid = OP_PCLID_DKP_SHA256;
703 : 0 : break;
704 : 0 : case OP_PCL_IPSEC_HMAC_SHA2_384_192:
705 : : dkp_protid = OP_PCLID_DKP_SHA384;
706 : 0 : break;
707 : 0 : case OP_PCL_IPSEC_HMAC_SHA2_512_256:
708 : : dkp_protid = OP_PCLID_DKP_SHA512;
709 : 0 : break;
710 : 0 : 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 : 0 : break;
715 : 0 : default:
716 : 0 : KEY(program, KEY2, authdata->key_enc_flags, authdata->key,
717 : : authdata->keylen, INLINE_KEY(authdata));
718 : 0 : return;
719 : : }
720 : :
721 [ # # ]: 0 : if (authdata->key_type == RTA_DATA_PTR)
722 : 0 : 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 : 0 : 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
753 : 0 : 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 [ # # # # : 0 : 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 : 0 : case OP_PCL_IPSEC_HMAC_SHA1_96:
769 : : case OP_PCL_IPSEC_HMAC_SHA1_160:
770 : : dkp_protid = OP_PCLID_DKP_SHA1;
771 : 0 : break;
772 : 0 : case OP_PCL_IPSEC_HMAC_SHA2_256_128:
773 : : dkp_protid = OP_PCLID_DKP_SHA256;
774 : 0 : break;
775 : 0 : case OP_PCL_IPSEC_HMAC_SHA2_384_192:
776 : : dkp_protid = OP_PCLID_DKP_SHA384;
777 : 0 : break;
778 : 0 : case OP_PCL_IPSEC_HMAC_SHA2_512_256:
779 : : dkp_protid = OP_PCLID_DKP_SHA512;
780 : 0 : break;
781 : 0 : 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 : 0 : break;
786 : 0 : default:
787 : 0 : 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 [ # # ]: 0 : if (auth_index != -1) {
795 [ # # ]: 0 : if (split_key_len(dkp_protid) > data_len[auth_index])
796 : 0 : data_len[auth_index] = split_key_len(dkp_protid);
797 : : }
798 : 0 : 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
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
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
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
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
1309 [ # # ]: 0 : 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 [ # # ]: 0 : if (swap)
1329 : : PROGRAM_SET_BSWAP(p);
1330 [ # # ]: 0 : if (ps)
1331 : : PROGRAM_SET_36BIT_ADDR(p);
1332 : 0 : phdr = SHR_HDR(p, share, hdr, 0);
1333 : :
1334 : 0 : __rta_copy_ipsec_encap_pdb(p, pdb, cipherdata->algtype);
1335 : :
1336 [ # # # ]: 0 : switch (pdb->options & PDBOPTS_ESP_OIHI_MASK) {
1337 : 0 : case PDBOPTS_ESP_OIHI_PDB_INL:
1338 : 0 : COPY_DATA(p, opt_ip_hdr, pdb->ip_hdr_len);
1339 : : break;
1340 : 0 : case PDBOPTS_ESP_OIHI_PDB_REF:
1341 [ # # ]: 0 : 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 : 0 : MATHB(p, DPOVRD, AND, IPSEC_N_ENCAP_DPOVRD_L2_COPY, NONE, 4, IMMED2);
1352 : 0 : pl2copy = JUMP(p, l2copy, LOCAL_JUMP, ALL_TRUE, MATH_Z);
1353 : 0 : MATHI(p, DPOVRD, RSHIFT, IPSEC_N_ENCAP_DPOVRD_L2_LEN_SHIFT, VSEQOUTSZ,
1354 : : 1, 0);
1355 : 0 : 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 : 0 : SEQFIFOSTORE(p, METADATA, 0, 0, CLASS2 | VLF);
1359 : : SET_LABEL(p, l2copy);
1360 : :
1361 : 0 : pkeyjmp = JUMP(p, keyjmp, LOCAL_JUMP, ALL_TRUE, SHRD);
1362 [ # # ]: 0 : if (authdata->keylen)
1363 : 0 : __gen_auth_key(p, authdata);
1364 [ # # ]: 0 : if (cipherdata->keylen)
1365 : 0 : KEY(p, KEY1, cipherdata->key_enc_flags, cipherdata->key,
1366 : : cipherdata->keylen, INLINE_KEY(cipherdata));
1367 : : SET_LABEL(p, keyjmp);
1368 : 0 : PROTOCOL(p, OP_TYPE_ENCAP_PROTOCOL,
1369 : : OP_PCLID_IPSEC_NEW,
1370 : : (uint16_t)(cipherdata->algtype | authdata->algtype));
1371 : 0 : PATCH_JUMP(p, pl2copy, l2copy);
1372 : 0 : PATCH_JUMP(p, pkeyjmp, keyjmp);
1373 : 0 : PATCH_HDR(p, phdr, hdr);
1374 : 0 : 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
1421 [ # # ]: 0 : 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 [ # # ]: 0 : if (swap)
1438 : : PROGRAM_SET_BSWAP(p);
1439 [ # # ]: 0 : if (ps)
1440 : : PROGRAM_SET_36BIT_ADDR(p);
1441 : 0 : phdr = SHR_HDR(p, share, hdr, 0);
1442 : 0 : __rta_copy_ipsec_decap_pdb(p, pdb, cipherdata->algtype);
1443 : : SET_LABEL(p, hdr);
1444 : 0 : pkeyjmp = JUMP(p, keyjmp, LOCAL_JUMP, ALL_TRUE, SHRD);
1445 [ # # ]: 0 : if (authdata->keylen)
1446 : 0 : __gen_auth_key(p, authdata);
1447 [ # # ]: 0 : if (cipherdata->keylen)
1448 : 0 : KEY(p, KEY1, cipherdata->key_enc_flags, cipherdata->key,
1449 : : cipherdata->keylen, INLINE_KEY(cipherdata));
1450 : : SET_LABEL(p, keyjmp);
1451 : 0 : PROTOCOL(p, OP_TYPE_DECAP_PROTOCOL,
1452 : : OP_PCLID_IPSEC_NEW,
1453 : : (uint16_t)(cipherdata->algtype | authdata->algtype));
1454 : 0 : PATCH_JUMP(p, pkeyjmp, keyjmp);
1455 : 0 : PATCH_HDR(p, phdr, hdr);
1456 : 0 : 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
1569 : 0 : 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 [ # # ]: 0 : const bool need_dk = (dir == DIR_DEC) &&
1579 [ # # # # ]: 0 : (cipherdata->algtype == OP_ALG_ALGSEL_AES) &&
1580 [ # # ]: 0 : (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 [ # # ]: 0 : if (swap)
1595 : : PROGRAM_SET_BSWAP(p);
1596 [ # # ]: 0 : 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 [ # # # # ]: 0 : trunc_len = trunc_len && (trunc_len < authdata->keylen) ?
1604 : 0 : trunc_len : (uint8_t)authdata->keylen;
1605 : :
1606 : 0 : SHR_HDR(p, share, 1, SC);
1607 : :
1608 : : /* Collect the (auth_tail || auth_hdr) len from DPOVRD */
1609 : 0 : MATHB(p, DPOVRD, ADD, 0x80000000, MATH2, 4, IMMED2);
1610 : :
1611 : : /* Get auth_hdr len in MATH0 */
1612 : 0 : MATHB(p, MATH2, AND, 0xFFFF, MATH0, 4, IMMED2);
1613 : :
1614 : : /* Get auth_tail len in MATH2 */
1615 : 0 : MATHB(p, MATH2, AND, 0xFFF0000, MATH2, 4, IMMED2);
1616 : 0 : MATHI(p, MATH2, RSHIFT, 16, MATH2, 4, IMMED2);
1617 : :
1618 : 0 : pkeyjmp = JUMP(p, keyjmp, LOCAL_JUMP, ALL_TRUE, SHRD);
1619 : :
1620 : 0 : KEY(p, KEY2, authdata->key_enc_flags, authdata->key, authdata->keylen,
1621 : : INLINE_KEY(authdata));
1622 : :
1623 : : /* Insert Key */
1624 : 0 : KEY(p, KEY1, cipherdata->key_enc_flags, cipherdata->key,
1625 : : cipherdata->keylen, INLINE_KEY(cipherdata));
1626 : :
1627 : : /* Do operation */
1628 : 0 : 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 [ # # ]: 0 : if (need_dk)
1634 : 0 : ALG_OPERATION(p, OP_ALG_ALGSEL_AES, cipherdata->algmode,
1635 : : OP_ALG_AS_INITFINAL, ICV_CHECK_DISABLE, dir);
1636 : 0 : pskipkeys = JUMP(p, skipkeys, LOCAL_JUMP, ALL_TRUE, 0);
1637 : :
1638 : : SET_LABEL(p, keyjmp);
1639 : :
1640 [ # # ]: 0 : if (authdata->algmode == OP_ALG_AAI_HMAC)
1641 : 0 : 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 : 0 : 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 [ # # ]: 0 : if (need_dk) {
1652 : 0 : 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 : 0 : ALG_OPERATION(p, cipherdata->algtype, cipherdata->algmode,
1659 : : OP_ALG_AS_INITFINAL, ICV_CHECK_DISABLE, dir);
1660 : : }
1661 : :
1662 : : /* Read IV */
1663 [ # # ]: 0 : if (cipherdata->algmode == OP_ALG_AAI_CTR)
1664 : 0 : SEQLOAD(p, CONTEXT1, 16, ivlen, 0);
1665 : : else
1666 : 0 : SEQLOAD(p, CONTEXT1, 0, ivlen, 0);
1667 : :
1668 : : /*
1669 : : * authenticate auth_hdr data
1670 : : */
1671 : 0 : MATHB(p, MATH0, ADD, ZERO, VSEQINSZ, 4, 0);
1672 : 0 : 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 : 0 : MATHB(p, SEQINSZ, SUB, MATH2, VSEQINSZ, 4, 0);
1679 [ # # ]: 0 : if (dir == DIR_DEC) {
1680 : 0 : MATHB(p, VSEQINSZ, SUB, trunc_len, VSEQINSZ, 4, IMMED2);
1681 : : data_type = MSGINSNOOP;
1682 : : } else {
1683 : : data_type = MSGOUTSNOOP;
1684 : : }
1685 : :
1686 : 0 : MATHB(p, VSEQINSZ, ADD, ZERO, VSEQOUTSZ, 4, 0);
1687 : :
1688 : : /* Prepare for writing the output frame */
1689 : 0 : SEQFIFOSTORE(p, MSG, 0, 0, VLF);
1690 : :
1691 : :
1692 : : /* Check if there is no auth-tail */
1693 : 0 : MATHB(p, MATH2, ADD, ZERO, MATH2, 4, 0);
1694 : 0 : 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 : 0 : SEQFIFOLOAD(p, data_type, 0, VLF | LAST1 | FLUSH1);
1701 : :
1702 : : /* Authenticate auth tail */
1703 : 0 : MATHB(p, MATH2, ADD, ZERO, VSEQINSZ, 4, 0);
1704 : 0 : SEQFIFOLOAD(p, MSG2, 0, VLF | LAST2);
1705 : :
1706 : : /* Jump to process icv */
1707 : 0 : p_proc_icv = JUMP(p, proc_icv, LOCAL_JUMP, ALL_FALSE, MATH_Z);
1708 : :
1709 : : SET_LABEL(p, no_auth_tail);
1710 : :
1711 : 0 : SEQFIFOLOAD(p, data_type, 0, VLF | LAST1 | LAST2 | FLUSH1);
1712 : :
1713 : : SET_LABEL(p, proc_icv);
1714 : :
1715 [ # # ]: 0 : if (dir == DIR_ENC)
1716 : : /* Finally, write the ICV */
1717 : 0 : SEQSTORE(p, CONTEXT2, 0, trunc_len, 0);
1718 : : else
1719 : : /* Read the ICV to check */
1720 : 0 : SEQFIFOLOAD(p, ICV2, trunc_len, LAST2);
1721 : :
1722 : 0 : PATCH_JUMP(p, pkeyjmp, keyjmp);
1723 : 0 : PATCH_JUMP(p, pskipkeys, skipkeys);
1724 : 0 : PATCH_JUMP(p, p_no_auth_tail, no_auth_tail);
1725 : 0 : PATCH_JUMP(p, p_proc_icv, proc_icv);
1726 : 0 : return PROGRAM_FINALIZE(p);
1727 : : }
1728 : :
1729 : : #endif /* __DESC_IPSEC_H__ */
|