Branch data Line data Source code
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
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 : 0 : if ((cipher_alg != PDCP_CIPHER_TYPE_NULL) &&
36 [ # # ]: 0 : (auth_alg != PDCP_AUTH_TYPE_NULL))
37 : : return 2;
38 : : else
39 : : return 0;
40 : : }
41 : :
42 : 0 : 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 : 0 : JUMP(p, lbl_skip_key_loading_jump, LOCAL_JUMP, ALL_TRUE,
59 : : SHRD | SELF | BOTH);
60 : :
61 : : /* Load the keys */
62 [ # # ]: 0 : if (cipherdata) {
63 : 0 : KEY(p, KEY1, cipherdata->key_enc_flags, cipherdata->key,
64 : : cipherdata->keylen, INLINE_KEY(cipherdata));
65 : : }
66 : :
67 [ # # ]: 0 : if (authdata) {
68 : 0 : 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 : 0 : PATCH_JUMP(p, ref_skip_key_loading_jump, lbl_skip_key_loading_jump);
76 : 0 : }
77 : :
78 : 0 : 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 [ # # # # : 0 : switch (sn_size) {
# # ]
84 : 0 : case PDCP_SN_SIZE_5:
85 : 0 : *offset = 7;
86 : 0 : *length = 1;
87 [ # # ]: 0 : *sn_mask = (swap == false) ? PDCP_C_PLANE_SN_MASK :
88 : : PDCP_C_PLANE_SN_MASK_BE;
89 : 0 : break;
90 : 0 : case PDCP_SN_SIZE_7:
91 : 0 : *offset = 7;
92 : 0 : *length = 1;
93 [ # # ]: 0 : *sn_mask = (swap == false) ? PDCP_7BIT_SN_MASK :
94 : : PDCP_7BIT_SN_MASK_BE;
95 : 0 : break;
96 : 0 : case PDCP_SN_SIZE_12:
97 : 0 : *offset = 6;
98 : 0 : *length = 2;
99 [ # # ]: 0 : *sn_mask = (swap == false) ? PDCP_12BIT_SN_MASK :
100 : : PDCP_12BIT_SN_MASK_BE;
101 : 0 : break;
102 : 0 : case PDCP_SN_SIZE_15:
103 : 0 : *offset = 6;
104 : 0 : *length = 2;
105 [ # # ]: 0 : *sn_mask = (swap == false) ? PDCP_U_PLANE_15BIT_SN_MASK :
106 : : PDCP_U_PLANE_15BIT_SN_MASK_BE;
107 : 0 : break;
108 : 0 : case PDCP_SN_SIZE_18:
109 : 0 : *offset = 5;
110 : 0 : *length = 3;
111 [ # # ]: 0 : *sn_mask = (swap == false) ? PDCP_U_PLANE_18BIT_SN_MASK :
112 : : PDCP_U_PLANE_18BIT_SN_MASK_BE;
113 : 0 : break;
114 : 0 : default:
115 : 0 : pr_err("Invalid sn_size for %s\n", __func__);
116 : 0 : return -ENOTSUP;
117 : : }
118 : :
119 : : #ifdef SDAP_SUPPORT
120 : 0 : *length += SDAP_BYTE_SIZE;
121 : 0 : *offset -= SDAP_BYTE_SIZE;
122 : : #endif
123 : :
124 : 0 : return 0;
125 : : }
126 : :
127 : 0 : 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 : 0 : uint32_t sn_mask = 0;
136 : 0 : uint32_t length = 0;
137 : 0 : uint32_t offset = 0;
138 : : int hfn_bearer_dir_offset_in_descbuf =
139 : : (pdb_type == PDCP_PDB_TYPE_FULL_PDB) ?
140 [ # # ]: 0 : FULL_PDB_DESCBUF_HFN_BEARER_DIR_OFFSET :
141 : : REDUCED_PDB_DESCBUF_HFN_BEARER_DIR_OFFSET;
142 : :
143 [ # # ]: 0 : if (pdcp_sdap_get_sn_parameters(sn_size, swap, &offset, &length,
144 : : &sn_mask))
145 : : return -ENOTSUP;
146 : :
147 : : /* Load key */
148 : 0 : key_loading_opti(p, cipherdata, NULL);
149 : :
150 : 0 : SEQLOAD(p, MATH0, offset, length, 0);
151 : 0 : JUMP(p, 1, LOCAL_JUMP, ALL_TRUE, CALM);
152 : : #ifdef SDAP_SUPPORT
153 [ # # ]: 0 : rta_mathi(p, MATH0,
154 : : ((swap == true) ? MATH_FUN_RSHIFT : MATH_FUN_LSHIFT),
155 : : SDAP_BITS_SIZE, MATH1, 8, 0);
156 : 0 : 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 : 0 : SEQSTORE(p, MATH0, offset, length, 0);
162 : :
163 : 0 : MATHB(p, MATH1, SHLD, MATH1, MATH1, 8, 0);
164 : 0 : MOVEB(p, DESCBUF, hfn_bearer_dir_offset_in_descbuf,
165 : : MATH2, 0, 8, WAITCOMP | IMMED);
166 : 0 : MATHB(p, MATH1, OR, MATH2, MATH2, 8, 0);
167 : :
168 : 0 : MATHB(p, SEQINSZ, SUB, MATH3, VSEQINSZ, 4, 0);
169 : 0 : MATHB(p, SEQINSZ, SUB, MATH3, VSEQOUTSZ, 4, 0);
170 : :
171 : 0 : SEQFIFOSTORE(p, MSG, 0, 0, VLF);
172 : :
173 : 0 : op = dir == OP_TYPE_ENCAP_PROTOCOL ? DIR_ENC : DIR_DEC;
174 [ # # # # ]: 0 : switch (cipherdata->algtype) {
175 : 0 : case PDCP_CIPHER_TYPE_SNOW:
176 : : /* Copy the IV */
177 : 0 : MOVEB(p, MATH2, 0, CONTEXT1, 0, 8, WAITCOMP | IMMED);
178 : 0 : ALG_OPERATION(p, OP_ALG_ALGSEL_SNOW_F8, OP_ALG_AAI_F8,
179 : : OP_ALG_AS_INITFINAL, ICV_CHECK_DISABLE, op);
180 : 0 : break;
181 : :
182 : 0 : case PDCP_CIPHER_TYPE_AES:
183 : : /* The first 64 bits are 0 */
184 : 0 : MOVEB(p, MATH2, 0, CONTEXT1, 16, 8, WAITCOMP | IMMED);
185 : 0 : ALG_OPERATION(p, OP_ALG_ALGSEL_AES, OP_ALG_AAI_CTR,
186 : : OP_ALG_AS_INITFINAL, ICV_CHECK_DISABLE, op);
187 : 0 : break;
188 : :
189 : 0 : case PDCP_CIPHER_TYPE_ZUC:
190 : : /* The LSB and MSB is the same for ZUC context */
191 : 0 : MOVEB(p, MATH2, 0, CONTEXT1, 0, 0x08, IMMED);
192 : 0 : MOVEB(p, MATH2, 0, CONTEXT1, 0x08, 0x08, WAITCOMP | IMMED);
193 : :
194 : 0 : ALG_OPERATION(p, OP_ALG_ALGSEL_ZUCE, OP_ALG_AAI_F8,
195 : : OP_ALG_AS_INITFINAL, ICV_CHECK_DISABLE, op);
196 : 0 : break;
197 : :
198 : 0 : default:
199 : 0 : pr_err("%s: Invalid encrypt algorithm selected: %d\n",
200 : : "pdcp_sdap_insert_15bit_op", cipherdata->algtype);
201 : 0 : return -EINVAL;
202 : : }
203 : :
204 : 0 : SEQFIFOLOAD(p, MSG1, 0, VLF | LAST1 | FLUSH1);
205 : :
206 : 0 : return 0;
207 : : }
208 : :
209 : : static inline int
210 : 0 : 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 : 0 : 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 [ # # ]: 0 : FULL_PDB_DESCBUF_HFN_BEARER_DIR_OFFSET :
220 : : REDUCED_PDB_DESCBUF_HFN_BEARER_DIR_OFFSET;
221 : :
222 [ # # ]: 0 : if (pdcp_sdap_get_sn_parameters(sn_size, swap, &offset, &length,
223 : : &sn_mask))
224 : : return -ENOTSUP;
225 : :
226 : : /* Load key */
227 : 0 : key_loading_opti(p, cipherdata, NULL);
228 : :
229 : : /* Load header */
230 : 0 : SEQLOAD(p, MATH0, offset, length, 0);
231 : 0 : JUMP(p, 1, LOCAL_JUMP, ALL_TRUE, CALM);
232 : :
233 : : #ifdef SDAP_SUPPORT
234 [ # # ]: 0 : rta_mathi(p, MATH0,
235 : : ((swap == true) ? MATH_FUN_RSHIFT : MATH_FUN_LSHIFT),
236 : : SDAP_BITS_SIZE, MATH1, 8, 0);
237 : 0 : 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 : 0 : MATHB(p, MATH1, SHLD, MATH1, MATH1, 8, 0);
244 : : /* Load words from PDB: word 02 (HFN) + word 03 (bearer_dir)*/
245 : 0 : MOVEB(p, DESCBUF, hfn_bearer_dir_offset_in_descbuf,
246 : : MATH2, 0, 8, WAITCOMP | IMMED);
247 : : /* Create basic IV */
248 : 0 : MATHB(p, MATH1, OR, MATH2, MATH2, 8, 0);
249 : :
250 : : /* Write header */
251 : 0 : SEQSTORE(p, MATH0, offset, length, 0);
252 : :
253 : 0 : MATHB(p, SEQINSZ, SUB, ZERO, VSEQINSZ, 4, 0);
254 : :
255 [ # # ]: 0 : if (dir == OP_TYPE_ENCAP_PROTOCOL)
256 : 0 : MATHB(p, SEQINSZ, ADD, PDCP_MAC_I_LEN, VSEQOUTSZ, 4, IMMED2);
257 : : else
258 : 0 : MATHB(p, SEQINSZ, SUB, PDCP_MAC_I_LEN, VSEQOUTSZ, 4, IMMED2);
259 : :
260 [ # # # # ]: 0 : switch (cipherdata->algtype) {
261 : 0 : case PDCP_CIPHER_TYPE_SNOW:
262 : 0 : MOVEB(p, MATH2, 0, CONTEXT1, 0, 8, WAITCOMP | IMMED);
263 : 0 : SEQFIFOSTORE(p, MSG, 0, 0, VLF | CONT);
264 : 0 : 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 : 0 : break;
269 : :
270 : 0 : case PDCP_CIPHER_TYPE_AES:
271 : 0 : MOVEB(p, MATH2, 0, CONTEXT1, 16, 8, WAITCOMP | IMMED);
272 : :
273 : 0 : SEQFIFOSTORE(p, MSG, 0, 0, VLF | CONT);
274 : 0 : 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 : 0 : break;
279 : :
280 : 0 : case PDCP_CIPHER_TYPE_ZUC:
281 : 0 : MOVEB(p, MATH2, 0, CONTEXT1, 0, 0x08, IMMED);
282 : 0 : MOVEB(p, MATH2, 0, CONTEXT1, 0x08, 0x08, WAITCOMP | IMMED);
283 : :
284 : 0 : SEQFIFOSTORE(p, MSG, 0, 0, VLF | CONT);
285 : 0 : 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 : 0 : break;
290 : :
291 : 0 : default:
292 : 0 : pr_err("%s: Invalid encrypt algorithm selected: %d\n",
293 : : "pdcp_sdap_insert_enc_only_op", cipherdata->algtype);
294 : 0 : return -EINVAL;
295 : : }
296 : :
297 [ # # ]: 0 : if (dir == OP_TYPE_ENCAP_PROTOCOL) {
298 : 0 : SEQFIFOLOAD(p, MSG1, 0, VLF);
299 : 0 : FIFOLOAD(p, MSG1, PDCP_NULL_INT_MAC_I_VAL, 4,
300 : : LAST1 | FLUSH1 | IMMED);
301 : : } else {
302 : 0 : SEQFIFOLOAD(p, MSG1, 0, VLF | LAST1 | FLUSH1);
303 : 0 : MOVE(p, OFIFO, 0, MATH1, 4, PDCP_MAC_I_LEN, WAITCOMP | IMMED);
304 : 0 : MATHB(p, MATH1, XOR, PDCP_NULL_INT_MAC_I_VAL, NONE, 4, IMMED2);
305 : 0 : 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
325 : 0 : 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 : 0 : 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 [ # # ]: 0 : FULL_PDB_DESCBUF_HFN_BEARER_DIR_OFFSET :
338 : : REDUCED_PDB_DESCBUF_HFN_BEARER_DIR_OFFSET;
339 : :
340 [ # # ]: 0 : if (pdcp_sdap_get_sn_parameters(sn_size, swap, &offset, &length,
341 : : &sn_mask))
342 : : return -ENOTSUP;
343 : :
344 [ # # ]: 0 : if (dir == OP_TYPE_ENCAP_PROTOCOL)
345 : 0 : MATHB(p, SEQINSZ, SUB, length, VSEQINSZ, 4, IMMED2);
346 : :
347 : 0 : 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 : 0 : SEQLOAD(p, MATH0, offset, length, 0);
353 : : /* Wait the SN is loaded */
354 : 0 : JUMP(p, 1, LOCAL_JUMP, ALL_TRUE, CALM);
355 : :
356 : : /* Pass the PDCP header to integrity block */
357 : 0 : 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 [ # # ]: 0 : 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 : 0 : 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 : 0 : 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 : 0 : 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 : 0 : MATHB(p, MATH1, OR, MATH2, MATH1, 8, 0);
386 : :
387 : : /* Set the IV of class 1 CHA */
388 [ # # ]: 0 : if (cipherdata->algtype == PDCP_CIPHER_TYPE_AES) {
389 : 0 : MOVEB(p, MATH1, 0, CONTEXT1, 16, 8, IMMED);
390 : : } else {
391 : : /* Set the IV for the confidentiality CHA */
392 : 0 : MOVEB(p, MATH1, 0, CONTEXT1, 0, 8, IMMED);
393 : : }
394 : :
395 : : /* Set the IV of class 2 CHA */
396 [ # # ]: 0 : if (authdata->algtype == PDCP_AUTH_TYPE_ZUC) {
397 : : /* Set the IV for the integrity CHA */
398 : 0 : MOVEB(p, MATH1, 0, CONTEXT2, 0, 8, WAITCOMP | IMMED);
399 [ # # ]: 0 : } else if (authdata->algtype == PDCP_AUTH_TYPE_SNOW) {
400 : 0 : 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 [ # # ]: 0 : if (swap == false) {
410 : 0 : MATHB(p, MATH1, AND, upper_32_bits(PDCP_BEARER_MASK),
411 : : MATH2, 4, IMMED2);
412 : 0 : MATHB(p, MATH1, AND, lower_32_bits(PDCP_DIR_MASK),
413 : : MATH3, 4, IMMED2);
414 : : } else {
415 : 0 : MATHB(p, MATH1, AND, lower_32_bits(PDCP_BEARER_MASK_BE),
416 : : MATH2, 4, IMMED2);
417 : 0 : MATHB(p, MATH1, AND, upper_32_bits(PDCP_DIR_MASK_BE),
418 : : MATH3, 4, IMMED2);
419 : : }
420 : : /* Word swap MATH3 reg */
421 : 0 : 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 : 0 : MOVEB(p, MATH2, 4, OFIFO, 0, 12, IMMED);
427 : :
428 : : /* Add the rest of the snow IV to the context */
429 : 0 : MOVE(p, OFIFO, 0, CONTEXT2, 4, 12, IMMED);
430 : : }
431 : :
432 : : /* Set the variable size of data the register will write */
433 [ # # ]: 0 : if (dir == OP_TYPE_ENCAP_PROTOCOL) {
434 : : /* We will add the integrity data so add its length */
435 : 0 : 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 : 0 : MATHI(p, SEQINSZ, SUB, PDCP_MAC_I_LEN, VSEQOUTSZ, 4, IMMED2);
439 : : /* Do not take the ICV in the out-snooping configuration */
440 : 0 : MATHI(p, SEQINSZ, SUB, PDCP_MAC_I_LEN, VSEQINSZ, 4, IMMED2);
441 : : }
442 : :
443 : : /* We write the PDCP header to output*/
444 : 0 : SEQSTORE(p, MATH0, offset, length, 0);
445 : :
446 : : /* Definition of the flow of output data */
447 [ # # ]: 0 : if (dir == OP_TYPE_ENCAP_PROTOCOL) {
448 : : /* We write data according to VSEQOUTSZ */
449 : 0 : SEQFIFOSTORE(p, MSG, 0, 0, VLF);
450 : : } else {
451 : : /* We write data according to VSEQOUTSZ */
452 : 0 : SEQFIFOSTORE(p, MSG, 0, 0, VLF | CONT);
453 : : }
454 : :
455 : : /* Get parameters for authentication */
456 [ # # ]: 0 : if (authdata->algtype == PDCP_AUTH_TYPE_ZUC) {
457 : : int_op_alg = OP_ALG_ALGSEL_ZUCA;
458 : : int_op_aai = OP_ALG_AAI_F9;
459 [ # # ]: 0 : } 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 : 0 : pr_err("%s no support for auth alg: %d\n", __func__,
464 : : authdata->algtype);
465 : 0 : return -1;
466 : : }
467 : :
468 : : /* Get parameters for ciphering */
469 [ # # ]: 0 : if (cipherdata->algtype == PDCP_CIPHER_TYPE_ZUC) {
470 : : cipher_op_alg = OP_ALG_ALGSEL_ZUCE;
471 : : cipher_op_aai = OP_ALG_AAI_F8;
472 [ # # ]: 0 : } 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 [ # # ]: 0 : } 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 : 0 : pr_err("%s no support for cipher alg: %d\n", __func__,
480 : : authdata->algtype);
481 : 0 : 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 : 0 : 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 : 0 : 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 [ # # ]: 0 : 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 : 0 : 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 : 0 : 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 : 0 : SEQFIFOLOAD(p, MSGOUTSNOOP, 0, VLF | LAST2);
521 : :
522 : : /* Process the ICV by class 1 CHA */
523 : 0 : 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 : 0 : JUMP(p, 1, LOCAL_JUMP, ALL_TRUE, CLASS1 | NOP | NIFP);
529 : :
530 : 0 : 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 : 0 : 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 : 0 : 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 : 0 : MOVE(p, MATH0, 0, IFIFO, 0, 4, WAITCOMP | IMMED);
546 : : }
547 : :
548 [ # # ]: 0 : 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 : 0 : LOAD(p, CLRW_CLR_C2MODE, CLRW, 0, 4, IMMED);
554 : 0 : 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 : : */
570 : 0 : 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 : 0 : 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 [ # # ]: 0 : FULL_PDB_DESCBUF_HFN_BEARER_DIR_OFFSET :
581 : : REDUCED_PDB_DESCBUF_HFN_BEARER_DIR_OFFSET;
582 : :
583 [ # # ]: 0 : if (pdcp_sdap_get_sn_parameters(sn_size, swap, &offset, &length,
584 : : &sn_mask))
585 : : return -ENOTSUP;
586 : :
587 : 0 : SEQLOAD(p, MATH0, offset, length, 0);
588 : 0 : JUMP(p, 1, LOCAL_JUMP, ALL_TRUE, CALM);
589 : :
590 : : #ifdef SDAP_SUPPORT
591 [ # # ]: 0 : rta_mathi(p, MATH0,
592 : : ((swap == true) ? MATH_FUN_RSHIFT : MATH_FUN_LSHIFT),
593 : : SDAP_BITS_SIZE, MATH1, 8, 0);
594 : 0 : 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 : 0 : MATHB(p, MATH1, SHLD, MATH1, MATH1, 8, 0);
600 : 0 : MOVEB(p, DESCBUF, hfn_bearer_dir_offset_in_descbuf,
601 : : MATH2, 0, 0x08, WAITCOMP | IMMED);
602 : 0 : MATHB(p, MATH1, OR, MATH2, MATH2, 8, 0);
603 : :
604 : 0 : SEQSTORE(p, MATH0, offset, length, 0);
605 : :
606 [ # # ]: 0 : if (dir == OP_TYPE_ENCAP_PROTOCOL) {
607 : : /* Load authentication key */
608 : 0 : KEY(p, KEY1, authdata->key_enc_flags, authdata->key,
609 : : authdata->keylen, INLINE_KEY(authdata));
610 : :
611 : : /* Set the iv for AES authentication */
612 : 0 : MOVEB(p, MATH2, 0, IFIFOAB1, 0, 8, IMMED);
613 : :
614 : : /* Pass the header */
615 : 0 : MOVEB(p, MATH0, offset, IFIFOAB1, 0, length, IMMED);
616 : :
617 : : /* Configure variable size for I/O */
618 : 0 : MATHB(p, SEQINSZ, SUB, ZERO, VSEQINSZ, 4, 0);
619 : 0 : MATHB(p, VSEQINSZ, ADD, PDCP_MAC_I_LEN, VSEQOUTSZ, 4, IMMED2);
620 : :
621 : : /* Perform the authentication */
622 : 0 : 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 : 0 : SEQFIFOLOAD(p, MSG1, 0, VLF | LAST1 | FLUSH1);
627 : :
628 : : /* Save the ICV generated */
629 : 0 : 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 : 0 : JUMP(p, 1, LOCAL_JUMP, ALL_TRUE, CALM);
635 : : /* The CHA will be reused so we need to clear it */
636 : 0 : 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 : 0 : KEY(p, KEY1, cipherdata->key_enc_flags, cipherdata->key,
646 : : cipherdata->keylen, INLINE_KEY(cipherdata));
647 : :
648 : : /* Load the IV for ciphering */
649 [ # # ]: 0 : if (cipherdata->algtype == PDCP_CIPHER_TYPE_AES) {
650 : 0 : 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 [ # # ]: 0 : } else if (cipherdata->algtype == PDCP_CIPHER_TYPE_ZUC) {
654 : : /* Set the IV for the confidentiality CHA */
655 : 0 : 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 [ # # ]: 0 : } else if (cipherdata->algtype == PDCP_CIPHER_TYPE_SNOW) {
659 : : /* Set the IV for the confidentiality CHA */
660 : 0 : 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 : 0 : SEQINPTR(p, 0, PDCP_NULL_MAX_FRAME_LEN, RTO);
667 : :
668 : : /* Define the ciphering operation */
669 : 0 : 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 : 0 : SEQFIFOSTORE(p, MSG, 0, 0, VLF);
674 : :
675 : : /* Skip the header which does not need to be encrypted */
676 : 0 : SEQFIFOLOAD(p, SKIP, length, 0);
677 : :
678 : : /* Read the rest of the data */
679 : 0 : SEQFIFOLOAD(p, MSG1, 0, VLF);
680 : :
681 : : /* Send the ICV stored in MATH3 for encryption */
682 : 0 : MOVEB(p, MATH3, 0, IFIFOAB1, 0, 4, LAST1 | FLUSH1 | IMMED);
683 : : } else {
684 : : /* Load the IV for ciphering */
685 [ # # ]: 0 : if (cipherdata->algtype == PDCP_CIPHER_TYPE_AES) {
686 : 0 : 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 [ # # ]: 0 : } else if (cipherdata->algtype == PDCP_CIPHER_TYPE_ZUC) {
690 : : /* Set the IV for the confidentiality CHA */
691 : 0 : 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 [ # # ]: 0 : } else if (cipherdata->algtype == PDCP_CIPHER_TYPE_SNOW) {
695 : : /* Set the IV for the confidentiality CHA */
696 : 0 : 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 : 0 : MOVEB(p, MATH2, 0, CONTEXT2, 0, 8, IMMED);
701 : :
702 : : /* Read all the data */
703 : 0 : MATHB(p, SEQINSZ, SUB, ZERO, VSEQINSZ, 4, 0);
704 : :
705 : : /* Do not write back the ICV */
706 : 0 : MATHB(p, SEQINSZ, SUB, PDCP_MAC_I_LEN, VSEQOUTSZ, 4, IMMED2);
707 : :
708 : : /* Load the key for ciphering */
709 : 0 : KEY(p, KEY1, cipherdata->key_enc_flags, cipherdata->key,
710 : : cipherdata->keylen, INLINE_KEY(cipherdata));
711 : :
712 : : /* Write all the data */
713 : 0 : SEQFIFOSTORE(p, MSG, 0, 0, VLF | CONT);
714 : :
715 : : /* Define the ciphering algorithm */
716 : 0 : 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 : 0 : SEQFIFOLOAD(p, MSG1, 0, VLF | LAST1 | FLUSH1);
721 : :
722 : : /* Save the ICV which is stalling in output FIFO to MATH3 */
723 : 0 : 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 : 0 : JUMP(p, 1, LOCAL_JUMP, ALL_TRUE, CALM);
729 : : /* Reset class 1 CHA */
730 : 0 : 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 : 0 : KEY(p, KEY1, authdata->key_enc_flags, authdata->key,
740 : : authdata->keylen, INLINE_KEY(authdata));
741 : :
742 : : /* Start a new sequence */
743 : 0 : SEQINPTR(p, 0, 0, SOP);
744 : :
745 : : /* Define the operation to verify the ICV */
746 : 0 : 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 : 0 : MATHB(p, SEQINSZ, SUB, ZERO, VSEQINSZ, 4, 0);
751 : :
752 : 0 : MOVE(p, CONTEXT2, 0, IFIFOAB1, 0, 8, IMMED);
753 : :
754 : 0 : SEQFIFOLOAD(p, MSG1, 0, VLF | LAST1 | FLUSH1);
755 : :
756 : : /* Define an NFIFO entry to load the ICV saved */
757 : 0 : 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 : 0 : MOVEB(p, MATH3, 0, ALTSOURCE, 0, 4, IMMED);
765 : : }
766 : :
767 : : return 0;
768 : : }
769 : :
770 : : static inline int
771 : 0 : 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 : 0 : return pdcp_insert_cplane_null_op(p, swap, cipherdata, authdata, dir,
780 : : sn_size);
781 : : }
782 : :
783 : : static inline int
784 : 0 : 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 : 0 : return pdcp_insert_cplane_int_only_op(p, swap, cipherdata, authdata,
793 : : dir, sn_size);
794 : : }
795 : :
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 : 0 : err = pdcp_cp_fp[cipherdata->algtype]
838 : 0 : [authdata->algtype](p, swap, cipherdata, authdata, dir,
839 : : sn_size, pdb_type);
840 [ # # ]: 0 : if (err)
841 : : return err;
842 : :
843 : : return 0;
844 : : }
845 : :
846 : : static inline int
847 : 0 : 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 [ # # ]: 0 : 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 : 0 : default:
905 : 0 : pr_err("Cipher algorithm not supported: %d\n",
906 : : cipherdata->algtype);
907 : 0 : return -ENOTSUP;
908 : : }
909 : :
910 : : /* Check the authentication algorithm is supported by the code */
911 [ # # ]: 0 : if (authdata) {
912 [ # # ]: 0 : 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 : 0 : default:
919 : 0 : pr_err("Auth algorithm not supported: %d\n",
920 : : authdata->algtype);
921 : 0 : return -ENOTSUP;
922 : : }
923 : : }
924 : :
925 : : /* Check the Sequence Number size is supported by the code */
926 [ # # ]: 0 : 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 : 0 : default:
934 : 0 : pr_err("SN size not supported: %d\n", sn_size);
935 : 0 : return -ENOTSUP;
936 : : }
937 : :
938 : : /* Initialize the program */
939 : : PROGRAM_CNTXT_INIT(p, descbuf, 0);
940 : :
941 [ # # ]: 0 : if (swap)
942 : : PROGRAM_SET_BSWAP(p);
943 : :
944 [ # # ]: 0 : if (ps)
945 : : PROGRAM_SET_36BIT_ADDR(p);
946 : :
947 : : /* Select the shared descriptor sharing mode */
948 [ # # ]: 0 : if (authdata)
949 : 0 : SHR_HDR(p, desc_share[cipherdata->algtype][authdata->algtype],
950 : : 0, 0);
951 : : else
952 : 0 : SHR_HDR(p, SHR_WAIT, 0, 0);
953 : :
954 : : /* Construct the PDB */
955 : 0 : pdb_type = cnstr_pdcp_u_plane_pdb(p, sn_size, hfn, bearer, direction,
956 : : hfn_threshold, cipherdata, authdata);
957 [ # # ]: 0 : if (pdb_type == PDCP_PDB_TYPE_INVALID) {
958 : 0 : pr_err("Error creating PDCP UPlane PDB\n");
959 : 0 : return -EINVAL;
960 : : }
961 : : SET_LABEL(p, pdb_end);
962 : :
963 : : /* Inser the HFN override operation */
964 : 0 : err = insert_hfn_ov_op(p, sn_size, pdb_type, false);
965 [ # # ]: 0 : if (err)
966 : : return err;
967 : :
968 : : /* Create the descriptor */
969 [ # # ]: 0 : if (!authdata) {
970 [ # # ]: 0 : if (cipherdata->algtype == PDCP_CIPHER_TYPE_NULL) {
971 : 0 : insert_copy_frame_op(p, cipherdata,
972 : : OP_TYPE_ENCAP_PROTOCOL);
973 : : } else {
974 : 0 : err = pdcp_sdap_insert_no_int_op(p, swap, cipherdata,
975 : : caps_mode,
976 : : sn_size, pdb_type);
977 [ # # ]: 0 : if (err) {
978 : 0 : pr_err("Fail pdcp_sdap_insert_no_int_op\n");
979 : 0 : return err;
980 : : }
981 : : }
982 : : } else {
983 : 0 : err = pdcp_sdap_insert_with_int_op(p, swap, cipherdata,
984 : : authdata, sn_size,
985 : : caps_mode, pdb_type);
986 : : if (err) {
987 : 0 : pr_err("Fail pdcp_sdap_insert_with_int_op\n");
988 : 0 : return err;
989 : : }
990 : : }
991 : :
992 : 0 : PATCH_HDR(p, 0, pdb_end);
993 : :
994 : 0 : 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
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 : 0 : 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
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 : 0 : 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__ */
|