Branch data Line data Source code
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
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 : : /* The CHA will be reused so we need to clear it */
632 : 0 : 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 [ # # ]: 0 : KEY(p, KEY1, cipherdata->key_enc_flags, cipherdata->key,
642 : : cipherdata->keylen, INLINE_KEY(cipherdata));
643 : :
644 : : /* Load the IV for ciphering */
645 [ # # ]: 0 : if (cipherdata->algtype == PDCP_CIPHER_TYPE_AES) {
646 : 0 : 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 [ # # ]: 0 : } else if (cipherdata->algtype == PDCP_CIPHER_TYPE_ZUC) {
650 : : /* Set the IV for the confidentiality CHA */
651 : 0 : 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 [ # # ]: 0 : } else if (cipherdata->algtype == PDCP_CIPHER_TYPE_SNOW) {
655 : : /* Set the IV for the confidentiality CHA */
656 : 0 : 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 : 0 : SEQINPTR(p, 0, PDCP_NULL_MAX_FRAME_LEN, RTO);
663 : :
664 : : /* Define the ciphering operation */
665 : 0 : 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 : 0 : SEQFIFOSTORE(p, MSG, 0, 0, VLF);
670 : :
671 : : /* Skip the header which does not need to be encrypted */
672 : 0 : SEQFIFOLOAD(p, SKIP, length, 0);
673 : :
674 : : /* Read the rest of the data */
675 : 0 : SEQFIFOLOAD(p, MSG1, 0, VLF);
676 : :
677 : : /* Send the ICV stored in MATH3 for encryption */
678 : 0 : MOVEB(p, MATH3, 0, IFIFOAB1, 0, 4, LAST1 | FLUSH1 | IMMED);
679 : : } else {
680 : : /* Load the IV for ciphering */
681 [ # # ]: 0 : if (cipherdata->algtype == PDCP_CIPHER_TYPE_AES) {
682 : 0 : 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 [ # # ]: 0 : } else if (cipherdata->algtype == PDCP_CIPHER_TYPE_ZUC) {
686 : : /* Set the IV for the confidentiality CHA */
687 : 0 : 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 [ # # ]: 0 : } else if (cipherdata->algtype == PDCP_CIPHER_TYPE_SNOW) {
691 : : /* Set the IV for the confidentiality CHA */
692 : 0 : 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 : 0 : MOVEB(p, MATH2, 0, CONTEXT2, 0, 8, IMMED);
697 : :
698 : : /* Read all the data */
699 : 0 : MATHB(p, SEQINSZ, SUB, ZERO, VSEQINSZ, 4, 0);
700 : :
701 : : /* Do not write back the ICV */
702 : 0 : MATHB(p, SEQINSZ, SUB, PDCP_MAC_I_LEN, VSEQOUTSZ, 4, IMMED2);
703 : :
704 : : /* Load the key for ciphering */
705 [ # # ]: 0 : KEY(p, KEY1, cipherdata->key_enc_flags, cipherdata->key,
706 : : cipherdata->keylen, INLINE_KEY(cipherdata));
707 : :
708 : : /* Write all the data */
709 : 0 : SEQFIFOSTORE(p, MSG, 0, 0, VLF | CONT);
710 : :
711 : : /* Define the ciphering algorithm */
712 : 0 : 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 : 0 : SEQFIFOLOAD(p, MSG1, 0, VLF | LAST1 | FLUSH1);
717 : :
718 : : /* Save the ICV which is stalling in output FIFO to MATH3 */
719 : 0 : MOVEB(p, OFIFO, 0, MATH3, 0, 4, IMMED);
720 : :
721 : : /* Reset class 1 CHA */
722 : 0 : 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 [ # # ]: 0 : KEY(p, KEY1, authdata->key_enc_flags, authdata->key,
732 : : authdata->keylen, INLINE_KEY(authdata));
733 : :
734 : : /* Start a new sequence */
735 : 0 : SEQINPTR(p, 0, 0, SOP);
736 : :
737 : : /* Define the operation to verify the ICV */
738 : 0 : 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 : 0 : MATHB(p, SEQINSZ, SUB, ZERO, VSEQINSZ, 4, 0);
743 : :
744 : 0 : MOVE(p, CONTEXT2, 0, IFIFOAB1, 0, 8, IMMED);
745 : :
746 : 0 : SEQFIFOLOAD(p, MSG1, 0, VLF | LAST1 | FLUSH1);
747 : :
748 : : /* Define an NFIFO entry to load the ICV saved */
749 : 0 : 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 : 0 : MOVEB(p, MATH3, 0, ALTSOURCE, 0, 4, IMMED);
757 : : }
758 : :
759 : : return 0;
760 : : }
761 : :
762 : : static inline int
763 : 0 : 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 : 0 : return pdcp_insert_cplane_null_op(p, swap, cipherdata, authdata, dir,
772 : : sn_size);
773 : : }
774 : :
775 : : static inline int
776 : 0 : 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 : 0 : return pdcp_insert_cplane_int_only_op(p, swap, cipherdata, authdata,
785 : : dir, sn_size);
786 : : }
787 : :
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 : 0 : err = pdcp_cp_fp[cipherdata->algtype]
830 : 0 : [authdata->algtype](p, swap, cipherdata, authdata, dir,
831 : : sn_size, pdb_type);
832 [ # # ]: 0 : if (err)
833 : : return err;
834 : :
835 : : return 0;
836 : : }
837 : :
838 : : static inline int
839 : 0 : 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 [ # # ]: 0 : 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 : 0 : default:
897 : 0 : pr_err("Cipher algorithm not supported: %d\n",
898 : : cipherdata->algtype);
899 : 0 : return -ENOTSUP;
900 : : }
901 : :
902 : : /* Check the authentication algorithm is supported by the code */
903 [ # # ]: 0 : if (authdata) {
904 [ # # ]: 0 : 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 : 0 : default:
911 : 0 : pr_err("Auth algorithm not supported: %d\n",
912 : : authdata->algtype);
913 : 0 : return -ENOTSUP;
914 : : }
915 : : }
916 : :
917 : : /* Check the Sequence Number size is supported by the code */
918 [ # # ]: 0 : 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 : 0 : default:
926 : 0 : pr_err("SN size not supported: %d\n", sn_size);
927 : 0 : return -ENOTSUP;
928 : : }
929 : :
930 : : /* Initialize the program */
931 : : PROGRAM_CNTXT_INIT(p, descbuf, 0);
932 : :
933 [ # # ]: 0 : if (swap)
934 : : PROGRAM_SET_BSWAP(p);
935 : :
936 [ # # ]: 0 : if (ps)
937 : : PROGRAM_SET_36BIT_ADDR(p);
938 : :
939 : : /* Select the shared descriptor sharing mode */
940 [ # # ]: 0 : if (authdata)
941 : 0 : SHR_HDR(p, desc_share[cipherdata->algtype][authdata->algtype],
942 : : 0, 0);
943 : : else
944 : 0 : SHR_HDR(p, SHR_WAIT, 0, 0);
945 : :
946 : : /* Construct the PDB */
947 : 0 : pdb_type = cnstr_pdcp_u_plane_pdb(p, sn_size, hfn, bearer, direction,
948 : : hfn_threshold, cipherdata, authdata);
949 [ # # ]: 0 : if (pdb_type == PDCP_PDB_TYPE_INVALID) {
950 : 0 : pr_err("Error creating PDCP UPlane PDB\n");
951 : 0 : return -EINVAL;
952 : : }
953 : : SET_LABEL(p, pdb_end);
954 : :
955 : : /* Inser the HFN override operation */
956 : 0 : err = insert_hfn_ov_op(p, sn_size, pdb_type, false);
957 [ # # ]: 0 : if (err)
958 : : return err;
959 : :
960 : : /* Create the descriptor */
961 [ # # ]: 0 : if (!authdata) {
962 [ # # ]: 0 : if (cipherdata->algtype == PDCP_CIPHER_TYPE_NULL) {
963 : 0 : insert_copy_frame_op(p, cipherdata,
964 : : OP_TYPE_ENCAP_PROTOCOL);
965 : : } else {
966 : 0 : err = pdcp_sdap_insert_no_int_op(p, swap, cipherdata,
967 : : caps_mode,
968 : : sn_size, pdb_type);
969 [ # # ]: 0 : if (err) {
970 : 0 : pr_err("Fail pdcp_sdap_insert_no_int_op\n");
971 : 0 : return err;
972 : : }
973 : : }
974 : : } else {
975 : 0 : err = pdcp_sdap_insert_with_int_op(p, swap, cipherdata,
976 : : authdata, sn_size,
977 : : caps_mode, pdb_type);
978 : : if (err) {
979 : 0 : pr_err("Fail pdcp_sdap_insert_with_int_op\n");
980 : 0 : return err;
981 : : }
982 : : }
983 : :
984 : 0 : PATCH_HDR(p, 0, pdb_end);
985 : :
986 : 0 : 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
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 : 0 : 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
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 : 0 : 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__ */
|