1 /* SPDX-License-Identifier: BSD-3-Clause or GPL-2.0+
2 * Copyright 2008-2013 Freescale Semiconductor, Inc.
6 #ifndef __DESC_PDCP_H__
7 #define __DESC_PDCP_H__
13 * DOC: PDCP Shared Descriptor Constructors
15 * Shared descriptors for PDCP protocol.
19 * PDCP_NULL_MAX_FRAME_LEN - The maximum frame frame length that is supported by
22 #define PDCP_NULL_MAX_FRAME_LEN 0x00002FFF
25 * PDCP_MAC_I_LEN - The length of the MAC-I for PDCP protocol operation
27 #define PDCP_MAC_I_LEN 0x00000004
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.
34 #define PDCP_MAX_FRAME_LEN_STATUS 0xF1
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
43 #define PDCP_C_PLANE_SN_MASK 0x1F000000
44 #define PDCP_C_PLANE_SN_MASK_BE 0x0000001F
47 * PDCP_12BIT_SN_MASK - This mask is used in the PDCP descriptors for
48 * extracting the sequence number (SN) from the
49 * PDCP User Plane header.
51 #define PDCP_12BIT_SN_MASK 0xFF0F0000
52 #define PDCP_12BIT_SN_MASK_BE 0x00000FFF
55 * PDCP_U_PLANE_15BIT_SN_MASK - This mask is used in the PDCP descriptors for
56 * extracting the sequence number (SN) from the
57 * PDCP User Plane header. For PDCP Control Plane,
58 * the SN is constant (5 bits) as opposed to PDCP
59 * Data Plane (7/12/15 bits).
61 #define PDCP_U_PLANE_15BIT_SN_MASK 0xFF7F0000
62 #define PDCP_U_PLANE_15BIT_SN_MASK_BE 0x00007FFF
65 * PDCP_U_PLANE_18BIT_SN_MASK - This mask is used in the PDCP descriptors for
66 * extracting the sequence number (SN) from the
67 * PDCP User Plane header.
69 #define PDCP_U_PLANE_18BIT_SN_MASK 0xFFFF0300
70 #define PDCP_U_PLANE_18BIT_SN_MASK_BE 0x0003FFFF
73 * PDCP_BEARER_MASK - This mask is used masking out the bearer for PDCP
74 * processing with SNOW f9 in LTE.
76 * The value on which this mask is applied is formatted as below:
77 * Count-C (32 bit) | Bearer (5 bit) | Direction (1 bit) | 0 (26 bits)
79 * Applying this mask is done for creating the upper 64 bits of the IV needed
82 * The lower 32 bits of the mask are used for masking the direction for AES
85 #define PDCP_BEARER_MASK 0x00000004FFFFFFFFull
86 #define PDCP_BEARER_MASK_BE 0xFFFFFFFF04000000ull
89 * PDCP_DIR_MASK - This mask is used masking out the direction for PDCP
90 * processing with SNOW f9 in LTE.
92 * The value on which this mask is applied is formatted as below:
93 * Bearer (5 bit) | Direction (1 bit) | 0 (26 bits)
95 * Applying this mask is done for creating the lower 32 bits of the IV needed
98 * The upper 32 bits of the mask are used for masking the direction for AES
101 #define PDCP_DIR_MASK 0x00000000000000F8ull
102 #define PDCP_DIR_MASK_BE 0xF800000000000000ull
105 * PDCP_NULL_INT_MAC_I_VAL - The value of the PDCP PDU MAC-I in case NULL
109 #define PDCP_NULL_INT_MAC_I_VAL 0x00000000
112 * PDCP_NULL_INT_ICV_CHECK_FAILED_STATUS - The status used to report ICV check
113 * failed in case of NULL integrity
114 * Control Plane processing.
116 #define PDCP_NULL_INT_ICV_CHECK_FAILED_STATUS 0x0A
118 * PDCP_DPOVRD_HFN_OV_EN - Value to be used in the FD status/cmd field to
119 * indicate the HFN override mechanism is active for the
122 #define PDCP_DPOVRD_HFN_OV_EN 0x80000000
125 * PDCP_P4080REV2_HFN_OV_BUFLEN - The length in bytes of the supplementary space
126 * that must be provided by the user at the
127 * beginning of the input frame buffer for
130 * The format of the frame buffer is the following:
132 * |<---PDCP_P4080REV2_HFN_OV_BUFLEN-->|
133 * //===================================||============||==============\\
134 * || PDCP_DPOVRD_HFN_OV_EN | HFN value || PDCP Header|| PDCP Payload ||
135 * \\===================================||============||==============//
137 * If HFN override mechanism is not desired, then the MSB of the first 4 bytes
140 #define PDCP_P4080REV2_HFN_OV_BUFLEN 4
143 * enum cipher_type_pdcp - Type selectors for cipher types in PDCP protocol OP
145 * @PDCP_CIPHER_TYPE_NULL: NULL
146 * @PDCP_CIPHER_TYPE_SNOW: SNOW F8
147 * @PDCP_CIPHER_TYPE_AES: AES
148 * @PDCP_CIPHER_TYPE_ZUC: ZUCE
149 * @PDCP_CIPHER_TYPE_INVALID: invalid option
151 enum cipher_type_pdcp {
152 PDCP_CIPHER_TYPE_NULL,
153 PDCP_CIPHER_TYPE_SNOW,
154 PDCP_CIPHER_TYPE_AES,
155 PDCP_CIPHER_TYPE_ZUC,
156 PDCP_CIPHER_TYPE_INVALID
160 * enum auth_type_pdcp - Type selectors for integrity types in PDCP protocol OP
162 * @PDCP_AUTH_TYPE_NULL: NULL
163 * @PDCP_AUTH_TYPE_SNOW: SNOW F9
164 * @PDCP_AUTH_TYPE_AES: AES CMAC
165 * @PDCP_AUTH_TYPE_ZUC: ZUCA
166 * @PDCP_AUTH_TYPE_INVALID: invalid option
168 enum auth_type_pdcp {
173 PDCP_AUTH_TYPE_INVALID
177 * enum pdcp_dir - Type selectors for direction for PDCP protocol
178 * @PDCP_DIR_UPLINK: uplink direction
179 * @PDCP_DIR_DOWNLINK: downlink direction
180 * @PDCP_DIR_INVALID: invalid option
184 PDCP_DIR_DOWNLINK = 1,
189 * enum pdcp_plane - PDCP domain selectors
190 * @PDCP_CONTROL_PLANE: Control Plane
191 * @PDCP_DATA_PLANE: Data Plane
192 * @PDCP_SHORT_MAC: Short MAC
201 * enum pdcp_sn_size - Sequence Number Size selectors for PDCP protocol
202 * @PDCP_SN_SIZE_5: 5bit sequence number
203 * @PDCP_SN_SIZE_7: 7bit sequence number
204 * @PDCP_SN_SIZE_12: 12bit sequence number
205 * @PDCP_SN_SIZE_15: 15bit sequence number
206 * @PDCP_SN_SIZE_18: 18bit sequence number
211 PDCP_SN_SIZE_12 = 12,
212 PDCP_SN_SIZE_15 = 15,
217 * PDCP Control Plane Protocol Data Blocks
219 #define PDCP_C_PLANE_PDB_HFN_SHIFT 5
220 #define PDCP_C_PLANE_PDB_BEARER_SHIFT 27
221 #define PDCP_C_PLANE_PDB_DIR_SHIFT 26
222 #define PDCP_C_PLANE_PDB_HFN_THR_SHIFT 5
224 #define PDCP_U_PLANE_PDB_OPT_SHORT_SN 0x2
225 #define PDCP_U_PLANE_PDB_OPT_15B_SN 0x4
226 #define PDCP_U_PLANE_PDB_OPT_18B_SN 0x6
227 #define PDCP_U_PLANE_PDB_SHORT_SN_HFN_SHIFT 7
228 #define PDCP_U_PLANE_PDB_LONG_SN_HFN_SHIFT 12
229 #define PDCP_U_PLANE_PDB_15BIT_SN_HFN_SHIFT 15
230 #define PDCP_U_PLANE_PDB_18BIT_SN_HFN_SHIFT 18
231 #define PDCP_U_PLANE_PDB_BEARER_SHIFT 27
232 #define PDCP_U_PLANE_PDB_DIR_SHIFT 26
233 #define PDCP_U_PLANE_PDB_SHORT_SN_HFN_THR_SHIFT 7
234 #define PDCP_U_PLANE_PDB_LONG_SN_HFN_THR_SHIFT 12
235 #define PDCP_U_PLANE_PDB_15BIT_SN_HFN_THR_SHIFT 15
236 #define PDCP_U_PLANE_PDB_18BIT_SN_HFN_THR_SHIFT 18
243 uint32_t hfn_res; /* HyperFrame number,(27, 25 or 21 bits),
244 * left aligned & right-padded with zeros.
246 uint32_t bearer_dir_res;/* Bearer(5 bits), packet direction (1 bit),
247 * left aligned & right-padded with zeros.
249 uint32_t hfn_thr_res; /* HyperFrame number threshold (27, 25 or 21
250 * bits), left aligned & right-padded with
256 * PDCP internal PDB types
259 PDCP_PDB_TYPE_NO_PDB,
260 PDCP_PDB_TYPE_FULL_PDB,
261 PDCP_PDB_TYPE_REDUCED_PDB,
262 PDCP_PDB_TYPE_INVALID
266 * rta_inline_pdcp_query() - Provide indications if a key can be passed as
267 * immediate data or shall be referenced in a
269 * Return: 0 if data can be inlined or 1 if referenced.
272 rta_inline_pdcp_query(enum auth_type_pdcp auth_alg,
273 enum cipher_type_pdcp cipher_alg,
274 enum pdcp_sn_size sn_size,
278 * Shared Descriptors for some of the cases does not fit in the
279 * MAX_DESC_SIZE of the descriptor especially when non-protocol
280 * descriptors are formed as in 18bit cases and when HFN override
281 * is enabled as 2 extra words are added in the job descriptor.
282 * The cases which exceed are for RTA_SEC_ERA=8 and HFN override
283 * enabled and 18bit uplane and either of following Algo combinations.
289 * We cannot make inline for all cases, as this will impact performance
290 * due to extra memory accesses for the keys.
292 if ((rta_sec_era == RTA_SEC_ERA_8) && hfn_ovd &&
293 (sn_size == PDCP_SN_SIZE_18) &&
294 ((cipher_alg == PDCP_CIPHER_TYPE_SNOW &&
295 auth_alg == PDCP_AUTH_TYPE_AES) ||
296 (cipher_alg == PDCP_CIPHER_TYPE_AES &&
297 auth_alg == PDCP_AUTH_TYPE_SNOW) ||
298 (cipher_alg == PDCP_CIPHER_TYPE_SNOW &&
299 auth_alg == PDCP_AUTH_TYPE_SNOW) ||
300 (cipher_alg == PDCP_CIPHER_TYPE_ZUC &&
301 auth_alg == PDCP_AUTH_TYPE_SNOW))) {
310 * Function for appending the portion of a PDCP Control Plane shared descriptor
311 * which performs NULL encryption and integrity (i.e. copies the input frame
312 * to the output frame, appending 32 bits of zeros at the end (MAC-I for
316 pdcp_insert_cplane_null_op(struct program *p,
317 bool swap __maybe_unused,
318 struct alginfo *cipherdata __maybe_unused,
319 struct alginfo *authdata __maybe_unused,
321 enum pdcp_sn_size sn_size __maybe_unused,
322 unsigned char era_2_sw_hfn_ovrd __maybe_unused)
325 REFERENCE(move_cmd_read_descbuf);
326 REFERENCE(move_cmd_write_descbuf);
328 if (rta_sec_era > RTA_SEC_ERA_2) {
329 MATHB(p, SEQINSZ, ADD, ZERO, VSEQINSZ, 4, 0);
330 if (dir == OP_TYPE_ENCAP_PROTOCOL)
331 MATHB(p, SEQINSZ, ADD, PDCP_MAC_I_LEN, VSEQOUTSZ, 4,
334 MATHB(p, SEQINSZ, SUB, PDCP_MAC_I_LEN, VSEQOUTSZ, 4,
337 MATHB(p, SEQINSZ, ADD, ONE, VSEQINSZ, 4, 0);
338 MATHB(p, VSEQINSZ, SUB, ONE, VSEQINSZ, 4, 0);
340 if (dir == OP_TYPE_ENCAP_PROTOCOL) {
341 MATHB(p, SEQINSZ, ADD, PDCP_MAC_I_LEN, VSEQOUTSZ, 4,
343 MATHB(p, VSEQINSZ, SUB, ONE, MATH0, 4, 0);
345 MATHB(p, VSEQINSZ, SUB, PDCP_MAC_I_LEN, VSEQINSZ, 4,
347 MATHB(p, SEQINSZ, SUB, PDCP_MAC_I_LEN, VSEQOUTSZ, 4,
349 MATHB(p, VSEQOUTSZ, SUB, ONE, MATH0, 4, 0);
352 MATHB(p, MATH0, ADD, ONE, MATH0, 4, 0);
355 * Since MOVELEN is available only starting with
356 * SEC ERA 3, use poor man's MOVELEN: create a MOVE
357 * command dynamically by writing the length from M1 by
358 * OR-ing the command in the M1 register and MOVE the
359 * result into the descriptor buffer. Care must be taken
360 * wrt. the location of the command because of SEC
361 * pipelining. The actual MOVEs are written at the end
362 * of the descriptor due to calculations needed on the
363 * offset in the descriptor for the MOVE command.
365 move_cmd_read_descbuf = MOVE(p, DESCBUF, 0, MATH0, 0, 6,
367 move_cmd_write_descbuf = MOVE(p, MATH0, 0, DESCBUF, 0, 8,
370 MATHB(p, VSEQINSZ, SUB, PDCP_NULL_MAX_FRAME_LEN, NONE, 4,
372 JUMP(p, PDCP_MAX_FRAME_LEN_STATUS, HALT_STATUS, ALL_FALSE, MATH_N);
374 if (rta_sec_era > RTA_SEC_ERA_2) {
375 if (dir == OP_TYPE_ENCAP_PROTOCOL)
376 MATHB(p, VSEQINSZ, ADD, ZERO, MATH0, 4, 0);
378 MATHB(p, VSEQOUTSZ, ADD, ZERO, MATH0, 4, 0);
380 SEQFIFOSTORE(p, MSG, 0, 0, VLF);
381 SEQFIFOLOAD(p, MSG1, 0, VLF | LAST1 | FLUSH1);
383 if (rta_sec_era > RTA_SEC_ERA_2) {
384 MOVE(p, AB1, 0, OFIFO, 0, MATH0, 0);
386 SET_LABEL(p, local_offset);
388 /* Shut off automatic Info FIFO entries */
389 LOAD(p, 0, DCTRL, LDOFF_DISABLE_AUTO_NFIFO, 0, IMMED);
390 /* Placeholder for MOVE command with length from M1 register */
391 MOVE(p, IFIFOAB1, 0, OFIFO, 0, 0, IMMED);
392 /* Enable automatic Info FIFO entries */
393 LOAD(p, 0, DCTRL, LDOFF_ENABLE_AUTO_NFIFO, 0, IMMED);
396 if (dir == OP_TYPE_ENCAP_PROTOCOL) {
397 MATHB(p, MATH1, XOR, MATH1, MATH0, 8, 0);
398 MOVE(p, MATH0, 0, OFIFO, 0, 4, IMMED);
401 if (rta_sec_era < RTA_SEC_ERA_3) {
402 PATCH_MOVE(p, move_cmd_read_descbuf, local_offset);
403 PATCH_MOVE(p, move_cmd_write_descbuf, local_offset);
410 insert_copy_frame_op(struct program *p,
411 struct alginfo *cipherdata __maybe_unused,
412 unsigned int dir __maybe_unused)
415 REFERENCE(move_cmd_read_descbuf);
416 REFERENCE(move_cmd_write_descbuf);
418 if (rta_sec_era > RTA_SEC_ERA_2) {
419 MATHB(p, SEQINSZ, ADD, ZERO, VSEQINSZ, 4, 0);
420 MATHB(p, SEQINSZ, ADD, ZERO, VSEQOUTSZ, 4, 0);
422 MATHB(p, SEQINSZ, ADD, ONE, VSEQINSZ, 4, 0);
423 MATHB(p, VSEQINSZ, SUB, ONE, VSEQINSZ, 4, 0);
424 MATHB(p, SEQINSZ, ADD, ONE, VSEQOUTSZ, 4, 0);
425 MATHB(p, VSEQOUTSZ, SUB, ONE, VSEQOUTSZ, 4, 0);
426 MATHB(p, VSEQINSZ, SUB, ONE, MATH0, 4, 0);
427 MATHB(p, MATH0, ADD, ONE, MATH0, 4, 0);
430 * Since MOVELEN is available only starting with
431 * SEC ERA 3, use poor man's MOVELEN: create a MOVE
432 * command dynamically by writing the length from M1 by
433 * OR-ing the command in the M1 register and MOVE the
434 * result into the descriptor buffer. Care must be taken
435 * wrt. the location of the command because of SEC
436 * pipelining. The actual MOVEs are written at the end
437 * of the descriptor due to calculations needed on the
438 * offset in the descriptor for the MOVE command.
440 move_cmd_read_descbuf = MOVE(p, DESCBUF, 0, MATH0, 0, 6,
442 move_cmd_write_descbuf = MOVE(p, MATH0, 0, DESCBUF, 0, 8,
445 MATHB(p, SEQINSZ, SUB, PDCP_NULL_MAX_FRAME_LEN, NONE, 4,
447 JUMP(p, PDCP_MAX_FRAME_LEN_STATUS, HALT_STATUS, ALL_FALSE, MATH_N);
449 if (rta_sec_era > RTA_SEC_ERA_2)
450 MATHB(p, VSEQINSZ, ADD, ZERO, MATH0, 4, 0);
452 SEQFIFOLOAD(p, MSG1, 0, VLF | LAST1 | FLUSH1);
453 if (rta_sec_era > RTA_SEC_ERA_2) {
454 MOVE(p, AB1, 0, OFIFO, 0, MATH0, 0);
456 SET_LABEL(p, local_offset);
458 /* Shut off automatic Info FIFO entries */
459 LOAD(p, 0, DCTRL, LDOFF_DISABLE_AUTO_NFIFO, 0, IMMED);
461 /* Placeholder for MOVE command with length from M0 register */
462 MOVE(p, IFIFOAB1, 0, OFIFO, 0, 0, IMMED);
464 /* Enable automatic Info FIFO entries */
465 LOAD(p, 0, DCTRL, LDOFF_ENABLE_AUTO_NFIFO, 0, IMMED);
468 SEQFIFOSTORE(p, MSG, 0, 0, VLF);
470 if (rta_sec_era < RTA_SEC_ERA_3) {
471 PATCH_MOVE(p, move_cmd_read_descbuf, local_offset);
472 PATCH_MOVE(p, move_cmd_write_descbuf, local_offset);
478 pdcp_insert_cplane_int_only_op(struct program *p,
479 bool swap __maybe_unused,
480 struct alginfo *cipherdata __maybe_unused,
481 struct alginfo *authdata, unsigned int dir,
482 enum pdcp_sn_size sn_size,
483 unsigned char era_2_sw_hfn_ovrd)
485 uint32_t offset = 0, length = 0, sn_mask = 0;
487 /* 12 bit SN is only supported for protocol offload case */
488 if (rta_sec_era >= RTA_SEC_ERA_8 && sn_size == PDCP_SN_SIZE_12) {
489 KEY(p, KEY2, authdata->key_enc_flags, authdata->key,
490 authdata->keylen, INLINE_KEY(authdata));
492 PROTOCOL(p, dir, OP_PCLID_LTE_PDCP_USER_RN,
493 (uint16_t)authdata->algtype);
497 /* Non-proto is supported only for 5bit cplane and 18bit uplane */
502 sn_mask = (swap == false) ? PDCP_C_PLANE_SN_MASK :
503 PDCP_C_PLANE_SN_MASK_BE;
505 case PDCP_SN_SIZE_18:
508 sn_mask = (swap == false) ? PDCP_U_PLANE_18BIT_SN_MASK :
509 PDCP_U_PLANE_18BIT_SN_MASK_BE;
512 case PDCP_SN_SIZE_12:
513 case PDCP_SN_SIZE_15:
514 pr_err("Invalid sn_size for %s\n", __func__);
519 REFERENCE(move_cmd_read_descbuf);
520 REFERENCE(move_cmd_write_descbuf);
522 switch (authdata->algtype) {
523 case PDCP_AUTH_TYPE_SNOW:
524 /* Insert Auth Key */
525 KEY(p, KEY2, authdata->key_enc_flags, authdata->key,
526 authdata->keylen, INLINE_KEY(authdata));
527 SEQLOAD(p, MATH0, offset, length, 0);
528 JUMP(p, 1, LOCAL_JUMP, ALL_TRUE, CALM);
530 if (rta_sec_era > RTA_SEC_ERA_2 ||
531 (rta_sec_era == RTA_SEC_ERA_2 &&
532 era_2_sw_hfn_ovrd == 0)) {
533 SEQINPTR(p, 0, length, RTO);
535 SEQINPTR(p, 0, 5, RTO);
536 SEQFIFOLOAD(p, SKIP, 4, 0);
540 MATHB(p, MATH0, AND, sn_mask, MATH1, 8,
542 MATHB(p, MATH1, SHLD, MATH1, MATH1, 8, 0);
544 MOVEB(p, DESCBUF, 8, MATH2, 0, 8, WAITCOMP | IMMED);
546 MATHB(p, MATH2, AND, PDCP_BEARER_MASK, MATH2, 8,
548 MOVEB(p, DESCBUF, 0x0C, MATH3, 0, 4, WAITCOMP | IMMED);
549 MATHB(p, MATH3, AND, PDCP_DIR_MASK, MATH3, 8, IMMED2);
550 MATHB(p, MATH1, OR, MATH2, MATH2, 8, 0);
551 MOVEB(p, MATH2, 0, CONTEXT2, 0, 0x0C, WAITCOMP | IMMED);
553 MATHB(p, MATH0, AND, sn_mask, MATH1, 8,
555 MATHB(p, MATH1, SHLD, MATH1, MATH1, 8, 0);
557 MOVE(p, DESCBUF, 8, MATH2, 0, 8, WAITCOMP | IMMED);
558 MATHB(p, MATH2, AND, PDCP_BEARER_MASK_BE, MATH2, 8,
561 MOVE(p, DESCBUF, 0x0C, MATH3, 0, 4, WAITCOMP | IMMED);
562 MATHB(p, MATH3, AND, PDCP_DIR_MASK_BE, MATH3, 8,
564 MATHB(p, MATH1, OR, MATH2, MATH2, 8, 0);
565 MOVE(p, MATH2, 0, CONTEXT2, 0, 0x0C, WAITCOMP | IMMED);
568 if (dir == OP_TYPE_DECAP_PROTOCOL) {
569 MATHB(p, SEQINSZ, SUB, PDCP_MAC_I_LEN, MATH1, 4,
572 if (rta_sec_era > RTA_SEC_ERA_2) {
573 MATHB(p, SEQINSZ, SUB, ZERO, MATH1, 4,
576 MATHB(p, SEQINSZ, ADD, ONE, MATH1, 4,
578 MATHB(p, MATH1, SUB, ONE, MATH1, 4,
583 if (rta_sec_era > RTA_SEC_ERA_2) {
584 MATHB(p, MATH1, SUB, ZERO, VSEQINSZ, 4, 0);
585 MATHB(p, MATH1, SUB, ZERO, VSEQOUTSZ, 4, 0);
587 MATHB(p, ZERO, ADD, MATH1, VSEQINSZ, 4, 0);
588 MATHB(p, ZERO, ADD, MATH1, VSEQOUTSZ, 4, 0);
591 * Since MOVELEN is available only starting with
592 * SEC ERA 3, use poor man's MOVELEN: create a MOVE
593 * command dynamically by writing the length from M1 by
594 * OR-ing the command in the M1 register and MOVE the
595 * result into the descriptor buffer. Care must be taken
596 * wrt. the location of the command because of SEC
597 * pipelining. The actual MOVEs are written at the end
598 * of the descriptor due to calculations needed on the
599 * offset in the descriptor for the MOVE command.
601 move_cmd_read_descbuf = MOVE(p, DESCBUF, 0, MATH1, 0, 6,
603 move_cmd_write_descbuf = MOVE(p, MATH1, 0, DESCBUF, 0,
604 8, WAITCOMP | IMMED);
607 SEQFIFOSTORE(p, MSG, 0, 0, VLF);
608 ALG_OPERATION(p, OP_ALG_ALGSEL_SNOW_F9, OP_ALG_AAI_F9,
610 dir == OP_TYPE_ENCAP_PROTOCOL ?
611 ICV_CHECK_DISABLE : ICV_CHECK_ENABLE,
614 if (rta_sec_era > RTA_SEC_ERA_2) {
615 SEQFIFOLOAD(p, MSGINSNOOP, 0,
616 VLF | LAST1 | LAST2 | FLUSH1);
617 MOVE(p, AB1, 0, OFIFO, 0, MATH1, 0);
619 SEQFIFOLOAD(p, MSGINSNOOP, 0,
620 VLF | LAST1 | LAST2 | FLUSH1);
621 SET_LABEL(p, local_offset);
623 /* Shut off automatic Info FIFO entries */
624 LOAD(p, 0, DCTRL, LDOFF_DISABLE_AUTO_NFIFO, 0, IMMED);
626 * Placeholder for MOVE command with length from M1
629 MOVE(p, IFIFOAB1, 0, OFIFO, 0, 0, IMMED);
630 /* Enable automatic Info FIFO entries */
631 LOAD(p, 0, DCTRL, LDOFF_ENABLE_AUTO_NFIFO, 0, IMMED);
634 if (dir == OP_TYPE_DECAP_PROTOCOL)
635 SEQFIFOLOAD(p, ICV2, 4, LAST2);
637 SEQSTORE(p, CONTEXT2, 0, 4, 0);
641 case PDCP_AUTH_TYPE_AES:
642 /* Insert Auth Key */
643 KEY(p, KEY1, authdata->key_enc_flags, authdata->key,
644 authdata->keylen, INLINE_KEY(authdata));
645 SEQLOAD(p, MATH0, offset, length, 0);
646 JUMP(p, 1, LOCAL_JUMP, ALL_TRUE, CALM);
647 if (rta_sec_era > RTA_SEC_ERA_2 ||
648 (rta_sec_era == RTA_SEC_ERA_2 &&
649 era_2_sw_hfn_ovrd == 0)) {
650 SEQINPTR(p, 0, length, RTO);
652 SEQINPTR(p, 0, 5, RTO);
653 SEQFIFOLOAD(p, SKIP, 4, 0);
657 MATHB(p, MATH0, AND, sn_mask, MATH1, 8,
659 MATHB(p, MATH1, SHLD, MATH1, MATH1, 8, 0);
661 MOVEB(p, DESCBUF, 8, MATH2, 0, 8, WAITCOMP | IMMED);
662 MATHB(p, MATH1, OR, MATH2, MATH2, 8, 0);
663 MOVEB(p, MATH2, 0, IFIFOAB1, 0, 8, IMMED);
665 MATHB(p, MATH0, AND, sn_mask, MATH1, 8,
667 MATHB(p, MATH1, SHLD, MATH1, MATH1, 8, 0);
669 MOVE(p, DESCBUF, 8, MATH2, 0, 8, WAITCOMP | IMMED);
670 MATHB(p, MATH1, OR, MATH2, MATH2, 8, 0);
671 MOVE(p, MATH2, 0, IFIFOAB1, 0, 8, IMMED);
674 if (dir == OP_TYPE_DECAP_PROTOCOL) {
675 MATHB(p, SEQINSZ, SUB, PDCP_MAC_I_LEN, MATH1, 4,
678 if (rta_sec_era > RTA_SEC_ERA_2) {
679 MATHB(p, SEQINSZ, SUB, ZERO, MATH1, 4,
682 MATHB(p, SEQINSZ, ADD, ONE, MATH1, 4,
684 MATHB(p, MATH1, SUB, ONE, MATH1, 4,
689 if (rta_sec_era > RTA_SEC_ERA_2) {
690 MATHB(p, MATH1, SUB, ZERO, VSEQINSZ, 4, 0);
691 MATHB(p, MATH1, SUB, ZERO, VSEQOUTSZ, 4, 0);
693 MATHB(p, ZERO, ADD, MATH1, VSEQINSZ, 4, 0);
694 MATHB(p, ZERO, ADD, MATH1, VSEQOUTSZ, 4, 0);
697 * Since MOVELEN is available only starting with
698 * SEC ERA 3, use poor man's MOVELEN: create a MOVE
699 * command dynamically by writing the length from M1 by
700 * OR-ing the command in the M1 register and MOVE the
701 * result into the descriptor buffer. Care must be taken
702 * wrt. the location of the command because of SEC
703 * pipelining. The actual MOVEs are written at the end
704 * of the descriptor due to calculations needed on the
705 * offset in the descriptor for the MOVE command.
707 move_cmd_read_descbuf = MOVE(p, DESCBUF, 0, MATH1, 0, 6,
709 move_cmd_write_descbuf = MOVE(p, MATH1, 0, DESCBUF, 0,
710 8, WAITCOMP | IMMED);
712 SEQFIFOSTORE(p, MSG, 0, 0, VLF);
713 ALG_OPERATION(p, OP_ALG_ALGSEL_AES,
716 dir == OP_TYPE_ENCAP_PROTOCOL ?
717 ICV_CHECK_DISABLE : ICV_CHECK_ENABLE,
720 if (rta_sec_era > RTA_SEC_ERA_2) {
721 MOVE(p, AB2, 0, OFIFO, 0, MATH1, 0);
722 SEQFIFOLOAD(p, MSGINSNOOP, 0,
723 VLF | LAST1 | LAST2 | FLUSH1);
725 SEQFIFOLOAD(p, MSGINSNOOP, 0,
726 VLF | LAST1 | LAST2 | FLUSH1);
727 SET_LABEL(p, local_offset);
729 /* Shut off automatic Info FIFO entries */
730 LOAD(p, 0, DCTRL, LDOFF_DISABLE_AUTO_NFIFO, 0, IMMED);
733 * Placeholder for MOVE command with length from
736 MOVE(p, IFIFOAB2, 0, OFIFO, 0, 0, IMMED);
738 /* Enable automatic Info FIFO entries */
739 LOAD(p, 0, DCTRL, LDOFF_ENABLE_AUTO_NFIFO, 0, IMMED);
742 if (dir == OP_TYPE_DECAP_PROTOCOL)
743 SEQFIFOLOAD(p, ICV1, 4, LAST1 | FLUSH1);
745 SEQSTORE(p, CONTEXT1, 0, 4, 0);
749 case PDCP_AUTH_TYPE_ZUC:
750 if (rta_sec_era < RTA_SEC_ERA_5) {
751 pr_err("Invalid era for selected algorithm\n");
754 /* Insert Auth Key */
755 KEY(p, KEY2, authdata->key_enc_flags, authdata->key,
756 authdata->keylen, INLINE_KEY(authdata));
757 SEQLOAD(p, MATH0, offset, length, 0);
758 JUMP(p, 1, LOCAL_JUMP, ALL_TRUE, CALM);
759 SEQINPTR(p, 0, length, RTO);
761 MATHB(p, MATH0, AND, sn_mask, MATH1, 8,
763 MATHB(p, MATH1, SHLD, MATH1, MATH1, 8, 0);
765 MOVEB(p, DESCBUF, 8, MATH2, 0, 8, WAITCOMP | IMMED);
766 MATHB(p, MATH1, OR, MATH2, MATH2, 8, 0);
767 MOVEB(p, MATH2, 0, CONTEXT2, 0, 8, IMMED);
770 MATHB(p, MATH0, AND, sn_mask, MATH1, 8,
772 MATHB(p, MATH1, SHLD, MATH1, MATH1, 8, 0);
774 MOVE(p, DESCBUF, 8, MATH2, 0, 8, WAITCOMP | IMMED);
775 MATHB(p, MATH1, OR, MATH2, MATH2, 8, 0);
776 MOVE(p, MATH2, 0, CONTEXT2, 0, 8, IMMED);
778 if (dir == OP_TYPE_DECAP_PROTOCOL)
779 MATHB(p, SEQINSZ, SUB, PDCP_MAC_I_LEN, MATH1, 4,
782 MATHB(p, SEQINSZ, SUB, ZERO, MATH1, 4, 0);
784 MATHB(p, MATH1, SUB, ZERO, VSEQINSZ, 4, 0);
785 MATHB(p, MATH1, SUB, ZERO, VSEQOUTSZ, 4, 0);
786 SEQFIFOSTORE(p, MSG, 0, 0, VLF);
787 ALG_OPERATION(p, OP_ALG_ALGSEL_ZUCA,
790 dir == OP_TYPE_ENCAP_PROTOCOL ?
791 ICV_CHECK_DISABLE : ICV_CHECK_ENABLE,
793 SEQFIFOLOAD(p, MSGINSNOOP, 0, VLF | LAST1 | LAST2 | FLUSH1);
794 MOVE(p, AB1, 0, OFIFO, 0, MATH1, 0);
796 if (dir == OP_TYPE_DECAP_PROTOCOL)
797 SEQFIFOLOAD(p, ICV2, 4, LAST2);
799 SEQSTORE(p, CONTEXT2, 0, 4, 0);
804 pr_err("%s: Invalid integrity algorithm selected: %d\n",
805 "pdcp_insert_cplane_int_only_op", authdata->algtype);
809 if (rta_sec_era < RTA_SEC_ERA_3) {
810 PATCH_MOVE(p, move_cmd_read_descbuf, local_offset);
811 PATCH_MOVE(p, move_cmd_write_descbuf, local_offset);
818 pdcp_insert_cplane_enc_only_op(struct program *p,
819 bool swap __maybe_unused,
820 struct alginfo *cipherdata,
821 struct alginfo *authdata __maybe_unused,
823 enum pdcp_sn_size sn_size,
824 unsigned char era_2_sw_hfn_ovrd __maybe_unused)
826 uint32_t offset = 0, length = 0, sn_mask = 0;
827 /* Insert Cipher Key */
828 KEY(p, KEY1, cipherdata->key_enc_flags, cipherdata->key,
829 cipherdata->keylen, INLINE_KEY(cipherdata));
831 if ((rta_sec_era >= RTA_SEC_ERA_8 && sn_size != PDCP_SN_SIZE_18 &&
832 !(rta_sec_era == RTA_SEC_ERA_8 &&
833 authdata->algtype == 0))
834 || (rta_sec_era == RTA_SEC_ERA_10)) {
835 if (sn_size == PDCP_SN_SIZE_5)
836 PROTOCOL(p, dir, OP_PCLID_LTE_PDCP_CTRL_MIXED,
837 (uint16_t)cipherdata->algtype << 8);
839 PROTOCOL(p, dir, OP_PCLID_LTE_PDCP_USER_RN,
840 (uint16_t)cipherdata->algtype << 8);
843 /* Non-proto is supported only for 5bit cplane and 18bit uplane */
848 sn_mask = (swap == false) ? PDCP_C_PLANE_SN_MASK :
849 PDCP_C_PLANE_SN_MASK_BE;
851 case PDCP_SN_SIZE_18:
854 sn_mask = (swap == false) ? PDCP_U_PLANE_18BIT_SN_MASK :
855 PDCP_U_PLANE_18BIT_SN_MASK_BE;
857 case PDCP_SN_SIZE_12:
860 sn_mask = (swap == false) ? PDCP_12BIT_SN_MASK :
861 PDCP_12BIT_SN_MASK_BE;
864 case PDCP_SN_SIZE_15:
865 pr_err("Invalid sn_size for %s\n", __func__);
869 SEQLOAD(p, MATH0, offset, length, 0);
870 JUMP(p, 1, LOCAL_JUMP, ALL_TRUE, CALM);
871 MATHB(p, MATH0, AND, sn_mask, MATH1, 8, IFB | IMMED2);
872 SEQSTORE(p, MATH0, offset, length, 0);
873 MATHB(p, MATH1, SHLD, MATH1, MATH1, 8, 0);
874 MOVEB(p, DESCBUF, 8, MATH2, 0, 8, WAITCOMP | IMMED);
875 MATHB(p, MATH1, OR, MATH2, MATH2, 8, 0);
877 switch (cipherdata->algtype) {
878 case PDCP_CIPHER_TYPE_SNOW:
879 MOVEB(p, MATH2, 0, CONTEXT1, 0, 8, WAITCOMP | IMMED);
881 if (rta_sec_era > RTA_SEC_ERA_2) {
882 MATHB(p, SEQINSZ, SUB, ZERO, VSEQINSZ, 4, 0);
884 MATHB(p, SEQINSZ, SUB, ONE, MATH1, 4, 0);
885 MATHB(p, MATH1, ADD, ONE, VSEQINSZ, 4, 0);
888 if (dir == OP_TYPE_ENCAP_PROTOCOL)
889 MATHB(p, SEQINSZ, ADD, PDCP_MAC_I_LEN, VSEQOUTSZ, 4,
892 MATHB(p, SEQINSZ, SUB, PDCP_MAC_I_LEN, VSEQOUTSZ, 4,
894 SEQFIFOSTORE(p, MSG, 0, 0, VLF | CONT);
895 ALG_OPERATION(p, OP_ALG_ALGSEL_SNOW_F8,
897 OP_ALG_AS_INITFINAL, ICV_CHECK_DISABLE,
898 dir == OP_TYPE_ENCAP_PROTOCOL ?
902 case PDCP_CIPHER_TYPE_AES:
903 MOVEB(p, MATH2, 0, CONTEXT1, 0x10, 0x10, WAITCOMP | IMMED);
905 if (rta_sec_era > RTA_SEC_ERA_2) {
906 MATHB(p, SEQINSZ, SUB, ZERO, VSEQINSZ, 4, 0);
908 MATHB(p, SEQINSZ, SUB, ONE, MATH1, 4, 0);
909 MATHB(p, MATH1, ADD, ONE, VSEQINSZ, 4, 0);
912 if (dir == OP_TYPE_ENCAP_PROTOCOL)
913 MATHB(p, SEQINSZ, ADD, PDCP_MAC_I_LEN, VSEQOUTSZ, 4,
916 MATHB(p, SEQINSZ, SUB, PDCP_MAC_I_LEN, VSEQOUTSZ, 4,
919 SEQFIFOSTORE(p, MSG, 0, 0, VLF | CONT);
920 ALG_OPERATION(p, OP_ALG_ALGSEL_AES,
924 dir == OP_TYPE_ENCAP_PROTOCOL ?
928 case PDCP_CIPHER_TYPE_ZUC:
929 if (rta_sec_era < RTA_SEC_ERA_5) {
930 pr_err("Invalid era for selected algorithm\n");
934 MOVEB(p, MATH2, 0, CONTEXT1, 0, 0x08, IMMED);
935 MOVEB(p, MATH2, 0, CONTEXT1, 0x08, 0x08, WAITCOMP | IMMED);
936 MATHB(p, SEQINSZ, SUB, ZERO, VSEQINSZ, 4, 0);
937 if (dir == OP_TYPE_ENCAP_PROTOCOL)
938 MATHB(p, SEQINSZ, ADD, PDCP_MAC_I_LEN, VSEQOUTSZ, 4,
941 MATHB(p, SEQINSZ, SUB, PDCP_MAC_I_LEN, VSEQOUTSZ, 4,
944 SEQFIFOSTORE(p, MSG, 0, 0, VLF | CONT);
945 ALG_OPERATION(p, OP_ALG_ALGSEL_ZUCE,
949 dir == OP_TYPE_ENCAP_PROTOCOL ?
954 pr_err("%s: Invalid encrypt algorithm selected: %d\n",
955 "pdcp_insert_cplane_enc_only_op", cipherdata->algtype);
959 if (dir == OP_TYPE_ENCAP_PROTOCOL) {
960 SEQFIFOLOAD(p, MSG1, 0, VLF);
961 FIFOLOAD(p, MSG1, PDCP_NULL_INT_MAC_I_VAL, 4,
962 LAST1 | FLUSH1 | IMMED);
964 SEQFIFOLOAD(p, MSG1, 0, VLF | LAST1 | FLUSH1);
965 MOVE(p, OFIFO, 0, MATH1, 4, PDCP_MAC_I_LEN, WAITCOMP | IMMED);
966 MATHB(p, MATH1, XOR, PDCP_NULL_INT_MAC_I_VAL, NONE, 4, IMMED2);
967 JUMP(p, PDCP_NULL_INT_ICV_CHECK_FAILED_STATUS,
968 HALT_STATUS, ALL_FALSE, MATH_Z);
975 pdcp_insert_uplane_snow_snow_op(struct program *p,
976 bool swap __maybe_unused,
977 struct alginfo *cipherdata,
978 struct alginfo *authdata,
980 enum pdcp_sn_size sn_size,
981 unsigned char era_2_sw_hfn_ovrd __maybe_unused)
983 uint32_t offset = 0, length = 0, sn_mask = 0;
985 KEY(p, KEY1, cipherdata->key_enc_flags, cipherdata->key,
986 cipherdata->keylen, INLINE_KEY(cipherdata));
987 KEY(p, KEY2, authdata->key_enc_flags, authdata->key, authdata->keylen,
988 INLINE_KEY(authdata));
990 if (rta_sec_era >= RTA_SEC_ERA_8 && sn_size != PDCP_SN_SIZE_18) {
993 if (sn_size == PDCP_SN_SIZE_5)
994 pclid = OP_PCLID_LTE_PDCP_CTRL_MIXED;
996 pclid = OP_PCLID_LTE_PDCP_USER_RN;
998 PROTOCOL(p, dir, pclid,
999 ((uint16_t)cipherdata->algtype << 8) |
1000 (uint16_t)authdata->algtype);
1004 /* Non-proto is supported only for 5bit cplane and 18bit uplane */
1006 case PDCP_SN_SIZE_5:
1009 sn_mask = (swap == false) ? PDCP_C_PLANE_SN_MASK :
1010 PDCP_C_PLANE_SN_MASK_BE;
1012 case PDCP_SN_SIZE_18:
1015 sn_mask = (swap == false) ? PDCP_U_PLANE_18BIT_SN_MASK :
1016 PDCP_U_PLANE_18BIT_SN_MASK_BE;
1018 case PDCP_SN_SIZE_7:
1019 case PDCP_SN_SIZE_12:
1020 case PDCP_SN_SIZE_15:
1021 pr_err("Invalid sn_size for %s\n", __func__);
1025 if (dir == OP_TYPE_ENCAP_PROTOCOL)
1026 MATHB(p, SEQINSZ, SUB, length, VSEQINSZ, 4, IMMED2);
1028 SEQLOAD(p, MATH0, offset, length, 0);
1029 JUMP(p, 1, LOCAL_JUMP, ALL_TRUE, CALM);
1030 MOVEB(p, MATH0, offset, IFIFOAB2, 0, length, IMMED);
1031 MATHB(p, MATH0, AND, sn_mask, MATH1, 8, IFB | IMMED2);
1033 SEQSTORE(p, MATH0, offset, length, 0);
1034 MATHB(p, MATH1, SHLD, MATH1, MATH1, 8, 0);
1035 MOVEB(p, DESCBUF, 8, MATH2, 0, 8, WAITCOMP | IMMED);
1036 MATHB(p, MATH1, OR, MATH2, MATH1, 8, 0);
1037 MOVEB(p, MATH1, 0, CONTEXT1, 0, 8, IMMED);
1038 MOVEB(p, MATH1, 0, CONTEXT2, 0, 4, WAITCOMP | IMMED);
1039 if (swap == false) {
1040 MATHB(p, MATH1, AND, upper_32_bits(PDCP_BEARER_MASK),
1042 MATHB(p, MATH1, AND, lower_32_bits(PDCP_DIR_MASK),
1045 MATHB(p, MATH1, AND, lower_32_bits(PDCP_BEARER_MASK_BE),
1047 MATHB(p, MATH1, AND, upper_32_bits(PDCP_DIR_MASK_BE),
1050 MATHB(p, MATH3, SHLD, MATH3, MATH3, 8, 0);
1052 MOVEB(p, MATH2, 4, OFIFO, 0, 12, IMMED);
1053 MOVE(p, OFIFO, 0, CONTEXT2, 4, 12, IMMED);
1054 if (dir == OP_TYPE_ENCAP_PROTOCOL) {
1055 MATHB(p, SEQINSZ, ADD, PDCP_MAC_I_LEN, VSEQOUTSZ, 4, IMMED2);
1057 MATHI(p, SEQINSZ, SUB, PDCP_MAC_I_LEN, VSEQOUTSZ, 4, IMMED2);
1058 MATHI(p, SEQINSZ, SUB, PDCP_MAC_I_LEN, VSEQINSZ, 4, IMMED2);
1061 if (dir == OP_TYPE_ENCAP_PROTOCOL)
1062 SEQFIFOSTORE(p, MSG, 0, 0, VLF);
1064 SEQFIFOSTORE(p, MSG, 0, 0, VLF | CONT);
1066 ALG_OPERATION(p, OP_ALG_ALGSEL_SNOW_F9,
1068 OP_ALG_AS_INITFINAL,
1069 dir == OP_TYPE_ENCAP_PROTOCOL ?
1070 ICV_CHECK_DISABLE : ICV_CHECK_ENABLE,
1072 ALG_OPERATION(p, OP_ALG_ALGSEL_SNOW_F8,
1074 OP_ALG_AS_INITFINAL,
1076 dir == OP_TYPE_ENCAP_PROTOCOL ? DIR_ENC : DIR_DEC);
1078 if (dir == OP_TYPE_ENCAP_PROTOCOL) {
1079 SEQFIFOLOAD(p, MSGINSNOOP, 0, VLF | LAST2);
1080 MOVE(p, CONTEXT2, 0, IFIFOAB1, 0, 4, LAST1 | FLUSH1 | IMMED);
1082 SEQFIFOLOAD(p, MSGOUTSNOOP, 0, VLF | LAST2);
1083 SEQFIFOLOAD(p, MSG1, 4, LAST1 | FLUSH1);
1084 JUMP(p, 1, LOCAL_JUMP, ALL_TRUE, CLASS1 | NOP | NIFP);
1086 if (rta_sec_era >= RTA_SEC_ERA_6)
1087 LOAD(p, 0, DCTRL, 0, LDLEN_RST_CHA_OFIFO_PTR, IMMED);
1089 MOVE(p, OFIFO, 0, MATH0, 0, 4, WAITCOMP | IMMED);
1091 NFIFOADD(p, IFIFO, ICV2, 4, LAST2);
1093 if (rta_sec_era <= RTA_SEC_ERA_2) {
1094 /* Shut off automatic Info FIFO entries */
1095 LOAD(p, 0, DCTRL, LDOFF_DISABLE_AUTO_NFIFO, 0, IMMED);
1096 MOVE(p, MATH0, 0, IFIFOAB2, 0, 4, WAITCOMP | IMMED);
1098 MOVE(p, MATH0, 0, IFIFO, 0, 4, WAITCOMP | IMMED);
1106 pdcp_insert_uplane_zuc_zuc_op(struct program *p,
1107 bool swap __maybe_unused,
1108 struct alginfo *cipherdata,
1109 struct alginfo *authdata,
1111 enum pdcp_sn_size sn_size,
1112 unsigned char era_2_sw_hfn_ovrd __maybe_unused)
1114 uint32_t offset = 0, length = 0, sn_mask = 0;
1117 REFERENCE(pkeyjump);
1119 if (rta_sec_era < RTA_SEC_ERA_5) {
1120 pr_err("Invalid era for selected algorithm\n");
1124 pkeyjump = JUMP(p, keyjump, LOCAL_JUMP, ALL_TRUE, SHRD | SELF | BOTH);
1125 KEY(p, KEY1, cipherdata->key_enc_flags, cipherdata->key,
1126 cipherdata->keylen, INLINE_KEY(cipherdata));
1127 KEY(p, KEY2, authdata->key_enc_flags, authdata->key, authdata->keylen,
1128 INLINE_KEY(authdata));
1130 SET_LABEL(p, keyjump);
1131 PATCH_JUMP(p, pkeyjump, keyjump);
1133 if (rta_sec_era >= RTA_SEC_ERA_8 && sn_size != PDCP_SN_SIZE_18) {
1136 if (sn_size == PDCP_SN_SIZE_5)
1137 pclid = OP_PCLID_LTE_PDCP_CTRL_MIXED;
1139 pclid = OP_PCLID_LTE_PDCP_USER_RN;
1141 PROTOCOL(p, dir, pclid,
1142 ((uint16_t)cipherdata->algtype << 8) |
1143 (uint16_t)authdata->algtype);
1147 /* Non-proto is supported only for 5bit cplane and 18bit uplane */
1149 case PDCP_SN_SIZE_5:
1152 sn_mask = (swap == false) ? PDCP_C_PLANE_SN_MASK :
1153 PDCP_C_PLANE_SN_MASK_BE;
1155 case PDCP_SN_SIZE_18:
1158 sn_mask = (swap == false) ? PDCP_U_PLANE_18BIT_SN_MASK :
1159 PDCP_U_PLANE_18BIT_SN_MASK_BE;
1161 case PDCP_SN_SIZE_7:
1162 case PDCP_SN_SIZE_12:
1163 case PDCP_SN_SIZE_15:
1164 pr_err("Invalid sn_size for %s\n", __func__);
1168 SEQLOAD(p, MATH0, offset, length, 0);
1169 JUMP(p, 1, LOCAL_JUMP, ALL_TRUE, CALM);
1170 MOVEB(p, MATH0, offset, IFIFOAB2, 0, length, IMMED);
1171 MATHB(p, MATH0, AND, sn_mask, MATH1, 8, IFB | IMMED2);
1172 MATHB(p, MATH1, SHLD, MATH1, MATH1, 8, 0);
1174 MOVEB(p, DESCBUF, 8, MATH2, 0, 8, WAITCOMP | IMMED);
1175 MATHB(p, MATH1, OR, MATH2, MATH2, 8, 0);
1176 MOVEB(p, MATH2, 0, CONTEXT1, 0, 8, IMMED);
1178 MOVEB(p, MATH2, 0, CONTEXT2, 0, 8, WAITCOMP | IMMED);
1180 if (dir == OP_TYPE_ENCAP_PROTOCOL)
1181 MATHB(p, SEQINSZ, ADD, PDCP_MAC_I_LEN, VSEQOUTSZ, 4, IMMED2);
1183 MATHB(p, SEQINSZ, SUB, PDCP_MAC_I_LEN, VSEQOUTSZ, 4, IMMED2);
1185 MATHB(p, SEQINSZ, SUB, ZERO, VSEQINSZ, 4, 0);
1186 SEQSTORE(p, MATH0, offset, length, 0);
1188 if (dir == OP_TYPE_ENCAP_PROTOCOL) {
1189 SEQFIFOSTORE(p, MSG, 0, 0, VLF);
1190 SEQFIFOLOAD(p, MSGINSNOOP, 0, VLF | LAST2);
1192 SEQFIFOSTORE(p, MSG, 0, 0, VLF | CONT);
1193 SEQFIFOLOAD(p, MSGOUTSNOOP, 0, VLF | LAST1 | FLUSH1);
1196 ALG_OPERATION(p, OP_ALG_ALGSEL_ZUCA,
1198 OP_ALG_AS_INITFINAL,
1199 dir == OP_TYPE_ENCAP_PROTOCOL ?
1200 ICV_CHECK_DISABLE : ICV_CHECK_ENABLE,
1203 ALG_OPERATION(p, OP_ALG_ALGSEL_ZUCE,
1205 OP_ALG_AS_INITFINAL,
1207 dir == OP_TYPE_ENCAP_PROTOCOL ? DIR_ENC : DIR_DEC);
1209 if (dir == OP_TYPE_ENCAP_PROTOCOL) {
1210 MOVE(p, CONTEXT2, 0, IFIFOAB1, 0, 4, LAST1 | FLUSH1 | IMMED);
1213 MOVEB(p, OFIFO, 0, MATH0, 0, 4, IMMED);
1215 LOAD(p, NFIFOENTRY_STYPE_ALTSOURCE |
1216 NFIFOENTRY_DEST_CLASS2 |
1217 NFIFOENTRY_DTYPE_ICV |
1218 NFIFOENTRY_LC2 | 4, NFIFO_SZL, 0, 4, IMMED);
1219 MOVEB(p, MATH0, 0, ALTSOURCE, 0, 4, WAITCOMP | IMMED);
1222 /* Reset ZUCA mode and done interrupt */
1223 LOAD(p, CLRW_CLR_C2MODE, CLRW, 0, 4, IMMED);
1224 LOAD(p, CIRQ_ZADI, ICTRL, 0, 4, IMMED);
1230 pdcp_insert_uplane_aes_aes_op(struct program *p,
1231 bool swap __maybe_unused,
1232 struct alginfo *cipherdata,
1233 struct alginfo *authdata,
1235 enum pdcp_sn_size sn_size,
1236 unsigned char era_2_sw_hfn_ovrd __maybe_unused)
1238 uint32_t offset = 0, length = 0, sn_mask = 0;
1240 if ((rta_sec_era >= RTA_SEC_ERA_8 && sn_size != PDCP_SN_SIZE_18)) {
1241 /* Insert Auth Key */
1242 KEY(p, KEY2, authdata->key_enc_flags, authdata->key,
1243 authdata->keylen, INLINE_KEY(authdata));
1245 /* Insert Cipher Key */
1246 KEY(p, KEY1, cipherdata->key_enc_flags, cipherdata->key,
1247 cipherdata->keylen, INLINE_KEY(cipherdata));
1249 PROTOCOL(p, dir, OP_PCLID_LTE_PDCP_USER_RN,
1250 ((uint16_t)cipherdata->algtype << 8) |
1251 (uint16_t)authdata->algtype);
1255 /* Non-proto is supported only for 5bit cplane and 18bit uplane */
1257 case PDCP_SN_SIZE_18:
1260 sn_mask = (swap == false) ? PDCP_U_PLANE_18BIT_SN_MASK :
1261 PDCP_U_PLANE_18BIT_SN_MASK_BE;
1265 pr_err("Invalid sn_size for %s\n", __func__);
1269 SEQLOAD(p, MATH0, offset, length, 0);
1270 JUMP(p, 1, LOCAL_JUMP, ALL_TRUE, CALM);
1271 MATHB(p, MATH0, AND, sn_mask, MATH1, 8, IFB | IMMED2);
1273 MATHB(p, MATH1, SHLD, MATH1, MATH1, 8, 0);
1274 MOVEB(p, DESCBUF, 8, MATH2, 0, 0x08, WAITCOMP | IMMED);
1275 MATHB(p, MATH1, OR, MATH2, MATH2, 8, 0);
1276 SEQSTORE(p, MATH0, offset, length, 0);
1278 if (dir == OP_TYPE_ENCAP_PROTOCOL) {
1279 KEY(p, KEY1, authdata->key_enc_flags, authdata->key,
1280 authdata->keylen, INLINE_KEY(authdata));
1281 MOVEB(p, MATH2, 0, IFIFOAB1, 0, 0x08, IMMED);
1282 MOVEB(p, MATH0, offset, IFIFOAB1, 0, length, IMMED);
1284 MATHB(p, SEQINSZ, SUB, ZERO, VSEQINSZ, 4, 0);
1285 MATHB(p, VSEQINSZ, ADD, PDCP_MAC_I_LEN, VSEQOUTSZ, 4, IMMED2);
1287 ALG_OPERATION(p, OP_ALG_ALGSEL_AES,
1289 OP_ALG_AS_INITFINAL,
1292 SEQFIFOLOAD(p, MSG1, 0, VLF | LAST1 | FLUSH1);
1293 MOVEB(p, CONTEXT1, 0, MATH3, 0, 4, WAITCOMP | IMMED);
1295 LOAD(p, CLRW_RESET_CLS1_CHA |
1303 KEY(p, KEY1, cipherdata->key_enc_flags, cipherdata->key,
1304 cipherdata->keylen, INLINE_KEY(cipherdata));
1306 MOVEB(p, MATH2, 0, CONTEXT1, 16, 8, IMMED);
1307 SEQINPTR(p, 0, PDCP_NULL_MAX_FRAME_LEN, RTO);
1309 ALG_OPERATION(p, OP_ALG_ALGSEL_AES,
1311 OP_ALG_AS_INITFINAL,
1315 SEQFIFOSTORE(p, MSG, 0, 0, VLF);
1317 SEQFIFOLOAD(p, SKIP, length, 0);
1319 SEQFIFOLOAD(p, MSG1, 0, VLF);
1320 MOVEB(p, MATH3, 0, IFIFOAB1, 0, 4, LAST1 | FLUSH1 | IMMED);
1322 MOVEB(p, MATH2, 0, CONTEXT1, 16, 8, IMMED);
1323 MOVEB(p, MATH2, 0, CONTEXT2, 0, 8, IMMED);
1325 MATHB(p, SEQINSZ, SUB, ZERO, VSEQINSZ, 4, 0);
1326 MATHB(p, SEQINSZ, SUB, PDCP_MAC_I_LEN, VSEQOUTSZ, 4, IMMED2);
1328 KEY(p, KEY1, cipherdata->key_enc_flags, cipherdata->key,
1329 cipherdata->keylen, INLINE_KEY(cipherdata));
1331 ALG_OPERATION(p, OP_ALG_ALGSEL_AES,
1333 OP_ALG_AS_INITFINAL,
1337 SEQFIFOSTORE(p, MSG, 0, 0, VLF | CONT);
1338 SEQFIFOLOAD(p, MSG1, 0, VLF | LAST1 | FLUSH1);
1340 MOVEB(p, OFIFO, 0, MATH3, 0, 4, IMMED);
1342 LOAD(p, CLRW_RESET_CLS1_CHA |
1350 KEY(p, KEY1, authdata->key_enc_flags, authdata->key,
1351 authdata->keylen, INLINE_KEY(authdata));
1353 SEQINPTR(p, 0, 0, SOP);
1355 ALG_OPERATION(p, OP_ALG_ALGSEL_AES,
1357 OP_ALG_AS_INITFINAL,
1361 MATHB(p, SEQINSZ, SUB, ZERO, VSEQINSZ, 4, 0);
1363 MOVE(p, CONTEXT2, 0, IFIFOAB1, 0, 8, IMMED);
1365 SEQFIFOLOAD(p, MSG1, 0, VLF | LAST1 | FLUSH1);
1367 LOAD(p, NFIFOENTRY_STYPE_ALTSOURCE |
1368 NFIFOENTRY_DEST_CLASS1 |
1369 NFIFOENTRY_DTYPE_ICV |
1371 NFIFOENTRY_FC1 | 4, NFIFO_SZL, 0, 4, IMMED);
1372 MOVEB(p, MATH3, 0, ALTSOURCE, 0, 4, IMMED);
1379 pdcp_insert_cplane_acc_op(struct program *p,
1380 bool swap __maybe_unused,
1381 struct alginfo *cipherdata,
1382 struct alginfo *authdata,
1384 enum pdcp_sn_size sn_size,
1385 unsigned char era_2_hfn_ovrd __maybe_unused)
1387 /* Insert Auth Key */
1388 KEY(p, KEY2, authdata->key_enc_flags, authdata->key, authdata->keylen,
1389 INLINE_KEY(authdata));
1391 /* Insert Cipher Key */
1392 KEY(p, KEY1, cipherdata->key_enc_flags, cipherdata->key,
1393 cipherdata->keylen, INLINE_KEY(cipherdata));
1395 if (sn_size == PDCP_SN_SIZE_5)
1396 PROTOCOL(p, dir, OP_PCLID_LTE_PDCP_CTRL,
1397 (uint16_t)cipherdata->algtype);
1399 PROTOCOL(p, dir, OP_PCLID_LTE_PDCP_USER_RN,
1400 ((uint16_t)cipherdata->algtype << 8) |
1401 (uint16_t)authdata->algtype);
1407 pdcp_insert_cplane_snow_aes_op(struct program *p,
1408 bool swap __maybe_unused,
1409 struct alginfo *cipherdata,
1410 struct alginfo *authdata,
1412 enum pdcp_sn_size sn_size,
1413 unsigned char era_2_sw_hfn_ovrd)
1415 uint32_t offset = 0, length = 0, sn_mask = 0;
1417 LABEL(back_to_sd_offset);
1419 LABEL(local_offset);
1420 LABEL(jump_to_beginning);
1421 LABEL(fifo_load_mac_i_offset);
1422 REFERENCE(seqin_ptr_read);
1423 REFERENCE(seqin_ptr_write);
1424 REFERENCE(seq_out_read);
1425 REFERENCE(jump_back_to_sd_cmd);
1426 REFERENCE(move_mac_i_to_desc_buf);
1428 if ((rta_sec_era >= RTA_SEC_ERA_8 && sn_size != PDCP_SN_SIZE_18) ||
1429 (rta_sec_era == RTA_SEC_ERA_10)) {
1430 KEY(p, KEY1, cipherdata->key_enc_flags, cipherdata->key,
1431 cipherdata->keylen, INLINE_KEY(cipherdata));
1432 KEY(p, KEY2, authdata->key_enc_flags, authdata->key,
1433 authdata->keylen, INLINE_KEY(authdata));
1435 if (sn_size == PDCP_SN_SIZE_5)
1436 PROTOCOL(p, dir, OP_PCLID_LTE_PDCP_CTRL_MIXED,
1437 ((uint16_t)cipherdata->algtype << 8) |
1438 (uint16_t)authdata->algtype);
1440 PROTOCOL(p, dir, OP_PCLID_LTE_PDCP_USER_RN,
1441 ((uint16_t)cipherdata->algtype << 8) |
1442 (uint16_t)authdata->algtype);
1446 /* Non-proto is supported only for 5bit cplane and 18bit uplane */
1448 case PDCP_SN_SIZE_5:
1451 sn_mask = (swap == false) ? PDCP_C_PLANE_SN_MASK :
1452 PDCP_C_PLANE_SN_MASK_BE;
1454 case PDCP_SN_SIZE_18:
1457 sn_mask = (swap == false) ? PDCP_U_PLANE_18BIT_SN_MASK :
1458 PDCP_U_PLANE_18BIT_SN_MASK_BE;
1460 case PDCP_SN_SIZE_7:
1461 case PDCP_SN_SIZE_12:
1462 case PDCP_SN_SIZE_15:
1463 pr_err("Invalid sn_size for %s\n", __func__);
1468 SEQLOAD(p, MATH0, offset, length, 0);
1469 JUMP(p, 1, LOCAL_JUMP, ALL_TRUE, CALM);
1470 MATHB(p, MATH0, AND, sn_mask, MATH1, 8, IFB | IMMED2);
1471 MATHB(p, MATH1, SHLD, MATH1, MATH1, 8, 0);
1472 MOVEB(p, DESCBUF, 4, MATH2, 0, 0x08, WAITCOMP | IMMED);
1473 MATHB(p, MATH1, OR, MATH2, MATH2, 8, 0);
1474 SEQSTORE(p, MATH0, offset, length, 0);
1475 if (dir == OP_TYPE_ENCAP_PROTOCOL) {
1476 if (rta_sec_era > RTA_SEC_ERA_2 ||
1477 (rta_sec_era == RTA_SEC_ERA_2 &&
1478 era_2_sw_hfn_ovrd == 0)) {
1479 SEQINPTR(p, 0, length, RTO);
1481 SEQINPTR(p, 0, 5, RTO);
1482 SEQFIFOLOAD(p, SKIP, 4, 0);
1484 KEY(p, KEY1, authdata->key_enc_flags, authdata->key,
1485 authdata->keylen, INLINE_KEY(authdata));
1486 MOVEB(p, MATH2, 0, IFIFOAB1, 0, 0x08, IMMED);
1488 if (rta_sec_era > RTA_SEC_ERA_2) {
1489 MATHB(p, SEQINSZ, SUB, ZERO, VSEQINSZ, 4, 0);
1490 MATHB(p, SEQINSZ, SUB, ZERO, MATH1, 4, 0);
1491 MATHB(p, VSEQINSZ, ADD, PDCP_MAC_I_LEN - 1, VSEQOUTSZ,
1494 MATHB(p, SEQINSZ, SUB, MATH3, VSEQINSZ, 4, 0);
1495 MATHB(p, VSEQINSZ, ADD, PDCP_MAC_I_LEN - 1, VSEQOUTSZ,
1498 * Note: Although the calculations below might seem a
1499 * little off, the logic is the following:
1501 * - SEQ IN PTR RTO below needs the full length of the
1502 * frame; in case of P4080_REV_2_HFN_OV_WORKAROUND,
1503 * this means the length of the frame to be processed
1504 * + 4 bytes (the HFN override flag and value).
1505 * The length of the frame to be processed minus 1
1506 * byte is in the VSIL register (because
1507 * VSIL = SIL + 3, due to 1 byte, the header being
1508 * already written by the SEQ STORE above). So for
1509 * calculating the length to use in RTO, I add one
1510 * to the VSIL value in order to obtain the total
1511 * frame length. This helps in case of P4080 which
1512 * can have the value 0 as an operand in a MATH
1513 * command only as SRC1 When the HFN override
1514 * workaround is not enabled, the length of the
1515 * frame is given by the SIL register; the
1516 * calculation is similar to the one in the SEC 4.2
1517 * and SEC 5.3 cases.
1519 if (era_2_sw_hfn_ovrd)
1520 MATHB(p, VSEQOUTSZ, ADD, ONE, MATH1, 4,
1523 MATHB(p, SEQINSZ, ADD, MATH3, MATH1, 4,
1527 * Placeholder for filling the length in
1528 * SEQIN PTR RTO below
1530 seqin_ptr_read = MOVE(p, DESCBUF, 0, MATH1, 0, 6, IMMED);
1531 seqin_ptr_write = MOVE(p, MATH1, 0, DESCBUF, 0, 8,
1533 ALG_OPERATION(p, OP_ALG_ALGSEL_AES,
1535 OP_ALG_AS_INITFINAL,
1538 SEQFIFOLOAD(p, MSG1, 0, VLF | LAST1 | FLUSH1);
1539 MOVEB(p, CONTEXT1, 0, MATH3, 0, 4, WAITCOMP | IMMED);
1540 if (rta_sec_era <= RTA_SEC_ERA_3)
1541 LOAD(p, CLRW_CLR_C1KEY |
1548 LOAD(p, CLRW_RESET_CLS1_CHA |
1556 if (rta_sec_era <= RTA_SEC_ERA_3)
1557 LOAD(p, CCTRL_RESET_CHA_ALL, CCTRL, 0, 4, IMMED);
1559 KEY(p, KEY1, cipherdata->key_enc_flags, cipherdata->key,
1560 cipherdata->keylen, INLINE_KEY(cipherdata));
1561 SET_LABEL(p, local_offset);
1562 MOVEB(p, MATH2, 0, CONTEXT1, 0, 8, IMMED);
1563 SEQINPTR(p, 0, 0, RTO);
1565 if (rta_sec_era == RTA_SEC_ERA_2 && era_2_sw_hfn_ovrd) {
1566 SEQFIFOLOAD(p, SKIP, 5, 0);
1567 MATHB(p, SEQINSZ, ADD, ONE, SEQINSZ, 4, 0);
1570 MATHB(p, SEQINSZ, SUB, length, VSEQINSZ, 4, IMMED2);
1571 ALG_OPERATION(p, OP_ALG_ALGSEL_SNOW_F8,
1573 OP_ALG_AS_INITFINAL,
1576 SEQFIFOSTORE(p, MSG, 0, 0, VLF);
1578 if (rta_sec_era > RTA_SEC_ERA_2 ||
1579 (rta_sec_era == RTA_SEC_ERA_2 &&
1580 era_2_sw_hfn_ovrd == 0))
1581 SEQFIFOLOAD(p, SKIP, length, 0);
1583 SEQFIFOLOAD(p, MSG1, 0, VLF);
1584 MOVEB(p, MATH3, 0, IFIFOAB1, 0, 4, LAST1 | FLUSH1 | IMMED);
1585 PATCH_MOVE(p, seqin_ptr_read, local_offset);
1586 PATCH_MOVE(p, seqin_ptr_write, local_offset);
1588 MOVEB(p, MATH2, 0, CONTEXT1, 0, 8, IMMED);
1590 if (rta_sec_era >= RTA_SEC_ERA_5)
1591 MOVE(p, CONTEXT1, 0, CONTEXT2, 0, 8, IMMED);
1593 if (rta_sec_era > RTA_SEC_ERA_2)
1594 MATHB(p, SEQINSZ, SUB, ZERO, VSEQINSZ, 4, 0);
1596 MATHB(p, SEQINSZ, SUB, MATH3, VSEQINSZ, 4, 0);
1598 MATHI(p, SEQINSZ, SUB, PDCP_MAC_I_LEN, VSEQOUTSZ, 4, IMMED2);
1600 * TODO: To be changed when proper support is added in RTA (can't load a
1601 * command that is also written by RTA (or patch it for that matter).
1602 * Change when proper RTA support is added.
1605 WORD(p, 0x168B0004);
1607 WORD(p, 0x16880404);
1609 jump_back_to_sd_cmd = JUMP(p, 0, LOCAL_JUMP, ALL_TRUE, 0);
1611 * Placeholder for command reading the SEQ OUT command in
1612 * JD. Done for rereading the decrypted data and performing
1613 * the integrity check
1616 * TODO: RTA currently doesn't support patching of length of a MOVE command
1617 * Thus, it is inserted as a raw word, as per PS setting.
1620 seq_out_read = MOVE(p, DESCBUF, 0, MATH1, 0, 20,
1623 seq_out_read = MOVE(p, DESCBUF, 0, MATH1, 0, 16,
1626 MATHB(p, MATH1, XOR, CMD_SEQ_IN_PTR ^ CMD_SEQ_OUT_PTR, MATH1, 4,
1628 /* Placeholder for overwriting the SEQ IN with SEQ OUT */
1630 * TODO: RTA currently doesn't support patching of length of a MOVE command
1631 * Thus, it is inserted as a raw word, as per PS setting.
1634 MOVE(p, MATH1, 0, DESCBUF, 0, 24, IMMED);
1636 MOVE(p, MATH1, 0, DESCBUF, 0, 20, IMMED);
1638 KEY(p, KEY1, cipherdata->key_enc_flags, cipherdata->key,
1639 cipherdata->keylen, INLINE_KEY(cipherdata));
1641 if (rta_sec_era >= RTA_SEC_ERA_4)
1642 MOVE(p, CONTEXT1, 0, CONTEXT2, 0, 8, IMMED);
1644 MOVE(p, CONTEXT1, 0, MATH3, 0, 8, IMMED);
1646 ALG_OPERATION(p, OP_ALG_ALGSEL_SNOW_F8,
1648 OP_ALG_AS_INITFINAL,
1651 SEQFIFOSTORE(p, MSG, 0, 0, VLF | CONT);
1652 SEQFIFOLOAD(p, MSG1, 0, VLF | LAST1 | FLUSH1);
1654 if (rta_sec_era <= RTA_SEC_ERA_3)
1655 move_mac_i_to_desc_buf = MOVE(p, OFIFO, 0, DESCBUF, 0,
1656 4, WAITCOMP | IMMED);
1658 MOVE(p, OFIFO, 0, MATH3, 0, 4, IMMED);
1660 if (rta_sec_era <= RTA_SEC_ERA_3)
1661 LOAD(p, CCTRL_RESET_CHA_ALL, CCTRL, 0, 4, IMMED);
1663 LOAD(p, CLRW_RESET_CLS1_CHA |
1671 KEY(p, KEY1, authdata->key_enc_flags, authdata->key,
1672 authdata->keylen, INLINE_KEY(authdata));
1674 * Placeholder for jump in SD for executing the new SEQ IN PTR
1675 * command (which is actually the old SEQ OUT PTR command
1676 * copied over from JD.
1678 SET_LABEL(p, jump_to_beginning);
1679 JUMP(p, 1 - jump_to_beginning, LOCAL_JUMP, ALL_TRUE, 0);
1680 SET_LABEL(p, back_to_sd_offset);
1681 ALG_OPERATION(p, OP_ALG_ALGSEL_AES,
1683 OP_ALG_AS_INITFINAL,
1687 /* Read the # of bytes written in the output buffer + 1 (HDR) */
1688 MATHI(p, VSEQOUTSZ, ADD, length, VSEQINSZ, 4, IMMED2);
1690 if (rta_sec_era <= RTA_SEC_ERA_3)
1691 MOVE(p, MATH3, 0, IFIFOAB1, 0, 8, IMMED);
1693 MOVE(p, CONTEXT2, 0, IFIFOAB1, 0, 8, IMMED);
1695 if (rta_sec_era == RTA_SEC_ERA_2 && era_2_sw_hfn_ovrd)
1696 SEQFIFOLOAD(p, SKIP, 4, 0);
1698 SEQFIFOLOAD(p, MSG1, 0, VLF | LAST1 | FLUSH1);
1700 if (rta_sec_era >= RTA_SEC_ERA_4) {
1701 LOAD(p, NFIFOENTRY_STYPE_ALTSOURCE |
1702 NFIFOENTRY_DEST_CLASS1 |
1703 NFIFOENTRY_DTYPE_ICV |
1705 NFIFOENTRY_FC1 | 4, NFIFO_SZL, 0, 4, IMMED);
1706 MOVE(p, MATH3, 0, ALTSOURCE, 0, 4, IMMED);
1708 SET_LABEL(p, fifo_load_mac_i_offset);
1709 FIFOLOAD(p, ICV1, fifo_load_mac_i_offset, 4,
1710 LAST1 | FLUSH1 | IMMED);
1713 SET_LABEL(p, end_desc);
1716 PATCH_MOVE(p, seq_out_read, end_desc + 1);
1717 PATCH_JUMP(p, jump_back_to_sd_cmd,
1718 back_to_sd_offset + jump_back_to_sd_cmd - 5);
1720 if (rta_sec_era <= RTA_SEC_ERA_3)
1721 PATCH_MOVE(p, move_mac_i_to_desc_buf,
1722 fifo_load_mac_i_offset + 1);
1724 PATCH_MOVE(p, seq_out_read, end_desc + 2);
1725 PATCH_JUMP(p, jump_back_to_sd_cmd,
1726 back_to_sd_offset + jump_back_to_sd_cmd - 5);
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);
1738 pdcp_insert_cplane_aes_snow_op(struct program *p,
1739 bool swap __maybe_unused,
1740 struct alginfo *cipherdata,
1741 struct alginfo *authdata,
1743 enum pdcp_sn_size sn_size,
1744 unsigned char era_2_sw_hfn_ovrd __maybe_unused)
1746 uint32_t offset = 0, length = 0, sn_mask = 0;
1748 KEY(p, KEY1, cipherdata->key_enc_flags, cipherdata->key,
1749 cipherdata->keylen, INLINE_KEY(cipherdata));
1750 KEY(p, KEY2, authdata->key_enc_flags, authdata->key, authdata->keylen,
1751 INLINE_KEY(authdata));
1753 if ((rta_sec_era >= RTA_SEC_ERA_8 && sn_size != PDCP_SN_SIZE_18) ||
1754 (rta_sec_era == RTA_SEC_ERA_10)) {
1757 if (sn_size == PDCP_SN_SIZE_5)
1758 pclid = OP_PCLID_LTE_PDCP_CTRL_MIXED;
1760 pclid = OP_PCLID_LTE_PDCP_USER_RN;
1762 PROTOCOL(p, dir, pclid,
1763 ((uint16_t)cipherdata->algtype << 8) |
1764 (uint16_t)authdata->algtype);
1768 /* Non-proto is supported only for 5bit cplane and 18bit uplane */
1770 case PDCP_SN_SIZE_5:
1773 sn_mask = (swap == false) ? PDCP_C_PLANE_SN_MASK :
1774 PDCP_C_PLANE_SN_MASK_BE;
1776 case PDCP_SN_SIZE_18:
1779 sn_mask = (swap == false) ? PDCP_U_PLANE_18BIT_SN_MASK :
1780 PDCP_U_PLANE_18BIT_SN_MASK_BE;
1782 case PDCP_SN_SIZE_7:
1783 case PDCP_SN_SIZE_12:
1784 case PDCP_SN_SIZE_15:
1785 pr_err("Invalid sn_size for %s\n", __func__);
1790 if (dir == OP_TYPE_ENCAP_PROTOCOL)
1791 MATHB(p, SEQINSZ, SUB, length, VSEQINSZ, 4, IMMED2);
1793 SEQLOAD(p, MATH0, offset, length, 0);
1794 JUMP(p, 1, LOCAL_JUMP, ALL_TRUE, CALM);
1795 MOVEB(p, MATH0, offset, IFIFOAB2, 0, length, IMMED);
1796 MATHB(p, MATH0, AND, sn_mask, MATH1, 8, IFB | IMMED2);
1798 SEQSTORE(p, MATH0, offset, length, 0);
1799 MATHB(p, MATH1, SHLD, MATH1, MATH1, 8, 0);
1800 MOVEB(p, DESCBUF, 4, MATH2, 0, 8, WAITCOMP | IMMED);
1801 MATHB(p, MATH1, OR, MATH2, MATH1, 8, 0);
1802 MOVEB(p, MATH1, 0, CONTEXT1, 16, 8, IMMED);
1803 MOVEB(p, MATH1, 0, CONTEXT2, 0, 4, IMMED);
1804 if (swap == false) {
1805 MATHB(p, MATH1, AND, upper_32_bits(PDCP_BEARER_MASK), MATH2, 4,
1807 MATHB(p, MATH1, AND, lower_32_bits(PDCP_DIR_MASK), MATH3, 4,
1810 MATHB(p, MATH1, AND, lower_32_bits(PDCP_BEARER_MASK_BE), MATH2,
1812 MATHB(p, MATH1, AND, upper_32_bits(PDCP_DIR_MASK_BE), MATH3,
1815 MATHB(p, MATH3, SHLD, MATH3, MATH3, 8, 0);
1816 MOVEB(p, MATH2, 4, OFIFO, 0, 12, IMMED);
1817 MOVE(p, OFIFO, 0, CONTEXT2, 4, 12, IMMED);
1818 if (dir == OP_TYPE_ENCAP_PROTOCOL) {
1819 MATHB(p, SEQINSZ, ADD, PDCP_MAC_I_LEN, VSEQOUTSZ, 4, IMMED2);
1821 MATHB(p, SEQINSZ, SUB, PDCP_MAC_I_LEN, MATH1, 4, IMMED2);
1823 MATHB(p, ZERO, ADD, MATH1, VSEQOUTSZ, 4, 0);
1824 MATHB(p, ZERO, ADD, MATH1, VSEQINSZ, 4, 0);
1827 if (dir == OP_TYPE_ENCAP_PROTOCOL)
1828 SEQFIFOSTORE(p, MSG, 0, 0, VLF);
1830 SEQFIFOSTORE(p, MSG, 0, 0, VLF | CONT);
1832 ALG_OPERATION(p, OP_ALG_ALGSEL_SNOW_F9,
1834 OP_ALG_AS_INITFINAL,
1835 dir == OP_TYPE_ENCAP_PROTOCOL ?
1836 ICV_CHECK_DISABLE : ICV_CHECK_ENABLE,
1838 ALG_OPERATION(p, OP_ALG_ALGSEL_AES,
1840 OP_ALG_AS_INITFINAL,
1842 dir == OP_TYPE_ENCAP_PROTOCOL ? DIR_ENC : DIR_DEC);
1844 if (dir == OP_TYPE_ENCAP_PROTOCOL) {
1845 SEQFIFOLOAD(p, MSGINSNOOP, 0, VLF | LAST2);
1846 MOVE(p, CONTEXT2, 0, IFIFOAB1, 0, 4, LAST1 | FLUSH1 | IMMED);
1848 SEQFIFOLOAD(p, MSGOUTSNOOP, 0, VLF | LAST2);
1849 SEQFIFOLOAD(p, MSG1, 4, LAST1 | FLUSH1);
1850 JUMP(p, 1, LOCAL_JUMP, ALL_TRUE, CLASS1 | NOP | NIFP);
1852 if (rta_sec_era >= RTA_SEC_ERA_6)
1853 LOAD(p, 0, DCTRL, 0, LDLEN_RST_CHA_OFIFO_PTR, IMMED);
1855 MOVE(p, OFIFO, 0, MATH0, 0, 4, WAITCOMP | IMMED);
1857 NFIFOADD(p, IFIFO, ICV2, 4, LAST2);
1859 if (rta_sec_era <= RTA_SEC_ERA_2) {
1860 /* Shut off automatic Info FIFO entries */
1861 LOAD(p, 0, DCTRL, LDOFF_DISABLE_AUTO_NFIFO, 0, IMMED);
1862 MOVE(p, MATH0, 0, IFIFOAB2, 0, 4, WAITCOMP | IMMED);
1864 MOVE(p, MATH0, 0, IFIFO, 0, 4, WAITCOMP | IMMED);
1872 pdcp_insert_cplane_snow_zuc_op(struct program *p,
1873 bool swap __maybe_unused,
1874 struct alginfo *cipherdata,
1875 struct alginfo *authdata,
1877 enum pdcp_sn_size sn_size,
1878 unsigned char era_2_sw_hfn_ovrd __maybe_unused)
1880 uint32_t offset = 0, length = 0, sn_mask = 0;
1883 REFERENCE(pkeyjump);
1885 if (rta_sec_era < RTA_SEC_ERA_5) {
1886 pr_err("Invalid era for selected algorithm\n");
1890 pkeyjump = JUMP(p, keyjump, LOCAL_JUMP, ALL_TRUE, SHRD | SELF | BOTH);
1891 KEY(p, KEY1, cipherdata->key_enc_flags, cipherdata->key,
1892 cipherdata->keylen, INLINE_KEY(cipherdata));
1893 KEY(p, KEY2, authdata->key_enc_flags, authdata->key, authdata->keylen,
1894 INLINE_KEY(authdata));
1896 SET_LABEL(p, keyjump);
1898 if ((rta_sec_era >= RTA_SEC_ERA_8 && sn_size != PDCP_SN_SIZE_18) ||
1899 (rta_sec_era == RTA_SEC_ERA_10)) {
1902 if (sn_size == PDCP_SN_SIZE_5)
1903 pclid = OP_PCLID_LTE_PDCP_CTRL_MIXED;
1905 pclid = OP_PCLID_LTE_PDCP_USER_RN;
1907 PROTOCOL(p, dir, pclid,
1908 ((uint16_t)cipherdata->algtype << 8) |
1909 (uint16_t)authdata->algtype);
1912 /* Non-proto is supported only for 5bit cplane and 18bit uplane */
1914 case PDCP_SN_SIZE_5:
1917 sn_mask = (swap == false) ? PDCP_C_PLANE_SN_MASK :
1918 PDCP_C_PLANE_SN_MASK_BE;
1920 case PDCP_SN_SIZE_18:
1923 sn_mask = (swap == false) ? PDCP_U_PLANE_18BIT_SN_MASK :
1924 PDCP_U_PLANE_18BIT_SN_MASK_BE;
1926 case PDCP_SN_SIZE_7:
1927 case PDCP_SN_SIZE_12:
1928 case PDCP_SN_SIZE_15:
1929 pr_err("Invalid sn_size for %s\n", __func__);
1934 SEQLOAD(p, MATH0, offset, length, 0);
1935 JUMP(p, 1, LOCAL_JUMP, ALL_TRUE, CALM);
1936 MOVEB(p, MATH0, offset, IFIFOAB2, 0, length, IMMED);
1937 MATHB(p, MATH0, AND, sn_mask, MATH1, 8, IFB | IMMED2);
1939 MATHB(p, MATH1, SHLD, MATH1, MATH1, 8, 0);
1940 MOVEB(p, DESCBUF, 4, MATH2, 0, 8, WAITCOMP | IMMED);
1941 MATHB(p, MATH1, OR, MATH2, MATH2, 8, 0);
1942 MOVEB(p, MATH2, 0, CONTEXT1, 0, 8, IMMED);
1943 MOVEB(p, MATH2, 0, CONTEXT2, 0, 8, WAITCOMP | IMMED);
1945 if (dir == OP_TYPE_ENCAP_PROTOCOL)
1946 MATHB(p, SEQINSZ, ADD, PDCP_MAC_I_LEN, VSEQOUTSZ, 4, IMMED2);
1948 MATHB(p, SEQINSZ, SUB, PDCP_MAC_I_LEN, VSEQOUTSZ, 4, IMMED2);
1950 MATHB(p, SEQINSZ, SUB, ZERO, VSEQINSZ, 4, 0);
1951 SEQSTORE(p, MATH0, offset, length, 0);
1953 if (dir == OP_TYPE_ENCAP_PROTOCOL) {
1954 SEQFIFOSTORE(p, MSG, 0, 0, VLF);
1955 SEQFIFOLOAD(p, MSGINSNOOP, 0, VLF | LAST2);
1957 SEQFIFOSTORE(p, MSG, 0, 0, VLF | CONT);
1958 SEQFIFOLOAD(p, MSGOUTSNOOP, 0, VLF | LAST1 | FLUSH1);
1961 ALG_OPERATION(p, OP_ALG_ALGSEL_ZUCA,
1963 OP_ALG_AS_INITFINAL,
1964 dir == OP_TYPE_ENCAP_PROTOCOL ?
1965 ICV_CHECK_DISABLE : ICV_CHECK_ENABLE,
1968 ALG_OPERATION(p, OP_ALG_ALGSEL_SNOW_F8,
1970 OP_ALG_AS_INITFINAL,
1972 dir == OP_TYPE_ENCAP_PROTOCOL ? DIR_ENC : DIR_DEC);
1973 if (dir == OP_TYPE_ENCAP_PROTOCOL) {
1974 MOVE(p, CONTEXT2, 0, IFIFOAB1, 0, 4, LAST1 | FLUSH1 | IMMED);
1977 MOVE(p, OFIFO, 0, MATH0, 0, 4, IMMED);
1978 LOAD(p, NFIFOENTRY_STYPE_ALTSOURCE |
1979 NFIFOENTRY_DEST_CLASS2 |
1980 NFIFOENTRY_DTYPE_ICV |
1981 NFIFOENTRY_LC2 | 4, NFIFO_SZL, 0, 4, IMMED);
1982 MOVE(p, MATH0, 0, ALTSOURCE, 0, 4, WAITCOMP | IMMED);
1985 /* Reset ZUCA mode and done interrupt */
1986 LOAD(p, CLRW_CLR_C2MODE, CLRW, 0, 4, IMMED);
1987 LOAD(p, CIRQ_ZADI, ICTRL, 0, 4, IMMED);
1989 PATCH_JUMP(p, pkeyjump, keyjump);
1994 pdcp_insert_cplane_aes_zuc_op(struct program *p,
1995 bool swap __maybe_unused,
1996 struct alginfo *cipherdata,
1997 struct alginfo *authdata,
1999 enum pdcp_sn_size sn_size,
2000 unsigned char era_2_sw_hfn_ovrd __maybe_unused)
2002 uint32_t offset = 0, length = 0, sn_mask = 0;
2004 REFERENCE(pkeyjump);
2006 if (rta_sec_era < RTA_SEC_ERA_5) {
2007 pr_err("Invalid era for selected algorithm\n");
2011 pkeyjump = JUMP(p, keyjump, LOCAL_JUMP, ALL_TRUE, SHRD | SELF | BOTH);
2012 KEY(p, KEY1, cipherdata->key_enc_flags, cipherdata->key,
2013 cipherdata->keylen, INLINE_KEY(cipherdata));
2014 KEY(p, KEY2, authdata->key_enc_flags, authdata->key, authdata->keylen,
2015 INLINE_KEY(authdata));
2017 if ((rta_sec_era >= RTA_SEC_ERA_8 && sn_size != PDCP_SN_SIZE_18) ||
2018 (rta_sec_era == RTA_SEC_ERA_10)) {
2021 if (sn_size == PDCP_SN_SIZE_5)
2022 pclid = OP_PCLID_LTE_PDCP_CTRL_MIXED;
2024 pclid = OP_PCLID_LTE_PDCP_USER_RN;
2026 PROTOCOL(p, dir, pclid,
2027 ((uint16_t)cipherdata->algtype << 8) |
2028 (uint16_t)authdata->algtype);
2032 /* Non-proto is supported only for 5bit cplane and 18bit uplane */
2034 case PDCP_SN_SIZE_5:
2037 sn_mask = (swap == false) ? PDCP_C_PLANE_SN_MASK :
2038 PDCP_C_PLANE_SN_MASK_BE;
2040 case PDCP_SN_SIZE_18:
2043 sn_mask = (swap == false) ? PDCP_U_PLANE_18BIT_SN_MASK :
2044 PDCP_U_PLANE_18BIT_SN_MASK_BE;
2046 case PDCP_SN_SIZE_7:
2047 case PDCP_SN_SIZE_12:
2048 case PDCP_SN_SIZE_15:
2049 pr_err("Invalid sn_size for %s\n", __func__);
2054 SET_LABEL(p, keyjump);
2055 SEQLOAD(p, MATH0, offset, length, 0);
2056 JUMP(p, 1, LOCAL_JUMP, ALL_TRUE, CALM);
2057 MOVEB(p, MATH0, offset, IFIFOAB2, 0, length, IMMED);
2058 MATHB(p, MATH0, AND, sn_mask, MATH1, 8, IFB | IMMED2);
2060 MATHB(p, MATH1, SHLD, MATH1, MATH1, 8, 0);
2061 MOVEB(p, DESCBUF, 4, MATH2, 0, 8, WAITCOMP | IMMED);
2062 MATHB(p, MATH1, OR, MATH2, MATH2, 8, 0);
2063 MOVEB(p, MATH2, 0, CONTEXT1, 16, 8, IMMED);
2064 MOVEB(p, MATH2, 0, CONTEXT2, 0, 8, WAITCOMP | IMMED);
2066 if (dir == OP_TYPE_ENCAP_PROTOCOL)
2067 MATHB(p, SEQINSZ, ADD, PDCP_MAC_I_LEN, VSEQOUTSZ, 4, IMMED2);
2069 MATHB(p, SEQINSZ, SUB, PDCP_MAC_I_LEN, VSEQOUTSZ, 4, IMMED2);
2071 MATHB(p, SEQINSZ, SUB, ZERO, VSEQINSZ, 4, 0);
2072 SEQSTORE(p, MATH0, offset, length, 0);
2074 if (dir == OP_TYPE_ENCAP_PROTOCOL) {
2075 SEQFIFOSTORE(p, MSG, 0, 0, VLF);
2076 SEQFIFOLOAD(p, MSGINSNOOP, 0, VLF | LAST2);
2078 SEQFIFOSTORE(p, MSG, 0, 0, VLF | CONT);
2079 SEQFIFOLOAD(p, MSGOUTSNOOP, 0, VLF | LAST1 | FLUSH1);
2082 ALG_OPERATION(p, OP_ALG_ALGSEL_ZUCA,
2084 OP_ALG_AS_INITFINAL,
2085 dir == OP_TYPE_ENCAP_PROTOCOL ?
2086 ICV_CHECK_DISABLE : ICV_CHECK_ENABLE,
2089 ALG_OPERATION(p, OP_ALG_ALGSEL_AES,
2091 OP_ALG_AS_INITFINAL,
2093 dir == OP_TYPE_ENCAP_PROTOCOL ? DIR_ENC : DIR_DEC);
2095 if (dir == OP_TYPE_ENCAP_PROTOCOL) {
2096 MOVE(p, CONTEXT2, 0, IFIFOAB1, 0, 4, LAST1 | FLUSH1 | IMMED);
2099 MOVE(p, OFIFO, 0, MATH0, 0, 4, IMMED);
2101 LOAD(p, NFIFOENTRY_STYPE_ALTSOURCE |
2102 NFIFOENTRY_DEST_CLASS2 |
2103 NFIFOENTRY_DTYPE_ICV |
2104 NFIFOENTRY_LC2 | 4, NFIFO_SZL, 0, 4, IMMED);
2105 MOVE(p, MATH0, 0, ALTSOURCE, 0, 4, WAITCOMP | IMMED);
2108 /* Reset ZUCA mode and done interrupt */
2109 LOAD(p, CLRW_CLR_C2MODE, CLRW, 0, 4, IMMED);
2110 LOAD(p, CIRQ_ZADI, ICTRL, 0, 4, IMMED);
2112 PATCH_JUMP(p, pkeyjump, keyjump);
2118 pdcp_insert_cplane_zuc_snow_op(struct program *p,
2119 bool swap __maybe_unused,
2120 struct alginfo *cipherdata,
2121 struct alginfo *authdata,
2123 enum pdcp_sn_size sn_size,
2124 unsigned char era_2_sw_hfn_ovrd __maybe_unused)
2126 uint32_t offset = 0, length = 0, sn_mask = 0;
2128 REFERENCE(pkeyjump);
2130 if (rta_sec_era < RTA_SEC_ERA_5) {
2131 pr_err("Invalid era for selected algorithm\n");
2135 pkeyjump = JUMP(p, keyjump, LOCAL_JUMP, ALL_TRUE, SHRD | SELF | BOTH);
2136 KEY(p, KEY1, cipherdata->key_enc_flags, cipherdata->key,
2137 cipherdata->keylen, INLINE_KEY(cipherdata));
2138 KEY(p, KEY2, authdata->key_enc_flags, authdata->key, authdata->keylen,
2139 INLINE_KEY(authdata));
2141 if ((rta_sec_era >= RTA_SEC_ERA_8 && sn_size != PDCP_SN_SIZE_18) ||
2142 (rta_sec_era == RTA_SEC_ERA_10)) {
2145 if (sn_size == PDCP_SN_SIZE_5)
2146 pclid = OP_PCLID_LTE_PDCP_CTRL_MIXED;
2148 pclid = OP_PCLID_LTE_PDCP_USER_RN;
2150 PROTOCOL(p, dir, pclid,
2151 ((uint16_t)cipherdata->algtype << 8) |
2152 (uint16_t)authdata->algtype);
2156 /* Non-proto is supported only for 5bit cplane and 18bit uplane */
2158 case PDCP_SN_SIZE_5:
2161 sn_mask = (swap == false) ? PDCP_C_PLANE_SN_MASK :
2162 PDCP_C_PLANE_SN_MASK_BE;
2164 case PDCP_SN_SIZE_18:
2167 sn_mask = (swap == false) ? PDCP_U_PLANE_18BIT_SN_MASK :
2168 PDCP_U_PLANE_18BIT_SN_MASK_BE;
2170 case PDCP_SN_SIZE_7:
2171 case PDCP_SN_SIZE_12:
2172 case PDCP_SN_SIZE_15:
2173 pr_err("Invalid sn_size for %s\n", __func__);
2177 SET_LABEL(p, keyjump);
2178 SEQLOAD(p, MATH0, offset, length, 0);
2179 JUMP(p, 1, LOCAL_JUMP, ALL_TRUE, CALM);
2180 MOVEB(p, MATH0, offset, IFIFOAB2, 0, length, IMMED);
2181 MATHB(p, MATH0, AND, sn_mask, MATH1, 8, IFB | IMMED2);
2183 MATHB(p, MATH1, SHLD, MATH1, MATH1, 8, 0);
2184 MOVEB(p, DESCBUF, 4, MATH2, 0, 8, WAITCOMP | IMMED);
2185 MATHB(p, MATH1, OR, MATH2, MATH1, 8, 0);
2186 MOVEB(p, MATH1, 0, CONTEXT1, 0, 8, IMMED);
2187 MOVEB(p, MATH1, 0, CONTEXT2, 0, 4, IMMED);
2188 if (swap == false) {
2189 MATHB(p, MATH1, AND, upper_32_bits(PDCP_BEARER_MASK), MATH2,
2191 MATHB(p, MATH1, AND, lower_32_bits(PDCP_DIR_MASK), MATH3,
2194 MATHB(p, MATH1, AND, lower_32_bits(PDCP_BEARER_MASK_BE), MATH2,
2196 MATHB(p, MATH1, AND, upper_32_bits(PDCP_DIR_MASK_BE), MATH3,
2199 MATHB(p, MATH3, SHLD, MATH3, MATH3, 8, 0);
2200 MOVEB(p, MATH2, 4, OFIFO, 0, 12, IMMED);
2201 MOVE(p, OFIFO, 0, CONTEXT2, 4, 12, IMMED);
2203 if (dir == OP_TYPE_ENCAP_PROTOCOL) {
2204 MATHB(p, SEQINSZ, ADD, PDCP_MAC_I_LEN, VSEQOUTSZ, 4, IMMED2);
2205 MATHB(p, SEQINSZ, SUB, ZERO, VSEQINSZ, 4, 0);
2207 MATHB(p, SEQINSZ, SUB, PDCP_MAC_I_LEN, VSEQOUTSZ, 4, IMMED2);
2208 MATHB(p, VSEQOUTSZ, SUB, ZERO, VSEQINSZ, 4, 0);
2211 SEQSTORE(p, MATH0, offset, length, 0);
2213 if (dir == OP_TYPE_ENCAP_PROTOCOL) {
2214 SEQFIFOSTORE(p, MSG, 0, 0, VLF);
2215 SEQFIFOLOAD(p, MSGINSNOOP, 0, VLF | LAST2);
2217 SEQFIFOSTORE(p, MSG, 0, 0, VLF | CONT);
2218 SEQFIFOLOAD(p, MSGOUTSNOOP, 0, VLF | LAST2);
2221 ALG_OPERATION(p, OP_ALG_ALGSEL_SNOW_F9,
2223 OP_ALG_AS_INITFINAL,
2224 dir == OP_TYPE_ENCAP_PROTOCOL ?
2225 ICV_CHECK_DISABLE : ICV_CHECK_ENABLE,
2228 ALG_OPERATION(p, OP_ALG_ALGSEL_ZUCE,
2230 OP_ALG_AS_INITFINAL,
2232 dir == OP_TYPE_ENCAP_PROTOCOL ? DIR_ENC : DIR_DEC);
2234 if (dir == OP_TYPE_ENCAP_PROTOCOL) {
2235 MOVE(p, CONTEXT2, 0, IFIFOAB1, 0, 4, LAST1 | FLUSH1 | IMMED);
2237 SEQFIFOLOAD(p, MSG1, 4, LAST1 | FLUSH1);
2238 JUMP(p, 1, LOCAL_JUMP, ALL_TRUE, CLASS1 | NOP | NIFP);
2240 if (rta_sec_era >= RTA_SEC_ERA_6)
2242 * For SEC ERA 6, there's a problem with the OFIFO
2243 * pointer, and thus it needs to be reset here before
2246 LOAD(p, 0, DCTRL, 0, LDLEN_RST_CHA_OFIFO_PTR, IMMED);
2248 /* Put ICV to M0 before sending it to C2 for comparison. */
2249 MOVEB(p, OFIFO, 0, MATH0, 0, 4, WAITCOMP | IMMED);
2251 LOAD(p, NFIFOENTRY_STYPE_ALTSOURCE |
2252 NFIFOENTRY_DEST_CLASS2 |
2253 NFIFOENTRY_DTYPE_ICV |
2254 NFIFOENTRY_LC2 | 4, NFIFO_SZL, 0, 4, IMMED);
2255 MOVEB(p, MATH0, 0, ALTSOURCE, 0, 4, IMMED);
2258 PATCH_JUMP(p, pkeyjump, keyjump);
2263 pdcp_insert_cplane_zuc_aes_op(struct program *p,
2264 bool swap __maybe_unused,
2265 struct alginfo *cipherdata,
2266 struct alginfo *authdata,
2268 enum pdcp_sn_size sn_size,
2269 unsigned char era_2_sw_hfn_ovrd __maybe_unused)
2271 uint32_t offset = 0, length = 0, sn_mask = 0;
2272 if (rta_sec_era < RTA_SEC_ERA_5) {
2273 pr_err("Invalid era for selected algorithm\n");
2277 if ((rta_sec_era >= RTA_SEC_ERA_8 && sn_size != PDCP_SN_SIZE_18) ||
2278 (rta_sec_era == RTA_SEC_ERA_10)) {
2281 KEY(p, KEY1, cipherdata->key_enc_flags, cipherdata->key,
2282 cipherdata->keylen, INLINE_KEY(cipherdata));
2283 KEY(p, KEY2, authdata->key_enc_flags, authdata->key,
2284 authdata->keylen, INLINE_KEY(authdata));
2286 if (sn_size == PDCP_SN_SIZE_5)
2287 pclid = OP_PCLID_LTE_PDCP_CTRL_MIXED;
2289 pclid = OP_PCLID_LTE_PDCP_USER_RN;
2291 PROTOCOL(p, dir, pclid,
2292 ((uint16_t)cipherdata->algtype << 8) |
2293 (uint16_t)authdata->algtype);
2296 /* Non-proto is supported only for 5bit cplane and 18bit uplane */
2298 case PDCP_SN_SIZE_5:
2301 sn_mask = (swap == false) ? PDCP_C_PLANE_SN_MASK :
2302 PDCP_C_PLANE_SN_MASK_BE;
2304 case PDCP_SN_SIZE_18:
2307 sn_mask = (swap == false) ? PDCP_U_PLANE_18BIT_SN_MASK :
2308 PDCP_U_PLANE_18BIT_SN_MASK_BE;
2310 case PDCP_SN_SIZE_7:
2311 case PDCP_SN_SIZE_12:
2312 case PDCP_SN_SIZE_15:
2313 pr_err("Invalid sn_size for %s\n", __func__);
2317 SEQLOAD(p, MATH0, offset, length, 0);
2318 JUMP(p, 1, LOCAL_JUMP, ALL_TRUE, CALM);
2319 MATHB(p, MATH0, AND, sn_mask, MATH1, 8, IFB | IMMED2);
2321 MATHB(p, MATH1, SHLD, MATH1, MATH1, 8, 0);
2322 MOVEB(p, DESCBUF, 4, MATH2, 0, 0x08, WAITCOMP | IMMED);
2323 MATHB(p, MATH1, OR, MATH2, MATH2, 8, 0);
2324 SEQSTORE(p, MATH0, offset, length, 0);
2325 if (dir == OP_TYPE_ENCAP_PROTOCOL) {
2326 KEY(p, KEY1, authdata->key_enc_flags, authdata->key,
2327 authdata->keylen, INLINE_KEY(authdata));
2328 MOVEB(p, MATH2, 0, IFIFOAB1, 0, 0x08, IMMED);
2329 MOVEB(p, MATH0, offset, IFIFOAB1, 0, length, IMMED);
2331 MATHB(p, SEQINSZ, SUB, ZERO, VSEQINSZ, 4, 0);
2332 MATHB(p, VSEQINSZ, ADD, PDCP_MAC_I_LEN, VSEQOUTSZ, 4, IMMED2);
2334 ALG_OPERATION(p, OP_ALG_ALGSEL_AES,
2336 OP_ALG_AS_INITFINAL,
2339 SEQFIFOLOAD(p, MSG1, 0, VLF | LAST1 | FLUSH1);
2340 MOVEB(p, CONTEXT1, 0, MATH3, 0, 4, WAITCOMP | IMMED);
2341 LOAD(p, CLRW_RESET_CLS1_CHA |
2349 KEY(p, KEY1, cipherdata->key_enc_flags, cipherdata->key,
2350 cipherdata->keylen, INLINE_KEY(cipherdata));
2352 MOVEB(p, MATH2, 0, CONTEXT1, 0, 8, IMMED);
2353 SEQINPTR(p, 0, PDCP_NULL_MAX_FRAME_LEN, RTO);
2355 ALG_OPERATION(p, OP_ALG_ALGSEL_ZUCE,
2357 OP_ALG_AS_INITFINAL,
2360 SEQFIFOSTORE(p, MSG, 0, 0, VLF);
2362 SEQFIFOLOAD(p, SKIP, length, 0);
2364 SEQFIFOLOAD(p, MSG1, 0, VLF);
2365 MOVEB(p, MATH3, 0, IFIFOAB1, 0, 4, LAST1 | FLUSH1 | IMMED);
2367 MOVEB(p, MATH2, 0, CONTEXT1, 0, 8, IMMED);
2369 MOVE(p, CONTEXT1, 0, CONTEXT2, 0, 8, IMMED);
2371 MATHB(p, SEQINSZ, SUB, ZERO, VSEQINSZ, 4, 0);
2373 MATHB(p, SEQINSZ, SUB, PDCP_MAC_I_LEN, VSEQOUTSZ, 4, IMMED2);
2375 KEY(p, KEY1, cipherdata->key_enc_flags, cipherdata->key,
2376 cipherdata->keylen, INLINE_KEY(cipherdata));
2378 MOVE(p, CONTEXT1, 0, CONTEXT2, 0, 8, IMMED);
2380 ALG_OPERATION(p, OP_ALG_ALGSEL_ZUCE,
2382 OP_ALG_AS_INITFINAL,
2385 SEQFIFOSTORE(p, MSG, 0, 0, VLF | CONT);
2386 SEQFIFOLOAD(p, MSG1, 0, VLF | LAST1 | FLUSH1);
2388 MOVEB(p, OFIFO, 0, MATH3, 0, 4, IMMED);
2390 LOAD(p, CLRW_RESET_CLS1_CHA |
2398 KEY(p, KEY1, authdata->key_enc_flags, authdata->key,
2399 authdata->keylen, INLINE_KEY(authdata));
2401 SEQINPTR(p, 0, 0, SOP);
2403 ALG_OPERATION(p, OP_ALG_ALGSEL_AES,
2405 OP_ALG_AS_INITFINAL,
2409 MATHB(p, SEQINSZ, SUB, ZERO, VSEQINSZ, 4, 0);
2411 MOVE(p, CONTEXT2, 0, IFIFOAB1, 0, 8, IMMED);
2413 SEQFIFOLOAD(p, MSG1, 0, VLF | LAST1 | FLUSH1);
2415 LOAD(p, NFIFOENTRY_STYPE_ALTSOURCE |
2416 NFIFOENTRY_DEST_CLASS1 |
2417 NFIFOENTRY_DTYPE_ICV |
2419 NFIFOENTRY_FC1 | 4, NFIFO_SZL, 0, 4, IMMED);
2420 MOVEB(p, MATH3, 0, ALTSOURCE, 0, 4, IMMED);
2427 pdcp_insert_uplane_no_int_op(struct program *p,
2428 bool swap __maybe_unused,
2429 struct alginfo *cipherdata,
2431 enum pdcp_sn_size sn_size)
2436 /* Insert Cipher Key */
2437 KEY(p, KEY1, cipherdata->key_enc_flags, cipherdata->key,
2438 cipherdata->keylen, INLINE_KEY(cipherdata));
2440 if ((rta_sec_era >= RTA_SEC_ERA_8 && sn_size == PDCP_SN_SIZE_15) ||
2441 (rta_sec_era >= RTA_SEC_ERA_10)) {
2442 PROTOCOL(p, dir, OP_PCLID_LTE_PDCP_USER,
2443 (uint16_t)cipherdata->algtype);
2447 if (sn_size == PDCP_SN_SIZE_15) {
2448 SEQLOAD(p, MATH0, 6, 2, 0);
2449 sn_mask = (swap == false) ? PDCP_U_PLANE_15BIT_SN_MASK :
2450 PDCP_U_PLANE_15BIT_SN_MASK_BE;
2451 } else { /* SN Size == PDCP_SN_SIZE_18 */
2452 SEQLOAD(p, MATH0, 5, 3, 0);
2453 sn_mask = (swap == false) ? PDCP_U_PLANE_18BIT_SN_MASK :
2454 PDCP_U_PLANE_18BIT_SN_MASK_BE;
2456 JUMP(p, 1, LOCAL_JUMP, ALL_TRUE, CALM);
2457 MATHB(p, MATH0, AND, sn_mask, MATH1, 8, IFB | IMMED2);
2459 if (sn_size == PDCP_SN_SIZE_15)
2460 SEQSTORE(p, MATH0, 6, 2, 0);
2461 else /* SN Size == PDCP_SN_SIZE_18 */
2462 SEQSTORE(p, MATH0, 5, 3, 0);
2464 MATHB(p, MATH1, SHLD, MATH1, MATH1, 8, 0);
2465 MOVEB(p, DESCBUF, 8, MATH2, 0, 8, WAITCOMP | IMMED);
2466 MATHB(p, MATH1, OR, MATH2, MATH2, 8, 0);
2468 MATHB(p, SEQINSZ, SUB, MATH3, VSEQINSZ, 4, 0);
2469 MATHB(p, SEQINSZ, SUB, MATH3, VSEQOUTSZ, 4, 0);
2471 SEQFIFOSTORE(p, MSG, 0, 0, VLF);
2473 op = dir == OP_TYPE_ENCAP_PROTOCOL ? DIR_ENC : DIR_DEC;
2474 switch (cipherdata->algtype) {
2475 case PDCP_CIPHER_TYPE_SNOW:
2476 MOVEB(p, MATH2, 0, CONTEXT1, 0, 8, WAITCOMP | IMMED);
2477 ALG_OPERATION(p, OP_ALG_ALGSEL_SNOW_F8,
2479 OP_ALG_AS_INITFINAL,
2484 case PDCP_CIPHER_TYPE_AES:
2485 MOVEB(p, MATH2, 0, CONTEXT1, 0x10, 0x10, WAITCOMP | IMMED);
2486 ALG_OPERATION(p, OP_ALG_ALGSEL_AES,
2488 OP_ALG_AS_INITFINAL,
2493 case PDCP_CIPHER_TYPE_ZUC:
2494 if (rta_sec_era < RTA_SEC_ERA_5) {
2495 pr_err("Invalid era for selected algorithm\n");
2498 MOVEB(p, MATH2, 0, CONTEXT1, 0, 0x08, IMMED);
2499 MOVEB(p, MATH2, 0, CONTEXT1, 0x08, 0x08, WAITCOMP | IMMED);
2501 ALG_OPERATION(p, OP_ALG_ALGSEL_ZUCE,
2503 OP_ALG_AS_INITFINAL,
2509 pr_err("%s: Invalid encrypt algorithm selected: %d\n",
2510 "pdcp_insert_uplane_15bit_op", cipherdata->algtype);
2514 SEQFIFOLOAD(p, MSG1, 0, VLF | LAST1 | FLUSH1);
2520 * Function for inserting the snippet of code responsible for creating
2521 * the HFN override code via either DPOVRD or via the input frame.
2524 insert_hfn_ov_op(struct program *p,
2526 enum pdb_type_e pdb_type,
2527 unsigned char era_2_sw_hfn_ovrd)
2529 uint32_t imm = PDCP_DPOVRD_HFN_OV_EN;
2530 uint16_t hfn_pdb_offset;
2532 REFERENCE(pkeyjump);
2534 if (rta_sec_era == RTA_SEC_ERA_2 && !era_2_sw_hfn_ovrd)
2538 case PDCP_PDB_TYPE_NO_PDB:
2540 * If there is no PDB, then HFN override mechanism does not
2541 * make any sense, thus in this case the function will
2542 * return the pointer to the current position in the
2547 case PDCP_PDB_TYPE_REDUCED_PDB:
2551 case PDCP_PDB_TYPE_FULL_PDB:
2559 if (rta_sec_era > RTA_SEC_ERA_2) {
2560 MATHB(p, DPOVRD, AND, imm, NONE, 8, IFB | IMMED2);
2562 SEQLOAD(p, MATH0, 4, 4, 0);
2563 JUMP(p, 1, LOCAL_JUMP, ALL_TRUE, CALM);
2564 MATHB(p, MATH0, AND, imm, NONE, 8, IFB | IMMED2);
2565 SEQSTORE(p, MATH0, 4, 4, 0);
2568 pkeyjump = JUMP(p, keyjump, LOCAL_JUMP, ALL_TRUE, MATH_Z);
2570 if (rta_sec_era > RTA_SEC_ERA_2)
2571 MATHI(p, DPOVRD, LSHIFT, shift, MATH0, 4, IMMED2);
2573 MATHB(p, MATH0, LSHIFT, shift, MATH0, 4, IMMED2);
2575 MATHB(p, MATH0, SHLD, MATH0, MATH0, 8, 0);
2576 MOVE(p, MATH0, 0, DESCBUF, hfn_pdb_offset, 4, IMMED);
2578 if (rta_sec_era >= RTA_SEC_ERA_8)
2580 * For ERA8, DPOVRD could be handled by the PROTOCOL command
2581 * itself. For now, this is not done. Thus, clear DPOVRD here
2582 * to alleviate any side-effects.
2584 MATHB(p, DPOVRD, AND, ZERO, DPOVRD, 4, STL);
2586 SET_LABEL(p, keyjump);
2587 PATCH_JUMP(p, pkeyjump, keyjump);
2592 * PDCP Control PDB creation function
2594 static inline enum pdb_type_e
2595 cnstr_pdcp_c_plane_pdb(struct program *p,
2597 enum pdcp_sn_size sn_size,
2598 unsigned char bearer,
2599 unsigned char direction,
2600 uint32_t hfn_threshold,
2601 struct alginfo *cipherdata,
2602 struct alginfo *authdata)
2604 struct pdcp_pdb pdb;
2606 pdb_mask[PDCP_CIPHER_TYPE_INVALID][PDCP_AUTH_TYPE_INVALID] = {
2608 PDCP_PDB_TYPE_NO_PDB, /* NULL */
2609 PDCP_PDB_TYPE_FULL_PDB, /* SNOW f9 */
2610 PDCP_PDB_TYPE_FULL_PDB, /* AES CMAC */
2611 PDCP_PDB_TYPE_FULL_PDB /* ZUC-I */
2614 PDCP_PDB_TYPE_FULL_PDB, /* NULL */
2615 PDCP_PDB_TYPE_FULL_PDB, /* SNOW f9 */
2616 PDCP_PDB_TYPE_REDUCED_PDB, /* AES CMAC */
2617 PDCP_PDB_TYPE_REDUCED_PDB /* ZUC-I */
2620 PDCP_PDB_TYPE_FULL_PDB, /* NULL */
2621 PDCP_PDB_TYPE_REDUCED_PDB, /* SNOW f9 */
2622 PDCP_PDB_TYPE_FULL_PDB, /* AES CMAC */
2623 PDCP_PDB_TYPE_REDUCED_PDB /* ZUC-I */
2626 PDCP_PDB_TYPE_FULL_PDB, /* NULL */
2627 PDCP_PDB_TYPE_REDUCED_PDB, /* SNOW f9 */
2628 PDCP_PDB_TYPE_REDUCED_PDB, /* AES CMAC */
2629 PDCP_PDB_TYPE_FULL_PDB /* ZUC-I */
2633 if (rta_sec_era >= RTA_SEC_ERA_8) {
2634 memset(&pdb, 0x00, sizeof(struct pdcp_pdb));
2636 /* To support 12-bit seq numbers, we use u-plane opt in pdb.
2637 * SEC supports 5-bit only with c-plane opt in pdb.
2639 if (sn_size == PDCP_SN_SIZE_12) {
2640 pdb.hfn_res = hfn << PDCP_U_PLANE_PDB_LONG_SN_HFN_SHIFT;
2641 pdb.bearer_dir_res = (uint32_t)
2642 ((bearer << PDCP_U_PLANE_PDB_BEARER_SHIFT) |
2643 (direction << PDCP_U_PLANE_PDB_DIR_SHIFT));
2646 hfn_threshold << PDCP_U_PLANE_PDB_LONG_SN_HFN_THR_SHIFT;
2649 /* This means 5-bit c-plane.
2650 * Here we use c-plane opt in pdb
2653 /* This is a HW issue. Bit 2 should be set to zero,
2654 * but it does not work this way. Override here.
2656 pdb.opt_res.rsvd = 0x00000002;
2658 /* Copy relevant information from user to PDB */
2659 pdb.hfn_res = hfn << PDCP_C_PLANE_PDB_HFN_SHIFT;
2660 pdb.bearer_dir_res = (uint32_t)
2661 ((bearer << PDCP_C_PLANE_PDB_BEARER_SHIFT) |
2662 (direction << PDCP_C_PLANE_PDB_DIR_SHIFT));
2664 hfn_threshold << PDCP_C_PLANE_PDB_HFN_THR_SHIFT;
2667 /* copy PDB in descriptor*/
2668 __rta_out32(p, pdb.opt_res.opt);
2669 __rta_out32(p, pdb.hfn_res);
2670 __rta_out32(p, pdb.bearer_dir_res);
2671 __rta_out32(p, pdb.hfn_thr_res);
2673 return PDCP_PDB_TYPE_FULL_PDB;
2676 switch (pdb_mask[cipherdata->algtype][authdata->algtype]) {
2677 case PDCP_PDB_TYPE_NO_PDB:
2680 case PDCP_PDB_TYPE_REDUCED_PDB:
2681 __rta_out32(p, (hfn << PDCP_C_PLANE_PDB_HFN_SHIFT));
2683 (uint32_t)((bearer <<
2684 PDCP_C_PLANE_PDB_BEARER_SHIFT) |
2686 PDCP_C_PLANE_PDB_DIR_SHIFT)));
2689 case PDCP_PDB_TYPE_FULL_PDB:
2690 memset(&pdb, 0x00, sizeof(struct pdcp_pdb));
2692 /* This is a HW issue. Bit 2 should be set to zero,
2693 * but it does not work this way. Override here.
2695 pdb.opt_res.rsvd = 0x00000002;
2697 /* Copy relevant information from user to PDB */
2698 pdb.hfn_res = hfn << PDCP_C_PLANE_PDB_HFN_SHIFT;
2699 pdb.bearer_dir_res = (uint32_t)
2700 ((bearer << PDCP_C_PLANE_PDB_BEARER_SHIFT) |
2701 (direction << PDCP_C_PLANE_PDB_DIR_SHIFT));
2703 hfn_threshold << PDCP_C_PLANE_PDB_HFN_THR_SHIFT;
2705 /* copy PDB in descriptor*/
2706 __rta_out32(p, pdb.opt_res.opt);
2707 __rta_out32(p, pdb.hfn_res);
2708 __rta_out32(p, pdb.bearer_dir_res);
2709 __rta_out32(p, pdb.hfn_thr_res);
2714 return PDCP_PDB_TYPE_INVALID;
2717 return pdb_mask[cipherdata->algtype][authdata->algtype];
2721 * PDCP UPlane PDB creation function
2723 static inline enum pdb_type_e
2724 cnstr_pdcp_u_plane_pdb(struct program *p,
2725 enum pdcp_sn_size sn_size,
2726 uint32_t hfn, unsigned short bearer,
2727 unsigned short direction,
2728 uint32_t hfn_threshold,
2729 struct alginfo *cipherdata,
2730 struct alginfo *authdata)
2732 struct pdcp_pdb pdb;
2733 enum pdb_type_e pdb_type = PDCP_PDB_TYPE_FULL_PDB;
2735 pdb_mask[PDCP_CIPHER_TYPE_INVALID][PDCP_AUTH_TYPE_INVALID] = {
2737 PDCP_PDB_TYPE_NO_PDB, /* NULL */
2738 PDCP_PDB_TYPE_FULL_PDB, /* SNOW f9 */
2739 PDCP_PDB_TYPE_FULL_PDB, /* AES CMAC */
2740 PDCP_PDB_TYPE_FULL_PDB /* ZUC-I */
2743 PDCP_PDB_TYPE_FULL_PDB, /* NULL */
2744 PDCP_PDB_TYPE_FULL_PDB, /* SNOW f9 */
2745 PDCP_PDB_TYPE_REDUCED_PDB, /* AES CMAC */
2746 PDCP_PDB_TYPE_REDUCED_PDB /* ZUC-I */
2749 PDCP_PDB_TYPE_FULL_PDB, /* NULL */
2750 PDCP_PDB_TYPE_REDUCED_PDB, /* SNOW f9 */
2751 PDCP_PDB_TYPE_FULL_PDB, /* AES CMAC */
2752 PDCP_PDB_TYPE_REDUCED_PDB /* ZUC-I */
2755 PDCP_PDB_TYPE_FULL_PDB, /* NULL */
2756 PDCP_PDB_TYPE_REDUCED_PDB, /* SNOW f9 */
2757 PDCP_PDB_TYPE_REDUCED_PDB, /* AES CMAC */
2758 PDCP_PDB_TYPE_FULL_PDB /* ZUC-I */
2762 /* Read options from user */
2763 /* Depending on sequence number length, the HFN and HFN threshold
2764 * have different lengths.
2766 memset(&pdb, 0x00, sizeof(struct pdcp_pdb));
2769 case PDCP_SN_SIZE_7:
2770 pdb.opt_res.opt |= PDCP_U_PLANE_PDB_OPT_SHORT_SN;
2771 pdb.hfn_res = hfn << PDCP_U_PLANE_PDB_SHORT_SN_HFN_SHIFT;
2773 hfn_threshold<<PDCP_U_PLANE_PDB_SHORT_SN_HFN_THR_SHIFT;
2776 case PDCP_SN_SIZE_12:
2777 pdb.opt_res.opt &= (uint32_t)(~PDCP_U_PLANE_PDB_OPT_SHORT_SN);
2778 pdb.hfn_res = hfn << PDCP_U_PLANE_PDB_LONG_SN_HFN_SHIFT;
2780 hfn_threshold<<PDCP_U_PLANE_PDB_LONG_SN_HFN_THR_SHIFT;
2783 case PDCP_SN_SIZE_15:
2784 pdb.opt_res.opt = (uint32_t)(PDCP_U_PLANE_PDB_OPT_15B_SN);
2785 pdb.hfn_res = hfn << PDCP_U_PLANE_PDB_15BIT_SN_HFN_SHIFT;
2787 hfn_threshold<<PDCP_U_PLANE_PDB_15BIT_SN_HFN_THR_SHIFT;
2790 case PDCP_SN_SIZE_18:
2791 pdb.opt_res.opt = (uint32_t)(PDCP_U_PLANE_PDB_OPT_18B_SN);
2792 pdb.hfn_res = hfn << PDCP_U_PLANE_PDB_18BIT_SN_HFN_SHIFT;
2794 hfn_threshold<<PDCP_U_PLANE_PDB_18BIT_SN_HFN_THR_SHIFT;
2796 if (rta_sec_era <= RTA_SEC_ERA_8) {
2797 if (cipherdata && authdata)
2798 pdb_type = pdb_mask[cipherdata->algtype]
2799 [authdata->algtype];
2804 pr_err("Invalid Sequence Number Size setting in PDB\n");
2808 pdb.bearer_dir_res = (uint32_t)
2809 ((bearer << PDCP_U_PLANE_PDB_BEARER_SHIFT) |
2810 (direction << PDCP_U_PLANE_PDB_DIR_SHIFT));
2813 case PDCP_PDB_TYPE_NO_PDB:
2816 case PDCP_PDB_TYPE_REDUCED_PDB:
2817 __rta_out32(p, pdb.hfn_res);
2818 __rta_out32(p, pdb.bearer_dir_res);
2821 case PDCP_PDB_TYPE_FULL_PDB:
2822 /* copy PDB in descriptor*/
2823 __rta_out32(p, pdb.opt_res.opt);
2824 __rta_out32(p, pdb.hfn_res);
2825 __rta_out32(p, pdb.bearer_dir_res);
2826 __rta_out32(p, pdb.hfn_thr_res);
2831 return PDCP_PDB_TYPE_INVALID;
2837 * cnstr_shdsc_pdcp_c_plane_encap - Function for creating a PDCP Control Plane
2838 * encapsulation descriptor.
2839 * @descbuf: pointer to buffer for descriptor construction
2840 * @ps: if 36/40bit addressing is desired, this parameter must be true
2841 * @swap: must be true when core endianness doesn't match SEC endianness
2842 * @hfn: starting Hyper Frame Number to be used together with the SN from the
2844 * @sn_size: size of sequence numbers, only 5/12 bit sequence numbers are valid
2845 * @bearer: radio bearer ID
2846 * @direction: the direction of the PDCP frame (UL/DL)
2847 * @hfn_threshold: HFN value that once reached triggers a warning from SEC that
2848 * keys should be renegotiated at the earliest convenience.
2849 * @cipherdata: pointer to block cipher transform definitions
2850 * Valid algorithm values are those from cipher_type_pdcp enum.
2851 * @authdata: pointer to authentication transform definitions
2852 * Valid algorithm values are those from auth_type_pdcp enum.
2853 * @era_2_sw_hfn_ovrd: if software HFN override mechanism is desired for
2854 * this descriptor. Note: Can only be used for
2856 * Return: size of descriptor written in words or negative number on error.
2857 * Once the function returns, the value of this parameter can be used
2858 * for reclaiming the space that wasn't used for the descriptor.
2860 * Note: descbuf must be large enough to contain a full 256 byte long
2861 * descriptor; after the function returns, by subtracting the actual number of
2862 * bytes used, the user can reuse the remaining buffer space for other purposes.
2865 cnstr_shdsc_pdcp_c_plane_encap(uint32_t *descbuf,
2869 enum pdcp_sn_size sn_size,
2870 unsigned char bearer,
2871 unsigned char direction,
2872 uint32_t hfn_threshold,
2873 struct alginfo *cipherdata,
2874 struct alginfo *authdata,
2875 unsigned char era_2_sw_hfn_ovrd)
2878 (*pdcp_cp_fp[PDCP_CIPHER_TYPE_INVALID][PDCP_AUTH_TYPE_INVALID])
2879 (struct program*, bool swap, struct alginfo *,
2880 struct alginfo *, unsigned int, enum pdcp_sn_size,
2881 unsigned char __maybe_unused) = {
2883 pdcp_insert_cplane_null_op, /* NULL */
2884 pdcp_insert_cplane_int_only_op, /* SNOW f9 */
2885 pdcp_insert_cplane_int_only_op, /* AES CMAC */
2886 pdcp_insert_cplane_int_only_op /* ZUC-I */
2889 pdcp_insert_cplane_enc_only_op, /* NULL */
2890 pdcp_insert_cplane_acc_op, /* SNOW f9 */
2891 pdcp_insert_cplane_snow_aes_op, /* AES CMAC */
2892 pdcp_insert_cplane_snow_zuc_op /* ZUC-I */
2895 pdcp_insert_cplane_enc_only_op, /* NULL */
2896 pdcp_insert_cplane_aes_snow_op, /* SNOW f9 */
2897 pdcp_insert_cplane_acc_op, /* AES CMAC */
2898 pdcp_insert_cplane_aes_zuc_op /* ZUC-I */
2901 pdcp_insert_cplane_enc_only_op, /* NULL */
2902 pdcp_insert_cplane_zuc_snow_op, /* SNOW f9 */
2903 pdcp_insert_cplane_zuc_aes_op, /* AES CMAC */
2904 pdcp_insert_cplane_acc_op /* ZUC-I */
2907 static enum rta_share_type
2908 desc_share[PDCP_CIPHER_TYPE_INVALID][PDCP_AUTH_TYPE_INVALID] = {
2910 SHR_WAIT, /* NULL */
2911 SHR_ALWAYS, /* SNOW f9 */
2912 SHR_ALWAYS, /* AES CMAC */
2913 SHR_ALWAYS /* ZUC-I */
2916 SHR_ALWAYS, /* NULL */
2917 SHR_ALWAYS, /* SNOW f9 */
2918 SHR_WAIT, /* AES CMAC */
2919 SHR_WAIT /* ZUC-I */
2922 SHR_ALWAYS, /* NULL */
2923 SHR_ALWAYS, /* SNOW f9 */
2924 SHR_ALWAYS, /* AES CMAC */
2925 SHR_WAIT /* ZUC-I */
2928 SHR_ALWAYS, /* NULL */
2929 SHR_WAIT, /* SNOW f9 */
2930 SHR_WAIT, /* AES CMAC */
2931 SHR_ALWAYS /* ZUC-I */
2934 enum pdb_type_e pdb_type;
2936 struct program *p = &prg;
2940 if (rta_sec_era != RTA_SEC_ERA_2 && era_2_sw_hfn_ovrd) {
2941 pr_err("Cannot select SW HFN override for other era than 2");
2945 if (sn_size != PDCP_SN_SIZE_12 && sn_size != PDCP_SN_SIZE_5) {
2946 pr_err("C-plane supports only 5-bit and 12-bit sequence numbers\n");
2950 PROGRAM_CNTXT_INIT(p, descbuf, 0);
2952 PROGRAM_SET_BSWAP(p);
2954 PROGRAM_SET_36BIT_ADDR(p);
2956 SHR_HDR(p, desc_share[cipherdata->algtype][authdata->algtype], 0, 0);
2958 pdb_type = cnstr_pdcp_c_plane_pdb(p,
2967 SET_LABEL(p, pdb_end);
2969 err = insert_hfn_ov_op(p, sn_size, pdb_type,
2974 err = pdcp_cp_fp[cipherdata->algtype][authdata->algtype](p,
2978 OP_TYPE_ENCAP_PROTOCOL,
2984 PATCH_HDR(p, 0, pdb_end);
2986 return PROGRAM_FINALIZE(p);
2990 * cnstr_shdsc_pdcp_c_plane_decap - Function for creating a PDCP Control Plane
2991 * decapsulation descriptor.
2992 * @descbuf: pointer to buffer for descriptor construction
2993 * @ps: if 36/40bit addressing is desired, this parameter must be true
2994 * @swap: must be true when core endianness doesn't match SEC endianness
2995 * @hfn: starting Hyper Frame Number to be used together with the SN from the
2997 * @sn_size: size of sequence numbers, only 5/12 bit sequence numbers are valid
2998 * @bearer: radio bearer ID
2999 * @direction: the direction of the PDCP frame (UL/DL)
3000 * @hfn_threshold: HFN value that once reached triggers a warning from SEC that
3001 * keys should be renegotiated at the earliest convenience.
3002 * @cipherdata: pointer to block cipher transform definitions
3003 * Valid algorithm values are those from cipher_type_pdcp enum.
3004 * @authdata: pointer to authentication transform definitions
3005 * Valid algorithm values are those from auth_type_pdcp enum.
3006 * @era_2_sw_hfn_ovrd: if software HFN override mechanism is desired for
3007 * this descriptor. Note: Can only be used for
3010 * Return: size of descriptor written in words or negative number on error.
3011 * Once the function returns, the value of this parameter can be used
3012 * for reclaiming the space that wasn't used for the descriptor.
3014 * Note: descbuf must be large enough to contain a full 256 byte long
3015 * descriptor; after the function returns, by subtracting the actual number of
3016 * bytes used, the user can reuse the remaining buffer space for other purposes.
3019 cnstr_shdsc_pdcp_c_plane_decap(uint32_t *descbuf,
3023 enum pdcp_sn_size sn_size,
3024 unsigned char bearer,
3025 unsigned char direction,
3026 uint32_t hfn_threshold,
3027 struct alginfo *cipherdata,
3028 struct alginfo *authdata,
3029 unsigned char era_2_sw_hfn_ovrd)
3032 (*pdcp_cp_fp[PDCP_CIPHER_TYPE_INVALID][PDCP_AUTH_TYPE_INVALID])
3033 (struct program*, bool swap, struct alginfo *,
3034 struct alginfo *, unsigned int, enum pdcp_sn_size,
3037 pdcp_insert_cplane_null_op, /* NULL */
3038 pdcp_insert_cplane_int_only_op, /* SNOW f9 */
3039 pdcp_insert_cplane_int_only_op, /* AES CMAC */
3040 pdcp_insert_cplane_int_only_op /* ZUC-I */
3043 pdcp_insert_cplane_enc_only_op, /* NULL */
3044 pdcp_insert_cplane_acc_op, /* SNOW f9 */
3045 pdcp_insert_cplane_snow_aes_op, /* AES CMAC */
3046 pdcp_insert_cplane_snow_zuc_op /* ZUC-I */
3049 pdcp_insert_cplane_enc_only_op, /* NULL */
3050 pdcp_insert_cplane_aes_snow_op, /* SNOW f9 */
3051 pdcp_insert_cplane_acc_op, /* AES CMAC */
3052 pdcp_insert_cplane_aes_zuc_op /* ZUC-I */
3055 pdcp_insert_cplane_enc_only_op, /* NULL */
3056 pdcp_insert_cplane_zuc_snow_op, /* SNOW f9 */
3057 pdcp_insert_cplane_zuc_aes_op, /* AES CMAC */
3058 pdcp_insert_cplane_acc_op /* ZUC-I */
3061 static enum rta_share_type
3062 desc_share[PDCP_CIPHER_TYPE_INVALID][PDCP_AUTH_TYPE_INVALID] = {
3064 SHR_WAIT, /* NULL */
3065 SHR_ALWAYS, /* SNOW f9 */
3066 SHR_ALWAYS, /* AES CMAC */
3067 SHR_ALWAYS /* ZUC-I */
3070 SHR_ALWAYS, /* NULL */
3071 SHR_ALWAYS, /* SNOW f9 */
3072 SHR_WAIT, /* AES CMAC */
3073 SHR_WAIT /* ZUC-I */
3076 SHR_ALWAYS, /* NULL */
3077 SHR_ALWAYS, /* SNOW f9 */
3078 SHR_ALWAYS, /* AES CMAC */
3079 SHR_WAIT /* ZUC-I */
3082 SHR_ALWAYS, /* NULL */
3083 SHR_WAIT, /* SNOW f9 */
3084 SHR_WAIT, /* AES CMAC */
3085 SHR_ALWAYS /* ZUC-I */
3088 enum pdb_type_e pdb_type;
3090 struct program *p = &prg;
3094 if (rta_sec_era != RTA_SEC_ERA_2 && era_2_sw_hfn_ovrd) {
3095 pr_err("Cannot select SW HFN override for other era than 2");
3099 if (sn_size != PDCP_SN_SIZE_12 && sn_size != PDCP_SN_SIZE_5) {
3100 pr_err("C-plane supports only 5-bit and 12-bit sequence numbers\n");
3104 PROGRAM_CNTXT_INIT(p, descbuf, 0);
3106 PROGRAM_SET_BSWAP(p);
3108 PROGRAM_SET_36BIT_ADDR(p);
3110 SHR_HDR(p, desc_share[cipherdata->algtype][authdata->algtype], 0, 0);
3112 pdb_type = cnstr_pdcp_c_plane_pdb(p,
3121 SET_LABEL(p, pdb_end);
3123 err = insert_hfn_ov_op(p, sn_size, pdb_type,
3128 err = pdcp_cp_fp[cipherdata->algtype][authdata->algtype](p,
3132 OP_TYPE_DECAP_PROTOCOL,
3138 PATCH_HDR(p, 0, pdb_end);
3140 return PROGRAM_FINALIZE(p);
3144 pdcp_insert_uplane_with_int_op(struct program *p,
3145 bool swap __maybe_unused,
3146 struct alginfo *cipherdata,
3147 struct alginfo *authdata,
3148 enum pdcp_sn_size sn_size,
3149 unsigned char era_2_sw_hfn_ovrd,
3153 (*pdcp_cp_fp[PDCP_CIPHER_TYPE_INVALID][PDCP_AUTH_TYPE_INVALID])
3154 (struct program*, bool swap, struct alginfo *,
3155 struct alginfo *, unsigned int, enum pdcp_sn_size,
3156 unsigned char __maybe_unused) = {
3158 pdcp_insert_cplane_null_op, /* NULL */
3159 pdcp_insert_cplane_int_only_op, /* SNOW f9 */
3160 pdcp_insert_cplane_int_only_op, /* AES CMAC */
3161 pdcp_insert_cplane_int_only_op /* ZUC-I */
3164 pdcp_insert_cplane_enc_only_op, /* NULL */
3165 pdcp_insert_uplane_snow_snow_op, /* SNOW f9 */
3166 pdcp_insert_cplane_snow_aes_op, /* AES CMAC */
3167 pdcp_insert_cplane_snow_zuc_op /* ZUC-I */
3170 pdcp_insert_cplane_enc_only_op, /* NULL */
3171 pdcp_insert_cplane_aes_snow_op, /* SNOW f9 */
3172 pdcp_insert_uplane_aes_aes_op, /* AES CMAC */
3173 pdcp_insert_cplane_aes_zuc_op /* ZUC-I */
3176 pdcp_insert_cplane_enc_only_op, /* NULL */
3177 pdcp_insert_cplane_zuc_snow_op, /* SNOW f9 */
3178 pdcp_insert_cplane_zuc_aes_op, /* AES CMAC */
3179 pdcp_insert_uplane_zuc_zuc_op /* ZUC-I */
3184 err = pdcp_cp_fp[cipherdata->algtype][authdata->algtype](p,
3199 * cnstr_shdsc_pdcp_u_plane_encap - Function for creating a PDCP User Plane
3200 * encapsulation descriptor.
3201 * @descbuf: pointer to buffer for descriptor construction
3202 * @ps: if 36/40bit addressing is desired, this parameter must be true
3203 * @swap: must be true when core endianness doesn't match SEC endianness
3204 * @sn_size: selects Sequence Number Size: 7/12/15 bits
3205 * @hfn: starting Hyper Frame Number to be used together with the SN from the
3207 * @bearer: radio bearer ID
3208 * @direction: the direction of the PDCP frame (UL/DL)
3209 * @hfn_threshold: HFN value that once reached triggers a warning from SEC that
3210 * keys should be renegotiated at the earliest convenience.
3211 * @cipherdata: pointer to block cipher transform definitions
3212 * Valid algorithm values are those from cipher_type_pdcp enum.
3213 * @era_2_sw_hfn_ovrd: if software HFN override mechanism is desired for
3214 * this descriptor. Note: Can only be used for
3217 * Return: size of descriptor written in words or negative number on error.
3218 * Once the function returns, the value of this parameter can be used
3219 * for reclaiming the space that wasn't used for the descriptor.
3221 * Note: descbuf must be large enough to contain a full 256 byte long
3222 * descriptor; after the function returns, by subtracting the actual number of
3223 * bytes used, the user can reuse the remaining buffer space for other purposes.
3226 cnstr_shdsc_pdcp_u_plane_encap(uint32_t *descbuf,
3229 enum pdcp_sn_size sn_size,
3231 unsigned short bearer,
3232 unsigned short direction,
3233 uint32_t hfn_threshold,
3234 struct alginfo *cipherdata,
3235 struct alginfo *authdata,
3236 unsigned char era_2_sw_hfn_ovrd)
3239 struct program *p = &prg;
3241 enum pdb_type_e pdb_type;
3242 static enum rta_share_type
3243 desc_share[PDCP_CIPHER_TYPE_INVALID][PDCP_AUTH_TYPE_INVALID] = {
3245 SHR_WAIT, /* NULL */
3246 SHR_ALWAYS, /* SNOW f9 */
3247 SHR_ALWAYS, /* AES CMAC */
3248 SHR_ALWAYS /* ZUC-I */
3251 SHR_ALWAYS, /* NULL */
3252 SHR_ALWAYS, /* SNOW f9 */
3253 SHR_WAIT, /* AES CMAC */
3254 SHR_WAIT /* ZUC-I */
3257 SHR_ALWAYS, /* NULL */
3258 SHR_ALWAYS, /* SNOW f9 */
3259 SHR_ALWAYS, /* AES CMAC */
3260 SHR_WAIT /* ZUC-I */
3263 SHR_ALWAYS, /* NULL */
3264 SHR_WAIT, /* SNOW f9 */
3265 SHR_WAIT, /* AES CMAC */
3266 SHR_ALWAYS /* ZUC-I */
3271 if (rta_sec_era != RTA_SEC_ERA_2 && era_2_sw_hfn_ovrd) {
3272 pr_err("Cannot select SW HFN ovrd for other era than 2");
3276 if (authdata && !authdata->algtype && rta_sec_era < RTA_SEC_ERA_8) {
3277 pr_err("Cannot use u-plane auth with era < 8");
3281 PROGRAM_CNTXT_INIT(p, descbuf, 0);
3283 PROGRAM_SET_BSWAP(p);
3285 PROGRAM_SET_36BIT_ADDR(p);
3288 SHR_HDR(p, desc_share[cipherdata->algtype][authdata->algtype], 0, 0);
3290 SHR_HDR(p, SHR_ALWAYS, 0, 0);
3291 pdb_type = cnstr_pdcp_u_plane_pdb(p, sn_size, hfn,
3292 bearer, direction, hfn_threshold,
3293 cipherdata, authdata);
3294 if (pdb_type == PDCP_PDB_TYPE_INVALID) {
3295 pr_err("Error creating PDCP UPlane PDB\n");
3298 SET_LABEL(p, pdb_end);
3300 err = insert_hfn_ov_op(p, sn_size, pdb_type, era_2_sw_hfn_ovrd);
3305 case PDCP_SN_SIZE_7:
3306 case PDCP_SN_SIZE_12:
3307 switch (cipherdata->algtype) {
3308 case PDCP_CIPHER_TYPE_ZUC:
3309 if (rta_sec_era < RTA_SEC_ERA_5) {
3310 pr_err("Invalid era for selected algorithm\n");
3314 case PDCP_CIPHER_TYPE_AES:
3315 case PDCP_CIPHER_TYPE_SNOW:
3316 case PDCP_CIPHER_TYPE_NULL:
3317 if (rta_sec_era == RTA_SEC_ERA_8 &&
3318 authdata && authdata->algtype == 0){
3319 err = pdcp_insert_uplane_with_int_op(p, swap,
3320 cipherdata, authdata,
3321 sn_size, era_2_sw_hfn_ovrd,
3322 OP_TYPE_ENCAP_PROTOCOL);
3328 if (pdb_type != PDCP_PDB_TYPE_FULL_PDB) {
3329 pr_err("PDB type must be FULL for PROTO desc\n");
3333 /* Insert auth key if requested */
3334 if (authdata && authdata->algtype) {
3335 KEY(p, KEY2, authdata->key_enc_flags,
3336 (uint64_t)authdata->key, authdata->keylen,
3337 INLINE_KEY(authdata));
3339 /* Insert Cipher Key */
3340 KEY(p, KEY1, cipherdata->key_enc_flags,
3341 (uint64_t)cipherdata->key, cipherdata->keylen,
3342 INLINE_KEY(cipherdata));
3345 PROTOCOL(p, OP_TYPE_ENCAP_PROTOCOL,
3346 OP_PCLID_LTE_PDCP_USER_RN,
3347 ((uint16_t)cipherdata->algtype << 8) |
3348 (uint16_t)authdata->algtype);
3350 PROTOCOL(p, OP_TYPE_ENCAP_PROTOCOL,
3351 OP_PCLID_LTE_PDCP_USER,
3352 (uint16_t)cipherdata->algtype);
3355 pr_err("%s: Invalid encrypt algorithm selected: %d\n",
3356 "cnstr_pcl_shdsc_pdcp_u_plane_decap",
3357 cipherdata->algtype);
3362 case PDCP_SN_SIZE_15:
3363 case PDCP_SN_SIZE_18:
3365 err = pdcp_insert_uplane_with_int_op(p, swap,
3366 cipherdata, authdata,
3367 sn_size, era_2_sw_hfn_ovrd,
3368 OP_TYPE_ENCAP_PROTOCOL);
3375 switch (cipherdata->algtype) {
3376 case PDCP_CIPHER_TYPE_NULL:
3377 insert_copy_frame_op(p,
3379 OP_TYPE_ENCAP_PROTOCOL);
3383 err = pdcp_insert_uplane_no_int_op(p, swap, cipherdata,
3384 OP_TYPE_ENCAP_PROTOCOL, sn_size);
3391 case PDCP_SN_SIZE_5:
3393 pr_err("Invalid SN size selected\n");
3397 PATCH_HDR(p, 0, pdb_end);
3398 return PROGRAM_FINALIZE(p);
3402 * cnstr_shdsc_pdcp_u_plane_decap - Function for creating a PDCP User Plane
3403 * decapsulation descriptor.
3404 * @descbuf: pointer to buffer for descriptor construction
3405 * @ps: if 36/40bit addressing is desired, this parameter must be true
3406 * @swap: must be true when core endianness doesn't match SEC endianness
3407 * @sn_size: selects Sequence Number Size: 7/12/15 bits
3408 * @hfn: starting Hyper Frame Number to be used together with the SN from the
3410 * @bearer: radio bearer ID
3411 * @direction: the direction of the PDCP frame (UL/DL)
3412 * @hfn_threshold: HFN value that once reached triggers a warning from SEC that
3413 * keys should be renegotiated at the earliest convenience.
3414 * @cipherdata: pointer to block cipher transform definitions
3415 * Valid algorithm values are those from cipher_type_pdcp enum.
3416 * @era_2_sw_hfn_ovrd: if software HFN override mechanism is desired for
3417 * this descriptor. Note: Can only be used for
3420 * Return: size of descriptor written in words or negative number on error.
3421 * Once the function returns, the value of this parameter can be used
3422 * for reclaiming the space that wasn't used for the descriptor.
3424 * Note: descbuf must be large enough to contain a full 256 byte long
3425 * descriptor; after the function returns, by subtracting the actual number of
3426 * bytes used, the user can reuse the remaining buffer space for other purposes.
3429 cnstr_shdsc_pdcp_u_plane_decap(uint32_t *descbuf,
3432 enum pdcp_sn_size sn_size,
3434 unsigned short bearer,
3435 unsigned short direction,
3436 uint32_t hfn_threshold,
3437 struct alginfo *cipherdata,
3438 struct alginfo *authdata,
3439 unsigned char era_2_sw_hfn_ovrd)
3442 struct program *p = &prg;
3444 enum pdb_type_e pdb_type;
3445 static enum rta_share_type
3446 desc_share[PDCP_CIPHER_TYPE_INVALID][PDCP_AUTH_TYPE_INVALID] = {
3448 SHR_WAIT, /* NULL */
3449 SHR_ALWAYS, /* SNOW f9 */
3450 SHR_ALWAYS, /* AES CMAC */
3451 SHR_ALWAYS /* ZUC-I */
3454 SHR_ALWAYS, /* NULL */
3455 SHR_ALWAYS, /* SNOW f9 */
3456 SHR_WAIT, /* AES CMAC */
3457 SHR_WAIT /* ZUC-I */
3460 SHR_ALWAYS, /* NULL */
3461 SHR_ALWAYS, /* SNOW f9 */
3462 SHR_ALWAYS, /* AES CMAC */
3463 SHR_WAIT /* ZUC-I */
3466 SHR_ALWAYS, /* NULL */
3467 SHR_WAIT, /* SNOW f9 */
3468 SHR_WAIT, /* AES CMAC */
3469 SHR_ALWAYS /* ZUC-I */
3475 if (rta_sec_era != RTA_SEC_ERA_2 && era_2_sw_hfn_ovrd) {
3476 pr_err("Cannot select SW HFN override for other era than 2");
3480 if (authdata && !authdata->algtype && rta_sec_era < RTA_SEC_ERA_8) {
3481 pr_err("Cannot use u-plane auth with era < 8");
3485 PROGRAM_CNTXT_INIT(p, descbuf, 0);
3487 PROGRAM_SET_BSWAP(p);
3489 PROGRAM_SET_36BIT_ADDR(p);
3491 SHR_HDR(p, desc_share[cipherdata->algtype][authdata->algtype], 0, 0);
3493 SHR_HDR(p, SHR_ALWAYS, 0, 0);
3495 pdb_type = cnstr_pdcp_u_plane_pdb(p, sn_size, hfn, bearer,
3496 direction, hfn_threshold,
3497 cipherdata, authdata);
3498 if (pdb_type == PDCP_PDB_TYPE_INVALID) {
3499 pr_err("Error creating PDCP UPlane PDB\n");
3502 SET_LABEL(p, pdb_end);
3504 err = insert_hfn_ov_op(p, sn_size, pdb_type, era_2_sw_hfn_ovrd);
3509 case PDCP_SN_SIZE_7:
3510 case PDCP_SN_SIZE_12:
3511 switch (cipherdata->algtype) {
3512 case PDCP_CIPHER_TYPE_ZUC:
3513 if (rta_sec_era < RTA_SEC_ERA_5) {
3514 pr_err("Invalid era for selected algorithm\n");
3518 case PDCP_CIPHER_TYPE_AES:
3519 case PDCP_CIPHER_TYPE_SNOW:
3520 case PDCP_CIPHER_TYPE_NULL:
3521 if (pdb_type != PDCP_PDB_TYPE_FULL_PDB) {
3522 pr_err("PDB type must be FULL for PROTO desc\n");
3526 /* Insert auth key if requested */
3527 if (authdata && authdata->algtype)
3528 KEY(p, KEY2, authdata->key_enc_flags,
3529 (uint64_t)authdata->key, authdata->keylen,
3530 INLINE_KEY(authdata));
3532 /* Insert Cipher Key */
3533 KEY(p, KEY1, cipherdata->key_enc_flags,
3534 cipherdata->key, cipherdata->keylen,
3535 INLINE_KEY(cipherdata));
3537 PROTOCOL(p, OP_TYPE_DECAP_PROTOCOL,
3538 OP_PCLID_LTE_PDCP_USER_RN,
3539 ((uint16_t)cipherdata->algtype << 8) |
3540 (uint16_t)authdata->algtype);
3542 PROTOCOL(p, OP_TYPE_DECAP_PROTOCOL,
3543 OP_PCLID_LTE_PDCP_USER,
3544 (uint16_t)cipherdata->algtype);
3547 pr_err("%s: Invalid encrypt algorithm selected: %d\n",
3548 "cnstr_pcl_shdsc_pdcp_u_plane_decap",
3549 cipherdata->algtype);
3554 case PDCP_SN_SIZE_15:
3555 case PDCP_SN_SIZE_18:
3557 err = pdcp_insert_uplane_with_int_op(p, swap,
3558 cipherdata, authdata,
3559 sn_size, era_2_sw_hfn_ovrd,
3560 OP_TYPE_DECAP_PROTOCOL);
3567 switch (cipherdata->algtype) {
3568 case PDCP_CIPHER_TYPE_NULL:
3569 insert_copy_frame_op(p,
3571 OP_TYPE_DECAP_PROTOCOL);
3575 err = pdcp_insert_uplane_no_int_op(p, swap, cipherdata,
3576 OP_TYPE_DECAP_PROTOCOL, sn_size);
3583 case PDCP_SN_SIZE_5:
3585 pr_err("Invalid SN size selected\n");
3589 PATCH_HDR(p, 0, pdb_end);
3590 return PROGRAM_FINALIZE(p);
3594 * cnstr_shdsc_pdcp_short_mac - Function for creating a PDCP Short MAC
3596 * @descbuf: pointer to buffer for descriptor construction
3597 * @ps: if 36/40bit addressing is desired, this parameter must be true
3598 * @swap: must be true when core endianness doesn't match SEC endianness
3599 * @authdata: pointer to authentication transform definitions
3600 * Valid algorithm values are those from auth_type_pdcp enum.
3602 * Return: size of descriptor written in words or negative number on error.
3603 * Once the function returns, the value of this parameter can be used
3604 * for reclaiming the space that wasn't used for the descriptor.
3606 * Note: descbuf must be large enough to contain a full 256 byte long
3607 * descriptor; after the function returns, by subtracting the actual number of
3608 * bytes used, the user can reuse the remaining buffer space for other purposes.
3611 cnstr_shdsc_pdcp_short_mac(uint32_t *descbuf,
3614 struct alginfo *authdata)
3617 struct program *p = &prg;
3618 uint32_t iv[3] = {0, 0, 0};
3619 LABEL(local_offset);
3620 REFERENCE(move_cmd_read_descbuf);
3621 REFERENCE(move_cmd_write_descbuf);
3623 PROGRAM_CNTXT_INIT(p, descbuf, 0);
3625 PROGRAM_SET_BSWAP(p);
3627 PROGRAM_SET_36BIT_ADDR(p);
3629 SHR_HDR(p, SHR_ALWAYS, 1, 0);
3631 if (rta_sec_era > RTA_SEC_ERA_2) {
3632 MATHB(p, SEQINSZ, SUB, ZERO, VSEQINSZ, 4, 0);
3633 MATHB(p, SEQINSZ, SUB, ZERO, MATH1, 4, 0);
3635 MATHB(p, SEQINSZ, ADD, ONE, MATH1, 4, 0);
3636 MATHB(p, MATH1, SUB, ONE, MATH1, 4, 0);
3637 MATHB(p, ZERO, ADD, MATH1, VSEQINSZ, 4, 0);
3638 MOVE(p, MATH1, 0, MATH0, 0, 8, IMMED);
3641 * Since MOVELEN is available only starting with
3642 * SEC ERA 3, use poor man's MOVELEN: create a MOVE
3643 * command dynamically by writing the length from M1 by
3644 * OR-ing the command in the M1 register and MOVE the
3645 * result into the descriptor buffer. Care must be taken
3646 * wrt. the location of the command because of SEC
3647 * pipelining. The actual MOVEs are written at the end
3648 * of the descriptor due to calculations needed on the
3649 * offset in the descriptor for the MOVE command.
3651 move_cmd_read_descbuf = MOVE(p, DESCBUF, 0, MATH0, 0, 6,
3653 move_cmd_write_descbuf = MOVE(p, MATH0, 0, DESCBUF, 0, 8,
3656 MATHB(p, ZERO, ADD, MATH1, VSEQOUTSZ, 4, 0);
3658 switch (authdata->algtype) {
3659 case PDCP_AUTH_TYPE_NULL:
3660 SEQFIFOSTORE(p, MSG, 0, 0, VLF);
3661 if (rta_sec_era > RTA_SEC_ERA_2) {
3662 MOVE(p, AB1, 0, OFIFO, 0, MATH1, 0);
3664 SET_LABEL(p, local_offset);
3666 /* Shut off automatic Info FIFO entries */
3667 LOAD(p, 0, DCTRL, LDOFF_DISABLE_AUTO_NFIFO, 0, IMMED);
3669 /* Placeholder for MOVE command with length from M1
3672 MOVE(p, IFIFOAB1, 0, OFIFO, 0, 0, IMMED);
3674 /* Enable automatic Info FIFO entries */
3675 LOAD(p, 0, DCTRL, LDOFF_ENABLE_AUTO_NFIFO, 0, IMMED);
3678 LOAD(p, (uintptr_t)iv, MATH0, 0, 8, IMMED | COPY);
3679 SEQFIFOLOAD(p, MSG1, 0, VLF | LAST1 | LAST2 | FLUSH1);
3680 SEQSTORE(p, MATH0, 0, 4, 0);
3684 case PDCP_AUTH_TYPE_SNOW:
3686 iv[1] = swap ? swab32(0x04000000) : 0x04000000;
3687 iv[2] = swap ? swab32(0xF8000000) : 0xF8000000;
3689 KEY(p, KEY2, authdata->key_enc_flags, authdata->key,
3690 authdata->keylen, INLINE_KEY(authdata));
3691 LOAD(p, (uintptr_t)&iv, CONTEXT2, 0, 12, IMMED | COPY);
3692 ALG_OPERATION(p, OP_ALG_ALGSEL_SNOW_F9,
3694 OP_ALG_AS_INITFINAL,
3697 SEQFIFOSTORE(p, MSG, 0, 0, VLF);
3699 if (rta_sec_era > RTA_SEC_ERA_2) {
3700 MOVE(p, AB1, 0, OFIFO, 0, MATH1, 0);
3702 SET_LABEL(p, local_offset);
3705 /* Shut off automatic Info FIFO entries */
3706 LOAD(p, 0, DCTRL, LDOFF_DISABLE_AUTO_NFIFO, 0, IMMED);
3708 /* Placeholder for MOVE command with length from M1
3711 MOVE(p, IFIFOAB1, 0, OFIFO, 0, 0, IMMED);
3713 /* Enable automatic Info FIFO entries */
3714 LOAD(p, 0, DCTRL, LDOFF_ENABLE_AUTO_NFIFO, 0, IMMED);
3716 SEQFIFOLOAD(p, MSGINSNOOP, 0, VLF | LAST1 | LAST2 | FLUSH1);
3717 SEQSTORE(p, CONTEXT2, 0, 4, 0);
3721 case PDCP_AUTH_TYPE_AES:
3723 iv[1] = swap ? swab32(0xFC000000) : 0xFC000000;
3724 iv[2] = 0x00000000; /* unused */
3726 KEY(p, KEY1, authdata->key_enc_flags, authdata->key,
3727 authdata->keylen, INLINE_KEY(authdata));
3728 LOAD(p, (uintptr_t)&iv, MATH0, 0, 8, IMMED | COPY);
3729 MOVE(p, MATH0, 0, IFIFOAB1, 0, 8, IMMED);
3730 ALG_OPERATION(p, OP_ALG_ALGSEL_AES,
3732 OP_ALG_AS_INITFINAL,
3735 SEQFIFOSTORE(p, MSG, 0, 0, VLF);
3737 if (rta_sec_era > RTA_SEC_ERA_2) {
3738 MOVE(p, AB2, 0, OFIFO, 0, MATH1, 0);
3740 SET_LABEL(p, local_offset);
3742 /* Shut off automatic Info FIFO entries */
3743 LOAD(p, 0, DCTRL, LDOFF_DISABLE_AUTO_NFIFO, 0, IMMED);
3745 /* Placeholder for MOVE command with length from M1
3748 MOVE(p, IFIFOAB2, 0, OFIFO, 0, 0, IMMED);
3750 /* Enable automatic Info FIFO entries */
3751 LOAD(p, 0, DCTRL, LDOFF_ENABLE_AUTO_NFIFO, 0, IMMED);
3753 SEQFIFOLOAD(p, MSGINSNOOP, 0, VLF | LAST1 | LAST2 | FLUSH1);
3754 SEQSTORE(p, CONTEXT1, 0, 4, 0);
3758 case PDCP_AUTH_TYPE_ZUC:
3759 if (rta_sec_era < RTA_SEC_ERA_5) {
3760 pr_err("Invalid era for selected algorithm\n");
3764 iv[1] = swap ? swab32(0xFC000000) : 0xFC000000;
3765 iv[2] = 0x00000000; /* unused */
3767 KEY(p, KEY2, authdata->key_enc_flags, authdata->key,
3768 authdata->keylen, INLINE_KEY(authdata));
3769 LOAD(p, (uintptr_t)&iv, CONTEXT2, 0, 12, IMMED | COPY);
3770 ALG_OPERATION(p, OP_ALG_ALGSEL_ZUCA,
3772 OP_ALG_AS_INITFINAL,
3775 SEQFIFOSTORE(p, MSG, 0, 0, VLF);
3776 MOVE(p, AB1, 0, OFIFO, 0, MATH1, 0);
3777 SEQFIFOLOAD(p, MSGINSNOOP, 0, VLF | LAST1 | LAST2 | FLUSH1);
3778 SEQSTORE(p, CONTEXT2, 0, 4, 0);
3783 pr_err("%s: Invalid integrity algorithm selected: %d\n",
3784 "cnstr_shdsc_pdcp_short_mac", authdata->algtype);
3789 if (rta_sec_era < RTA_SEC_ERA_3) {
3790 PATCH_MOVE(p, move_cmd_read_descbuf, local_offset);
3791 PATCH_MOVE(p, move_cmd_write_descbuf, local_offset);
3794 return PROGRAM_FINALIZE(p);
3797 #endif /* __DESC_PDCP_H__ */