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