1 /* SPDX-License-Identifier: BSD-3-Clause
2 * Copyright 2020-2022 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 /* The CHA will be reused so we need to clear it */
632 LOAD(p, CLRW_RESET_CLS1_CHA |
633 CLRW_CLR_C1KEY |
634 CLRW_CLR_C1CTX |
635 CLRW_CLR_C1ICV |
636 CLRW_CLR_C1DATAS |
637 CLRW_CLR_C1MODE,
638 CLRW, 0, 4, IMMED);
639
640 /* Load confidentiality key */
641 KEY(p, KEY1, cipherdata->key_enc_flags, cipherdata->key,
642 cipherdata->keylen, INLINE_KEY(cipherdata));
643
644 /* Load the IV for ciphering */
645 if (cipherdata->algtype == PDCP_CIPHER_TYPE_AES) {
646 MOVEB(p, MATH2, 0, CONTEXT1, 16, 8, IMMED);
647 cipher_alg_op = OP_ALG_ALGSEL_AES;
648 cipher_alg_aai = OP_ALG_AAI_CTR;
649 } else if (cipherdata->algtype == PDCP_CIPHER_TYPE_ZUC) {
650 /* Set the IV for the confidentiality CHA */
651 MOVEB(p, MATH2, 0, CONTEXT1, 0, 8, IMMED);
652 cipher_alg_op = OP_ALG_ALGSEL_ZUCE;
653 cipher_alg_aai = OP_ALG_AAI_F8;
654 } else if (cipherdata->algtype == PDCP_CIPHER_TYPE_SNOW) {
655 /* Set the IV for the confidentiality CHA */
656 MOVEB(p, MATH2, 0, CONTEXT1, 0, 8, IMMED);
657 cipher_alg_op = OP_ALG_ALGSEL_SNOW_F8;
658 cipher_alg_aai = OP_ALG_AAI_F8;
659 }
660
661 /* Rewind the pointer on input data to reread it */
662 SEQINPTR(p, 0, PDCP_NULL_MAX_FRAME_LEN, RTO);
663
664 /* Define the ciphering operation */
665 ALG_OPERATION(p, cipher_alg_op, cipher_alg_aai,
666 OP_ALG_AS_INITFINAL, ICV_CHECK_DISABLE, DIR_ENC);
667
668 /* Define the data to write */
669 SEQFIFOSTORE(p, MSG, 0, 0, VLF);
670
671 /* Skip the header which does not need to be encrypted */
672 SEQFIFOLOAD(p, SKIP, length, 0);
673
674 /* Read the rest of the data */
675 SEQFIFOLOAD(p, MSG1, 0, VLF);
676
677 /* Send the ICV stored in MATH3 for encryption */
678 MOVEB(p, MATH3, 0, IFIFOAB1, 0, 4, LAST1 | FLUSH1 | IMMED);
679 } else {
680 /* Load the IV for ciphering */
681 if (cipherdata->algtype == PDCP_CIPHER_TYPE_AES) {
682 MOVEB(p, MATH2, 0, CONTEXT1, 16, 8, IMMED);
683 cipher_alg_op = OP_ALG_ALGSEL_AES;
684 cipher_alg_aai = OP_ALG_AAI_CTR;
685 } else if (cipherdata->algtype == PDCP_CIPHER_TYPE_ZUC) {
686 /* Set the IV for the confidentiality CHA */
687 MOVEB(p, MATH2, 0, CONTEXT1, 0, 8, IMMED);
688 cipher_alg_op = OP_ALG_ALGSEL_ZUCE;
689 cipher_alg_aai = OP_ALG_AAI_F8;
690 } else if (cipherdata->algtype == PDCP_CIPHER_TYPE_SNOW) {
691 /* Set the IV for the confidentiality CHA */
692 MOVEB(p, MATH2, 0, CONTEXT1, 0, 8, IMMED);
693 cipher_alg_op = OP_ALG_ALGSEL_SNOW_F8;
694 cipher_alg_aai = OP_ALG_AAI_F8;
695 }
696 MOVEB(p, MATH2, 0, CONTEXT2, 0, 8, IMMED);
697
698 /* Read all the data */
699 MATHB(p, SEQINSZ, SUB, ZERO, VSEQINSZ, 4, 0);
700
701 /* Do not write back the ICV */
702 MATHB(p, SEQINSZ, SUB, PDCP_MAC_I_LEN, VSEQOUTSZ, 4, IMMED2);
703
704 /* Load the key for ciphering */
705 KEY(p, KEY1, cipherdata->key_enc_flags, cipherdata->key,
706 cipherdata->keylen, INLINE_KEY(cipherdata));
707
708 /* Write all the data */
709 SEQFIFOSTORE(p, MSG, 0, 0, VLF | CONT);
710
711 /* Define the ciphering algorithm */
712 ALG_OPERATION(p, cipher_alg_op, cipher_alg_aai,
713 OP_ALG_AS_INITFINAL, ICV_CHECK_DISABLE, DIR_DEC);
714
715 /* Read all the data */
716 SEQFIFOLOAD(p, MSG1, 0, VLF | LAST1 | FLUSH1);
717
718 /* Save the ICV which is stalling in output FIFO to MATH3 */
719 MOVEB(p, OFIFO, 0, MATH3, 0, 4, IMMED);
720
721 /* Reset class 1 CHA */
722 LOAD(p, CLRW_RESET_CLS1_CHA |
723 CLRW_CLR_C1KEY |
724 CLRW_CLR_C1CTX |
725 CLRW_CLR_C1ICV |
726 CLRW_CLR_C1DATAS |
727 CLRW_CLR_C1MODE,
728 CLRW, 0, 4, IMMED);
729
730 /* Load the key for authentication */
731 KEY(p, KEY1, authdata->key_enc_flags, authdata->key,
732 authdata->keylen, INLINE_KEY(authdata));
733
734 /* Start a new sequence */
735 SEQINPTR(p, 0, 0, SOP);
736
737 /* Define the operation to verify the ICV */
738 ALG_OPERATION(p, OP_ALG_ALGSEL_AES, OP_ALG_AAI_CMAC,
739 OP_ALG_AS_INITFINAL, ICV_CHECK_ENABLE, DIR_DEC);
740
741 /* Set the variable size input */
742 MATHB(p, SEQINSZ, SUB, ZERO, VSEQINSZ, 4, 0);
743
744 MOVE(p, CONTEXT2, 0, IFIFOAB1, 0, 8, IMMED);
745
746 SEQFIFOLOAD(p, MSG1, 0, VLF | LAST1 | FLUSH1);
747
748 /* Define an NFIFO entry to load the ICV saved */
749 LOAD(p, NFIFOENTRY_STYPE_ALTSOURCE |
750 NFIFOENTRY_DEST_CLASS1 |
751 NFIFOENTRY_DTYPE_ICV |
752 NFIFOENTRY_LC1 |
753 NFIFOENTRY_FC1 | 4, NFIFO_SZL, 0, 4, IMMED);
754
755 /* Load the ICV */
756 MOVEB(p, MATH3, 0, ALTSOURCE, 0, 4, IMMED);
757 }
758
759 return 0;
760 }
761
762 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)763 pdcp_sdap_insert_cplane_null_op(struct program *p,
764 bool swap __maybe_unused,
765 struct alginfo *cipherdata,
766 struct alginfo *authdata,
767 unsigned int dir,
768 enum pdcp_sn_size sn_size,
769 enum pdb_type_e pdb_type __maybe_unused)
770 {
771 return pdcp_insert_cplane_null_op(p, swap, cipherdata, authdata, dir,
772 sn_size);
773 }
774
775 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)776 pdcp_sdap_insert_cplane_int_only_op(struct program *p,
777 bool swap __maybe_unused,
778 struct alginfo *cipherdata,
779 struct alginfo *authdata,
780 unsigned int dir,
781 enum pdcp_sn_size sn_size,
782 enum pdb_type_e pdb_type __maybe_unused)
783 {
784 return pdcp_insert_cplane_int_only_op(p, swap, cipherdata, authdata,
785 dir, sn_size);
786 }
787
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)788 static int pdcp_sdap_insert_with_int_op(
789 struct program *p, bool swap __maybe_unused, struct alginfo *cipherdata,
790 struct alginfo *authdata, enum pdcp_sn_size sn_size,
791 unsigned int dir,
792 enum pdb_type_e pdb_type)
793 {
794 static int (
795 *pdcp_cp_fp[PDCP_CIPHER_TYPE_INVALID][PDCP_AUTH_TYPE_INVALID])(
796 struct program *, bool swap, struct alginfo *, struct alginfo *,
797 unsigned int dir, enum pdcp_sn_size, enum pdb_type_e pdb_type) = {
798 {
799 /* NULL */
800 pdcp_sdap_insert_cplane_null_op, /* NULL */
801 pdcp_sdap_insert_cplane_int_only_op, /* SNOW f9 */
802 pdcp_sdap_insert_cplane_int_only_op, /* AES CMAC */
803 pdcp_sdap_insert_cplane_int_only_op /* ZUC-I */
804 },
805 {
806 /* SNOW f8 */
807 pdcp_sdap_insert_enc_only_op, /* NULL */
808 pdcp_sdap_insert_snoop_op, /* SNOW f9 */
809 pdcp_sdap_insert_no_snoop_op, /* AES CMAC */
810 pdcp_sdap_insert_snoop_op /* ZUC-I */
811 },
812 {
813 /* AES CTR */
814 pdcp_sdap_insert_enc_only_op, /* NULL */
815 pdcp_sdap_insert_snoop_op, /* SNOW f9 */
816 pdcp_sdap_insert_no_snoop_op, /* AES CMAC */
817 pdcp_sdap_insert_snoop_op /* ZUC-I */
818 },
819 {
820 /* ZUC-E */
821 pdcp_sdap_insert_enc_only_op, /* NULL */
822 pdcp_sdap_insert_snoop_op, /* SNOW f9 */
823 pdcp_sdap_insert_no_snoop_op, /* AES CMAC */
824 pdcp_sdap_insert_snoop_op /* ZUC-I */
825 },
826 };
827 int err;
828
829 err = pdcp_cp_fp[cipherdata->algtype]
830 [authdata->algtype](p, swap, cipherdata, authdata, dir,
831 sn_size, pdb_type);
832 if (err)
833 return err;
834
835 return 0;
836 }
837
838 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)839 cnstr_shdsc_pdcp_sdap_u_plane(uint32_t *descbuf,
840 bool ps,
841 bool swap,
842 enum pdcp_sn_size sn_size,
843 uint32_t hfn,
844 unsigned short bearer,
845 unsigned short direction,
846 uint32_t hfn_threshold,
847 struct alginfo *cipherdata,
848 struct alginfo *authdata,
849 uint32_t caps_mode)
850 {
851 struct program prg;
852 struct program *p = &prg;
853 int err;
854 enum pdb_type_e pdb_type;
855 static enum rta_share_type
856 desc_share[PDCP_CIPHER_TYPE_INVALID][PDCP_AUTH_TYPE_INVALID] = {
857 {
858 /* NULL */
859 SHR_WAIT, /* NULL */
860 SHR_WAIT, /* SNOW f9 */
861 SHR_WAIT, /* AES CMAC */
862 SHR_WAIT /* ZUC-I */
863 },
864 {
865 /* SNOW f8 */
866 SHR_WAIT, /* NULL */
867 SHR_WAIT, /* SNOW f9 */
868 SHR_WAIT, /* AES CMAC */
869 SHR_WAIT /* ZUC-I */
870 },
871 {
872 /* AES CTR */
873 SHR_WAIT, /* NULL */
874 SHR_WAIT, /* SNOW f9 */
875 SHR_WAIT, /* AES CMAC */
876 SHR_WAIT /* ZUC-I */
877 },
878 {
879 /* ZUC-E */
880 SHR_WAIT, /* NULL */
881 SHR_WAIT, /* SNOW f9 */
882 SHR_WAIT, /* AES CMAC */
883 SHR_WAIT /* ZUC-I */
884 },
885 };
886
887 LABEL(pdb_end);
888
889 /* Check the confidentiality algorithm is supported by the code */
890 switch (cipherdata->algtype) {
891 case PDCP_CIPHER_TYPE_NULL:
892 case PDCP_CIPHER_TYPE_SNOW:
893 case PDCP_CIPHER_TYPE_AES:
894 case PDCP_CIPHER_TYPE_ZUC:
895 break;
896 default:
897 pr_err("Cipher algorithm not supported: %d\n",
898 cipherdata->algtype);
899 return -ENOTSUP;
900 }
901
902 /* Check the authentication algorithm is supported by the code */
903 if (authdata) {
904 switch (authdata->algtype) {
905 case PDCP_AUTH_TYPE_NULL:
906 case PDCP_AUTH_TYPE_SNOW:
907 case PDCP_AUTH_TYPE_AES:
908 case PDCP_AUTH_TYPE_ZUC:
909 break;
910 default:
911 pr_err("Auth algorithm not supported: %d\n",
912 authdata->algtype);
913 return -ENOTSUP;
914 }
915 }
916
917 /* Check the Sequence Number size is supported by the code */
918 switch (sn_size) {
919 case PDCP_SN_SIZE_5:
920 case PDCP_SN_SIZE_7:
921 case PDCP_SN_SIZE_12:
922 case PDCP_SN_SIZE_15:
923 case PDCP_SN_SIZE_18:
924 break;
925 default:
926 pr_err("SN size not supported: %d\n", sn_size);
927 return -ENOTSUP;
928 }
929
930 /* Initialize the program */
931 PROGRAM_CNTXT_INIT(p, descbuf, 0);
932
933 if (swap)
934 PROGRAM_SET_BSWAP(p);
935
936 if (ps)
937 PROGRAM_SET_36BIT_ADDR(p);
938
939 /* Select the shared descriptor sharing mode */
940 if (authdata)
941 SHR_HDR(p, desc_share[cipherdata->algtype][authdata->algtype],
942 0, 0);
943 else
944 SHR_HDR(p, SHR_WAIT, 0, 0);
945
946 /* Construct the PDB */
947 pdb_type = cnstr_pdcp_u_plane_pdb(p, sn_size, hfn, bearer, direction,
948 hfn_threshold, cipherdata, authdata);
949 if (pdb_type == PDCP_PDB_TYPE_INVALID) {
950 pr_err("Error creating PDCP UPlane PDB\n");
951 return -EINVAL;
952 }
953 SET_LABEL(p, pdb_end);
954
955 /* Inser the HFN override operation */
956 err = insert_hfn_ov_op(p, sn_size, pdb_type, false);
957 if (err)
958 return err;
959
960 /* Create the descriptor */
961 if (!authdata) {
962 if (cipherdata->algtype == PDCP_CIPHER_TYPE_NULL) {
963 insert_copy_frame_op(p, cipherdata,
964 OP_TYPE_ENCAP_PROTOCOL);
965 } else {
966 err = pdcp_sdap_insert_no_int_op(p, swap, cipherdata,
967 caps_mode,
968 sn_size, pdb_type);
969 if (err) {
970 pr_err("Fail pdcp_sdap_insert_no_int_op\n");
971 return err;
972 }
973 }
974 } else {
975 err = pdcp_sdap_insert_with_int_op(p, swap, cipherdata,
976 authdata, sn_size,
977 caps_mode, pdb_type);
978 if (err) {
979 pr_err("Fail pdcp_sdap_insert_with_int_op\n");
980 return err;
981 }
982 }
983
984 PATCH_HDR(p, 0, pdb_end);
985
986 return PROGRAM_FINALIZE(p);
987 }
988
989 /**
990 * cnstr_shdsc_pdcp_sdap_u_plane_encap - Function for creating a PDCP-SDAP
991 * User Plane encapsulation descriptor.
992 * @descbuf: pointer to buffer for descriptor construction
993 * @ps: if 36/40bit addressing is desired, this parameter must be true
994 * @swap: must be true when core endianness doesn't match SEC endianness
995 * @sn_size: selects Sequence Number Size: 7/12/15 bits
996 * @hfn: starting Hyper Frame Number to be used together with the SN from the
997 * PDCP frames.
998 * @bearer: radio bearer ID
999 * @direction: the direction of the PDCP frame (UL/DL)
1000 * @hfn_threshold: HFN value that once reached triggers a warning from SEC that
1001 * keys should be renegotiated at the earliest convenience.
1002 * @cipherdata: pointer to block cipher transform definitions
1003 * Valid algorithm values are those from cipher_type_pdcp enum.
1004 *
1005 * Return: size of descriptor written in words or negative number on error.
1006 * Once the function returns, the value of this parameter can be used
1007 * for reclaiming the space that wasn't used for the descriptor.
1008 *
1009 * Note: descbuf must be large enough to contain a full 256 byte long
1010 * descriptor; after the function returns, by subtracting the actual number of
1011 * bytes used, the user can reuse the remaining buffer space for other purposes.
1012 */
1013 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)1014 cnstr_shdsc_pdcp_sdap_u_plane_encap(uint32_t *descbuf,
1015 bool ps,
1016 bool swap,
1017 enum pdcp_sn_size sn_size,
1018 uint32_t hfn,
1019 unsigned short bearer,
1020 unsigned short direction,
1021 uint32_t hfn_threshold,
1022 struct alginfo *cipherdata,
1023 struct alginfo *authdata)
1024 {
1025 return cnstr_shdsc_pdcp_sdap_u_plane(descbuf, ps, swap, sn_size,
1026 hfn, bearer, direction, hfn_threshold, cipherdata,
1027 authdata, OP_TYPE_ENCAP_PROTOCOL);
1028 }
1029
1030 /**
1031 * cnstr_shdsc_pdcp_sdap_u_plane_decap - Function for creating a PDCP-SDAP
1032 * User Plane decapsulation descriptor.
1033 * @descbuf: pointer to buffer for descriptor construction
1034 * @ps: if 36/40bit addressing is desired, this parameter must be true
1035 * @swap: must be true when core endianness doesn't match SEC endianness
1036 * @sn_size: selects Sequence Number Size: 7/12/15 bits
1037 * @hfn: starting Hyper Frame Number to be used together with the SN from the
1038 * PDCP frames.
1039 * @bearer: radio bearer ID
1040 * @direction: the direction of the PDCP frame (UL/DL)
1041 * @hfn_threshold: HFN value that once reached triggers a warning from SEC that
1042 * keys should be renegotiated at the earliest convenience.
1043 * @cipherdata: pointer to block cipher transform definitions
1044 * Valid algorithm values are those from cipher_type_pdcp enum.
1045 *
1046 * Return: size of descriptor written in words or negative number on error.
1047 * Once the function returns, the value of this parameter can be used
1048 * for reclaiming the space that wasn't used for the descriptor.
1049 *
1050 * Note: descbuf must be large enough to contain a full 256 byte long
1051 * descriptor; after the function returns, by subtracting the actual number of
1052 * bytes used, the user can reuse the remaining buffer space for other purposes.
1053 */
1054 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)1055 cnstr_shdsc_pdcp_sdap_u_plane_decap(uint32_t *descbuf,
1056 bool ps,
1057 bool swap,
1058 enum pdcp_sn_size sn_size,
1059 uint32_t hfn,
1060 unsigned short bearer,
1061 unsigned short direction,
1062 uint32_t hfn_threshold,
1063 struct alginfo *cipherdata,
1064 struct alginfo *authdata)
1065 {
1066 return cnstr_shdsc_pdcp_sdap_u_plane(descbuf, ps, swap, sn_size, hfn,
1067 bearer, direction, hfn_threshold, cipherdata, authdata,
1068 OP_TYPE_DECAP_PROTOCOL);
1069 }
1070
1071 #endif /* __DESC_SDAP_H__ */
1072