Branch data Line data Source code
1 : : /* SPDX-License-Identifier: BSD-3-Clause or GPL-2.0+
2 : : * Copyright 2008-2013 Freescale Semiconductor, Inc.
3 : : * Copyright 2019-2025 NXP
4 : : */
5 : :
6 : : #ifndef __DESC_PDCP_H__
7 : : #define __DESC_PDCP_H__
8 : :
9 : : #include "rta.h"
10 : : #include "common.h"
11 : :
12 : : /**
13 : : * DOC: PDCP Shared Descriptor Constructors
14 : : *
15 : : * Shared descriptors for PDCP protocol.
16 : : */
17 : :
18 : : /**
19 : : * PDCP_NULL_MAX_FRAME_LEN - The maximum frame frame length that is supported by
20 : : * PDCP NULL protocol.
21 : : */
22 : : #define PDCP_NULL_MAX_FRAME_LEN 0x00002FFF
23 : :
24 : : /**
25 : : * PDCP_MAC_I_LEN - The length of the MAC-I for PDCP protocol operation
26 : : */
27 : : #define PDCP_MAC_I_LEN 0x00000004
28 : :
29 : : /**
30 : : * PDCP_MAX_FRAME_LEN_STATUS - The status returned in FD status/command field in
31 : : * case the input frame is larger than
32 : : * PDCP_NULL_MAX_FRAME_LEN.
33 : : */
34 : : #define PDCP_MAX_FRAME_LEN_STATUS 0xF1
35 : :
36 : : /**
37 : : * PDCP_C_PLANE_SN_MASK - This mask is used in the PDCP descriptors for
38 : : * extracting the sequence number (SN) from the PDCP
39 : : * Control Plane header. For PDCP Control Plane, the SN
40 : : * is constant (5 bits) as opposed to PDCP Data Plane
41 : : * (7/12/15 bits).
42 : : */
43 : : #define PDCP_C_PLANE_SN_MASK 0x1F000000
44 : : #define PDCP_C_PLANE_SN_MASK_BE 0x0000001F
45 : :
46 : : /**
47 : : * PDCP_7BIT_SN_MASK - This mask is used in the PDCP descriptors for
48 : : * extracting the sequence number (SN) from the
49 : : * PDCP User Plane header.
50 : : */
51 : : #define PDCP_7BIT_SN_MASK 0x7F000000
52 : : #define PDCP_7BIT_SN_MASK_BE 0x0000007F
53 : :
54 : : /**
55 : : * PDCP_12BIT_SN_MASK - This mask is used in the PDCP descriptors for
56 : : * extracting the sequence number (SN) from the
57 : : * PDCP User Plane header.
58 : : */
59 : : #define PDCP_12BIT_SN_MASK 0xFF0F0000
60 : : #define PDCP_12BIT_SN_MASK_BE 0x00000FFF
61 : :
62 : : /**
63 : : * PDCP_U_PLANE_15BIT_SN_MASK - This mask is used in the PDCP descriptors for
64 : : * extracting the sequence number (SN) from the
65 : : * PDCP User Plane header. For PDCP Control Plane,
66 : : * the SN is constant (5 bits) as opposed to PDCP
67 : : * Data Plane (7/12/15 bits).
68 : : */
69 : : #define PDCP_U_PLANE_15BIT_SN_MASK 0xFF7F0000
70 : : #define PDCP_U_PLANE_15BIT_SN_MASK_BE 0x00007FFF
71 : :
72 : : /**
73 : : * PDCP_U_PLANE_18BIT_SN_MASK - This mask is used in the PDCP descriptors for
74 : : * extracting the sequence number (SN) from the
75 : : * PDCP User Plane header.
76 : : */
77 : : #define PDCP_U_PLANE_18BIT_SN_MASK 0xFFFF0300
78 : : #define PDCP_U_PLANE_18BIT_SN_MASK_BE 0x0003FFFF
79 : :
80 : : /**
81 : : * PDCP_BEARER_MASK - This mask is used masking out the bearer for PDCP
82 : : * processing with SNOW f9 in LTE.
83 : : *
84 : : * The value on which this mask is applied is formatted as below:
85 : : * Count-C (32 bit) | Bearer (5 bit) | Direction (1 bit) | 0 (26 bits)
86 : : *
87 : : * Applying this mask is done for creating the upper 64 bits of the IV needed
88 : : * for SNOW f9.
89 : : *
90 : : * The lower 32 bits of the mask are used for masking the direction for AES
91 : : * CMAC IV.
92 : : */
93 : : #define PDCP_BEARER_MASK 0x00000004FFFFFFFFull
94 : : #define PDCP_BEARER_MASK_BE 0xFFFFFFFF04000000ull
95 : :
96 : : /**
97 : : * PDCP_DIR_MASK - This mask is used masking out the direction for PDCP
98 : : * processing with SNOW f9 in LTE.
99 : : *
100 : : * The value on which this mask is applied is formatted as below:
101 : : * Bearer (5 bit) | Direction (1 bit) | 0 (26 bits)
102 : : *
103 : : * Applying this mask is done for creating the lower 32 bits of the IV needed
104 : : * for SNOW f9.
105 : : *
106 : : * The upper 32 bits of the mask are used for masking the direction for AES
107 : : * CMAC IV.
108 : : */
109 : : #define PDCP_DIR_MASK 0x00000000000000F8ull
110 : : #define PDCP_DIR_MASK_BE 0xF800000000000000ull
111 : :
112 : : /**
113 : : * PDCP_NULL_INT_MAC_I_VAL - The value of the PDCP PDU MAC-I in case NULL
114 : : * integrity is used.
115 : : */
116 : :
117 : : #define PDCP_NULL_INT_MAC_I_VAL 0x00000000
118 : :
119 : : /**
120 : : * PDCP_NULL_INT_ICV_CHECK_FAILED_STATUS - The status used to report ICV check
121 : : * failed in case of NULL integrity
122 : : * Control Plane processing.
123 : : */
124 : : #define PDCP_NULL_INT_ICV_CHECK_FAILED_STATUS 0x0A
125 : : /**
126 : : * PDCP_DPOVRD_HFN_OV_EN - Value to be used in the FD status/cmd field to
127 : : * indicate the HFN override mechanism is active for the
128 : : * frame.
129 : : */
130 : : #define PDCP_DPOVRD_HFN_OV_EN 0x80000000
131 : :
132 : : /**
133 : : * PDCP_P4080REV2_HFN_OV_BUFLEN - The length in bytes of the supplementary space
134 : : * that must be provided by the user at the
135 : : * beginning of the input frame buffer for
136 : : * P4080 REV 2.
137 : : *
138 : : * The format of the frame buffer is the following:
139 : : *
140 : : * |<---PDCP_P4080REV2_HFN_OV_BUFLEN-->|
141 : : * //===================================||============||==============\\
142 : : * || PDCP_DPOVRD_HFN_OV_EN | HFN value || PDCP Header|| PDCP Payload ||
143 : : * \\===================================||============||==============//
144 : : *
145 : : * If HFN override mechanism is not desired, then the MSB of the first 4 bytes
146 : : * must be set to 0b.
147 : : */
148 : : #define PDCP_P4080REV2_HFN_OV_BUFLEN 4
149 : :
150 : : /**
151 : : * enum cipher_type_pdcp - Type selectors for cipher types in PDCP protocol OP
152 : : * instructions.
153 : : * @PDCP_CIPHER_TYPE_NULL: NULL
154 : : * @PDCP_CIPHER_TYPE_SNOW: SNOW F8
155 : : * @PDCP_CIPHER_TYPE_AES: AES
156 : : * @PDCP_CIPHER_TYPE_ZUC: ZUCE
157 : : * @PDCP_CIPHER_TYPE_INVALID: invalid option
158 : : */
159 : : enum cipher_type_pdcp {
160 : : PDCP_CIPHER_TYPE_NULL,
161 : : PDCP_CIPHER_TYPE_SNOW,
162 : : PDCP_CIPHER_TYPE_AES,
163 : : PDCP_CIPHER_TYPE_ZUC,
164 : : PDCP_CIPHER_TYPE_INVALID
165 : : };
166 : :
167 : : /**
168 : : * enum auth_type_pdcp - Type selectors for integrity types in PDCP protocol OP
169 : : * instructions.
170 : : * @PDCP_AUTH_TYPE_NULL: NULL
171 : : * @PDCP_AUTH_TYPE_SNOW: SNOW F9
172 : : * @PDCP_AUTH_TYPE_AES: AES CMAC
173 : : * @PDCP_AUTH_TYPE_ZUC: ZUCA
174 : : * @PDCP_AUTH_TYPE_INVALID: invalid option
175 : : */
176 : : enum auth_type_pdcp {
177 : : PDCP_AUTH_TYPE_NULL,
178 : : PDCP_AUTH_TYPE_SNOW,
179 : : PDCP_AUTH_TYPE_AES,
180 : : PDCP_AUTH_TYPE_ZUC,
181 : : PDCP_AUTH_TYPE_INVALID
182 : : };
183 : :
184 : : /**
185 : : * enum pdcp_dir - Type selectors for direction for PDCP protocol
186 : : * @PDCP_DIR_UPLINK: uplink direction
187 : : * @PDCP_DIR_DOWNLINK: downlink direction
188 : : * @PDCP_DIR_INVALID: invalid option
189 : : */
190 : : enum pdcp_dir {
191 : : PDCP_DIR_UPLINK = 0,
192 : : PDCP_DIR_DOWNLINK = 1,
193 : : PDCP_DIR_INVALID
194 : : };
195 : :
196 : : /**
197 : : * enum pdcp_plane - PDCP domain selectors
198 : : * @PDCP_CONTROL_PLANE: Control Plane
199 : : * @PDCP_DATA_PLANE: Data Plane
200 : : * @PDCP_SHORT_MAC: Short MAC
201 : : */
202 : : enum pdcp_plane {
203 : : PDCP_CONTROL_PLANE,
204 : : PDCP_DATA_PLANE,
205 : : PDCP_SHORT_MAC
206 : : };
207 : :
208 : : /**
209 : : * enum pdcp_sn_size - Sequence Number Size selectors for PDCP protocol
210 : : * @PDCP_SN_SIZE_5: 5bit sequence number
211 : : * @PDCP_SN_SIZE_7: 7bit sequence number
212 : : * @PDCP_SN_SIZE_12: 12bit sequence number
213 : : * @PDCP_SN_SIZE_15: 15bit sequence number
214 : : * @PDCP_SN_SIZE_18: 18bit sequence number
215 : : */
216 : : enum pdcp_sn_size {
217 : : PDCP_SN_SIZE_5 = 5,
218 : : PDCP_SN_SIZE_7 = 7,
219 : : PDCP_SN_SIZE_12 = 12,
220 : : PDCP_SN_SIZE_15 = 15,
221 : : PDCP_SN_SIZE_18 = 18
222 : : };
223 : :
224 : : /*
225 : : * PDCP Control Plane Protocol Data Blocks
226 : : */
227 : : #define PDCP_C_PLANE_PDB_HFN_SHIFT 5
228 : : #define PDCP_C_PLANE_PDB_BEARER_SHIFT 27
229 : : #define PDCP_C_PLANE_PDB_DIR_SHIFT 26
230 : : #define PDCP_C_PLANE_PDB_HFN_THR_SHIFT 5
231 : :
232 : : #define PDCP_U_PLANE_PDB_OPT_SHORT_SN 0x2
233 : : #define PDCP_U_PLANE_PDB_OPT_15B_SN 0x4
234 : : #define PDCP_U_PLANE_PDB_OPT_18B_SN 0x6
235 : : #define PDCP_U_PLANE_PDB_SHORT_SN_HFN_SHIFT 7
236 : : #define PDCP_U_PLANE_PDB_LONG_SN_HFN_SHIFT 12
237 : : #define PDCP_U_PLANE_PDB_15BIT_SN_HFN_SHIFT 15
238 : : #define PDCP_U_PLANE_PDB_18BIT_SN_HFN_SHIFT 18
239 : : #define PDCP_U_PLANE_PDB_BEARER_SHIFT 27
240 : : #define PDCP_U_PLANE_PDB_DIR_SHIFT 26
241 : : #define PDCP_U_PLANE_PDB_SHORT_SN_HFN_THR_SHIFT 7
242 : : #define PDCP_U_PLANE_PDB_LONG_SN_HFN_THR_SHIFT 12
243 : : #define PDCP_U_PLANE_PDB_15BIT_SN_HFN_THR_SHIFT 15
244 : : #define PDCP_U_PLANE_PDB_18BIT_SN_HFN_THR_SHIFT 18
245 : :
246 : : struct pdcp_pdb {
247 : : union {
248 : : uint32_t opt;
249 : : uint32_t rsvd;
250 : : } opt_res;
251 : : uint32_t hfn_res; /* HyperFrame number,(27, 25 or 21 bits),
252 : : * left aligned & right-padded with zeros.
253 : : */
254 : : uint32_t bearer_dir_res;/* Bearer(5 bits), packet direction (1 bit),
255 : : * left aligned & right-padded with zeros.
256 : : */
257 : : uint32_t hfn_thr_res; /* HyperFrame number threshold (27, 25 or 21
258 : : * bits), left aligned & right-padded with
259 : : * zeros.
260 : : */
261 : : };
262 : :
263 : : /*
264 : : * PDCP internal PDB types
265 : : */
266 : : enum pdb_type_e {
267 : : PDCP_PDB_TYPE_NO_PDB,
268 : : PDCP_PDB_TYPE_FULL_PDB,
269 : : PDCP_PDB_TYPE_REDUCED_PDB,
270 : : PDCP_PDB_TYPE_INVALID
271 : : };
272 : :
273 : : #define REDUCED_PDB_DESCBUF_HFN_BEARER_DIR_OFFSET 4
274 : : #define FULL_PDB_DESCBUF_HFN_BEARER_DIR_OFFSET 8
275 : :
276 : : /**
277 : : * rta_inline_pdcp_query() - Provide indications if a key can be passed as
278 : : * immediate data or shall be referenced in a
279 : : * shared descriptor.
280 : : * Return: 0 if data can be inlined or 1 if referenced.
281 : : */
282 : : static inline int
283 : 0 : rta_inline_pdcp_query(enum auth_type_pdcp auth_alg,
284 : : enum cipher_type_pdcp cipher_alg,
285 : : enum pdcp_sn_size sn_size,
286 : : int8_t hfn_ovd)
287 : : {
288 : : /**
289 : : * Shared Descriptors for some of the cases does not fit in the
290 : : * MAX_DESC_SIZE of the descriptor especially when non-protocol
291 : : * descriptors are formed as in 18bit cases and when HFN override
292 : : * is enabled as 2 extra words are added in the job descriptor.
293 : : * The cases which exceed are for RTA_SEC_ERA=8 and HFN override
294 : : * enabled and 18bit uplane and either of following Algo combinations.
295 : : * - SNOW-AES
296 : : * - AES-SNOW
297 : : * - SNOW-SNOW
298 : : * - ZUC-SNOW
299 : : *
300 : : * We cannot make inline for all cases, as this will impact performance
301 : : * due to extra memory accesses for the keys.
302 : : */
303 [ # # ]: 0 : if ((rta_sec_era == RTA_SEC_ERA_8) && hfn_ovd &&
304 [ # # ]: 0 : (sn_size == PDCP_SN_SIZE_18) &&
305 : 0 : ((cipher_alg == PDCP_CIPHER_TYPE_SNOW &&
306 [ # # ]: 0 : auth_alg == PDCP_AUTH_TYPE_AES) ||
307 : 0 : (cipher_alg == PDCP_CIPHER_TYPE_AES &&
308 [ # # ]: 0 : auth_alg == PDCP_AUTH_TYPE_SNOW) ||
309 [ # # ]: 0 : (cipher_alg == PDCP_CIPHER_TYPE_SNOW &&
310 : 0 : auth_alg == PDCP_AUTH_TYPE_SNOW) ||
311 [ # # ]: 0 : (cipher_alg == PDCP_CIPHER_TYPE_ZUC &&
312 : : auth_alg == PDCP_AUTH_TYPE_SNOW))) {
313 : :
314 : 0 : return 1;
315 : : }
316 : :
317 : : return 0;
318 : : }
319 : :
320 : : /*
321 : : * Function for appending the portion of a PDCP Control Plane shared descriptor
322 : : * which performs NULL encryption and integrity (i.e. copies the input frame
323 : : * to the output frame, appending 32 bits of zeros at the end (MAC-I for
324 : : * NULL integrity).
325 : : */
326 : : static inline int
327 : 0 : pdcp_insert_cplane_null_op(struct program *p,
328 : : bool swap __maybe_unused,
329 : : struct alginfo *cipherdata __maybe_unused,
330 : : struct alginfo *authdata __maybe_unused,
331 : : unsigned int dir,
332 : : enum pdcp_sn_size sn_size __maybe_unused)
333 : : {
334 : 0 : MATHB(p, SEQINSZ, ADD, ZERO, VSEQINSZ, 4, 0);
335 [ # # ]: 0 : if (dir == OP_TYPE_ENCAP_PROTOCOL)
336 : 0 : MATHB(p, SEQINSZ, ADD, PDCP_MAC_I_LEN, VSEQOUTSZ, 4,
337 : : IMMED2);
338 : : else
339 : 0 : MATHB(p, SEQINSZ, SUB, PDCP_MAC_I_LEN, VSEQOUTSZ, 4,
340 : : IMMED2);
341 : :
342 : 0 : MATHB(p, VSEQINSZ, SUB, PDCP_NULL_MAX_FRAME_LEN, NONE, 4,
343 : : IMMED2);
344 : 0 : JUMP(p, PDCP_MAX_FRAME_LEN_STATUS, HALT_STATUS, ALL_FALSE, MATH_N);
345 : :
346 [ # # ]: 0 : if (dir == OP_TYPE_ENCAP_PROTOCOL)
347 : 0 : MATHB(p, VSEQINSZ, ADD, ZERO, MATH0, 4, 0);
348 : : else
349 : 0 : MATHB(p, VSEQOUTSZ, ADD, ZERO, MATH0, 4, 0);
350 : :
351 : 0 : SEQFIFOSTORE(p, MSG, 0, 0, VLF);
352 : 0 : SEQFIFOLOAD(p, MSG1, 0, VLF | LAST1 | FLUSH1);
353 : :
354 : 0 : MOVE(p, AB1, 0, OFIFO, 0, MATH0, 0);
355 : :
356 [ # # ]: 0 : if (dir == OP_TYPE_ENCAP_PROTOCOL) {
357 : 0 : MATHB(p, MATH1, XOR, MATH1, MATH0, 8, 0);
358 : 0 : MOVE(p, MATH0, 0, OFIFO, 0, 4, IMMED);
359 : : }
360 : :
361 : 0 : return 0;
362 : : }
363 : :
364 : : static inline int
365 : 0 : insert_copy_frame_op(struct program *p,
366 : : struct alginfo *cipherdata __maybe_unused,
367 : : unsigned int dir __maybe_unused)
368 : : {
369 : 0 : MATHB(p, SEQINSZ, ADD, ZERO, VSEQINSZ, 4, 0);
370 : 0 : MATHB(p, SEQINSZ, ADD, ZERO, VSEQOUTSZ, 4, 0);
371 : :
372 : 0 : MATHB(p, SEQINSZ, SUB, PDCP_NULL_MAX_FRAME_LEN, NONE, 4,
373 : : IFB | IMMED2);
374 : 0 : JUMP(p, PDCP_MAX_FRAME_LEN_STATUS, HALT_STATUS, ALL_FALSE, MATH_N);
375 : :
376 : 0 : MATHB(p, VSEQINSZ, ADD, ZERO, MATH0, 4, 0);
377 : :
378 : 0 : SEQFIFOLOAD(p, MSG1, 0, VLF | LAST1 | FLUSH1);
379 : :
380 : 0 : MOVE(p, AB1, 0, OFIFO, 0, MATH0, 0);
381 : :
382 : 0 : SEQFIFOSTORE(p, MSG, 0, 0, VLF);
383 : :
384 : 0 : return 0;
385 : : }
386 : :
387 : : static inline int
388 : 0 : pdcp_insert_cplane_int_only_op(struct program *p,
389 : : bool swap __maybe_unused,
390 : : struct alginfo *cipherdata __maybe_unused,
391 : : struct alginfo *authdata, unsigned int dir,
392 : : enum pdcp_sn_size sn_size)
393 : : {
394 : : uint32_t offset = 0, length = 0, sn_mask = 0;
395 : :
396 : : /* 12 bit SN is only supported for protocol offload case */
397 [ # # ]: 0 : if (sn_size == PDCP_SN_SIZE_12) {
398 : 0 : KEY(p, KEY2, authdata->key_enc_flags, authdata->key,
399 : : authdata->keylen, INLINE_KEY(authdata));
400 : :
401 : 0 : PROTOCOL(p, dir, OP_PCLID_LTE_PDCP_USER_RN,
402 : : (uint16_t)authdata->algtype);
403 : 0 : return 0;
404 : : }
405 : :
406 : : /* Non-proto is supported only for 5bit cplane and 18bit uplane */
407 [ # # # # ]: 0 : switch (sn_size) {
408 : 0 : case PDCP_SN_SIZE_5:
409 : : offset = 7;
410 : : length = 1;
411 [ # # ]: 0 : sn_mask = (swap == false) ? PDCP_C_PLANE_SN_MASK :
412 : : PDCP_C_PLANE_SN_MASK_BE;
413 : : break;
414 : 0 : case PDCP_SN_SIZE_18:
415 : : offset = 5;
416 : : length = 3;
417 [ # # ]: 0 : sn_mask = (swap == false) ? PDCP_U_PLANE_18BIT_SN_MASK :
418 : : PDCP_U_PLANE_18BIT_SN_MASK_BE;
419 : : break;
420 : 0 : case PDCP_SN_SIZE_7:
421 : : case PDCP_SN_SIZE_12:
422 : : case PDCP_SN_SIZE_15:
423 : 0 : pr_err("Invalid sn_size for %s\n", __func__);
424 : 0 : return -ENOTSUP;
425 : :
426 : : }
427 : :
428 [ # # # # ]: 0 : switch (authdata->algtype) {
429 : 0 : case PDCP_AUTH_TYPE_SNOW:
430 : : /* Insert Auth Key */
431 : 0 : KEY(p, KEY2, authdata->key_enc_flags, authdata->key,
432 : : authdata->keylen, INLINE_KEY(authdata));
433 : 0 : SEQLOAD(p, MATH0, offset, length, 0);
434 : 0 : JUMP(p, 1, LOCAL_JUMP, ALL_TRUE, CALM);
435 : :
436 : 0 : SEQINPTR(p, 0, length, RTO);
437 : :
438 [ # # ]: 0 : if (swap == false) {
439 : 0 : MATHB(p, MATH0, AND, sn_mask, MATH1, 8,
440 : : IFB | IMMED2);
441 : 0 : MATHB(p, MATH1, SHLD, MATH1, MATH1, 8, 0);
442 : :
443 : 0 : MOVEB(p, DESCBUF, 8, MATH2, 0, 8, WAITCOMP | IMMED);
444 : :
445 : 0 : MATHB(p, MATH2, AND, PDCP_BEARER_MASK, MATH2, 8,
446 : : IMMED2);
447 : 0 : MOVEB(p, DESCBUF, 0x0C, MATH3, 0, 4, WAITCOMP | IMMED);
448 : 0 : MATHB(p, MATH3, AND, PDCP_DIR_MASK, MATH3, 8, IMMED2);
449 : 0 : MATHB(p, MATH1, OR, MATH2, MATH2, 8, 0);
450 : 0 : MOVEB(p, MATH2, 0, CONTEXT2, 0, 0x0C, WAITCOMP | IMMED);
451 : : } else {
452 : 0 : MATHB(p, MATH0, AND, sn_mask, MATH1, 8,
453 : : IFB | IMMED2);
454 : 0 : MATHB(p, MATH1, SHLD, MATH1, MATH1, 8, 0);
455 : :
456 : 0 : MOVE(p, DESCBUF, 8, MATH2, 0, 8, WAITCOMP | IMMED);
457 : 0 : MATHB(p, MATH2, AND, PDCP_BEARER_MASK_BE, MATH2, 8,
458 : : IMMED2);
459 : :
460 : 0 : MOVE(p, DESCBUF, 0x0C, MATH3, 0, 4, WAITCOMP | IMMED);
461 : 0 : MATHB(p, MATH3, AND, PDCP_DIR_MASK_BE, MATH3, 8,
462 : : IMMED2);
463 : 0 : MATHB(p, MATH1, OR, MATH2, MATH2, 8, 0);
464 : 0 : MOVE(p, MATH2, 0, CONTEXT2, 0, 0x0C, WAITCOMP | IMMED);
465 : : }
466 : :
467 [ # # ]: 0 : if (dir == OP_TYPE_DECAP_PROTOCOL) {
468 : 0 : MATHB(p, SEQINSZ, SUB, PDCP_MAC_I_LEN, MATH1, 4,
469 : : IMMED2);
470 : : } else {
471 : 0 : MATHB(p, SEQINSZ, SUB, ZERO, MATH1, 4, 0);
472 : : }
473 : :
474 : 0 : MATHB(p, MATH1, SUB, ZERO, VSEQINSZ, 4, 0);
475 : 0 : MATHB(p, MATH1, SUB, ZERO, VSEQOUTSZ, 4, 0);
476 : :
477 : 0 : SEQFIFOSTORE(p, MSG, 0, 0, VLF);
478 : 0 : ALG_OPERATION(p, OP_ALG_ALGSEL_SNOW_F9, OP_ALG_AAI_F9,
479 : : OP_ALG_AS_INITFINAL,
480 : : dir == OP_TYPE_ENCAP_PROTOCOL ?
481 : : ICV_CHECK_DISABLE : ICV_CHECK_ENABLE,
482 : : DIR_ENC);
483 : :
484 : 0 : SEQFIFOLOAD(p, MSGINSNOOP, 0,
485 : : VLF | LAST1 | LAST2 | FLUSH1);
486 : 0 : MOVE(p, AB1, 0, OFIFO, 0, MATH1, 0);
487 : :
488 [ # # ]: 0 : if (dir == OP_TYPE_DECAP_PROTOCOL)
489 : 0 : SEQFIFOLOAD(p, ICV2, 4, LAST2);
490 : : else
491 : 0 : SEQSTORE(p, CONTEXT2, 0, 4, 0);
492 : :
493 : : break;
494 : :
495 : 0 : case PDCP_AUTH_TYPE_AES:
496 : : /* Insert Auth Key */
497 : 0 : KEY(p, KEY1, authdata->key_enc_flags, authdata->key,
498 : : authdata->keylen, INLINE_KEY(authdata));
499 : 0 : SEQLOAD(p, MATH0, offset, length, 0);
500 : 0 : JUMP(p, 1, LOCAL_JUMP, ALL_TRUE, CALM);
501 : 0 : SEQINPTR(p, 0, length, RTO);
502 : :
503 [ # # ]: 0 : if (swap == false) {
504 : 0 : MATHB(p, MATH0, AND, sn_mask, MATH1, 8,
505 : : IFB | IMMED2);
506 : 0 : MATHB(p, MATH1, SHLD, MATH1, MATH1, 8, 0);
507 : :
508 : 0 : MOVEB(p, DESCBUF, 8, MATH2, 0, 8, WAITCOMP | IMMED);
509 : 0 : MATHB(p, MATH1, OR, MATH2, MATH2, 8, 0);
510 : 0 : MOVEB(p, MATH2, 0, IFIFOAB1, 0, 8, IMMED);
511 : : } else {
512 : 0 : MATHB(p, MATH0, AND, sn_mask, MATH1, 8,
513 : : IFB | IMMED2);
514 : 0 : MATHB(p, MATH1, SHLD, MATH1, MATH1, 8, 0);
515 : :
516 : 0 : MOVE(p, DESCBUF, 8, MATH2, 0, 8, WAITCOMP | IMMED);
517 : 0 : MATHB(p, MATH1, OR, MATH2, MATH2, 8, 0);
518 : 0 : MOVE(p, MATH2, 0, IFIFOAB1, 0, 8, IMMED);
519 : : }
520 : :
521 [ # # ]: 0 : if (dir == OP_TYPE_DECAP_PROTOCOL) {
522 : 0 : MATHB(p, SEQINSZ, SUB, PDCP_MAC_I_LEN, MATH1, 4,
523 : : IMMED2);
524 : : } else {
525 : 0 : MATHB(p, SEQINSZ, SUB, ZERO, MATH1, 4, 0);
526 : : }
527 : :
528 : 0 : MATHB(p, MATH1, SUB, ZERO, VSEQINSZ, 4, 0);
529 : 0 : MATHB(p, MATH1, SUB, ZERO, VSEQOUTSZ, 4, 0);
530 : :
531 : 0 : SEQFIFOSTORE(p, MSG, 0, 0, VLF);
532 : 0 : ALG_OPERATION(p, OP_ALG_ALGSEL_AES,
533 : : OP_ALG_AAI_CMAC,
534 : : OP_ALG_AS_INITFINAL,
535 : : dir == OP_TYPE_ENCAP_PROTOCOL ?
536 : : ICV_CHECK_DISABLE : ICV_CHECK_ENABLE,
537 : : DIR_ENC);
538 : :
539 : 0 : MOVE(p, AB2, 0, OFIFO, 0, MATH1, 0);
540 : 0 : SEQFIFOLOAD(p, MSGINSNOOP, 0,
541 : : VLF | LAST1 | LAST2 | FLUSH1);
542 : :
543 [ # # ]: 0 : if (dir == OP_TYPE_DECAP_PROTOCOL)
544 : 0 : SEQFIFOLOAD(p, ICV1, 4, LAST1 | FLUSH1);
545 : : else
546 : 0 : SEQSTORE(p, CONTEXT1, 0, 4, 0);
547 : :
548 : : break;
549 : :
550 : 0 : case PDCP_AUTH_TYPE_ZUC:
551 : : /* Insert Auth Key */
552 : 0 : KEY(p, KEY2, authdata->key_enc_flags, authdata->key,
553 : : authdata->keylen, INLINE_KEY(authdata));
554 : 0 : SEQLOAD(p, MATH0, offset, length, 0);
555 : 0 : JUMP(p, 1, LOCAL_JUMP, ALL_TRUE, CALM);
556 : 0 : SEQINPTR(p, 0, length, RTO);
557 [ # # ]: 0 : if (swap == false) {
558 : 0 : MATHB(p, MATH0, AND, sn_mask, MATH1, 8,
559 : : IFB | IMMED2);
560 : 0 : MATHB(p, MATH1, SHLD, MATH1, MATH1, 8, 0);
561 : :
562 : 0 : MOVEB(p, DESCBUF, 8, MATH2, 0, 8, WAITCOMP | IMMED);
563 : 0 : MATHB(p, MATH1, OR, MATH2, MATH2, 8, 0);
564 : 0 : MOVEB(p, MATH2, 0, CONTEXT2, 0, 8, IMMED);
565 : :
566 : : } else {
567 : 0 : MATHB(p, MATH0, AND, sn_mask, MATH1, 8,
568 : : IFB | IMMED2);
569 : 0 : MATHB(p, MATH1, SHLD, MATH1, MATH1, 8, 0);
570 : :
571 : 0 : MOVE(p, DESCBUF, 8, MATH2, 0, 8, WAITCOMP | IMMED);
572 : 0 : MATHB(p, MATH1, OR, MATH2, MATH2, 8, 0);
573 : 0 : MOVE(p, MATH2, 0, CONTEXT2, 0, 8, IMMED);
574 : : }
575 [ # # ]: 0 : if (dir == OP_TYPE_DECAP_PROTOCOL)
576 : 0 : MATHB(p, SEQINSZ, SUB, PDCP_MAC_I_LEN, MATH1, 4,
577 : : IMMED2);
578 : : else
579 : 0 : MATHB(p, SEQINSZ, SUB, ZERO, MATH1, 4, 0);
580 : :
581 : 0 : MATHB(p, MATH1, SUB, ZERO, VSEQINSZ, 4, 0);
582 : 0 : MATHB(p, MATH1, SUB, ZERO, VSEQOUTSZ, 4, 0);
583 : 0 : SEQFIFOSTORE(p, MSG, 0, 0, VLF);
584 : 0 : ALG_OPERATION(p, OP_ALG_ALGSEL_ZUCA,
585 : : OP_ALG_AAI_F9,
586 : : OP_ALG_AS_INITFINAL,
587 : : dir == OP_TYPE_ENCAP_PROTOCOL ?
588 : : ICV_CHECK_DISABLE : ICV_CHECK_ENABLE,
589 : : DIR_ENC);
590 : 0 : SEQFIFOLOAD(p, MSGINSNOOP, 0, VLF | LAST1 | LAST2 | FLUSH1);
591 : 0 : MOVE(p, AB1, 0, OFIFO, 0, MATH1, 0);
592 : :
593 [ # # ]: 0 : if (dir == OP_TYPE_DECAP_PROTOCOL)
594 : 0 : SEQFIFOLOAD(p, ICV2, 4, LAST2);
595 : : else
596 : 0 : SEQSTORE(p, CONTEXT2, 0, 4, 0);
597 : :
598 : : break;
599 : :
600 : 0 : default:
601 : 0 : pr_err("%s: Invalid integrity algorithm selected: %d\n",
602 : : "pdcp_insert_cplane_int_only_op", authdata->algtype);
603 : 0 : return -EINVAL;
604 : : }
605 : :
606 : : return 0;
607 : : }
608 : :
609 : : static inline int
610 : 0 : pdcp_insert_cplane_enc_only_op(struct program *p,
611 : : bool swap __maybe_unused,
612 : : struct alginfo *cipherdata,
613 : : struct alginfo *authdata __maybe_unused,
614 : : unsigned int dir,
615 : : enum pdcp_sn_size sn_size)
616 : : {
617 : : uint32_t offset = 0, length = 0, sn_mask = 0;
618 : : /* Insert Cipher Key */
619 : 0 : KEY(p, KEY1, cipherdata->key_enc_flags, cipherdata->key,
620 : : cipherdata->keylen, INLINE_KEY(cipherdata));
621 : :
622 [ # # ]: 0 : if ((authdata && sn_size != PDCP_SN_SIZE_18 &&
623 [ # # ]: 0 : !(rta_sec_era == RTA_SEC_ERA_8 &&
624 [ # # ]: 0 : authdata->algtype == 0))
625 [ # # ]: 0 : || (rta_sec_era == RTA_SEC_ERA_10)) {
626 [ # # ]: 0 : if (sn_size == PDCP_SN_SIZE_5)
627 : 0 : PROTOCOL(p, dir, OP_PCLID_LTE_PDCP_CTRL_MIXED,
628 : : (uint16_t)cipherdata->algtype << 8);
629 : : else
630 : 0 : PROTOCOL(p, dir, OP_PCLID_LTE_PDCP_USER_RN,
631 : : (uint16_t)cipherdata->algtype << 8);
632 : 0 : return 0;
633 : : }
634 : :
635 : : /* Non-proto is supported only for 5bit cplane and 18bit uplane */
636 [ # # # # : 0 : switch (sn_size) {
# ]
637 : 0 : case PDCP_SN_SIZE_5:
638 : : offset = 7;
639 : : length = 1;
640 [ # # ]: 0 : sn_mask = (swap == false) ? PDCP_C_PLANE_SN_MASK :
641 : : PDCP_C_PLANE_SN_MASK_BE;
642 : : break;
643 : 0 : case PDCP_SN_SIZE_18:
644 : : offset = 5;
645 : : length = 3;
646 [ # # ]: 0 : sn_mask = (swap == false) ? PDCP_U_PLANE_18BIT_SN_MASK :
647 : : PDCP_U_PLANE_18BIT_SN_MASK_BE;
648 : : break;
649 : 0 : case PDCP_SN_SIZE_12:
650 : : offset = 6;
651 : : length = 2;
652 [ # # ]: 0 : sn_mask = (swap == false) ? PDCP_12BIT_SN_MASK :
653 : : PDCP_12BIT_SN_MASK_BE;
654 : : break;
655 : 0 : case PDCP_SN_SIZE_7:
656 : : case PDCP_SN_SIZE_15:
657 : 0 : pr_err("Invalid sn_size for %s\n", __func__);
658 : 0 : return -ENOTSUP;
659 : : }
660 : :
661 : 0 : SEQLOAD(p, MATH0, offset, length, 0);
662 : 0 : JUMP(p, 1, LOCAL_JUMP, ALL_TRUE, CALM);
663 : 0 : MATHB(p, MATH0, AND, sn_mask, MATH1, 8, IFB | IMMED2);
664 : 0 : SEQSTORE(p, MATH0, offset, length, 0);
665 : 0 : MATHB(p, MATH1, SHLD, MATH1, MATH1, 8, 0);
666 : 0 : MOVEB(p, DESCBUF, 8, MATH2, 0, 8, WAITCOMP | IMMED);
667 : 0 : MATHB(p, MATH1, OR, MATH2, MATH2, 8, 0);
668 : :
669 [ # # # # ]: 0 : switch (cipherdata->algtype) {
670 : 0 : case PDCP_CIPHER_TYPE_SNOW:
671 : 0 : MOVEB(p, MATH2, 0, CONTEXT1, 0, 8, WAITCOMP | IMMED);
672 : :
673 : 0 : MATHB(p, SEQINSZ, SUB, ZERO, VSEQINSZ, 4, 0);
674 : :
675 [ # # ]: 0 : if (dir == OP_TYPE_ENCAP_PROTOCOL)
676 : 0 : MATHB(p, SEQINSZ, ADD, PDCP_MAC_I_LEN, VSEQOUTSZ, 4,
677 : : IMMED2);
678 : : else
679 : 0 : MATHB(p, SEQINSZ, SUB, PDCP_MAC_I_LEN, VSEQOUTSZ, 4,
680 : : IMMED2);
681 : 0 : SEQFIFOSTORE(p, MSG, 0, 0, VLF | CONT);
682 : 0 : ALG_OPERATION(p, OP_ALG_ALGSEL_SNOW_F8,
683 : : OP_ALG_AAI_F8,
684 : : OP_ALG_AS_INITFINAL, ICV_CHECK_DISABLE,
685 : : dir == OP_TYPE_ENCAP_PROTOCOL ?
686 : : DIR_ENC : DIR_DEC);
687 : 0 : break;
688 : :
689 : 0 : case PDCP_CIPHER_TYPE_AES:
690 : 0 : MOVEB(p, MATH2, 0, CONTEXT1, 0x10, 0x10, WAITCOMP | IMMED);
691 : :
692 : 0 : MATHB(p, SEQINSZ, SUB, ZERO, VSEQINSZ, 4, 0);
693 : :
694 [ # # ]: 0 : if (dir == OP_TYPE_ENCAP_PROTOCOL)
695 : 0 : MATHB(p, SEQINSZ, ADD, PDCP_MAC_I_LEN, VSEQOUTSZ, 4,
696 : : IMMED2);
697 : : else
698 : 0 : MATHB(p, SEQINSZ, SUB, PDCP_MAC_I_LEN, VSEQOUTSZ, 4,
699 : : IMMED2);
700 : :
701 : 0 : SEQFIFOSTORE(p, MSG, 0, 0, VLF | CONT);
702 : 0 : ALG_OPERATION(p, OP_ALG_ALGSEL_AES,
703 : : OP_ALG_AAI_CTR,
704 : : OP_ALG_AS_INITFINAL,
705 : : ICV_CHECK_DISABLE,
706 : : dir == OP_TYPE_ENCAP_PROTOCOL ?
707 : : DIR_ENC : DIR_DEC);
708 : 0 : break;
709 : :
710 : 0 : case PDCP_CIPHER_TYPE_ZUC:
711 : 0 : MOVEB(p, MATH2, 0, CONTEXT1, 0, 0x08, IMMED);
712 : 0 : MOVEB(p, MATH2, 0, CONTEXT1, 0x08, 0x08, WAITCOMP | IMMED);
713 : 0 : MATHB(p, SEQINSZ, SUB, ZERO, VSEQINSZ, 4, 0);
714 [ # # ]: 0 : if (dir == OP_TYPE_ENCAP_PROTOCOL)
715 : 0 : MATHB(p, SEQINSZ, ADD, PDCP_MAC_I_LEN, VSEQOUTSZ, 4,
716 : : IMMED2);
717 : : else
718 : 0 : MATHB(p, SEQINSZ, SUB, PDCP_MAC_I_LEN, VSEQOUTSZ, 4,
719 : : IMMED2);
720 : :
721 : 0 : SEQFIFOSTORE(p, MSG, 0, 0, VLF | CONT);
722 : 0 : ALG_OPERATION(p, OP_ALG_ALGSEL_ZUCE,
723 : : OP_ALG_AAI_F8,
724 : : OP_ALG_AS_INITFINAL,
725 : : ICV_CHECK_DISABLE,
726 : : dir == OP_TYPE_ENCAP_PROTOCOL ?
727 : : DIR_ENC : DIR_DEC);
728 : 0 : break;
729 : :
730 : 0 : default:
731 : 0 : pr_err("%s: Invalid encrypt algorithm selected: %d\n",
732 : : "pdcp_insert_cplane_enc_only_op", cipherdata->algtype);
733 : 0 : return -EINVAL;
734 : : }
735 : :
736 [ # # ]: 0 : if (dir == OP_TYPE_ENCAP_PROTOCOL) {
737 : 0 : SEQFIFOLOAD(p, MSG1, 0, VLF);
738 : 0 : FIFOLOAD(p, MSG1, PDCP_NULL_INT_MAC_I_VAL, 4,
739 : : LAST1 | FLUSH1 | IMMED);
740 : : } else {
741 : 0 : SEQFIFOLOAD(p, MSG1, 0, VLF | LAST1 | FLUSH1);
742 : 0 : MOVE(p, OFIFO, 0, MATH1, 4, PDCP_MAC_I_LEN, WAITCOMP | IMMED);
743 : 0 : MATHB(p, MATH1, XOR, PDCP_NULL_INT_MAC_I_VAL, NONE, 4, IMMED2);
744 : 0 : JUMP(p, PDCP_NULL_INT_ICV_CHECK_FAILED_STATUS,
745 : : HALT_STATUS, ALL_FALSE, MATH_Z);
746 : : }
747 : :
748 : : return 0;
749 : : }
750 : :
751 : : static inline int
752 : 0 : pdcp_insert_uplane_snow_snow_op(struct program *p,
753 : : bool swap __maybe_unused,
754 : : struct alginfo *cipherdata,
755 : : struct alginfo *authdata,
756 : : unsigned int dir,
757 : : enum pdcp_sn_size sn_size)
758 : : {
759 : : uint32_t offset = 0, length = 0, sn_mask = 0;
760 : :
761 : 0 : KEY(p, KEY1, cipherdata->key_enc_flags, cipherdata->key,
762 : : cipherdata->keylen, INLINE_KEY(cipherdata));
763 : 0 : KEY(p, KEY2, authdata->key_enc_flags, authdata->key, authdata->keylen,
764 : : INLINE_KEY(authdata));
765 : :
766 [ # # ]: 0 : if (sn_size != PDCP_SN_SIZE_18) {
767 : : int pclid;
768 : :
769 [ # # ]: 0 : if (sn_size == PDCP_SN_SIZE_5)
770 : : pclid = OP_PCLID_LTE_PDCP_CTRL_MIXED;
771 : : else
772 : : pclid = OP_PCLID_LTE_PDCP_USER_RN;
773 : :
774 : 0 : PROTOCOL(p, dir, pclid,
775 : : ((uint16_t)cipherdata->algtype << 8) |
776 : : (uint16_t)authdata->algtype);
777 : :
778 : 0 : return 0;
779 : : }
780 : : /* sn_size is 18 */
781 : : offset = 5;
782 : : length = 3;
783 [ # # ]: 0 : sn_mask = (swap == false) ? PDCP_U_PLANE_18BIT_SN_MASK :
784 : : PDCP_U_PLANE_18BIT_SN_MASK_BE;
785 : :
786 [ # # ]: 0 : if (dir == OP_TYPE_ENCAP_PROTOCOL)
787 : 0 : MATHB(p, SEQINSZ, SUB, length, VSEQINSZ, 4, IMMED2);
788 : :
789 : 0 : SEQLOAD(p, MATH0, offset, length, 0);
790 : 0 : JUMP(p, 1, LOCAL_JUMP, ALL_TRUE, CALM);
791 : 0 : MOVEB(p, MATH0, offset, IFIFOAB2, 0, length, IMMED);
792 : 0 : MATHB(p, MATH0, AND, sn_mask, MATH1, 8, IFB | IMMED2);
793 : :
794 : 0 : SEQSTORE(p, MATH0, offset, length, 0);
795 : 0 : MATHB(p, MATH1, SHLD, MATH1, MATH1, 8, 0);
796 : 0 : MOVEB(p, DESCBUF, 8, MATH2, 0, 8, WAITCOMP | IMMED);
797 : 0 : MATHB(p, MATH1, OR, MATH2, MATH1, 8, 0);
798 : 0 : MOVEB(p, MATH1, 0, CONTEXT1, 0, 8, IMMED);
799 : 0 : MOVEB(p, MATH1, 0, CONTEXT2, 0, 4, WAITCOMP | IMMED);
800 [ # # ]: 0 : if (swap == false) {
801 : 0 : MATHB(p, MATH1, AND, upper_32_bits(PDCP_BEARER_MASK),
802 : : MATH2, 4, IMMED2);
803 : 0 : MATHB(p, MATH1, AND, lower_32_bits(PDCP_DIR_MASK),
804 : : MATH3, 4, IMMED2);
805 : : } else {
806 : 0 : MATHB(p, MATH1, AND, lower_32_bits(PDCP_BEARER_MASK_BE),
807 : : MATH2, 4, IMMED2);
808 : 0 : MATHB(p, MATH1, AND, upper_32_bits(PDCP_DIR_MASK_BE),
809 : : MATH3, 4, IMMED2);
810 : : }
811 : 0 : MATHB(p, MATH3, SHLD, MATH3, MATH3, 8, 0);
812 : :
813 : 0 : MOVEB(p, MATH2, 4, OFIFO, 0, 12, IMMED);
814 : 0 : MOVE(p, OFIFO, 0, CONTEXT2, 4, 12, IMMED);
815 [ # # ]: 0 : if (dir == OP_TYPE_ENCAP_PROTOCOL) {
816 : 0 : MATHB(p, SEQINSZ, ADD, PDCP_MAC_I_LEN, VSEQOUTSZ, 4, IMMED2);
817 : : } else {
818 : 0 : MATHI(p, SEQINSZ, SUB, PDCP_MAC_I_LEN, VSEQOUTSZ, 4, IMMED2);
819 : 0 : MATHI(p, SEQINSZ, SUB, PDCP_MAC_I_LEN, VSEQINSZ, 4, IMMED2);
820 : : }
821 : :
822 [ # # ]: 0 : if (dir == OP_TYPE_ENCAP_PROTOCOL)
823 : 0 : SEQFIFOSTORE(p, MSG, 0, 0, VLF);
824 : : else
825 : 0 : SEQFIFOSTORE(p, MSG, 0, 0, VLF | CONT);
826 : :
827 : 0 : ALG_OPERATION(p, OP_ALG_ALGSEL_SNOW_F9,
828 : : OP_ALG_AAI_F9,
829 : : OP_ALG_AS_INITFINAL,
830 : : dir == OP_TYPE_ENCAP_PROTOCOL ?
831 : : ICV_CHECK_DISABLE : ICV_CHECK_ENABLE,
832 : : DIR_DEC);
833 : 0 : ALG_OPERATION(p, OP_ALG_ALGSEL_SNOW_F8,
834 : : OP_ALG_AAI_F8,
835 : : OP_ALG_AS_INITFINAL,
836 : : ICV_CHECK_DISABLE,
837 : : dir == OP_TYPE_ENCAP_PROTOCOL ? DIR_ENC : DIR_DEC);
838 : :
839 [ # # ]: 0 : if (dir == OP_TYPE_ENCAP_PROTOCOL) {
840 : 0 : SEQFIFOLOAD(p, MSGINSNOOP, 0, VLF | LAST2);
841 : 0 : MOVE(p, CONTEXT2, 0, IFIFOAB1, 0, 4, LAST1 | FLUSH1 | IMMED);
842 : : } else {
843 : 0 : SEQFIFOLOAD(p, MSGOUTSNOOP, 0, VLF | LAST2);
844 : 0 : SEQFIFOLOAD(p, MSG1, 4, LAST1 | FLUSH1);
845 : 0 : JUMP(p, 1, LOCAL_JUMP, ALL_TRUE, CLASS1 | NOP | NIFP);
846 : :
847 : 0 : LOAD(p, 0, DCTRL, 0, LDLEN_RST_CHA_OFIFO_PTR, IMMED);
848 : :
849 : 0 : MOVE(p, OFIFO, 0, MATH0, 0, 4, WAITCOMP | IMMED);
850 : :
851 : 0 : NFIFOADD(p, IFIFO, ICV2, 4, LAST2);
852 : :
853 : 0 : MOVE(p, MATH0, 0, IFIFO, 0, 4, WAITCOMP | IMMED);
854 : : }
855 : :
856 : : return 0;
857 : : }
858 : :
859 : : static inline int
860 : 0 : pdcp_insert_uplane_zuc_zuc_op(struct program *p,
861 : : bool swap __maybe_unused,
862 : : struct alginfo *cipherdata,
863 : : struct alginfo *authdata,
864 : : unsigned int dir,
865 : : enum pdcp_sn_size sn_size)
866 : : {
867 : : uint32_t offset = 0, length = 0, sn_mask = 0;
868 : :
869 : : LABEL(keyjump);
870 : : REFERENCE(pkeyjump);
871 : :
872 : 0 : pkeyjump = JUMP(p, keyjump, LOCAL_JUMP, ALL_TRUE, SHRD | SELF | BOTH);
873 : 0 : KEY(p, KEY1, cipherdata->key_enc_flags, cipherdata->key,
874 : : cipherdata->keylen, INLINE_KEY(cipherdata));
875 : 0 : KEY(p, KEY2, authdata->key_enc_flags, authdata->key, authdata->keylen,
876 : : INLINE_KEY(authdata));
877 : :
878 : : SET_LABEL(p, keyjump);
879 : 0 : PATCH_JUMP(p, pkeyjump, keyjump);
880 : :
881 [ # # ]: 0 : if (sn_size != PDCP_SN_SIZE_18) {
882 : : int pclid;
883 : :
884 [ # # ]: 0 : if (sn_size == PDCP_SN_SIZE_5)
885 : : pclid = OP_PCLID_LTE_PDCP_CTRL_MIXED;
886 : : else
887 : : pclid = OP_PCLID_LTE_PDCP_USER_RN;
888 : :
889 : 0 : PROTOCOL(p, dir, pclid,
890 : : ((uint16_t)cipherdata->algtype << 8) |
891 : : (uint16_t)authdata->algtype);
892 : :
893 : 0 : return 0;
894 : : }
895 : : /* sn_size is 18 */
896 : : offset = 5;
897 : : length = 3;
898 [ # # ]: 0 : sn_mask = (swap == false) ? PDCP_U_PLANE_18BIT_SN_MASK :
899 : : PDCP_U_PLANE_18BIT_SN_MASK_BE;
900 : :
901 : 0 : SEQLOAD(p, MATH0, offset, length, 0);
902 : 0 : JUMP(p, 1, LOCAL_JUMP, ALL_TRUE, CALM);
903 : 0 : MOVEB(p, MATH0, offset, IFIFOAB2, 0, length, IMMED);
904 : 0 : MATHB(p, MATH0, AND, sn_mask, MATH1, 8, IFB | IMMED2);
905 : 0 : MATHB(p, MATH1, SHLD, MATH1, MATH1, 8, 0);
906 : :
907 : 0 : MOVEB(p, DESCBUF, 8, MATH2, 0, 8, WAITCOMP | IMMED);
908 : 0 : MATHB(p, MATH1, OR, MATH2, MATH2, 8, 0);
909 : 0 : MOVEB(p, MATH2, 0, CONTEXT1, 0, 8, IMMED);
910 : :
911 : 0 : MOVEB(p, MATH2, 0, CONTEXT2, 0, 8, WAITCOMP | IMMED);
912 : :
913 [ # # ]: 0 : if (dir == OP_TYPE_ENCAP_PROTOCOL)
914 : 0 : MATHB(p, SEQINSZ, ADD, PDCP_MAC_I_LEN, VSEQOUTSZ, 4, IMMED2);
915 : : else
916 : 0 : MATHB(p, SEQINSZ, SUB, PDCP_MAC_I_LEN, VSEQOUTSZ, 4, IMMED2);
917 : :
918 : 0 : MATHB(p, SEQINSZ, SUB, ZERO, VSEQINSZ, 4, 0);
919 : 0 : SEQSTORE(p, MATH0, offset, length, 0);
920 : :
921 [ # # ]: 0 : if (dir == OP_TYPE_ENCAP_PROTOCOL) {
922 : 0 : SEQFIFOSTORE(p, MSG, 0, 0, VLF);
923 : 0 : SEQFIFOLOAD(p, MSGINSNOOP, 0, VLF | LAST2);
924 : : } else {
925 : 0 : SEQFIFOSTORE(p, MSG, 0, 0, VLF | CONT);
926 : 0 : SEQFIFOLOAD(p, MSGOUTSNOOP, 0, VLF | LAST1 | FLUSH1);
927 : : }
928 : :
929 : 0 : ALG_OPERATION(p, OP_ALG_ALGSEL_ZUCA,
930 : : OP_ALG_AAI_F9,
931 : : OP_ALG_AS_INITFINAL,
932 : : dir == OP_TYPE_ENCAP_PROTOCOL ?
933 : : ICV_CHECK_DISABLE : ICV_CHECK_ENABLE,
934 : : DIR_ENC);
935 : :
936 : 0 : ALG_OPERATION(p, OP_ALG_ALGSEL_ZUCE,
937 : : OP_ALG_AAI_F8,
938 : : OP_ALG_AS_INITFINAL,
939 : : ICV_CHECK_DISABLE,
940 : : dir == OP_TYPE_ENCAP_PROTOCOL ? DIR_ENC : DIR_DEC);
941 : :
942 [ # # ]: 0 : if (dir == OP_TYPE_ENCAP_PROTOCOL) {
943 : 0 : MOVE(p, CONTEXT2, 0, IFIFOAB1, 0, 4, LAST1 | FLUSH1 | IMMED);
944 : : } else {
945 : : /* Save ICV */
946 : 0 : MOVEB(p, OFIFO, 0, MATH0, 0, 4, IMMED);
947 : :
948 : 0 : LOAD(p, NFIFOENTRY_STYPE_ALTSOURCE |
949 : : NFIFOENTRY_DEST_CLASS2 |
950 : : NFIFOENTRY_DTYPE_ICV |
951 : : NFIFOENTRY_LC2 | 4, NFIFO_SZL, 0, 4, IMMED);
952 : 0 : MOVEB(p, MATH0, 0, ALTSOURCE, 0, 4, WAITCOMP | IMMED);
953 : : }
954 : :
955 : : /* Reset ZUCA mode and done interrupt */
956 : 0 : LOAD(p, CLRW_CLR_C2MODE, CLRW, 0, 4, IMMED);
957 : 0 : LOAD(p, CIRQ_ZADI, ICTRL, 0, 4, IMMED);
958 : :
959 : 0 : return 0;
960 : : }
961 : :
962 : : static inline int
963 : 0 : pdcp_insert_uplane_aes_aes_op(struct program *p,
964 : : bool swap __maybe_unused,
965 : : struct alginfo *cipherdata,
966 : : struct alginfo *authdata,
967 : : unsigned int dir,
968 : : enum pdcp_sn_size sn_size)
969 : : {
970 : : uint32_t offset = 0, length = 0, sn_mask = 0;
971 : :
972 [ # # ]: 0 : if (sn_size != PDCP_SN_SIZE_18) {
973 : : /* Insert Auth Key */
974 : 0 : KEY(p, KEY2, authdata->key_enc_flags, authdata->key,
975 : : authdata->keylen, INLINE_KEY(authdata));
976 : :
977 : : /* Insert Cipher Key */
978 : 0 : KEY(p, KEY1, cipherdata->key_enc_flags, cipherdata->key,
979 : : cipherdata->keylen, INLINE_KEY(cipherdata));
980 : :
981 : 0 : PROTOCOL(p, dir, OP_PCLID_LTE_PDCP_USER_RN,
982 : : ((uint16_t)cipherdata->algtype << 8) |
983 : : (uint16_t)authdata->algtype);
984 : 0 : return 0;
985 : : }
986 : :
987 : : /* Non-proto is supported only for 5bit cplane and 18bit uplane */
988 : : switch (sn_size) {
989 : 0 : case PDCP_SN_SIZE_18:
990 : : offset = 5;
991 : : length = 3;
992 [ # # ]: 0 : sn_mask = (swap == false) ? PDCP_U_PLANE_18BIT_SN_MASK :
993 : : PDCP_U_PLANE_18BIT_SN_MASK_BE;
994 : : break;
995 : :
996 : : default:
997 : : pr_err("Invalid sn_size for %s\n", __func__);
998 : : return -ENOTSUP;
999 : : }
1000 : :
1001 : 0 : SEQLOAD(p, MATH0, offset, length, 0);
1002 : 0 : JUMP(p, 1, LOCAL_JUMP, ALL_TRUE, CALM);
1003 : 0 : MATHB(p, MATH0, AND, sn_mask, MATH1, 8, IFB | IMMED2);
1004 : :
1005 : 0 : MATHB(p, MATH1, SHLD, MATH1, MATH1, 8, 0);
1006 : 0 : MOVEB(p, DESCBUF, 8, MATH2, 0, 0x08, WAITCOMP | IMMED);
1007 : 0 : MATHB(p, MATH1, OR, MATH2, MATH2, 8, 0);
1008 : 0 : SEQSTORE(p, MATH0, offset, length, 0);
1009 : :
1010 [ # # ]: 0 : if (dir == OP_TYPE_ENCAP_PROTOCOL) {
1011 : 0 : KEY(p, KEY1, authdata->key_enc_flags, authdata->key,
1012 : : authdata->keylen, INLINE_KEY(authdata));
1013 : 0 : MOVEB(p, MATH2, 0, IFIFOAB1, 0, 0x08, IMMED);
1014 : 0 : MOVEB(p, MATH0, offset, IFIFOAB1, 0, length, IMMED);
1015 : :
1016 : 0 : MATHB(p, SEQINSZ, SUB, ZERO, VSEQINSZ, 4, 0);
1017 : 0 : MATHB(p, VSEQINSZ, ADD, PDCP_MAC_I_LEN, VSEQOUTSZ, 4, IMMED2);
1018 : :
1019 : 0 : ALG_OPERATION(p, OP_ALG_ALGSEL_AES,
1020 : : OP_ALG_AAI_CMAC,
1021 : : OP_ALG_AS_INITFINAL,
1022 : : ICV_CHECK_DISABLE,
1023 : : DIR_DEC);
1024 : 0 : SEQFIFOLOAD(p, MSG1, 0, VLF | LAST1 | FLUSH1);
1025 : 0 : MOVEB(p, CONTEXT1, 0, MATH3, 0, 4, WAITCOMP | IMMED);
1026 : :
1027 : : /* conditional jump with calm added to ensure that the
1028 : : * previous processing has been completed
1029 : : */
1030 : 0 : JUMP(p, 1, LOCAL_JUMP, ALL_TRUE, CALM);
1031 : :
1032 : 0 : LOAD(p, CLRW_RESET_CLS1_CHA |
1033 : : CLRW_CLR_C1KEY |
1034 : : CLRW_CLR_C1CTX |
1035 : : CLRW_CLR_C1ICV |
1036 : : CLRW_CLR_C1DATAS |
1037 : : CLRW_CLR_C1MODE,
1038 : : CLRW, 0, 4, IMMED);
1039 : :
1040 : 0 : KEY(p, KEY1, cipherdata->key_enc_flags, cipherdata->key,
1041 : : cipherdata->keylen, INLINE_KEY(cipherdata));
1042 : :
1043 : 0 : MOVEB(p, MATH2, 0, CONTEXT1, 16, 8, IMMED);
1044 : 0 : SEQINPTR(p, 0, PDCP_NULL_MAX_FRAME_LEN, RTO);
1045 : :
1046 : 0 : ALG_OPERATION(p, OP_ALG_ALGSEL_AES,
1047 : : OP_ALG_AAI_CTR,
1048 : : OP_ALG_AS_INITFINAL,
1049 : : ICV_CHECK_DISABLE,
1050 : : DIR_ENC);
1051 : :
1052 : 0 : SEQFIFOSTORE(p, MSG, 0, 0, VLF);
1053 : :
1054 : 0 : SEQFIFOLOAD(p, SKIP, length, 0);
1055 : :
1056 : 0 : SEQFIFOLOAD(p, MSG1, 0, VLF);
1057 : 0 : MOVEB(p, MATH3, 0, IFIFOAB1, 0, 4, LAST1 | FLUSH1 | IMMED);
1058 : : } else {
1059 : 0 : MOVEB(p, MATH2, 0, CONTEXT1, 16, 8, IMMED);
1060 : 0 : MOVEB(p, MATH2, 0, CONTEXT2, 0, 8, IMMED);
1061 : :
1062 : 0 : MATHB(p, SEQINSZ, SUB, ZERO, VSEQINSZ, 4, 0);
1063 : 0 : MATHB(p, SEQINSZ, SUB, PDCP_MAC_I_LEN, VSEQOUTSZ, 4, IMMED2);
1064 : :
1065 : 0 : KEY(p, KEY1, cipherdata->key_enc_flags, cipherdata->key,
1066 : : cipherdata->keylen, INLINE_KEY(cipherdata));
1067 : :
1068 : 0 : ALG_OPERATION(p, OP_ALG_ALGSEL_AES,
1069 : : OP_ALG_AAI_CTR,
1070 : : OP_ALG_AS_INITFINAL,
1071 : : ICV_CHECK_DISABLE,
1072 : : DIR_DEC);
1073 : :
1074 : 0 : SEQFIFOSTORE(p, MSG, 0, 0, VLF | CONT);
1075 : 0 : SEQFIFOLOAD(p, MSG1, 0, VLF | LAST1 | FLUSH1);
1076 : :
1077 : 0 : MOVEB(p, OFIFO, 0, MATH3, 0, 4, IMMED);
1078 : :
1079 : : /* conditional jump with calm added to ensure that the
1080 : : * previous processing has been completed
1081 : : */
1082 : 0 : JUMP(p, 1, LOCAL_JUMP, ALL_TRUE, CALM);
1083 : :
1084 : 0 : LOAD(p, CLRW_RESET_CLS1_CHA |
1085 : : CLRW_CLR_C1KEY |
1086 : : CLRW_CLR_C1CTX |
1087 : : CLRW_CLR_C1ICV |
1088 : : CLRW_CLR_C1DATAS |
1089 : : CLRW_CLR_C1MODE,
1090 : : CLRW, 0, 4, IMMED);
1091 : :
1092 : 0 : KEY(p, KEY1, authdata->key_enc_flags, authdata->key,
1093 : : authdata->keylen, INLINE_KEY(authdata));
1094 : :
1095 : 0 : SEQINPTR(p, 0, 0, SOP);
1096 : :
1097 : 0 : ALG_OPERATION(p, OP_ALG_ALGSEL_AES,
1098 : : OP_ALG_AAI_CMAC,
1099 : : OP_ALG_AS_INITFINAL,
1100 : : ICV_CHECK_ENABLE,
1101 : : DIR_DEC);
1102 : :
1103 : 0 : MATHB(p, SEQINSZ, SUB, ZERO, VSEQINSZ, 4, 0);
1104 : :
1105 : 0 : MOVE(p, CONTEXT2, 0, IFIFOAB1, 0, 8, IMMED);
1106 : :
1107 : 0 : SEQFIFOLOAD(p, MSG1, 0, VLF | LAST1 | FLUSH1);
1108 : :
1109 : 0 : LOAD(p, NFIFOENTRY_STYPE_ALTSOURCE |
1110 : : NFIFOENTRY_DEST_CLASS1 |
1111 : : NFIFOENTRY_DTYPE_ICV |
1112 : : NFIFOENTRY_LC1 |
1113 : : NFIFOENTRY_FC1 | 4, NFIFO_SZL, 0, 4, IMMED);
1114 : 0 : MOVEB(p, MATH3, 0, ALTSOURCE, 0, 4, IMMED);
1115 : : }
1116 : :
1117 : : return 0;
1118 : : }
1119 : :
1120 : : static inline int
1121 : 0 : pdcp_insert_cplane_acc_op(struct program *p,
1122 : : bool swap __maybe_unused,
1123 : : struct alginfo *cipherdata,
1124 : : struct alginfo *authdata,
1125 : : unsigned int dir,
1126 : : enum pdcp_sn_size sn_size)
1127 : : {
1128 : : /* Insert Auth Key */
1129 : 0 : KEY(p, KEY2, authdata->key_enc_flags, authdata->key, authdata->keylen,
1130 : : INLINE_KEY(authdata));
1131 : :
1132 : : /* Insert Cipher Key */
1133 : 0 : KEY(p, KEY1, cipherdata->key_enc_flags, cipherdata->key,
1134 : : cipherdata->keylen, INLINE_KEY(cipherdata));
1135 : :
1136 [ # # ]: 0 : if (sn_size == PDCP_SN_SIZE_5)
1137 : 0 : PROTOCOL(p, dir, OP_PCLID_LTE_PDCP_CTRL,
1138 : : (uint16_t)cipherdata->algtype);
1139 : : else
1140 : 0 : PROTOCOL(p, dir, OP_PCLID_LTE_PDCP_USER_RN,
1141 : : ((uint16_t)cipherdata->algtype << 8) |
1142 : : (uint16_t)authdata->algtype);
1143 : :
1144 : 0 : return 0;
1145 : : }
1146 : :
1147 : : static inline int
1148 : 0 : pdcp_insert_cplane_snow_aes_op(struct program *p,
1149 : : bool swap __maybe_unused,
1150 : : struct alginfo *cipherdata,
1151 : : struct alginfo *authdata,
1152 : : unsigned int dir,
1153 : : enum pdcp_sn_size sn_size)
1154 : : {
1155 : : uint32_t offset = 0, length = 0, sn_mask = 0;
1156 : :
1157 : : LABEL(back_to_sd_offset);
1158 : : LABEL(end_desc);
1159 : : LABEL(local_offset);
1160 : : LABEL(jump_to_beginning);
1161 : : REFERENCE(seqin_ptr_read);
1162 : : REFERENCE(seqin_ptr_write);
1163 : : REFERENCE(seq_out_read);
1164 : : REFERENCE(jump_back_to_sd_cmd);
1165 : :
1166 [ # # ]: 0 : if ((sn_size != PDCP_SN_SIZE_18) ||
1167 [ # # ]: 0 : (rta_sec_era == RTA_SEC_ERA_10)) {
1168 : 0 : KEY(p, KEY1, cipherdata->key_enc_flags, cipherdata->key,
1169 : : cipherdata->keylen, INLINE_KEY(cipherdata));
1170 : 0 : KEY(p, KEY2, authdata->key_enc_flags, authdata->key,
1171 : : authdata->keylen, INLINE_KEY(authdata));
1172 : :
1173 [ # # ]: 0 : if (sn_size == PDCP_SN_SIZE_5)
1174 : 0 : PROTOCOL(p, dir, OP_PCLID_LTE_PDCP_CTRL_MIXED,
1175 : : ((uint16_t)cipherdata->algtype << 8) |
1176 : : (uint16_t)authdata->algtype);
1177 : : else
1178 : 0 : PROTOCOL(p, dir, OP_PCLID_LTE_PDCP_USER_RN,
1179 : : ((uint16_t)cipherdata->algtype << 8) |
1180 : : (uint16_t)authdata->algtype);
1181 : :
1182 : 0 : return 0;
1183 : : }
1184 : : /* sn_size is 18 */
1185 : : offset = 5;
1186 : : length = 3;
1187 [ # # ]: 0 : sn_mask = (swap == false) ? PDCP_U_PLANE_18BIT_SN_MASK :
1188 : : PDCP_U_PLANE_18BIT_SN_MASK_BE;
1189 : :
1190 : 0 : SEQLOAD(p, MATH0, offset, length, 0);
1191 : 0 : JUMP(p, 1, LOCAL_JUMP, ALL_TRUE, CALM);
1192 : 0 : MATHB(p, MATH0, AND, sn_mask, MATH1, 8, IFB | IMMED2);
1193 : 0 : MATHB(p, MATH1, SHLD, MATH1, MATH1, 8, 0);
1194 : 0 : MOVEB(p, DESCBUF, 4, MATH2, 0, 0x08, WAITCOMP | IMMED);
1195 : 0 : MATHB(p, MATH1, OR, MATH2, MATH2, 8, 0);
1196 : 0 : SEQSTORE(p, MATH0, offset, length, 0);
1197 [ # # ]: 0 : if (dir == OP_TYPE_ENCAP_PROTOCOL) {
1198 : 0 : SEQINPTR(p, 0, length, RTO);
1199 : :
1200 : 0 : KEY(p, KEY1, authdata->key_enc_flags, authdata->key,
1201 : : authdata->keylen, INLINE_KEY(authdata));
1202 : 0 : MOVEB(p, MATH2, 0, IFIFOAB1, 0, 0x08, IMMED);
1203 : :
1204 : 0 : MATHB(p, SEQINSZ, SUB, ZERO, VSEQINSZ, 4, 0);
1205 : 0 : MATHB(p, SEQINSZ, SUB, ZERO, MATH1, 4, 0);
1206 : 0 : MATHB(p, VSEQINSZ, ADD, PDCP_MAC_I_LEN - 1, VSEQOUTSZ,
1207 : : 4, IMMED2);
1208 : :
1209 : : /*
1210 : : * Placeholder for filling the length in
1211 : : * SEQIN PTR RTO below
1212 : : */
1213 : 0 : seqin_ptr_read = MOVE(p, DESCBUF, 0, MATH1, 0, 6, IMMED);
1214 : 0 : seqin_ptr_write = MOVE(p, MATH1, 0, DESCBUF, 0, 8,
1215 : : WAITCOMP | IMMED);
1216 : 0 : ALG_OPERATION(p, OP_ALG_ALGSEL_AES,
1217 : : OP_ALG_AAI_CMAC,
1218 : : OP_ALG_AS_INITFINAL,
1219 : : ICV_CHECK_DISABLE,
1220 : : DIR_DEC);
1221 : 0 : SEQFIFOLOAD(p, MSG1, 0, VLF | LAST1 | FLUSH1);
1222 : 0 : MOVEB(p, CONTEXT1, 0, MATH3, 0, 4, WAITCOMP | IMMED);
1223 : :
1224 : : /* conditional jump with calm added to ensure that the
1225 : : * previous processing has been completed
1226 : : */
1227 : 0 : JUMP(p, 1, LOCAL_JUMP, ALL_TRUE, CALM);
1228 : :
1229 : 0 : LOAD(p, CLRW_RESET_CLS1_CHA |
1230 : : CLRW_CLR_C1KEY |
1231 : : CLRW_CLR_C1CTX |
1232 : : CLRW_CLR_C1ICV |
1233 : : CLRW_CLR_C1DATAS |
1234 : : CLRW_CLR_C1MODE,
1235 : : CLRW, 0, 4, IMMED);
1236 : :
1237 : 0 : KEY(p, KEY1, cipherdata->key_enc_flags, cipherdata->key,
1238 : : cipherdata->keylen, INLINE_KEY(cipherdata));
1239 : : SET_LABEL(p, local_offset);
1240 : 0 : MOVEB(p, MATH2, 0, CONTEXT1, 0, 8, IMMED);
1241 : 0 : SEQINPTR(p, 0, 0, RTO);
1242 : :
1243 : 0 : MATHB(p, SEQINSZ, SUB, length, VSEQINSZ, 4, IMMED2);
1244 : 0 : ALG_OPERATION(p, OP_ALG_ALGSEL_SNOW_F8,
1245 : : OP_ALG_AAI_F8,
1246 : : OP_ALG_AS_INITFINAL,
1247 : : ICV_CHECK_DISABLE,
1248 : : DIR_ENC);
1249 : 0 : SEQFIFOSTORE(p, MSG, 0, 0, VLF);
1250 : :
1251 : 0 : SEQFIFOLOAD(p, SKIP, length, 0);
1252 : :
1253 : 0 : SEQFIFOLOAD(p, MSG1, 0, VLF);
1254 : 0 : MOVEB(p, MATH3, 0, IFIFOAB1, 0, 4, LAST1 | FLUSH1 | IMMED);
1255 : 0 : PATCH_MOVE(p, seqin_ptr_read, local_offset);
1256 : 0 : PATCH_MOVE(p, seqin_ptr_write, local_offset);
1257 : : } else {
1258 : 0 : MOVEB(p, MATH2, 0, CONTEXT1, 0, 8, IMMED);
1259 : :
1260 : 0 : MOVE(p, CONTEXT1, 0, CONTEXT2, 0, 8, IMMED);
1261 : :
1262 : 0 : MATHB(p, SEQINSZ, SUB, ZERO, VSEQINSZ, 4, 0);
1263 : :
1264 : 0 : MATHI(p, SEQINSZ, SUB, PDCP_MAC_I_LEN, VSEQOUTSZ, 4, IMMED2);
1265 : : /*
1266 : : * TODO: To be changed when proper support is added in RTA (can't load a
1267 : : * command that is also written by RTA (or patch it for that matter).
1268 : : * Change when proper RTA support is added.
1269 : : */
1270 [ # # ]: 0 : if (p->ps)
1271 : : WORD(p, 0x168B0004);
1272 : : else
1273 : : WORD(p, 0x16880404);
1274 : :
1275 : 0 : jump_back_to_sd_cmd = JUMP(p, 0, LOCAL_JUMP, ALL_TRUE, 0);
1276 : : /*
1277 : : * Placeholder for command reading the SEQ OUT command in
1278 : : * JD. Done for rereading the decrypted data and performing
1279 : : * the integrity check
1280 : : */
1281 : : /*
1282 : : * TODO: RTA currently doesn't support patching of length of a MOVE command
1283 : : * Thus, it is inserted as a raw word, as per PS setting.
1284 : : */
1285 [ # # ]: 0 : if (p->ps)
1286 : 0 : seq_out_read = MOVE(p, DESCBUF, 0, MATH1, 0, 20,
1287 : : WAITCOMP | IMMED);
1288 : : else
1289 : 0 : seq_out_read = MOVE(p, DESCBUF, 0, MATH1, 0, 16,
1290 : : WAITCOMP | IMMED);
1291 : :
1292 : 0 : MATHB(p, MATH1, XOR, CMD_SEQ_IN_PTR ^ CMD_SEQ_OUT_PTR, MATH1, 4,
1293 : : IMMED2);
1294 : : /* Placeholder for overwriting the SEQ IN with SEQ OUT */
1295 : : /*
1296 : : * TODO: RTA currently doesn't support patching of length of a MOVE command
1297 : : * Thus, it is inserted as a raw word, as per PS setting.
1298 : : */
1299 [ # # ]: 0 : if (p->ps)
1300 : 0 : MOVE(p, MATH1, 0, DESCBUF, 0, 24, IMMED);
1301 : : else
1302 : 0 : MOVE(p, MATH1, 0, DESCBUF, 0, 20, IMMED);
1303 : :
1304 : 0 : KEY(p, KEY1, cipherdata->key_enc_flags, cipherdata->key,
1305 : : cipherdata->keylen, INLINE_KEY(cipherdata));
1306 : :
1307 : 0 : MOVE(p, CONTEXT1, 0, CONTEXT2, 0, 8, IMMED);
1308 : :
1309 : 0 : ALG_OPERATION(p, OP_ALG_ALGSEL_SNOW_F8,
1310 : : OP_ALG_AAI_F8,
1311 : : OP_ALG_AS_INITFINAL,
1312 : : ICV_CHECK_DISABLE,
1313 : : DIR_DEC);
1314 : 0 : SEQFIFOSTORE(p, MSG, 0, 0, VLF | CONT);
1315 : 0 : SEQFIFOLOAD(p, MSG1, 0, VLF | LAST1 | FLUSH1);
1316 : :
1317 : 0 : MOVE(p, OFIFO, 0, MATH3, 0, 4, IMMED);
1318 : :
1319 : 0 : LOAD(p, CLRW_RESET_CLS1_CHA |
1320 : : CLRW_CLR_C1KEY |
1321 : : CLRW_CLR_C1CTX |
1322 : : CLRW_CLR_C1ICV |
1323 : : CLRW_CLR_C1DATAS |
1324 : : CLRW_CLR_C1MODE,
1325 : : CLRW, 0, 4, IMMED);
1326 : :
1327 : 0 : KEY(p, KEY1, authdata->key_enc_flags, authdata->key,
1328 : : authdata->keylen, INLINE_KEY(authdata));
1329 : : /*
1330 : : * Placeholder for jump in SD for executing the new SEQ IN PTR
1331 : : * command (which is actually the old SEQ OUT PTR command
1332 : : * copied over from JD.
1333 : : */
1334 : : SET_LABEL(p, jump_to_beginning);
1335 : 0 : JUMP(p, 1 - jump_to_beginning, LOCAL_JUMP, ALL_TRUE, 0);
1336 : : SET_LABEL(p, back_to_sd_offset);
1337 : 0 : ALG_OPERATION(p, OP_ALG_ALGSEL_AES,
1338 : : OP_ALG_AAI_CMAC,
1339 : : OP_ALG_AS_INITFINAL,
1340 : : ICV_CHECK_ENABLE,
1341 : : DIR_DEC);
1342 : :
1343 : : /* Read the # of bytes written in the output buffer + 1 (HDR) */
1344 : 0 : MATHI(p, VSEQOUTSZ, ADD, length, VSEQINSZ, 4, IMMED2);
1345 : :
1346 : 0 : MOVE(p, CONTEXT2, 0, IFIFOAB1, 0, 8, IMMED);
1347 : :
1348 : 0 : SEQFIFOLOAD(p, MSG1, 0, VLF | LAST1 | FLUSH1);
1349 : :
1350 : 0 : LOAD(p, NFIFOENTRY_STYPE_ALTSOURCE |
1351 : : NFIFOENTRY_DEST_CLASS1 |
1352 : : NFIFOENTRY_DTYPE_ICV |
1353 : : NFIFOENTRY_LC1 |
1354 : : NFIFOENTRY_FC1 | 4, NFIFO_SZL, 0, 4, IMMED);
1355 : 0 : MOVE(p, MATH3, 0, ALTSOURCE, 0, 4, IMMED);
1356 : :
1357 : :
1358 : : SET_LABEL(p, end_desc);
1359 : :
1360 [ # # ]: 0 : if (!p->ps) {
1361 : 0 : PATCH_MOVE(p, seq_out_read, end_desc + 1);
1362 : 0 : PATCH_JUMP(p, jump_back_to_sd_cmd,
1363 : : back_to_sd_offset + jump_back_to_sd_cmd - 5);
1364 : : } else {
1365 : 0 : PATCH_MOVE(p, seq_out_read, end_desc + 2);
1366 : 0 : PATCH_JUMP(p, jump_back_to_sd_cmd,
1367 : : back_to_sd_offset + jump_back_to_sd_cmd - 5);
1368 : : }
1369 : : }
1370 : :
1371 : : return 0;
1372 : : }
1373 : :
1374 : : static inline int
1375 : 0 : pdcp_insert_cplane_aes_snow_op(struct program *p,
1376 : : bool swap __maybe_unused,
1377 : : struct alginfo *cipherdata,
1378 : : struct alginfo *authdata,
1379 : : unsigned int dir,
1380 : : enum pdcp_sn_size sn_size)
1381 : : {
1382 : : uint32_t offset = 0, length = 0, sn_mask = 0;
1383 : :
1384 : 0 : KEY(p, KEY1, cipherdata->key_enc_flags, cipherdata->key,
1385 : : cipherdata->keylen, INLINE_KEY(cipherdata));
1386 : 0 : KEY(p, KEY2, authdata->key_enc_flags, authdata->key, authdata->keylen,
1387 : : INLINE_KEY(authdata));
1388 : :
1389 [ # # ]: 0 : if ((sn_size != PDCP_SN_SIZE_18) ||
1390 [ # # ]: 0 : (rta_sec_era == RTA_SEC_ERA_10)) {
1391 : : int pclid;
1392 : :
1393 [ # # ]: 0 : if (sn_size == PDCP_SN_SIZE_5)
1394 : : pclid = OP_PCLID_LTE_PDCP_CTRL_MIXED;
1395 : : else
1396 : : pclid = OP_PCLID_LTE_PDCP_USER_RN;
1397 : :
1398 : 0 : PROTOCOL(p, dir, pclid,
1399 : : ((uint16_t)cipherdata->algtype << 8) |
1400 : : (uint16_t)authdata->algtype);
1401 : :
1402 : 0 : return 0;
1403 : : }
1404 : : /* sn_size is 18 */
1405 : : offset = 5;
1406 : : length = 3;
1407 [ # # ]: 0 : sn_mask = (swap == false) ? PDCP_U_PLANE_18BIT_SN_MASK :
1408 : : PDCP_U_PLANE_18BIT_SN_MASK_BE;
1409 : :
1410 [ # # ]: 0 : if (dir == OP_TYPE_ENCAP_PROTOCOL)
1411 : 0 : MATHB(p, SEQINSZ, SUB, length, VSEQINSZ, 4, IMMED2);
1412 : :
1413 : 0 : SEQLOAD(p, MATH0, offset, length, 0);
1414 : 0 : JUMP(p, 1, LOCAL_JUMP, ALL_TRUE, CALM);
1415 : 0 : MOVEB(p, MATH0, offset, IFIFOAB2, 0, length, IMMED);
1416 : 0 : MATHB(p, MATH0, AND, sn_mask, MATH1, 8, IFB | IMMED2);
1417 : :
1418 : 0 : SEQSTORE(p, MATH0, offset, length, 0);
1419 : 0 : MATHB(p, MATH1, SHLD, MATH1, MATH1, 8, 0);
1420 : 0 : MOVEB(p, DESCBUF, 4, MATH2, 0, 8, WAITCOMP | IMMED);
1421 : 0 : MATHB(p, MATH1, OR, MATH2, MATH1, 8, 0);
1422 : 0 : MOVEB(p, MATH1, 0, CONTEXT1, 16, 8, IMMED);
1423 : 0 : MOVEB(p, MATH1, 0, CONTEXT2, 0, 4, IMMED);
1424 [ # # ]: 0 : if (swap == false) {
1425 : 0 : MATHB(p, MATH1, AND, upper_32_bits(PDCP_BEARER_MASK), MATH2, 4,
1426 : : IMMED2);
1427 : 0 : MATHB(p, MATH1, AND, lower_32_bits(PDCP_DIR_MASK), MATH3, 4,
1428 : : IMMED2);
1429 : : } else {
1430 : 0 : MATHB(p, MATH1, AND, lower_32_bits(PDCP_BEARER_MASK_BE), MATH2,
1431 : : 4, IMMED2);
1432 : 0 : MATHB(p, MATH1, AND, upper_32_bits(PDCP_DIR_MASK_BE), MATH3,
1433 : : 4, IMMED2);
1434 : : }
1435 : 0 : MATHB(p, MATH3, SHLD, MATH3, MATH3, 8, 0);
1436 : 0 : MOVEB(p, MATH2, 4, OFIFO, 0, 12, IMMED);
1437 : 0 : MOVE(p, OFIFO, 0, CONTEXT2, 4, 12, IMMED);
1438 [ # # ]: 0 : if (dir == OP_TYPE_ENCAP_PROTOCOL) {
1439 : 0 : MATHB(p, SEQINSZ, ADD, PDCP_MAC_I_LEN, VSEQOUTSZ, 4, IMMED2);
1440 : : } else {
1441 : 0 : MATHB(p, SEQINSZ, SUB, PDCP_MAC_I_LEN, MATH1, 4, IMMED2);
1442 : :
1443 : 0 : MATHB(p, ZERO, ADD, MATH1, VSEQOUTSZ, 4, 0);
1444 : 0 : MATHB(p, ZERO, ADD, MATH1, VSEQINSZ, 4, 0);
1445 : : }
1446 : :
1447 [ # # ]: 0 : if (dir == OP_TYPE_ENCAP_PROTOCOL)
1448 : 0 : SEQFIFOSTORE(p, MSG, 0, 0, VLF);
1449 : : else
1450 : 0 : SEQFIFOSTORE(p, MSG, 0, 0, VLF | CONT);
1451 : :
1452 : 0 : ALG_OPERATION(p, OP_ALG_ALGSEL_SNOW_F9,
1453 : : OP_ALG_AAI_F9,
1454 : : OP_ALG_AS_INITFINAL,
1455 : : dir == OP_TYPE_ENCAP_PROTOCOL ?
1456 : : ICV_CHECK_DISABLE : ICV_CHECK_ENABLE,
1457 : : DIR_DEC);
1458 : 0 : ALG_OPERATION(p, OP_ALG_ALGSEL_AES,
1459 : : OP_ALG_AAI_CTR,
1460 : : OP_ALG_AS_INITFINAL,
1461 : : ICV_CHECK_DISABLE,
1462 : : dir == OP_TYPE_ENCAP_PROTOCOL ? DIR_ENC : DIR_DEC);
1463 : :
1464 [ # # ]: 0 : if (dir == OP_TYPE_ENCAP_PROTOCOL) {
1465 : 0 : SEQFIFOLOAD(p, MSGINSNOOP, 0, VLF | LAST2);
1466 : 0 : MOVE(p, CONTEXT2, 0, IFIFOAB1, 0, 4, LAST1 | FLUSH1 | IMMED);
1467 : : } else {
1468 : 0 : SEQFIFOLOAD(p, MSGOUTSNOOP, 0, VLF | LAST2);
1469 : 0 : SEQFIFOLOAD(p, MSG1, 4, LAST1 | FLUSH1);
1470 : 0 : JUMP(p, 1, LOCAL_JUMP, ALL_TRUE, CLASS1 | NOP | NIFP);
1471 : :
1472 : 0 : LOAD(p, 0, DCTRL, 0, LDLEN_RST_CHA_OFIFO_PTR, IMMED);
1473 : :
1474 : 0 : MOVE(p, OFIFO, 0, MATH0, 0, 4, WAITCOMP | IMMED);
1475 : :
1476 : 0 : NFIFOADD(p, IFIFO, ICV2, 4, LAST2);
1477 : :
1478 : 0 : MOVE(p, MATH0, 0, IFIFO, 0, 4, WAITCOMP | IMMED);
1479 : : }
1480 : :
1481 : : return 0;
1482 : : }
1483 : :
1484 : : static inline int
1485 : 0 : pdcp_insert_cplane_snow_zuc_op(struct program *p,
1486 : : bool swap __maybe_unused,
1487 : : struct alginfo *cipherdata,
1488 : : struct alginfo *authdata,
1489 : : unsigned int dir,
1490 : : enum pdcp_sn_size sn_size)
1491 : : {
1492 : : uint32_t offset = 0, length = 0, sn_mask = 0;
1493 : :
1494 : : LABEL(keyjump);
1495 : : REFERENCE(pkeyjump);
1496 : :
1497 [ # # ]: 0 : if ((sn_size != PDCP_SN_SIZE_18) ||
1498 [ # # ]: 0 : (rta_sec_era == RTA_SEC_ERA_10)) {
1499 : : int pclid;
1500 : 0 : KEY(p, KEY1, cipherdata->key_enc_flags, cipherdata->key,
1501 : : cipherdata->keylen, INLINE_KEY(cipherdata));
1502 : 0 : KEY(p, KEY2, authdata->key_enc_flags, authdata->key, authdata->keylen,
1503 : : INLINE_KEY(authdata));
1504 : :
1505 [ # # ]: 0 : if (sn_size == PDCP_SN_SIZE_5)
1506 : : pclid = OP_PCLID_LTE_PDCP_CTRL_MIXED;
1507 : : else
1508 : : pclid = OP_PCLID_LTE_PDCP_USER_RN;
1509 : :
1510 : 0 : PROTOCOL(p, dir, pclid,
1511 : : ((uint16_t)cipherdata->algtype << 8) |
1512 : : (uint16_t)authdata->algtype);
1513 : 0 : return 0;
1514 : : }
1515 : : /* sn_size is 18 */
1516 : : offset = 5;
1517 : : length = 3;
1518 [ # # ]: 0 : sn_mask = (swap == false) ? PDCP_U_PLANE_18BIT_SN_MASK :
1519 : : PDCP_U_PLANE_18BIT_SN_MASK_BE;
1520 : :
1521 : 0 : pkeyjump = JUMP(p, keyjump, LOCAL_JUMP, ALL_TRUE, SHRD | SELF | BOTH);
1522 : 0 : KEY(p, KEY1, cipherdata->key_enc_flags, cipherdata->key,
1523 : : cipherdata->keylen, INLINE_KEY(cipherdata));
1524 : 0 : KEY(p, KEY2, authdata->key_enc_flags, authdata->key, authdata->keylen,
1525 : : INLINE_KEY(authdata));
1526 : :
1527 : : SET_LABEL(p, keyjump);
1528 : 0 : SEQLOAD(p, MATH0, offset, length, 0);
1529 : 0 : JUMP(p, 1, LOCAL_JUMP, ALL_TRUE, CALM);
1530 : 0 : MOVEB(p, MATH0, offset, IFIFOAB2, 0, length, IMMED);
1531 : 0 : MATHB(p, MATH0, AND, sn_mask, MATH1, 8, IFB | IMMED2);
1532 : :
1533 : 0 : MATHB(p, MATH1, SHLD, MATH1, MATH1, 8, 0);
1534 : 0 : MOVEB(p, DESCBUF, 4, MATH2, 0, 8, WAITCOMP | IMMED);
1535 : 0 : MATHB(p, MATH1, OR, MATH2, MATH2, 8, 0);
1536 : 0 : MOVEB(p, MATH2, 0, CONTEXT1, 0, 8, IMMED);
1537 : 0 : MOVEB(p, MATH2, 0, CONTEXT2, 0, 8, WAITCOMP | IMMED);
1538 : :
1539 [ # # ]: 0 : if (dir == OP_TYPE_ENCAP_PROTOCOL)
1540 : 0 : MATHB(p, SEQINSZ, ADD, PDCP_MAC_I_LEN, VSEQOUTSZ, 4, IMMED2);
1541 : : else
1542 : 0 : MATHB(p, SEQINSZ, SUB, PDCP_MAC_I_LEN, VSEQOUTSZ, 4, IMMED2);
1543 : :
1544 : 0 : MATHB(p, SEQINSZ, SUB, ZERO, VSEQINSZ, 4, 0);
1545 : 0 : SEQSTORE(p, MATH0, offset, length, 0);
1546 : :
1547 [ # # ]: 0 : if (dir == OP_TYPE_ENCAP_PROTOCOL) {
1548 : 0 : SEQFIFOSTORE(p, MSG, 0, 0, VLF);
1549 : 0 : SEQFIFOLOAD(p, MSGINSNOOP, 0, VLF | LAST2);
1550 : : } else {
1551 : 0 : SEQFIFOSTORE(p, MSG, 0, 0, VLF | CONT);
1552 : 0 : SEQFIFOLOAD(p, MSGOUTSNOOP, 0, VLF | LAST1 | FLUSH1);
1553 : : }
1554 : :
1555 : 0 : ALG_OPERATION(p, OP_ALG_ALGSEL_ZUCA,
1556 : : OP_ALG_AAI_F9,
1557 : : OP_ALG_AS_INITFINAL,
1558 : : dir == OP_TYPE_ENCAP_PROTOCOL ?
1559 : : ICV_CHECK_DISABLE : ICV_CHECK_ENABLE,
1560 : : DIR_ENC);
1561 : :
1562 : 0 : ALG_OPERATION(p, OP_ALG_ALGSEL_SNOW_F8,
1563 : : OP_ALG_AAI_F8,
1564 : : OP_ALG_AS_INITFINAL,
1565 : : ICV_CHECK_DISABLE,
1566 : : dir == OP_TYPE_ENCAP_PROTOCOL ? DIR_ENC : DIR_DEC);
1567 [ # # ]: 0 : if (dir == OP_TYPE_ENCAP_PROTOCOL) {
1568 : 0 : MOVE(p, CONTEXT2, 0, IFIFOAB1, 0, 4, LAST1 | FLUSH1 | IMMED);
1569 : : } else {
1570 : : /* Save ICV */
1571 : 0 : MOVE(p, OFIFO, 0, MATH0, 0, 4, IMMED);
1572 : 0 : LOAD(p, NFIFOENTRY_STYPE_ALTSOURCE |
1573 : : NFIFOENTRY_DEST_CLASS2 |
1574 : : NFIFOENTRY_DTYPE_ICV |
1575 : : NFIFOENTRY_LC2 | 4, NFIFO_SZL, 0, 4, IMMED);
1576 : 0 : MOVE(p, MATH0, 0, ALTSOURCE, 0, 4, WAITCOMP | IMMED);
1577 : : }
1578 : :
1579 : : /* Reset ZUCA mode and done interrupt */
1580 : 0 : LOAD(p, CLRW_CLR_C2MODE, CLRW, 0, 4, IMMED);
1581 : 0 : LOAD(p, CIRQ_ZADI, ICTRL, 0, 4, IMMED);
1582 : :
1583 : 0 : PATCH_JUMP(p, pkeyjump, keyjump);
1584 : 0 : return 0;
1585 : : }
1586 : :
1587 : : static inline int
1588 : 0 : pdcp_insert_cplane_aes_zuc_op(struct program *p,
1589 : : bool swap __maybe_unused,
1590 : : struct alginfo *cipherdata,
1591 : : struct alginfo *authdata,
1592 : : unsigned int dir,
1593 : : enum pdcp_sn_size sn_size)
1594 : : {
1595 : : uint32_t offset = 0, length = 0, sn_mask = 0;
1596 : : LABEL(keyjump);
1597 : : REFERENCE(pkeyjump);
1598 : :
1599 [ # # ]: 0 : if ((sn_size != PDCP_SN_SIZE_18) ||
1600 [ # # ]: 0 : (rta_sec_era == RTA_SEC_ERA_10)) {
1601 : : int pclid;
1602 : 0 : KEY(p, KEY1, cipherdata->key_enc_flags, cipherdata->key,
1603 : : cipherdata->keylen, INLINE_KEY(cipherdata));
1604 : 0 : KEY(p, KEY2, authdata->key_enc_flags, authdata->key, authdata->keylen,
1605 : : INLINE_KEY(authdata));
1606 : :
1607 [ # # ]: 0 : if (sn_size == PDCP_SN_SIZE_5)
1608 : : pclid = OP_PCLID_LTE_PDCP_CTRL_MIXED;
1609 : : else
1610 : : pclid = OP_PCLID_LTE_PDCP_USER_RN;
1611 : :
1612 : 0 : PROTOCOL(p, dir, pclid,
1613 : : ((uint16_t)cipherdata->algtype << 8) |
1614 : : (uint16_t)authdata->algtype);
1615 : :
1616 : 0 : return 0;
1617 : : }
1618 : : /* sn_size is 18 */
1619 : : offset = 5;
1620 : : length = 3;
1621 [ # # ]: 0 : sn_mask = (swap == false) ? PDCP_U_PLANE_18BIT_SN_MASK :
1622 : : PDCP_U_PLANE_18BIT_SN_MASK_BE;
1623 : :
1624 : 0 : pkeyjump = JUMP(p, keyjump, LOCAL_JUMP, ALL_TRUE, SHRD | SELF | BOTH);
1625 : 0 : KEY(p, KEY1, cipherdata->key_enc_flags, cipherdata->key,
1626 : : cipherdata->keylen, INLINE_KEY(cipherdata));
1627 : 0 : KEY(p, KEY2, authdata->key_enc_flags, authdata->key, authdata->keylen,
1628 : : INLINE_KEY(authdata));
1629 : :
1630 : : SET_LABEL(p, keyjump);
1631 : :
1632 : 0 : SEQLOAD(p, MATH0, offset, length, 0);
1633 : 0 : JUMP(p, 1, LOCAL_JUMP, ALL_TRUE, CALM);
1634 : 0 : MOVEB(p, MATH0, offset, IFIFOAB2, 0, length, IMMED);
1635 : 0 : MATHB(p, MATH0, AND, sn_mask, MATH1, 8, IFB | IMMED2);
1636 : :
1637 : 0 : MATHB(p, MATH1, SHLD, MATH1, MATH1, 8, 0);
1638 : 0 : MOVEB(p, DESCBUF, 4, MATH2, 0, 8, WAITCOMP | IMMED);
1639 : 0 : MATHB(p, MATH1, OR, MATH2, MATH2, 8, 0);
1640 : 0 : MOVEB(p, MATH2, 0, CONTEXT1, 16, 8, IMMED);
1641 : 0 : MOVEB(p, MATH2, 0, CONTEXT2, 0, 8, WAITCOMP | IMMED);
1642 : :
1643 [ # # ]: 0 : if (dir == OP_TYPE_ENCAP_PROTOCOL)
1644 : 0 : MATHB(p, SEQINSZ, ADD, PDCP_MAC_I_LEN, VSEQOUTSZ, 4, IMMED2);
1645 : : else
1646 : 0 : MATHB(p, SEQINSZ, SUB, PDCP_MAC_I_LEN, VSEQOUTSZ, 4, IMMED2);
1647 : :
1648 : 0 : MATHB(p, SEQINSZ, SUB, ZERO, VSEQINSZ, 4, 0);
1649 : 0 : SEQSTORE(p, MATH0, offset, length, 0);
1650 : :
1651 [ # # ]: 0 : if (dir == OP_TYPE_ENCAP_PROTOCOL) {
1652 : 0 : SEQFIFOSTORE(p, MSG, 0, 0, VLF);
1653 : 0 : SEQFIFOLOAD(p, MSGINSNOOP, 0, VLF | LAST2);
1654 : : } else {
1655 : 0 : SEQFIFOSTORE(p, MSG, 0, 0, VLF | CONT);
1656 : 0 : SEQFIFOLOAD(p, MSGOUTSNOOP, 0, VLF | LAST1 | FLUSH1);
1657 : : }
1658 : :
1659 : 0 : ALG_OPERATION(p, OP_ALG_ALGSEL_ZUCA,
1660 : : OP_ALG_AAI_F9,
1661 : : OP_ALG_AS_INITFINAL,
1662 : : dir == OP_TYPE_ENCAP_PROTOCOL ?
1663 : : ICV_CHECK_DISABLE : ICV_CHECK_ENABLE,
1664 : : DIR_ENC);
1665 : :
1666 : 0 : ALG_OPERATION(p, OP_ALG_ALGSEL_AES,
1667 : : OP_ALG_AAI_CTR,
1668 : : OP_ALG_AS_INITFINAL,
1669 : : ICV_CHECK_DISABLE,
1670 : : dir == OP_TYPE_ENCAP_PROTOCOL ? DIR_ENC : DIR_DEC);
1671 : :
1672 [ # # ]: 0 : if (dir == OP_TYPE_ENCAP_PROTOCOL) {
1673 : 0 : MOVE(p, CONTEXT2, 0, IFIFOAB1, 0, 4, LAST1 | FLUSH1 | IMMED);
1674 : : } else {
1675 : : /* Save ICV */
1676 : 0 : MOVE(p, OFIFO, 0, MATH0, 0, 4, IMMED);
1677 : :
1678 : 0 : LOAD(p, NFIFOENTRY_STYPE_ALTSOURCE |
1679 : : NFIFOENTRY_DEST_CLASS2 |
1680 : : NFIFOENTRY_DTYPE_ICV |
1681 : : NFIFOENTRY_LC2 | 4, NFIFO_SZL, 0, 4, IMMED);
1682 : 0 : MOVE(p, MATH0, 0, ALTSOURCE, 0, 4, WAITCOMP | IMMED);
1683 : : }
1684 : :
1685 : : /* Reset ZUCA mode and done interrupt */
1686 : 0 : LOAD(p, CLRW_CLR_C2MODE, CLRW, 0, 4, IMMED);
1687 : 0 : LOAD(p, CIRQ_ZADI, ICTRL, 0, 4, IMMED);
1688 : :
1689 : 0 : PATCH_JUMP(p, pkeyjump, keyjump);
1690 : :
1691 : 0 : return 0;
1692 : : }
1693 : :
1694 : : static inline int
1695 : 0 : pdcp_insert_cplane_zuc_snow_op(struct program *p,
1696 : : bool swap __maybe_unused,
1697 : : struct alginfo *cipherdata,
1698 : : struct alginfo *authdata,
1699 : : unsigned int dir,
1700 : : enum pdcp_sn_size sn_size)
1701 : : {
1702 : : uint32_t offset = 0, length = 0, sn_mask = 0;
1703 : : LABEL(keyjump);
1704 : : REFERENCE(pkeyjump);
1705 : :
1706 [ # # ]: 0 : if ((sn_size != PDCP_SN_SIZE_18) ||
1707 [ # # ]: 0 : (rta_sec_era == RTA_SEC_ERA_10)) {
1708 : : int pclid;
1709 : 0 : KEY(p, KEY1, cipherdata->key_enc_flags, cipherdata->key,
1710 : : cipherdata->keylen, INLINE_KEY(cipherdata));
1711 : 0 : KEY(p, KEY2, authdata->key_enc_flags, authdata->key, authdata->keylen,
1712 : : INLINE_KEY(authdata));
1713 : :
1714 [ # # ]: 0 : if (sn_size == PDCP_SN_SIZE_5)
1715 : : pclid = OP_PCLID_LTE_PDCP_CTRL_MIXED;
1716 : : else
1717 : : pclid = OP_PCLID_LTE_PDCP_USER_RN;
1718 : :
1719 : 0 : PROTOCOL(p, dir, pclid,
1720 : : ((uint16_t)cipherdata->algtype << 8) |
1721 : : (uint16_t)authdata->algtype);
1722 : :
1723 : 0 : return 0;
1724 : : }
1725 : : /* sn_size is 18 */
1726 : : offset = 5;
1727 : : length = 3;
1728 [ # # ]: 0 : sn_mask = (swap == false) ? PDCP_U_PLANE_18BIT_SN_MASK :
1729 : : PDCP_U_PLANE_18BIT_SN_MASK_BE;
1730 : :
1731 : 0 : pkeyjump = JUMP(p, keyjump, LOCAL_JUMP, ALL_TRUE, SHRD | SELF | BOTH);
1732 : 0 : KEY(p, KEY1, cipherdata->key_enc_flags, cipherdata->key,
1733 : : cipherdata->keylen, INLINE_KEY(cipherdata));
1734 : 0 : KEY(p, KEY2, authdata->key_enc_flags, authdata->key, authdata->keylen,
1735 : : INLINE_KEY(authdata));
1736 : :
1737 : : SET_LABEL(p, keyjump);
1738 : 0 : SEQLOAD(p, MATH0, offset, length, 0);
1739 : 0 : JUMP(p, 1, LOCAL_JUMP, ALL_TRUE, CALM);
1740 : 0 : MOVEB(p, MATH0, offset, IFIFOAB2, 0, length, IMMED);
1741 : 0 : MATHB(p, MATH0, AND, sn_mask, MATH1, 8, IFB | IMMED2);
1742 : :
1743 : 0 : MATHB(p, MATH1, SHLD, MATH1, MATH1, 8, 0);
1744 : 0 : MOVEB(p, DESCBUF, 4, MATH2, 0, 8, WAITCOMP | IMMED);
1745 : 0 : MATHB(p, MATH1, OR, MATH2, MATH1, 8, 0);
1746 : 0 : MOVEB(p, MATH1, 0, CONTEXT1, 0, 8, IMMED);
1747 : 0 : MOVEB(p, MATH1, 0, CONTEXT2, 0, 4, IMMED);
1748 [ # # ]: 0 : if (swap == false) {
1749 : 0 : MATHB(p, MATH1, AND, upper_32_bits(PDCP_BEARER_MASK), MATH2,
1750 : : 4, IMMED2);
1751 : 0 : MATHB(p, MATH1, AND, lower_32_bits(PDCP_DIR_MASK), MATH3,
1752 : : 4, IMMED2);
1753 : : } else {
1754 : 0 : MATHB(p, MATH1, AND, lower_32_bits(PDCP_BEARER_MASK_BE), MATH2,
1755 : : 4, IMMED2);
1756 : 0 : MATHB(p, MATH1, AND, upper_32_bits(PDCP_DIR_MASK_BE), MATH3,
1757 : : 4, IMMED2);
1758 : : }
1759 : 0 : MATHB(p, MATH3, SHLD, MATH3, MATH3, 8, 0);
1760 : 0 : MOVEB(p, MATH2, 4, OFIFO, 0, 12, IMMED);
1761 : 0 : MOVE(p, OFIFO, 0, CONTEXT2, 4, 12, IMMED);
1762 : :
1763 [ # # ]: 0 : if (dir == OP_TYPE_ENCAP_PROTOCOL) {
1764 : 0 : MATHB(p, SEQINSZ, ADD, PDCP_MAC_I_LEN, VSEQOUTSZ, 4, IMMED2);
1765 : 0 : MATHB(p, SEQINSZ, SUB, ZERO, VSEQINSZ, 4, 0);
1766 : : } else {
1767 : 0 : MATHB(p, SEQINSZ, SUB, PDCP_MAC_I_LEN, VSEQOUTSZ, 4, IMMED2);
1768 : 0 : MATHB(p, VSEQOUTSZ, SUB, ZERO, VSEQINSZ, 4, 0);
1769 : : }
1770 : :
1771 : 0 : SEQSTORE(p, MATH0, offset, length, 0);
1772 : :
1773 [ # # ]: 0 : if (dir == OP_TYPE_ENCAP_PROTOCOL) {
1774 : 0 : SEQFIFOSTORE(p, MSG, 0, 0, VLF);
1775 : 0 : SEQFIFOLOAD(p, MSGINSNOOP, 0, VLF | LAST2);
1776 : : } else {
1777 : 0 : SEQFIFOSTORE(p, MSG, 0, 0, VLF | CONT);
1778 : 0 : SEQFIFOLOAD(p, MSGOUTSNOOP, 0, VLF | LAST2);
1779 : : }
1780 : :
1781 : 0 : ALG_OPERATION(p, OP_ALG_ALGSEL_SNOW_F9,
1782 : : OP_ALG_AAI_F9,
1783 : : OP_ALG_AS_INITFINAL,
1784 : : dir == OP_TYPE_ENCAP_PROTOCOL ?
1785 : : ICV_CHECK_DISABLE : ICV_CHECK_ENABLE,
1786 : : DIR_DEC);
1787 : :
1788 : 0 : ALG_OPERATION(p, OP_ALG_ALGSEL_ZUCE,
1789 : : OP_ALG_AAI_F8,
1790 : : OP_ALG_AS_INITFINAL,
1791 : : ICV_CHECK_DISABLE,
1792 : : dir == OP_TYPE_ENCAP_PROTOCOL ? DIR_ENC : DIR_DEC);
1793 : :
1794 [ # # ]: 0 : if (dir == OP_TYPE_ENCAP_PROTOCOL) {
1795 : 0 : MOVE(p, CONTEXT2, 0, IFIFOAB1, 0, 4, LAST1 | FLUSH1 | IMMED);
1796 : : } else {
1797 : 0 : SEQFIFOLOAD(p, MSG1, 4, LAST1 | FLUSH1);
1798 : 0 : JUMP(p, 1, LOCAL_JUMP, ALL_TRUE, CLASS1 | NOP | NIFP);
1799 : :
1800 : : /*
1801 : : * For SEC ERA 6, there's a problem with the OFIFO
1802 : : * pointer, and thus it needs to be reset here before
1803 : : * moving to M0.
1804 : : */
1805 : 0 : LOAD(p, 0, DCTRL, 0, LDLEN_RST_CHA_OFIFO_PTR, IMMED);
1806 : :
1807 : : /* Put ICV to M0 before sending it to C2 for comparison. */
1808 : 0 : MOVEB(p, OFIFO, 0, MATH0, 0, 4, WAITCOMP | IMMED);
1809 : :
1810 : 0 : LOAD(p, NFIFOENTRY_STYPE_ALTSOURCE |
1811 : : NFIFOENTRY_DEST_CLASS2 |
1812 : : NFIFOENTRY_DTYPE_ICV |
1813 : : NFIFOENTRY_LC2 | 4, NFIFO_SZL, 0, 4, IMMED);
1814 : 0 : MOVEB(p, MATH0, 0, ALTSOURCE, 0, 4, IMMED);
1815 : : }
1816 : :
1817 : 0 : PATCH_JUMP(p, pkeyjump, keyjump);
1818 : 0 : return 0;
1819 : : }
1820 : :
1821 : : static inline int
1822 : 0 : pdcp_insert_cplane_zuc_aes_op(struct program *p,
1823 : : bool swap __maybe_unused,
1824 : : struct alginfo *cipherdata,
1825 : : struct alginfo *authdata,
1826 : : unsigned int dir,
1827 : : enum pdcp_sn_size sn_size)
1828 : : {
1829 : : uint32_t offset = 0, length = 0, sn_mask = 0;
1830 : :
1831 [ # # ]: 0 : if ((sn_size != PDCP_SN_SIZE_18) ||
1832 [ # # ]: 0 : (rta_sec_era == RTA_SEC_ERA_10)) {
1833 : : int pclid;
1834 : :
1835 : 0 : KEY(p, KEY1, cipherdata->key_enc_flags, cipherdata->key,
1836 : : cipherdata->keylen, INLINE_KEY(cipherdata));
1837 : 0 : KEY(p, KEY2, authdata->key_enc_flags, authdata->key,
1838 : : authdata->keylen, INLINE_KEY(authdata));
1839 : :
1840 [ # # ]: 0 : if (sn_size == PDCP_SN_SIZE_5)
1841 : : pclid = OP_PCLID_LTE_PDCP_CTRL_MIXED;
1842 : : else
1843 : : pclid = OP_PCLID_LTE_PDCP_USER_RN;
1844 : :
1845 : 0 : PROTOCOL(p, dir, pclid,
1846 : : ((uint16_t)cipherdata->algtype << 8) |
1847 : : (uint16_t)authdata->algtype);
1848 : 0 : return 0;
1849 : : }
1850 : :
1851 : : /* sn_size is 18 */
1852 : : offset = 5;
1853 : : length = 3;
1854 [ # # ]: 0 : sn_mask = (swap == false) ? PDCP_U_PLANE_18BIT_SN_MASK :
1855 : : PDCP_U_PLANE_18BIT_SN_MASK_BE;
1856 : :
1857 : 0 : SEQLOAD(p, MATH0, offset, length, 0);
1858 : 0 : JUMP(p, 1, LOCAL_JUMP, ALL_TRUE, CALM);
1859 : 0 : MATHB(p, MATH0, AND, sn_mask, MATH1, 8, IFB | IMMED2);
1860 : :
1861 : 0 : MATHB(p, MATH1, SHLD, MATH1, MATH1, 8, 0);
1862 : 0 : MOVEB(p, DESCBUF, 4, MATH2, 0, 0x08, WAITCOMP | IMMED);
1863 : 0 : MATHB(p, MATH1, OR, MATH2, MATH2, 8, 0);
1864 : 0 : SEQSTORE(p, MATH0, offset, length, 0);
1865 [ # # ]: 0 : if (dir == OP_TYPE_ENCAP_PROTOCOL) {
1866 : 0 : KEY(p, KEY1, authdata->key_enc_flags, authdata->key,
1867 : : authdata->keylen, INLINE_KEY(authdata));
1868 : 0 : MOVEB(p, MATH2, 0, IFIFOAB1, 0, 0x08, IMMED);
1869 : 0 : MOVEB(p, MATH0, offset, IFIFOAB1, 0, length, IMMED);
1870 : :
1871 : 0 : MATHB(p, SEQINSZ, SUB, ZERO, VSEQINSZ, 4, 0);
1872 : 0 : MATHB(p, VSEQINSZ, ADD, PDCP_MAC_I_LEN, VSEQOUTSZ, 4, IMMED2);
1873 : :
1874 : 0 : ALG_OPERATION(p, OP_ALG_ALGSEL_AES,
1875 : : OP_ALG_AAI_CMAC,
1876 : : OP_ALG_AS_INITFINAL,
1877 : : ICV_CHECK_DISABLE,
1878 : : DIR_DEC);
1879 : 0 : SEQFIFOLOAD(p, MSG1, 0, VLF | LAST1 | FLUSH1);
1880 : 0 : MOVEB(p, CONTEXT1, 0, MATH3, 0, 4, WAITCOMP | IMMED);
1881 : 0 : LOAD(p, CLRW_RESET_CLS1_CHA |
1882 : : CLRW_CLR_C1KEY |
1883 : : CLRW_CLR_C1CTX |
1884 : : CLRW_CLR_C1ICV |
1885 : : CLRW_CLR_C1DATAS |
1886 : : CLRW_CLR_C1MODE,
1887 : : CLRW, 0, 4, IMMED);
1888 : :
1889 : 0 : KEY(p, KEY1, cipherdata->key_enc_flags, cipherdata->key,
1890 : : cipherdata->keylen, INLINE_KEY(cipherdata));
1891 : :
1892 : 0 : MOVEB(p, MATH2, 0, CONTEXT1, 0, 8, IMMED);
1893 : 0 : SEQINPTR(p, 0, PDCP_NULL_MAX_FRAME_LEN, RTO);
1894 : :
1895 : 0 : ALG_OPERATION(p, OP_ALG_ALGSEL_ZUCE,
1896 : : OP_ALG_AAI_F8,
1897 : : OP_ALG_AS_INITFINAL,
1898 : : ICV_CHECK_DISABLE,
1899 : : DIR_ENC);
1900 : 0 : SEQFIFOSTORE(p, MSG, 0, 0, VLF);
1901 : :
1902 : 0 : SEQFIFOLOAD(p, SKIP, length, 0);
1903 : :
1904 : 0 : SEQFIFOLOAD(p, MSG1, 0, VLF);
1905 : 0 : MOVEB(p, MATH3, 0, IFIFOAB1, 0, 4, LAST1 | FLUSH1 | IMMED);
1906 : : } else {
1907 : 0 : MOVEB(p, MATH2, 0, CONTEXT1, 0, 8, IMMED);
1908 : :
1909 : 0 : MOVE(p, CONTEXT1, 0, CONTEXT2, 0, 8, IMMED);
1910 : :
1911 : 0 : MATHB(p, SEQINSZ, SUB, ZERO, VSEQINSZ, 4, 0);
1912 : :
1913 : 0 : MATHB(p, SEQINSZ, SUB, PDCP_MAC_I_LEN, VSEQOUTSZ, 4, IMMED2);
1914 : :
1915 : 0 : KEY(p, KEY1, cipherdata->key_enc_flags, cipherdata->key,
1916 : : cipherdata->keylen, INLINE_KEY(cipherdata));
1917 : :
1918 : 0 : MOVE(p, CONTEXT1, 0, CONTEXT2, 0, 8, IMMED);
1919 : :
1920 : 0 : ALG_OPERATION(p, OP_ALG_ALGSEL_ZUCE,
1921 : : OP_ALG_AAI_F8,
1922 : : OP_ALG_AS_INITFINAL,
1923 : : ICV_CHECK_DISABLE,
1924 : : DIR_DEC);
1925 : 0 : SEQFIFOSTORE(p, MSG, 0, 0, VLF | CONT);
1926 : 0 : SEQFIFOLOAD(p, MSG1, 0, VLF | LAST1 | FLUSH1);
1927 : :
1928 : 0 : MOVEB(p, OFIFO, 0, MATH3, 0, 4, IMMED);
1929 : :
1930 : : /* conditional jump with calm added to ensure that the
1931 : : * previous processing has been completed
1932 : : */
1933 : 0 : JUMP(p, 1, LOCAL_JUMP, ALL_TRUE, CALM);
1934 : :
1935 : 0 : LOAD(p, CLRW_RESET_CLS1_CHA |
1936 : : CLRW_CLR_C1KEY |
1937 : : CLRW_CLR_C1CTX |
1938 : : CLRW_CLR_C1ICV |
1939 : : CLRW_CLR_C1DATAS |
1940 : : CLRW_CLR_C1MODE,
1941 : : CLRW, 0, 4, IMMED);
1942 : :
1943 : 0 : KEY(p, KEY1, authdata->key_enc_flags, authdata->key,
1944 : : authdata->keylen, INLINE_KEY(authdata));
1945 : :
1946 : 0 : SEQINPTR(p, 0, 0, SOP);
1947 : :
1948 : 0 : ALG_OPERATION(p, OP_ALG_ALGSEL_AES,
1949 : : OP_ALG_AAI_CMAC,
1950 : : OP_ALG_AS_INITFINAL,
1951 : : ICV_CHECK_ENABLE,
1952 : : DIR_DEC);
1953 : :
1954 : 0 : MATHB(p, SEQINSZ, SUB, ZERO, VSEQINSZ, 4, 0);
1955 : :
1956 : 0 : MOVE(p, CONTEXT2, 0, IFIFOAB1, 0, 8, IMMED);
1957 : :
1958 : 0 : SEQFIFOLOAD(p, MSG1, 0, VLF | LAST1 | FLUSH1);
1959 : :
1960 : 0 : LOAD(p, NFIFOENTRY_STYPE_ALTSOURCE |
1961 : : NFIFOENTRY_DEST_CLASS1 |
1962 : : NFIFOENTRY_DTYPE_ICV |
1963 : : NFIFOENTRY_LC1 |
1964 : : NFIFOENTRY_FC1 | 4, NFIFO_SZL, 0, 4, IMMED);
1965 : 0 : MOVEB(p, MATH3, 0, ALTSOURCE, 0, 4, IMMED);
1966 : : }
1967 : :
1968 : : return 0;
1969 : : }
1970 : :
1971 : : static inline int
1972 : 0 : pdcp_insert_uplane_no_int_op(struct program *p,
1973 : : bool swap __maybe_unused,
1974 : : struct alginfo *cipherdata,
1975 : : unsigned int dir,
1976 : : enum pdcp_sn_size sn_size)
1977 : : {
1978 : : int op;
1979 : : uint32_t sn_mask;
1980 : :
1981 : : /* Insert Cipher Key */
1982 : 0 : KEY(p, KEY1, cipherdata->key_enc_flags, cipherdata->key,
1983 : : cipherdata->keylen, INLINE_KEY(cipherdata));
1984 : :
1985 [ # # ]: 0 : if (sn_size == PDCP_SN_SIZE_15) {
1986 : 0 : PROTOCOL(p, dir, OP_PCLID_LTE_PDCP_USER,
1987 : : (uint16_t)cipherdata->algtype);
1988 : 0 : return 0;
1989 : : }
1990 : :
1991 [ # # ]: 0 : if (sn_size == PDCP_SN_SIZE_12) {
1992 : 0 : SEQLOAD(p, MATH0, 6, 2, 0);
1993 [ # # ]: 0 : sn_mask = (swap == false) ? PDCP_12BIT_SN_MASK :
1994 : : PDCP_12BIT_SN_MASK_BE;
1995 : : } else { /* SN Size == PDCP_SN_SIZE_18 */
1996 : 0 : SEQLOAD(p, MATH0, 5, 3, 0);
1997 [ # # ]: 0 : sn_mask = (swap == false) ? PDCP_U_PLANE_18BIT_SN_MASK :
1998 : : PDCP_U_PLANE_18BIT_SN_MASK_BE;
1999 : : }
2000 : 0 : JUMP(p, 1, LOCAL_JUMP, ALL_TRUE, CALM);
2001 : 0 : MATHB(p, MATH0, AND, sn_mask, MATH1, 8, IFB | IMMED2);
2002 : :
2003 [ # # ]: 0 : if (sn_size == PDCP_SN_SIZE_12)
2004 : 0 : SEQSTORE(p, MATH0, 6, 2, 0);
2005 : : else /* SN Size == PDCP_SN_SIZE_18 */
2006 : 0 : SEQSTORE(p, MATH0, 5, 3, 0);
2007 : :
2008 : 0 : MATHB(p, MATH1, SHLD, MATH1, MATH1, 8, 0);
2009 : 0 : MOVEB(p, DESCBUF, 8, MATH2, 0, 8, WAITCOMP | IMMED);
2010 : 0 : MATHB(p, MATH1, OR, MATH2, MATH2, 8, 0);
2011 : :
2012 : 0 : MATHB(p, SEQINSZ, SUB, MATH3, VSEQINSZ, 4, 0);
2013 : 0 : MATHB(p, SEQINSZ, SUB, MATH3, VSEQOUTSZ, 4, 0);
2014 : :
2015 : 0 : SEQFIFOSTORE(p, MSG, 0, 0, VLF);
2016 : :
2017 : 0 : op = dir == OP_TYPE_ENCAP_PROTOCOL ? DIR_ENC : DIR_DEC;
2018 [ # # # # ]: 0 : switch (cipherdata->algtype) {
2019 : 0 : case PDCP_CIPHER_TYPE_SNOW:
2020 : 0 : MOVEB(p, MATH2, 0, CONTEXT1, 0, 8, WAITCOMP | IMMED);
2021 : 0 : ALG_OPERATION(p, OP_ALG_ALGSEL_SNOW_F8,
2022 : : OP_ALG_AAI_F8,
2023 : : OP_ALG_AS_INITFINAL,
2024 : : ICV_CHECK_DISABLE,
2025 : : op);
2026 : 0 : break;
2027 : :
2028 : 0 : case PDCP_CIPHER_TYPE_AES:
2029 : 0 : MOVEB(p, MATH2, 0, CONTEXT1, 0x10, 0x10, WAITCOMP | IMMED);
2030 : 0 : ALG_OPERATION(p, OP_ALG_ALGSEL_AES,
2031 : : OP_ALG_AAI_CTR,
2032 : : OP_ALG_AS_INITFINAL,
2033 : : ICV_CHECK_DISABLE,
2034 : : op);
2035 : 0 : break;
2036 : :
2037 : 0 : case PDCP_CIPHER_TYPE_ZUC:
2038 : 0 : MOVEB(p, MATH2, 0, CONTEXT1, 0, 0x08, IMMED);
2039 : 0 : MOVEB(p, MATH2, 0, CONTEXT1, 0x08, 0x08, WAITCOMP | IMMED);
2040 : :
2041 : 0 : ALG_OPERATION(p, OP_ALG_ALGSEL_ZUCE,
2042 : : OP_ALG_AAI_F8,
2043 : : OP_ALG_AS_INITFINAL,
2044 : : ICV_CHECK_DISABLE,
2045 : : op);
2046 : 0 : break;
2047 : :
2048 : 0 : default:
2049 : 0 : pr_err("%s: Invalid encrypt algorithm selected: %d\n",
2050 : : "pdcp_insert_uplane_no_int_op", cipherdata->algtype);
2051 : 0 : return -EINVAL;
2052 : : }
2053 : :
2054 : 0 : SEQFIFOLOAD(p, MSG1, 0, VLF | LAST1 | FLUSH1);
2055 : :
2056 : 0 : return 0;
2057 : : }
2058 : :
2059 : : /*
2060 : : * Function for inserting the snippet of code responsible for creating
2061 : : * the HFN override code via either DPOVRD or via the input frame.
2062 : : */
2063 : : static inline int
2064 : 0 : insert_hfn_ov_op(struct program *p,
2065 : : uint32_t shift,
2066 : : enum pdb_type_e pdb_type,
2067 : : bool clear_dpovrd_at_end)
2068 : : {
2069 : : uint32_t imm = PDCP_DPOVRD_HFN_OV_EN;
2070 : : uint16_t hfn_pdb_offset;
2071 : : LABEL(keyjump);
2072 : : REFERENCE(pkeyjump);
2073 : :
2074 [ # # # # ]: 0 : switch (pdb_type) {
2075 : : case PDCP_PDB_TYPE_NO_PDB:
2076 : : /*
2077 : : * If there is no PDB, then HFN override mechanism does not
2078 : : * make any sense, thus in this case the function will
2079 : : * return the pointer to the current position in the
2080 : : * descriptor buffer
2081 : : */
2082 : : return 0;
2083 : :
2084 : : case PDCP_PDB_TYPE_REDUCED_PDB:
2085 : : hfn_pdb_offset = REDUCED_PDB_DESCBUF_HFN_BEARER_DIR_OFFSET;
2086 : : break;
2087 : :
2088 : 0 : case PDCP_PDB_TYPE_FULL_PDB:
2089 : : hfn_pdb_offset = FULL_PDB_DESCBUF_HFN_BEARER_DIR_OFFSET;
2090 : 0 : break;
2091 : :
2092 : 0 : default:
2093 : 0 : return -EINVAL;
2094 : : }
2095 : :
2096 : 0 : MATHB(p, DPOVRD, AND, imm, NONE, 8, IFB | IMMED2);
2097 : :
2098 : 0 : pkeyjump = JUMP(p, keyjump, LOCAL_JUMP, ALL_TRUE, MATH_Z);
2099 : :
2100 : 0 : MATHI(p, DPOVRD, LSHIFT, shift, MATH0, 4, IMMED2);
2101 : :
2102 : 0 : MATHB(p, MATH0, SHLD, MATH0, MATH0, 8, 0);
2103 : 0 : MOVE(p, MATH0, 0, DESCBUF, hfn_pdb_offset, 4, IMMED);
2104 : :
2105 [ # # ]: 0 : if (clear_dpovrd_at_end) {
2106 : : /*
2107 : : * For ERA8, DPOVRD could be handled by the PROTOCOL command
2108 : : * itself. For now, this is not done. Thus, clear DPOVRD here
2109 : : * to alleviate any side-effects.
2110 : : */
2111 : 0 : MATHB(p, DPOVRD, AND, ZERO, DPOVRD, 4, STL);
2112 : : }
2113 : :
2114 : : SET_LABEL(p, keyjump);
2115 : 0 : PATCH_JUMP(p, pkeyjump, keyjump);
2116 : 0 : return 0;
2117 : : }
2118 : :
2119 : : /*
2120 : : * PDCP Control PDB creation function
2121 : : */
2122 : : static inline enum pdb_type_e
2123 [ # # ]: 0 : cnstr_pdcp_c_plane_pdb(struct program *p,
2124 : : uint32_t hfn,
2125 : : enum pdcp_sn_size sn_size,
2126 : : unsigned char bearer,
2127 : : unsigned char direction,
2128 : : uint32_t hfn_threshold)
2129 : : {
2130 : : struct pdcp_pdb pdb;
2131 : :
2132 : : memset(&pdb, 0x00, sizeof(struct pdcp_pdb));
2133 : :
2134 : : /* To support 12-bit seq numbers, we use u-plane opt in pdb.
2135 : : * SEC supports 5-bit only with c-plane opt in pdb.
2136 : : */
2137 [ # # ]: 0 : if (sn_size == PDCP_SN_SIZE_12) {
2138 : 0 : pdb.hfn_res = hfn << PDCP_U_PLANE_PDB_LONG_SN_HFN_SHIFT;
2139 : 0 : pdb.bearer_dir_res = (uint32_t)
2140 : 0 : ((bearer << PDCP_U_PLANE_PDB_BEARER_SHIFT) |
2141 : 0 : (direction << PDCP_U_PLANE_PDB_DIR_SHIFT));
2142 : :
2143 : 0 : pdb.hfn_thr_res =
2144 : 0 : hfn_threshold << PDCP_U_PLANE_PDB_LONG_SN_HFN_THR_SHIFT;
2145 : :
2146 : : } else {
2147 : : /* This means 5-bit c-plane.
2148 : : * Here we use c-plane opt in pdb
2149 : : */
2150 : :
2151 : : /* This is a HW issue. Bit 2 should be set to zero,
2152 : : * but it does not work this way. Override here.
2153 : : */
2154 : 0 : pdb.opt_res.rsvd = 0x00000002;
2155 : :
2156 : : /* Copy relevant information from user to PDB */
2157 : 0 : pdb.hfn_res = hfn << PDCP_C_PLANE_PDB_HFN_SHIFT;
2158 : 0 : pdb.bearer_dir_res = (uint32_t)
2159 : 0 : ((bearer << PDCP_C_PLANE_PDB_BEARER_SHIFT) |
2160 : 0 : (direction << PDCP_C_PLANE_PDB_DIR_SHIFT));
2161 : 0 : pdb.hfn_thr_res =
2162 : 0 : hfn_threshold << PDCP_C_PLANE_PDB_HFN_THR_SHIFT;
2163 : : }
2164 : :
2165 : : /* copy PDB in descriptor*/
2166 : 0 : __rta_out32(p, pdb.opt_res.opt);
2167 : 0 : __rta_out32(p, pdb.hfn_res);
2168 : 0 : __rta_out32(p, pdb.bearer_dir_res);
2169 : 0 : __rta_out32(p, pdb.hfn_thr_res);
2170 : :
2171 : 0 : return PDCP_PDB_TYPE_FULL_PDB;
2172 : : }
2173 : :
2174 : : /*
2175 : : * PDCP UPlane PDB creation function
2176 : : */
2177 : : static inline enum pdb_type_e
2178 : 0 : cnstr_pdcp_u_plane_pdb(struct program *p,
2179 : : enum pdcp_sn_size sn_size,
2180 : : uint32_t hfn, unsigned short bearer,
2181 : : unsigned short direction,
2182 : : uint32_t hfn_threshold,
2183 : : struct alginfo *cipherdata,
2184 : : struct alginfo *authdata)
2185 : : {
2186 : : struct pdcp_pdb pdb;
2187 : : enum pdb_type_e pdb_type = PDCP_PDB_TYPE_FULL_PDB;
2188 : : enum pdb_type_e
2189 [ # # # # : 0 : pdb_mask[PDCP_CIPHER_TYPE_INVALID][PDCP_AUTH_TYPE_INVALID] = {
# ]
2190 : : { /* NULL */
2191 : : PDCP_PDB_TYPE_NO_PDB, /* NULL */
2192 : : PDCP_PDB_TYPE_FULL_PDB, /* SNOW f9 */
2193 : : PDCP_PDB_TYPE_FULL_PDB, /* AES CMAC */
2194 : : PDCP_PDB_TYPE_FULL_PDB /* ZUC-I */
2195 : : },
2196 : : { /* SNOW f8 */
2197 : : PDCP_PDB_TYPE_FULL_PDB, /* NULL */
2198 : : PDCP_PDB_TYPE_FULL_PDB, /* SNOW f9 */
2199 : : PDCP_PDB_TYPE_REDUCED_PDB, /* AES CMAC */
2200 : : PDCP_PDB_TYPE_REDUCED_PDB /* ZUC-I */
2201 : : },
2202 : : { /* AES CTR */
2203 : : PDCP_PDB_TYPE_FULL_PDB, /* NULL */
2204 : : PDCP_PDB_TYPE_REDUCED_PDB, /* SNOW f9 */
2205 : : PDCP_PDB_TYPE_FULL_PDB, /* AES CMAC */
2206 : : PDCP_PDB_TYPE_REDUCED_PDB /* ZUC-I */
2207 : : },
2208 : : { /* ZUC-E */
2209 : : PDCP_PDB_TYPE_FULL_PDB, /* NULL */
2210 : : PDCP_PDB_TYPE_REDUCED_PDB, /* SNOW f9 */
2211 : : PDCP_PDB_TYPE_REDUCED_PDB, /* AES CMAC */
2212 : : PDCP_PDB_TYPE_FULL_PDB /* ZUC-I */
2213 : : },
2214 : : };
2215 : :
2216 : : /* Read options from user */
2217 : : /* Depending on sequence number length, the HFN and HFN threshold
2218 : : * have different lengths.
2219 : : */
2220 : : memset(&pdb, 0x00, sizeof(struct pdcp_pdb));
2221 : :
2222 [ # # # # : 0 : switch (sn_size) {
# ]
2223 : 0 : case PDCP_SN_SIZE_7:
2224 : 0 : pdb.opt_res.opt |= PDCP_U_PLANE_PDB_OPT_SHORT_SN;
2225 : 0 : pdb.hfn_res = hfn << PDCP_U_PLANE_PDB_SHORT_SN_HFN_SHIFT;
2226 : 0 : pdb.hfn_thr_res =
2227 : 0 : hfn_threshold<<PDCP_U_PLANE_PDB_SHORT_SN_HFN_THR_SHIFT;
2228 : 0 : break;
2229 : :
2230 : 0 : case PDCP_SN_SIZE_12:
2231 : : pdb.opt_res.opt &= (uint32_t)(~PDCP_U_PLANE_PDB_OPT_SHORT_SN);
2232 : 0 : pdb.hfn_res = hfn << PDCP_U_PLANE_PDB_LONG_SN_HFN_SHIFT;
2233 : 0 : pdb.hfn_thr_res =
2234 : 0 : hfn_threshold<<PDCP_U_PLANE_PDB_LONG_SN_HFN_THR_SHIFT;
2235 : 0 : break;
2236 : :
2237 : 0 : case PDCP_SN_SIZE_15:
2238 : 0 : pdb.opt_res.opt = (uint32_t)(PDCP_U_PLANE_PDB_OPT_15B_SN);
2239 : 0 : pdb.hfn_res = hfn << PDCP_U_PLANE_PDB_15BIT_SN_HFN_SHIFT;
2240 : 0 : pdb.hfn_thr_res =
2241 : 0 : hfn_threshold<<PDCP_U_PLANE_PDB_15BIT_SN_HFN_THR_SHIFT;
2242 : 0 : break;
2243 : :
2244 : 0 : case PDCP_SN_SIZE_18:
2245 : 0 : pdb.opt_res.opt = (uint32_t)(PDCP_U_PLANE_PDB_OPT_18B_SN);
2246 : 0 : pdb.hfn_res = hfn << PDCP_U_PLANE_PDB_18BIT_SN_HFN_SHIFT;
2247 : 0 : pdb.hfn_thr_res =
2248 : 0 : hfn_threshold<<PDCP_U_PLANE_PDB_18BIT_SN_HFN_THR_SHIFT;
2249 : :
2250 [ # # ]: 0 : if (rta_sec_era == RTA_SEC_ERA_8) {
2251 [ # # ]: 0 : if (cipherdata && authdata)
2252 : 0 : pdb_type = pdb_mask[cipherdata->algtype]
2253 : 0 : [authdata->algtype];
2254 : : }
2255 : : break;
2256 : :
2257 : 0 : default:
2258 : 0 : pr_err("Invalid Sequence Number Size setting in PDB\n");
2259 : 0 : return -EINVAL;
2260 : : }
2261 : :
2262 : 0 : pdb.bearer_dir_res = (uint32_t)
2263 : 0 : ((bearer << PDCP_U_PLANE_PDB_BEARER_SHIFT) |
2264 : 0 : (direction << PDCP_U_PLANE_PDB_DIR_SHIFT));
2265 : :
2266 [ # # # # ]: 0 : switch (pdb_type) {
2267 : : case PDCP_PDB_TYPE_NO_PDB:
2268 : : break;
2269 : :
2270 : 0 : case PDCP_PDB_TYPE_REDUCED_PDB:
2271 : 0 : __rta_out32(p, pdb.hfn_res);
2272 : 0 : __rta_out32(p, pdb.bearer_dir_res);
2273 : 0 : break;
2274 : :
2275 : 0 : case PDCP_PDB_TYPE_FULL_PDB:
2276 : : /* copy PDB in descriptor*/
2277 : 0 : __rta_out32(p, pdb.opt_res.opt);
2278 : 0 : __rta_out32(p, pdb.hfn_res);
2279 : 0 : __rta_out32(p, pdb.bearer_dir_res);
2280 : 0 : __rta_out32(p, pdb.hfn_thr_res);
2281 : :
2282 : 0 : break;
2283 : :
2284 : : default:
2285 : : return PDCP_PDB_TYPE_INVALID;
2286 : : }
2287 : :
2288 : : return pdb_type;
2289 : : }
2290 : :
2291 : : /**
2292 : : * cnstr_shdsc_pdcp_c_plane_encap - Function for creating a PDCP Control Plane
2293 : : * encapsulation descriptor.
2294 : : * @descbuf: pointer to buffer for descriptor construction
2295 : : * @ps: if 36/40bit addressing is desired, this parameter must be true
2296 : : * @swap: must be true when core endianness doesn't match SEC endianness
2297 : : * @hfn: starting Hyper Frame Number to be used together with the SN from the
2298 : : * PDCP frames.
2299 : : * @sn_size: size of sequence numbers, only 5/12 bit sequence numbers are valid
2300 : : * @bearer: radio bearer ID
2301 : : * @direction: the direction of the PDCP frame (UL/DL)
2302 : : * @hfn_threshold: HFN value that once reached triggers a warning from SEC that
2303 : : * keys should be renegotiated at the earliest convenience.
2304 : : * @cipherdata: pointer to block cipher transform definitions
2305 : : * Valid algorithm values are those from cipher_type_pdcp enum.
2306 : : * @authdata: pointer to authentication transform definitions
2307 : : * Valid algorithm values are those from auth_type_pdcp enum.
2308 : : * Return: size of descriptor written in words or negative number on error.
2309 : : * Once the function returns, the value of this parameter can be used
2310 : : * for reclaiming the space that wasn't used for the descriptor.
2311 : : *
2312 : : * Note: descbuf must be large enough to contain a full 256 byte long
2313 : : * descriptor; after the function returns, by subtracting the actual number of
2314 : : * bytes used, the user can reuse the remaining buffer space for other purposes.
2315 : : */
2316 : : static inline int
2317 : 0 : cnstr_shdsc_pdcp_c_plane_encap(uint32_t *descbuf,
2318 : : bool ps,
2319 : : bool swap,
2320 : : uint32_t hfn,
2321 : : enum pdcp_sn_size sn_size,
2322 : : unsigned char bearer,
2323 : : unsigned char direction,
2324 : : uint32_t hfn_threshold,
2325 : : struct alginfo *cipherdata,
2326 : : struct alginfo *authdata)
2327 : : {
2328 : : static int
2329 : : (*pdcp_cp_fp[PDCP_CIPHER_TYPE_INVALID][PDCP_AUTH_TYPE_INVALID])
2330 : : (struct program*, bool swap, struct alginfo *,
2331 : : struct alginfo *, unsigned int dir, enum pdcp_sn_size) = {
2332 : : { /* NULL */
2333 : : pdcp_insert_cplane_null_op, /* NULL */
2334 : : pdcp_insert_cplane_int_only_op, /* SNOW f9 */
2335 : : pdcp_insert_cplane_int_only_op, /* AES CMAC */
2336 : : pdcp_insert_cplane_int_only_op /* ZUC-I */
2337 : : },
2338 : : { /* SNOW f8 */
2339 : : pdcp_insert_cplane_enc_only_op, /* NULL */
2340 : : pdcp_insert_cplane_acc_op, /* SNOW f9 */
2341 : : pdcp_insert_cplane_snow_aes_op, /* AES CMAC */
2342 : : pdcp_insert_cplane_snow_zuc_op /* ZUC-I */
2343 : : },
2344 : : { /* AES CTR */
2345 : : pdcp_insert_cplane_enc_only_op, /* NULL */
2346 : : pdcp_insert_cplane_aes_snow_op, /* SNOW f9 */
2347 : : pdcp_insert_cplane_acc_op, /* AES CMAC */
2348 : : pdcp_insert_cplane_aes_zuc_op /* ZUC-I */
2349 : : },
2350 : : { /* ZUC-E */
2351 : : pdcp_insert_cplane_enc_only_op, /* NULL */
2352 : : pdcp_insert_cplane_zuc_snow_op, /* SNOW f9 */
2353 : : pdcp_insert_cplane_zuc_aes_op, /* AES CMAC */
2354 : : pdcp_insert_cplane_acc_op /* ZUC-I */
2355 : : },
2356 : : };
2357 : : static enum rta_share_type
2358 : : desc_share[PDCP_CIPHER_TYPE_INVALID][PDCP_AUTH_TYPE_INVALID] = {
2359 : : { /* NULL */
2360 : : SHR_WAIT, /* NULL */
2361 : : SHR_WAIT, /* SNOW f9 */
2362 : : SHR_ALWAYS, /* AES CMAC */
2363 : : SHR_WAIT /* ZUC-I */
2364 : : },
2365 : : { /* SNOW f8 */
2366 : : SHR_WAIT, /* NULL */
2367 : : SHR_WAIT, /* SNOW f9 */
2368 : : SHR_WAIT, /* AES CMAC */
2369 : : SHR_WAIT /* ZUC-I */
2370 : : },
2371 : : { /* AES CTR */
2372 : : SHR_WAIT, /* NULL */
2373 : : SHR_WAIT, /* SNOW f9 */
2374 : : SHR_ALWAYS, /* AES CMAC */
2375 : : SHR_WAIT /* ZUC-I */
2376 : : },
2377 : : { /* ZUC-E */
2378 : : SHR_WAIT, /* NULL */
2379 : : SHR_WAIT, /* SNOW f9 */
2380 : : SHR_WAIT, /* AES CMAC */
2381 : : SHR_WAIT /* ZUC-I */
2382 : : },
2383 : : };
2384 : : enum pdb_type_e pdb_type;
2385 : : struct program prg;
2386 : : struct program *p = &prg;
2387 : : int err;
2388 : : LABEL(pdb_end);
2389 : :
2390 [ # # ]: 0 : if (sn_size != PDCP_SN_SIZE_12 && sn_size != PDCP_SN_SIZE_5) {
2391 : 0 : pr_err("C-plane supports only 5-bit and 12-bit sequence numbers\n");
2392 : 0 : return -EINVAL;
2393 : : }
2394 : :
2395 : : PROGRAM_CNTXT_INIT(p, descbuf, 0);
2396 [ # # ]: 0 : if (swap)
2397 : : PROGRAM_SET_BSWAP(p);
2398 [ # # ]: 0 : if (ps)
2399 : : PROGRAM_SET_36BIT_ADDR(p);
2400 : :
2401 : 0 : SHR_HDR(p, desc_share[cipherdata->algtype][authdata->algtype], 0, 0);
2402 : :
2403 : 0 : pdb_type = cnstr_pdcp_c_plane_pdb(p,
2404 : : hfn,
2405 : : sn_size,
2406 : : bearer,
2407 : : direction,
2408 : : hfn_threshold);
2409 : :
2410 : : SET_LABEL(p, pdb_end);
2411 : :
2412 : 0 : err = insert_hfn_ov_op(p, sn_size, pdb_type, true);
2413 [ # # ]: 0 : if (err)
2414 : : return err;
2415 : :
2416 : 0 : err = pdcp_cp_fp[cipherdata->algtype][authdata->algtype](p,
2417 : : swap,
2418 : : cipherdata,
2419 : : authdata,
2420 : : OP_TYPE_ENCAP_PROTOCOL,
2421 : : sn_size);
2422 [ # # ]: 0 : if (err)
2423 : : return err;
2424 : :
2425 : 0 : PATCH_HDR(p, 0, pdb_end);
2426 : :
2427 : 0 : return PROGRAM_FINALIZE(p);
2428 : : }
2429 : :
2430 : : /**
2431 : : * cnstr_shdsc_pdcp_c_plane_decap - Function for creating a PDCP Control Plane
2432 : : * decapsulation descriptor.
2433 : : * @descbuf: pointer to buffer for descriptor construction
2434 : : * @ps: if 36/40bit addressing is desired, this parameter must be true
2435 : : * @swap: must be true when core endianness doesn't match SEC endianness
2436 : : * @hfn: starting Hyper Frame Number to be used together with the SN from the
2437 : : * PDCP frames.
2438 : : * @sn_size: size of sequence numbers, only 5/12 bit sequence numbers are valid
2439 : : * @bearer: radio bearer ID
2440 : : * @direction: the direction of the PDCP frame (UL/DL)
2441 : : * @hfn_threshold: HFN value that once reached triggers a warning from SEC that
2442 : : * keys should be renegotiated at the earliest convenience.
2443 : : * @cipherdata: pointer to block cipher transform definitions
2444 : : * Valid algorithm values are those from cipher_type_pdcp enum.
2445 : : * @authdata: pointer to authentication transform definitions
2446 : : * Valid algorithm values are those from auth_type_pdcp enum.
2447 : : *
2448 : : * Return: size of descriptor written in words or negative number on error.
2449 : : * Once the function returns, the value of this parameter can be used
2450 : : * for reclaiming the space that wasn't used for the descriptor.
2451 : : *
2452 : : * Note: descbuf must be large enough to contain a full 256 byte long
2453 : : * descriptor; after the function returns, by subtracting the actual number of
2454 : : * bytes used, the user can reuse the remaining buffer space for other purposes.
2455 : : */
2456 : : static inline int
2457 : 0 : cnstr_shdsc_pdcp_c_plane_decap(uint32_t *descbuf,
2458 : : bool ps,
2459 : : bool swap,
2460 : : uint32_t hfn,
2461 : : enum pdcp_sn_size sn_size,
2462 : : unsigned char bearer,
2463 : : unsigned char direction,
2464 : : uint32_t hfn_threshold,
2465 : : struct alginfo *cipherdata,
2466 : : struct alginfo *authdata)
2467 : : {
2468 : : static int
2469 : : (*pdcp_cp_fp[PDCP_CIPHER_TYPE_INVALID][PDCP_AUTH_TYPE_INVALID])
2470 : : (struct program*, bool swap, struct alginfo *,
2471 : : struct alginfo *, unsigned int dir, enum pdcp_sn_size) = {
2472 : : { /* NULL */
2473 : : pdcp_insert_cplane_null_op, /* NULL */
2474 : : pdcp_insert_cplane_int_only_op, /* SNOW f9 */
2475 : : pdcp_insert_cplane_int_only_op, /* AES CMAC */
2476 : : pdcp_insert_cplane_int_only_op /* ZUC-I */
2477 : : },
2478 : : { /* SNOW f8 */
2479 : : pdcp_insert_cplane_enc_only_op, /* NULL */
2480 : : pdcp_insert_cplane_acc_op, /* SNOW f9 */
2481 : : pdcp_insert_cplane_snow_aes_op, /* AES CMAC */
2482 : : pdcp_insert_cplane_snow_zuc_op /* ZUC-I */
2483 : : },
2484 : : { /* AES CTR */
2485 : : pdcp_insert_cplane_enc_only_op, /* NULL */
2486 : : pdcp_insert_cplane_aes_snow_op, /* SNOW f9 */
2487 : : pdcp_insert_cplane_acc_op, /* AES CMAC */
2488 : : pdcp_insert_cplane_aes_zuc_op /* ZUC-I */
2489 : : },
2490 : : { /* ZUC-E */
2491 : : pdcp_insert_cplane_enc_only_op, /* NULL */
2492 : : pdcp_insert_cplane_zuc_snow_op, /* SNOW f9 */
2493 : : pdcp_insert_cplane_zuc_aes_op, /* AES CMAC */
2494 : : pdcp_insert_cplane_acc_op /* ZUC-I */
2495 : : },
2496 : : };
2497 : : static enum rta_share_type
2498 : : desc_share[PDCP_CIPHER_TYPE_INVALID][PDCP_AUTH_TYPE_INVALID] = {
2499 : : { /* NULL */
2500 : : SHR_WAIT, /* NULL */
2501 : : SHR_WAIT, /* SNOW f9 */
2502 : : SHR_ALWAYS, /* AES CMAC */
2503 : : SHR_WAIT /* ZUC-I */
2504 : : },
2505 : : { /* SNOW f8 */
2506 : : SHR_WAIT, /* NULL */
2507 : : SHR_WAIT, /* SNOW f9 */
2508 : : SHR_WAIT, /* AES CMAC */
2509 : : SHR_WAIT /* ZUC-I */
2510 : : },
2511 : : { /* AES CTR */
2512 : : SHR_WAIT, /* NULL */
2513 : : SHR_WAIT, /* SNOW f9 */
2514 : : SHR_ALWAYS, /* AES CMAC */
2515 : : SHR_WAIT /* ZUC-I */
2516 : : },
2517 : : { /* ZUC-E */
2518 : : SHR_WAIT, /* NULL */
2519 : : SHR_WAIT, /* SNOW f9 */
2520 : : SHR_WAIT, /* AES CMAC */
2521 : : SHR_WAIT /* ZUC-I */
2522 : : },
2523 : : };
2524 : : enum pdb_type_e pdb_type;
2525 : : struct program prg;
2526 : : struct program *p = &prg;
2527 : : int err;
2528 : : LABEL(pdb_end);
2529 : :
2530 [ # # ]: 0 : if (sn_size != PDCP_SN_SIZE_12 && sn_size != PDCP_SN_SIZE_5) {
2531 : 0 : pr_err("C-plane supports only 5-bit and 12-bit sequence numbers\n");
2532 : 0 : return -EINVAL;
2533 : : }
2534 : :
2535 : : PROGRAM_CNTXT_INIT(p, descbuf, 0);
2536 [ # # ]: 0 : if (swap)
2537 : : PROGRAM_SET_BSWAP(p);
2538 [ # # ]: 0 : if (ps)
2539 : : PROGRAM_SET_36BIT_ADDR(p);
2540 : :
2541 : 0 : SHR_HDR(p, desc_share[cipherdata->algtype][authdata->algtype], 0, 0);
2542 : :
2543 : 0 : pdb_type = cnstr_pdcp_c_plane_pdb(p,
2544 : : hfn,
2545 : : sn_size,
2546 : : bearer,
2547 : : direction,
2548 : : hfn_threshold);
2549 : :
2550 : : SET_LABEL(p, pdb_end);
2551 : :
2552 : 0 : err = insert_hfn_ov_op(p, sn_size, pdb_type, true);
2553 [ # # ]: 0 : if (err)
2554 : : return err;
2555 : :
2556 : 0 : err = pdcp_cp_fp[cipherdata->algtype][authdata->algtype](p,
2557 : : swap,
2558 : : cipherdata,
2559 : : authdata,
2560 : : OP_TYPE_DECAP_PROTOCOL,
2561 : : sn_size);
2562 [ # # ]: 0 : if (err)
2563 : : return err;
2564 : :
2565 : 0 : PATCH_HDR(p, 0, pdb_end);
2566 : :
2567 : 0 : return PROGRAM_FINALIZE(p);
2568 : : }
2569 : :
2570 : : static int
2571 : : pdcp_insert_uplane_with_int_op(struct program *p,
2572 : : bool swap __maybe_unused,
2573 : : struct alginfo *cipherdata,
2574 : : struct alginfo *authdata,
2575 : : enum pdcp_sn_size sn_size,
2576 : : unsigned int dir)
2577 : : {
2578 : : static int
2579 : : (*pdcp_cp_fp[PDCP_CIPHER_TYPE_INVALID][PDCP_AUTH_TYPE_INVALID])
2580 : : (struct program*, bool swap, struct alginfo *,
2581 : : struct alginfo *, unsigned int dir, enum pdcp_sn_size) = {
2582 : : { /* NULL */
2583 : : pdcp_insert_cplane_null_op, /* NULL */
2584 : : pdcp_insert_cplane_int_only_op, /* SNOW f9 */
2585 : : pdcp_insert_cplane_int_only_op, /* AES CMAC */
2586 : : pdcp_insert_cplane_int_only_op /* ZUC-I */
2587 : : },
2588 : : { /* SNOW f8 */
2589 : : pdcp_insert_cplane_enc_only_op, /* NULL */
2590 : : pdcp_insert_uplane_snow_snow_op, /* SNOW f9 */
2591 : : pdcp_insert_cplane_snow_aes_op, /* AES CMAC */
2592 : : pdcp_insert_cplane_snow_zuc_op /* ZUC-I */
2593 : : },
2594 : : { /* AES CTR */
2595 : : pdcp_insert_cplane_enc_only_op, /* NULL */
2596 : : pdcp_insert_cplane_aes_snow_op, /* SNOW f9 */
2597 : : pdcp_insert_uplane_aes_aes_op, /* AES CMAC */
2598 : : pdcp_insert_cplane_aes_zuc_op /* ZUC-I */
2599 : : },
2600 : : { /* ZUC-E */
2601 : : pdcp_insert_cplane_enc_only_op, /* NULL */
2602 : : pdcp_insert_cplane_zuc_snow_op, /* SNOW f9 */
2603 : : pdcp_insert_cplane_zuc_aes_op, /* AES CMAC */
2604 : : pdcp_insert_uplane_zuc_zuc_op /* ZUC-I */
2605 : : },
2606 : : };
2607 : : int err;
2608 : :
2609 : 0 : err = pdcp_cp_fp[cipherdata->algtype][authdata->algtype](p,
2610 : : swap,
2611 : : cipherdata,
2612 : : authdata,
2613 : : dir,
2614 : : sn_size);
2615 [ # # # # : 0 : if (err)
# # # # ]
2616 : : return err;
2617 : :
2618 : : return 0;
2619 : : }
2620 : :
2621 : :
2622 : : /**
2623 : : * cnstr_shdsc_pdcp_u_plane_encap - Function for creating a PDCP User Plane
2624 : : * encapsulation descriptor.
2625 : : * @descbuf: pointer to buffer for descriptor construction
2626 : : * @ps: if 36/40bit addressing is desired, this parameter must be true
2627 : : * @swap: must be true when core endianness doesn't match SEC endianness
2628 : : * @sn_size: selects Sequence Number Size: 7/12/15 bits
2629 : : * @hfn: starting Hyper Frame Number to be used together with the SN from the
2630 : : * PDCP frames.
2631 : : * @bearer: radio bearer ID
2632 : : * @direction: the direction of the PDCP frame (UL/DL)
2633 : : * @hfn_threshold: HFN value that once reached triggers a warning from SEC that
2634 : : * keys should be renegotiated at the earliest convenience.
2635 : : * @cipherdata: pointer to block cipher transform definitions
2636 : : * Valid algorithm values are those from cipher_type_pdcp enum.
2637 : : *
2638 : : * Return: size of descriptor written in words or negative number on error.
2639 : : * Once the function returns, the value of this parameter can be used
2640 : : * for reclaiming the space that wasn't used for the descriptor.
2641 : : *
2642 : : * Note: descbuf must be large enough to contain a full 256 byte long
2643 : : * descriptor; after the function returns, by subtracting the actual number of
2644 : : * bytes used, the user can reuse the remaining buffer space for other purposes.
2645 : : */
2646 : : static inline int
2647 [ # # ]: 0 : cnstr_shdsc_pdcp_u_plane_encap(uint32_t *descbuf,
2648 : : bool ps,
2649 : : bool swap,
2650 : : enum pdcp_sn_size sn_size,
2651 : : uint32_t hfn,
2652 : : unsigned short bearer,
2653 : : unsigned short direction,
2654 : : uint32_t hfn_threshold,
2655 : : struct alginfo *cipherdata,
2656 : : struct alginfo *authdata)
2657 : : {
2658 : : struct program prg;
2659 : : struct program *p = &prg;
2660 : : int err;
2661 : : enum pdb_type_e pdb_type;
2662 : : static enum rta_share_type
2663 : : desc_share[PDCP_CIPHER_TYPE_INVALID][PDCP_AUTH_TYPE_INVALID] = {
2664 : : { /* NULL */
2665 : : SHR_WAIT, /* NULL */
2666 : : SHR_WAIT, /* SNOW f9 */
2667 : : SHR_ALWAYS, /* AES CMAC */
2668 : : SHR_WAIT /* ZUC-I */
2669 : : },
2670 : : { /* SNOW f8 */
2671 : : SHR_WAIT, /* NULL */
2672 : : SHR_WAIT, /* SNOW f9 */
2673 : : SHR_WAIT, /* AES CMAC */
2674 : : SHR_WAIT /* ZUC-I */
2675 : : },
2676 : : { /* AES CTR */
2677 : : SHR_WAIT, /* NULL */
2678 : : SHR_WAIT, /* SNOW f9 */
2679 : : SHR_ALWAYS, /* AES CMAC */
2680 : : SHR_WAIT /* ZUC-I */
2681 : : },
2682 : : { /* ZUC-E */
2683 : : SHR_WAIT, /* NULL */
2684 : : SHR_WAIT, /* SNOW f9 */
2685 : : SHR_WAIT, /* AES CMAC */
2686 : : SHR_WAIT /* ZUC-I */
2687 : : },
2688 : : };
2689 : : LABEL(pdb_end);
2690 : :
2691 : : PROGRAM_CNTXT_INIT(p, descbuf, 0);
2692 [ # # ]: 0 : if (swap)
2693 : : PROGRAM_SET_BSWAP(p);
2694 [ # # ]: 0 : if (ps)
2695 : : PROGRAM_SET_36BIT_ADDR(p);
2696 : :
2697 [ # # ]: 0 : if (authdata)
2698 : 0 : SHR_HDR(p, desc_share[cipherdata->algtype][authdata->algtype], 0, 0);
2699 : : else
2700 : 0 : SHR_HDR(p, SHR_WAIT, 0, 0);
2701 : 0 : pdb_type = cnstr_pdcp_u_plane_pdb(p, sn_size, hfn,
2702 : : bearer, direction, hfn_threshold,
2703 : : cipherdata, authdata);
2704 [ # # ]: 0 : if (pdb_type == PDCP_PDB_TYPE_INVALID) {
2705 : 0 : pr_err("Error creating PDCP UPlane PDB\n");
2706 : 0 : return -EINVAL;
2707 : : }
2708 : : SET_LABEL(p, pdb_end);
2709 : :
2710 : 0 : err = insert_hfn_ov_op(p, sn_size, pdb_type, true);
2711 [ # # ]: 0 : if (err)
2712 : : return err;
2713 : :
2714 [ # # # ]: 0 : switch (sn_size) {
2715 : 0 : case PDCP_SN_SIZE_7:
2716 : : case PDCP_SN_SIZE_12:
2717 [ # # ]: 0 : switch (cipherdata->algtype) {
2718 : 0 : case PDCP_CIPHER_TYPE_ZUC:
2719 : : /* fallthrough */
2720 : : case PDCP_CIPHER_TYPE_AES:
2721 : : case PDCP_CIPHER_TYPE_SNOW:
2722 : : case PDCP_CIPHER_TYPE_NULL:
2723 [ # # # # ]: 0 : if (rta_sec_era >= RTA_SEC_ERA_8 &&
2724 [ # # ]: 0 : authdata && authdata->algtype == 0){
2725 : 0 : err = pdcp_insert_uplane_with_int_op(p, swap,
2726 : : cipherdata, authdata,
2727 : : sn_size,
2728 : : OP_TYPE_ENCAP_PROTOCOL);
2729 : : if (err)
2730 : : return err;
2731 : : break;
2732 : : }
2733 [ # # # # ]: 0 : if (rta_sec_era >= RTA_SEC_ERA_8 &&
2734 : : cipherdata->algtype == PDCP_CIPHER_TYPE_AES
2735 : 0 : && !authdata
2736 [ # # ]: 0 : && sn_size == PDCP_SN_SIZE_12) {
2737 : 0 : err = pdcp_insert_uplane_no_int_op(p, swap, cipherdata,
2738 : : OP_TYPE_ENCAP_PROTOCOL, sn_size);
2739 [ # # ]: 0 : if (err)
2740 : : return err;
2741 : : break;
2742 : : }
2743 : :
2744 [ # # ]: 0 : if (pdb_type != PDCP_PDB_TYPE_FULL_PDB) {
2745 : 0 : pr_err("PDB type must be FULL for PROTO desc\n");
2746 : 0 : return -EINVAL;
2747 : : }
2748 : :
2749 : : /* Insert auth key if requested */
2750 [ # # # # ]: 0 : if (authdata && authdata->algtype) {
2751 : 0 : KEY(p, KEY2, authdata->key_enc_flags,
2752 : : (uint64_t)authdata->key, authdata->keylen,
2753 : : INLINE_KEY(authdata));
2754 : : }
2755 : : /* Insert Cipher Key */
2756 : 0 : KEY(p, KEY1, cipherdata->key_enc_flags,
2757 : : (uint64_t)cipherdata->key, cipherdata->keylen,
2758 : : INLINE_KEY(cipherdata));
2759 : :
2760 : 0 : JUMP(p, 1, LOCAL_JUMP, ALL_TRUE, CALM);
2761 [ # # ]: 0 : if (authdata)
2762 : 0 : PROTOCOL(p, OP_TYPE_ENCAP_PROTOCOL,
2763 : : OP_PCLID_LTE_PDCP_USER_RN,
2764 : : ((uint16_t)cipherdata->algtype << 8) |
2765 : : (uint16_t)authdata->algtype);
2766 : : else
2767 : 0 : PROTOCOL(p, OP_TYPE_ENCAP_PROTOCOL,
2768 : : OP_PCLID_LTE_PDCP_USER,
2769 : : (uint16_t)cipherdata->algtype);
2770 : : break;
2771 : 0 : default:
2772 : 0 : pr_err("%s: Invalid encrypt algorithm selected: %d\n",
2773 : : "cnstr_pcl_shdsc_pdcp_u_plane_decap",
2774 : : cipherdata->algtype);
2775 : 0 : return -EINVAL;
2776 : : }
2777 : : break;
2778 : :
2779 : 0 : case PDCP_SN_SIZE_15:
2780 : : case PDCP_SN_SIZE_18:
2781 [ # # ]: 0 : if (authdata) {
2782 : 0 : err = pdcp_insert_uplane_with_int_op(p, swap,
2783 : : cipherdata, authdata,
2784 : : sn_size,
2785 : : OP_TYPE_ENCAP_PROTOCOL);
2786 : : if (err)
2787 : : return err;
2788 : :
2789 : : break;
2790 : : }
2791 : :
2792 [ # # ]: 0 : switch (cipherdata->algtype) {
2793 : 0 : case PDCP_CIPHER_TYPE_NULL:
2794 : 0 : insert_copy_frame_op(p,
2795 : : cipherdata,
2796 : : OP_TYPE_ENCAP_PROTOCOL);
2797 : 0 : break;
2798 : :
2799 : 0 : default:
2800 : 0 : err = pdcp_insert_uplane_no_int_op(p, swap, cipherdata,
2801 : : OP_TYPE_ENCAP_PROTOCOL, sn_size);
2802 [ # # ]: 0 : if (err)
2803 : : return err;
2804 : : break;
2805 : : }
2806 : : break;
2807 : :
2808 : 0 : case PDCP_SN_SIZE_5:
2809 : : default:
2810 : 0 : pr_err("Invalid SN size selected\n");
2811 : 0 : return -ENOTSUP;
2812 : : }
2813 : :
2814 : 0 : PATCH_HDR(p, 0, pdb_end);
2815 : 0 : return PROGRAM_FINALIZE(p);
2816 : : }
2817 : :
2818 : : /**
2819 : : * cnstr_shdsc_pdcp_u_plane_decap - Function for creating a PDCP User Plane
2820 : : * decapsulation descriptor.
2821 : : * @descbuf: pointer to buffer for descriptor construction
2822 : : * @ps: if 36/40bit addressing is desired, this parameter must be true
2823 : : * @swap: must be true when core endianness doesn't match SEC endianness
2824 : : * @sn_size: selects Sequence Number Size: 7/12/15 bits
2825 : : * @hfn: starting Hyper Frame Number to be used together with the SN from the
2826 : : * PDCP frames.
2827 : : * @bearer: radio bearer ID
2828 : : * @direction: the direction of the PDCP frame (UL/DL)
2829 : : * @hfn_threshold: HFN value that once reached triggers a warning from SEC that
2830 : : * keys should be renegotiated at the earliest convenience.
2831 : : * @cipherdata: pointer to block cipher transform definitions
2832 : : * Valid algorithm values are those from cipher_type_pdcp enum.
2833 : : *
2834 : : * Return: size of descriptor written in words or negative number on error.
2835 : : * Once the function returns, the value of this parameter can be used
2836 : : * for reclaiming the space that wasn't used for the descriptor.
2837 : : *
2838 : : * Note: descbuf must be large enough to contain a full 256 byte long
2839 : : * descriptor; after the function returns, by subtracting the actual number of
2840 : : * bytes used, the user can reuse the remaining buffer space for other purposes.
2841 : : */
2842 : : static inline int
2843 [ # # ]: 0 : cnstr_shdsc_pdcp_u_plane_decap(uint32_t *descbuf,
2844 : : bool ps,
2845 : : bool swap,
2846 : : enum pdcp_sn_size sn_size,
2847 : : uint32_t hfn,
2848 : : unsigned short bearer,
2849 : : unsigned short direction,
2850 : : uint32_t hfn_threshold,
2851 : : struct alginfo *cipherdata,
2852 : : struct alginfo *authdata)
2853 : : {
2854 : : struct program prg;
2855 : : struct program *p = &prg;
2856 : : int err;
2857 : : enum pdb_type_e pdb_type;
2858 : : static enum rta_share_type
2859 : : desc_share[PDCP_CIPHER_TYPE_INVALID][PDCP_AUTH_TYPE_INVALID] = {
2860 : : { /* NULL */
2861 : : SHR_WAIT, /* NULL */
2862 : : SHR_WAIT, /* SNOW f9 */
2863 : : SHR_ALWAYS, /* AES CMAC */
2864 : : SHR_WAIT /* ZUC-I */
2865 : : },
2866 : : { /* SNOW f8 */
2867 : : SHR_WAIT, /* NULL */
2868 : : SHR_WAIT, /* SNOW f9 */
2869 : : SHR_WAIT, /* AES CMAC */
2870 : : SHR_WAIT /* ZUC-I */
2871 : : },
2872 : : { /* AES CTR */
2873 : : SHR_WAIT, /* NULL */
2874 : : SHR_WAIT, /* SNOW f9 */
2875 : : SHR_ALWAYS, /* AES CMAC */
2876 : : SHR_WAIT /* ZUC-I */
2877 : : },
2878 : : { /* ZUC-E */
2879 : : SHR_WAIT, /* NULL */
2880 : : SHR_WAIT, /* SNOW f9 */
2881 : : SHR_WAIT, /* AES CMAC */
2882 : : SHR_WAIT /* ZUC-I */
2883 : : },
2884 : : };
2885 : :
2886 : : LABEL(pdb_end);
2887 : :
2888 : : PROGRAM_CNTXT_INIT(p, descbuf, 0);
2889 [ # # ]: 0 : if (swap)
2890 : : PROGRAM_SET_BSWAP(p);
2891 [ # # ]: 0 : if (ps)
2892 : : PROGRAM_SET_36BIT_ADDR(p);
2893 [ # # ]: 0 : if (authdata)
2894 : 0 : SHR_HDR(p, desc_share[cipherdata->algtype][authdata->algtype], 0, 0);
2895 : : else
2896 : 0 : SHR_HDR(p, SHR_WAIT, 0, 0);
2897 : :
2898 : 0 : pdb_type = cnstr_pdcp_u_plane_pdb(p, sn_size, hfn, bearer,
2899 : : direction, hfn_threshold,
2900 : : cipherdata, authdata);
2901 [ # # ]: 0 : if (pdb_type == PDCP_PDB_TYPE_INVALID) {
2902 : 0 : pr_err("Error creating PDCP UPlane PDB\n");
2903 : 0 : return -EINVAL;
2904 : : }
2905 : : SET_LABEL(p, pdb_end);
2906 : :
2907 : 0 : err = insert_hfn_ov_op(p, sn_size, pdb_type, true);
2908 [ # # ]: 0 : if (err)
2909 : : return err;
2910 : :
2911 [ # # # ]: 0 : switch (sn_size) {
2912 : 0 : case PDCP_SN_SIZE_7:
2913 : : case PDCP_SN_SIZE_12:
2914 [ # # ]: 0 : switch (cipherdata->algtype) {
2915 : 0 : case PDCP_CIPHER_TYPE_ZUC:
2916 : : /* fallthrough */
2917 : : case PDCP_CIPHER_TYPE_AES:
2918 : : case PDCP_CIPHER_TYPE_SNOW:
2919 : : case PDCP_CIPHER_TYPE_NULL:
2920 [ # # ]: 0 : if (pdb_type != PDCP_PDB_TYPE_FULL_PDB) {
2921 : 0 : pr_err("PDB type must be FULL for PROTO desc\n");
2922 : 0 : return -EINVAL;
2923 : : }
2924 : :
2925 : : /* Insert auth key if requested */
2926 [ # # # # ]: 0 : if (authdata && authdata->algtype)
2927 : 0 : KEY(p, KEY2, authdata->key_enc_flags,
2928 : : (uint64_t)authdata->key, authdata->keylen,
2929 : : INLINE_KEY(authdata));
2930 [ # # # # ]: 0 : else if (authdata && authdata->algtype == 0) {
2931 : 0 : err = pdcp_insert_uplane_with_int_op(p, swap,
2932 : : cipherdata, authdata,
2933 : : sn_size,
2934 : : OP_TYPE_DECAP_PROTOCOL);
2935 : : if (err)
2936 : : return err;
2937 : : break;
2938 : : }
2939 : :
2940 : : /* Insert Cipher Key */
2941 : 0 : KEY(p, KEY1, cipherdata->key_enc_flags,
2942 : : cipherdata->key, cipherdata->keylen,
2943 : : INLINE_KEY(cipherdata));
2944 [ # # ]: 0 : if (authdata)
2945 : 0 : PROTOCOL(p, OP_TYPE_DECAP_PROTOCOL,
2946 : : OP_PCLID_LTE_PDCP_USER_RN,
2947 : : ((uint16_t)cipherdata->algtype << 8) |
2948 : : (uint16_t)authdata->algtype);
2949 : : else
2950 : 0 : PROTOCOL(p, OP_TYPE_DECAP_PROTOCOL,
2951 : : OP_PCLID_LTE_PDCP_USER,
2952 : : (uint16_t)cipherdata->algtype);
2953 : : break;
2954 : 0 : default:
2955 : 0 : pr_err("%s: Invalid encrypt algorithm selected: %d\n",
2956 : : "cnstr_pcl_shdsc_pdcp_u_plane_decap",
2957 : : cipherdata->algtype);
2958 : 0 : return -EINVAL;
2959 : : }
2960 : : break;
2961 : :
2962 : 0 : case PDCP_SN_SIZE_15:
2963 : : case PDCP_SN_SIZE_18:
2964 [ # # ]: 0 : if (authdata) {
2965 : 0 : err = pdcp_insert_uplane_with_int_op(p, swap,
2966 : : cipherdata, authdata,
2967 : : sn_size,
2968 : : OP_TYPE_DECAP_PROTOCOL);
2969 : : if (err)
2970 : : return err;
2971 : :
2972 : : break;
2973 : : }
2974 : :
2975 [ # # ]: 0 : switch (cipherdata->algtype) {
2976 : 0 : case PDCP_CIPHER_TYPE_NULL:
2977 : 0 : insert_copy_frame_op(p,
2978 : : cipherdata,
2979 : : OP_TYPE_DECAP_PROTOCOL);
2980 : 0 : break;
2981 : :
2982 : 0 : default:
2983 : 0 : err = pdcp_insert_uplane_no_int_op(p, swap, cipherdata,
2984 : : OP_TYPE_DECAP_PROTOCOL, sn_size);
2985 [ # # ]: 0 : if (err)
2986 : : return err;
2987 : : break;
2988 : : }
2989 : : break;
2990 : :
2991 : 0 : case PDCP_SN_SIZE_5:
2992 : : default:
2993 : 0 : pr_err("Invalid SN size selected\n");
2994 : 0 : return -ENOTSUP;
2995 : : }
2996 : :
2997 : 0 : PATCH_HDR(p, 0, pdb_end);
2998 : 0 : return PROGRAM_FINALIZE(p);
2999 : : }
3000 : :
3001 : : /**
3002 : : * cnstr_shdsc_pdcp_short_mac - Function for creating a PDCP Short MAC
3003 : : * descriptor.
3004 : : * @descbuf: pointer to buffer for descriptor construction
3005 : : * @ps: if 36/40bit addressing is desired, this parameter must be true
3006 : : * @swap: must be true when core endianness doesn't match SEC endianness
3007 : : * @authdata: pointer to authentication transform definitions
3008 : : * Valid algorithm values are those from auth_type_pdcp enum.
3009 : : *
3010 : : * Return: size of descriptor written in words or negative number on error.
3011 : : * Once the function returns, the value of this parameter can be used
3012 : : * for reclaiming the space that wasn't used for the descriptor.
3013 : : *
3014 : : * Note: descbuf must be large enough to contain a full 256 byte long
3015 : : * descriptor; after the function returns, by subtracting the actual number of
3016 : : * bytes used, the user can reuse the remaining buffer space for other purposes.
3017 : : */
3018 : : static inline int
3019 : 0 : cnstr_shdsc_pdcp_short_mac(uint32_t *descbuf,
3020 : : bool ps,
3021 : : bool swap,
3022 : : struct alginfo *authdata)
3023 : : {
3024 : : struct program prg;
3025 : : struct program *p = &prg;
3026 [ # # ]: 0 : uint32_t iv[3] = {0, 0, 0};
3027 : :
3028 : : PROGRAM_CNTXT_INIT(p, descbuf, 0);
3029 [ # # ]: 0 : if (swap)
3030 : : PROGRAM_SET_BSWAP(p);
3031 [ # # ]: 0 : if (ps)
3032 : : PROGRAM_SET_36BIT_ADDR(p);
3033 : :
3034 : 0 : SHR_HDR(p, SHR_ALWAYS, 1, 0);
3035 : :
3036 : 0 : MATHB(p, SEQINSZ, SUB, ZERO, VSEQINSZ, 4, 0);
3037 : 0 : MATHB(p, SEQINSZ, SUB, ZERO, MATH1, 4, 0);
3038 : :
3039 : 0 : MATHB(p, ZERO, ADD, MATH1, VSEQOUTSZ, 4, 0);
3040 : :
3041 [ # # # # : 0 : switch (authdata->algtype) {
# ]
3042 : 0 : case PDCP_AUTH_TYPE_NULL:
3043 : 0 : SEQFIFOSTORE(p, MSG, 0, 0, VLF);
3044 : 0 : MOVE(p, AB1, 0, OFIFO, 0, MATH1, 0);
3045 : :
3046 : 0 : LOAD(p, (uintptr_t)iv, MATH0, 0, 8, IMMED | COPY);
3047 : 0 : SEQFIFOLOAD(p, MSG1, 0, VLF | LAST1 | LAST2 | FLUSH1);
3048 : 0 : SEQSTORE(p, MATH0, 0, 4, 0);
3049 : :
3050 : 0 : break;
3051 : :
3052 : 0 : case PDCP_AUTH_TYPE_SNOW:
3053 : : /* IV calculation based on 3GPP specs. 36331, section:5.3.7.4 */
3054 : 0 : iv[0] = 0xFFFFFFFF;
3055 : 0 : iv[1] = swab32(0x04000000);
3056 : 0 : iv[2] = swab32(0xF8000000);
3057 : :
3058 : 0 : KEY(p, KEY2, authdata->key_enc_flags, authdata->key,
3059 : : authdata->keylen, INLINE_KEY(authdata));
3060 : 0 : LOAD(p, (uintptr_t)&iv, CONTEXT2, 0, 12, IMMED | COPY);
3061 : 0 : ALG_OPERATION(p, OP_ALG_ALGSEL_SNOW_F9,
3062 : : OP_ALG_AAI_F9,
3063 : : OP_ALG_AS_INITFINAL,
3064 : : ICV_CHECK_DISABLE,
3065 : : DIR_ENC);
3066 : 0 : SEQFIFOSTORE(p, MSG, 0, 0, VLF);
3067 : :
3068 : 0 : MOVE(p, AB1, 0, OFIFO, 0, MATH1, 0);
3069 : :
3070 : 0 : SEQFIFOLOAD(p, MSGINSNOOP, 0, VLF | LAST1 | LAST2 | FLUSH1);
3071 : 0 : SEQSTORE(p, CONTEXT2, 0, 4, 0);
3072 : :
3073 : 0 : break;
3074 : :
3075 : 0 : case PDCP_AUTH_TYPE_AES:
3076 : 0 : iv[0] = 0xFFFFFFFF;
3077 [ # # ]: 0 : iv[1] = swap ? swab32(0xFC000000) : 0xFC000000;
3078 : 0 : iv[2] = 0x00000000; /* unused */
3079 : :
3080 : 0 : KEY(p, KEY1, authdata->key_enc_flags, authdata->key,
3081 : : authdata->keylen, INLINE_KEY(authdata));
3082 : 0 : LOAD(p, (uintptr_t)&iv, MATH0, 0, 8, IMMED | COPY);
3083 : 0 : MOVE(p, MATH0, 0, IFIFOAB1, 0, 8, IMMED);
3084 : 0 : ALG_OPERATION(p, OP_ALG_ALGSEL_AES,
3085 : : OP_ALG_AAI_CMAC,
3086 : : OP_ALG_AS_INITFINAL,
3087 : : ICV_CHECK_DISABLE,
3088 : : DIR_ENC);
3089 : 0 : SEQFIFOSTORE(p, MSG, 0, 0, VLF);
3090 : :
3091 : 0 : MOVE(p, AB2, 0, OFIFO, 0, MATH1, 0);
3092 : :
3093 : 0 : SEQFIFOLOAD(p, MSGINSNOOP, 0, VLF | LAST1 | LAST2 | FLUSH1);
3094 : 0 : SEQSTORE(p, CONTEXT1, 0, 4, 0);
3095 : :
3096 : 0 : break;
3097 : :
3098 : 0 : case PDCP_AUTH_TYPE_ZUC:
3099 : 0 : iv[0] = 0xFFFFFFFF;
3100 : 0 : iv[1] = swab32(0xFC000000);
3101 : 0 : iv[2] = 0x00000000; /* unused */
3102 : :
3103 : 0 : KEY(p, KEY2, authdata->key_enc_flags, authdata->key,
3104 : : authdata->keylen, INLINE_KEY(authdata));
3105 : 0 : LOAD(p, (uintptr_t)&iv, CONTEXT2, 0, 12, IMMED | COPY);
3106 : 0 : ALG_OPERATION(p, OP_ALG_ALGSEL_ZUCA,
3107 : : OP_ALG_AAI_F9,
3108 : : OP_ALG_AS_INITFINAL,
3109 : : ICV_CHECK_DISABLE,
3110 : : DIR_ENC);
3111 : 0 : SEQFIFOSTORE(p, MSG, 0, 0, VLF);
3112 : 0 : MOVE(p, AB1, 0, OFIFO, 0, MATH1, 0);
3113 : 0 : SEQFIFOLOAD(p, MSGINSNOOP, 0, VLF | LAST1 | LAST2 | FLUSH1);
3114 : 0 : SEQSTORE(p, CONTEXT2, 0, 4, 0);
3115 : :
3116 : 0 : break;
3117 : :
3118 : 0 : default:
3119 : 0 : pr_err("%s: Invalid integrity algorithm selected: %d\n",
3120 : : "cnstr_shdsc_pdcp_short_mac", authdata->algtype);
3121 : 0 : return -EINVAL;
3122 : : }
3123 : :
3124 : 0 : return PROGRAM_FINALIZE(p);
3125 : : }
3126 : :
3127 : : #endif /* __DESC_PDCP_H__ */
|