1 /* SPDX-License-Identifier: BSD-3-Clause or GPL-2.0+
2 * Copyright 2008-2013 Freescale Semiconductor, Inc.
3 * Copyright 2019-2020 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 /**
274 * rta_inline_pdcp_query() - Provide indications if a key can be passed as
275 * immediate data or shall be referenced in a
276 * shared descriptor.
277 * Return: 0 if data can be inlined or 1 if referenced.
278 */
279 static inline int
rta_inline_pdcp_query(enum auth_type_pdcp auth_alg,enum cipher_type_pdcp cipher_alg,enum pdcp_sn_size sn_size,int8_t hfn_ovd)280 rta_inline_pdcp_query(enum auth_type_pdcp auth_alg,
281 enum cipher_type_pdcp cipher_alg,
282 enum pdcp_sn_size sn_size,
283 int8_t hfn_ovd)
284 {
285 /**
286 * Shared Descriptors for some of the cases does not fit in the
287 * MAX_DESC_SIZE of the descriptor especially when non-protocol
288 * descriptors are formed as in 18bit cases and when HFN override
289 * is enabled as 2 extra words are added in the job descriptor.
290 * The cases which exceed are for RTA_SEC_ERA=8 and HFN override
291 * enabled and 18bit uplane and either of following Algo combinations.
292 * - SNOW-AES
293 * - AES-SNOW
294 * - SNOW-SNOW
295 * - ZUC-SNOW
296 *
297 * We cannot make inline for all cases, as this will impact performance
298 * due to extra memory accesses for the keys.
299 */
300 if ((rta_sec_era == RTA_SEC_ERA_8) && hfn_ovd &&
301 (sn_size == PDCP_SN_SIZE_18) &&
302 ((cipher_alg == PDCP_CIPHER_TYPE_SNOW &&
303 auth_alg == PDCP_AUTH_TYPE_AES) ||
304 (cipher_alg == PDCP_CIPHER_TYPE_AES &&
305 auth_alg == PDCP_AUTH_TYPE_SNOW) ||
306 (cipher_alg == PDCP_CIPHER_TYPE_SNOW &&
307 auth_alg == PDCP_AUTH_TYPE_SNOW) ||
308 (cipher_alg == PDCP_CIPHER_TYPE_ZUC &&
309 auth_alg == PDCP_AUTH_TYPE_SNOW))) {
310
311 return 1;
312 }
313
314 return 0;
315 }
316
317 /*
318 * Function for appending the portion of a PDCP Control Plane shared descriptor
319 * which performs NULL encryption and integrity (i.e. copies the input frame
320 * to the output frame, appending 32 bits of zeros at the end (MAC-I for
321 * NULL integrity).
322 */
323 static inline int
pdcp_insert_cplane_null_op(struct program * p,bool swap __maybe_unused,struct alginfo * cipherdata __maybe_unused,struct alginfo * authdata __maybe_unused,unsigned int dir,enum pdcp_sn_size sn_size __maybe_unused,unsigned char era_2_sw_hfn_ovrd __maybe_unused)324 pdcp_insert_cplane_null_op(struct program *p,
325 bool swap __maybe_unused,
326 struct alginfo *cipherdata __maybe_unused,
327 struct alginfo *authdata __maybe_unused,
328 unsigned int dir,
329 enum pdcp_sn_size sn_size __maybe_unused,
330 unsigned char era_2_sw_hfn_ovrd __maybe_unused)
331 {
332 LABEL(local_offset);
333 REFERENCE(move_cmd_read_descbuf);
334 REFERENCE(move_cmd_write_descbuf);
335
336 if (rta_sec_era > RTA_SEC_ERA_2) {
337 MATHB(p, SEQINSZ, ADD, ZERO, VSEQINSZ, 4, 0);
338 if (dir == OP_TYPE_ENCAP_PROTOCOL)
339 MATHB(p, SEQINSZ, ADD, PDCP_MAC_I_LEN, VSEQOUTSZ, 4,
340 IMMED2);
341 else
342 MATHB(p, SEQINSZ, SUB, PDCP_MAC_I_LEN, VSEQOUTSZ, 4,
343 IMMED2);
344 } else {
345 MATHB(p, SEQINSZ, ADD, ONE, VSEQINSZ, 4, 0);
346 MATHB(p, VSEQINSZ, SUB, ONE, VSEQINSZ, 4, 0);
347
348 if (dir == OP_TYPE_ENCAP_PROTOCOL) {
349 MATHB(p, SEQINSZ, ADD, PDCP_MAC_I_LEN, VSEQOUTSZ, 4,
350 IMMED2);
351 MATHB(p, VSEQINSZ, SUB, ONE, MATH0, 4, 0);
352 } else {
353 MATHB(p, VSEQINSZ, SUB, PDCP_MAC_I_LEN, VSEQINSZ, 4,
354 IMMED2);
355 MATHB(p, SEQINSZ, SUB, PDCP_MAC_I_LEN, VSEQOUTSZ, 4,
356 IMMED2);
357 MATHB(p, VSEQOUTSZ, SUB, ONE, MATH0, 4, 0);
358 }
359
360 MATHB(p, MATH0, ADD, ONE, MATH0, 4, 0);
361
362 /*
363 * Since MOVELEN is available only starting with
364 * SEC ERA 3, use poor man's MOVELEN: create a MOVE
365 * command dynamically by writing the length from M1 by
366 * OR-ing the command in the M1 register and MOVE the
367 * result into the descriptor buffer. Care must be taken
368 * wrt. the location of the command because of SEC
369 * pipelining. The actual MOVEs are written at the end
370 * of the descriptor due to calculations needed on the
371 * offset in the descriptor for the MOVE command.
372 */
373 move_cmd_read_descbuf = MOVE(p, DESCBUF, 0, MATH0, 0, 6,
374 IMMED);
375 move_cmd_write_descbuf = MOVE(p, MATH0, 0, DESCBUF, 0, 8,
376 WAITCOMP | IMMED);
377 }
378 MATHB(p, VSEQINSZ, SUB, PDCP_NULL_MAX_FRAME_LEN, NONE, 4,
379 IMMED2);
380 JUMP(p, PDCP_MAX_FRAME_LEN_STATUS, HALT_STATUS, ALL_FALSE, MATH_N);
381
382 if (rta_sec_era > RTA_SEC_ERA_2) {
383 if (dir == OP_TYPE_ENCAP_PROTOCOL)
384 MATHB(p, VSEQINSZ, ADD, ZERO, MATH0, 4, 0);
385 else
386 MATHB(p, VSEQOUTSZ, ADD, ZERO, MATH0, 4, 0);
387 }
388 SEQFIFOSTORE(p, MSG, 0, 0, VLF);
389 SEQFIFOLOAD(p, MSG1, 0, VLF | LAST1 | FLUSH1);
390
391 if (rta_sec_era > RTA_SEC_ERA_2) {
392 MOVE(p, AB1, 0, OFIFO, 0, MATH0, 0);
393 } else {
394 SET_LABEL(p, local_offset);
395
396 /* Shut off automatic Info FIFO entries */
397 LOAD(p, 0, DCTRL, LDOFF_DISABLE_AUTO_NFIFO, 0, IMMED);
398 /* Placeholder for MOVE command with length from M1 register */
399 MOVE(p, IFIFOAB1, 0, OFIFO, 0, 0, IMMED);
400 /* Enable automatic Info FIFO entries */
401 LOAD(p, 0, DCTRL, LDOFF_ENABLE_AUTO_NFIFO, 0, IMMED);
402 }
403
404 if (dir == OP_TYPE_ENCAP_PROTOCOL) {
405 MATHB(p, MATH1, XOR, MATH1, MATH0, 8, 0);
406 MOVE(p, MATH0, 0, OFIFO, 0, 4, IMMED);
407 }
408
409 if (rta_sec_era < RTA_SEC_ERA_3) {
410 PATCH_MOVE(p, move_cmd_read_descbuf, local_offset);
411 PATCH_MOVE(p, move_cmd_write_descbuf, local_offset);
412 }
413
414 return 0;
415 }
416
417 static inline int
insert_copy_frame_op(struct program * p,struct alginfo * cipherdata __maybe_unused,unsigned int dir __maybe_unused)418 insert_copy_frame_op(struct program *p,
419 struct alginfo *cipherdata __maybe_unused,
420 unsigned int dir __maybe_unused)
421 {
422 LABEL(local_offset);
423 REFERENCE(move_cmd_read_descbuf);
424 REFERENCE(move_cmd_write_descbuf);
425
426 if (rta_sec_era > RTA_SEC_ERA_2) {
427 MATHB(p, SEQINSZ, ADD, ZERO, VSEQINSZ, 4, 0);
428 MATHB(p, SEQINSZ, ADD, ZERO, VSEQOUTSZ, 4, 0);
429 } else {
430 MATHB(p, SEQINSZ, ADD, ONE, VSEQINSZ, 4, 0);
431 MATHB(p, VSEQINSZ, SUB, ONE, VSEQINSZ, 4, 0);
432 MATHB(p, SEQINSZ, ADD, ONE, VSEQOUTSZ, 4, 0);
433 MATHB(p, VSEQOUTSZ, SUB, ONE, VSEQOUTSZ, 4, 0);
434 MATHB(p, VSEQINSZ, SUB, ONE, MATH0, 4, 0);
435 MATHB(p, MATH0, ADD, ONE, MATH0, 4, 0);
436
437 /*
438 * Since MOVELEN is available only starting with
439 * SEC ERA 3, use poor man's MOVELEN: create a MOVE
440 * command dynamically by writing the length from M1 by
441 * OR-ing the command in the M1 register and MOVE the
442 * result into the descriptor buffer. Care must be taken
443 * wrt. the location of the command because of SEC
444 * pipelining. The actual MOVEs are written at the end
445 * of the descriptor due to calculations needed on the
446 * offset in the descriptor for the MOVE command.
447 */
448 move_cmd_read_descbuf = MOVE(p, DESCBUF, 0, MATH0, 0, 6,
449 IMMED);
450 move_cmd_write_descbuf = MOVE(p, MATH0, 0, DESCBUF, 0, 8,
451 WAITCOMP | IMMED);
452 }
453 MATHB(p, SEQINSZ, SUB, PDCP_NULL_MAX_FRAME_LEN, NONE, 4,
454 IFB | IMMED2);
455 JUMP(p, PDCP_MAX_FRAME_LEN_STATUS, HALT_STATUS, ALL_FALSE, MATH_N);
456
457 if (rta_sec_era > RTA_SEC_ERA_2)
458 MATHB(p, VSEQINSZ, ADD, ZERO, MATH0, 4, 0);
459
460 SEQFIFOLOAD(p, MSG1, 0, VLF | LAST1 | FLUSH1);
461 if (rta_sec_era > RTA_SEC_ERA_2) {
462 MOVE(p, AB1, 0, OFIFO, 0, MATH0, 0);
463 } else {
464 SET_LABEL(p, local_offset);
465
466 /* Shut off automatic Info FIFO entries */
467 LOAD(p, 0, DCTRL, LDOFF_DISABLE_AUTO_NFIFO, 0, IMMED);
468
469 /* Placeholder for MOVE command with length from M0 register */
470 MOVE(p, IFIFOAB1, 0, OFIFO, 0, 0, IMMED);
471
472 /* Enable automatic Info FIFO entries */
473 LOAD(p, 0, DCTRL, LDOFF_ENABLE_AUTO_NFIFO, 0, IMMED);
474 }
475
476 SEQFIFOSTORE(p, MSG, 0, 0, VLF);
477
478 if (rta_sec_era < RTA_SEC_ERA_3) {
479 PATCH_MOVE(p, move_cmd_read_descbuf, local_offset);
480 PATCH_MOVE(p, move_cmd_write_descbuf, local_offset);
481 }
482 return 0;
483 }
484
485 static inline int
pdcp_insert_cplane_int_only_op(struct program * p,bool swap __maybe_unused,struct alginfo * cipherdata __maybe_unused,struct alginfo * authdata,unsigned int dir,enum pdcp_sn_size sn_size,unsigned char era_2_sw_hfn_ovrd)486 pdcp_insert_cplane_int_only_op(struct program *p,
487 bool swap __maybe_unused,
488 struct alginfo *cipherdata __maybe_unused,
489 struct alginfo *authdata, unsigned int dir,
490 enum pdcp_sn_size sn_size,
491 unsigned char era_2_sw_hfn_ovrd)
492 {
493 uint32_t offset = 0, length = 0, sn_mask = 0;
494
495 /* 12 bit SN is only supported for protocol offload case */
496 if (rta_sec_era >= RTA_SEC_ERA_8 && sn_size == PDCP_SN_SIZE_12) {
497 KEY(p, KEY2, authdata->key_enc_flags, authdata->key,
498 authdata->keylen, INLINE_KEY(authdata));
499
500 PROTOCOL(p, dir, OP_PCLID_LTE_PDCP_USER_RN,
501 (uint16_t)authdata->algtype);
502 return 0;
503 }
504
505 /* Non-proto is supported only for 5bit cplane and 18bit uplane */
506 switch (sn_size) {
507 case PDCP_SN_SIZE_5:
508 offset = 7;
509 length = 1;
510 sn_mask = (swap == false) ? PDCP_C_PLANE_SN_MASK :
511 PDCP_C_PLANE_SN_MASK_BE;
512 break;
513 case PDCP_SN_SIZE_18:
514 offset = 5;
515 length = 3;
516 sn_mask = (swap == false) ? PDCP_U_PLANE_18BIT_SN_MASK :
517 PDCP_U_PLANE_18BIT_SN_MASK_BE;
518 break;
519 case PDCP_SN_SIZE_7:
520 case PDCP_SN_SIZE_12:
521 case PDCP_SN_SIZE_15:
522 pr_err("Invalid sn_size for %s\n", __func__);
523 return -ENOTSUP;
524
525 }
526 LABEL(local_offset);
527 REFERENCE(move_cmd_read_descbuf);
528 REFERENCE(move_cmd_write_descbuf);
529
530 switch (authdata->algtype) {
531 case PDCP_AUTH_TYPE_SNOW:
532 /* Insert Auth Key */
533 KEY(p, KEY2, authdata->key_enc_flags, authdata->key,
534 authdata->keylen, INLINE_KEY(authdata));
535 SEQLOAD(p, MATH0, offset, length, 0);
536 JUMP(p, 1, LOCAL_JUMP, ALL_TRUE, CALM);
537
538 if (rta_sec_era > RTA_SEC_ERA_2 ||
539 (rta_sec_era == RTA_SEC_ERA_2 &&
540 era_2_sw_hfn_ovrd == 0)) {
541 SEQINPTR(p, 0, length, RTO);
542 } else {
543 SEQINPTR(p, 0, 5, RTO);
544 SEQFIFOLOAD(p, SKIP, 4, 0);
545 }
546
547 if (swap == false) {
548 MATHB(p, MATH0, AND, sn_mask, MATH1, 8,
549 IFB | IMMED2);
550 MATHB(p, MATH1, SHLD, MATH1, MATH1, 8, 0);
551
552 MOVEB(p, DESCBUF, 8, MATH2, 0, 8, WAITCOMP | IMMED);
553
554 MATHB(p, MATH2, AND, PDCP_BEARER_MASK, MATH2, 8,
555 IMMED2);
556 MOVEB(p, DESCBUF, 0x0C, MATH3, 0, 4, WAITCOMP | IMMED);
557 MATHB(p, MATH3, AND, PDCP_DIR_MASK, MATH3, 8, IMMED2);
558 MATHB(p, MATH1, OR, MATH2, MATH2, 8, 0);
559 MOVEB(p, MATH2, 0, CONTEXT2, 0, 0x0C, WAITCOMP | IMMED);
560 } else {
561 MATHB(p, MATH0, AND, sn_mask, MATH1, 8,
562 IFB | IMMED2);
563 MATHB(p, MATH1, SHLD, MATH1, MATH1, 8, 0);
564
565 MOVE(p, DESCBUF, 8, MATH2, 0, 8, WAITCOMP | IMMED);
566 MATHB(p, MATH2, AND, PDCP_BEARER_MASK_BE, MATH2, 8,
567 IMMED2);
568
569 MOVE(p, DESCBUF, 0x0C, MATH3, 0, 4, WAITCOMP | IMMED);
570 MATHB(p, MATH3, AND, PDCP_DIR_MASK_BE, MATH3, 8,
571 IMMED2);
572 MATHB(p, MATH1, OR, MATH2, MATH2, 8, 0);
573 MOVE(p, MATH2, 0, CONTEXT2, 0, 0x0C, WAITCOMP | IMMED);
574 }
575
576 if (dir == OP_TYPE_DECAP_PROTOCOL) {
577 MATHB(p, SEQINSZ, SUB, PDCP_MAC_I_LEN, MATH1, 4,
578 IMMED2);
579 } else {
580 if (rta_sec_era > RTA_SEC_ERA_2) {
581 MATHB(p, SEQINSZ, SUB, ZERO, MATH1, 4,
582 0);
583 } else {
584 MATHB(p, SEQINSZ, ADD, ONE, MATH1, 4,
585 0);
586 MATHB(p, MATH1, SUB, ONE, MATH1, 4,
587 0);
588 }
589 }
590
591 if (rta_sec_era > RTA_SEC_ERA_2) {
592 MATHB(p, MATH1, SUB, ZERO, VSEQINSZ, 4, 0);
593 MATHB(p, MATH1, SUB, ZERO, VSEQOUTSZ, 4, 0);
594 } else {
595 MATHB(p, ZERO, ADD, MATH1, VSEQINSZ, 4, 0);
596 MATHB(p, ZERO, ADD, MATH1, VSEQOUTSZ, 4, 0);
597
598 /*
599 * Since MOVELEN is available only starting with
600 * SEC ERA 3, use poor man's MOVELEN: create a MOVE
601 * command dynamically by writing the length from M1 by
602 * OR-ing the command in the M1 register and MOVE the
603 * result into the descriptor buffer. Care must be taken
604 * wrt. the location of the command because of SEC
605 * pipelining. The actual MOVEs are written at the end
606 * of the descriptor due to calculations needed on the
607 * offset in the descriptor for the MOVE command.
608 */
609 move_cmd_read_descbuf = MOVE(p, DESCBUF, 0, MATH1, 0, 6,
610 IMMED);
611 move_cmd_write_descbuf = MOVE(p, MATH1, 0, DESCBUF, 0,
612 8, WAITCOMP | IMMED);
613 }
614
615 SEQFIFOSTORE(p, MSG, 0, 0, VLF);
616 ALG_OPERATION(p, OP_ALG_ALGSEL_SNOW_F9, OP_ALG_AAI_F9,
617 OP_ALG_AS_INITFINAL,
618 dir == OP_TYPE_ENCAP_PROTOCOL ?
619 ICV_CHECK_DISABLE : ICV_CHECK_ENABLE,
620 DIR_ENC);
621
622 if (rta_sec_era > RTA_SEC_ERA_2) {
623 SEQFIFOLOAD(p, MSGINSNOOP, 0,
624 VLF | LAST1 | LAST2 | FLUSH1);
625 MOVE(p, AB1, 0, OFIFO, 0, MATH1, 0);
626 } else {
627 SEQFIFOLOAD(p, MSGINSNOOP, 0,
628 VLF | LAST1 | LAST2 | FLUSH1);
629 SET_LABEL(p, local_offset);
630
631 /* Shut off automatic Info FIFO entries */
632 LOAD(p, 0, DCTRL, LDOFF_DISABLE_AUTO_NFIFO, 0, IMMED);
633 /*
634 * Placeholder for MOVE command with length from M1
635 * register
636 */
637 MOVE(p, IFIFOAB1, 0, OFIFO, 0, 0, IMMED);
638 /* Enable automatic Info FIFO entries */
639 LOAD(p, 0, DCTRL, LDOFF_ENABLE_AUTO_NFIFO, 0, IMMED);
640 }
641
642 if (dir == OP_TYPE_DECAP_PROTOCOL)
643 SEQFIFOLOAD(p, ICV2, 4, LAST2);
644 else
645 SEQSTORE(p, CONTEXT2, 0, 4, 0);
646
647 break;
648
649 case PDCP_AUTH_TYPE_AES:
650 /* Insert Auth Key */
651 KEY(p, KEY1, authdata->key_enc_flags, authdata->key,
652 authdata->keylen, INLINE_KEY(authdata));
653 SEQLOAD(p, MATH0, offset, length, 0);
654 JUMP(p, 1, LOCAL_JUMP, ALL_TRUE, CALM);
655 if (rta_sec_era > RTA_SEC_ERA_2 ||
656 (rta_sec_era == RTA_SEC_ERA_2 &&
657 era_2_sw_hfn_ovrd == 0)) {
658 SEQINPTR(p, 0, length, RTO);
659 } else {
660 SEQINPTR(p, 0, 5, RTO);
661 SEQFIFOLOAD(p, SKIP, 4, 0);
662 }
663
664 if (swap == false) {
665 MATHB(p, MATH0, AND, sn_mask, MATH1, 8,
666 IFB | IMMED2);
667 MATHB(p, MATH1, SHLD, MATH1, MATH1, 8, 0);
668
669 MOVEB(p, DESCBUF, 8, MATH2, 0, 8, WAITCOMP | IMMED);
670 MATHB(p, MATH1, OR, MATH2, MATH2, 8, 0);
671 MOVEB(p, MATH2, 0, IFIFOAB1, 0, 8, IMMED);
672 } else {
673 MATHB(p, MATH0, AND, sn_mask, MATH1, 8,
674 IFB | IMMED2);
675 MATHB(p, MATH1, SHLD, MATH1, MATH1, 8, 0);
676
677 MOVE(p, DESCBUF, 8, MATH2, 0, 8, WAITCOMP | IMMED);
678 MATHB(p, MATH1, OR, MATH2, MATH2, 8, 0);
679 MOVE(p, MATH2, 0, IFIFOAB1, 0, 8, IMMED);
680 }
681
682 if (dir == OP_TYPE_DECAP_PROTOCOL) {
683 MATHB(p, SEQINSZ, SUB, PDCP_MAC_I_LEN, MATH1, 4,
684 IMMED2);
685 } else {
686 if (rta_sec_era > RTA_SEC_ERA_2) {
687 MATHB(p, SEQINSZ, SUB, ZERO, MATH1, 4,
688 0);
689 } else {
690 MATHB(p, SEQINSZ, ADD, ONE, MATH1, 4,
691 0);
692 MATHB(p, MATH1, SUB, ONE, MATH1, 4,
693 0);
694 }
695 }
696
697 if (rta_sec_era > RTA_SEC_ERA_2) {
698 MATHB(p, MATH1, SUB, ZERO, VSEQINSZ, 4, 0);
699 MATHB(p, MATH1, SUB, ZERO, VSEQOUTSZ, 4, 0);
700 } else {
701 MATHB(p, ZERO, ADD, MATH1, VSEQINSZ, 4, 0);
702 MATHB(p, ZERO, ADD, MATH1, VSEQOUTSZ, 4, 0);
703
704 /*
705 * Since MOVELEN is available only starting with
706 * SEC ERA 3, use poor man's MOVELEN: create a MOVE
707 * command dynamically by writing the length from M1 by
708 * OR-ing the command in the M1 register and MOVE the
709 * result into the descriptor buffer. Care must be taken
710 * wrt. the location of the command because of SEC
711 * pipelining. The actual MOVEs are written at the end
712 * of the descriptor due to calculations needed on the
713 * offset in the descriptor for the MOVE command.
714 */
715 move_cmd_read_descbuf = MOVE(p, DESCBUF, 0, MATH1, 0, 6,
716 IMMED);
717 move_cmd_write_descbuf = MOVE(p, MATH1, 0, DESCBUF, 0,
718 8, WAITCOMP | IMMED);
719 }
720 SEQFIFOSTORE(p, MSG, 0, 0, VLF);
721 ALG_OPERATION(p, OP_ALG_ALGSEL_AES,
722 OP_ALG_AAI_CMAC,
723 OP_ALG_AS_INITFINAL,
724 dir == OP_TYPE_ENCAP_PROTOCOL ?
725 ICV_CHECK_DISABLE : ICV_CHECK_ENABLE,
726 DIR_ENC);
727
728 if (rta_sec_era > RTA_SEC_ERA_2) {
729 MOVE(p, AB2, 0, OFIFO, 0, MATH1, 0);
730 SEQFIFOLOAD(p, MSGINSNOOP, 0,
731 VLF | LAST1 | LAST2 | FLUSH1);
732 } else {
733 SEQFIFOLOAD(p, MSGINSNOOP, 0,
734 VLF | LAST1 | LAST2 | FLUSH1);
735 SET_LABEL(p, local_offset);
736
737 /* Shut off automatic Info FIFO entries */
738 LOAD(p, 0, DCTRL, LDOFF_DISABLE_AUTO_NFIFO, 0, IMMED);
739
740 /*
741 * Placeholder for MOVE command with length from
742 * M1 register
743 */
744 MOVE(p, IFIFOAB2, 0, OFIFO, 0, 0, IMMED);
745
746 /* Enable automatic Info FIFO entries */
747 LOAD(p, 0, DCTRL, LDOFF_ENABLE_AUTO_NFIFO, 0, IMMED);
748 }
749
750 if (dir == OP_TYPE_DECAP_PROTOCOL)
751 SEQFIFOLOAD(p, ICV1, 4, LAST1 | FLUSH1);
752 else
753 SEQSTORE(p, CONTEXT1, 0, 4, 0);
754
755 break;
756
757 case PDCP_AUTH_TYPE_ZUC:
758 if (rta_sec_era < RTA_SEC_ERA_5) {
759 pr_err("Invalid era for selected algorithm\n");
760 return -ENOTSUP;
761 }
762 /* Insert Auth Key */
763 KEY(p, KEY2, authdata->key_enc_flags, authdata->key,
764 authdata->keylen, INLINE_KEY(authdata));
765 SEQLOAD(p, MATH0, offset, length, 0);
766 JUMP(p, 1, LOCAL_JUMP, ALL_TRUE, CALM);
767 SEQINPTR(p, 0, length, RTO);
768 if (swap == false) {
769 MATHB(p, MATH0, AND, sn_mask, MATH1, 8,
770 IFB | IMMED2);
771 MATHB(p, MATH1, SHLD, MATH1, MATH1, 8, 0);
772
773 MOVEB(p, DESCBUF, 8, MATH2, 0, 8, WAITCOMP | IMMED);
774 MATHB(p, MATH1, OR, MATH2, MATH2, 8, 0);
775 MOVEB(p, MATH2, 0, CONTEXT2, 0, 8, IMMED);
776
777 } else {
778 MATHB(p, MATH0, AND, sn_mask, MATH1, 8,
779 IFB | IMMED2);
780 MATHB(p, MATH1, SHLD, MATH1, MATH1, 8, 0);
781
782 MOVE(p, DESCBUF, 8, MATH2, 0, 8, WAITCOMP | IMMED);
783 MATHB(p, MATH1, OR, MATH2, MATH2, 8, 0);
784 MOVE(p, MATH2, 0, CONTEXT2, 0, 8, IMMED);
785 }
786 if (dir == OP_TYPE_DECAP_PROTOCOL)
787 MATHB(p, SEQINSZ, SUB, PDCP_MAC_I_LEN, MATH1, 4,
788 IMMED2);
789 else
790 MATHB(p, SEQINSZ, SUB, ZERO, MATH1, 4, 0);
791
792 MATHB(p, MATH1, SUB, ZERO, VSEQINSZ, 4, 0);
793 MATHB(p, MATH1, SUB, ZERO, VSEQOUTSZ, 4, 0);
794 SEQFIFOSTORE(p, MSG, 0, 0, VLF);
795 ALG_OPERATION(p, OP_ALG_ALGSEL_ZUCA,
796 OP_ALG_AAI_F9,
797 OP_ALG_AS_INITFINAL,
798 dir == OP_TYPE_ENCAP_PROTOCOL ?
799 ICV_CHECK_DISABLE : ICV_CHECK_ENABLE,
800 DIR_ENC);
801 SEQFIFOLOAD(p, MSGINSNOOP, 0, VLF | LAST1 | LAST2 | FLUSH1);
802 MOVE(p, AB1, 0, OFIFO, 0, MATH1, 0);
803
804 if (dir == OP_TYPE_DECAP_PROTOCOL)
805 SEQFIFOLOAD(p, ICV2, 4, LAST2);
806 else
807 SEQSTORE(p, CONTEXT2, 0, 4, 0);
808
809 break;
810
811 default:
812 pr_err("%s: Invalid integrity algorithm selected: %d\n",
813 "pdcp_insert_cplane_int_only_op", authdata->algtype);
814 return -EINVAL;
815 }
816
817 if (rta_sec_era < RTA_SEC_ERA_3) {
818 PATCH_MOVE(p, move_cmd_read_descbuf, local_offset);
819 PATCH_MOVE(p, move_cmd_write_descbuf, local_offset);
820 }
821
822 return 0;
823 }
824
825 static inline int
pdcp_insert_cplane_enc_only_op(struct program * p,bool swap __maybe_unused,struct alginfo * cipherdata,struct alginfo * authdata __maybe_unused,unsigned int dir,enum pdcp_sn_size sn_size,unsigned char era_2_sw_hfn_ovrd __maybe_unused)826 pdcp_insert_cplane_enc_only_op(struct program *p,
827 bool swap __maybe_unused,
828 struct alginfo *cipherdata,
829 struct alginfo *authdata __maybe_unused,
830 unsigned int dir,
831 enum pdcp_sn_size sn_size,
832 unsigned char era_2_sw_hfn_ovrd __maybe_unused)
833 {
834 uint32_t offset = 0, length = 0, sn_mask = 0;
835 /* Insert Cipher Key */
836 KEY(p, KEY1, cipherdata->key_enc_flags, cipherdata->key,
837 cipherdata->keylen, INLINE_KEY(cipherdata));
838
839 if ((rta_sec_era >= RTA_SEC_ERA_8 && sn_size != PDCP_SN_SIZE_18 &&
840 !(rta_sec_era == RTA_SEC_ERA_8 &&
841 authdata->algtype == 0))
842 || (rta_sec_era == RTA_SEC_ERA_10)) {
843 if (sn_size == PDCP_SN_SIZE_5)
844 PROTOCOL(p, dir, OP_PCLID_LTE_PDCP_CTRL_MIXED,
845 (uint16_t)cipherdata->algtype << 8);
846 else
847 PROTOCOL(p, dir, OP_PCLID_LTE_PDCP_USER_RN,
848 (uint16_t)cipherdata->algtype << 8);
849 return 0;
850 }
851 /* Non-proto is supported only for 5bit cplane and 18bit uplane */
852 switch (sn_size) {
853 case PDCP_SN_SIZE_5:
854 offset = 7;
855 length = 1;
856 sn_mask = (swap == false) ? PDCP_C_PLANE_SN_MASK :
857 PDCP_C_PLANE_SN_MASK_BE;
858 break;
859 case PDCP_SN_SIZE_18:
860 offset = 5;
861 length = 3;
862 sn_mask = (swap == false) ? PDCP_U_PLANE_18BIT_SN_MASK :
863 PDCP_U_PLANE_18BIT_SN_MASK_BE;
864 break;
865 case PDCP_SN_SIZE_12:
866 offset = 6;
867 length = 2;
868 sn_mask = (swap == false) ? PDCP_12BIT_SN_MASK :
869 PDCP_12BIT_SN_MASK_BE;
870 break;
871 case PDCP_SN_SIZE_7:
872 case PDCP_SN_SIZE_15:
873 pr_err("Invalid sn_size for %s\n", __func__);
874 return -ENOTSUP;
875 }
876
877 SEQLOAD(p, MATH0, offset, length, 0);
878 JUMP(p, 1, LOCAL_JUMP, ALL_TRUE, CALM);
879 MATHB(p, MATH0, AND, sn_mask, MATH1, 8, IFB | IMMED2);
880 SEQSTORE(p, MATH0, offset, length, 0);
881 MATHB(p, MATH1, SHLD, MATH1, MATH1, 8, 0);
882 MOVEB(p, DESCBUF, 8, MATH2, 0, 8, WAITCOMP | IMMED);
883 MATHB(p, MATH1, OR, MATH2, MATH2, 8, 0);
884
885 switch (cipherdata->algtype) {
886 case PDCP_CIPHER_TYPE_SNOW:
887 MOVEB(p, MATH2, 0, CONTEXT1, 0, 8, WAITCOMP | IMMED);
888
889 if (rta_sec_era > RTA_SEC_ERA_2) {
890 MATHB(p, SEQINSZ, SUB, ZERO, VSEQINSZ, 4, 0);
891 } else {
892 MATHB(p, SEQINSZ, SUB, ONE, MATH1, 4, 0);
893 MATHB(p, MATH1, ADD, ONE, VSEQINSZ, 4, 0);
894 }
895
896 if (dir == OP_TYPE_ENCAP_PROTOCOL)
897 MATHB(p, SEQINSZ, ADD, PDCP_MAC_I_LEN, VSEQOUTSZ, 4,
898 IMMED2);
899 else
900 MATHB(p, SEQINSZ, SUB, PDCP_MAC_I_LEN, VSEQOUTSZ, 4,
901 IMMED2);
902 SEQFIFOSTORE(p, MSG, 0, 0, VLF | CONT);
903 ALG_OPERATION(p, OP_ALG_ALGSEL_SNOW_F8,
904 OP_ALG_AAI_F8,
905 OP_ALG_AS_INITFINAL, ICV_CHECK_DISABLE,
906 dir == OP_TYPE_ENCAP_PROTOCOL ?
907 DIR_ENC : DIR_DEC);
908 break;
909
910 case PDCP_CIPHER_TYPE_AES:
911 MOVEB(p, MATH2, 0, CONTEXT1, 0x10, 0x10, WAITCOMP | IMMED);
912
913 if (rta_sec_era > RTA_SEC_ERA_2) {
914 MATHB(p, SEQINSZ, SUB, ZERO, VSEQINSZ, 4, 0);
915 } else {
916 MATHB(p, SEQINSZ, SUB, ONE, MATH1, 4, 0);
917 MATHB(p, MATH1, ADD, ONE, VSEQINSZ, 4, 0);
918 }
919
920 if (dir == OP_TYPE_ENCAP_PROTOCOL)
921 MATHB(p, SEQINSZ, ADD, PDCP_MAC_I_LEN, VSEQOUTSZ, 4,
922 IMMED2);
923 else
924 MATHB(p, SEQINSZ, SUB, PDCP_MAC_I_LEN, VSEQOUTSZ, 4,
925 IMMED2);
926
927 SEQFIFOSTORE(p, MSG, 0, 0, VLF | CONT);
928 ALG_OPERATION(p, OP_ALG_ALGSEL_AES,
929 OP_ALG_AAI_CTR,
930 OP_ALG_AS_INITFINAL,
931 ICV_CHECK_DISABLE,
932 dir == OP_TYPE_ENCAP_PROTOCOL ?
933 DIR_ENC : DIR_DEC);
934 break;
935
936 case PDCP_CIPHER_TYPE_ZUC:
937 if (rta_sec_era < RTA_SEC_ERA_5) {
938 pr_err("Invalid era for selected algorithm\n");
939 return -ENOTSUP;
940 }
941
942 MOVEB(p, MATH2, 0, CONTEXT1, 0, 0x08, IMMED);
943 MOVEB(p, MATH2, 0, CONTEXT1, 0x08, 0x08, WAITCOMP | IMMED);
944 MATHB(p, SEQINSZ, SUB, ZERO, VSEQINSZ, 4, 0);
945 if (dir == OP_TYPE_ENCAP_PROTOCOL)
946 MATHB(p, SEQINSZ, ADD, PDCP_MAC_I_LEN, VSEQOUTSZ, 4,
947 IMMED2);
948 else
949 MATHB(p, SEQINSZ, SUB, PDCP_MAC_I_LEN, VSEQOUTSZ, 4,
950 IMMED2);
951
952 SEQFIFOSTORE(p, MSG, 0, 0, VLF | CONT);
953 ALG_OPERATION(p, OP_ALG_ALGSEL_ZUCE,
954 OP_ALG_AAI_F8,
955 OP_ALG_AS_INITFINAL,
956 ICV_CHECK_DISABLE,
957 dir == OP_TYPE_ENCAP_PROTOCOL ?
958 DIR_ENC : DIR_DEC);
959 break;
960
961 default:
962 pr_err("%s: Invalid encrypt algorithm selected: %d\n",
963 "pdcp_insert_cplane_enc_only_op", cipherdata->algtype);
964 return -EINVAL;
965 }
966
967 if (dir == OP_TYPE_ENCAP_PROTOCOL) {
968 SEQFIFOLOAD(p, MSG1, 0, VLF);
969 FIFOLOAD(p, MSG1, PDCP_NULL_INT_MAC_I_VAL, 4,
970 LAST1 | FLUSH1 | IMMED);
971 } else {
972 SEQFIFOLOAD(p, MSG1, 0, VLF | LAST1 | FLUSH1);
973 MOVE(p, OFIFO, 0, MATH1, 4, PDCP_MAC_I_LEN, WAITCOMP | IMMED);
974 MATHB(p, MATH1, XOR, PDCP_NULL_INT_MAC_I_VAL, NONE, 4, IMMED2);
975 JUMP(p, PDCP_NULL_INT_ICV_CHECK_FAILED_STATUS,
976 HALT_STATUS, ALL_FALSE, MATH_Z);
977 }
978
979 return 0;
980 }
981
982 static inline int
pdcp_insert_uplane_snow_snow_op(struct program * p,bool swap __maybe_unused,struct alginfo * cipherdata,struct alginfo * authdata,unsigned int dir,enum pdcp_sn_size sn_size,unsigned char era_2_sw_hfn_ovrd __maybe_unused)983 pdcp_insert_uplane_snow_snow_op(struct program *p,
984 bool swap __maybe_unused,
985 struct alginfo *cipherdata,
986 struct alginfo *authdata,
987 unsigned int dir,
988 enum pdcp_sn_size sn_size,
989 unsigned char era_2_sw_hfn_ovrd __maybe_unused)
990 {
991 uint32_t offset = 0, length = 0, sn_mask = 0;
992
993 KEY(p, KEY1, cipherdata->key_enc_flags, cipherdata->key,
994 cipherdata->keylen, INLINE_KEY(cipherdata));
995 KEY(p, KEY2, authdata->key_enc_flags, authdata->key, authdata->keylen,
996 INLINE_KEY(authdata));
997
998 if (rta_sec_era >= RTA_SEC_ERA_8 && sn_size != PDCP_SN_SIZE_18) {
999 int pclid;
1000
1001 if (sn_size == PDCP_SN_SIZE_5)
1002 pclid = OP_PCLID_LTE_PDCP_CTRL_MIXED;
1003 else
1004 pclid = OP_PCLID_LTE_PDCP_USER_RN;
1005
1006 PROTOCOL(p, dir, pclid,
1007 ((uint16_t)cipherdata->algtype << 8) |
1008 (uint16_t)authdata->algtype);
1009
1010 return 0;
1011 }
1012 /* Non-proto is supported only for 5bit cplane and 18bit uplane */
1013 switch (sn_size) {
1014 case PDCP_SN_SIZE_5:
1015 offset = 7;
1016 length = 1;
1017 sn_mask = (swap == false) ? PDCP_C_PLANE_SN_MASK :
1018 PDCP_C_PLANE_SN_MASK_BE;
1019 break;
1020 case PDCP_SN_SIZE_18:
1021 offset = 5;
1022 length = 3;
1023 sn_mask = (swap == false) ? PDCP_U_PLANE_18BIT_SN_MASK :
1024 PDCP_U_PLANE_18BIT_SN_MASK_BE;
1025 break;
1026 case PDCP_SN_SIZE_7:
1027 case PDCP_SN_SIZE_12:
1028 case PDCP_SN_SIZE_15:
1029 pr_err("Invalid sn_size for %s\n", __func__);
1030 return -ENOTSUP;
1031 }
1032
1033 if (dir == OP_TYPE_ENCAP_PROTOCOL)
1034 MATHB(p, SEQINSZ, SUB, length, VSEQINSZ, 4, IMMED2);
1035
1036 SEQLOAD(p, MATH0, offset, length, 0);
1037 JUMP(p, 1, LOCAL_JUMP, ALL_TRUE, CALM);
1038 MOVEB(p, MATH0, offset, IFIFOAB2, 0, length, IMMED);
1039 MATHB(p, MATH0, AND, sn_mask, MATH1, 8, IFB | IMMED2);
1040
1041 SEQSTORE(p, MATH0, offset, length, 0);
1042 MATHB(p, MATH1, SHLD, MATH1, MATH1, 8, 0);
1043 MOVEB(p, DESCBUF, 8, MATH2, 0, 8, WAITCOMP | IMMED);
1044 MATHB(p, MATH1, OR, MATH2, MATH1, 8, 0);
1045 MOVEB(p, MATH1, 0, CONTEXT1, 0, 8, IMMED);
1046 MOVEB(p, MATH1, 0, CONTEXT2, 0, 4, WAITCOMP | IMMED);
1047 if (swap == false) {
1048 MATHB(p, MATH1, AND, upper_32_bits(PDCP_BEARER_MASK),
1049 MATH2, 4, IMMED2);
1050 MATHB(p, MATH1, AND, lower_32_bits(PDCP_DIR_MASK),
1051 MATH3, 4, IMMED2);
1052 } else {
1053 MATHB(p, MATH1, AND, lower_32_bits(PDCP_BEARER_MASK_BE),
1054 MATH2, 4, IMMED2);
1055 MATHB(p, MATH1, AND, upper_32_bits(PDCP_DIR_MASK_BE),
1056 MATH3, 4, IMMED2);
1057 }
1058 MATHB(p, MATH3, SHLD, MATH3, MATH3, 8, 0);
1059
1060 MOVEB(p, MATH2, 4, OFIFO, 0, 12, IMMED);
1061 MOVE(p, OFIFO, 0, CONTEXT2, 4, 12, IMMED);
1062 if (dir == OP_TYPE_ENCAP_PROTOCOL) {
1063 MATHB(p, SEQINSZ, ADD, PDCP_MAC_I_LEN, VSEQOUTSZ, 4, IMMED2);
1064 } else {
1065 MATHI(p, SEQINSZ, SUB, PDCP_MAC_I_LEN, VSEQOUTSZ, 4, IMMED2);
1066 MATHI(p, SEQINSZ, SUB, PDCP_MAC_I_LEN, VSEQINSZ, 4, IMMED2);
1067 }
1068
1069 if (dir == OP_TYPE_ENCAP_PROTOCOL)
1070 SEQFIFOSTORE(p, MSG, 0, 0, VLF);
1071 else
1072 SEQFIFOSTORE(p, MSG, 0, 0, VLF | CONT);
1073
1074 ALG_OPERATION(p, OP_ALG_ALGSEL_SNOW_F9,
1075 OP_ALG_AAI_F9,
1076 OP_ALG_AS_INITFINAL,
1077 dir == OP_TYPE_ENCAP_PROTOCOL ?
1078 ICV_CHECK_DISABLE : ICV_CHECK_ENABLE,
1079 DIR_DEC);
1080 ALG_OPERATION(p, OP_ALG_ALGSEL_SNOW_F8,
1081 OP_ALG_AAI_F8,
1082 OP_ALG_AS_INITFINAL,
1083 ICV_CHECK_DISABLE,
1084 dir == OP_TYPE_ENCAP_PROTOCOL ? DIR_ENC : DIR_DEC);
1085
1086 if (dir == OP_TYPE_ENCAP_PROTOCOL) {
1087 SEQFIFOLOAD(p, MSGINSNOOP, 0, VLF | LAST2);
1088 MOVE(p, CONTEXT2, 0, IFIFOAB1, 0, 4, LAST1 | FLUSH1 | IMMED);
1089 } else {
1090 SEQFIFOLOAD(p, MSGOUTSNOOP, 0, VLF | LAST2);
1091 SEQFIFOLOAD(p, MSG1, 4, LAST1 | FLUSH1);
1092 JUMP(p, 1, LOCAL_JUMP, ALL_TRUE, CLASS1 | NOP | NIFP);
1093
1094 if (rta_sec_era >= RTA_SEC_ERA_6)
1095 LOAD(p, 0, DCTRL, 0, LDLEN_RST_CHA_OFIFO_PTR, IMMED);
1096
1097 MOVE(p, OFIFO, 0, MATH0, 0, 4, WAITCOMP | IMMED);
1098
1099 NFIFOADD(p, IFIFO, ICV2, 4, LAST2);
1100
1101 if (rta_sec_era <= RTA_SEC_ERA_2) {
1102 /* Shut off automatic Info FIFO entries */
1103 LOAD(p, 0, DCTRL, LDOFF_DISABLE_AUTO_NFIFO, 0, IMMED);
1104 MOVE(p, MATH0, 0, IFIFOAB2, 0, 4, WAITCOMP | IMMED);
1105 } else {
1106 MOVE(p, MATH0, 0, IFIFO, 0, 4, WAITCOMP | IMMED);
1107 }
1108 }
1109
1110 return 0;
1111 }
1112
1113 static inline int
pdcp_insert_uplane_zuc_zuc_op(struct program * p,bool swap __maybe_unused,struct alginfo * cipherdata,struct alginfo * authdata,unsigned int dir,enum pdcp_sn_size sn_size,unsigned char era_2_sw_hfn_ovrd __maybe_unused)1114 pdcp_insert_uplane_zuc_zuc_op(struct program *p,
1115 bool swap __maybe_unused,
1116 struct alginfo *cipherdata,
1117 struct alginfo *authdata,
1118 unsigned int dir,
1119 enum pdcp_sn_size sn_size,
1120 unsigned char era_2_sw_hfn_ovrd __maybe_unused)
1121 {
1122 uint32_t offset = 0, length = 0, sn_mask = 0;
1123
1124 LABEL(keyjump);
1125 REFERENCE(pkeyjump);
1126
1127 if (rta_sec_era < RTA_SEC_ERA_5) {
1128 pr_err("Invalid era for selected algorithm\n");
1129 return -ENOTSUP;
1130 }
1131
1132 pkeyjump = JUMP(p, keyjump, LOCAL_JUMP, ALL_TRUE, SHRD | SELF | BOTH);
1133 KEY(p, KEY1, cipherdata->key_enc_flags, cipherdata->key,
1134 cipherdata->keylen, INLINE_KEY(cipherdata));
1135 KEY(p, KEY2, authdata->key_enc_flags, authdata->key, authdata->keylen,
1136 INLINE_KEY(authdata));
1137
1138 SET_LABEL(p, keyjump);
1139 PATCH_JUMP(p, pkeyjump, keyjump);
1140
1141 if (rta_sec_era >= RTA_SEC_ERA_8 && sn_size != PDCP_SN_SIZE_18) {
1142 int pclid;
1143
1144 if (sn_size == PDCP_SN_SIZE_5)
1145 pclid = OP_PCLID_LTE_PDCP_CTRL_MIXED;
1146 else
1147 pclid = OP_PCLID_LTE_PDCP_USER_RN;
1148
1149 PROTOCOL(p, dir, pclid,
1150 ((uint16_t)cipherdata->algtype << 8) |
1151 (uint16_t)authdata->algtype);
1152
1153 return 0;
1154 }
1155 /* Non-proto is supported only for 5bit cplane and 18bit uplane */
1156 switch (sn_size) {
1157 case PDCP_SN_SIZE_5:
1158 offset = 7;
1159 length = 1;
1160 sn_mask = (swap == false) ? PDCP_C_PLANE_SN_MASK :
1161 PDCP_C_PLANE_SN_MASK_BE;
1162 break;
1163 case PDCP_SN_SIZE_18:
1164 offset = 5;
1165 length = 3;
1166 sn_mask = (swap == false) ? PDCP_U_PLANE_18BIT_SN_MASK :
1167 PDCP_U_PLANE_18BIT_SN_MASK_BE;
1168 break;
1169 case PDCP_SN_SIZE_7:
1170 case PDCP_SN_SIZE_12:
1171 case PDCP_SN_SIZE_15:
1172 pr_err("Invalid sn_size for %s\n", __func__);
1173 return -ENOTSUP;
1174 }
1175
1176 SEQLOAD(p, MATH0, offset, length, 0);
1177 JUMP(p, 1, LOCAL_JUMP, ALL_TRUE, CALM);
1178 MOVEB(p, MATH0, offset, IFIFOAB2, 0, length, IMMED);
1179 MATHB(p, MATH0, AND, sn_mask, MATH1, 8, IFB | IMMED2);
1180 MATHB(p, MATH1, SHLD, MATH1, MATH1, 8, 0);
1181
1182 MOVEB(p, DESCBUF, 8, MATH2, 0, 8, WAITCOMP | IMMED);
1183 MATHB(p, MATH1, OR, MATH2, MATH2, 8, 0);
1184 MOVEB(p, MATH2, 0, CONTEXT1, 0, 8, IMMED);
1185
1186 MOVEB(p, MATH2, 0, CONTEXT2, 0, 8, WAITCOMP | IMMED);
1187
1188 if (dir == OP_TYPE_ENCAP_PROTOCOL)
1189 MATHB(p, SEQINSZ, ADD, PDCP_MAC_I_LEN, VSEQOUTSZ, 4, IMMED2);
1190 else
1191 MATHB(p, SEQINSZ, SUB, PDCP_MAC_I_LEN, VSEQOUTSZ, 4, IMMED2);
1192
1193 MATHB(p, SEQINSZ, SUB, ZERO, VSEQINSZ, 4, 0);
1194 SEQSTORE(p, MATH0, offset, length, 0);
1195
1196 if (dir == OP_TYPE_ENCAP_PROTOCOL) {
1197 SEQFIFOSTORE(p, MSG, 0, 0, VLF);
1198 SEQFIFOLOAD(p, MSGINSNOOP, 0, VLF | LAST2);
1199 } else {
1200 SEQFIFOSTORE(p, MSG, 0, 0, VLF | CONT);
1201 SEQFIFOLOAD(p, MSGOUTSNOOP, 0, VLF | LAST1 | FLUSH1);
1202 }
1203
1204 ALG_OPERATION(p, OP_ALG_ALGSEL_ZUCA,
1205 OP_ALG_AAI_F9,
1206 OP_ALG_AS_INITFINAL,
1207 dir == OP_TYPE_ENCAP_PROTOCOL ?
1208 ICV_CHECK_DISABLE : ICV_CHECK_ENABLE,
1209 DIR_ENC);
1210
1211 ALG_OPERATION(p, OP_ALG_ALGSEL_ZUCE,
1212 OP_ALG_AAI_F8,
1213 OP_ALG_AS_INITFINAL,
1214 ICV_CHECK_DISABLE,
1215 dir == OP_TYPE_ENCAP_PROTOCOL ? DIR_ENC : DIR_DEC);
1216
1217 if (dir == OP_TYPE_ENCAP_PROTOCOL) {
1218 MOVE(p, CONTEXT2, 0, IFIFOAB1, 0, 4, LAST1 | FLUSH1 | IMMED);
1219 } else {
1220 /* Save ICV */
1221 MOVEB(p, OFIFO, 0, MATH0, 0, 4, IMMED);
1222
1223 LOAD(p, NFIFOENTRY_STYPE_ALTSOURCE |
1224 NFIFOENTRY_DEST_CLASS2 |
1225 NFIFOENTRY_DTYPE_ICV |
1226 NFIFOENTRY_LC2 | 4, NFIFO_SZL, 0, 4, IMMED);
1227 MOVEB(p, MATH0, 0, ALTSOURCE, 0, 4, WAITCOMP | IMMED);
1228 }
1229
1230 /* Reset ZUCA mode and done interrupt */
1231 LOAD(p, CLRW_CLR_C2MODE, CLRW, 0, 4, IMMED);
1232 LOAD(p, CIRQ_ZADI, ICTRL, 0, 4, IMMED);
1233
1234 return 0;
1235 }
1236
1237 static inline int
pdcp_insert_uplane_aes_aes_op(struct program * p,bool swap __maybe_unused,struct alginfo * cipherdata,struct alginfo * authdata,unsigned int dir,enum pdcp_sn_size sn_size,unsigned char era_2_sw_hfn_ovrd __maybe_unused)1238 pdcp_insert_uplane_aes_aes_op(struct program *p,
1239 bool swap __maybe_unused,
1240 struct alginfo *cipherdata,
1241 struct alginfo *authdata,
1242 unsigned int dir,
1243 enum pdcp_sn_size sn_size,
1244 unsigned char era_2_sw_hfn_ovrd __maybe_unused)
1245 {
1246 uint32_t offset = 0, length = 0, sn_mask = 0;
1247
1248 if ((rta_sec_era >= RTA_SEC_ERA_8 && sn_size != PDCP_SN_SIZE_18)) {
1249 /* Insert Auth Key */
1250 KEY(p, KEY2, authdata->key_enc_flags, authdata->key,
1251 authdata->keylen, INLINE_KEY(authdata));
1252
1253 /* Insert Cipher Key */
1254 KEY(p, KEY1, cipherdata->key_enc_flags, cipherdata->key,
1255 cipherdata->keylen, INLINE_KEY(cipherdata));
1256
1257 PROTOCOL(p, dir, OP_PCLID_LTE_PDCP_USER_RN,
1258 ((uint16_t)cipherdata->algtype << 8) |
1259 (uint16_t)authdata->algtype);
1260 return 0;
1261 }
1262
1263 /* Non-proto is supported only for 5bit cplane and 18bit uplane */
1264 switch (sn_size) {
1265 case PDCP_SN_SIZE_18:
1266 offset = 5;
1267 length = 3;
1268 sn_mask = (swap == false) ? PDCP_U_PLANE_18BIT_SN_MASK :
1269 PDCP_U_PLANE_18BIT_SN_MASK_BE;
1270 break;
1271
1272 default:
1273 pr_err("Invalid sn_size for %s\n", __func__);
1274 return -ENOTSUP;
1275 }
1276
1277 SEQLOAD(p, MATH0, offset, length, 0);
1278 JUMP(p, 1, LOCAL_JUMP, ALL_TRUE, CALM);
1279 MATHB(p, MATH0, AND, sn_mask, MATH1, 8, IFB | IMMED2);
1280
1281 MATHB(p, MATH1, SHLD, MATH1, MATH1, 8, 0);
1282 MOVEB(p, DESCBUF, 8, MATH2, 0, 0x08, WAITCOMP | IMMED);
1283 MATHB(p, MATH1, OR, MATH2, MATH2, 8, 0);
1284 SEQSTORE(p, MATH0, offset, length, 0);
1285
1286 if (dir == OP_TYPE_ENCAP_PROTOCOL) {
1287 KEY(p, KEY1, authdata->key_enc_flags, authdata->key,
1288 authdata->keylen, INLINE_KEY(authdata));
1289 MOVEB(p, MATH2, 0, IFIFOAB1, 0, 0x08, IMMED);
1290 MOVEB(p, MATH0, offset, IFIFOAB1, 0, length, IMMED);
1291
1292 MATHB(p, SEQINSZ, SUB, ZERO, VSEQINSZ, 4, 0);
1293 MATHB(p, VSEQINSZ, ADD, PDCP_MAC_I_LEN, VSEQOUTSZ, 4, IMMED2);
1294
1295 ALG_OPERATION(p, OP_ALG_ALGSEL_AES,
1296 OP_ALG_AAI_CMAC,
1297 OP_ALG_AS_INITFINAL,
1298 ICV_CHECK_DISABLE,
1299 DIR_DEC);
1300 SEQFIFOLOAD(p, MSG1, 0, VLF | LAST1 | FLUSH1);
1301 MOVEB(p, CONTEXT1, 0, MATH3, 0, 4, WAITCOMP | IMMED);
1302
1303 LOAD(p, CLRW_RESET_CLS1_CHA |
1304 CLRW_CLR_C1KEY |
1305 CLRW_CLR_C1CTX |
1306 CLRW_CLR_C1ICV |
1307 CLRW_CLR_C1DATAS |
1308 CLRW_CLR_C1MODE,
1309 CLRW, 0, 4, IMMED);
1310
1311 KEY(p, KEY1, cipherdata->key_enc_flags, cipherdata->key,
1312 cipherdata->keylen, INLINE_KEY(cipherdata));
1313
1314 MOVEB(p, MATH2, 0, CONTEXT1, 16, 8, IMMED);
1315 SEQINPTR(p, 0, PDCP_NULL_MAX_FRAME_LEN, RTO);
1316
1317 ALG_OPERATION(p, OP_ALG_ALGSEL_AES,
1318 OP_ALG_AAI_CTR,
1319 OP_ALG_AS_INITFINAL,
1320 ICV_CHECK_DISABLE,
1321 DIR_ENC);
1322
1323 SEQFIFOSTORE(p, MSG, 0, 0, VLF);
1324
1325 SEQFIFOLOAD(p, SKIP, length, 0);
1326
1327 SEQFIFOLOAD(p, MSG1, 0, VLF);
1328 MOVEB(p, MATH3, 0, IFIFOAB1, 0, 4, LAST1 | FLUSH1 | IMMED);
1329 } else {
1330 MOVEB(p, MATH2, 0, CONTEXT1, 16, 8, IMMED);
1331 MOVEB(p, MATH2, 0, CONTEXT2, 0, 8, IMMED);
1332
1333 MATHB(p, SEQINSZ, SUB, ZERO, VSEQINSZ, 4, 0);
1334 MATHB(p, SEQINSZ, SUB, PDCP_MAC_I_LEN, VSEQOUTSZ, 4, IMMED2);
1335
1336 KEY(p, KEY1, cipherdata->key_enc_flags, cipherdata->key,
1337 cipherdata->keylen, INLINE_KEY(cipherdata));
1338
1339 ALG_OPERATION(p, OP_ALG_ALGSEL_AES,
1340 OP_ALG_AAI_CTR,
1341 OP_ALG_AS_INITFINAL,
1342 ICV_CHECK_DISABLE,
1343 DIR_DEC);
1344
1345 SEQFIFOSTORE(p, MSG, 0, 0, VLF | CONT);
1346 SEQFIFOLOAD(p, MSG1, 0, VLF | LAST1 | FLUSH1);
1347
1348 MOVEB(p, OFIFO, 0, MATH3, 0, 4, IMMED);
1349
1350 LOAD(p, CLRW_RESET_CLS1_CHA |
1351 CLRW_CLR_C1KEY |
1352 CLRW_CLR_C1CTX |
1353 CLRW_CLR_C1ICV |
1354 CLRW_CLR_C1DATAS |
1355 CLRW_CLR_C1MODE,
1356 CLRW, 0, 4, IMMED);
1357
1358 KEY(p, KEY1, authdata->key_enc_flags, authdata->key,
1359 authdata->keylen, INLINE_KEY(authdata));
1360
1361 SEQINPTR(p, 0, 0, SOP);
1362
1363 ALG_OPERATION(p, OP_ALG_ALGSEL_AES,
1364 OP_ALG_AAI_CMAC,
1365 OP_ALG_AS_INITFINAL,
1366 ICV_CHECK_ENABLE,
1367 DIR_DEC);
1368
1369 MATHB(p, SEQINSZ, SUB, ZERO, VSEQINSZ, 4, 0);
1370
1371 MOVE(p, CONTEXT2, 0, IFIFOAB1, 0, 8, IMMED);
1372
1373 SEQFIFOLOAD(p, MSG1, 0, VLF | LAST1 | FLUSH1);
1374
1375 LOAD(p, NFIFOENTRY_STYPE_ALTSOURCE |
1376 NFIFOENTRY_DEST_CLASS1 |
1377 NFIFOENTRY_DTYPE_ICV |
1378 NFIFOENTRY_LC1 |
1379 NFIFOENTRY_FC1 | 4, NFIFO_SZL, 0, 4, IMMED);
1380 MOVEB(p, MATH3, 0, ALTSOURCE, 0, 4, IMMED);
1381 }
1382
1383 return 0;
1384 }
1385
1386 static inline int
pdcp_insert_cplane_acc_op(struct program * p,bool swap __maybe_unused,struct alginfo * cipherdata,struct alginfo * authdata,unsigned int dir,enum pdcp_sn_size sn_size,unsigned char era_2_hfn_ovrd __maybe_unused)1387 pdcp_insert_cplane_acc_op(struct program *p,
1388 bool swap __maybe_unused,
1389 struct alginfo *cipherdata,
1390 struct alginfo *authdata,
1391 unsigned int dir,
1392 enum pdcp_sn_size sn_size,
1393 unsigned char era_2_hfn_ovrd __maybe_unused)
1394 {
1395 /* Insert Auth Key */
1396 KEY(p, KEY2, authdata->key_enc_flags, authdata->key, authdata->keylen,
1397 INLINE_KEY(authdata));
1398
1399 /* Insert Cipher Key */
1400 KEY(p, KEY1, cipherdata->key_enc_flags, cipherdata->key,
1401 cipherdata->keylen, INLINE_KEY(cipherdata));
1402
1403 if (sn_size == PDCP_SN_SIZE_5)
1404 PROTOCOL(p, dir, OP_PCLID_LTE_PDCP_CTRL,
1405 (uint16_t)cipherdata->algtype);
1406 else
1407 PROTOCOL(p, dir, OP_PCLID_LTE_PDCP_USER_RN,
1408 ((uint16_t)cipherdata->algtype << 8) |
1409 (uint16_t)authdata->algtype);
1410
1411 return 0;
1412 }
1413
1414 static inline int
pdcp_insert_cplane_snow_aes_op(struct program * p,bool swap __maybe_unused,struct alginfo * cipherdata,struct alginfo * authdata,unsigned int dir,enum pdcp_sn_size sn_size,unsigned char era_2_sw_hfn_ovrd)1415 pdcp_insert_cplane_snow_aes_op(struct program *p,
1416 bool swap __maybe_unused,
1417 struct alginfo *cipherdata,
1418 struct alginfo *authdata,
1419 unsigned int dir,
1420 enum pdcp_sn_size sn_size,
1421 unsigned char era_2_sw_hfn_ovrd)
1422 {
1423 uint32_t offset = 0, length = 0, sn_mask = 0;
1424
1425 LABEL(back_to_sd_offset);
1426 LABEL(end_desc);
1427 LABEL(local_offset);
1428 LABEL(jump_to_beginning);
1429 LABEL(fifo_load_mac_i_offset);
1430 REFERENCE(seqin_ptr_read);
1431 REFERENCE(seqin_ptr_write);
1432 REFERENCE(seq_out_read);
1433 REFERENCE(jump_back_to_sd_cmd);
1434 REFERENCE(move_mac_i_to_desc_buf);
1435
1436 if ((rta_sec_era >= RTA_SEC_ERA_8 && sn_size != PDCP_SN_SIZE_18) ||
1437 (rta_sec_era == RTA_SEC_ERA_10)) {
1438 KEY(p, KEY1, cipherdata->key_enc_flags, cipherdata->key,
1439 cipherdata->keylen, INLINE_KEY(cipherdata));
1440 KEY(p, KEY2, authdata->key_enc_flags, authdata->key,
1441 authdata->keylen, INLINE_KEY(authdata));
1442
1443 if (sn_size == PDCP_SN_SIZE_5)
1444 PROTOCOL(p, dir, OP_PCLID_LTE_PDCP_CTRL_MIXED,
1445 ((uint16_t)cipherdata->algtype << 8) |
1446 (uint16_t)authdata->algtype);
1447 else
1448 PROTOCOL(p, dir, OP_PCLID_LTE_PDCP_USER_RN,
1449 ((uint16_t)cipherdata->algtype << 8) |
1450 (uint16_t)authdata->algtype);
1451
1452 return 0;
1453 }
1454 /* Non-proto is supported only for 5bit cplane and 18bit uplane */
1455 switch (sn_size) {
1456 case PDCP_SN_SIZE_5:
1457 offset = 7;
1458 length = 1;
1459 sn_mask = (swap == false) ? PDCP_C_PLANE_SN_MASK :
1460 PDCP_C_PLANE_SN_MASK_BE;
1461 break;
1462 case PDCP_SN_SIZE_18:
1463 offset = 5;
1464 length = 3;
1465 sn_mask = (swap == false) ? PDCP_U_PLANE_18BIT_SN_MASK :
1466 PDCP_U_PLANE_18BIT_SN_MASK_BE;
1467 break;
1468 case PDCP_SN_SIZE_7:
1469 case PDCP_SN_SIZE_12:
1470 case PDCP_SN_SIZE_15:
1471 pr_err("Invalid sn_size for %s\n", __func__);
1472 return -ENOTSUP;
1473
1474 }
1475
1476 SEQLOAD(p, MATH0, offset, length, 0);
1477 JUMP(p, 1, LOCAL_JUMP, ALL_TRUE, CALM);
1478 MATHB(p, MATH0, AND, sn_mask, MATH1, 8, IFB | IMMED2);
1479 MATHB(p, MATH1, SHLD, MATH1, MATH1, 8, 0);
1480 MOVEB(p, DESCBUF, 4, MATH2, 0, 0x08, WAITCOMP | IMMED);
1481 MATHB(p, MATH1, OR, MATH2, MATH2, 8, 0);
1482 SEQSTORE(p, MATH0, offset, length, 0);
1483 if (dir == OP_TYPE_ENCAP_PROTOCOL) {
1484 if (rta_sec_era > RTA_SEC_ERA_2 ||
1485 (rta_sec_era == RTA_SEC_ERA_2 &&
1486 era_2_sw_hfn_ovrd == 0)) {
1487 SEQINPTR(p, 0, length, RTO);
1488 } else {
1489 SEQINPTR(p, 0, 5, RTO);
1490 SEQFIFOLOAD(p, SKIP, 4, 0);
1491 }
1492 KEY(p, KEY1, authdata->key_enc_flags, authdata->key,
1493 authdata->keylen, INLINE_KEY(authdata));
1494 MOVEB(p, MATH2, 0, IFIFOAB1, 0, 0x08, IMMED);
1495
1496 if (rta_sec_era > RTA_SEC_ERA_2) {
1497 MATHB(p, SEQINSZ, SUB, ZERO, VSEQINSZ, 4, 0);
1498 MATHB(p, SEQINSZ, SUB, ZERO, MATH1, 4, 0);
1499 MATHB(p, VSEQINSZ, ADD, PDCP_MAC_I_LEN - 1, VSEQOUTSZ,
1500 4, IMMED2);
1501 } else {
1502 MATHB(p, SEQINSZ, SUB, MATH3, VSEQINSZ, 4, 0);
1503 MATHB(p, VSEQINSZ, ADD, PDCP_MAC_I_LEN - 1, VSEQOUTSZ,
1504 4, IMMED2);
1505 /*
1506 * Note: Although the calculations below might seem a
1507 * little off, the logic is the following:
1508 *
1509 * - SEQ IN PTR RTO below needs the full length of the
1510 * frame; in case of P4080_REV_2_HFN_OV_WORKAROUND,
1511 * this means the length of the frame to be processed
1512 * + 4 bytes (the HFN override flag and value).
1513 * The length of the frame to be processed minus 1
1514 * byte is in the VSIL register (because
1515 * VSIL = SIL + 3, due to 1 byte, the header being
1516 * already written by the SEQ STORE above). So for
1517 * calculating the length to use in RTO, I add one
1518 * to the VSIL value in order to obtain the total
1519 * frame length. This helps in case of P4080 which
1520 * can have the value 0 as an operand in a MATH
1521 * command only as SRC1 When the HFN override
1522 * workaround is not enabled, the length of the
1523 * frame is given by the SIL register; the
1524 * calculation is similar to the one in the SEC 4.2
1525 * and SEC 5.3 cases.
1526 */
1527 if (era_2_sw_hfn_ovrd)
1528 MATHB(p, VSEQOUTSZ, ADD, ONE, MATH1, 4,
1529 0);
1530 else
1531 MATHB(p, SEQINSZ, ADD, MATH3, MATH1, 4,
1532 0);
1533 }
1534 /*
1535 * Placeholder for filling the length in
1536 * SEQIN PTR RTO below
1537 */
1538 seqin_ptr_read = MOVE(p, DESCBUF, 0, MATH1, 0, 6, IMMED);
1539 seqin_ptr_write = MOVE(p, MATH1, 0, DESCBUF, 0, 8,
1540 WAITCOMP | IMMED);
1541 ALG_OPERATION(p, OP_ALG_ALGSEL_AES,
1542 OP_ALG_AAI_CMAC,
1543 OP_ALG_AS_INITFINAL,
1544 ICV_CHECK_DISABLE,
1545 DIR_DEC);
1546 SEQFIFOLOAD(p, MSG1, 0, VLF | LAST1 | FLUSH1);
1547 MOVEB(p, CONTEXT1, 0, MATH3, 0, 4, WAITCOMP | IMMED);
1548 if (rta_sec_era <= RTA_SEC_ERA_3)
1549 LOAD(p, CLRW_CLR_C1KEY |
1550 CLRW_CLR_C1CTX |
1551 CLRW_CLR_C1ICV |
1552 CLRW_CLR_C1DATAS |
1553 CLRW_CLR_C1MODE,
1554 CLRW, 0, 4, IMMED);
1555 else
1556 LOAD(p, CLRW_RESET_CLS1_CHA |
1557 CLRW_CLR_C1KEY |
1558 CLRW_CLR_C1CTX |
1559 CLRW_CLR_C1ICV |
1560 CLRW_CLR_C1DATAS |
1561 CLRW_CLR_C1MODE,
1562 CLRW, 0, 4, IMMED);
1563
1564 if (rta_sec_era <= RTA_SEC_ERA_3)
1565 LOAD(p, CCTRL_RESET_CHA_ALL, CCTRL, 0, 4, IMMED);
1566
1567 KEY(p, KEY1, cipherdata->key_enc_flags, cipherdata->key,
1568 cipherdata->keylen, INLINE_KEY(cipherdata));
1569 SET_LABEL(p, local_offset);
1570 MOVEB(p, MATH2, 0, CONTEXT1, 0, 8, IMMED);
1571 SEQINPTR(p, 0, 0, RTO);
1572
1573 if (rta_sec_era == RTA_SEC_ERA_2 && era_2_sw_hfn_ovrd) {
1574 SEQFIFOLOAD(p, SKIP, 5, 0);
1575 MATHB(p, SEQINSZ, ADD, ONE, SEQINSZ, 4, 0);
1576 }
1577
1578 MATHB(p, SEQINSZ, SUB, length, VSEQINSZ, 4, IMMED2);
1579 ALG_OPERATION(p, OP_ALG_ALGSEL_SNOW_F8,
1580 OP_ALG_AAI_F8,
1581 OP_ALG_AS_INITFINAL,
1582 ICV_CHECK_DISABLE,
1583 DIR_ENC);
1584 SEQFIFOSTORE(p, MSG, 0, 0, VLF);
1585
1586 if (rta_sec_era > RTA_SEC_ERA_2 ||
1587 (rta_sec_era == RTA_SEC_ERA_2 &&
1588 era_2_sw_hfn_ovrd == 0))
1589 SEQFIFOLOAD(p, SKIP, length, 0);
1590
1591 SEQFIFOLOAD(p, MSG1, 0, VLF);
1592 MOVEB(p, MATH3, 0, IFIFOAB1, 0, 4, LAST1 | FLUSH1 | IMMED);
1593 PATCH_MOVE(p, seqin_ptr_read, local_offset);
1594 PATCH_MOVE(p, seqin_ptr_write, local_offset);
1595 } else {
1596 MOVEB(p, MATH2, 0, CONTEXT1, 0, 8, IMMED);
1597
1598 if (rta_sec_era >= RTA_SEC_ERA_5)
1599 MOVE(p, CONTEXT1, 0, CONTEXT2, 0, 8, IMMED);
1600
1601 if (rta_sec_era > RTA_SEC_ERA_2)
1602 MATHB(p, SEQINSZ, SUB, ZERO, VSEQINSZ, 4, 0);
1603 else
1604 MATHB(p, SEQINSZ, SUB, MATH3, VSEQINSZ, 4, 0);
1605
1606 MATHI(p, SEQINSZ, SUB, PDCP_MAC_I_LEN, VSEQOUTSZ, 4, IMMED2);
1607 /*
1608 * TODO: To be changed when proper support is added in RTA (can't load a
1609 * command that is also written by RTA (or patch it for that matter).
1610 * Change when proper RTA support is added.
1611 */
1612 if (p->ps)
1613 WORD(p, 0x168B0004);
1614 else
1615 WORD(p, 0x16880404);
1616
1617 jump_back_to_sd_cmd = JUMP(p, 0, LOCAL_JUMP, ALL_TRUE, 0);
1618 /*
1619 * Placeholder for command reading the SEQ OUT command in
1620 * JD. Done for rereading the decrypted data and performing
1621 * the integrity check
1622 */
1623 /*
1624 * TODO: RTA currently doesn't support patching of length of a MOVE command
1625 * Thus, it is inserted as a raw word, as per PS setting.
1626 */
1627 if (p->ps)
1628 seq_out_read = MOVE(p, DESCBUF, 0, MATH1, 0, 20,
1629 WAITCOMP | IMMED);
1630 else
1631 seq_out_read = MOVE(p, DESCBUF, 0, MATH1, 0, 16,
1632 WAITCOMP | IMMED);
1633
1634 MATHB(p, MATH1, XOR, CMD_SEQ_IN_PTR ^ CMD_SEQ_OUT_PTR, MATH1, 4,
1635 IMMED2);
1636 /* Placeholder for overwriting the SEQ IN with SEQ OUT */
1637 /*
1638 * TODO: RTA currently doesn't support patching of length of a MOVE command
1639 * Thus, it is inserted as a raw word, as per PS setting.
1640 */
1641 if (p->ps)
1642 MOVE(p, MATH1, 0, DESCBUF, 0, 24, IMMED);
1643 else
1644 MOVE(p, MATH1, 0, DESCBUF, 0, 20, IMMED);
1645
1646 KEY(p, KEY1, cipherdata->key_enc_flags, cipherdata->key,
1647 cipherdata->keylen, INLINE_KEY(cipherdata));
1648
1649 if (rta_sec_era >= RTA_SEC_ERA_4)
1650 MOVE(p, CONTEXT1, 0, CONTEXT2, 0, 8, IMMED);
1651 else
1652 MOVE(p, CONTEXT1, 0, MATH3, 0, 8, IMMED);
1653
1654 ALG_OPERATION(p, OP_ALG_ALGSEL_SNOW_F8,
1655 OP_ALG_AAI_F8,
1656 OP_ALG_AS_INITFINAL,
1657 ICV_CHECK_DISABLE,
1658 DIR_DEC);
1659 SEQFIFOSTORE(p, MSG, 0, 0, VLF | CONT);
1660 SEQFIFOLOAD(p, MSG1, 0, VLF | LAST1 | FLUSH1);
1661
1662 if (rta_sec_era <= RTA_SEC_ERA_3)
1663 move_mac_i_to_desc_buf = MOVE(p, OFIFO, 0, DESCBUF, 0,
1664 4, WAITCOMP | IMMED);
1665 else
1666 MOVE(p, OFIFO, 0, MATH3, 0, 4, IMMED);
1667
1668 if (rta_sec_era <= RTA_SEC_ERA_3)
1669 LOAD(p, CCTRL_RESET_CHA_ALL, CCTRL, 0, 4, IMMED);
1670 else
1671 LOAD(p, CLRW_RESET_CLS1_CHA |
1672 CLRW_CLR_C1KEY |
1673 CLRW_CLR_C1CTX |
1674 CLRW_CLR_C1ICV |
1675 CLRW_CLR_C1DATAS |
1676 CLRW_CLR_C1MODE,
1677 CLRW, 0, 4, IMMED);
1678
1679 KEY(p, KEY1, authdata->key_enc_flags, authdata->key,
1680 authdata->keylen, INLINE_KEY(authdata));
1681 /*
1682 * Placeholder for jump in SD for executing the new SEQ IN PTR
1683 * command (which is actually the old SEQ OUT PTR command
1684 * copied over from JD.
1685 */
1686 SET_LABEL(p, jump_to_beginning);
1687 JUMP(p, 1 - jump_to_beginning, LOCAL_JUMP, ALL_TRUE, 0);
1688 SET_LABEL(p, back_to_sd_offset);
1689 ALG_OPERATION(p, OP_ALG_ALGSEL_AES,
1690 OP_ALG_AAI_CMAC,
1691 OP_ALG_AS_INITFINAL,
1692 ICV_CHECK_ENABLE,
1693 DIR_DEC);
1694
1695 /* Read the # of bytes written in the output buffer + 1 (HDR) */
1696 MATHI(p, VSEQOUTSZ, ADD, length, VSEQINSZ, 4, IMMED2);
1697
1698 if (rta_sec_era <= RTA_SEC_ERA_3)
1699 MOVE(p, MATH3, 0, IFIFOAB1, 0, 8, IMMED);
1700 else
1701 MOVE(p, CONTEXT2, 0, IFIFOAB1, 0, 8, IMMED);
1702
1703 if (rta_sec_era == RTA_SEC_ERA_2 && era_2_sw_hfn_ovrd)
1704 SEQFIFOLOAD(p, SKIP, 4, 0);
1705
1706 SEQFIFOLOAD(p, MSG1, 0, VLF | LAST1 | FLUSH1);
1707
1708 if (rta_sec_era >= RTA_SEC_ERA_4) {
1709 LOAD(p, NFIFOENTRY_STYPE_ALTSOURCE |
1710 NFIFOENTRY_DEST_CLASS1 |
1711 NFIFOENTRY_DTYPE_ICV |
1712 NFIFOENTRY_LC1 |
1713 NFIFOENTRY_FC1 | 4, NFIFO_SZL, 0, 4, IMMED);
1714 MOVE(p, MATH3, 0, ALTSOURCE, 0, 4, IMMED);
1715 } else {
1716 SET_LABEL(p, fifo_load_mac_i_offset);
1717 FIFOLOAD(p, ICV1, fifo_load_mac_i_offset, 4,
1718 LAST1 | FLUSH1 | IMMED);
1719 }
1720
1721 SET_LABEL(p, end_desc);
1722
1723 if (!p->ps) {
1724 PATCH_MOVE(p, seq_out_read, end_desc + 1);
1725 PATCH_JUMP(p, jump_back_to_sd_cmd,
1726 back_to_sd_offset + jump_back_to_sd_cmd - 5);
1727
1728 if (rta_sec_era <= RTA_SEC_ERA_3)
1729 PATCH_MOVE(p, move_mac_i_to_desc_buf,
1730 fifo_load_mac_i_offset + 1);
1731 } else {
1732 PATCH_MOVE(p, seq_out_read, end_desc + 2);
1733 PATCH_JUMP(p, jump_back_to_sd_cmd,
1734 back_to_sd_offset + jump_back_to_sd_cmd - 5);
1735
1736 if (rta_sec_era <= RTA_SEC_ERA_3)
1737 PATCH_MOVE(p, move_mac_i_to_desc_buf,
1738 fifo_load_mac_i_offset + 1);
1739 }
1740 }
1741
1742 return 0;
1743 }
1744
1745 static inline int
pdcp_insert_cplane_aes_snow_op(struct program * p,bool swap __maybe_unused,struct alginfo * cipherdata,struct alginfo * authdata,unsigned int dir,enum pdcp_sn_size sn_size,unsigned char era_2_sw_hfn_ovrd __maybe_unused)1746 pdcp_insert_cplane_aes_snow_op(struct program *p,
1747 bool swap __maybe_unused,
1748 struct alginfo *cipherdata,
1749 struct alginfo *authdata,
1750 unsigned int dir,
1751 enum pdcp_sn_size sn_size,
1752 unsigned char era_2_sw_hfn_ovrd __maybe_unused)
1753 {
1754 uint32_t offset = 0, length = 0, sn_mask = 0;
1755
1756 KEY(p, KEY1, cipherdata->key_enc_flags, cipherdata->key,
1757 cipherdata->keylen, INLINE_KEY(cipherdata));
1758 KEY(p, KEY2, authdata->key_enc_flags, authdata->key, authdata->keylen,
1759 INLINE_KEY(authdata));
1760
1761 if ((rta_sec_era >= RTA_SEC_ERA_8 && sn_size != PDCP_SN_SIZE_18) ||
1762 (rta_sec_era == RTA_SEC_ERA_10)) {
1763 int pclid;
1764
1765 if (sn_size == PDCP_SN_SIZE_5)
1766 pclid = OP_PCLID_LTE_PDCP_CTRL_MIXED;
1767 else
1768 pclid = OP_PCLID_LTE_PDCP_USER_RN;
1769
1770 PROTOCOL(p, dir, pclid,
1771 ((uint16_t)cipherdata->algtype << 8) |
1772 (uint16_t)authdata->algtype);
1773
1774 return 0;
1775 }
1776 /* Non-proto is supported only for 5bit cplane and 18bit uplane */
1777 switch (sn_size) {
1778 case PDCP_SN_SIZE_5:
1779 offset = 7;
1780 length = 1;
1781 sn_mask = (swap == false) ? PDCP_C_PLANE_SN_MASK :
1782 PDCP_C_PLANE_SN_MASK_BE;
1783 break;
1784 case PDCP_SN_SIZE_18:
1785 offset = 5;
1786 length = 3;
1787 sn_mask = (swap == false) ? PDCP_U_PLANE_18BIT_SN_MASK :
1788 PDCP_U_PLANE_18BIT_SN_MASK_BE;
1789 break;
1790 case PDCP_SN_SIZE_7:
1791 case PDCP_SN_SIZE_12:
1792 case PDCP_SN_SIZE_15:
1793 pr_err("Invalid sn_size for %s\n", __func__);
1794 return -ENOTSUP;
1795
1796 }
1797
1798 if (dir == OP_TYPE_ENCAP_PROTOCOL)
1799 MATHB(p, SEQINSZ, SUB, length, VSEQINSZ, 4, IMMED2);
1800
1801 SEQLOAD(p, MATH0, offset, length, 0);
1802 JUMP(p, 1, LOCAL_JUMP, ALL_TRUE, CALM);
1803 MOVEB(p, MATH0, offset, IFIFOAB2, 0, length, IMMED);
1804 MATHB(p, MATH0, AND, sn_mask, MATH1, 8, IFB | IMMED2);
1805
1806 SEQSTORE(p, MATH0, offset, length, 0);
1807 MATHB(p, MATH1, SHLD, MATH1, MATH1, 8, 0);
1808 MOVEB(p, DESCBUF, 4, MATH2, 0, 8, WAITCOMP | IMMED);
1809 MATHB(p, MATH1, OR, MATH2, MATH1, 8, 0);
1810 MOVEB(p, MATH1, 0, CONTEXT1, 16, 8, IMMED);
1811 MOVEB(p, MATH1, 0, CONTEXT2, 0, 4, IMMED);
1812 if (swap == false) {
1813 MATHB(p, MATH1, AND, upper_32_bits(PDCP_BEARER_MASK), MATH2, 4,
1814 IMMED2);
1815 MATHB(p, MATH1, AND, lower_32_bits(PDCP_DIR_MASK), MATH3, 4,
1816 IMMED2);
1817 } else {
1818 MATHB(p, MATH1, AND, lower_32_bits(PDCP_BEARER_MASK_BE), MATH2,
1819 4, IMMED2);
1820 MATHB(p, MATH1, AND, upper_32_bits(PDCP_DIR_MASK_BE), MATH3,
1821 4, IMMED2);
1822 }
1823 MATHB(p, MATH3, SHLD, MATH3, MATH3, 8, 0);
1824 MOVEB(p, MATH2, 4, OFIFO, 0, 12, IMMED);
1825 MOVE(p, OFIFO, 0, CONTEXT2, 4, 12, IMMED);
1826 if (dir == OP_TYPE_ENCAP_PROTOCOL) {
1827 MATHB(p, SEQINSZ, ADD, PDCP_MAC_I_LEN, VSEQOUTSZ, 4, IMMED2);
1828 } else {
1829 MATHB(p, SEQINSZ, SUB, PDCP_MAC_I_LEN, MATH1, 4, IMMED2);
1830
1831 MATHB(p, ZERO, ADD, MATH1, VSEQOUTSZ, 4, 0);
1832 MATHB(p, ZERO, ADD, MATH1, VSEQINSZ, 4, 0);
1833 }
1834
1835 if (dir == OP_TYPE_ENCAP_PROTOCOL)
1836 SEQFIFOSTORE(p, MSG, 0, 0, VLF);
1837 else
1838 SEQFIFOSTORE(p, MSG, 0, 0, VLF | CONT);
1839
1840 ALG_OPERATION(p, OP_ALG_ALGSEL_SNOW_F9,
1841 OP_ALG_AAI_F9,
1842 OP_ALG_AS_INITFINAL,
1843 dir == OP_TYPE_ENCAP_PROTOCOL ?
1844 ICV_CHECK_DISABLE : ICV_CHECK_ENABLE,
1845 DIR_DEC);
1846 ALG_OPERATION(p, OP_ALG_ALGSEL_AES,
1847 OP_ALG_AAI_CTR,
1848 OP_ALG_AS_INITFINAL,
1849 ICV_CHECK_DISABLE,
1850 dir == OP_TYPE_ENCAP_PROTOCOL ? DIR_ENC : DIR_DEC);
1851
1852 if (dir == OP_TYPE_ENCAP_PROTOCOL) {
1853 SEQFIFOLOAD(p, MSGINSNOOP, 0, VLF | LAST2);
1854 MOVE(p, CONTEXT2, 0, IFIFOAB1, 0, 4, LAST1 | FLUSH1 | IMMED);
1855 } else {
1856 SEQFIFOLOAD(p, MSGOUTSNOOP, 0, VLF | LAST2);
1857 SEQFIFOLOAD(p, MSG1, 4, LAST1 | FLUSH1);
1858 JUMP(p, 1, LOCAL_JUMP, ALL_TRUE, CLASS1 | NOP | NIFP);
1859
1860 if (rta_sec_era >= RTA_SEC_ERA_6)
1861 LOAD(p, 0, DCTRL, 0, LDLEN_RST_CHA_OFIFO_PTR, IMMED);
1862
1863 MOVE(p, OFIFO, 0, MATH0, 0, 4, WAITCOMP | IMMED);
1864
1865 NFIFOADD(p, IFIFO, ICV2, 4, LAST2);
1866
1867 if (rta_sec_era <= RTA_SEC_ERA_2) {
1868 /* Shut off automatic Info FIFO entries */
1869 LOAD(p, 0, DCTRL, LDOFF_DISABLE_AUTO_NFIFO, 0, IMMED);
1870 MOVE(p, MATH0, 0, IFIFOAB2, 0, 4, WAITCOMP | IMMED);
1871 } else {
1872 MOVE(p, MATH0, 0, IFIFO, 0, 4, WAITCOMP | IMMED);
1873 }
1874 }
1875
1876 return 0;
1877 }
1878
1879 static inline int
pdcp_insert_cplane_snow_zuc_op(struct program * p,bool swap __maybe_unused,struct alginfo * cipherdata,struct alginfo * authdata,unsigned int dir,enum pdcp_sn_size sn_size,unsigned char era_2_sw_hfn_ovrd __maybe_unused)1880 pdcp_insert_cplane_snow_zuc_op(struct program *p,
1881 bool swap __maybe_unused,
1882 struct alginfo *cipherdata,
1883 struct alginfo *authdata,
1884 unsigned int dir,
1885 enum pdcp_sn_size sn_size,
1886 unsigned char era_2_sw_hfn_ovrd __maybe_unused)
1887 {
1888 uint32_t offset = 0, length = 0, sn_mask = 0;
1889
1890 LABEL(keyjump);
1891 REFERENCE(pkeyjump);
1892
1893 if (rta_sec_era < RTA_SEC_ERA_5) {
1894 pr_err("Invalid era for selected algorithm\n");
1895 return -ENOTSUP;
1896 }
1897
1898 if ((rta_sec_era >= RTA_SEC_ERA_8 && sn_size != PDCP_SN_SIZE_18) ||
1899 (rta_sec_era == RTA_SEC_ERA_10)) {
1900 int pclid;
1901 KEY(p, KEY1, cipherdata->key_enc_flags, cipherdata->key,
1902 cipherdata->keylen, INLINE_KEY(cipherdata));
1903 KEY(p, KEY2, authdata->key_enc_flags, authdata->key, authdata->keylen,
1904 INLINE_KEY(authdata));
1905
1906 if (sn_size == PDCP_SN_SIZE_5)
1907 pclid = OP_PCLID_LTE_PDCP_CTRL_MIXED;
1908 else
1909 pclid = OP_PCLID_LTE_PDCP_USER_RN;
1910
1911 PROTOCOL(p, dir, pclid,
1912 ((uint16_t)cipherdata->algtype << 8) |
1913 (uint16_t)authdata->algtype);
1914 return 0;
1915 }
1916 /* Non-proto is supported only for 5bit cplane and 18bit uplane */
1917 switch (sn_size) {
1918 case PDCP_SN_SIZE_5:
1919 offset = 7;
1920 length = 1;
1921 sn_mask = (swap == false) ? PDCP_C_PLANE_SN_MASK :
1922 PDCP_C_PLANE_SN_MASK_BE;
1923 break;
1924 case PDCP_SN_SIZE_18:
1925 offset = 5;
1926 length = 3;
1927 sn_mask = (swap == false) ? PDCP_U_PLANE_18BIT_SN_MASK :
1928 PDCP_U_PLANE_18BIT_SN_MASK_BE;
1929 break;
1930 case PDCP_SN_SIZE_7:
1931 case PDCP_SN_SIZE_12:
1932 case PDCP_SN_SIZE_15:
1933 pr_err("Invalid sn_size for %s\n", __func__);
1934 return -ENOTSUP;
1935
1936 }
1937
1938 pkeyjump = JUMP(p, keyjump, LOCAL_JUMP, ALL_TRUE, SHRD | SELF | BOTH);
1939 KEY(p, KEY1, cipherdata->key_enc_flags, cipherdata->key,
1940 cipherdata->keylen, INLINE_KEY(cipherdata));
1941 KEY(p, KEY2, authdata->key_enc_flags, authdata->key, authdata->keylen,
1942 INLINE_KEY(authdata));
1943
1944 SET_LABEL(p, keyjump);
1945 SEQLOAD(p, MATH0, offset, length, 0);
1946 JUMP(p, 1, LOCAL_JUMP, ALL_TRUE, CALM);
1947 MOVEB(p, MATH0, offset, IFIFOAB2, 0, length, IMMED);
1948 MATHB(p, MATH0, AND, sn_mask, MATH1, 8, IFB | IMMED2);
1949
1950 MATHB(p, MATH1, SHLD, MATH1, MATH1, 8, 0);
1951 MOVEB(p, DESCBUF, 4, MATH2, 0, 8, WAITCOMP | IMMED);
1952 MATHB(p, MATH1, OR, MATH2, MATH2, 8, 0);
1953 MOVEB(p, MATH2, 0, CONTEXT1, 0, 8, IMMED);
1954 MOVEB(p, MATH2, 0, CONTEXT2, 0, 8, WAITCOMP | IMMED);
1955
1956 if (dir == OP_TYPE_ENCAP_PROTOCOL)
1957 MATHB(p, SEQINSZ, ADD, PDCP_MAC_I_LEN, VSEQOUTSZ, 4, IMMED2);
1958 else
1959 MATHB(p, SEQINSZ, SUB, PDCP_MAC_I_LEN, VSEQOUTSZ, 4, IMMED2);
1960
1961 MATHB(p, SEQINSZ, SUB, ZERO, VSEQINSZ, 4, 0);
1962 SEQSTORE(p, MATH0, offset, length, 0);
1963
1964 if (dir == OP_TYPE_ENCAP_PROTOCOL) {
1965 SEQFIFOSTORE(p, MSG, 0, 0, VLF);
1966 SEQFIFOLOAD(p, MSGINSNOOP, 0, VLF | LAST2);
1967 } else {
1968 SEQFIFOSTORE(p, MSG, 0, 0, VLF | CONT);
1969 SEQFIFOLOAD(p, MSGOUTSNOOP, 0, VLF | LAST1 | FLUSH1);
1970 }
1971
1972 ALG_OPERATION(p, OP_ALG_ALGSEL_ZUCA,
1973 OP_ALG_AAI_F9,
1974 OP_ALG_AS_INITFINAL,
1975 dir == OP_TYPE_ENCAP_PROTOCOL ?
1976 ICV_CHECK_DISABLE : ICV_CHECK_ENABLE,
1977 DIR_ENC);
1978
1979 ALG_OPERATION(p, OP_ALG_ALGSEL_SNOW_F8,
1980 OP_ALG_AAI_F8,
1981 OP_ALG_AS_INITFINAL,
1982 ICV_CHECK_DISABLE,
1983 dir == OP_TYPE_ENCAP_PROTOCOL ? DIR_ENC : DIR_DEC);
1984 if (dir == OP_TYPE_ENCAP_PROTOCOL) {
1985 MOVE(p, CONTEXT2, 0, IFIFOAB1, 0, 4, LAST1 | FLUSH1 | IMMED);
1986 } else {
1987 /* Save ICV */
1988 MOVE(p, OFIFO, 0, MATH0, 0, 4, IMMED);
1989 LOAD(p, NFIFOENTRY_STYPE_ALTSOURCE |
1990 NFIFOENTRY_DEST_CLASS2 |
1991 NFIFOENTRY_DTYPE_ICV |
1992 NFIFOENTRY_LC2 | 4, NFIFO_SZL, 0, 4, IMMED);
1993 MOVE(p, MATH0, 0, ALTSOURCE, 0, 4, WAITCOMP | IMMED);
1994 }
1995
1996 /* Reset ZUCA mode and done interrupt */
1997 LOAD(p, CLRW_CLR_C2MODE, CLRW, 0, 4, IMMED);
1998 LOAD(p, CIRQ_ZADI, ICTRL, 0, 4, IMMED);
1999
2000 PATCH_JUMP(p, pkeyjump, keyjump);
2001 return 0;
2002 }
2003
2004 static inline int
pdcp_insert_cplane_aes_zuc_op(struct program * p,bool swap __maybe_unused,struct alginfo * cipherdata,struct alginfo * authdata,unsigned int dir,enum pdcp_sn_size sn_size,unsigned char era_2_sw_hfn_ovrd __maybe_unused)2005 pdcp_insert_cplane_aes_zuc_op(struct program *p,
2006 bool swap __maybe_unused,
2007 struct alginfo *cipherdata,
2008 struct alginfo *authdata,
2009 unsigned int dir,
2010 enum pdcp_sn_size sn_size,
2011 unsigned char era_2_sw_hfn_ovrd __maybe_unused)
2012 {
2013 uint32_t offset = 0, length = 0, sn_mask = 0;
2014 LABEL(keyjump);
2015 REFERENCE(pkeyjump);
2016
2017 if (rta_sec_era < RTA_SEC_ERA_5) {
2018 pr_err("Invalid era for selected algorithm\n");
2019 return -ENOTSUP;
2020 }
2021
2022 if ((rta_sec_era >= RTA_SEC_ERA_8 && sn_size != PDCP_SN_SIZE_18) ||
2023 (rta_sec_era == RTA_SEC_ERA_10)) {
2024 int pclid;
2025 KEY(p, KEY1, cipherdata->key_enc_flags, cipherdata->key,
2026 cipherdata->keylen, INLINE_KEY(cipherdata));
2027 KEY(p, KEY2, authdata->key_enc_flags, authdata->key, authdata->keylen,
2028 INLINE_KEY(authdata));
2029
2030 if (sn_size == PDCP_SN_SIZE_5)
2031 pclid = OP_PCLID_LTE_PDCP_CTRL_MIXED;
2032 else
2033 pclid = OP_PCLID_LTE_PDCP_USER_RN;
2034
2035 PROTOCOL(p, dir, pclid,
2036 ((uint16_t)cipherdata->algtype << 8) |
2037 (uint16_t)authdata->algtype);
2038
2039 return 0;
2040 }
2041 /* Non-proto is supported only for 5bit cplane and 18bit uplane */
2042 switch (sn_size) {
2043 case PDCP_SN_SIZE_5:
2044 offset = 7;
2045 length = 1;
2046 sn_mask = (swap == false) ? PDCP_C_PLANE_SN_MASK :
2047 PDCP_C_PLANE_SN_MASK_BE;
2048 break;
2049 case PDCP_SN_SIZE_18:
2050 offset = 5;
2051 length = 3;
2052 sn_mask = (swap == false) ? PDCP_U_PLANE_18BIT_SN_MASK :
2053 PDCP_U_PLANE_18BIT_SN_MASK_BE;
2054 break;
2055 case PDCP_SN_SIZE_7:
2056 case PDCP_SN_SIZE_12:
2057 case PDCP_SN_SIZE_15:
2058 pr_err("Invalid sn_size for %s\n", __func__);
2059 return -ENOTSUP;
2060
2061 }
2062 pkeyjump = JUMP(p, keyjump, LOCAL_JUMP, ALL_TRUE, SHRD | SELF | BOTH);
2063 KEY(p, KEY1, cipherdata->key_enc_flags, cipherdata->key,
2064 cipherdata->keylen, INLINE_KEY(cipherdata));
2065 KEY(p, KEY2, authdata->key_enc_flags, authdata->key, authdata->keylen,
2066 INLINE_KEY(authdata));
2067
2068 SET_LABEL(p, keyjump);
2069
2070 SEQLOAD(p, MATH0, offset, length, 0);
2071 JUMP(p, 1, LOCAL_JUMP, ALL_TRUE, CALM);
2072 MOVEB(p, MATH0, offset, IFIFOAB2, 0, length, IMMED);
2073 MATHB(p, MATH0, AND, sn_mask, MATH1, 8, IFB | IMMED2);
2074
2075 MATHB(p, MATH1, SHLD, MATH1, MATH1, 8, 0);
2076 MOVEB(p, DESCBUF, 4, MATH2, 0, 8, WAITCOMP | IMMED);
2077 MATHB(p, MATH1, OR, MATH2, MATH2, 8, 0);
2078 MOVEB(p, MATH2, 0, CONTEXT1, 16, 8, IMMED);
2079 MOVEB(p, MATH2, 0, CONTEXT2, 0, 8, WAITCOMP | IMMED);
2080
2081 if (dir == OP_TYPE_ENCAP_PROTOCOL)
2082 MATHB(p, SEQINSZ, ADD, PDCP_MAC_I_LEN, VSEQOUTSZ, 4, IMMED2);
2083 else
2084 MATHB(p, SEQINSZ, SUB, PDCP_MAC_I_LEN, VSEQOUTSZ, 4, IMMED2);
2085
2086 MATHB(p, SEQINSZ, SUB, ZERO, VSEQINSZ, 4, 0);
2087 SEQSTORE(p, MATH0, offset, length, 0);
2088
2089 if (dir == OP_TYPE_ENCAP_PROTOCOL) {
2090 SEQFIFOSTORE(p, MSG, 0, 0, VLF);
2091 SEQFIFOLOAD(p, MSGINSNOOP, 0, VLF | LAST2);
2092 } else {
2093 SEQFIFOSTORE(p, MSG, 0, 0, VLF | CONT);
2094 SEQFIFOLOAD(p, MSGOUTSNOOP, 0, VLF | LAST1 | FLUSH1);
2095 }
2096
2097 ALG_OPERATION(p, OP_ALG_ALGSEL_ZUCA,
2098 OP_ALG_AAI_F9,
2099 OP_ALG_AS_INITFINAL,
2100 dir == OP_TYPE_ENCAP_PROTOCOL ?
2101 ICV_CHECK_DISABLE : ICV_CHECK_ENABLE,
2102 DIR_ENC);
2103
2104 ALG_OPERATION(p, OP_ALG_ALGSEL_AES,
2105 OP_ALG_AAI_CTR,
2106 OP_ALG_AS_INITFINAL,
2107 ICV_CHECK_DISABLE,
2108 dir == OP_TYPE_ENCAP_PROTOCOL ? DIR_ENC : DIR_DEC);
2109
2110 if (dir == OP_TYPE_ENCAP_PROTOCOL) {
2111 MOVE(p, CONTEXT2, 0, IFIFOAB1, 0, 4, LAST1 | FLUSH1 | IMMED);
2112 } else {
2113 /* Save ICV */
2114 MOVE(p, OFIFO, 0, MATH0, 0, 4, IMMED);
2115
2116 LOAD(p, NFIFOENTRY_STYPE_ALTSOURCE |
2117 NFIFOENTRY_DEST_CLASS2 |
2118 NFIFOENTRY_DTYPE_ICV |
2119 NFIFOENTRY_LC2 | 4, NFIFO_SZL, 0, 4, IMMED);
2120 MOVE(p, MATH0, 0, ALTSOURCE, 0, 4, WAITCOMP | IMMED);
2121 }
2122
2123 /* Reset ZUCA mode and done interrupt */
2124 LOAD(p, CLRW_CLR_C2MODE, CLRW, 0, 4, IMMED);
2125 LOAD(p, CIRQ_ZADI, ICTRL, 0, 4, IMMED);
2126
2127 PATCH_JUMP(p, pkeyjump, keyjump);
2128
2129 return 0;
2130 }
2131
2132 static inline int
pdcp_insert_cplane_zuc_snow_op(struct program * p,bool swap __maybe_unused,struct alginfo * cipherdata,struct alginfo * authdata,unsigned int dir,enum pdcp_sn_size sn_size,unsigned char era_2_sw_hfn_ovrd __maybe_unused)2133 pdcp_insert_cplane_zuc_snow_op(struct program *p,
2134 bool swap __maybe_unused,
2135 struct alginfo *cipherdata,
2136 struct alginfo *authdata,
2137 unsigned int dir,
2138 enum pdcp_sn_size sn_size,
2139 unsigned char era_2_sw_hfn_ovrd __maybe_unused)
2140 {
2141 uint32_t offset = 0, length = 0, sn_mask = 0;
2142 LABEL(keyjump);
2143 REFERENCE(pkeyjump);
2144
2145 if (rta_sec_era < RTA_SEC_ERA_5) {
2146 pr_err("Invalid era for selected algorithm\n");
2147 return -ENOTSUP;
2148 }
2149
2150 if ((rta_sec_era >= RTA_SEC_ERA_8 && sn_size != PDCP_SN_SIZE_18) ||
2151 (rta_sec_era == RTA_SEC_ERA_10)) {
2152 int pclid;
2153 KEY(p, KEY1, cipherdata->key_enc_flags, cipherdata->key,
2154 cipherdata->keylen, INLINE_KEY(cipherdata));
2155 KEY(p, KEY2, authdata->key_enc_flags, authdata->key, authdata->keylen,
2156 INLINE_KEY(authdata));
2157
2158 if (sn_size == PDCP_SN_SIZE_5)
2159 pclid = OP_PCLID_LTE_PDCP_CTRL_MIXED;
2160 else
2161 pclid = OP_PCLID_LTE_PDCP_USER_RN;
2162
2163 PROTOCOL(p, dir, pclid,
2164 ((uint16_t)cipherdata->algtype << 8) |
2165 (uint16_t)authdata->algtype);
2166
2167 return 0;
2168 }
2169 /* Non-proto is supported only for 5bit cplane and 18bit uplane */
2170 switch (sn_size) {
2171 case PDCP_SN_SIZE_5:
2172 offset = 7;
2173 length = 1;
2174 sn_mask = (swap == false) ? PDCP_C_PLANE_SN_MASK :
2175 PDCP_C_PLANE_SN_MASK_BE;
2176 break;
2177 case PDCP_SN_SIZE_18:
2178 offset = 5;
2179 length = 3;
2180 sn_mask = (swap == false) ? PDCP_U_PLANE_18BIT_SN_MASK :
2181 PDCP_U_PLANE_18BIT_SN_MASK_BE;
2182 break;
2183 case PDCP_SN_SIZE_7:
2184 case PDCP_SN_SIZE_12:
2185 case PDCP_SN_SIZE_15:
2186 pr_err("Invalid sn_size for %s\n", __func__);
2187 return -ENOTSUP;
2188
2189 }
2190 pkeyjump = JUMP(p, keyjump, LOCAL_JUMP, ALL_TRUE, SHRD | SELF | BOTH);
2191 KEY(p, KEY1, cipherdata->key_enc_flags, cipherdata->key,
2192 cipherdata->keylen, INLINE_KEY(cipherdata));
2193 KEY(p, KEY2, authdata->key_enc_flags, authdata->key, authdata->keylen,
2194 INLINE_KEY(authdata));
2195
2196 SET_LABEL(p, keyjump);
2197 SEQLOAD(p, MATH0, offset, length, 0);
2198 JUMP(p, 1, LOCAL_JUMP, ALL_TRUE, CALM);
2199 MOVEB(p, MATH0, offset, IFIFOAB2, 0, length, IMMED);
2200 MATHB(p, MATH0, AND, sn_mask, MATH1, 8, IFB | IMMED2);
2201
2202 MATHB(p, MATH1, SHLD, MATH1, MATH1, 8, 0);
2203 MOVEB(p, DESCBUF, 4, MATH2, 0, 8, WAITCOMP | IMMED);
2204 MATHB(p, MATH1, OR, MATH2, MATH1, 8, 0);
2205 MOVEB(p, MATH1, 0, CONTEXT1, 0, 8, IMMED);
2206 MOVEB(p, MATH1, 0, CONTEXT2, 0, 4, IMMED);
2207 if (swap == false) {
2208 MATHB(p, MATH1, AND, upper_32_bits(PDCP_BEARER_MASK), MATH2,
2209 4, IMMED2);
2210 MATHB(p, MATH1, AND, lower_32_bits(PDCP_DIR_MASK), MATH3,
2211 4, IMMED2);
2212 } else {
2213 MATHB(p, MATH1, AND, lower_32_bits(PDCP_BEARER_MASK_BE), MATH2,
2214 4, IMMED2);
2215 MATHB(p, MATH1, AND, upper_32_bits(PDCP_DIR_MASK_BE), MATH3,
2216 4, IMMED2);
2217 }
2218 MATHB(p, MATH3, SHLD, MATH3, MATH3, 8, 0);
2219 MOVEB(p, MATH2, 4, OFIFO, 0, 12, IMMED);
2220 MOVE(p, OFIFO, 0, CONTEXT2, 4, 12, IMMED);
2221
2222 if (dir == OP_TYPE_ENCAP_PROTOCOL) {
2223 MATHB(p, SEQINSZ, ADD, PDCP_MAC_I_LEN, VSEQOUTSZ, 4, IMMED2);
2224 MATHB(p, SEQINSZ, SUB, ZERO, VSEQINSZ, 4, 0);
2225 } else {
2226 MATHB(p, SEQINSZ, SUB, PDCP_MAC_I_LEN, VSEQOUTSZ, 4, IMMED2);
2227 MATHB(p, VSEQOUTSZ, SUB, ZERO, VSEQINSZ, 4, 0);
2228 }
2229
2230 SEQSTORE(p, MATH0, offset, length, 0);
2231
2232 if (dir == OP_TYPE_ENCAP_PROTOCOL) {
2233 SEQFIFOSTORE(p, MSG, 0, 0, VLF);
2234 SEQFIFOLOAD(p, MSGINSNOOP, 0, VLF | LAST2);
2235 } else {
2236 SEQFIFOSTORE(p, MSG, 0, 0, VLF | CONT);
2237 SEQFIFOLOAD(p, MSGOUTSNOOP, 0, VLF | LAST2);
2238 }
2239
2240 ALG_OPERATION(p, OP_ALG_ALGSEL_SNOW_F9,
2241 OP_ALG_AAI_F9,
2242 OP_ALG_AS_INITFINAL,
2243 dir == OP_TYPE_ENCAP_PROTOCOL ?
2244 ICV_CHECK_DISABLE : ICV_CHECK_ENABLE,
2245 DIR_DEC);
2246
2247 ALG_OPERATION(p, OP_ALG_ALGSEL_ZUCE,
2248 OP_ALG_AAI_F8,
2249 OP_ALG_AS_INITFINAL,
2250 ICV_CHECK_DISABLE,
2251 dir == OP_TYPE_ENCAP_PROTOCOL ? DIR_ENC : DIR_DEC);
2252
2253 if (dir == OP_TYPE_ENCAP_PROTOCOL) {
2254 MOVE(p, CONTEXT2, 0, IFIFOAB1, 0, 4, LAST1 | FLUSH1 | IMMED);
2255 } else {
2256 SEQFIFOLOAD(p, MSG1, 4, LAST1 | FLUSH1);
2257 JUMP(p, 1, LOCAL_JUMP, ALL_TRUE, CLASS1 | NOP | NIFP);
2258
2259 if (rta_sec_era >= RTA_SEC_ERA_6)
2260 /*
2261 * For SEC ERA 6, there's a problem with the OFIFO
2262 * pointer, and thus it needs to be reset here before
2263 * moving to M0.
2264 */
2265 LOAD(p, 0, DCTRL, 0, LDLEN_RST_CHA_OFIFO_PTR, IMMED);
2266
2267 /* Put ICV to M0 before sending it to C2 for comparison. */
2268 MOVEB(p, OFIFO, 0, MATH0, 0, 4, WAITCOMP | IMMED);
2269
2270 LOAD(p, NFIFOENTRY_STYPE_ALTSOURCE |
2271 NFIFOENTRY_DEST_CLASS2 |
2272 NFIFOENTRY_DTYPE_ICV |
2273 NFIFOENTRY_LC2 | 4, NFIFO_SZL, 0, 4, IMMED);
2274 MOVEB(p, MATH0, 0, ALTSOURCE, 0, 4, IMMED);
2275 }
2276
2277 PATCH_JUMP(p, pkeyjump, keyjump);
2278 return 0;
2279 }
2280
2281 static inline int
pdcp_insert_cplane_zuc_aes_op(struct program * p,bool swap __maybe_unused,struct alginfo * cipherdata,struct alginfo * authdata,unsigned int dir,enum pdcp_sn_size sn_size,unsigned char era_2_sw_hfn_ovrd __maybe_unused)2282 pdcp_insert_cplane_zuc_aes_op(struct program *p,
2283 bool swap __maybe_unused,
2284 struct alginfo *cipherdata,
2285 struct alginfo *authdata,
2286 unsigned int dir,
2287 enum pdcp_sn_size sn_size,
2288 unsigned char era_2_sw_hfn_ovrd __maybe_unused)
2289 {
2290 uint32_t offset = 0, length = 0, sn_mask = 0;
2291 if (rta_sec_era < RTA_SEC_ERA_5) {
2292 pr_err("Invalid era for selected algorithm\n");
2293 return -ENOTSUP;
2294 }
2295
2296 if ((rta_sec_era >= RTA_SEC_ERA_8 && sn_size != PDCP_SN_SIZE_18) ||
2297 (rta_sec_era == RTA_SEC_ERA_10)) {
2298 int pclid;
2299
2300 KEY(p, KEY1, cipherdata->key_enc_flags, cipherdata->key,
2301 cipherdata->keylen, INLINE_KEY(cipherdata));
2302 KEY(p, KEY2, authdata->key_enc_flags, authdata->key,
2303 authdata->keylen, INLINE_KEY(authdata));
2304
2305 if (sn_size == PDCP_SN_SIZE_5)
2306 pclid = OP_PCLID_LTE_PDCP_CTRL_MIXED;
2307 else
2308 pclid = OP_PCLID_LTE_PDCP_USER_RN;
2309
2310 PROTOCOL(p, dir, pclid,
2311 ((uint16_t)cipherdata->algtype << 8) |
2312 (uint16_t)authdata->algtype);
2313 return 0;
2314 }
2315 /* Non-proto is supported only for 5bit cplane and 18bit uplane */
2316 switch (sn_size) {
2317 case PDCP_SN_SIZE_5:
2318 offset = 7;
2319 length = 1;
2320 sn_mask = (swap == false) ? PDCP_C_PLANE_SN_MASK :
2321 PDCP_C_PLANE_SN_MASK_BE;
2322 break;
2323 case PDCP_SN_SIZE_18:
2324 offset = 5;
2325 length = 3;
2326 sn_mask = (swap == false) ? PDCP_U_PLANE_18BIT_SN_MASK :
2327 PDCP_U_PLANE_18BIT_SN_MASK_BE;
2328 break;
2329 case PDCP_SN_SIZE_7:
2330 case PDCP_SN_SIZE_12:
2331 case PDCP_SN_SIZE_15:
2332 pr_err("Invalid sn_size for %s\n", __func__);
2333 return -ENOTSUP;
2334 }
2335
2336 SEQLOAD(p, MATH0, offset, length, 0);
2337 JUMP(p, 1, LOCAL_JUMP, ALL_TRUE, CALM);
2338 MATHB(p, MATH0, AND, sn_mask, MATH1, 8, IFB | IMMED2);
2339
2340 MATHB(p, MATH1, SHLD, MATH1, MATH1, 8, 0);
2341 MOVEB(p, DESCBUF, 4, MATH2, 0, 0x08, WAITCOMP | IMMED);
2342 MATHB(p, MATH1, OR, MATH2, MATH2, 8, 0);
2343 SEQSTORE(p, MATH0, offset, length, 0);
2344 if (dir == OP_TYPE_ENCAP_PROTOCOL) {
2345 KEY(p, KEY1, authdata->key_enc_flags, authdata->key,
2346 authdata->keylen, INLINE_KEY(authdata));
2347 MOVEB(p, MATH2, 0, IFIFOAB1, 0, 0x08, IMMED);
2348 MOVEB(p, MATH0, offset, IFIFOAB1, 0, length, IMMED);
2349
2350 MATHB(p, SEQINSZ, SUB, ZERO, VSEQINSZ, 4, 0);
2351 MATHB(p, VSEQINSZ, ADD, PDCP_MAC_I_LEN, VSEQOUTSZ, 4, IMMED2);
2352
2353 ALG_OPERATION(p, OP_ALG_ALGSEL_AES,
2354 OP_ALG_AAI_CMAC,
2355 OP_ALG_AS_INITFINAL,
2356 ICV_CHECK_DISABLE,
2357 DIR_DEC);
2358 SEQFIFOLOAD(p, MSG1, 0, VLF | LAST1 | FLUSH1);
2359 MOVEB(p, CONTEXT1, 0, MATH3, 0, 4, WAITCOMP | IMMED);
2360 LOAD(p, CLRW_RESET_CLS1_CHA |
2361 CLRW_CLR_C1KEY |
2362 CLRW_CLR_C1CTX |
2363 CLRW_CLR_C1ICV |
2364 CLRW_CLR_C1DATAS |
2365 CLRW_CLR_C1MODE,
2366 CLRW, 0, 4, IMMED);
2367
2368 KEY(p, KEY1, cipherdata->key_enc_flags, cipherdata->key,
2369 cipherdata->keylen, INLINE_KEY(cipherdata));
2370
2371 MOVEB(p, MATH2, 0, CONTEXT1, 0, 8, IMMED);
2372 SEQINPTR(p, 0, PDCP_NULL_MAX_FRAME_LEN, RTO);
2373
2374 ALG_OPERATION(p, OP_ALG_ALGSEL_ZUCE,
2375 OP_ALG_AAI_F8,
2376 OP_ALG_AS_INITFINAL,
2377 ICV_CHECK_DISABLE,
2378 DIR_ENC);
2379 SEQFIFOSTORE(p, MSG, 0, 0, VLF);
2380
2381 SEQFIFOLOAD(p, SKIP, length, 0);
2382
2383 SEQFIFOLOAD(p, MSG1, 0, VLF);
2384 MOVEB(p, MATH3, 0, IFIFOAB1, 0, 4, LAST1 | FLUSH1 | IMMED);
2385 } else {
2386 MOVEB(p, MATH2, 0, CONTEXT1, 0, 8, IMMED);
2387
2388 MOVE(p, CONTEXT1, 0, CONTEXT2, 0, 8, IMMED);
2389
2390 MATHB(p, SEQINSZ, SUB, ZERO, VSEQINSZ, 4, 0);
2391
2392 MATHB(p, SEQINSZ, SUB, PDCP_MAC_I_LEN, VSEQOUTSZ, 4, IMMED2);
2393
2394 KEY(p, KEY1, cipherdata->key_enc_flags, cipherdata->key,
2395 cipherdata->keylen, INLINE_KEY(cipherdata));
2396
2397 MOVE(p, CONTEXT1, 0, CONTEXT2, 0, 8, IMMED);
2398
2399 ALG_OPERATION(p, OP_ALG_ALGSEL_ZUCE,
2400 OP_ALG_AAI_F8,
2401 OP_ALG_AS_INITFINAL,
2402 ICV_CHECK_DISABLE,
2403 DIR_DEC);
2404 SEQFIFOSTORE(p, MSG, 0, 0, VLF | CONT);
2405 SEQFIFOLOAD(p, MSG1, 0, VLF | LAST1 | FLUSH1);
2406
2407 MOVEB(p, OFIFO, 0, MATH3, 0, 4, IMMED);
2408
2409 LOAD(p, CLRW_RESET_CLS1_CHA |
2410 CLRW_CLR_C1KEY |
2411 CLRW_CLR_C1CTX |
2412 CLRW_CLR_C1ICV |
2413 CLRW_CLR_C1DATAS |
2414 CLRW_CLR_C1MODE,
2415 CLRW, 0, 4, IMMED);
2416
2417 KEY(p, KEY1, authdata->key_enc_flags, authdata->key,
2418 authdata->keylen, INLINE_KEY(authdata));
2419
2420 SEQINPTR(p, 0, 0, SOP);
2421
2422 ALG_OPERATION(p, OP_ALG_ALGSEL_AES,
2423 OP_ALG_AAI_CMAC,
2424 OP_ALG_AS_INITFINAL,
2425 ICV_CHECK_ENABLE,
2426 DIR_DEC);
2427
2428 MATHB(p, SEQINSZ, SUB, ZERO, VSEQINSZ, 4, 0);
2429
2430 MOVE(p, CONTEXT2, 0, IFIFOAB1, 0, 8, IMMED);
2431
2432 SEQFIFOLOAD(p, MSG1, 0, VLF | LAST1 | FLUSH1);
2433
2434 LOAD(p, NFIFOENTRY_STYPE_ALTSOURCE |
2435 NFIFOENTRY_DEST_CLASS1 |
2436 NFIFOENTRY_DTYPE_ICV |
2437 NFIFOENTRY_LC1 |
2438 NFIFOENTRY_FC1 | 4, NFIFO_SZL, 0, 4, IMMED);
2439 MOVEB(p, MATH3, 0, ALTSOURCE, 0, 4, IMMED);
2440 }
2441
2442 return 0;
2443 }
2444
2445 static inline int
pdcp_insert_uplane_no_int_op(struct program * p,bool swap __maybe_unused,struct alginfo * cipherdata,unsigned int dir,enum pdcp_sn_size sn_size)2446 pdcp_insert_uplane_no_int_op(struct program *p,
2447 bool swap __maybe_unused,
2448 struct alginfo *cipherdata,
2449 unsigned int dir,
2450 enum pdcp_sn_size sn_size)
2451 {
2452 int op;
2453 uint32_t sn_mask;
2454
2455 /* Insert Cipher Key */
2456 KEY(p, KEY1, cipherdata->key_enc_flags, cipherdata->key,
2457 cipherdata->keylen, INLINE_KEY(cipherdata));
2458
2459 if ((rta_sec_era >= RTA_SEC_ERA_8 && sn_size == PDCP_SN_SIZE_15) ||
2460 (rta_sec_era >= RTA_SEC_ERA_10)) {
2461 PROTOCOL(p, dir, OP_PCLID_LTE_PDCP_USER,
2462 (uint16_t)cipherdata->algtype);
2463 return 0;
2464 }
2465
2466 if (sn_size == PDCP_SN_SIZE_15) {
2467 SEQLOAD(p, MATH0, 6, 2, 0);
2468 sn_mask = (swap == false) ? PDCP_U_PLANE_15BIT_SN_MASK :
2469 PDCP_U_PLANE_15BIT_SN_MASK_BE;
2470 } else { /* SN Size == PDCP_SN_SIZE_18 */
2471 SEQLOAD(p, MATH0, 5, 3, 0);
2472 sn_mask = (swap == false) ? PDCP_U_PLANE_18BIT_SN_MASK :
2473 PDCP_U_PLANE_18BIT_SN_MASK_BE;
2474 }
2475 JUMP(p, 1, LOCAL_JUMP, ALL_TRUE, CALM);
2476 MATHB(p, MATH0, AND, sn_mask, MATH1, 8, IFB | IMMED2);
2477
2478 if (sn_size == PDCP_SN_SIZE_15)
2479 SEQSTORE(p, MATH0, 6, 2, 0);
2480 else /* SN Size == PDCP_SN_SIZE_18 */
2481 SEQSTORE(p, MATH0, 5, 3, 0);
2482
2483 MATHB(p, MATH1, SHLD, MATH1, MATH1, 8, 0);
2484 MOVEB(p, DESCBUF, 8, MATH2, 0, 8, WAITCOMP | IMMED);
2485 MATHB(p, MATH1, OR, MATH2, MATH2, 8, 0);
2486
2487 MATHB(p, SEQINSZ, SUB, MATH3, VSEQINSZ, 4, 0);
2488 MATHB(p, SEQINSZ, SUB, MATH3, VSEQOUTSZ, 4, 0);
2489
2490 SEQFIFOSTORE(p, MSG, 0, 0, VLF);
2491
2492 op = dir == OP_TYPE_ENCAP_PROTOCOL ? DIR_ENC : DIR_DEC;
2493 switch (cipherdata->algtype) {
2494 case PDCP_CIPHER_TYPE_SNOW:
2495 MOVEB(p, MATH2, 0, CONTEXT1, 0, 8, WAITCOMP | IMMED);
2496 ALG_OPERATION(p, OP_ALG_ALGSEL_SNOW_F8,
2497 OP_ALG_AAI_F8,
2498 OP_ALG_AS_INITFINAL,
2499 ICV_CHECK_DISABLE,
2500 op);
2501 break;
2502
2503 case PDCP_CIPHER_TYPE_AES:
2504 MOVEB(p, MATH2, 0, CONTEXT1, 0x10, 0x10, WAITCOMP | IMMED);
2505 ALG_OPERATION(p, OP_ALG_ALGSEL_AES,
2506 OP_ALG_AAI_CTR,
2507 OP_ALG_AS_INITFINAL,
2508 ICV_CHECK_DISABLE,
2509 op);
2510 break;
2511
2512 case PDCP_CIPHER_TYPE_ZUC:
2513 if (rta_sec_era < RTA_SEC_ERA_5) {
2514 pr_err("Invalid era for selected algorithm\n");
2515 return -ENOTSUP;
2516 }
2517 MOVEB(p, MATH2, 0, CONTEXT1, 0, 0x08, IMMED);
2518 MOVEB(p, MATH2, 0, CONTEXT1, 0x08, 0x08, WAITCOMP | IMMED);
2519
2520 ALG_OPERATION(p, OP_ALG_ALGSEL_ZUCE,
2521 OP_ALG_AAI_F8,
2522 OP_ALG_AS_INITFINAL,
2523 ICV_CHECK_DISABLE,
2524 op);
2525 break;
2526
2527 default:
2528 pr_err("%s: Invalid encrypt algorithm selected: %d\n",
2529 "pdcp_insert_uplane_15bit_op", cipherdata->algtype);
2530 return -EINVAL;
2531 }
2532
2533 SEQFIFOLOAD(p, MSG1, 0, VLF | LAST1 | FLUSH1);
2534
2535 return 0;
2536 }
2537
2538 /*
2539 * Function for inserting the snippet of code responsible for creating
2540 * the HFN override code via either DPOVRD or via the input frame.
2541 */
2542 static inline int
insert_hfn_ov_op(struct program * p,uint32_t shift,enum pdb_type_e pdb_type,unsigned char era_2_sw_hfn_ovrd)2543 insert_hfn_ov_op(struct program *p,
2544 uint32_t shift,
2545 enum pdb_type_e pdb_type,
2546 unsigned char era_2_sw_hfn_ovrd)
2547 {
2548 uint32_t imm = PDCP_DPOVRD_HFN_OV_EN;
2549 uint16_t hfn_pdb_offset;
2550 LABEL(keyjump);
2551 REFERENCE(pkeyjump);
2552
2553 if (rta_sec_era == RTA_SEC_ERA_2 && !era_2_sw_hfn_ovrd)
2554 return 0;
2555
2556 switch (pdb_type) {
2557 case PDCP_PDB_TYPE_NO_PDB:
2558 /*
2559 * If there is no PDB, then HFN override mechanism does not
2560 * make any sense, thus in this case the function will
2561 * return the pointer to the current position in the
2562 * descriptor buffer
2563 */
2564 return 0;
2565
2566 case PDCP_PDB_TYPE_REDUCED_PDB:
2567 hfn_pdb_offset = 4;
2568 break;
2569
2570 case PDCP_PDB_TYPE_FULL_PDB:
2571 hfn_pdb_offset = 8;
2572 break;
2573
2574 default:
2575 return -EINVAL;
2576 }
2577
2578 if (rta_sec_era > RTA_SEC_ERA_2) {
2579 MATHB(p, DPOVRD, AND, imm, NONE, 8, IFB | IMMED2);
2580 } else {
2581 SEQLOAD(p, MATH0, 4, 4, 0);
2582 JUMP(p, 1, LOCAL_JUMP, ALL_TRUE, CALM);
2583 MATHB(p, MATH0, AND, imm, NONE, 8, IFB | IMMED2);
2584 SEQSTORE(p, MATH0, 4, 4, 0);
2585 }
2586
2587 pkeyjump = JUMP(p, keyjump, LOCAL_JUMP, ALL_TRUE, MATH_Z);
2588
2589 if (rta_sec_era > RTA_SEC_ERA_2)
2590 MATHI(p, DPOVRD, LSHIFT, shift, MATH0, 4, IMMED2);
2591 else
2592 MATHB(p, MATH0, LSHIFT, shift, MATH0, 4, IMMED2);
2593
2594 MATHB(p, MATH0, SHLD, MATH0, MATH0, 8, 0);
2595 MOVE(p, MATH0, 0, DESCBUF, hfn_pdb_offset, 4, IMMED);
2596
2597 if (rta_sec_era >= RTA_SEC_ERA_8)
2598 /*
2599 * For ERA8, DPOVRD could be handled by the PROTOCOL command
2600 * itself. For now, this is not done. Thus, clear DPOVRD here
2601 * to alleviate any side-effects.
2602 */
2603 MATHB(p, DPOVRD, AND, ZERO, DPOVRD, 4, STL);
2604
2605 SET_LABEL(p, keyjump);
2606 PATCH_JUMP(p, pkeyjump, keyjump);
2607 return 0;
2608 }
2609
2610 /*
2611 * PDCP Control PDB creation function
2612 */
2613 static inline enum pdb_type_e
cnstr_pdcp_c_plane_pdb(struct program * p,uint32_t hfn,enum pdcp_sn_size sn_size,unsigned char bearer,unsigned char direction,uint32_t hfn_threshold,struct alginfo * cipherdata,struct alginfo * authdata)2614 cnstr_pdcp_c_plane_pdb(struct program *p,
2615 uint32_t hfn,
2616 enum pdcp_sn_size sn_size,
2617 unsigned char bearer,
2618 unsigned char direction,
2619 uint32_t hfn_threshold,
2620 struct alginfo *cipherdata,
2621 struct alginfo *authdata)
2622 {
2623 struct pdcp_pdb pdb;
2624 enum pdb_type_e
2625 pdb_mask[PDCP_CIPHER_TYPE_INVALID][PDCP_AUTH_TYPE_INVALID] = {
2626 { /* NULL */
2627 PDCP_PDB_TYPE_NO_PDB, /* NULL */
2628 PDCP_PDB_TYPE_FULL_PDB, /* SNOW f9 */
2629 PDCP_PDB_TYPE_FULL_PDB, /* AES CMAC */
2630 PDCP_PDB_TYPE_FULL_PDB /* ZUC-I */
2631 },
2632 { /* SNOW f8 */
2633 PDCP_PDB_TYPE_FULL_PDB, /* NULL */
2634 PDCP_PDB_TYPE_FULL_PDB, /* SNOW f9 */
2635 PDCP_PDB_TYPE_REDUCED_PDB, /* AES CMAC */
2636 PDCP_PDB_TYPE_REDUCED_PDB /* ZUC-I */
2637 },
2638 { /* AES CTR */
2639 PDCP_PDB_TYPE_FULL_PDB, /* NULL */
2640 PDCP_PDB_TYPE_REDUCED_PDB, /* SNOW f9 */
2641 PDCP_PDB_TYPE_FULL_PDB, /* AES CMAC */
2642 PDCP_PDB_TYPE_REDUCED_PDB /* ZUC-I */
2643 },
2644 { /* ZUC-E */
2645 PDCP_PDB_TYPE_FULL_PDB, /* NULL */
2646 PDCP_PDB_TYPE_REDUCED_PDB, /* SNOW f9 */
2647 PDCP_PDB_TYPE_REDUCED_PDB, /* AES CMAC */
2648 PDCP_PDB_TYPE_FULL_PDB /* ZUC-I */
2649 },
2650 };
2651
2652 if (rta_sec_era >= RTA_SEC_ERA_8) {
2653 memset(&pdb, 0x00, sizeof(struct pdcp_pdb));
2654
2655 /* To support 12-bit seq numbers, we use u-plane opt in pdb.
2656 * SEC supports 5-bit only with c-plane opt in pdb.
2657 */
2658 if (sn_size == PDCP_SN_SIZE_12) {
2659 pdb.hfn_res = hfn << PDCP_U_PLANE_PDB_LONG_SN_HFN_SHIFT;
2660 pdb.bearer_dir_res = (uint32_t)
2661 ((bearer << PDCP_U_PLANE_PDB_BEARER_SHIFT) |
2662 (direction << PDCP_U_PLANE_PDB_DIR_SHIFT));
2663
2664 pdb.hfn_thr_res =
2665 hfn_threshold << PDCP_U_PLANE_PDB_LONG_SN_HFN_THR_SHIFT;
2666
2667 } else {
2668 /* This means 5-bit c-plane.
2669 * Here we use c-plane opt in pdb
2670 */
2671
2672 /* This is a HW issue. Bit 2 should be set to zero,
2673 * but it does not work this way. Override here.
2674 */
2675 pdb.opt_res.rsvd = 0x00000002;
2676
2677 /* Copy relevant information from user to PDB */
2678 pdb.hfn_res = hfn << PDCP_C_PLANE_PDB_HFN_SHIFT;
2679 pdb.bearer_dir_res = (uint32_t)
2680 ((bearer << PDCP_C_PLANE_PDB_BEARER_SHIFT) |
2681 (direction << PDCP_C_PLANE_PDB_DIR_SHIFT));
2682 pdb.hfn_thr_res =
2683 hfn_threshold << PDCP_C_PLANE_PDB_HFN_THR_SHIFT;
2684 }
2685
2686 /* copy PDB in descriptor*/
2687 __rta_out32(p, pdb.opt_res.opt);
2688 __rta_out32(p, pdb.hfn_res);
2689 __rta_out32(p, pdb.bearer_dir_res);
2690 __rta_out32(p, pdb.hfn_thr_res);
2691
2692 return PDCP_PDB_TYPE_FULL_PDB;
2693 }
2694
2695 switch (pdb_mask[cipherdata->algtype][authdata->algtype]) {
2696 case PDCP_PDB_TYPE_NO_PDB:
2697 break;
2698
2699 case PDCP_PDB_TYPE_REDUCED_PDB:
2700 __rta_out32(p, (hfn << PDCP_C_PLANE_PDB_HFN_SHIFT));
2701 __rta_out32(p,
2702 (uint32_t)((bearer <<
2703 PDCP_C_PLANE_PDB_BEARER_SHIFT) |
2704 (direction <<
2705 PDCP_C_PLANE_PDB_DIR_SHIFT)));
2706 break;
2707
2708 case PDCP_PDB_TYPE_FULL_PDB:
2709 memset(&pdb, 0x00, sizeof(struct pdcp_pdb));
2710
2711 /* This is a HW issue. Bit 2 should be set to zero,
2712 * but it does not work this way. Override here.
2713 */
2714 pdb.opt_res.rsvd = 0x00000002;
2715
2716 /* Copy relevant information from user to PDB */
2717 pdb.hfn_res = hfn << PDCP_C_PLANE_PDB_HFN_SHIFT;
2718 pdb.bearer_dir_res = (uint32_t)
2719 ((bearer << PDCP_C_PLANE_PDB_BEARER_SHIFT) |
2720 (direction << PDCP_C_PLANE_PDB_DIR_SHIFT));
2721 pdb.hfn_thr_res =
2722 hfn_threshold << PDCP_C_PLANE_PDB_HFN_THR_SHIFT;
2723
2724 /* copy PDB in descriptor*/
2725 __rta_out32(p, pdb.opt_res.opt);
2726 __rta_out32(p, pdb.hfn_res);
2727 __rta_out32(p, pdb.bearer_dir_res);
2728 __rta_out32(p, pdb.hfn_thr_res);
2729
2730 break;
2731
2732 default:
2733 return PDCP_PDB_TYPE_INVALID;
2734 }
2735
2736 return pdb_mask[cipherdata->algtype][authdata->algtype];
2737 }
2738
2739 /*
2740 * PDCP UPlane PDB creation function
2741 */
2742 static inline enum pdb_type_e
cnstr_pdcp_u_plane_pdb(struct program * p,enum pdcp_sn_size sn_size,uint32_t hfn,unsigned short bearer,unsigned short direction,uint32_t hfn_threshold,struct alginfo * cipherdata,struct alginfo * authdata)2743 cnstr_pdcp_u_plane_pdb(struct program *p,
2744 enum pdcp_sn_size sn_size,
2745 uint32_t hfn, unsigned short bearer,
2746 unsigned short direction,
2747 uint32_t hfn_threshold,
2748 struct alginfo *cipherdata,
2749 struct alginfo *authdata)
2750 {
2751 struct pdcp_pdb pdb;
2752 enum pdb_type_e pdb_type = PDCP_PDB_TYPE_FULL_PDB;
2753 enum pdb_type_e
2754 pdb_mask[PDCP_CIPHER_TYPE_INVALID][PDCP_AUTH_TYPE_INVALID] = {
2755 { /* NULL */
2756 PDCP_PDB_TYPE_NO_PDB, /* NULL */
2757 PDCP_PDB_TYPE_FULL_PDB, /* SNOW f9 */
2758 PDCP_PDB_TYPE_FULL_PDB, /* AES CMAC */
2759 PDCP_PDB_TYPE_FULL_PDB /* ZUC-I */
2760 },
2761 { /* SNOW f8 */
2762 PDCP_PDB_TYPE_FULL_PDB, /* NULL */
2763 PDCP_PDB_TYPE_FULL_PDB, /* SNOW f9 */
2764 PDCP_PDB_TYPE_REDUCED_PDB, /* AES CMAC */
2765 PDCP_PDB_TYPE_REDUCED_PDB /* ZUC-I */
2766 },
2767 { /* AES CTR */
2768 PDCP_PDB_TYPE_FULL_PDB, /* NULL */
2769 PDCP_PDB_TYPE_REDUCED_PDB, /* SNOW f9 */
2770 PDCP_PDB_TYPE_FULL_PDB, /* AES CMAC */
2771 PDCP_PDB_TYPE_REDUCED_PDB /* ZUC-I */
2772 },
2773 { /* ZUC-E */
2774 PDCP_PDB_TYPE_FULL_PDB, /* NULL */
2775 PDCP_PDB_TYPE_REDUCED_PDB, /* SNOW f9 */
2776 PDCP_PDB_TYPE_REDUCED_PDB, /* AES CMAC */
2777 PDCP_PDB_TYPE_FULL_PDB /* ZUC-I */
2778 },
2779 };
2780
2781 /* Read options from user */
2782 /* Depending on sequence number length, the HFN and HFN threshold
2783 * have different lengths.
2784 */
2785 memset(&pdb, 0x00, sizeof(struct pdcp_pdb));
2786
2787 switch (sn_size) {
2788 case PDCP_SN_SIZE_7:
2789 pdb.opt_res.opt |= PDCP_U_PLANE_PDB_OPT_SHORT_SN;
2790 pdb.hfn_res = hfn << PDCP_U_PLANE_PDB_SHORT_SN_HFN_SHIFT;
2791 pdb.hfn_thr_res =
2792 hfn_threshold<<PDCP_U_PLANE_PDB_SHORT_SN_HFN_THR_SHIFT;
2793 break;
2794
2795 case PDCP_SN_SIZE_12:
2796 pdb.opt_res.opt &= (uint32_t)(~PDCP_U_PLANE_PDB_OPT_SHORT_SN);
2797 pdb.hfn_res = hfn << PDCP_U_PLANE_PDB_LONG_SN_HFN_SHIFT;
2798 pdb.hfn_thr_res =
2799 hfn_threshold<<PDCP_U_PLANE_PDB_LONG_SN_HFN_THR_SHIFT;
2800 break;
2801
2802 case PDCP_SN_SIZE_15:
2803 pdb.opt_res.opt = (uint32_t)(PDCP_U_PLANE_PDB_OPT_15B_SN);
2804 pdb.hfn_res = hfn << PDCP_U_PLANE_PDB_15BIT_SN_HFN_SHIFT;
2805 pdb.hfn_thr_res =
2806 hfn_threshold<<PDCP_U_PLANE_PDB_15BIT_SN_HFN_THR_SHIFT;
2807 break;
2808
2809 case PDCP_SN_SIZE_18:
2810 pdb.opt_res.opt = (uint32_t)(PDCP_U_PLANE_PDB_OPT_18B_SN);
2811 pdb.hfn_res = hfn << PDCP_U_PLANE_PDB_18BIT_SN_HFN_SHIFT;
2812 pdb.hfn_thr_res =
2813 hfn_threshold<<PDCP_U_PLANE_PDB_18BIT_SN_HFN_THR_SHIFT;
2814
2815 if (rta_sec_era <= RTA_SEC_ERA_8) {
2816 if (cipherdata && authdata)
2817 pdb_type = pdb_mask[cipherdata->algtype]
2818 [authdata->algtype];
2819 }
2820 break;
2821
2822 default:
2823 pr_err("Invalid Sequence Number Size setting in PDB\n");
2824 return -EINVAL;
2825 }
2826
2827 pdb.bearer_dir_res = (uint32_t)
2828 ((bearer << PDCP_U_PLANE_PDB_BEARER_SHIFT) |
2829 (direction << PDCP_U_PLANE_PDB_DIR_SHIFT));
2830
2831 switch (pdb_type) {
2832 case PDCP_PDB_TYPE_NO_PDB:
2833 break;
2834
2835 case PDCP_PDB_TYPE_REDUCED_PDB:
2836 __rta_out32(p, pdb.hfn_res);
2837 __rta_out32(p, pdb.bearer_dir_res);
2838 break;
2839
2840 case PDCP_PDB_TYPE_FULL_PDB:
2841 /* copy PDB in descriptor*/
2842 __rta_out32(p, pdb.opt_res.opt);
2843 __rta_out32(p, pdb.hfn_res);
2844 __rta_out32(p, pdb.bearer_dir_res);
2845 __rta_out32(p, pdb.hfn_thr_res);
2846
2847 break;
2848
2849 default:
2850 return PDCP_PDB_TYPE_INVALID;
2851 }
2852
2853 return pdb_type;
2854 }
2855 /**
2856 * cnstr_shdsc_pdcp_c_plane_encap - Function for creating a PDCP Control Plane
2857 * encapsulation descriptor.
2858 * @descbuf: pointer to buffer for descriptor construction
2859 * @ps: if 36/40bit addressing is desired, this parameter must be true
2860 * @swap: must be true when core endianness doesn't match SEC endianness
2861 * @hfn: starting Hyper Frame Number to be used together with the SN from the
2862 * PDCP frames.
2863 * @sn_size: size of sequence numbers, only 5/12 bit sequence numbers are valid
2864 * @bearer: radio bearer ID
2865 * @direction: the direction of the PDCP frame (UL/DL)
2866 * @hfn_threshold: HFN value that once reached triggers a warning from SEC that
2867 * keys should be renegotiated at the earliest convenience.
2868 * @cipherdata: pointer to block cipher transform definitions
2869 * Valid algorithm values are those from cipher_type_pdcp enum.
2870 * @authdata: pointer to authentication transform definitions
2871 * Valid algorithm values are those from auth_type_pdcp enum.
2872 * @era_2_sw_hfn_ovrd: if software HFN override mechanism is desired for
2873 * this descriptor. Note: Can only be used for
2874 * SEC ERA 2.
2875 * Return: size of descriptor written in words or negative number on error.
2876 * Once the function returns, the value of this parameter can be used
2877 * for reclaiming the space that wasn't used for the descriptor.
2878 *
2879 * Note: descbuf must be large enough to contain a full 256 byte long
2880 * descriptor; after the function returns, by subtracting the actual number of
2881 * bytes used, the user can reuse the remaining buffer space for other purposes.
2882 */
2883 static inline int
cnstr_shdsc_pdcp_c_plane_encap(uint32_t * descbuf,bool ps,bool swap,uint32_t hfn,enum pdcp_sn_size sn_size,unsigned char bearer,unsigned char direction,uint32_t hfn_threshold,struct alginfo * cipherdata,struct alginfo * authdata,unsigned char era_2_sw_hfn_ovrd)2884 cnstr_shdsc_pdcp_c_plane_encap(uint32_t *descbuf,
2885 bool ps,
2886 bool swap,
2887 uint32_t hfn,
2888 enum pdcp_sn_size sn_size,
2889 unsigned char bearer,
2890 unsigned char direction,
2891 uint32_t hfn_threshold,
2892 struct alginfo *cipherdata,
2893 struct alginfo *authdata,
2894 unsigned char era_2_sw_hfn_ovrd)
2895 {
2896 static int
2897 (*pdcp_cp_fp[PDCP_CIPHER_TYPE_INVALID][PDCP_AUTH_TYPE_INVALID])
2898 (struct program*, bool swap, struct alginfo *,
2899 struct alginfo *, unsigned int, enum pdcp_sn_size,
2900 unsigned char __maybe_unused) = {
2901 { /* NULL */
2902 pdcp_insert_cplane_null_op, /* NULL */
2903 pdcp_insert_cplane_int_only_op, /* SNOW f9 */
2904 pdcp_insert_cplane_int_only_op, /* AES CMAC */
2905 pdcp_insert_cplane_int_only_op /* ZUC-I */
2906 },
2907 { /* SNOW f8 */
2908 pdcp_insert_cplane_enc_only_op, /* NULL */
2909 pdcp_insert_cplane_acc_op, /* SNOW f9 */
2910 pdcp_insert_cplane_snow_aes_op, /* AES CMAC */
2911 pdcp_insert_cplane_snow_zuc_op /* ZUC-I */
2912 },
2913 { /* AES CTR */
2914 pdcp_insert_cplane_enc_only_op, /* NULL */
2915 pdcp_insert_cplane_aes_snow_op, /* SNOW f9 */
2916 pdcp_insert_cplane_acc_op, /* AES CMAC */
2917 pdcp_insert_cplane_aes_zuc_op /* ZUC-I */
2918 },
2919 { /* ZUC-E */
2920 pdcp_insert_cplane_enc_only_op, /* NULL */
2921 pdcp_insert_cplane_zuc_snow_op, /* SNOW f9 */
2922 pdcp_insert_cplane_zuc_aes_op, /* AES CMAC */
2923 pdcp_insert_cplane_acc_op /* ZUC-I */
2924 },
2925 };
2926 static enum rta_share_type
2927 desc_share[PDCP_CIPHER_TYPE_INVALID][PDCP_AUTH_TYPE_INVALID] = {
2928 { /* NULL */
2929 SHR_WAIT, /* NULL */
2930 SHR_ALWAYS, /* SNOW f9 */
2931 SHR_ALWAYS, /* AES CMAC */
2932 SHR_ALWAYS /* ZUC-I */
2933 },
2934 { /* SNOW f8 */
2935 SHR_ALWAYS, /* NULL */
2936 SHR_ALWAYS, /* SNOW f9 */
2937 SHR_WAIT, /* AES CMAC */
2938 SHR_WAIT /* ZUC-I */
2939 },
2940 { /* AES CTR */
2941 SHR_ALWAYS, /* NULL */
2942 SHR_ALWAYS, /* SNOW f9 */
2943 SHR_ALWAYS, /* AES CMAC */
2944 SHR_WAIT /* ZUC-I */
2945 },
2946 { /* ZUC-E */
2947 SHR_ALWAYS, /* NULL */
2948 SHR_WAIT, /* SNOW f9 */
2949 SHR_WAIT, /* AES CMAC */
2950 SHR_ALWAYS /* ZUC-I */
2951 },
2952 };
2953 enum pdb_type_e pdb_type;
2954 struct program prg;
2955 struct program *p = &prg;
2956 int err;
2957 LABEL(pdb_end);
2958
2959 if (rta_sec_era != RTA_SEC_ERA_2 && era_2_sw_hfn_ovrd) {
2960 pr_err("Cannot select SW HFN override for other era than 2");
2961 return -EINVAL;
2962 }
2963
2964 if (sn_size != PDCP_SN_SIZE_12 && sn_size != PDCP_SN_SIZE_5) {
2965 pr_err("C-plane supports only 5-bit and 12-bit sequence numbers\n");
2966 return -EINVAL;
2967 }
2968
2969 PROGRAM_CNTXT_INIT(p, descbuf, 0);
2970 if (swap)
2971 PROGRAM_SET_BSWAP(p);
2972 if (ps)
2973 PROGRAM_SET_36BIT_ADDR(p);
2974
2975 SHR_HDR(p, desc_share[cipherdata->algtype][authdata->algtype], 0, 0);
2976
2977 pdb_type = cnstr_pdcp_c_plane_pdb(p,
2978 hfn,
2979 sn_size,
2980 bearer,
2981 direction,
2982 hfn_threshold,
2983 cipherdata,
2984 authdata);
2985
2986 SET_LABEL(p, pdb_end);
2987
2988 err = insert_hfn_ov_op(p, sn_size, pdb_type,
2989 era_2_sw_hfn_ovrd);
2990 if (err)
2991 return err;
2992
2993 err = pdcp_cp_fp[cipherdata->algtype][authdata->algtype](p,
2994 swap,
2995 cipherdata,
2996 authdata,
2997 OP_TYPE_ENCAP_PROTOCOL,
2998 sn_size,
2999 era_2_sw_hfn_ovrd);
3000 if (err)
3001 return err;
3002
3003 PATCH_HDR(p, 0, pdb_end);
3004
3005 return PROGRAM_FINALIZE(p);
3006 }
3007
3008 /**
3009 * cnstr_shdsc_pdcp_c_plane_decap - Function for creating a PDCP Control Plane
3010 * decapsulation descriptor.
3011 * @descbuf: pointer to buffer for descriptor construction
3012 * @ps: if 36/40bit addressing is desired, this parameter must be true
3013 * @swap: must be true when core endianness doesn't match SEC endianness
3014 * @hfn: starting Hyper Frame Number to be used together with the SN from the
3015 * PDCP frames.
3016 * @sn_size: size of sequence numbers, only 5/12 bit sequence numbers are valid
3017 * @bearer: radio bearer ID
3018 * @direction: the direction of the PDCP frame (UL/DL)
3019 * @hfn_threshold: HFN value that once reached triggers a warning from SEC that
3020 * keys should be renegotiated at the earliest convenience.
3021 * @cipherdata: pointer to block cipher transform definitions
3022 * Valid algorithm values are those from cipher_type_pdcp enum.
3023 * @authdata: pointer to authentication transform definitions
3024 * Valid algorithm values are those from auth_type_pdcp enum.
3025 * @era_2_sw_hfn_ovrd: if software HFN override mechanism is desired for
3026 * this descriptor. Note: Can only be used for
3027 * SEC ERA 2.
3028 *
3029 * Return: size of descriptor written in words or negative number on error.
3030 * Once the function returns, the value of this parameter can be used
3031 * for reclaiming the space that wasn't used for the descriptor.
3032 *
3033 * Note: descbuf must be large enough to contain a full 256 byte long
3034 * descriptor; after the function returns, by subtracting the actual number of
3035 * bytes used, the user can reuse the remaining buffer space for other purposes.
3036 */
3037 static inline int
cnstr_shdsc_pdcp_c_plane_decap(uint32_t * descbuf,bool ps,bool swap,uint32_t hfn,enum pdcp_sn_size sn_size,unsigned char bearer,unsigned char direction,uint32_t hfn_threshold,struct alginfo * cipherdata,struct alginfo * authdata,unsigned char era_2_sw_hfn_ovrd)3038 cnstr_shdsc_pdcp_c_plane_decap(uint32_t *descbuf,
3039 bool ps,
3040 bool swap,
3041 uint32_t hfn,
3042 enum pdcp_sn_size sn_size,
3043 unsigned char bearer,
3044 unsigned char direction,
3045 uint32_t hfn_threshold,
3046 struct alginfo *cipherdata,
3047 struct alginfo *authdata,
3048 unsigned char era_2_sw_hfn_ovrd)
3049 {
3050 static int
3051 (*pdcp_cp_fp[PDCP_CIPHER_TYPE_INVALID][PDCP_AUTH_TYPE_INVALID])
3052 (struct program*, bool swap, struct alginfo *,
3053 struct alginfo *, unsigned int, enum pdcp_sn_size,
3054 unsigned char) = {
3055 { /* NULL */
3056 pdcp_insert_cplane_null_op, /* NULL */
3057 pdcp_insert_cplane_int_only_op, /* SNOW f9 */
3058 pdcp_insert_cplane_int_only_op, /* AES CMAC */
3059 pdcp_insert_cplane_int_only_op /* ZUC-I */
3060 },
3061 { /* SNOW f8 */
3062 pdcp_insert_cplane_enc_only_op, /* NULL */
3063 pdcp_insert_cplane_acc_op, /* SNOW f9 */
3064 pdcp_insert_cplane_snow_aes_op, /* AES CMAC */
3065 pdcp_insert_cplane_snow_zuc_op /* ZUC-I */
3066 },
3067 { /* AES CTR */
3068 pdcp_insert_cplane_enc_only_op, /* NULL */
3069 pdcp_insert_cplane_aes_snow_op, /* SNOW f9 */
3070 pdcp_insert_cplane_acc_op, /* AES CMAC */
3071 pdcp_insert_cplane_aes_zuc_op /* ZUC-I */
3072 },
3073 { /* ZUC-E */
3074 pdcp_insert_cplane_enc_only_op, /* NULL */
3075 pdcp_insert_cplane_zuc_snow_op, /* SNOW f9 */
3076 pdcp_insert_cplane_zuc_aes_op, /* AES CMAC */
3077 pdcp_insert_cplane_acc_op /* ZUC-I */
3078 },
3079 };
3080 static enum rta_share_type
3081 desc_share[PDCP_CIPHER_TYPE_INVALID][PDCP_AUTH_TYPE_INVALID] = {
3082 { /* NULL */
3083 SHR_WAIT, /* NULL */
3084 SHR_ALWAYS, /* SNOW f9 */
3085 SHR_ALWAYS, /* AES CMAC */
3086 SHR_ALWAYS /* ZUC-I */
3087 },
3088 { /* SNOW f8 */
3089 SHR_ALWAYS, /* NULL */
3090 SHR_ALWAYS, /* SNOW f9 */
3091 SHR_WAIT, /* AES CMAC */
3092 SHR_WAIT /* ZUC-I */
3093 },
3094 { /* AES CTR */
3095 SHR_ALWAYS, /* NULL */
3096 SHR_ALWAYS, /* SNOW f9 */
3097 SHR_ALWAYS, /* AES CMAC */
3098 SHR_WAIT /* ZUC-I */
3099 },
3100 { /* ZUC-E */
3101 SHR_ALWAYS, /* NULL */
3102 SHR_WAIT, /* SNOW f9 */
3103 SHR_WAIT, /* AES CMAC */
3104 SHR_ALWAYS /* ZUC-I */
3105 },
3106 };
3107 enum pdb_type_e pdb_type;
3108 struct program prg;
3109 struct program *p = &prg;
3110 int err;
3111 LABEL(pdb_end);
3112
3113 if (rta_sec_era != RTA_SEC_ERA_2 && era_2_sw_hfn_ovrd) {
3114 pr_err("Cannot select SW HFN override for other era than 2");
3115 return -EINVAL;
3116 }
3117
3118 if (sn_size != PDCP_SN_SIZE_12 && sn_size != PDCP_SN_SIZE_5) {
3119 pr_err("C-plane supports only 5-bit and 12-bit sequence numbers\n");
3120 return -EINVAL;
3121 }
3122
3123 PROGRAM_CNTXT_INIT(p, descbuf, 0);
3124 if (swap)
3125 PROGRAM_SET_BSWAP(p);
3126 if (ps)
3127 PROGRAM_SET_36BIT_ADDR(p);
3128
3129 SHR_HDR(p, desc_share[cipherdata->algtype][authdata->algtype], 0, 0);
3130
3131 pdb_type = cnstr_pdcp_c_plane_pdb(p,
3132 hfn,
3133 sn_size,
3134 bearer,
3135 direction,
3136 hfn_threshold,
3137 cipherdata,
3138 authdata);
3139
3140 SET_LABEL(p, pdb_end);
3141
3142 err = insert_hfn_ov_op(p, sn_size, pdb_type,
3143 era_2_sw_hfn_ovrd);
3144 if (err)
3145 return err;
3146
3147 err = pdcp_cp_fp[cipherdata->algtype][authdata->algtype](p,
3148 swap,
3149 cipherdata,
3150 authdata,
3151 OP_TYPE_DECAP_PROTOCOL,
3152 sn_size,
3153 era_2_sw_hfn_ovrd);
3154 if (err)
3155 return err;
3156
3157 PATCH_HDR(p, 0, pdb_end);
3158
3159 return PROGRAM_FINALIZE(p);
3160 }
3161
3162 static int
pdcp_insert_uplane_with_int_op(struct program * p,bool swap __maybe_unused,struct alginfo * cipherdata,struct alginfo * authdata,enum pdcp_sn_size sn_size,unsigned char era_2_sw_hfn_ovrd,unsigned int dir)3163 pdcp_insert_uplane_with_int_op(struct program *p,
3164 bool swap __maybe_unused,
3165 struct alginfo *cipherdata,
3166 struct alginfo *authdata,
3167 enum pdcp_sn_size sn_size,
3168 unsigned char era_2_sw_hfn_ovrd,
3169 unsigned int dir)
3170 {
3171 static int
3172 (*pdcp_cp_fp[PDCP_CIPHER_TYPE_INVALID][PDCP_AUTH_TYPE_INVALID])
3173 (struct program*, bool swap, struct alginfo *,
3174 struct alginfo *, unsigned int, enum pdcp_sn_size,
3175 unsigned char __maybe_unused) = {
3176 { /* NULL */
3177 pdcp_insert_cplane_null_op, /* NULL */
3178 pdcp_insert_cplane_int_only_op, /* SNOW f9 */
3179 pdcp_insert_cplane_int_only_op, /* AES CMAC */
3180 pdcp_insert_cplane_int_only_op /* ZUC-I */
3181 },
3182 { /* SNOW f8 */
3183 pdcp_insert_cplane_enc_only_op, /* NULL */
3184 pdcp_insert_uplane_snow_snow_op, /* SNOW f9 */
3185 pdcp_insert_cplane_snow_aes_op, /* AES CMAC */
3186 pdcp_insert_cplane_snow_zuc_op /* ZUC-I */
3187 },
3188 { /* AES CTR */
3189 pdcp_insert_cplane_enc_only_op, /* NULL */
3190 pdcp_insert_cplane_aes_snow_op, /* SNOW f9 */
3191 pdcp_insert_uplane_aes_aes_op, /* AES CMAC */
3192 pdcp_insert_cplane_aes_zuc_op /* ZUC-I */
3193 },
3194 { /* ZUC-E */
3195 pdcp_insert_cplane_enc_only_op, /* NULL */
3196 pdcp_insert_cplane_zuc_snow_op, /* SNOW f9 */
3197 pdcp_insert_cplane_zuc_aes_op, /* AES CMAC */
3198 pdcp_insert_uplane_zuc_zuc_op /* ZUC-I */
3199 },
3200 };
3201 int err;
3202
3203 err = pdcp_cp_fp[cipherdata->algtype][authdata->algtype](p,
3204 swap,
3205 cipherdata,
3206 authdata,
3207 dir,
3208 sn_size,
3209 era_2_sw_hfn_ovrd);
3210 if (err)
3211 return err;
3212
3213 return 0;
3214 }
3215
3216
3217 /**
3218 * cnstr_shdsc_pdcp_u_plane_encap - Function for creating a PDCP User Plane
3219 * encapsulation descriptor.
3220 * @descbuf: pointer to buffer for descriptor construction
3221 * @ps: if 36/40bit addressing is desired, this parameter must be true
3222 * @swap: must be true when core endianness doesn't match SEC endianness
3223 * @sn_size: selects Sequence Number Size: 7/12/15 bits
3224 * @hfn: starting Hyper Frame Number to be used together with the SN from the
3225 * PDCP frames.
3226 * @bearer: radio bearer ID
3227 * @direction: the direction of the PDCP frame (UL/DL)
3228 * @hfn_threshold: HFN value that once reached triggers a warning from SEC that
3229 * keys should be renegotiated at the earliest convenience.
3230 * @cipherdata: pointer to block cipher transform definitions
3231 * Valid algorithm values are those from cipher_type_pdcp enum.
3232 * @era_2_sw_hfn_ovrd: if software HFN override mechanism is desired for
3233 * this descriptor. Note: Can only be used for
3234 * SEC ERA 2.
3235 *
3236 * Return: size of descriptor written in words or negative number on error.
3237 * Once the function returns, the value of this parameter can be used
3238 * for reclaiming the space that wasn't used for the descriptor.
3239 *
3240 * Note: descbuf must be large enough to contain a full 256 byte long
3241 * descriptor; after the function returns, by subtracting the actual number of
3242 * bytes used, the user can reuse the remaining buffer space for other purposes.
3243 */
3244 static inline int
cnstr_shdsc_pdcp_u_plane_encap(uint32_t * descbuf,bool ps,bool swap,enum pdcp_sn_size sn_size,uint32_t hfn,unsigned short bearer,unsigned short direction,uint32_t hfn_threshold,struct alginfo * cipherdata,struct alginfo * authdata,unsigned char era_2_sw_hfn_ovrd)3245 cnstr_shdsc_pdcp_u_plane_encap(uint32_t *descbuf,
3246 bool ps,
3247 bool swap,
3248 enum pdcp_sn_size sn_size,
3249 uint32_t hfn,
3250 unsigned short bearer,
3251 unsigned short direction,
3252 uint32_t hfn_threshold,
3253 struct alginfo *cipherdata,
3254 struct alginfo *authdata,
3255 unsigned char era_2_sw_hfn_ovrd)
3256 {
3257 struct program prg;
3258 struct program *p = &prg;
3259 int err;
3260 enum pdb_type_e pdb_type;
3261 static enum rta_share_type
3262 desc_share[PDCP_CIPHER_TYPE_INVALID][PDCP_AUTH_TYPE_INVALID] = {
3263 { /* NULL */
3264 SHR_WAIT, /* NULL */
3265 SHR_ALWAYS, /* SNOW f9 */
3266 SHR_ALWAYS, /* AES CMAC */
3267 SHR_ALWAYS /* ZUC-I */
3268 },
3269 { /* SNOW f8 */
3270 SHR_ALWAYS, /* NULL */
3271 SHR_ALWAYS, /* SNOW f9 */
3272 SHR_WAIT, /* AES CMAC */
3273 SHR_WAIT /* ZUC-I */
3274 },
3275 { /* AES CTR */
3276 SHR_ALWAYS, /* NULL */
3277 SHR_ALWAYS, /* SNOW f9 */
3278 SHR_ALWAYS, /* AES CMAC */
3279 SHR_WAIT /* ZUC-I */
3280 },
3281 { /* ZUC-E */
3282 SHR_ALWAYS, /* NULL */
3283 SHR_WAIT, /* SNOW f9 */
3284 SHR_WAIT, /* AES CMAC */
3285 SHR_ALWAYS /* ZUC-I */
3286 },
3287 };
3288 LABEL(pdb_end);
3289
3290 if (rta_sec_era != RTA_SEC_ERA_2 && era_2_sw_hfn_ovrd) {
3291 pr_err("Cannot select SW HFN ovrd for other era than 2");
3292 return -EINVAL;
3293 }
3294
3295 if (authdata && !authdata->algtype && rta_sec_era < RTA_SEC_ERA_8) {
3296 pr_err("Cannot use u-plane auth with era < 8");
3297 return -EINVAL;
3298 }
3299
3300 PROGRAM_CNTXT_INIT(p, descbuf, 0);
3301 if (swap)
3302 PROGRAM_SET_BSWAP(p);
3303 if (ps)
3304 PROGRAM_SET_36BIT_ADDR(p);
3305
3306 if (authdata)
3307 SHR_HDR(p, desc_share[cipherdata->algtype][authdata->algtype], 0, 0);
3308 else
3309 SHR_HDR(p, SHR_ALWAYS, 0, 0);
3310 pdb_type = cnstr_pdcp_u_plane_pdb(p, sn_size, hfn,
3311 bearer, direction, hfn_threshold,
3312 cipherdata, authdata);
3313 if (pdb_type == PDCP_PDB_TYPE_INVALID) {
3314 pr_err("Error creating PDCP UPlane PDB\n");
3315 return -EINVAL;
3316 }
3317 SET_LABEL(p, pdb_end);
3318
3319 err = insert_hfn_ov_op(p, sn_size, pdb_type, era_2_sw_hfn_ovrd);
3320 if (err)
3321 return err;
3322
3323 switch (sn_size) {
3324 case PDCP_SN_SIZE_7:
3325 case PDCP_SN_SIZE_12:
3326 switch (cipherdata->algtype) {
3327 case PDCP_CIPHER_TYPE_ZUC:
3328 if (rta_sec_era < RTA_SEC_ERA_5) {
3329 pr_err("Invalid era for selected algorithm\n");
3330 return -ENOTSUP;
3331 }
3332 /* fallthrough */
3333 case PDCP_CIPHER_TYPE_AES:
3334 case PDCP_CIPHER_TYPE_SNOW:
3335 case PDCP_CIPHER_TYPE_NULL:
3336 if (rta_sec_era == RTA_SEC_ERA_8 &&
3337 authdata && authdata->algtype == 0){
3338 err = pdcp_insert_uplane_with_int_op(p, swap,
3339 cipherdata, authdata,
3340 sn_size, era_2_sw_hfn_ovrd,
3341 OP_TYPE_ENCAP_PROTOCOL);
3342 if (err)
3343 return err;
3344 break;
3345 }
3346
3347 if (pdb_type != PDCP_PDB_TYPE_FULL_PDB) {
3348 pr_err("PDB type must be FULL for PROTO desc\n");
3349 return -EINVAL;
3350 }
3351
3352 /* Insert auth key if requested */
3353 if (authdata && authdata->algtype) {
3354 KEY(p, KEY2, authdata->key_enc_flags,
3355 (uint64_t)authdata->key, authdata->keylen,
3356 INLINE_KEY(authdata));
3357 }
3358 /* Insert Cipher Key */
3359 KEY(p, KEY1, cipherdata->key_enc_flags,
3360 (uint64_t)cipherdata->key, cipherdata->keylen,
3361 INLINE_KEY(cipherdata));
3362
3363 if (authdata)
3364 PROTOCOL(p, OP_TYPE_ENCAP_PROTOCOL,
3365 OP_PCLID_LTE_PDCP_USER_RN,
3366 ((uint16_t)cipherdata->algtype << 8) |
3367 (uint16_t)authdata->algtype);
3368 else
3369 PROTOCOL(p, OP_TYPE_ENCAP_PROTOCOL,
3370 OP_PCLID_LTE_PDCP_USER,
3371 (uint16_t)cipherdata->algtype);
3372 break;
3373 default:
3374 pr_err("%s: Invalid encrypt algorithm selected: %d\n",
3375 "cnstr_pcl_shdsc_pdcp_u_plane_decap",
3376 cipherdata->algtype);
3377 return -EINVAL;
3378 }
3379 break;
3380
3381 case PDCP_SN_SIZE_15:
3382 case PDCP_SN_SIZE_18:
3383 if (authdata) {
3384 err = pdcp_insert_uplane_with_int_op(p, swap,
3385 cipherdata, authdata,
3386 sn_size, era_2_sw_hfn_ovrd,
3387 OP_TYPE_ENCAP_PROTOCOL);
3388 if (err)
3389 return err;
3390
3391 break;
3392 }
3393
3394 switch (cipherdata->algtype) {
3395 case PDCP_CIPHER_TYPE_NULL:
3396 insert_copy_frame_op(p,
3397 cipherdata,
3398 OP_TYPE_ENCAP_PROTOCOL);
3399 break;
3400
3401 default:
3402 err = pdcp_insert_uplane_no_int_op(p, swap, cipherdata,
3403 OP_TYPE_ENCAP_PROTOCOL, sn_size);
3404 if (err)
3405 return err;
3406 break;
3407 }
3408 break;
3409
3410 case PDCP_SN_SIZE_5:
3411 default:
3412 pr_err("Invalid SN size selected\n");
3413 return -ENOTSUP;
3414 }
3415
3416 PATCH_HDR(p, 0, pdb_end);
3417 return PROGRAM_FINALIZE(p);
3418 }
3419
3420 /**
3421 * cnstr_shdsc_pdcp_u_plane_decap - Function for creating a PDCP User Plane
3422 * decapsulation descriptor.
3423 * @descbuf: pointer to buffer for descriptor construction
3424 * @ps: if 36/40bit addressing is desired, this parameter must be true
3425 * @swap: must be true when core endianness doesn't match SEC endianness
3426 * @sn_size: selects Sequence Number Size: 7/12/15 bits
3427 * @hfn: starting Hyper Frame Number to be used together with the SN from the
3428 * PDCP frames.
3429 * @bearer: radio bearer ID
3430 * @direction: the direction of the PDCP frame (UL/DL)
3431 * @hfn_threshold: HFN value that once reached triggers a warning from SEC that
3432 * keys should be renegotiated at the earliest convenience.
3433 * @cipherdata: pointer to block cipher transform definitions
3434 * Valid algorithm values are those from cipher_type_pdcp enum.
3435 * @era_2_sw_hfn_ovrd: if software HFN override mechanism is desired for
3436 * this descriptor. Note: Can only be used for
3437 * SEC ERA 2.
3438 *
3439 * Return: size of descriptor written in words or negative number on error.
3440 * Once the function returns, the value of this parameter can be used
3441 * for reclaiming the space that wasn't used for the descriptor.
3442 *
3443 * Note: descbuf must be large enough to contain a full 256 byte long
3444 * descriptor; after the function returns, by subtracting the actual number of
3445 * bytes used, the user can reuse the remaining buffer space for other purposes.
3446 */
3447 static inline int
cnstr_shdsc_pdcp_u_plane_decap(uint32_t * descbuf,bool ps,bool swap,enum pdcp_sn_size sn_size,uint32_t hfn,unsigned short bearer,unsigned short direction,uint32_t hfn_threshold,struct alginfo * cipherdata,struct alginfo * authdata,unsigned char era_2_sw_hfn_ovrd)3448 cnstr_shdsc_pdcp_u_plane_decap(uint32_t *descbuf,
3449 bool ps,
3450 bool swap,
3451 enum pdcp_sn_size sn_size,
3452 uint32_t hfn,
3453 unsigned short bearer,
3454 unsigned short direction,
3455 uint32_t hfn_threshold,
3456 struct alginfo *cipherdata,
3457 struct alginfo *authdata,
3458 unsigned char era_2_sw_hfn_ovrd)
3459 {
3460 struct program prg;
3461 struct program *p = &prg;
3462 int err;
3463 enum pdb_type_e pdb_type;
3464 static enum rta_share_type
3465 desc_share[PDCP_CIPHER_TYPE_INVALID][PDCP_AUTH_TYPE_INVALID] = {
3466 { /* NULL */
3467 SHR_WAIT, /* NULL */
3468 SHR_ALWAYS, /* SNOW f9 */
3469 SHR_ALWAYS, /* AES CMAC */
3470 SHR_ALWAYS /* ZUC-I */
3471 },
3472 { /* SNOW f8 */
3473 SHR_ALWAYS, /* NULL */
3474 SHR_ALWAYS, /* SNOW f9 */
3475 SHR_WAIT, /* AES CMAC */
3476 SHR_WAIT /* ZUC-I */
3477 },
3478 { /* AES CTR */
3479 SHR_ALWAYS, /* NULL */
3480 SHR_ALWAYS, /* SNOW f9 */
3481 SHR_ALWAYS, /* AES CMAC */
3482 SHR_WAIT /* ZUC-I */
3483 },
3484 { /* ZUC-E */
3485 SHR_ALWAYS, /* NULL */
3486 SHR_WAIT, /* SNOW f9 */
3487 SHR_WAIT, /* AES CMAC */
3488 SHR_ALWAYS /* ZUC-I */
3489 },
3490 };
3491
3492 LABEL(pdb_end);
3493
3494 if (rta_sec_era != RTA_SEC_ERA_2 && era_2_sw_hfn_ovrd) {
3495 pr_err("Cannot select SW HFN override for other era than 2");
3496 return -EINVAL;
3497 }
3498
3499 if (authdata && !authdata->algtype && rta_sec_era < RTA_SEC_ERA_8) {
3500 pr_err("Cannot use u-plane auth with era < 8");
3501 return -EINVAL;
3502 }
3503
3504 PROGRAM_CNTXT_INIT(p, descbuf, 0);
3505 if (swap)
3506 PROGRAM_SET_BSWAP(p);
3507 if (ps)
3508 PROGRAM_SET_36BIT_ADDR(p);
3509 if (authdata)
3510 SHR_HDR(p, desc_share[cipherdata->algtype][authdata->algtype], 0, 0);
3511 else
3512 SHR_HDR(p, SHR_ALWAYS, 0, 0);
3513
3514 pdb_type = cnstr_pdcp_u_plane_pdb(p, sn_size, hfn, bearer,
3515 direction, hfn_threshold,
3516 cipherdata, authdata);
3517 if (pdb_type == PDCP_PDB_TYPE_INVALID) {
3518 pr_err("Error creating PDCP UPlane PDB\n");
3519 return -EINVAL;
3520 }
3521 SET_LABEL(p, pdb_end);
3522
3523 err = insert_hfn_ov_op(p, sn_size, pdb_type, era_2_sw_hfn_ovrd);
3524 if (err)
3525 return err;
3526
3527 switch (sn_size) {
3528 case PDCP_SN_SIZE_7:
3529 case PDCP_SN_SIZE_12:
3530 switch (cipherdata->algtype) {
3531 case PDCP_CIPHER_TYPE_ZUC:
3532 if (rta_sec_era < RTA_SEC_ERA_5) {
3533 pr_err("Invalid era for selected algorithm\n");
3534 return -ENOTSUP;
3535 }
3536 /* fallthrough */
3537 case PDCP_CIPHER_TYPE_AES:
3538 case PDCP_CIPHER_TYPE_SNOW:
3539 case PDCP_CIPHER_TYPE_NULL:
3540 if (pdb_type != PDCP_PDB_TYPE_FULL_PDB) {
3541 pr_err("PDB type must be FULL for PROTO desc\n");
3542 return -EINVAL;
3543 }
3544
3545 /* Insert auth key if requested */
3546 if (authdata && authdata->algtype)
3547 KEY(p, KEY2, authdata->key_enc_flags,
3548 (uint64_t)authdata->key, authdata->keylen,
3549 INLINE_KEY(authdata));
3550 else if (authdata && authdata->algtype == 0) {
3551 err = pdcp_insert_uplane_with_int_op(p, swap,
3552 cipherdata, authdata,
3553 sn_size, era_2_sw_hfn_ovrd,
3554 OP_TYPE_DECAP_PROTOCOL);
3555 if (err)
3556 return err;
3557 break;
3558 }
3559
3560 /* Insert Cipher Key */
3561 KEY(p, KEY1, cipherdata->key_enc_flags,
3562 cipherdata->key, cipherdata->keylen,
3563 INLINE_KEY(cipherdata));
3564 if (authdata)
3565 PROTOCOL(p, OP_TYPE_DECAP_PROTOCOL,
3566 OP_PCLID_LTE_PDCP_USER_RN,
3567 ((uint16_t)cipherdata->algtype << 8) |
3568 (uint16_t)authdata->algtype);
3569 else
3570 PROTOCOL(p, OP_TYPE_DECAP_PROTOCOL,
3571 OP_PCLID_LTE_PDCP_USER,
3572 (uint16_t)cipherdata->algtype);
3573 break;
3574 default:
3575 pr_err("%s: Invalid encrypt algorithm selected: %d\n",
3576 "cnstr_pcl_shdsc_pdcp_u_plane_decap",
3577 cipherdata->algtype);
3578 return -EINVAL;
3579 }
3580 break;
3581
3582 case PDCP_SN_SIZE_15:
3583 case PDCP_SN_SIZE_18:
3584 if (authdata) {
3585 err = pdcp_insert_uplane_with_int_op(p, swap,
3586 cipherdata, authdata,
3587 sn_size, era_2_sw_hfn_ovrd,
3588 OP_TYPE_DECAP_PROTOCOL);
3589 if (err)
3590 return err;
3591
3592 break;
3593 }
3594
3595 switch (cipherdata->algtype) {
3596 case PDCP_CIPHER_TYPE_NULL:
3597 insert_copy_frame_op(p,
3598 cipherdata,
3599 OP_TYPE_DECAP_PROTOCOL);
3600 break;
3601
3602 default:
3603 err = pdcp_insert_uplane_no_int_op(p, swap, cipherdata,
3604 OP_TYPE_DECAP_PROTOCOL, sn_size);
3605 if (err)
3606 return err;
3607 break;
3608 }
3609 break;
3610
3611 case PDCP_SN_SIZE_5:
3612 default:
3613 pr_err("Invalid SN size selected\n");
3614 return -ENOTSUP;
3615 }
3616
3617 PATCH_HDR(p, 0, pdb_end);
3618 return PROGRAM_FINALIZE(p);
3619 }
3620
3621 /**
3622 * cnstr_shdsc_pdcp_short_mac - Function for creating a PDCP Short MAC
3623 * descriptor.
3624 * @descbuf: pointer to buffer for descriptor construction
3625 * @ps: if 36/40bit addressing is desired, this parameter must be true
3626 * @swap: must be true when core endianness doesn't match SEC endianness
3627 * @authdata: pointer to authentication transform definitions
3628 * Valid algorithm values are those from auth_type_pdcp enum.
3629 *
3630 * Return: size of descriptor written in words or negative number on error.
3631 * Once the function returns, the value of this parameter can be used
3632 * for reclaiming the space that wasn't used for the descriptor.
3633 *
3634 * Note: descbuf must be large enough to contain a full 256 byte long
3635 * descriptor; after the function returns, by subtracting the actual number of
3636 * bytes used, the user can reuse the remaining buffer space for other purposes.
3637 */
3638 static inline int
cnstr_shdsc_pdcp_short_mac(uint32_t * descbuf,bool ps,bool swap,struct alginfo * authdata)3639 cnstr_shdsc_pdcp_short_mac(uint32_t *descbuf,
3640 bool ps,
3641 bool swap,
3642 struct alginfo *authdata)
3643 {
3644 struct program prg;
3645 struct program *p = &prg;
3646 uint32_t iv[3] = {0, 0, 0};
3647 LABEL(local_offset);
3648 REFERENCE(move_cmd_read_descbuf);
3649 REFERENCE(move_cmd_write_descbuf);
3650
3651 PROGRAM_CNTXT_INIT(p, descbuf, 0);
3652 if (swap)
3653 PROGRAM_SET_BSWAP(p);
3654 if (ps)
3655 PROGRAM_SET_36BIT_ADDR(p);
3656
3657 SHR_HDR(p, SHR_ALWAYS, 1, 0);
3658
3659 if (rta_sec_era > RTA_SEC_ERA_2) {
3660 MATHB(p, SEQINSZ, SUB, ZERO, VSEQINSZ, 4, 0);
3661 MATHB(p, SEQINSZ, SUB, ZERO, MATH1, 4, 0);
3662 } else {
3663 MATHB(p, SEQINSZ, ADD, ONE, MATH1, 4, 0);
3664 MATHB(p, MATH1, SUB, ONE, MATH1, 4, 0);
3665 MATHB(p, ZERO, ADD, MATH1, VSEQINSZ, 4, 0);
3666 MOVE(p, MATH1, 0, MATH0, 0, 8, IMMED);
3667
3668 /*
3669 * Since MOVELEN is available only starting with
3670 * SEC ERA 3, use poor man's MOVELEN: create a MOVE
3671 * command dynamically by writing the length from M1 by
3672 * OR-ing the command in the M1 register and MOVE the
3673 * result into the descriptor buffer. Care must be taken
3674 * wrt. the location of the command because of SEC
3675 * pipelining. The actual MOVEs are written at the end
3676 * of the descriptor due to calculations needed on the
3677 * offset in the descriptor for the MOVE command.
3678 */
3679 move_cmd_read_descbuf = MOVE(p, DESCBUF, 0, MATH0, 0, 6,
3680 IMMED);
3681 move_cmd_write_descbuf = MOVE(p, MATH0, 0, DESCBUF, 0, 8,
3682 WAITCOMP | IMMED);
3683 }
3684 MATHB(p, ZERO, ADD, MATH1, VSEQOUTSZ, 4, 0);
3685
3686 switch (authdata->algtype) {
3687 case PDCP_AUTH_TYPE_NULL:
3688 SEQFIFOSTORE(p, MSG, 0, 0, VLF);
3689 if (rta_sec_era > RTA_SEC_ERA_2) {
3690 MOVE(p, AB1, 0, OFIFO, 0, MATH1, 0);
3691 } else {
3692 SET_LABEL(p, local_offset);
3693
3694 /* Shut off automatic Info FIFO entries */
3695 LOAD(p, 0, DCTRL, LDOFF_DISABLE_AUTO_NFIFO, 0, IMMED);
3696
3697 /* Placeholder for MOVE command with length from M1
3698 * register
3699 */
3700 MOVE(p, IFIFOAB1, 0, OFIFO, 0, 0, IMMED);
3701
3702 /* Enable automatic Info FIFO entries */
3703 LOAD(p, 0, DCTRL, LDOFF_ENABLE_AUTO_NFIFO, 0, IMMED);
3704 }
3705
3706 LOAD(p, (uintptr_t)iv, MATH0, 0, 8, IMMED | COPY);
3707 SEQFIFOLOAD(p, MSG1, 0, VLF | LAST1 | LAST2 | FLUSH1);
3708 SEQSTORE(p, MATH0, 0, 4, 0);
3709
3710 break;
3711
3712 case PDCP_AUTH_TYPE_SNOW:
3713 iv[0] = 0xFFFFFFFF;
3714 iv[1] = swap ? swab32(0x04000000) : 0x04000000;
3715 iv[2] = swap ? swab32(0xF8000000) : 0xF8000000;
3716
3717 KEY(p, KEY2, authdata->key_enc_flags, authdata->key,
3718 authdata->keylen, INLINE_KEY(authdata));
3719 LOAD(p, (uintptr_t)&iv, CONTEXT2, 0, 12, IMMED | COPY);
3720 ALG_OPERATION(p, OP_ALG_ALGSEL_SNOW_F9,
3721 OP_ALG_AAI_F9,
3722 OP_ALG_AS_INITFINAL,
3723 ICV_CHECK_DISABLE,
3724 DIR_ENC);
3725 SEQFIFOSTORE(p, MSG, 0, 0, VLF);
3726
3727 if (rta_sec_era > RTA_SEC_ERA_2) {
3728 MOVE(p, AB1, 0, OFIFO, 0, MATH1, 0);
3729 } else {
3730 SET_LABEL(p, local_offset);
3731
3732
3733 /* Shut off automatic Info FIFO entries */
3734 LOAD(p, 0, DCTRL, LDOFF_DISABLE_AUTO_NFIFO, 0, IMMED);
3735
3736 /* Placeholder for MOVE command with length from M1
3737 * register
3738 */
3739 MOVE(p, IFIFOAB1, 0, OFIFO, 0, 0, IMMED);
3740
3741 /* Enable automatic Info FIFO entries */
3742 LOAD(p, 0, DCTRL, LDOFF_ENABLE_AUTO_NFIFO, 0, IMMED);
3743 }
3744 SEQFIFOLOAD(p, MSGINSNOOP, 0, VLF | LAST1 | LAST2 | FLUSH1);
3745 SEQSTORE(p, CONTEXT2, 0, 4, 0);
3746
3747 break;
3748
3749 case PDCP_AUTH_TYPE_AES:
3750 iv[0] = 0xFFFFFFFF;
3751 iv[1] = swap ? swab32(0xFC000000) : 0xFC000000;
3752 iv[2] = 0x00000000; /* unused */
3753
3754 KEY(p, KEY1, authdata->key_enc_flags, authdata->key,
3755 authdata->keylen, INLINE_KEY(authdata));
3756 LOAD(p, (uintptr_t)&iv, MATH0, 0, 8, IMMED | COPY);
3757 MOVE(p, MATH0, 0, IFIFOAB1, 0, 8, IMMED);
3758 ALG_OPERATION(p, OP_ALG_ALGSEL_AES,
3759 OP_ALG_AAI_CMAC,
3760 OP_ALG_AS_INITFINAL,
3761 ICV_CHECK_DISABLE,
3762 DIR_ENC);
3763 SEQFIFOSTORE(p, MSG, 0, 0, VLF);
3764
3765 if (rta_sec_era > RTA_SEC_ERA_2) {
3766 MOVE(p, AB2, 0, OFIFO, 0, MATH1, 0);
3767 } else {
3768 SET_LABEL(p, local_offset);
3769
3770 /* Shut off automatic Info FIFO entries */
3771 LOAD(p, 0, DCTRL, LDOFF_DISABLE_AUTO_NFIFO, 0, IMMED);
3772
3773 /* Placeholder for MOVE command with length from M1
3774 * register
3775 */
3776 MOVE(p, IFIFOAB2, 0, OFIFO, 0, 0, IMMED);
3777
3778 /* Enable automatic Info FIFO entries */
3779 LOAD(p, 0, DCTRL, LDOFF_ENABLE_AUTO_NFIFO, 0, IMMED);
3780 }
3781 SEQFIFOLOAD(p, MSGINSNOOP, 0, VLF | LAST1 | LAST2 | FLUSH1);
3782 SEQSTORE(p, CONTEXT1, 0, 4, 0);
3783
3784 break;
3785
3786 case PDCP_AUTH_TYPE_ZUC:
3787 if (rta_sec_era < RTA_SEC_ERA_5) {
3788 pr_err("Invalid era for selected algorithm\n");
3789 return -ENOTSUP;
3790 }
3791 iv[0] = 0xFFFFFFFF;
3792 iv[1] = swap ? swab32(0xFC000000) : 0xFC000000;
3793 iv[2] = 0x00000000; /* unused */
3794
3795 KEY(p, KEY2, authdata->key_enc_flags, authdata->key,
3796 authdata->keylen, INLINE_KEY(authdata));
3797 LOAD(p, (uintptr_t)&iv, CONTEXT2, 0, 12, IMMED | COPY);
3798 ALG_OPERATION(p, OP_ALG_ALGSEL_ZUCA,
3799 OP_ALG_AAI_F9,
3800 OP_ALG_AS_INITFINAL,
3801 ICV_CHECK_DISABLE,
3802 DIR_ENC);
3803 SEQFIFOSTORE(p, MSG, 0, 0, VLF);
3804 MOVE(p, AB1, 0, OFIFO, 0, MATH1, 0);
3805 SEQFIFOLOAD(p, MSGINSNOOP, 0, VLF | LAST1 | LAST2 | FLUSH1);
3806 SEQSTORE(p, CONTEXT2, 0, 4, 0);
3807
3808 break;
3809
3810 default:
3811 pr_err("%s: Invalid integrity algorithm selected: %d\n",
3812 "cnstr_shdsc_pdcp_short_mac", authdata->algtype);
3813 return -EINVAL;
3814 }
3815
3816
3817 if (rta_sec_era < RTA_SEC_ERA_3) {
3818 PATCH_MOVE(p, move_cmd_read_descbuf, local_offset);
3819 PATCH_MOVE(p, move_cmd_write_descbuf, local_offset);
3820 }
3821
3822 return PROGRAM_FINALIZE(p);
3823 }
3824
3825 #endif /* __DESC_PDCP_H__ */
3826