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