1 /* SPDX-License-Identifier: BSD-3-Clause
2 * Copyright 2020 NXP
3 */
4
5 #ifndef __DESC_SDAP_H__
6 #define __DESC_SDAP_H__
7
8 #include "rta.h"
9 #include "common.h"
10 #include "pdcp.h"
11
12 /* The file defines all the functions to do PDCP without protocol support in
13 * SEC
14 */
15
16 /* Enable SDAP support */
17 #define SDAP_SUPPORT
18 #ifdef SDAP_SUPPORT
19 #define SDAP_BYTE_SIZE 1
20 #define SDAP_BITS_SIZE (SDAP_BYTE_SIZE * 8)
21 #endif
22
key_loading_opti(struct program * p,struct alginfo * cipherdata,struct alginfo * authdata)23 static inline void key_loading_opti(struct program *p,
24 struct alginfo *cipherdata,
25 struct alginfo *authdata)
26 {
27 LABEL(lbl_skip_key_loading_jump);
28 REFERENCE(ref_skip_key_loading_jump);
29
30 /* Optimisation to bypass key loading (and decryption of the keys):
31 * Jump command testing:
32 * - SHRD: Descriptor is shared
33 * - SELF: The shared descriptor is in the same DECO
34 * - BOTH: The Class 1 and 2 CHA have finished
35 * -> If this is true, we jump and skip loading of the keys as they are
36 * already loaded
37 */
38 ref_skip_key_loading_jump =
39 JUMP(p, lbl_skip_key_loading_jump, LOCAL_JUMP, ALL_TRUE,
40 SHRD | SELF | BOTH);
41
42 /* Load the keys */
43 if (cipherdata) {
44 KEY(p, KEY1, cipherdata->key_enc_flags, cipherdata->key,
45 cipherdata->keylen, INLINE_KEY(cipherdata));
46 }
47
48 if (authdata) {
49 KEY(p, KEY2, authdata->key_enc_flags, authdata->key,
50 authdata->keylen, INLINE_KEY(authdata));
51 }
52
53 /* Save the place where we want the jump to go */
54 SET_LABEL(p, lbl_skip_key_loading_jump);
55 /* Update the jump command with the position where to jump */
56 PATCH_JUMP(p, ref_skip_key_loading_jump, lbl_skip_key_loading_jump);
57 }
58
pdcp_sdap_get_sn_parameters(enum pdcp_sn_size sn_size,bool swap,uint32_t * offset,uint32_t * length,uint32_t * sn_mask)59 static inline int pdcp_sdap_get_sn_parameters(enum pdcp_sn_size sn_size,
60 bool swap, uint32_t *offset,
61 uint32_t *length,
62 uint32_t *sn_mask)
63 {
64 switch (sn_size) {
65 case PDCP_SN_SIZE_5:
66 *offset = 7;
67 *length = 1;
68 *sn_mask = (swap == false) ? PDCP_C_PLANE_SN_MASK :
69 PDCP_C_PLANE_SN_MASK_BE;
70 break;
71 case PDCP_SN_SIZE_7:
72 *offset = 7;
73 *length = 1;
74 *sn_mask = (swap == false) ? PDCP_7BIT_SN_MASK :
75 PDCP_7BIT_SN_MASK_BE;
76 break;
77 case PDCP_SN_SIZE_12:
78 *offset = 6;
79 *length = 2;
80 *sn_mask = (swap == false) ? PDCP_12BIT_SN_MASK :
81 PDCP_12BIT_SN_MASK_BE;
82 break;
83 case PDCP_SN_SIZE_15:
84 *offset = 6;
85 *length = 2;
86 *sn_mask = (swap == false) ? PDCP_U_PLANE_15BIT_SN_MASK :
87 PDCP_U_PLANE_15BIT_SN_MASK_BE;
88 break;
89 case PDCP_SN_SIZE_18:
90 *offset = 5;
91 *length = 3;
92 *sn_mask = (swap == false) ? PDCP_U_PLANE_18BIT_SN_MASK :
93 PDCP_U_PLANE_18BIT_SN_MASK_BE;
94 break;
95 default:
96 pr_err("Invalid sn_size for %s\n", __func__);
97 return -ENOTSUP;
98 }
99
100 #ifdef SDAP_SUPPORT
101 *length += SDAP_BYTE_SIZE;
102 *offset -= SDAP_BYTE_SIZE;
103 #endif
104
105 return 0;
106 }
107
pdcp_sdap_insert_no_int_op(struct program * p,bool swap __maybe_unused,struct alginfo * cipherdata,unsigned int dir,enum pdcp_sn_size sn_size)108 static inline int pdcp_sdap_insert_no_int_op(struct program *p,
109 bool swap __maybe_unused,
110 struct alginfo *cipherdata,
111 unsigned int dir,
112 enum pdcp_sn_size sn_size)
113 {
114 int op;
115 uint32_t sn_mask = 0;
116 uint32_t length = 0;
117 uint32_t offset = 0;
118
119 if (pdcp_sdap_get_sn_parameters(sn_size, swap, &offset, &length,
120 &sn_mask))
121 return -ENOTSUP;
122
123 /* Load key */
124 key_loading_opti(p, cipherdata, NULL);
125
126 SEQLOAD(p, MATH0, offset, length, 0);
127 JUMP(p, 1, LOCAL_JUMP, ALL_TRUE, CALM);
128 #ifdef SDAP_SUPPORT
129 rta_mathi(p, MATH0,
130 ((swap == true) ? MATH_FUN_RSHIFT : MATH_FUN_LSHIFT),
131 SDAP_BITS_SIZE, MATH1, 8, 0);
132 MATHB(p, MATH1, AND, sn_mask, MATH1, 8, IFB | IMMED2);
133 #else
134 MATHB(p, MATH0, AND, sn_mask, MATH1, 8, IFB | IMMED2);
135 #endif
136
137 SEQSTORE(p, MATH0, offset, length, 0);
138
139 MATHB(p, MATH1, SHLD, MATH1, MATH1, 8, 0);
140 MOVEB(p, DESCBUF, 8, MATH2, 0, 8, WAITCOMP | IMMED);
141 MATHB(p, MATH1, OR, MATH2, MATH2, 8, 0);
142
143 MATHB(p, SEQINSZ, SUB, MATH3, VSEQINSZ, 4, 0);
144 MATHB(p, SEQINSZ, SUB, MATH3, VSEQOUTSZ, 4, 0);
145
146 SEQFIFOSTORE(p, MSG, 0, 0, VLF);
147
148 op = dir == OP_TYPE_ENCAP_PROTOCOL ? DIR_ENC : DIR_DEC;
149 switch (cipherdata->algtype) {
150 case PDCP_CIPHER_TYPE_SNOW:
151 /* Copy the IV */
152 MOVEB(p, MATH2, 0, CONTEXT1, 0, 8, WAITCOMP | IMMED);
153 ALG_OPERATION(p, OP_ALG_ALGSEL_SNOW_F8, OP_ALG_AAI_F8,
154 OP_ALG_AS_INITFINAL, ICV_CHECK_DISABLE, op);
155 break;
156
157 case PDCP_CIPHER_TYPE_AES:
158 /* The first 64 bits are 0 */
159 MOVEB(p, MATH2, 0, CONTEXT1, 16, 8, WAITCOMP | IMMED);
160 ALG_OPERATION(p, OP_ALG_ALGSEL_AES, OP_ALG_AAI_CTR,
161 OP_ALG_AS_INITFINAL, ICV_CHECK_DISABLE, op);
162 break;
163
164 case PDCP_CIPHER_TYPE_ZUC:
165 if (rta_sec_era < RTA_SEC_ERA_5) {
166 pr_err("Invalid era for selected algorithm\n");
167 return -ENOTSUP;
168 }
169 /* The LSB and MSB is the same for ZUC context */
170 MOVEB(p, MATH2, 0, CONTEXT1, 0, 0x08, IMMED);
171 MOVEB(p, MATH2, 0, CONTEXT1, 0x08, 0x08, WAITCOMP | IMMED);
172
173 ALG_OPERATION(p, OP_ALG_ALGSEL_ZUCE, OP_ALG_AAI_F8,
174 OP_ALG_AS_INITFINAL, ICV_CHECK_DISABLE, op);
175 break;
176
177 default:
178 pr_err("%s: Invalid encrypt algorithm selected: %d\n",
179 "pdcp_sdap_insert_15bit_op", cipherdata->algtype);
180 return -EINVAL;
181 }
182
183 SEQFIFOLOAD(p, MSG1, 0, VLF | LAST1 | FLUSH1);
184
185 return 0;
186 }
187
188 static inline int
pdcp_sdap_insert_enc_only_op(struct program * p,bool swap __maybe_unused,struct alginfo * cipherdata,struct alginfo * authdata __maybe_unused,unsigned int dir,enum pdcp_sn_size sn_size,unsigned char era_2_sw_hfn_ovrd __maybe_unused)189 pdcp_sdap_insert_enc_only_op(struct program *p, bool swap __maybe_unused,
190 struct alginfo *cipherdata,
191 struct alginfo *authdata __maybe_unused,
192 unsigned int dir, enum pdcp_sn_size sn_size,
193 unsigned char era_2_sw_hfn_ovrd __maybe_unused)
194 {
195 uint32_t offset = 0, length = 0, sn_mask = 0;
196
197 if (pdcp_sdap_get_sn_parameters(sn_size, swap, &offset, &length,
198 &sn_mask))
199 return -ENOTSUP;
200
201 /* Load key */
202 key_loading_opti(p, cipherdata, NULL);
203
204 /* Load header */
205 SEQLOAD(p, MATH0, offset, length, 0);
206 JUMP(p, 1, LOCAL_JUMP, ALL_TRUE, CALM);
207
208 #ifdef SDAP_SUPPORT
209 rta_mathi(p, MATH0,
210 ((swap == true) ? MATH_FUN_RSHIFT : MATH_FUN_LSHIFT),
211 SDAP_BITS_SIZE, MATH1, 8, 0);
212 MATHB(p, MATH1, AND, sn_mask, MATH1, 8, IFB | IMMED2);
213 #else
214 MATHB(p, MATH0, AND, sn_mask, MATH1, 8, IFB | IMMED2);
215 #endif
216
217 /* Word (32 bit) swap */
218 MATHB(p, MATH1, SHLD, MATH1, MATH1, 8, 0);
219 /* Load words from PDB: word 02 (HFN) + word 03 (bearer_dir)*/
220 MOVEB(p, DESCBUF, 8, MATH2, 0, 8, WAITCOMP | IMMED);
221 /* Create basic IV */
222 MATHB(p, MATH1, OR, MATH2, MATH2, 8, 0);
223
224 /* Write header */
225 SEQSTORE(p, MATH0, offset, length, 0);
226
227 if (rta_sec_era > RTA_SEC_ERA_2) {
228 MATHB(p, SEQINSZ, SUB, ZERO, VSEQINSZ, 4, 0);
229 } else {
230 MATHB(p, SEQINSZ, SUB, ONE, MATH1, 4, 0);
231 MATHB(p, MATH1, ADD, ONE, VSEQINSZ, 4, 0);
232 }
233
234 if (dir == OP_TYPE_ENCAP_PROTOCOL)
235 MATHB(p, SEQINSZ, ADD, PDCP_MAC_I_LEN, VSEQOUTSZ, 4, IMMED2);
236 else
237 MATHB(p, SEQINSZ, SUB, PDCP_MAC_I_LEN, VSEQOUTSZ, 4, IMMED2);
238
239 switch (cipherdata->algtype) {
240 case PDCP_CIPHER_TYPE_SNOW:
241 MOVEB(p, MATH2, 0, CONTEXT1, 0, 8, WAITCOMP | IMMED);
242 SEQFIFOSTORE(p, MSG, 0, 0, VLF | CONT);
243 ALG_OPERATION(p, OP_ALG_ALGSEL_SNOW_F8, OP_ALG_AAI_F8,
244 OP_ALG_AS_INITFINAL, ICV_CHECK_DISABLE,
245 dir == OP_TYPE_ENCAP_PROTOCOL ? DIR_ENC :
246 DIR_DEC);
247 break;
248
249 case PDCP_CIPHER_TYPE_AES:
250 MOVEB(p, MATH2, 0, CONTEXT1, 16, 8, WAITCOMP | IMMED);
251
252 SEQFIFOSTORE(p, MSG, 0, 0, VLF | CONT);
253 ALG_OPERATION(p, OP_ALG_ALGSEL_AES, OP_ALG_AAI_CTR,
254 OP_ALG_AS_INITFINAL, ICV_CHECK_DISABLE,
255 dir == OP_TYPE_ENCAP_PROTOCOL ? DIR_ENC :
256 DIR_DEC);
257 break;
258
259 case PDCP_CIPHER_TYPE_ZUC:
260 if (rta_sec_era < RTA_SEC_ERA_5) {
261 pr_err("Invalid era for selected algorithm\n");
262 return -ENOTSUP;
263 }
264
265 MOVEB(p, MATH2, 0, CONTEXT1, 0, 0x08, IMMED);
266 MOVEB(p, MATH2, 0, CONTEXT1, 0x08, 0x08, WAITCOMP | IMMED);
267
268 SEQFIFOSTORE(p, MSG, 0, 0, VLF | CONT);
269 ALG_OPERATION(p, OP_ALG_ALGSEL_ZUCE, OP_ALG_AAI_F8,
270 OP_ALG_AS_INITFINAL, ICV_CHECK_DISABLE,
271 dir == OP_TYPE_ENCAP_PROTOCOL ? DIR_ENC :
272 DIR_DEC);
273 break;
274
275 default:
276 pr_err("%s: Invalid encrypt algorithm selected: %d\n",
277 "pdcp_sdap_insert_enc_only_op", cipherdata->algtype);
278 return -EINVAL;
279 }
280
281 if (dir == OP_TYPE_ENCAP_PROTOCOL) {
282 SEQFIFOLOAD(p, MSG1, 0, VLF);
283 FIFOLOAD(p, MSG1, PDCP_NULL_INT_MAC_I_VAL, 4,
284 LAST1 | FLUSH1 | IMMED);
285 } else {
286 SEQFIFOLOAD(p, MSG1, 0, VLF | LAST1 | FLUSH1);
287 MOVE(p, OFIFO, 0, MATH1, 4, PDCP_MAC_I_LEN, WAITCOMP | IMMED);
288 MATHB(p, MATH1, XOR, PDCP_NULL_INT_MAC_I_VAL, NONE, 4, IMMED2);
289 JUMP(p, PDCP_NULL_INT_ICV_CHECK_FAILED_STATUS, HALT_STATUS,
290 ALL_FALSE, MATH_Z);
291 }
292
293 return 0;
294 }
295
296 /*
297 * This function leverage the use of in/out snooping as SNOW and ZUC both
298 * have a class 1 and class 2 CHA. It also supports AES as cipher.
299 * Supported:
300 * - cipher:
301 * - AES-CTR
302 * - SNOW F8
303 * - ZUC F8
304 * - authentication
305 * - SNOW F8
306 * - ZUC F8
307 */
308 static inline int
pdcp_sdap_insert_snoop_op(struct program * p,bool swap __maybe_unused,struct alginfo * cipherdata,struct alginfo * authdata,unsigned int dir,enum pdcp_sn_size sn_size,unsigned char era_2_sw_hfn_ovrd __maybe_unused)309 pdcp_sdap_insert_snoop_op(struct program *p, bool swap __maybe_unused,
310 struct alginfo *cipherdata, struct alginfo *authdata,
311 unsigned int dir, enum pdcp_sn_size sn_size,
312 unsigned char era_2_sw_hfn_ovrd __maybe_unused)
313 {
314 uint32_t offset = 0, length = 0, sn_mask = 0;
315 uint32_t int_op_alg = 0;
316 uint32_t int_op_aai = 0;
317 uint32_t cipher_op_alg = 0;
318 uint32_t cipher_op_aai = 0;
319
320 if (authdata->algtype == PDCP_CIPHER_TYPE_ZUC) {
321 if (rta_sec_era < RTA_SEC_ERA_5) {
322 pr_err("Invalid era for selected algorithm\n");
323 return -ENOTSUP;
324 }
325 }
326
327 if (pdcp_sdap_get_sn_parameters(sn_size, swap, &offset, &length,
328 &sn_mask))
329 return -ENOTSUP;
330
331 if (dir == OP_TYPE_ENCAP_PROTOCOL)
332 MATHB(p, SEQINSZ, SUB, length, VSEQINSZ, 4, IMMED2);
333
334 key_loading_opti(p, cipherdata, authdata);
335
336 /* Load the PDCP header from the input data
337 * Note: SEQINSZ is decremented by length
338 */
339 SEQLOAD(p, MATH0, offset, length, 0);
340 /* Wait the SN is loaded */
341 JUMP(p, 1, LOCAL_JUMP, ALL_TRUE, CALM);
342
343 /* Pass the PDCP header to integrity block */
344 MOVEB(p, MATH0, offset, IFIFOAB2, 0, length, IMMED);
345
346 #ifdef SDAP_SUPPORT
347 /* If SDAP is enabled, the least significant byte is the SDAP header
348 * Remove it by shifting the register
349 */
350 rta_mathi(p, MATH0,
351 ((swap == true) ? MATH_FUN_RSHIFT : MATH_FUN_LSHIFT),
352 SDAP_BITS_SIZE, MATH1, 8, 0);
353 /* Mask the PDCP header to keep only the SN */
354 MATHB(p, MATH1, AND, sn_mask, MATH1, 8, IFB | IMMED2);
355 #else
356 /* Mask the PDCP header to keep only the SN */
357 MATHB(p, MATH0, AND, sn_mask, MATH1, 8, IFB | IMMED2);
358 #endif
359
360 /* Do a byte swap, it places the SN in upper part of the MATH reg */
361 MATHB(p, MATH1, SHLD, MATH1, MATH1, 8, 0);
362
363 /* Load the HFN / Beare / Dir from the PDB
364 * CAAM word are 32bit hence loading 8 byte loads 2 words:
365 * - The HFN at offset 8
366 * - The Bearer / Dir at offset 12
367 */
368 MOVEB(p, DESCBUF, 8, MATH2, 0, 8, WAITCOMP | IMMED);
369 /* Create the 4 first byte of the ICV by oring the math registers */
370 MATHB(p, MATH1, OR, MATH2, MATH1, 8, 0);
371
372 /* Set the IV of class 1 CHA */
373 if (cipherdata->algtype == PDCP_CIPHER_TYPE_AES) {
374 MOVEB(p, MATH1, 0, CONTEXT1, 16, 8, IMMED);
375 } else {
376 /* Set the IV for the confidentiality CHA */
377 MOVEB(p, MATH1, 0, CONTEXT1, 0, 8, IMMED);
378 }
379
380 /* Set the IV of class 2 CHA */
381 if (authdata->algtype == PDCP_AUTH_TYPE_ZUC) {
382 /* Set the IV for the integrity CHA */
383 MOVEB(p, MATH1, 0, CONTEXT2, 0, 8, WAITCOMP | IMMED);
384 } else if (authdata->algtype == PDCP_AUTH_TYPE_SNOW) {
385 MOVEB(p, MATH1, 0, CONTEXT2, 0, 4, WAITCOMP | IMMED);
386
387 /* Generate the bottom snow IV for integrity
388 * Note: MATH1 lowest 32bits is as follow:
389 * | bearer (5) | Dir (1) | zero (26) |
390 * the resulting math regs will be:
391 * MATH3 MATH2
392 * | zero (5) | Dir (1) | zero (26) | | Bearer (5) | zero (27) |
393 */
394 if (swap == false) {
395 MATHB(p, MATH1, AND, upper_32_bits(PDCP_BEARER_MASK),
396 MATH2, 4, IMMED2);
397 MATHB(p, MATH1, AND, lower_32_bits(PDCP_DIR_MASK),
398 MATH3, 4, IMMED2);
399 } else {
400 MATHB(p, MATH1, AND, lower_32_bits(PDCP_BEARER_MASK_BE),
401 MATH2, 4, IMMED2);
402 MATHB(p, MATH1, AND, upper_32_bits(PDCP_DIR_MASK_BE),
403 MATH3, 4, IMMED2);
404 }
405 /* Word swap MATH3 reg */
406 MATHB(p, MATH3, SHLD, MATH3, MATH3, 8, 0);
407
408 /* Don't understand, seems to be doing a move of 12 byte
409 * (read MATH2 and overread MATH3)
410 */
411 MOVEB(p, MATH2, 4, OFIFO, 0, 12, IMMED);
412
413 /* Add the rest of the snow IV to the context */
414 MOVE(p, OFIFO, 0, CONTEXT2, 4, 12, IMMED);
415 }
416
417 /* Set the variable size of data the register will write */
418 if (dir == OP_TYPE_ENCAP_PROTOCOL) {
419 /* We will add the interity data so add its length */
420 MATHI(p, SEQINSZ, ADD, PDCP_MAC_I_LEN, VSEQOUTSZ, 4, IMMED2);
421 } else {
422 /* We will check the interity data so remove its length */
423 MATHI(p, SEQINSZ, SUB, PDCP_MAC_I_LEN, VSEQOUTSZ, 4, IMMED2);
424 /* Do not take the ICV in the out-snooping configuration */
425 MATHI(p, SEQINSZ, SUB, PDCP_MAC_I_LEN, VSEQINSZ, 4, IMMED2);
426 }
427
428 /* We write the PDCP header to output*/
429 SEQSTORE(p, MATH0, offset, length, 0);
430
431 /* Definition of the flow of output data */
432 if (dir == OP_TYPE_ENCAP_PROTOCOL) {
433 /* We write data according to VSEQOUTSZ */
434 SEQFIFOSTORE(p, MSG, 0, 0, VLF);
435 } else {
436 /* We write data according to VSEQOUTSZ */
437 SEQFIFOSTORE(p, MSG, 0, 0, VLF | CONT);
438 }
439
440 /* Get parameters for authentication */
441 if (authdata->algtype == PDCP_AUTH_TYPE_ZUC) {
442 int_op_alg = OP_ALG_ALGSEL_ZUCA;
443 int_op_aai = OP_ALG_AAI_F9;
444 } else if (authdata->algtype == PDCP_AUTH_TYPE_SNOW) {
445 int_op_alg = OP_ALG_ALGSEL_SNOW_F9;
446 int_op_aai = OP_ALG_AAI_F9;
447 } else {
448 pr_err("%s no support for auth alg: %d\n", __func__,
449 authdata->algtype);
450 return -1;
451 }
452
453 /* Get parameters for ciphering */
454 if (cipherdata->algtype == PDCP_CIPHER_TYPE_ZUC) {
455 cipher_op_alg = OP_ALG_ALGSEL_ZUCE;
456 cipher_op_aai = OP_ALG_AAI_F8;
457 } else if (cipherdata->algtype == PDCP_CIPHER_TYPE_SNOW) {
458 cipher_op_alg = OP_ALG_ALGSEL_SNOW_F8;
459 cipher_op_aai = OP_ALG_AAI_F8;
460 } else if (cipherdata->algtype == PDCP_CIPHER_TYPE_AES) {
461 cipher_op_alg = OP_ALG_ALGSEL_AES;
462 cipher_op_aai = OP_ALG_AAI_CTR;
463 } else {
464 pr_err("%s no support for cipher alg: %d\n", __func__,
465 authdata->algtype);
466 return -1;
467 }
468
469 /* Configure the CHA, the class 2 CHA must be configured first or an
470 * error will be generated
471 */
472
473 /* Configure the class 2 CHA (integrity )*/
474 ALG_OPERATION(p, int_op_alg, int_op_aai, OP_ALG_AS_INITFINAL,
475 dir == OP_TYPE_ENCAP_PROTOCOL ? ICV_CHECK_DISABLE :
476 ICV_CHECK_ENABLE,
477 DIR_ENC);
478
479 /* Configure class 1 CHA (confidentiality)*/
480 ALG_OPERATION(p, cipher_op_alg, cipher_op_aai, OP_ALG_AS_INITFINAL,
481 ICV_CHECK_DISABLE,
482 dir == OP_TYPE_ENCAP_PROTOCOL ? DIR_ENC : DIR_DEC);
483
484 /* Definition of the flow of input data */
485 if (dir == OP_TYPE_ENCAP_PROTOCOL) {
486 /* We read data according to VSEQINSZ
487 * Note: we perform an in-snooping, eg the data will be read
488 * only once. they will be sent to both the integrity CHA and
489 * confidentiality CHA
490 */
491 SEQFIFOLOAD(p, MSGINSNOOP, 0, VLF | LAST2);
492
493 /* When the integrity CHA is finished, send the ICV stored in
494 * the context to the confidentiality CHA for encryption
495 */
496 MOVE(p, CONTEXT2, 0, IFIFOAB1, 0, 4, LAST1 | FLUSH1 | IMMED);
497 } else {
498 /* We read data according to VSEQINSZ
499 * Note: we perform an out-snooping, eg the data will be read
500 * only once. The will first be sent to the confidentiality
501 * CHA for decryption, then the CAAM will direct them to the
502 * integrity CHA to verify the ICV (which is at the end of the
503 * sequence)
504 */
505 SEQFIFOLOAD(p, MSGOUTSNOOP, 0, VLF | LAST2);
506
507 /* Process the ICV by class 1 CHA */
508 SEQFIFOLOAD(p, MSG1, 4, LAST1 | FLUSH1);
509
510 /* Wait for class 1 CHA to finish, the ICV data are stalling in
511 * the output fifo
512 */
513 JUMP(p, 1, LOCAL_JUMP, ALL_TRUE, CLASS1 | NOP | NIFP);
514
515 if (rta_sec_era >= RTA_SEC_ERA_6)
516 LOAD(p, 0, DCTRL, 0, LDLEN_RST_CHA_OFIFO_PTR, IMMED);
517
518 /* Save the content left in the Output FIFO (the ICV) to MATH0
519 */
520 MOVE(p, OFIFO, 0, MATH0, 0, 4, WAITCOMP | IMMED);
521
522 /* Configure a NFIFO entry to take data from the altsource
523 * and send it to the class 2 CHA as an ICV
524 */
525 NFIFOADD(p, IFIFO, ICV2, 4, LAST2);
526
527 /* Move the content of MATH0 (OFIFO offset) to altsource
528 * Note: As configured by the altsource, this will send
529 * the
530 */
531 if (rta_sec_era <= RTA_SEC_ERA_2) {
532 /* Shut off automatic Info FIFO entries */
533 LOAD(p, 0, DCTRL, LDOFF_DISABLE_AUTO_NFIFO, 0, IMMED);
534 MOVE(p, MATH0, 0, IFIFOAB2, 0, 4, WAITCOMP | IMMED);
535 } else {
536 MOVE(p, MATH0, 0, IFIFO, 0, 4, WAITCOMP | IMMED);
537 }
538 }
539
540 if (authdata->algtype == PDCP_CIPHER_TYPE_ZUC) {
541 /* Reset ZUCA mode and done interrupt
542 * Note: If it is not done, DECO generate an error: 200031ca
543 * -> ZUCA ICV failed
544 */
545 LOAD(p, CLRW_CLR_C2MODE, CLRW, 0, 4, IMMED);
546 LOAD(p, CIRQ_ZADI, ICTRL, 0, 4, IMMED);
547 }
548
549 return 0;
550 }
551
552 /* Function used when the integrity algorithm is a class 1 CHA so outsnooping
553 * is not possible
554 * Supported:
555 * - cipher:
556 * - AES-CTR
557 * - SNOW F8
558 * - ZUC F8
559 * - authentication
560 * - AES-CMAC
561 */
pdcp_sdap_insert_no_snoop_op(struct program * p,bool swap __maybe_unused,struct alginfo * cipherdata,struct alginfo * authdata,unsigned int dir,enum pdcp_sn_size sn_size,unsigned char era_2_sw_hfn_ovrd __maybe_unused)562 static inline int pdcp_sdap_insert_no_snoop_op(
563 struct program *p, bool swap __maybe_unused, struct alginfo *cipherdata,
564 struct alginfo *authdata, unsigned int dir, enum pdcp_sn_size sn_size,
565 unsigned char era_2_sw_hfn_ovrd __maybe_unused)
566 {
567 uint32_t offset = 0, length = 0, sn_mask = 0;
568 uint32_t cipher_alg_op = 0;
569 uint32_t cipher_alg_aai = 0;
570
571 if (authdata->algtype == PDCP_CIPHER_TYPE_ZUC) {
572 if (rta_sec_era < RTA_SEC_ERA_5) {
573 pr_err("Invalid era for selected algorithm\n");
574 return -ENOTSUP;
575 }
576 }
577
578 if (pdcp_sdap_get_sn_parameters(sn_size, swap, &offset, &length,
579 &sn_mask))
580 return -ENOTSUP;
581
582 SEQLOAD(p, MATH0, offset, length, 0);
583 JUMP(p, 1, LOCAL_JUMP, ALL_TRUE, CALM);
584
585 #ifdef SDAP_SUPPORT
586 rta_mathi(p, MATH0,
587 ((swap == true) ? MATH_FUN_RSHIFT : MATH_FUN_LSHIFT),
588 SDAP_BITS_SIZE, MATH1, 8, 0);
589 MATHB(p, MATH1, AND, sn_mask, MATH1, 8, IFB | IMMED2);
590 #else
591 MATHB(p, MATH0, AND, sn_mask, MATH1, 8, IFB | IMMED2);
592 #endif
593
594 MATHB(p, MATH1, SHLD, MATH1, MATH1, 8, 0);
595 MOVEB(p, DESCBUF, 8, MATH2, 0, 0x08, WAITCOMP | IMMED);
596 MATHB(p, MATH1, OR, MATH2, MATH2, 8, 0);
597
598 SEQSTORE(p, MATH0, offset, length, 0);
599
600 if (dir == OP_TYPE_ENCAP_PROTOCOL) {
601 /* Load authentication key */
602 KEY(p, KEY1, authdata->key_enc_flags, authdata->key,
603 authdata->keylen, INLINE_KEY(authdata));
604
605 /* Set the iv for AES authentication */
606 MOVEB(p, MATH2, 0, IFIFOAB1, 0, 8, IMMED);
607
608 /* Pass the header */
609 MOVEB(p, MATH0, offset, IFIFOAB1, 0, length, IMMED);
610
611 /* Configure variable size for I/O */
612 MATHB(p, SEQINSZ, SUB, ZERO, VSEQINSZ, 4, 0);
613 MATHB(p, VSEQINSZ, ADD, PDCP_MAC_I_LEN, VSEQOUTSZ, 4, IMMED2);
614
615 /* Perform the authentication */
616 ALG_OPERATION(p, OP_ALG_ALGSEL_AES, OP_ALG_AAI_CMAC,
617 OP_ALG_AS_INITFINAL, ICV_CHECK_DISABLE, DIR_DEC);
618
619 /* Configure the read of data */
620 SEQFIFOLOAD(p, MSG1, 0, VLF | LAST1 | FLUSH1);
621
622 /* Save the ICV generated */
623 MOVEB(p, CONTEXT1, 0, MATH3, 0, 4, WAITCOMP | IMMED);
624
625 /* The CHA will be reused so we need to clear it */
626 LOAD(p, CLRW_RESET_CLS1_CHA |
627 CLRW_CLR_C1KEY |
628 CLRW_CLR_C1CTX |
629 CLRW_CLR_C1ICV |
630 CLRW_CLR_C1DATAS |
631 CLRW_CLR_C1MODE,
632 CLRW, 0, 4, IMMED);
633
634 /* Load confidentiality key */
635 KEY(p, KEY1, cipherdata->key_enc_flags, cipherdata->key,
636 cipherdata->keylen, INLINE_KEY(cipherdata));
637
638 /* Load the IV for ciphering */
639 if (cipherdata->algtype == PDCP_CIPHER_TYPE_AES) {
640 MOVEB(p, MATH2, 0, CONTEXT1, 16, 8, IMMED);
641 cipher_alg_op = OP_ALG_ALGSEL_AES;
642 cipher_alg_aai = OP_ALG_AAI_CTR;
643 } else if (cipherdata->algtype == PDCP_CIPHER_TYPE_ZUC) {
644 /* Set the IV for the confidentiality CHA */
645 MOVEB(p, MATH2, 0, CONTEXT1, 0, 8, IMMED);
646 cipher_alg_op = OP_ALG_ALGSEL_ZUCE;
647 cipher_alg_aai = OP_ALG_AAI_F8;
648 } else if (cipherdata->algtype == PDCP_CIPHER_TYPE_SNOW) {
649 /* Set the IV for the confidentiality CHA */
650 MOVEB(p, MATH2, 0, CONTEXT1, 0, 8, IMMED);
651 cipher_alg_op = OP_ALG_ALGSEL_SNOW_F8;
652 cipher_alg_aai = OP_ALG_AAI_F8;
653 }
654
655 /* Rewind the pointer on input data to reread it */
656 SEQINPTR(p, 0, PDCP_NULL_MAX_FRAME_LEN, RTO);
657
658 /* Define the ciphering operation */
659 ALG_OPERATION(p, cipher_alg_op, cipher_alg_aai,
660 OP_ALG_AS_INITFINAL, ICV_CHECK_DISABLE, DIR_ENC);
661
662 /* Define the data to write */
663 SEQFIFOSTORE(p, MSG, 0, 0, VLF);
664
665 /* Skip the header which does not need to be encrypted */
666 SEQFIFOLOAD(p, SKIP, length, 0);
667
668 /* Read the rest of the data */
669 SEQFIFOLOAD(p, MSG1, 0, VLF);
670
671 /* Send the ICV stored in MATH3 for encryption */
672 MOVEB(p, MATH3, 0, IFIFOAB1, 0, 4, LAST1 | FLUSH1 | IMMED);
673 } else {
674 /* Load the IV for ciphering */
675 if (cipherdata->algtype == PDCP_CIPHER_TYPE_AES) {
676 MOVEB(p, MATH2, 0, CONTEXT1, 16, 8, IMMED);
677 cipher_alg_op = OP_ALG_ALGSEL_AES;
678 cipher_alg_aai = OP_ALG_AAI_CTR;
679 } else if (cipherdata->algtype == PDCP_CIPHER_TYPE_ZUC) {
680 /* Set the IV for the confidentiality CHA */
681 MOVEB(p, MATH2, 0, CONTEXT1, 0, 8, IMMED);
682 cipher_alg_op = OP_ALG_ALGSEL_ZUCE;
683 cipher_alg_aai = OP_ALG_AAI_F8;
684 } else if (cipherdata->algtype == PDCP_CIPHER_TYPE_SNOW) {
685 /* Set the IV for the confidentiality CHA */
686 MOVEB(p, MATH2, 0, CONTEXT1, 0, 8, IMMED);
687 cipher_alg_op = OP_ALG_ALGSEL_SNOW_F8;
688 cipher_alg_aai = OP_ALG_AAI_F8;
689 }
690 MOVEB(p, MATH2, 0, CONTEXT2, 0, 8, IMMED);
691
692 /* Read all the data */
693 MATHB(p, SEQINSZ, SUB, ZERO, VSEQINSZ, 4, 0);
694
695 /* Do not write back the ICV */
696 MATHB(p, SEQINSZ, SUB, PDCP_MAC_I_LEN, VSEQOUTSZ, 4, IMMED2);
697
698 /* Load the key for ciphering */
699 KEY(p, KEY1, cipherdata->key_enc_flags, cipherdata->key,
700 cipherdata->keylen, INLINE_KEY(cipherdata));
701
702 /* Write all the data */
703 SEQFIFOSTORE(p, MSG, 0, 0, VLF | CONT);
704
705 /* Define the ciphering algorithm */
706 ALG_OPERATION(p, cipher_alg_op, cipher_alg_aai,
707 OP_ALG_AS_INITFINAL, ICV_CHECK_DISABLE, DIR_DEC);
708
709 /* Read all the data */
710 SEQFIFOLOAD(p, MSG1, 0, VLF | LAST1 | FLUSH1);
711
712 /* Save the ICV which is stalling in output FIFO to MATH3 */
713 MOVEB(p, OFIFO, 0, MATH3, 0, 4, IMMED);
714
715 /* Reset class 1 CHA */
716 LOAD(p, CLRW_RESET_CLS1_CHA |
717 CLRW_CLR_C1KEY |
718 CLRW_CLR_C1CTX |
719 CLRW_CLR_C1ICV |
720 CLRW_CLR_C1DATAS |
721 CLRW_CLR_C1MODE,
722 CLRW, 0, 4, IMMED);
723
724 /* Load the key for authentcation */
725 KEY(p, KEY1, authdata->key_enc_flags, authdata->key,
726 authdata->keylen, INLINE_KEY(authdata));
727
728 /* Start a new sequence */
729 SEQINPTR(p, 0, 0, SOP);
730
731 /* Define the operation to verify the ICV */
732 ALG_OPERATION(p, OP_ALG_ALGSEL_AES, OP_ALG_AAI_CMAC,
733 OP_ALG_AS_INITFINAL, ICV_CHECK_ENABLE, DIR_DEC);
734
735 /* Set the variable size input */
736 MATHB(p, SEQINSZ, SUB, ZERO, VSEQINSZ, 4, 0);
737
738 MOVE(p, CONTEXT2, 0, IFIFOAB1, 0, 8, IMMED);
739
740 SEQFIFOLOAD(p, MSG1, 0, VLF | LAST1 | FLUSH1);
741
742 /* Define an NFIFO entry to load the ICV saved */
743 LOAD(p, NFIFOENTRY_STYPE_ALTSOURCE |
744 NFIFOENTRY_DEST_CLASS1 |
745 NFIFOENTRY_DTYPE_ICV |
746 NFIFOENTRY_LC1 |
747 NFIFOENTRY_FC1 | 4, NFIFO_SZL, 0, 4, IMMED);
748
749 /* Load the ICV */
750 MOVEB(p, MATH3, 0, ALTSOURCE, 0, 4, IMMED);
751 }
752
753 return 0;
754 }
755
pdcp_sdap_insert_with_int_op(struct program * p,bool swap __maybe_unused,struct alginfo * cipherdata,struct alginfo * authdata,enum pdcp_sn_size sn_size,unsigned char era_2_sw_hfn_ovrd,unsigned int dir)756 static int pdcp_sdap_insert_with_int_op(
757 struct program *p, bool swap __maybe_unused, struct alginfo *cipherdata,
758 struct alginfo *authdata, enum pdcp_sn_size sn_size,
759 unsigned char era_2_sw_hfn_ovrd, unsigned int dir)
760 {
761 static int (
762 *pdcp_cp_fp[PDCP_CIPHER_TYPE_INVALID][PDCP_AUTH_TYPE_INVALID])(
763 struct program *, bool swap, struct alginfo *, struct alginfo *,
764 unsigned int, enum pdcp_sn_size,
765 unsigned char __maybe_unused) = {
766 {
767 /* NULL */
768 pdcp_insert_cplane_null_op, /* NULL */
769 pdcp_insert_cplane_int_only_op, /* SNOW f9 */
770 pdcp_insert_cplane_int_only_op, /* AES CMAC */
771 pdcp_insert_cplane_int_only_op /* ZUC-I */
772 },
773 {
774 /* SNOW f8 */
775 pdcp_sdap_insert_enc_only_op, /* NULL */
776 pdcp_sdap_insert_snoop_op, /* SNOW f9 */
777 pdcp_sdap_insert_no_snoop_op, /* AES CMAC */
778 pdcp_sdap_insert_snoop_op /* ZUC-I */
779 },
780 {
781 /* AES CTR */
782 pdcp_sdap_insert_enc_only_op, /* NULL */
783 pdcp_sdap_insert_snoop_op, /* SNOW f9 */
784 pdcp_sdap_insert_no_snoop_op, /* AES CMAC */
785 pdcp_sdap_insert_snoop_op /* ZUC-I */
786 },
787 {
788 /* ZUC-E */
789 pdcp_sdap_insert_enc_only_op, /* NULL */
790 pdcp_sdap_insert_snoop_op, /* SNOW f9 */
791 pdcp_sdap_insert_no_snoop_op, /* AES CMAC */
792 pdcp_sdap_insert_snoop_op /* ZUC-I */
793 },
794 };
795 int err;
796
797 err = pdcp_cp_fp[cipherdata->algtype]
798 [authdata->algtype](p, swap, cipherdata, authdata, dir,
799 sn_size, era_2_sw_hfn_ovrd);
800 if (err)
801 return err;
802
803 return 0;
804 }
805
806 static inline int
cnstr_shdsc_pdcp_sdap_u_plane(uint32_t * descbuf,bool ps,bool swap,enum pdcp_sn_size sn_size,uint32_t hfn,unsigned short bearer,unsigned short direction,uint32_t hfn_threshold,struct alginfo * cipherdata,struct alginfo * authdata,unsigned char era_2_sw_hfn_ovrd,uint32_t caps_mode)807 cnstr_shdsc_pdcp_sdap_u_plane(uint32_t *descbuf,
808 bool ps,
809 bool swap,
810 enum pdcp_sn_size sn_size,
811 uint32_t hfn,
812 unsigned short bearer,
813 unsigned short direction,
814 uint32_t hfn_threshold,
815 struct alginfo *cipherdata,
816 struct alginfo *authdata,
817 unsigned char era_2_sw_hfn_ovrd,
818 uint32_t caps_mode)
819 {
820 struct program prg;
821 struct program *p = &prg;
822 int err;
823 enum pdb_type_e pdb_type;
824 static enum rta_share_type
825 desc_share[PDCP_CIPHER_TYPE_INVALID][PDCP_AUTH_TYPE_INVALID] = {
826 {
827 /* NULL */
828 SHR_WAIT, /* NULL */
829 SHR_ALWAYS, /* SNOW f9 */
830 SHR_ALWAYS, /* AES CMAC */
831 SHR_ALWAYS /* ZUC-I */
832 },
833 {
834 /* SNOW f8 */
835 SHR_ALWAYS, /* NULL */
836 SHR_ALWAYS, /* SNOW f9 */
837 SHR_WAIT, /* AES CMAC */
838 SHR_WAIT /* ZUC-I */
839 },
840 {
841 /* AES CTR */
842 SHR_ALWAYS, /* NULL */
843 SHR_ALWAYS, /* SNOW f9 */
844 SHR_ALWAYS, /* AES CMAC */
845 SHR_WAIT /* ZUC-I */
846 },
847 {
848 /* ZUC-E */
849 SHR_ALWAYS, /* NULL */
850 SHR_WAIT, /* SNOW f9 */
851 SHR_WAIT, /* AES CMAC */
852 SHR_WAIT /* ZUC-I */
853 },
854 };
855
856 LABEL(pdb_end);
857
858 /* Check HFN override for ERA 2 */
859 if (rta_sec_era != RTA_SEC_ERA_2 && era_2_sw_hfn_ovrd) {
860 pr_err("Cannot select SW HFN ovrd for other era than 2");
861 return -EINVAL;
862 }
863
864 /* Check the confidentiality algorithm is supported by the code */
865 switch (cipherdata->algtype) {
866 case PDCP_CIPHER_TYPE_NULL:
867 case PDCP_CIPHER_TYPE_SNOW:
868 case PDCP_CIPHER_TYPE_AES:
869 case PDCP_CIPHER_TYPE_ZUC:
870 break;
871 default:
872 pr_err("Cipher algorithm not supported: %d\n",
873 cipherdata->algtype);
874 return -ENOTSUP;
875 }
876
877 /* Check the authentication algorithm is supported by the code */
878 if (authdata) {
879 switch (authdata->algtype) {
880 case PDCP_AUTH_TYPE_NULL:
881 case PDCP_AUTH_TYPE_SNOW:
882 case PDCP_AUTH_TYPE_AES:
883 case PDCP_AUTH_TYPE_ZUC:
884 break;
885 default:
886 pr_err("Auth algorithm not supported: %d\n",
887 authdata->algtype);
888 return -ENOTSUP;
889 }
890 }
891
892 /* Check the Sequence Number size is supported by the code */
893 switch (sn_size) {
894 case PDCP_SN_SIZE_5:
895 case PDCP_SN_SIZE_7:
896 case PDCP_SN_SIZE_12:
897 case PDCP_SN_SIZE_15:
898 case PDCP_SN_SIZE_18:
899 break;
900 default:
901 pr_err("SN size not supported: %d\n", sn_size);
902 return -ENOTSUP;
903 }
904
905 /* Check that we are not performing ZUC algo on old platforms */
906 if (cipherdata->algtype == PDCP_CIPHER_TYPE_ZUC &&
907 rta_sec_era < RTA_SEC_ERA_5) {
908 pr_err("ZUC algorithm not supported for era: %d\n",
909 rta_sec_era);
910 return -ENOTSUP;
911 }
912
913 /* Initialize the program */
914 PROGRAM_CNTXT_INIT(p, descbuf, 0);
915
916 if (swap)
917 PROGRAM_SET_BSWAP(p);
918
919 if (ps)
920 PROGRAM_SET_36BIT_ADDR(p);
921
922 /* Select the shared descriptor sharing mode */
923 if (authdata)
924 SHR_HDR(p, desc_share[cipherdata->algtype][authdata->algtype],
925 0, 0);
926 else
927 SHR_HDR(p, SHR_ALWAYS, 0, 0);
928
929 /* Construct the PDB */
930 pdb_type = cnstr_pdcp_u_plane_pdb(p, sn_size, hfn, bearer, direction,
931 hfn_threshold, cipherdata, authdata);
932 if (pdb_type == PDCP_PDB_TYPE_INVALID) {
933 pr_err("Error creating PDCP UPlane PDB\n");
934 return -EINVAL;
935 }
936 SET_LABEL(p, pdb_end);
937
938 /* Inser the HFN override operation */
939 err = insert_hfn_ov_op(p, sn_size, pdb_type, era_2_sw_hfn_ovrd);
940 if (err)
941 return err;
942
943 /* Create the descriptor */
944 if (!authdata) {
945 if (cipherdata->algtype == PDCP_CIPHER_TYPE_NULL) {
946 insert_copy_frame_op(p, cipherdata,
947 OP_TYPE_ENCAP_PROTOCOL);
948 } else {
949 err = pdcp_sdap_insert_no_int_op(p, swap, cipherdata,
950 caps_mode,
951 sn_size);
952 if (err) {
953 pr_err("Fail pdcp_sdap_insert_no_int_op\n");
954 return err;
955 }
956 }
957 } else {
958 err = pdcp_sdap_insert_with_int_op(p, swap, cipherdata,
959 authdata, sn_size,
960 era_2_sw_hfn_ovrd,
961 caps_mode);
962 if (err) {
963 pr_err("Fail pdcp_sdap_insert_with_int_op\n");
964 return err;
965 }
966 }
967
968 PATCH_HDR(p, 0, pdb_end);
969
970 return PROGRAM_FINALIZE(p);
971 }
972
973 /**
974 * cnstr_shdsc_pdcp_sdap_u_plane_encap - Function for creating a PDCP-SDAP
975 * User Plane encapsulation descriptor.
976 * @descbuf: pointer to buffer for descriptor construction
977 * @ps: if 36/40bit addressing is desired, this parameter must be true
978 * @swap: must be true when core endianness doesn't match SEC endianness
979 * @sn_size: selects Sequence Number Size: 7/12/15 bits
980 * @hfn: starting Hyper Frame Number to be used together with the SN from the
981 * PDCP frames.
982 * @bearer: radio bearer ID
983 * @direction: the direction of the PDCP frame (UL/DL)
984 * @hfn_threshold: HFN value that once reached triggers a warning from SEC that
985 * keys should be renegotiated at the earliest convenience.
986 * @cipherdata: pointer to block cipher transform definitions
987 * Valid algorithm values are those from cipher_type_pdcp enum.
988 * @era_2_sw_hfn_ovrd: if software HFN override mechanism is desired for
989 * this descriptor. Note: Can only be used for
990 * SEC ERA 2.
991 *
992 * Return: size of descriptor written in words or negative number on error.
993 * Once the function returns, the value of this parameter can be used
994 * for reclaiming the space that wasn't used for the descriptor.
995 *
996 * Note: descbuf must be large enough to contain a full 256 byte long
997 * descriptor; after the function returns, by subtracting the actual number of
998 * bytes used, the user can reuse the remaining buffer space for other purposes.
999 */
1000 static inline int
cnstr_shdsc_pdcp_sdap_u_plane_encap(uint32_t * descbuf,bool ps,bool swap,enum pdcp_sn_size sn_size,uint32_t hfn,unsigned short bearer,unsigned short direction,uint32_t hfn_threshold,struct alginfo * cipherdata,struct alginfo * authdata,unsigned char era_2_sw_hfn_ovrd)1001 cnstr_shdsc_pdcp_sdap_u_plane_encap(uint32_t *descbuf,
1002 bool ps,
1003 bool swap,
1004 enum pdcp_sn_size sn_size,
1005 uint32_t hfn,
1006 unsigned short bearer,
1007 unsigned short direction,
1008 uint32_t hfn_threshold,
1009 struct alginfo *cipherdata,
1010 struct alginfo *authdata,
1011 unsigned char era_2_sw_hfn_ovrd)
1012 {
1013 return cnstr_shdsc_pdcp_sdap_u_plane(descbuf, ps, swap, sn_size,
1014 hfn, bearer, direction, hfn_threshold, cipherdata,
1015 authdata, era_2_sw_hfn_ovrd, OP_TYPE_ENCAP_PROTOCOL);
1016 }
1017
1018 /**
1019 * cnstr_shdsc_pdcp_sdap_u_plane_decap - Function for creating a PDCP-SDAP
1020 * User Plane decapsulation descriptor.
1021 * @descbuf: pointer to buffer for descriptor construction
1022 * @ps: if 36/40bit addressing is desired, this parameter must be true
1023 * @swap: must be true when core endianness doesn't match SEC endianness
1024 * @sn_size: selects Sequence Number Size: 7/12/15 bits
1025 * @hfn: starting Hyper Frame Number to be used together with the SN from the
1026 * PDCP frames.
1027 * @bearer: radio bearer ID
1028 * @direction: the direction of the PDCP frame (UL/DL)
1029 * @hfn_threshold: HFN value that once reached triggers a warning from SEC that
1030 * keys should be renegotiated at the earliest convenience.
1031 * @cipherdata: pointer to block cipher transform definitions
1032 * Valid algorithm values are those from cipher_type_pdcp enum.
1033 * @era_2_sw_hfn_ovrd: if software HFN override mechanism is desired for
1034 * this descriptor. Note: Can only be used for
1035 * SEC ERA 2.
1036 *
1037 * Return: size of descriptor written in words or negative number on error.
1038 * Once the function returns, the value of this parameter can be used
1039 * for reclaiming the space that wasn't used for the descriptor.
1040 *
1041 * Note: descbuf must be large enough to contain a full 256 byte long
1042 * descriptor; after the function returns, by subtracting the actual number of
1043 * bytes used, the user can reuse the remaining buffer space for other purposes.
1044 */
1045 static inline int
cnstr_shdsc_pdcp_sdap_u_plane_decap(uint32_t * descbuf,bool ps,bool swap,enum pdcp_sn_size sn_size,uint32_t hfn,unsigned short bearer,unsigned short direction,uint32_t hfn_threshold,struct alginfo * cipherdata,struct alginfo * authdata,unsigned char era_2_sw_hfn_ovrd)1046 cnstr_shdsc_pdcp_sdap_u_plane_decap(uint32_t *descbuf,
1047 bool ps,
1048 bool swap,
1049 enum pdcp_sn_size sn_size,
1050 uint32_t hfn,
1051 unsigned short bearer,
1052 unsigned short direction,
1053 uint32_t hfn_threshold,
1054 struct alginfo *cipherdata,
1055 struct alginfo *authdata,
1056 unsigned char era_2_sw_hfn_ovrd)
1057 {
1058 return cnstr_shdsc_pdcp_sdap_u_plane(descbuf, ps, swap, sn_size, hfn,
1059 bearer, direction, hfn_threshold, cipherdata, authdata,
1060 era_2_sw_hfn_ovrd, OP_TYPE_DECAP_PROTOCOL);
1061 }
1062
1063 #endif /* __DESC_SDAP_H__ */
1064