1 /* SPDX-License-Identifier: BSD-3-Clause or GPL-2.0+
2 * Copyright 2008-2013 Freescale Semiconductor, Inc.
5 #ifndef __DESC_PDCP_H__
6 #define __DESC_PDCP_H__
12 * DOC: PDCP Shared Descriptor Constructors
14 * Shared descriptors for PDCP protocol.
18 * PDCP_NULL_MAX_FRAME_LEN - The maximum frame frame length that is supported by
21 #define PDCP_NULL_MAX_FRAME_LEN 0x00002FFF
24 * PDCP_MAC_I_LEN - The length of the MAC-I for PDCP protocol operation
26 #define PDCP_MAC_I_LEN 0x00000004
29 * PDCP_MAX_FRAME_LEN_STATUS - The status returned in FD status/command field in
30 * case the input frame is larger than
31 * PDCP_NULL_MAX_FRAME_LEN.
33 #define PDCP_MAX_FRAME_LEN_STATUS 0xF1
36 * PDCP_C_PLANE_SN_MASK - This mask is used in the PDCP descriptors for
37 * extracting the sequence number (SN) from the PDCP
38 * Control Plane header. For PDCP Control Plane, the SN
39 * is constant (5 bits) as opposed to PDCP Data Plane
42 #define PDCP_C_PLANE_SN_MASK 0x1F000000
43 #define PDCP_C_PLANE_SN_MASK_BE 0x0000001F
46 * PDCP_U_PLANE_15BIT_SN_MASK - This mask is used in the PDCP descriptors for
47 * extracting the sequence number (SN) from the
48 * PDCP User Plane header. For PDCP Control Plane,
49 * the SN is constant (5 bits) as opposed to PDCP
50 * Data Plane (7/12/15 bits).
52 #define PDCP_U_PLANE_15BIT_SN_MASK 0xFF7F0000
53 #define PDCP_U_PLANE_15BIT_SN_MASK_BE 0x00007FFF
56 * PDCP_BEARER_MASK - This mask is used masking out the bearer for PDCP
57 * processing with SNOW f9 in LTE.
59 * The value on which this mask is applied is formatted as below:
60 * Count-C (32 bit) | Bearer (5 bit) | Direction (1 bit) | 0 (26 bits)
62 * Applying this mask is done for creating the upper 64 bits of the IV needed
65 * The lower 32 bits of the mask are used for masking the direction for AES
68 #define PDCP_BEARER_MASK 0x00000004FFFFFFFFull
69 #define PDCP_BEARER_MASK_BE 0xFFFFFFFF04000000ull
72 * PDCP_DIR_MASK - This mask is used masking out the direction for PDCP
73 * processing with SNOW f9 in LTE.
75 * The value on which this mask is applied is formatted as below:
76 * Bearer (5 bit) | Direction (1 bit) | 0 (26 bits)
78 * Applying this mask is done for creating the lower 32 bits of the IV needed
81 * The upper 32 bits of the mask are used for masking the direction for AES
84 #define PDCP_DIR_MASK 0x00000000000000F8ull
85 #define PDCP_DIR_MASK_BE 0xF800000000000000ull
88 * PDCP_NULL_INT_MAC_I_VAL - The value of the PDCP PDU MAC-I in case NULL
92 #define PDCP_NULL_INT_MAC_I_VAL 0x00000000
95 * PDCP_NULL_INT_ICV_CHECK_FAILED_STATUS - The status used to report ICV check
96 * failed in case of NULL integrity
97 * Control Plane processing.
99 #define PDCP_NULL_INT_ICV_CHECK_FAILED_STATUS 0x0A
101 * PDCP_DPOVRD_HFN_OV_EN - Value to be used in the FD status/cmd field to
102 * indicate the HFN override mechanism is active for the
105 #define PDCP_DPOVRD_HFN_OV_EN 0x80000000
108 * PDCP_P4080REV2_HFN_OV_BUFLEN - The length in bytes of the supplementary space
109 * that must be provided by the user at the
110 * beginning of the input frame buffer for
113 * The format of the frame buffer is the following:
115 * |<---PDCP_P4080REV2_HFN_OV_BUFLEN-->|
116 * //===================================||============||==============\\
117 * || PDCP_DPOVRD_HFN_OV_EN | HFN value || PDCP Header|| PDCP Payload ||
118 * \\===================================||============||==============//
120 * If HFN override mechanism is not desired, then the MSB of the first 4 bytes
123 #define PDCP_P4080REV2_HFN_OV_BUFLEN 4
126 * enum cipher_type_pdcp - Type selectors for cipher types in PDCP protocol OP
128 * @PDCP_CIPHER_TYPE_NULL: NULL
129 * @PDCP_CIPHER_TYPE_SNOW: SNOW F8
130 * @PDCP_CIPHER_TYPE_AES: AES
131 * @PDCP_CIPHER_TYPE_ZUC: ZUCE
132 * @PDCP_CIPHER_TYPE_INVALID: invalid option
134 enum cipher_type_pdcp {
135 PDCP_CIPHER_TYPE_NULL,
136 PDCP_CIPHER_TYPE_SNOW,
137 PDCP_CIPHER_TYPE_AES,
138 PDCP_CIPHER_TYPE_ZUC,
139 PDCP_CIPHER_TYPE_INVALID
143 * enum auth_type_pdcp - Type selectors for integrity types in PDCP protocol OP
145 * @PDCP_AUTH_TYPE_NULL: NULL
146 * @PDCP_AUTH_TYPE_SNOW: SNOW F9
147 * @PDCP_AUTH_TYPE_AES: AES CMAC
148 * @PDCP_AUTH_TYPE_ZUC: ZUCA
149 * @PDCP_AUTH_TYPE_INVALID: invalid option
151 enum auth_type_pdcp {
156 PDCP_AUTH_TYPE_INVALID
160 * enum pdcp_dir - Type selectors for direction for PDCP protocol
161 * @PDCP_DIR_UPLINK: uplink direction
162 * @PDCP_DIR_DOWNLINK: downlink direction
163 * @PDCP_DIR_INVALID: invalid option
167 PDCP_DIR_DOWNLINK = 1,
172 * enum pdcp_plane - PDCP domain selectors
173 * @PDCP_CONTROL_PLANE: Control Plane
174 * @PDCP_DATA_PLANE: Data Plane
175 * @PDCP_SHORT_MAC: Short MAC
184 * enum pdcp_sn_size - Sequence Number Size selectors for PDCP protocol
185 * @PDCP_SN_SIZE_5: 5bit sequence number
186 * @PDCP_SN_SIZE_7: 7bit sequence number
187 * @PDCP_SN_SIZE_12: 12bit sequence number
188 * @PDCP_SN_SIZE_15: 15bit sequence number
189 * @PDCP_SN_SIZE_18: 18bit sequence number
194 PDCP_SN_SIZE_12 = 12,
199 * PDCP Control Plane Protocol Data Blocks
201 #define PDCP_C_PLANE_PDB_HFN_SHIFT 5
202 #define PDCP_C_PLANE_PDB_BEARER_SHIFT 27
203 #define PDCP_C_PLANE_PDB_DIR_SHIFT 26
204 #define PDCP_C_PLANE_PDB_HFN_THR_SHIFT 5
206 #define PDCP_U_PLANE_PDB_OPT_SHORT_SN 0x2
207 #define PDCP_U_PLANE_PDB_OPT_15B_SN 0x4
208 #define PDCP_U_PLANE_PDB_SHORT_SN_HFN_SHIFT 7
209 #define PDCP_U_PLANE_PDB_LONG_SN_HFN_SHIFT 12
210 #define PDCP_U_PLANE_PDB_15BIT_SN_HFN_SHIFT 15
211 #define PDCP_U_PLANE_PDB_BEARER_SHIFT 27
212 #define PDCP_U_PLANE_PDB_DIR_SHIFT 26
213 #define PDCP_U_PLANE_PDB_SHORT_SN_HFN_THR_SHIFT 7
214 #define PDCP_U_PLANE_PDB_LONG_SN_HFN_THR_SHIFT 12
215 #define PDCP_U_PLANE_PDB_15BIT_SN_HFN_THR_SHIFT 15
222 uint32_t hfn_res; /* HyperFrame number,(27, 25 or 21 bits),
223 * left aligned & right-padded with zeros.
225 uint32_t bearer_dir_res;/* Bearer(5 bits), packet direction (1 bit),
226 * left aligned & right-padded with zeros.
228 uint32_t hfn_thr_res; /* HyperFrame number threshold (27, 25 or 21
229 * bits), left aligned & right-padded with
235 * PDCP internal PDB types
238 PDCP_PDB_TYPE_NO_PDB,
239 PDCP_PDB_TYPE_FULL_PDB,
240 PDCP_PDB_TYPE_REDUCED_PDB,
241 PDCP_PDB_TYPE_INVALID
245 * Function for appending the portion of a PDCP Control Plane shared descriptor
246 * which performs NULL encryption and integrity (i.e. copies the input frame
247 * to the output frame, appending 32 bits of zeros at the end (MAC-I for
251 pdcp_insert_cplane_null_op(struct program *p,
252 bool swap __maybe_unused,
253 struct alginfo *cipherdata __maybe_unused,
254 struct alginfo *authdata __maybe_unused,
256 enum pdcp_sn_size sn_size __maybe_unused,
257 unsigned char era_2_sw_hfn_ovrd __maybe_unused)
260 REFERENCE(move_cmd_read_descbuf);
261 REFERENCE(move_cmd_write_descbuf);
263 if (rta_sec_era > RTA_SEC_ERA_2) {
264 MATHB(p, SEQINSZ, ADD, ZERO, VSEQINSZ, 4, 0);
265 if (dir == OP_TYPE_ENCAP_PROTOCOL)
266 MATHB(p, SEQINSZ, ADD, PDCP_MAC_I_LEN, VSEQOUTSZ, 4,
269 MATHB(p, SEQINSZ, SUB, PDCP_MAC_I_LEN, VSEQOUTSZ, 4,
272 MATHB(p, SEQINSZ, ADD, ONE, VSEQINSZ, 4, 0);
273 MATHB(p, VSEQINSZ, SUB, ONE, VSEQINSZ, 4, 0);
275 if (dir == OP_TYPE_ENCAP_PROTOCOL) {
276 MATHB(p, SEQINSZ, ADD, PDCP_MAC_I_LEN, VSEQOUTSZ, 4,
278 MATHB(p, VSEQINSZ, SUB, ONE, MATH0, 4, 0);
280 MATHB(p, VSEQINSZ, SUB, PDCP_MAC_I_LEN, VSEQINSZ, 4,
282 MATHB(p, SEQINSZ, SUB, PDCP_MAC_I_LEN, VSEQOUTSZ, 4,
284 MATHB(p, VSEQOUTSZ, SUB, ONE, MATH0, 4, 0);
287 MATHB(p, MATH0, ADD, ONE, MATH0, 4, 0);
290 * Since MOVELEN is available only starting with
291 * SEC ERA 3, use poor man's MOVELEN: create a MOVE
292 * command dynamically by writing the length from M1 by
293 * OR-ing the command in the M1 register and MOVE the
294 * result into the descriptor buffer. Care must be taken
295 * wrt. the location of the command because of SEC
296 * pipelining. The actual MOVEs are written at the end
297 * of the descriptor due to calculations needed on the
298 * offset in the descriptor for the MOVE command.
300 move_cmd_read_descbuf = MOVE(p, DESCBUF, 0, MATH0, 0, 6,
302 move_cmd_write_descbuf = MOVE(p, MATH0, 0, DESCBUF, 0, 8,
305 MATHB(p, VSEQINSZ, SUB, PDCP_NULL_MAX_FRAME_LEN, NONE, 4,
307 JUMP(p, PDCP_MAX_FRAME_LEN_STATUS, HALT_STATUS, ALL_FALSE, MATH_N);
309 if (rta_sec_era > RTA_SEC_ERA_2) {
310 if (dir == OP_TYPE_ENCAP_PROTOCOL)
311 MATHB(p, VSEQINSZ, ADD, ZERO, MATH0, 4, 0);
313 MATHB(p, VSEQOUTSZ, ADD, ZERO, MATH0, 4, 0);
315 SEQFIFOSTORE(p, MSG, 0, 0, VLF);
316 SEQFIFOLOAD(p, MSG1, 0, VLF | LAST1 | FLUSH1);
318 if (rta_sec_era > RTA_SEC_ERA_2) {
319 MOVE(p, AB1, 0, OFIFO, 0, MATH0, 0);
321 SET_LABEL(p, local_offset);
323 /* Shut off automatic Info FIFO entries */
324 LOAD(p, 0, DCTRL, LDOFF_DISABLE_AUTO_NFIFO, 0, IMMED);
325 /* Placeholder for MOVE command with length from M1 register */
326 MOVE(p, IFIFOAB1, 0, OFIFO, 0, 0, IMMED);
327 /* Enable automatic Info FIFO entries */
328 LOAD(p, 0, DCTRL, LDOFF_ENABLE_AUTO_NFIFO, 0, IMMED);
331 if (dir == OP_TYPE_ENCAP_PROTOCOL) {
332 MATHB(p, MATH1, XOR, MATH1, MATH0, 8, 0);
333 MOVE(p, MATH0, 0, OFIFO, 0, 4, IMMED);
336 if (rta_sec_era < RTA_SEC_ERA_3) {
337 PATCH_MOVE(p, move_cmd_read_descbuf, local_offset);
338 PATCH_MOVE(p, move_cmd_write_descbuf, local_offset);
345 insert_copy_frame_op(struct program *p,
346 struct alginfo *cipherdata __maybe_unused,
347 unsigned int dir __maybe_unused)
350 REFERENCE(move_cmd_read_descbuf);
351 REFERENCE(move_cmd_write_descbuf);
353 if (rta_sec_era > RTA_SEC_ERA_2) {
354 MATHB(p, SEQINSZ, ADD, ZERO, VSEQINSZ, 4, 0);
355 MATHB(p, SEQINSZ, ADD, ZERO, VSEQOUTSZ, 4, 0);
357 MATHB(p, SEQINSZ, ADD, ONE, VSEQINSZ, 4, 0);
358 MATHB(p, VSEQINSZ, SUB, ONE, VSEQINSZ, 4, 0);
359 MATHB(p, SEQINSZ, ADD, ONE, VSEQOUTSZ, 4, 0);
360 MATHB(p, VSEQOUTSZ, SUB, ONE, VSEQOUTSZ, 4, 0);
361 MATHB(p, VSEQINSZ, SUB, ONE, MATH0, 4, 0);
362 MATHB(p, MATH0, ADD, ONE, MATH0, 4, 0);
365 * Since MOVELEN is available only starting with
366 * SEC ERA 3, use poor man's MOVELEN: create a MOVE
367 * command dynamically by writing the length from M1 by
368 * OR-ing the command in the M1 register and MOVE the
369 * result into the descriptor buffer. Care must be taken
370 * wrt. the location of the command because of SEC
371 * pipelining. The actual MOVEs are written at the end
372 * of the descriptor due to calculations needed on the
373 * offset in the descriptor for the MOVE command.
375 move_cmd_read_descbuf = MOVE(p, DESCBUF, 0, MATH0, 0, 6,
377 move_cmd_write_descbuf = MOVE(p, MATH0, 0, DESCBUF, 0, 8,
380 MATHB(p, SEQINSZ, SUB, PDCP_NULL_MAX_FRAME_LEN, NONE, 4,
382 JUMP(p, PDCP_MAX_FRAME_LEN_STATUS, HALT_STATUS, ALL_FALSE, MATH_N);
384 if (rta_sec_era > RTA_SEC_ERA_2)
385 MATHB(p, VSEQINSZ, ADD, ZERO, MATH0, 4, 0);
387 SEQFIFOLOAD(p, MSG1, 0, VLF | LAST1 | FLUSH1);
388 if (rta_sec_era > RTA_SEC_ERA_2) {
389 MOVE(p, AB1, 0, OFIFO, 0, MATH0, 0);
391 SET_LABEL(p, local_offset);
393 /* Shut off automatic Info FIFO entries */
394 LOAD(p, 0, DCTRL, LDOFF_DISABLE_AUTO_NFIFO, 0, IMMED);
396 /* Placeholder for MOVE command with length from M0 register */
397 MOVE(p, IFIFOAB1, 0, OFIFO, 0, 0, IMMED);
399 /* Enable automatic Info FIFO entries */
400 LOAD(p, 0, DCTRL, LDOFF_ENABLE_AUTO_NFIFO, 0, IMMED);
403 SEQFIFOSTORE(p, MSG, 0, 0, VLF);
405 if (rta_sec_era < RTA_SEC_ERA_3) {
406 PATCH_MOVE(p, move_cmd_read_descbuf, local_offset);
407 PATCH_MOVE(p, move_cmd_write_descbuf, local_offset);
413 pdcp_insert_cplane_int_only_op(struct program *p,
414 bool swap __maybe_unused,
415 struct alginfo *cipherdata __maybe_unused,
416 struct alginfo *authdata, unsigned int dir,
417 enum pdcp_sn_size sn_size,
418 unsigned char era_2_sw_hfn_ovrd)
420 if (rta_sec_era >= RTA_SEC_ERA_8 && sn_size == PDCP_SN_SIZE_12) {
421 KEY(p, KEY2, authdata->key_enc_flags, authdata->key,
422 authdata->keylen, INLINE_KEY(authdata));
424 PROTOCOL(p, dir, OP_PCLID_LTE_PDCP_USER_RN,
425 (uint16_t)authdata->algtype);
430 REFERENCE(move_cmd_read_descbuf);
431 REFERENCE(move_cmd_write_descbuf);
433 switch (authdata->algtype) {
434 case PDCP_AUTH_TYPE_SNOW:
435 /* Insert Auth Key */
436 KEY(p, KEY2, authdata->key_enc_flags, authdata->key,
437 authdata->keylen, INLINE_KEY(authdata));
438 SEQLOAD(p, MATH0, 7, 1, 0);
439 JUMP(p, 1, LOCAL_JUMP, ALL_TRUE, CALM);
441 if (rta_sec_era > RTA_SEC_ERA_2 ||
442 (rta_sec_era == RTA_SEC_ERA_2 &&
443 era_2_sw_hfn_ovrd == 0)) {
444 SEQINPTR(p, 0, 1, RTO);
446 SEQINPTR(p, 0, 5, RTO);
447 SEQFIFOLOAD(p, SKIP, 4, 0);
451 MATHB(p, MATH0, AND, PDCP_C_PLANE_SN_MASK, MATH1, 8,
453 MATHB(p, MATH1, SHLD, MATH1, MATH1, 8, 0);
455 MOVEB(p, DESCBUF, 8, MATH2, 0, 8, WAITCOMP | IMMED);
457 MATHB(p, MATH2, AND, PDCP_BEARER_MASK, MATH2, 8,
459 MOVEB(p, DESCBUF, 0x0C, MATH3, 0, 4, WAITCOMP | IMMED);
460 MATHB(p, MATH3, AND, PDCP_DIR_MASK, MATH3, 8, IMMED2);
461 MATHB(p, MATH1, OR, MATH2, MATH2, 8, 0);
462 MOVEB(p, MATH2, 0, CONTEXT2, 0, 0x0C, WAITCOMP | IMMED);
464 MATHB(p, MATH0, AND, PDCP_C_PLANE_SN_MASK_BE, MATH1, 8,
466 MATHB(p, MATH1, SHLD, MATH1, MATH1, 8, 0);
468 MOVE(p, DESCBUF, 8, MATH2, 0, 8, WAITCOMP | IMMED);
469 MATHB(p, MATH2, AND, PDCP_BEARER_MASK_BE, MATH2, 8,
472 MOVE(p, DESCBUF, 0x0C, MATH3, 0, 4, WAITCOMP | IMMED);
473 MATHB(p, MATH3, AND, PDCP_DIR_MASK_BE, MATH3, 8,
475 MATHB(p, MATH1, OR, MATH2, MATH2, 8, 0);
476 MOVE(p, MATH2, 0, CONTEXT2, 0, 0x0C, WAITCOMP | IMMED);
479 if (dir == OP_TYPE_DECAP_PROTOCOL) {
480 MATHB(p, SEQINSZ, SUB, PDCP_MAC_I_LEN, MATH1, 4,
483 if (rta_sec_era > RTA_SEC_ERA_2) {
484 MATHB(p, SEQINSZ, SUB, ZERO, MATH1, 4,
487 MATHB(p, SEQINSZ, ADD, ONE, MATH1, 4,
489 MATHB(p, MATH1, SUB, ONE, MATH1, 4,
494 if (rta_sec_era > RTA_SEC_ERA_2) {
495 MATHB(p, MATH1, SUB, ZERO, VSEQINSZ, 4, 0);
496 MATHB(p, MATH1, SUB, ZERO, VSEQOUTSZ, 4, 0);
498 MATHB(p, ZERO, ADD, MATH1, VSEQINSZ, 4, 0);
499 MATHB(p, ZERO, ADD, MATH1, VSEQOUTSZ, 4, 0);
502 * Since MOVELEN is available only starting with
503 * SEC ERA 3, use poor man's MOVELEN: create a MOVE
504 * command dynamically by writing the length from M1 by
505 * OR-ing the command in the M1 register and MOVE the
506 * result into the descriptor buffer. Care must be taken
507 * wrt. the location of the command because of SEC
508 * pipelining. The actual MOVEs are written at the end
509 * of the descriptor due to calculations needed on the
510 * offset in the descriptor for the MOVE command.
512 move_cmd_read_descbuf = MOVE(p, DESCBUF, 0, MATH1, 0, 6,
514 move_cmd_write_descbuf = MOVE(p, MATH1, 0, DESCBUF, 0,
515 8, WAITCOMP | IMMED);
518 SEQFIFOSTORE(p, MSG, 0, 0, VLF);
519 ALG_OPERATION(p, OP_ALG_ALGSEL_SNOW_F9, OP_ALG_AAI_F9,
521 dir == OP_TYPE_ENCAP_PROTOCOL ?
522 ICV_CHECK_DISABLE : ICV_CHECK_ENABLE,
525 if (rta_sec_era > RTA_SEC_ERA_2) {
526 SEQFIFOLOAD(p, MSGINSNOOP, 0,
527 VLF | LAST1 | LAST2 | FLUSH1);
528 MOVE(p, AB1, 0, OFIFO, 0, MATH1, 0);
530 SEQFIFOLOAD(p, MSGINSNOOP, 0,
531 VLF | LAST1 | LAST2 | FLUSH1);
532 SET_LABEL(p, local_offset);
534 /* Shut off automatic Info FIFO entries */
535 LOAD(p, 0, DCTRL, LDOFF_DISABLE_AUTO_NFIFO, 0, IMMED);
537 * Placeholder for MOVE command with length from M1
540 MOVE(p, IFIFOAB1, 0, OFIFO, 0, 0, IMMED);
541 /* Enable automatic Info FIFO entries */
542 LOAD(p, 0, DCTRL, LDOFF_ENABLE_AUTO_NFIFO, 0, IMMED);
545 if (dir == OP_TYPE_DECAP_PROTOCOL)
546 SEQFIFOLOAD(p, ICV2, 4, LAST2);
548 SEQSTORE(p, CONTEXT2, 0, 4, 0);
552 case PDCP_AUTH_TYPE_AES:
553 /* Insert Auth Key */
554 KEY(p, KEY1, authdata->key_enc_flags, authdata->key,
555 authdata->keylen, INLINE_KEY(authdata));
556 SEQLOAD(p, MATH0, 7, 1, 0);
557 JUMP(p, 1, LOCAL_JUMP, ALL_TRUE, CALM);
558 if (rta_sec_era > RTA_SEC_ERA_2 ||
559 (rta_sec_era == RTA_SEC_ERA_2 &&
560 era_2_sw_hfn_ovrd == 0)) {
561 SEQINPTR(p, 0, 1, RTO);
563 SEQINPTR(p, 0, 5, RTO);
564 SEQFIFOLOAD(p, SKIP, 4, 0);
568 MATHB(p, MATH0, AND, PDCP_C_PLANE_SN_MASK, MATH1, 8,
570 MATHB(p, MATH1, SHLD, MATH1, MATH1, 8, 0);
572 MOVEB(p, DESCBUF, 8, MATH2, 0, 8, WAITCOMP | IMMED);
573 MATHB(p, MATH1, OR, MATH2, MATH2, 8, 0);
574 MOVEB(p, MATH2, 0, IFIFOAB1, 0, 8, IMMED);
576 MATHB(p, MATH0, AND, PDCP_C_PLANE_SN_MASK_BE, MATH1, 8,
578 MATHB(p, MATH1, SHLD, MATH1, MATH1, 8, 0);
580 MOVE(p, DESCBUF, 8, MATH2, 0, 8, WAITCOMP | IMMED);
581 MATHB(p, MATH1, OR, MATH2, MATH2, 8, 0);
582 MOVE(p, MATH2, 0, IFIFOAB1, 0, 8, IMMED);
585 if (dir == OP_TYPE_DECAP_PROTOCOL) {
586 MATHB(p, SEQINSZ, SUB, PDCP_MAC_I_LEN, MATH1, 4,
589 if (rta_sec_era > RTA_SEC_ERA_2) {
590 MATHB(p, SEQINSZ, SUB, ZERO, MATH1, 4,
593 MATHB(p, SEQINSZ, ADD, ONE, MATH1, 4,
595 MATHB(p, MATH1, SUB, ONE, MATH1, 4,
600 if (rta_sec_era > RTA_SEC_ERA_2) {
601 MATHB(p, MATH1, SUB, ZERO, VSEQINSZ, 4, 0);
602 MATHB(p, MATH1, SUB, ZERO, VSEQOUTSZ, 4, 0);
604 MATHB(p, ZERO, ADD, MATH1, VSEQINSZ, 4, 0);
605 MATHB(p, ZERO, ADD, MATH1, VSEQOUTSZ, 4, 0);
608 * Since MOVELEN is available only starting with
609 * SEC ERA 3, use poor man's MOVELEN: create a MOVE
610 * command dynamically by writing the length from M1 by
611 * OR-ing the command in the M1 register and MOVE the
612 * result into the descriptor buffer. Care must be taken
613 * wrt. the location of the command because of SEC
614 * pipelining. The actual MOVEs are written at the end
615 * of the descriptor due to calculations needed on the
616 * offset in the descriptor for the MOVE command.
618 move_cmd_read_descbuf = MOVE(p, DESCBUF, 0, MATH1, 0, 6,
620 move_cmd_write_descbuf = MOVE(p, MATH1, 0, DESCBUF, 0,
621 8, WAITCOMP | IMMED);
623 SEQFIFOSTORE(p, MSG, 0, 0, VLF);
624 ALG_OPERATION(p, OP_ALG_ALGSEL_AES,
627 dir == OP_TYPE_ENCAP_PROTOCOL ?
628 ICV_CHECK_DISABLE : ICV_CHECK_ENABLE,
631 if (rta_sec_era > RTA_SEC_ERA_2) {
632 MOVE(p, AB2, 0, OFIFO, 0, MATH1, 0);
633 SEQFIFOLOAD(p, MSGINSNOOP, 0,
634 VLF | LAST1 | LAST2 | FLUSH1);
636 SEQFIFOLOAD(p, MSGINSNOOP, 0,
637 VLF | LAST1 | LAST2 | FLUSH1);
638 SET_LABEL(p, local_offset);
640 /* Shut off automatic Info FIFO entries */
641 LOAD(p, 0, DCTRL, LDOFF_DISABLE_AUTO_NFIFO, 0, IMMED);
644 * Placeholder for MOVE command with length from
647 MOVE(p, IFIFOAB2, 0, OFIFO, 0, 0, IMMED);
649 /* Enable automatic Info FIFO entries */
650 LOAD(p, 0, DCTRL, LDOFF_ENABLE_AUTO_NFIFO, 0, IMMED);
653 if (dir == OP_TYPE_DECAP_PROTOCOL)
654 SEQFIFOLOAD(p, ICV1, 4, LAST1 | FLUSH1);
656 SEQSTORE(p, CONTEXT1, 0, 4, 0);
660 case PDCP_AUTH_TYPE_ZUC:
661 if (rta_sec_era < RTA_SEC_ERA_5) {
662 pr_err("Invalid era for selected algorithm\n");
665 /* Insert Auth Key */
666 KEY(p, KEY2, authdata->key_enc_flags, authdata->key,
667 authdata->keylen, INLINE_KEY(authdata));
668 SEQLOAD(p, MATH0, 7, 1, 0);
669 JUMP(p, 1, LOCAL_JUMP, ALL_TRUE, CALM);
670 SEQINPTR(p, 0, 1, RTO);
672 MATHB(p, MATH0, AND, PDCP_C_PLANE_SN_MASK, MATH1, 8,
674 MATHB(p, MATH1, SHLD, MATH1, MATH1, 8, 0);
676 MOVEB(p, DESCBUF, 8, MATH2, 0, 8, WAITCOMP | IMMED);
677 MATHB(p, MATH1, OR, MATH2, MATH2, 8, 0);
678 MOVEB(p, MATH2, 0, CONTEXT2, 0, 8, IMMED);
681 MATHB(p, MATH0, AND, PDCP_C_PLANE_SN_MASK_BE, MATH1, 8,
683 MATHB(p, MATH1, SHLD, MATH1, MATH1, 8, 0);
685 MOVE(p, DESCBUF, 8, MATH2, 0, 8, WAITCOMP | IMMED);
686 MATHB(p, MATH1, OR, MATH2, MATH2, 8, 0);
687 MOVE(p, MATH2, 0, CONTEXT2, 0, 8, IMMED);
689 if (dir == OP_TYPE_DECAP_PROTOCOL)
690 MATHB(p, SEQINSZ, SUB, PDCP_MAC_I_LEN, MATH1, 4,
693 MATHB(p, SEQINSZ, SUB, ZERO, MATH1, 4, 0);
695 MATHB(p, MATH1, SUB, ZERO, VSEQINSZ, 4, 0);
696 MATHB(p, MATH1, SUB, ZERO, VSEQOUTSZ, 4, 0);
697 SEQFIFOSTORE(p, MSG, 0, 0, VLF);
698 ALG_OPERATION(p, OP_ALG_ALGSEL_ZUCA,
701 dir == OP_TYPE_ENCAP_PROTOCOL ?
702 ICV_CHECK_DISABLE : ICV_CHECK_ENABLE,
704 SEQFIFOLOAD(p, MSGINSNOOP, 0, VLF | LAST1 | LAST2 | FLUSH1);
705 MOVE(p, AB1, 0, OFIFO, 0, MATH1, 0);
707 if (dir == OP_TYPE_DECAP_PROTOCOL)
708 SEQFIFOLOAD(p, ICV2, 4, LAST2);
710 SEQSTORE(p, CONTEXT2, 0, 4, 0);
715 pr_err("%s: Invalid integrity algorithm selected: %d\n",
716 "pdcp_insert_cplane_int_only_op", authdata->algtype);
720 if (rta_sec_era < RTA_SEC_ERA_3) {
721 PATCH_MOVE(p, move_cmd_read_descbuf, local_offset);
722 PATCH_MOVE(p, move_cmd_write_descbuf, local_offset);
729 pdcp_insert_cplane_enc_only_op(struct program *p,
730 bool swap __maybe_unused,
731 struct alginfo *cipherdata,
732 struct alginfo *authdata __maybe_unused,
734 enum pdcp_sn_size sn_size,
735 unsigned char era_2_sw_hfn_ovrd __maybe_unused)
737 /* Insert Cipher Key */
738 KEY(p, KEY1, cipherdata->key_enc_flags, cipherdata->key,
739 cipherdata->keylen, INLINE_KEY(cipherdata));
741 if (rta_sec_era >= RTA_SEC_ERA_8) {
742 if (sn_size == PDCP_SN_SIZE_5)
743 PROTOCOL(p, dir, OP_PCLID_LTE_PDCP_CTRL_MIXED,
744 (uint16_t)cipherdata->algtype << 8);
746 PROTOCOL(p, dir, OP_PCLID_LTE_PDCP_USER_RN,
747 (uint16_t)cipherdata->algtype << 8);
751 SEQLOAD(p, MATH0, 7, 1, 0);
752 JUMP(p, 1, LOCAL_JUMP, ALL_TRUE, CALM);
754 MATHB(p, MATH0, AND, PDCP_C_PLANE_SN_MASK, MATH1, 8,
757 MATHB(p, MATH0, AND, PDCP_C_PLANE_SN_MASK_BE, MATH1, 8,
759 SEQSTORE(p, MATH0, 7, 1, 0);
760 MATHB(p, MATH1, SHLD, MATH1, MATH1, 8, 0);
761 MOVEB(p, DESCBUF, 8, MATH2, 0, 8, WAITCOMP | IMMED);
762 MATHB(p, MATH1, OR, MATH2, MATH2, 8, 0);
764 switch (cipherdata->algtype) {
765 case PDCP_CIPHER_TYPE_SNOW:
766 MOVEB(p, MATH2, 0, CONTEXT1, 0, 8, WAITCOMP | IMMED);
768 if (rta_sec_era > RTA_SEC_ERA_2) {
769 MATHB(p, SEQINSZ, SUB, ZERO, VSEQINSZ, 4, 0);
771 MATHB(p, SEQINSZ, SUB, ONE, MATH1, 4, 0);
772 MATHB(p, MATH1, ADD, ONE, VSEQINSZ, 4, 0);
775 if (dir == OP_TYPE_ENCAP_PROTOCOL)
776 MATHB(p, SEQINSZ, ADD, PDCP_MAC_I_LEN, VSEQOUTSZ, 4,
779 MATHB(p, SEQINSZ, SUB, PDCP_MAC_I_LEN, VSEQOUTSZ, 4,
781 SEQFIFOSTORE(p, MSG, 0, 0, VLF | CONT);
782 ALG_OPERATION(p, OP_ALG_ALGSEL_SNOW_F8,
784 OP_ALG_AS_INITFINAL, ICV_CHECK_DISABLE,
785 dir == OP_TYPE_ENCAP_PROTOCOL ?
789 case PDCP_CIPHER_TYPE_AES:
790 MOVEB(p, MATH2, 0, CONTEXT1, 0x10, 0x10, WAITCOMP | IMMED);
792 if (rta_sec_era > RTA_SEC_ERA_2) {
793 MATHB(p, SEQINSZ, SUB, ZERO, VSEQINSZ, 4, 0);
795 MATHB(p, SEQINSZ, SUB, ONE, MATH1, 4, 0);
796 MATHB(p, MATH1, ADD, ONE, VSEQINSZ, 4, 0);
799 if (dir == OP_TYPE_ENCAP_PROTOCOL)
800 MATHB(p, SEQINSZ, ADD, PDCP_MAC_I_LEN, VSEQOUTSZ, 4,
803 MATHB(p, SEQINSZ, SUB, PDCP_MAC_I_LEN, VSEQOUTSZ, 4,
806 SEQFIFOSTORE(p, MSG, 0, 0, VLF | CONT);
807 ALG_OPERATION(p, OP_ALG_ALGSEL_AES,
811 dir == OP_TYPE_ENCAP_PROTOCOL ?
815 case PDCP_CIPHER_TYPE_ZUC:
816 if (rta_sec_era < RTA_SEC_ERA_5) {
817 pr_err("Invalid era for selected algorithm\n");
821 MOVEB(p, MATH2, 0, CONTEXT1, 0, 0x08, IMMED);
822 MOVEB(p, MATH2, 0, CONTEXT1, 0x08, 0x08, WAITCOMP | IMMED);
823 MATHB(p, SEQINSZ, SUB, ZERO, VSEQINSZ, 4, 0);
824 if (dir == OP_TYPE_ENCAP_PROTOCOL)
825 MATHB(p, SEQINSZ, ADD, PDCP_MAC_I_LEN, VSEQOUTSZ, 4,
828 MATHB(p, SEQINSZ, SUB, PDCP_MAC_I_LEN, VSEQOUTSZ, 4,
831 SEQFIFOSTORE(p, MSG, 0, 0, VLF | CONT);
832 ALG_OPERATION(p, OP_ALG_ALGSEL_ZUCE,
836 dir == OP_TYPE_ENCAP_PROTOCOL ?
841 pr_err("%s: Invalid encrypt algorithm selected: %d\n",
842 "pdcp_insert_cplane_enc_only_op", cipherdata->algtype);
846 if (dir == OP_TYPE_ENCAP_PROTOCOL) {
847 SEQFIFOLOAD(p, MSG1, 0, VLF);
848 FIFOLOAD(p, MSG1, PDCP_NULL_INT_MAC_I_VAL, 4,
849 LAST1 | FLUSH1 | IMMED);
851 SEQFIFOLOAD(p, MSG1, 0, VLF | LAST1 | FLUSH1);
852 MOVE(p, OFIFO, 0, MATH1, 4, PDCP_MAC_I_LEN, WAITCOMP | IMMED);
853 MATHB(p, MATH1, XOR, PDCP_NULL_INT_MAC_I_VAL, NONE, 4, IMMED2);
854 JUMP(p, PDCP_NULL_INT_ICV_CHECK_FAILED_STATUS,
855 HALT_STATUS, ALL_FALSE, MATH_Z);
862 pdcp_insert_cplane_acc_op(struct program *p,
863 bool swap __maybe_unused,
864 struct alginfo *cipherdata,
865 struct alginfo *authdata,
867 enum pdcp_sn_size sn_size,
868 unsigned char era_2_hfn_ovrd __maybe_unused)
870 /* Insert Auth Key */
871 KEY(p, KEY2, authdata->key_enc_flags, authdata->key, authdata->keylen,
872 INLINE_KEY(authdata));
874 /* Insert Cipher Key */
875 KEY(p, KEY1, cipherdata->key_enc_flags, cipherdata->key,
876 cipherdata->keylen, INLINE_KEY(cipherdata));
878 if (sn_size == PDCP_SN_SIZE_5)
879 PROTOCOL(p, dir, OP_PCLID_LTE_PDCP_CTRL,
880 (uint16_t)cipherdata->algtype);
882 PROTOCOL(p, dir, OP_PCLID_LTE_PDCP_USER_RN,
883 ((uint16_t)cipherdata->algtype << 8) |
884 (uint16_t)authdata->algtype);
890 pdcp_insert_cplane_snow_aes_op(struct program *p,
891 bool swap __maybe_unused,
892 struct alginfo *cipherdata,
893 struct alginfo *authdata,
895 enum pdcp_sn_size sn_size,
896 unsigned char era_2_sw_hfn_ovrd)
898 LABEL(back_to_sd_offset);
901 LABEL(jump_to_beginning);
902 LABEL(fifo_load_mac_i_offset);
903 REFERENCE(seqin_ptr_read);
904 REFERENCE(seqin_ptr_write);
905 REFERENCE(seq_out_read);
906 REFERENCE(jump_back_to_sd_cmd);
907 REFERENCE(move_mac_i_to_desc_buf);
909 if (rta_sec_era >= RTA_SEC_ERA_8) {
910 KEY(p, KEY1, cipherdata->key_enc_flags, cipherdata->key,
911 cipherdata->keylen, INLINE_KEY(cipherdata));
912 KEY(p, KEY2, authdata->key_enc_flags, authdata->key,
913 authdata->keylen, INLINE_KEY(authdata));
915 if (sn_size == PDCP_SN_SIZE_5)
916 PROTOCOL(p, dir, OP_PCLID_LTE_PDCP_CTRL_MIXED,
917 ((uint16_t)cipherdata->algtype << 8) |
918 (uint16_t)authdata->algtype);
920 PROTOCOL(p, dir, OP_PCLID_LTE_PDCP_USER_RN,
921 ((uint16_t)cipherdata->algtype << 8) |
922 (uint16_t)authdata->algtype);
927 SEQLOAD(p, MATH0, 7, 1, 0);
928 JUMP(p, 1, LOCAL_JUMP, ALL_TRUE, CALM);
930 MATHB(p, MATH0, AND, PDCP_C_PLANE_SN_MASK, MATH1, 8,
933 MATHB(p, MATH0, AND, PDCP_C_PLANE_SN_MASK_BE, MATH1, 8,
935 MATHB(p, MATH1, SHLD, MATH1, MATH1, 8, 0);
936 MOVE(p, DESCBUF, 4, MATH2, 0, 0x08, WAITCOMP | IMMED);
937 MATHB(p, MATH1, OR, MATH2, MATH2, 8, 0);
938 SEQSTORE(p, MATH0, 7, 1, 0);
939 if (dir == OP_TYPE_ENCAP_PROTOCOL) {
940 if (rta_sec_era > RTA_SEC_ERA_2 ||
941 (rta_sec_era == RTA_SEC_ERA_2 &&
942 era_2_sw_hfn_ovrd == 0)) {
943 SEQINPTR(p, 0, 1, RTO);
945 SEQINPTR(p, 0, 5, RTO);
946 SEQFIFOLOAD(p, SKIP, 4, 0);
948 KEY(p, KEY1, authdata->key_enc_flags, authdata->key,
949 authdata->keylen, INLINE_KEY(authdata));
950 MOVE(p, MATH2, 0, IFIFOAB1, 0, 0x08, IMMED);
952 if (rta_sec_era > RTA_SEC_ERA_2) {
953 MATHB(p, SEQINSZ, SUB, ZERO, VSEQINSZ, 4, 0);
954 MATHB(p, SEQINSZ, SUB, ZERO, MATH1, 4, 0);
955 MATHB(p, VSEQINSZ, ADD, PDCP_MAC_I_LEN - 1, VSEQOUTSZ,
958 MATHB(p, SEQINSZ, SUB, MATH3, VSEQINSZ, 4, 0);
959 MATHB(p, VSEQINSZ, ADD, PDCP_MAC_I_LEN - 1, VSEQOUTSZ,
962 * Note: Although the calculations below might seem a
963 * little off, the logic is the following:
965 * - SEQ IN PTR RTO below needs the full length of the
966 * frame; in case of P4080_REV_2_HFN_OV_WORKAROUND,
967 * this means the length of the frame to be processed
968 * + 4 bytes (the HFN override flag and value).
969 * The length of the frame to be processed minus 1
970 * byte is in the VSIL register (because
971 * VSIL = SIL + 3, due to 1 byte, the header being
972 * already written by the SEQ STORE above). So for
973 * calculating the length to use in RTO, I add one
974 * to the VSIL value in order to obtain the total
975 * frame length. This helps in case of P4080 which
976 * can have the value 0 as an operand in a MATH
977 * command only as SRC1 When the HFN override
978 * workaround is not enabled, the length of the
979 * frame is given by the SIL register; the
980 * calculation is similar to the one in the SEC 4.2
983 if (era_2_sw_hfn_ovrd)
984 MATHB(p, VSEQOUTSZ, ADD, ONE, MATH1, 4,
987 MATHB(p, SEQINSZ, ADD, MATH3, MATH1, 4,
991 * Placeholder for filling the length in
992 * SEQIN PTR RTO below
994 seqin_ptr_read = MOVE(p, DESCBUF, 0, MATH1, 0, 6, IMMED);
995 seqin_ptr_write = MOVE(p, MATH1, 0, DESCBUF, 0, 8,
997 ALG_OPERATION(p, OP_ALG_ALGSEL_AES,
1002 SEQFIFOLOAD(p, MSG1, 0, VLF | LAST1 | FLUSH1);
1003 MOVE(p, CONTEXT1, 0, MATH3, 0, 4, WAITCOMP | IMMED);
1004 if (rta_sec_era <= RTA_SEC_ERA_3)
1005 LOAD(p, CLRW_CLR_C1KEY |
1012 LOAD(p, CLRW_RESET_CLS1_CHA |
1020 if (rta_sec_era <= RTA_SEC_ERA_3)
1021 LOAD(p, CCTRL_RESET_CHA_ALL, CCTRL, 0, 4, IMMED);
1023 KEY(p, KEY1, cipherdata->key_enc_flags, cipherdata->key,
1024 cipherdata->keylen, INLINE_KEY(cipherdata));
1025 SET_LABEL(p, local_offset);
1026 MOVE(p, MATH2, 0, CONTEXT1, 0, 8, IMMED);
1027 SEQINPTR(p, 0, 0, RTO);
1029 if (rta_sec_era == RTA_SEC_ERA_2 && era_2_sw_hfn_ovrd) {
1030 SEQFIFOLOAD(p, SKIP, 5, 0);
1031 MATHB(p, SEQINSZ, ADD, ONE, SEQINSZ, 4, 0);
1034 MATHB(p, SEQINSZ, SUB, ONE, VSEQINSZ, 4, 0);
1035 ALG_OPERATION(p, OP_ALG_ALGSEL_SNOW_F8,
1037 OP_ALG_AS_INITFINAL,
1040 SEQFIFOSTORE(p, MSG, 0, 0, VLF);
1042 if (rta_sec_era > RTA_SEC_ERA_2 ||
1043 (rta_sec_era == RTA_SEC_ERA_2 &&
1044 era_2_sw_hfn_ovrd == 0))
1045 SEQFIFOLOAD(p, SKIP, 1, 0);
1047 SEQFIFOLOAD(p, MSG1, 0, VLF);
1048 MOVE(p, MATH3, 0, IFIFOAB1, 0, 4, LAST1 | FLUSH1 | IMMED);
1049 PATCH_MOVE(p, seqin_ptr_read, local_offset);
1050 PATCH_MOVE(p, seqin_ptr_write, local_offset);
1052 MOVE(p, MATH2, 0, CONTEXT1, 0, 8, IMMED);
1054 if (rta_sec_era >= RTA_SEC_ERA_5)
1055 MOVE(p, CONTEXT1, 0, CONTEXT2, 0, 8, IMMED);
1057 if (rta_sec_era > RTA_SEC_ERA_2)
1058 MATHB(p, SEQINSZ, SUB, ZERO, VSEQINSZ, 4, 0);
1060 MATHB(p, SEQINSZ, SUB, MATH3, VSEQINSZ, 4, 0);
1062 MATHB(p, SEQINSZ, SUB, PDCP_MAC_I_LEN, VSEQOUTSZ, 4, IMMED2);
1064 * TODO: To be changed when proper support is added in RTA (can't load a
1065 * command that is also written by RTA (or patch it for that matter).
1066 * Change when proper RTA support is added.
1069 WORD(p, 0x168B0004);
1071 WORD(p, 0x16880404);
1073 jump_back_to_sd_cmd = JUMP(p, 0, LOCAL_JUMP, ALL_TRUE, 0);
1075 * Placeholder for command reading the SEQ OUT command in
1076 * JD. Done for rereading the decrypted data and performing
1077 * the integrity check
1080 * TODO: RTA currently doesn't support patching of length of a MOVE command
1081 * Thus, it is inserted as a raw word, as per PS setting.
1084 seq_out_read = MOVE(p, DESCBUF, 0, MATH1, 0, 20,
1087 seq_out_read = MOVE(p, DESCBUF, 0, MATH1, 0, 16,
1090 MATHB(p, MATH1, XOR, CMD_SEQ_IN_PTR ^ CMD_SEQ_OUT_PTR, MATH1, 4,
1092 /* Placeholder for overwriting the SEQ IN with SEQ OUT */
1094 * TODO: RTA currently doesn't support patching of length of a MOVE command
1095 * Thus, it is inserted as a raw word, as per PS setting.
1098 MOVE(p, MATH1, 0, DESCBUF, 0, 24, IMMED);
1100 MOVE(p, MATH1, 0, DESCBUF, 0, 20, IMMED);
1102 KEY(p, KEY1, cipherdata->key_enc_flags, cipherdata->key,
1103 cipherdata->keylen, INLINE_KEY(cipherdata));
1105 if (rta_sec_era >= RTA_SEC_ERA_4)
1106 MOVE(p, CONTEXT1, 0, CONTEXT2, 0, 8, IMMED);
1108 MOVE(p, CONTEXT1, 0, MATH3, 0, 8, IMMED);
1110 ALG_OPERATION(p, OP_ALG_ALGSEL_SNOW_F8,
1112 OP_ALG_AS_INITFINAL,
1115 SEQFIFOSTORE(p, MSG, 0, 0, VLF | CONT);
1116 SEQFIFOLOAD(p, MSG1, 0, VLF | LAST1 | FLUSH1);
1118 if (rta_sec_era <= RTA_SEC_ERA_3)
1119 move_mac_i_to_desc_buf = MOVE(p, OFIFO, 0, DESCBUF, 0,
1120 4, WAITCOMP | IMMED);
1122 MOVE(p, OFIFO, 0, MATH3, 0, 4, IMMED);
1124 if (rta_sec_era <= RTA_SEC_ERA_3)
1125 LOAD(p, CCTRL_RESET_CHA_ALL, CCTRL, 0, 4, IMMED);
1127 LOAD(p, CLRW_RESET_CLS1_CHA |
1135 KEY(p, KEY1, authdata->key_enc_flags, authdata->key,
1136 authdata->keylen, INLINE_KEY(authdata));
1138 * Placeholder for jump in SD for executing the new SEQ IN PTR
1139 * command (which is actually the old SEQ OUT PTR command
1140 * copied over from JD.
1142 SET_LABEL(p, jump_to_beginning);
1143 JUMP(p, 1 - jump_to_beginning, LOCAL_JUMP, ALL_TRUE, 0);
1144 SET_LABEL(p, back_to_sd_offset);
1145 ALG_OPERATION(p, OP_ALG_ALGSEL_AES,
1147 OP_ALG_AS_INITFINAL,
1151 /* Read the # of bytes written in the output buffer + 1 (HDR) */
1152 MATHB(p, VSEQOUTSZ, ADD, ONE, VSEQINSZ, 4, 0);
1154 if (rta_sec_era <= RTA_SEC_ERA_3)
1155 MOVE(p, MATH3, 0, IFIFOAB1, 0, 8, IMMED);
1157 MOVE(p, CONTEXT2, 0, IFIFOAB1, 0, 8, IMMED);
1159 if (rta_sec_era == RTA_SEC_ERA_2 && era_2_sw_hfn_ovrd)
1160 SEQFIFOLOAD(p, SKIP, 4, 0);
1162 SEQFIFOLOAD(p, MSG1, 0, VLF | LAST1 | FLUSH1);
1164 if (rta_sec_era >= RTA_SEC_ERA_4) {
1165 LOAD(p, NFIFOENTRY_STYPE_ALTSOURCE |
1166 NFIFOENTRY_DEST_CLASS1 |
1167 NFIFOENTRY_DTYPE_ICV |
1169 NFIFOENTRY_FC1 | 4, NFIFO_SZL, 0, 4, IMMED);
1170 MOVE(p, MATH3, 0, ALTSOURCE, 0, 4, IMMED);
1172 SET_LABEL(p, fifo_load_mac_i_offset);
1173 FIFOLOAD(p, ICV1, fifo_load_mac_i_offset, 4,
1174 LAST1 | FLUSH1 | IMMED);
1177 SET_LABEL(p, end_desc);
1180 PATCH_MOVE(p, seq_out_read, end_desc + 1);
1181 PATCH_JUMP(p, jump_back_to_sd_cmd,
1182 back_to_sd_offset + jump_back_to_sd_cmd - 5);
1184 if (rta_sec_era <= RTA_SEC_ERA_3)
1185 PATCH_MOVE(p, move_mac_i_to_desc_buf,
1186 fifo_load_mac_i_offset + 1);
1188 PATCH_MOVE(p, seq_out_read, end_desc + 2);
1189 PATCH_JUMP(p, jump_back_to_sd_cmd,
1190 back_to_sd_offset + jump_back_to_sd_cmd - 5);
1192 if (rta_sec_era <= RTA_SEC_ERA_3)
1193 PATCH_MOVE(p, move_mac_i_to_desc_buf,
1194 fifo_load_mac_i_offset + 1);
1202 pdcp_insert_cplane_aes_snow_op(struct program *p,
1203 bool swap __maybe_unused,
1204 struct alginfo *cipherdata,
1205 struct alginfo *authdata,
1207 enum pdcp_sn_size sn_size,
1208 unsigned char era_2_sw_hfn_ovrd __maybe_unused)
1210 KEY(p, KEY1, cipherdata->key_enc_flags, cipherdata->key,
1211 cipherdata->keylen, INLINE_KEY(cipherdata));
1212 KEY(p, KEY2, authdata->key_enc_flags, authdata->key, authdata->keylen,
1213 INLINE_KEY(authdata));
1215 if (rta_sec_era >= RTA_SEC_ERA_8) {
1218 if (sn_size == PDCP_SN_SIZE_5)
1219 pclid = OP_PCLID_LTE_PDCP_CTRL_MIXED;
1221 pclid = OP_PCLID_LTE_PDCP_USER_RN;
1223 PROTOCOL(p, dir, pclid,
1224 ((uint16_t)cipherdata->algtype << 8) |
1225 (uint16_t)authdata->algtype);
1230 if (dir == OP_TYPE_ENCAP_PROTOCOL)
1231 MATHB(p, SEQINSZ, SUB, ONE, VSEQINSZ, 4, 0);
1233 SEQLOAD(p, MATH0, 7, 1, 0);
1234 JUMP(p, 1, LOCAL_JUMP, ALL_TRUE, CALM);
1235 MOVE(p, MATH0, 7, IFIFOAB2, 0, 1, IMMED);
1237 MATHB(p, MATH0, AND, PDCP_C_PLANE_SN_MASK, MATH1, 8,
1240 MATHB(p, MATH0, AND, PDCP_C_PLANE_SN_MASK_BE, MATH1, 8,
1243 SEQSTORE(p, MATH0, 7, 1, 0);
1244 MATHB(p, MATH1, SHLD, MATH1, MATH1, 8, 0);
1245 MOVE(p, DESCBUF, 4, MATH2, 0, 8, WAITCOMP | IMMED);
1246 MATHB(p, MATH1, OR, MATH2, MATH1, 8, 0);
1247 MOVE(p, MATH1, 0, CONTEXT1, 16, 8, IMMED);
1248 MOVE(p, MATH1, 0, CONTEXT2, 0, 4, IMMED);
1249 if (swap == false) {
1250 MATHB(p, MATH1, AND, lower_32_bits(PDCP_BEARER_MASK), MATH2, 4,
1252 MATHB(p, MATH1, AND, upper_32_bits(PDCP_DIR_MASK), MATH3, 4,
1255 MATHB(p, MATH1, AND, lower_32_bits(PDCP_BEARER_MASK_BE), MATH2,
1257 MATHB(p, MATH1, AND, upper_32_bits(PDCP_DIR_MASK_BE), MATH3,
1260 MATHB(p, MATH3, SHLD, MATH3, MATH3, 8, 0);
1261 MOVE(p, MATH2, 4, OFIFO, 0, 12, IMMED);
1262 MOVE(p, OFIFO, 0, CONTEXT2, 4, 12, IMMED);
1263 if (dir == OP_TYPE_ENCAP_PROTOCOL) {
1264 MATHB(p, SEQINSZ, ADD, PDCP_MAC_I_LEN, VSEQOUTSZ, 4, IMMED2);
1266 MATHB(p, SEQINSZ, SUB, PDCP_MAC_I_LEN, MATH1, 4, IMMED2);
1268 MATHB(p, ZERO, ADD, MATH1, VSEQOUTSZ, 4, 0);
1269 MATHB(p, ZERO, ADD, MATH1, VSEQINSZ, 4, 0);
1272 if (dir == OP_TYPE_ENCAP_PROTOCOL)
1273 SEQFIFOSTORE(p, MSG, 0, 0, VLF);
1275 SEQFIFOSTORE(p, MSG, 0, 0, VLF | CONT);
1277 ALG_OPERATION(p, OP_ALG_ALGSEL_SNOW_F9,
1279 OP_ALG_AS_INITFINAL,
1280 dir == OP_TYPE_ENCAP_PROTOCOL ?
1281 ICV_CHECK_DISABLE : ICV_CHECK_ENABLE,
1283 ALG_OPERATION(p, OP_ALG_ALGSEL_AES,
1285 OP_ALG_AS_INITFINAL,
1287 dir == OP_TYPE_ENCAP_PROTOCOL ? DIR_ENC : DIR_DEC);
1289 if (dir == OP_TYPE_ENCAP_PROTOCOL) {
1290 SEQFIFOLOAD(p, MSGINSNOOP, 0, VLF | LAST2);
1291 MOVE(p, CONTEXT2, 0, IFIFOAB1, 0, 4, LAST1 | FLUSH1 | IMMED);
1293 SEQFIFOLOAD(p, MSGOUTSNOOP, 0, VLF | LAST2);
1294 SEQFIFOLOAD(p, MSG1, 4, LAST1 | FLUSH1);
1295 JUMP(p, 1, LOCAL_JUMP, ALL_TRUE, CLASS1 | NOP | NIFP);
1297 if (rta_sec_era >= RTA_SEC_ERA_6)
1298 LOAD(p, 0, DCTRL, 0, LDLEN_RST_CHA_OFIFO_PTR, IMMED);
1300 MOVE(p, OFIFO, 0, MATH0, 0, 4, WAITCOMP | IMMED);
1302 NFIFOADD(p, IFIFO, ICV2, 4, LAST2);
1304 if (rta_sec_era <= RTA_SEC_ERA_2) {
1305 /* Shut off automatic Info FIFO entries */
1306 LOAD(p, 0, DCTRL, LDOFF_DISABLE_AUTO_NFIFO, 0, IMMED);
1307 MOVE(p, MATH0, 0, IFIFOAB2, 0, 4, WAITCOMP | IMMED);
1309 MOVE(p, MATH0, 0, IFIFO, 0, 4, WAITCOMP | IMMED);
1317 pdcp_insert_cplane_snow_zuc_op(struct program *p,
1318 bool swap __maybe_unused,
1319 struct alginfo *cipherdata,
1320 struct alginfo *authdata,
1322 enum pdcp_sn_size sn_size,
1323 unsigned char era_2_sw_hfn_ovrd __maybe_unused)
1326 REFERENCE(pkeyjump);
1328 if (rta_sec_era < RTA_SEC_ERA_5) {
1329 pr_err("Invalid era for selected algorithm\n");
1333 pkeyjump = JUMP(p, keyjump, LOCAL_JUMP, ALL_TRUE, SHRD | SELF | BOTH);
1334 KEY(p, KEY1, cipherdata->key_enc_flags, cipherdata->key,
1335 cipherdata->keylen, INLINE_KEY(cipherdata));
1336 KEY(p, KEY2, authdata->key_enc_flags, authdata->key, authdata->keylen,
1337 INLINE_KEY(authdata));
1339 SET_LABEL(p, keyjump);
1341 if (rta_sec_era >= RTA_SEC_ERA_8) {
1344 if (sn_size == PDCP_SN_SIZE_5)
1345 pclid = OP_PCLID_LTE_PDCP_CTRL_MIXED;
1347 pclid = OP_PCLID_LTE_PDCP_USER_RN;
1349 PROTOCOL(p, dir, pclid,
1350 ((uint16_t)cipherdata->algtype << 8) |
1351 (uint16_t)authdata->algtype);
1355 SEQLOAD(p, MATH0, 7, 1, 0);
1356 JUMP(p, 1, LOCAL_JUMP, ALL_TRUE, CALM);
1357 MOVE(p, MATH0, 7, IFIFOAB2, 0, 1, IMMED);
1359 MATHB(p, MATH0, AND, PDCP_C_PLANE_SN_MASK, MATH1, 8,
1362 MATHB(p, MATH0, AND, PDCP_C_PLANE_SN_MASK, MATH1, 8,
1365 MATHB(p, MATH1, SHLD, MATH1, MATH1, 8, 0);
1366 MOVE(p, DESCBUF, 4, MATH2, 0, 8, WAITCOMP | IMMED);
1367 MATHB(p, MATH1, OR, MATH2, MATH2, 8, 0);
1368 MOVE(p, MATH2, 0, CONTEXT1, 0, 8, IMMED);
1369 MOVE(p, MATH2, 0, CONTEXT2, 0, 8, WAITCOMP | IMMED);
1371 if (dir == OP_TYPE_ENCAP_PROTOCOL)
1372 MATHB(p, SEQINSZ, ADD, PDCP_MAC_I_LEN, VSEQOUTSZ, 4, IMMED2);
1374 MATHB(p, SEQINSZ, SUB, PDCP_MAC_I_LEN, VSEQOUTSZ, 4, IMMED2);
1376 MATHB(p, SEQINSZ, SUB, ZERO, VSEQINSZ, 4, 0);
1377 SEQSTORE(p, MATH0, 7, 1, 0);
1379 if (dir == OP_TYPE_ENCAP_PROTOCOL) {
1380 SEQFIFOSTORE(p, MSG, 0, 0, VLF);
1381 SEQFIFOLOAD(p, MSGINSNOOP, 0, VLF | LAST2);
1383 SEQFIFOSTORE(p, MSG, 0, 0, VLF | CONT);
1384 SEQFIFOLOAD(p, MSGOUTSNOOP, 0, VLF | LAST1 | FLUSH1);
1387 ALG_OPERATION(p, OP_ALG_ALGSEL_ZUCA,
1389 OP_ALG_AS_INITFINAL,
1390 dir == OP_TYPE_ENCAP_PROTOCOL ?
1391 ICV_CHECK_DISABLE : ICV_CHECK_ENABLE,
1394 ALG_OPERATION(p, OP_ALG_ALGSEL_SNOW_F8,
1396 OP_ALG_AS_INITFINAL,
1398 dir == OP_TYPE_ENCAP_PROTOCOL ? DIR_ENC : DIR_DEC);
1399 if (dir == OP_TYPE_ENCAP_PROTOCOL) {
1400 MOVE(p, CONTEXT2, 0, IFIFOAB1, 0, 4, LAST1 | FLUSH1 | IMMED);
1403 MOVE(p, OFIFO, 0, MATH0, 0, 4, IMMED);
1404 LOAD(p, NFIFOENTRY_STYPE_ALTSOURCE |
1405 NFIFOENTRY_DEST_CLASS2 |
1406 NFIFOENTRY_DTYPE_ICV |
1407 NFIFOENTRY_LC2 | 4, NFIFO_SZL, 0, 4, IMMED);
1408 MOVE(p, MATH0, 0, ALTSOURCE, 0, 4, WAITCOMP | IMMED);
1411 /* Reset ZUCA mode and done interrupt */
1412 LOAD(p, CLRW_CLR_C2MODE, CLRW, 0, 4, IMMED);
1413 LOAD(p, CIRQ_ZADI, ICTRL, 0, 4, IMMED);
1415 PATCH_JUMP(p, pkeyjump, keyjump);
1420 pdcp_insert_cplane_aes_zuc_op(struct program *p,
1421 bool swap __maybe_unused,
1422 struct alginfo *cipherdata,
1423 struct alginfo *authdata,
1425 enum pdcp_sn_size sn_size,
1426 unsigned char era_2_sw_hfn_ovrd __maybe_unused)
1429 REFERENCE(pkeyjump);
1431 if (rta_sec_era < RTA_SEC_ERA_5) {
1432 pr_err("Invalid era for selected algorithm\n");
1436 pkeyjump = JUMP(p, keyjump, LOCAL_JUMP, ALL_TRUE, SHRD | SELF | BOTH);
1437 KEY(p, KEY1, cipherdata->key_enc_flags, cipherdata->key,
1438 cipherdata->keylen, INLINE_KEY(cipherdata));
1439 KEY(p, KEY2, authdata->key_enc_flags, authdata->key, authdata->keylen,
1440 INLINE_KEY(authdata));
1442 if (rta_sec_era >= RTA_SEC_ERA_8) {
1445 if (sn_size == PDCP_SN_SIZE_5)
1446 pclid = OP_PCLID_LTE_PDCP_CTRL_MIXED;
1448 pclid = OP_PCLID_LTE_PDCP_USER_RN;
1450 PROTOCOL(p, dir, pclid,
1451 ((uint16_t)cipherdata->algtype << 8) |
1452 (uint16_t)authdata->algtype);
1457 SET_LABEL(p, keyjump);
1458 SEQLOAD(p, MATH0, 7, 1, 0);
1459 JUMP(p, 1, LOCAL_JUMP, ALL_TRUE, CALM);
1460 MOVE(p, MATH0, 7, IFIFOAB2, 0, 1, IMMED);
1462 MATHB(p, MATH0, AND, PDCP_C_PLANE_SN_MASK, MATH1, 8,
1465 MATHB(p, MATH0, AND, PDCP_C_PLANE_SN_MASK, MATH1, 8,
1468 MATHB(p, MATH1, SHLD, MATH1, MATH1, 8, 0);
1469 MOVE(p, DESCBUF, 4, MATH2, 0, 8, WAITCOMP | IMMED);
1470 MATHB(p, MATH1, OR, MATH2, MATH2, 8, 0);
1471 MOVE(p, MATH2, 0, CONTEXT1, 16, 8, IMMED);
1472 MOVE(p, MATH2, 0, CONTEXT2, 0, 8, WAITCOMP | IMMED);
1474 if (dir == OP_TYPE_ENCAP_PROTOCOL)
1475 MATHB(p, SEQINSZ, ADD, PDCP_MAC_I_LEN, VSEQOUTSZ, 4, IMMED2);
1477 MATHB(p, SEQINSZ, SUB, PDCP_MAC_I_LEN, VSEQOUTSZ, 4, IMMED2);
1479 MATHB(p, SEQINSZ, SUB, ZERO, VSEQINSZ, 4, 0);
1480 SEQSTORE(p, MATH0, 7, 1, 0);
1482 if (dir == OP_TYPE_ENCAP_PROTOCOL) {
1483 SEQFIFOSTORE(p, MSG, 0, 0, VLF);
1484 SEQFIFOLOAD(p, MSGINSNOOP, 0, VLF | LAST2);
1486 SEQFIFOSTORE(p, MSG, 0, 0, VLF | CONT);
1487 SEQFIFOLOAD(p, MSGOUTSNOOP, 0, VLF | LAST1 | FLUSH1);
1490 ALG_OPERATION(p, OP_ALG_ALGSEL_ZUCA,
1492 OP_ALG_AS_INITFINAL,
1493 dir == OP_TYPE_ENCAP_PROTOCOL ?
1494 ICV_CHECK_DISABLE : ICV_CHECK_ENABLE,
1497 ALG_OPERATION(p, OP_ALG_ALGSEL_AES,
1499 OP_ALG_AS_INITFINAL,
1501 dir == OP_TYPE_ENCAP_PROTOCOL ? DIR_ENC : DIR_DEC);
1503 if (dir == OP_TYPE_ENCAP_PROTOCOL) {
1504 MOVE(p, CONTEXT2, 0, IFIFOAB1, 0, 4, LAST1 | FLUSH1 | IMMED);
1507 MOVE(p, OFIFO, 0, MATH0, 0, 4, IMMED);
1509 LOAD(p, NFIFOENTRY_STYPE_ALTSOURCE |
1510 NFIFOENTRY_DEST_CLASS2 |
1511 NFIFOENTRY_DTYPE_ICV |
1512 NFIFOENTRY_LC2 | 4, NFIFO_SZL, 0, 4, IMMED);
1513 MOVE(p, MATH0, 0, ALTSOURCE, 0, 4, WAITCOMP | IMMED);
1516 /* Reset ZUCA mode and done interrupt */
1517 LOAD(p, CLRW_CLR_C2MODE, CLRW, 0, 4, IMMED);
1518 LOAD(p, CIRQ_ZADI, ICTRL, 0, 4, IMMED);
1520 PATCH_JUMP(p, pkeyjump, keyjump);
1526 pdcp_insert_cplane_zuc_snow_op(struct program *p,
1527 bool swap __maybe_unused,
1528 struct alginfo *cipherdata,
1529 struct alginfo *authdata,
1531 enum pdcp_sn_size sn_size,
1532 unsigned char era_2_sw_hfn_ovrd __maybe_unused)
1535 REFERENCE(pkeyjump);
1537 if (rta_sec_era < RTA_SEC_ERA_5) {
1538 pr_err("Invalid era for selected algorithm\n");
1542 pkeyjump = JUMP(p, keyjump, LOCAL_JUMP, ALL_TRUE, SHRD | SELF | BOTH);
1543 KEY(p, KEY1, cipherdata->key_enc_flags, cipherdata->key,
1544 cipherdata->keylen, INLINE_KEY(cipherdata));
1545 KEY(p, KEY2, authdata->key_enc_flags, authdata->key, authdata->keylen,
1546 INLINE_KEY(authdata));
1548 if (rta_sec_era >= RTA_SEC_ERA_8) {
1551 if (sn_size == PDCP_SN_SIZE_5)
1552 pclid = OP_PCLID_LTE_PDCP_CTRL_MIXED;
1554 pclid = OP_PCLID_LTE_PDCP_USER_RN;
1556 PROTOCOL(p, dir, pclid,
1557 ((uint16_t)cipherdata->algtype << 8) |
1558 (uint16_t)authdata->algtype);
1563 SET_LABEL(p, keyjump);
1564 SEQLOAD(p, MATH0, 7, 1, 0);
1565 JUMP(p, 1, LOCAL_JUMP, ALL_TRUE, CALM);
1566 MOVE(p, MATH0, 7, IFIFOAB2, 0, 1, IMMED);
1568 MATHB(p, MATH0, AND, PDCP_C_PLANE_SN_MASK, MATH1, 8,
1571 MATHB(p, MATH0, AND, PDCP_C_PLANE_SN_MASK, MATH1, 8,
1574 MATHB(p, MATH1, SHLD, MATH1, MATH1, 8, 0);
1575 MOVE(p, DESCBUF, 4, MATH2, 0, 8, WAITCOMP | IMMED);
1576 MATHB(p, MATH1, OR, MATH2, MATH1, 8, 0);
1577 MOVE(p, MATH1, 0, CONTEXT1, 0, 8, IMMED);
1578 MOVE(p, MATH1, 0, CONTEXT2, 0, 4, IMMED);
1579 if (swap == false) {
1580 MATHB(p, MATH1, AND, lower_32_bits(PDCP_BEARER_MASK), MATH2,
1582 MATHB(p, MATH1, AND, upper_32_bits(PDCP_DIR_MASK), MATH3,
1585 MATHB(p, MATH1, AND, lower_32_bits(PDCP_BEARER_MASK_BE), MATH2,
1587 MATHB(p, MATH1, AND, upper_32_bits(PDCP_DIR_MASK_BE), MATH3,
1590 MATHB(p, MATH3, SHLD, MATH3, MATH3, 8, 0);
1591 MOVE(p, MATH2, 4, OFIFO, 0, 12, IMMED);
1592 MOVE(p, OFIFO, 0, CONTEXT2, 4, 12, IMMED);
1594 if (dir == OP_TYPE_ENCAP_PROTOCOL) {
1595 MATHB(p, SEQINSZ, ADD, PDCP_MAC_I_LEN, VSEQOUTSZ, 4, IMMED2);
1596 MATHB(p, SEQINSZ, SUB, ZERO, VSEQINSZ, 4, 0);
1598 MATHB(p, SEQINSZ, SUB, PDCP_MAC_I_LEN, VSEQOUTSZ, 4, IMMED2);
1599 MATHB(p, VSEQOUTSZ, SUB, ZERO, VSEQINSZ, 4, 0);
1602 SEQSTORE(p, MATH0, 7, 1, 0);
1604 if (dir == OP_TYPE_ENCAP_PROTOCOL) {
1605 SEQFIFOSTORE(p, MSG, 0, 0, VLF);
1606 SEQFIFOLOAD(p, MSGINSNOOP, 0, VLF | LAST2);
1608 SEQFIFOSTORE(p, MSG, 0, 0, VLF | CONT);
1609 SEQFIFOLOAD(p, MSGOUTSNOOP, 0, VLF | LAST2);
1612 ALG_OPERATION(p, OP_ALG_ALGSEL_SNOW_F9,
1614 OP_ALG_AS_INITFINAL,
1615 dir == OP_TYPE_ENCAP_PROTOCOL ?
1616 ICV_CHECK_DISABLE : ICV_CHECK_ENABLE,
1619 ALG_OPERATION(p, OP_ALG_ALGSEL_ZUCE,
1621 OP_ALG_AS_INITFINAL,
1623 dir == OP_TYPE_ENCAP_PROTOCOL ? DIR_ENC : DIR_DEC);
1625 if (dir == OP_TYPE_ENCAP_PROTOCOL) {
1626 MOVE(p, CONTEXT2, 0, IFIFOAB1, 0, 4, LAST1 | FLUSH1 | IMMED);
1628 SEQFIFOLOAD(p, MSG1, 4, LAST1 | FLUSH1);
1629 JUMP(p, 1, LOCAL_JUMP, ALL_TRUE, CLASS1 | NOP | NIFP);
1631 if (rta_sec_era >= RTA_SEC_ERA_6)
1633 * For SEC ERA 6, there's a problem with the OFIFO
1634 * pointer, and thus it needs to be reset here before
1637 LOAD(p, 0, DCTRL, 0, LDLEN_RST_CHA_OFIFO_PTR, IMMED);
1639 /* Put ICV to M0 before sending it to C2 for comparison. */
1640 MOVE(p, OFIFO, 0, MATH0, 0, 4, WAITCOMP | IMMED);
1642 LOAD(p, NFIFOENTRY_STYPE_ALTSOURCE |
1643 NFIFOENTRY_DEST_CLASS2 |
1644 NFIFOENTRY_DTYPE_ICV |
1645 NFIFOENTRY_LC2 | 4, NFIFO_SZL, 0, 4, IMMED);
1646 MOVE(p, MATH0, 0, ALTSOURCE, 0, 4, IMMED);
1649 PATCH_JUMP(p, pkeyjump, keyjump);
1654 pdcp_insert_cplane_zuc_aes_op(struct program *p,
1655 bool swap __maybe_unused,
1656 struct alginfo *cipherdata,
1657 struct alginfo *authdata,
1659 enum pdcp_sn_size sn_size,
1660 unsigned char era_2_sw_hfn_ovrd __maybe_unused)
1662 if (rta_sec_era < RTA_SEC_ERA_5) {
1663 pr_err("Invalid era for selected algorithm\n");
1667 if (rta_sec_era >= RTA_SEC_ERA_8) {
1670 KEY(p, KEY1, cipherdata->key_enc_flags, cipherdata->key,
1671 cipherdata->keylen, INLINE_KEY(cipherdata));
1672 KEY(p, KEY2, authdata->key_enc_flags, authdata->key,
1673 authdata->keylen, INLINE_KEY(authdata));
1675 if (sn_size == PDCP_SN_SIZE_5)
1676 pclid = OP_PCLID_LTE_PDCP_CTRL_MIXED;
1678 pclid = OP_PCLID_LTE_PDCP_USER_RN;
1680 PROTOCOL(p, dir, pclid,
1681 ((uint16_t)cipherdata->algtype << 8) |
1682 (uint16_t)authdata->algtype);
1686 SEQLOAD(p, MATH0, 7, 1, 0);
1687 JUMP(p, 1, LOCAL_JUMP, ALL_TRUE, CALM);
1689 MATHB(p, MATH0, AND, PDCP_C_PLANE_SN_MASK, MATH1, 8,
1692 MATHB(p, MATH0, AND, PDCP_C_PLANE_SN_MASK, MATH1, 8,
1695 MATHB(p, MATH1, SHLD, MATH1, MATH1, 8, 0);
1696 MOVE(p, DESCBUF, 4, MATH2, 0, 0x08, WAITCOMP | IMMED);
1697 MATHB(p, MATH1, OR, MATH2, MATH2, 8, 0);
1698 SEQSTORE(p, MATH0, 7, 1, 0);
1699 if (dir == OP_TYPE_ENCAP_PROTOCOL) {
1700 KEY(p, KEY1, authdata->key_enc_flags, authdata->key,
1701 authdata->keylen, INLINE_KEY(authdata));
1702 MOVE(p, MATH2, 0, IFIFOAB1, 0, 0x08, IMMED);
1703 MOVE(p, MATH0, 7, IFIFOAB1, 0, 1, IMMED);
1705 MATHB(p, SEQINSZ, SUB, ZERO, VSEQINSZ, 4, 0);
1706 MATHB(p, VSEQINSZ, ADD, PDCP_MAC_I_LEN, VSEQOUTSZ, 4, IMMED2);
1708 ALG_OPERATION(p, OP_ALG_ALGSEL_AES,
1710 OP_ALG_AS_INITFINAL,
1713 SEQFIFOLOAD(p, MSG1, 0, VLF | LAST1 | FLUSH1);
1714 MOVE(p, CONTEXT1, 0, MATH3, 0, 4, WAITCOMP | IMMED);
1715 LOAD(p, CLRW_RESET_CLS1_CHA |
1723 KEY(p, KEY1, cipherdata->key_enc_flags, cipherdata->key,
1724 cipherdata->keylen, INLINE_KEY(cipherdata));
1726 MOVE(p, MATH2, 0, CONTEXT1, 0, 8, IMMED);
1727 SEQINPTR(p, 0, PDCP_NULL_MAX_FRAME_LEN, RTO);
1729 ALG_OPERATION(p, OP_ALG_ALGSEL_ZUCE,
1731 OP_ALG_AS_INITFINAL,
1734 SEQFIFOSTORE(p, MSG, 0, 0, VLF);
1736 SEQFIFOLOAD(p, SKIP, 1, 0);
1738 SEQFIFOLOAD(p, MSG1, 0, VLF);
1739 MOVE(p, MATH3, 0, IFIFOAB1, 0, 4, LAST1 | FLUSH1 | IMMED);
1741 MOVE(p, MATH2, 0, CONTEXT1, 0, 8, IMMED);
1743 MOVE(p, CONTEXT1, 0, CONTEXT2, 0, 8, IMMED);
1745 MATHB(p, SEQINSZ, SUB, ZERO, VSEQINSZ, 4, 0);
1747 MATHB(p, SEQINSZ, SUB, PDCP_MAC_I_LEN, VSEQOUTSZ, 4, IMMED2);
1749 KEY(p, KEY1, cipherdata->key_enc_flags, cipherdata->key,
1750 cipherdata->keylen, INLINE_KEY(cipherdata));
1752 MOVE(p, CONTEXT1, 0, CONTEXT2, 0, 8, IMMED);
1754 ALG_OPERATION(p, OP_ALG_ALGSEL_ZUCE,
1756 OP_ALG_AS_INITFINAL,
1759 SEQFIFOSTORE(p, MSG, 0, 0, VLF | CONT);
1760 SEQFIFOLOAD(p, MSG1, 0, VLF | LAST1 | FLUSH1);
1762 MOVE(p, OFIFO, 0, MATH3, 0, 4, IMMED);
1764 LOAD(p, CLRW_RESET_CLS1_CHA |
1772 KEY(p, KEY1, authdata->key_enc_flags, authdata->key,
1773 authdata->keylen, INLINE_KEY(authdata));
1775 SEQINPTR(p, 0, 0, SOP);
1777 ALG_OPERATION(p, OP_ALG_ALGSEL_AES,
1779 OP_ALG_AS_INITFINAL,
1783 MATHB(p, SEQINSZ, SUB, ZERO, VSEQINSZ, 4, 0);
1785 MOVE(p, CONTEXT2, 0, IFIFOAB1, 0, 8, IMMED);
1787 SEQFIFOLOAD(p, MSG1, 0, VLF | LAST1 | FLUSH1);
1789 LOAD(p, NFIFOENTRY_STYPE_ALTSOURCE |
1790 NFIFOENTRY_DEST_CLASS1 |
1791 NFIFOENTRY_DTYPE_ICV |
1793 NFIFOENTRY_FC1 | 4, NFIFO_SZL, 0, 4, IMMED);
1794 MOVE(p, MATH3, 0, ALTSOURCE, 0, 4, IMMED);
1801 pdcp_insert_uplane_15bit_op(struct program *p,
1802 bool swap __maybe_unused,
1803 struct alginfo *cipherdata,
1807 /* Insert Cipher Key */
1808 KEY(p, KEY1, cipherdata->key_enc_flags, cipherdata->key,
1809 cipherdata->keylen, INLINE_KEY(cipherdata));
1811 if (rta_sec_era >= RTA_SEC_ERA_8) {
1812 PROTOCOL(p, dir, OP_PCLID_LTE_PDCP_USER,
1813 (uint16_t)cipherdata->algtype);
1817 SEQLOAD(p, MATH0, 6, 2, 0);
1818 JUMP(p, 1, LOCAL_JUMP, ALL_TRUE, CALM);
1820 MATHB(p, MATH0, AND, PDCP_U_PLANE_15BIT_SN_MASK, MATH1, 8,
1823 MATHB(p, MATH0, AND, PDCP_U_PLANE_15BIT_SN_MASK_BE, MATH1, 8,
1825 SEQSTORE(p, MATH0, 6, 2, 0);
1826 MATHB(p, MATH1, SHLD, MATH1, MATH1, 8, 0);
1827 MOVEB(p, DESCBUF, 8, MATH2, 0, 8, WAITCOMP | IMMED);
1828 MATHB(p, MATH1, OR, MATH2, MATH2, 8, 0);
1830 MATHB(p, SEQINSZ, SUB, MATH3, VSEQINSZ, 4, 0);
1831 MATHB(p, SEQINSZ, SUB, MATH3, VSEQOUTSZ, 4, 0);
1833 SEQFIFOSTORE(p, MSG, 0, 0, VLF);
1835 op = dir == OP_TYPE_ENCAP_PROTOCOL ? DIR_ENC : DIR_DEC;
1836 switch (cipherdata->algtype) {
1837 case PDCP_CIPHER_TYPE_SNOW:
1838 MOVEB(p, MATH2, 0, CONTEXT1, 0, 8, WAITCOMP | IMMED);
1839 ALG_OPERATION(p, OP_ALG_ALGSEL_SNOW_F8,
1841 OP_ALG_AS_INITFINAL,
1846 case PDCP_CIPHER_TYPE_AES:
1847 MOVEB(p, MATH2, 0, CONTEXT1, 0x10, 0x10, WAITCOMP | IMMED);
1848 ALG_OPERATION(p, OP_ALG_ALGSEL_AES,
1850 OP_ALG_AS_INITFINAL,
1855 case PDCP_CIPHER_TYPE_ZUC:
1856 if (rta_sec_era < RTA_SEC_ERA_5) {
1857 pr_err("Invalid era for selected algorithm\n");
1860 MOVEB(p, MATH2, 0, CONTEXT1, 0, 0x08, IMMED);
1861 MOVEB(p, MATH2, 0, CONTEXT1, 0x08, 0x08, WAITCOMP | IMMED);
1863 ALG_OPERATION(p, OP_ALG_ALGSEL_ZUCE,
1865 OP_ALG_AS_INITFINAL,
1871 pr_err("%s: Invalid encrypt algorithm selected: %d\n",
1872 "pdcp_insert_uplane_15bit_op", cipherdata->algtype);
1876 SEQFIFOLOAD(p, MSG1, 0, VLF | LAST1 | FLUSH1);
1882 * Function for inserting the snippet of code responsible for creating
1883 * the HFN override code via either DPOVRD or via the input frame.
1886 insert_hfn_ov_op(struct program *p,
1888 enum pdb_type_e pdb_type,
1889 unsigned char era_2_sw_hfn_ovrd)
1891 uint32_t imm = PDCP_DPOVRD_HFN_OV_EN;
1892 uint16_t hfn_pdb_offset;
1894 if (rta_sec_era == RTA_SEC_ERA_2 && !era_2_sw_hfn_ovrd)
1898 case PDCP_PDB_TYPE_NO_PDB:
1900 * If there is no PDB, then HFN override mechanism does not
1901 * make any sense, thus in this case the function will
1902 * return the pointer to the current position in the
1907 case PDCP_PDB_TYPE_REDUCED_PDB:
1911 case PDCP_PDB_TYPE_FULL_PDB:
1919 if (rta_sec_era > RTA_SEC_ERA_2) {
1920 MATHB(p, DPOVRD, AND, imm, NONE, 8, IFB | IMMED2);
1922 SEQLOAD(p, MATH0, 4, 4, 0);
1923 JUMP(p, 1, LOCAL_JUMP, ALL_TRUE, CALM);
1924 MATHB(p, MATH0, AND, imm, NONE, 8, IFB | IMMED2);
1925 SEQSTORE(p, MATH0, 4, 4, 0);
1928 if (rta_sec_era >= RTA_SEC_ERA_8)
1929 JUMP(p, 6, LOCAL_JUMP, ALL_TRUE, MATH_Z);
1931 JUMP(p, 5, LOCAL_JUMP, ALL_TRUE, MATH_Z);
1933 if (rta_sec_era > RTA_SEC_ERA_2)
1934 MATHB(p, DPOVRD, LSHIFT, shift, MATH0, 4, IMMED2);
1936 MATHB(p, MATH0, LSHIFT, shift, MATH0, 4, IMMED2);
1938 MATHB(p, MATH0, SHLD, MATH0, MATH0, 8, 0);
1939 MOVE(p, MATH0, 0, DESCBUF, hfn_pdb_offset, 4, IMMED);
1941 if (rta_sec_era >= RTA_SEC_ERA_8)
1943 * For ERA8, DPOVRD could be handled by the PROTOCOL command
1944 * itself. For now, this is not done. Thus, clear DPOVRD here
1945 * to alleviate any side-effects.
1947 MATHB(p, DPOVRD, AND, ZERO, DPOVRD, 4, STL);
1953 * PDCP Control PDB creation function
1955 static inline enum pdb_type_e
1956 cnstr_pdcp_c_plane_pdb(struct program *p,
1958 enum pdcp_sn_size sn_size,
1959 unsigned char bearer,
1960 unsigned char direction,
1961 uint32_t hfn_threshold,
1962 struct alginfo *cipherdata,
1963 struct alginfo *authdata)
1965 struct pdcp_pdb pdb;
1967 pdb_mask[PDCP_CIPHER_TYPE_INVALID][PDCP_AUTH_TYPE_INVALID] = {
1969 PDCP_PDB_TYPE_NO_PDB, /* NULL */
1970 PDCP_PDB_TYPE_FULL_PDB, /* SNOW f9 */
1971 PDCP_PDB_TYPE_FULL_PDB, /* AES CMAC */
1972 PDCP_PDB_TYPE_FULL_PDB /* ZUC-I */
1975 PDCP_PDB_TYPE_FULL_PDB, /* NULL */
1976 PDCP_PDB_TYPE_FULL_PDB, /* SNOW f9 */
1977 PDCP_PDB_TYPE_REDUCED_PDB, /* AES CMAC */
1978 PDCP_PDB_TYPE_REDUCED_PDB /* ZUC-I */
1981 PDCP_PDB_TYPE_FULL_PDB, /* NULL */
1982 PDCP_PDB_TYPE_REDUCED_PDB, /* SNOW f9 */
1983 PDCP_PDB_TYPE_FULL_PDB, /* AES CMAC */
1984 PDCP_PDB_TYPE_REDUCED_PDB /* ZUC-I */
1987 PDCP_PDB_TYPE_FULL_PDB, /* NULL */
1988 PDCP_PDB_TYPE_REDUCED_PDB, /* SNOW f9 */
1989 PDCP_PDB_TYPE_REDUCED_PDB, /* AES CMAC */
1990 PDCP_PDB_TYPE_FULL_PDB /* ZUC-I */
1994 if (rta_sec_era >= RTA_SEC_ERA_8) {
1995 memset(&pdb, 0x00, sizeof(struct pdcp_pdb));
1997 /* To support 12-bit seq numbers, we use u-plane opt in pdb.
1998 * SEC supports 5-bit only with c-plane opt in pdb.
2000 if (sn_size == PDCP_SN_SIZE_12) {
2001 pdb.hfn_res = hfn << PDCP_U_PLANE_PDB_LONG_SN_HFN_SHIFT;
2002 pdb.bearer_dir_res = (uint32_t)
2003 ((bearer << PDCP_U_PLANE_PDB_BEARER_SHIFT) |
2004 (direction << PDCP_U_PLANE_PDB_DIR_SHIFT));
2007 hfn_threshold << PDCP_U_PLANE_PDB_LONG_SN_HFN_THR_SHIFT;
2010 /* This means 5-bit c-plane.
2011 * Here we use c-plane opt in pdb
2014 /* This is a HW issue. Bit 2 should be set to zero,
2015 * but it does not work this way. Override here.
2017 pdb.opt_res.rsvd = 0x00000002;
2019 /* Copy relevant information from user to PDB */
2020 pdb.hfn_res = hfn << PDCP_C_PLANE_PDB_HFN_SHIFT;
2021 pdb.bearer_dir_res = (uint32_t)
2022 ((bearer << PDCP_C_PLANE_PDB_BEARER_SHIFT) |
2023 (direction << PDCP_C_PLANE_PDB_DIR_SHIFT));
2025 hfn_threshold << PDCP_C_PLANE_PDB_HFN_THR_SHIFT;
2028 /* copy PDB in descriptor*/
2029 __rta_out32(p, pdb.opt_res.opt);
2030 __rta_out32(p, pdb.hfn_res);
2031 __rta_out32(p, pdb.bearer_dir_res);
2032 __rta_out32(p, pdb.hfn_thr_res);
2034 return PDCP_PDB_TYPE_FULL_PDB;
2037 switch (pdb_mask[cipherdata->algtype][authdata->algtype]) {
2038 case PDCP_PDB_TYPE_NO_PDB:
2041 case PDCP_PDB_TYPE_REDUCED_PDB:
2042 __rta_out32(p, (hfn << PDCP_C_PLANE_PDB_HFN_SHIFT));
2044 (uint32_t)((bearer <<
2045 PDCP_C_PLANE_PDB_BEARER_SHIFT) |
2047 PDCP_C_PLANE_PDB_DIR_SHIFT)));
2050 case PDCP_PDB_TYPE_FULL_PDB:
2051 memset(&pdb, 0x00, sizeof(struct pdcp_pdb));
2053 /* This is a HW issue. Bit 2 should be set to zero,
2054 * but it does not work this way. Override here.
2056 pdb.opt_res.rsvd = 0x00000002;
2058 /* Copy relevant information from user to PDB */
2059 pdb.hfn_res = hfn << PDCP_C_PLANE_PDB_HFN_SHIFT;
2060 pdb.bearer_dir_res = (uint32_t)
2061 ((bearer << PDCP_C_PLANE_PDB_BEARER_SHIFT) |
2062 (direction << PDCP_C_PLANE_PDB_DIR_SHIFT));
2064 hfn_threshold << PDCP_C_PLANE_PDB_HFN_THR_SHIFT;
2066 /* copy PDB in descriptor*/
2067 __rta_out32(p, pdb.opt_res.opt);
2068 __rta_out32(p, pdb.hfn_res);
2069 __rta_out32(p, pdb.bearer_dir_res);
2070 __rta_out32(p, pdb.hfn_thr_res);
2075 return PDCP_PDB_TYPE_INVALID;
2078 return pdb_mask[cipherdata->algtype][authdata->algtype];
2082 * PDCP UPlane PDB creation function
2085 cnstr_pdcp_u_plane_pdb(struct program *p,
2086 enum pdcp_sn_size sn_size,
2087 uint32_t hfn, unsigned short bearer,
2088 unsigned short direction,
2089 uint32_t hfn_threshold)
2091 struct pdcp_pdb pdb;
2092 /* Read options from user */
2093 /* Depending on sequence number length, the HFN and HFN threshold
2094 * have different lengths.
2096 memset(&pdb, 0x00, sizeof(struct pdcp_pdb));
2099 case PDCP_SN_SIZE_7:
2100 pdb.opt_res.opt |= PDCP_U_PLANE_PDB_OPT_SHORT_SN;
2101 pdb.hfn_res = hfn << PDCP_U_PLANE_PDB_SHORT_SN_HFN_SHIFT;
2103 hfn_threshold<<PDCP_U_PLANE_PDB_SHORT_SN_HFN_THR_SHIFT;
2106 case PDCP_SN_SIZE_12:
2107 pdb.opt_res.opt &= (uint32_t)(~PDCP_U_PLANE_PDB_OPT_SHORT_SN);
2108 pdb.hfn_res = hfn << PDCP_U_PLANE_PDB_LONG_SN_HFN_SHIFT;
2110 hfn_threshold<<PDCP_U_PLANE_PDB_LONG_SN_HFN_THR_SHIFT;
2113 case PDCP_SN_SIZE_15:
2114 pdb.opt_res.opt = (uint32_t)(PDCP_U_PLANE_PDB_OPT_15B_SN);
2115 pdb.hfn_res = hfn << PDCP_U_PLANE_PDB_15BIT_SN_HFN_SHIFT;
2117 hfn_threshold<<PDCP_U_PLANE_PDB_15BIT_SN_HFN_THR_SHIFT;
2121 pr_err("Invalid Sequence Number Size setting in PDB\n");
2125 pdb.bearer_dir_res = (uint32_t)
2126 ((bearer << PDCP_U_PLANE_PDB_BEARER_SHIFT) |
2127 (direction << PDCP_U_PLANE_PDB_DIR_SHIFT));
2129 /* copy PDB in descriptor*/
2130 __rta_out32(p, pdb.opt_res.opt);
2131 __rta_out32(p, pdb.hfn_res);
2132 __rta_out32(p, pdb.bearer_dir_res);
2133 __rta_out32(p, pdb.hfn_thr_res);
2138 * cnstr_shdsc_pdcp_c_plane_encap - Function for creating a PDCP Control Plane
2139 * encapsulation descriptor.
2140 * @descbuf: pointer to buffer for descriptor construction
2141 * @ps: if 36/40bit addressing is desired, this parameter must be true
2142 * @swap: must be true when core endianness doesn't match SEC endianness
2143 * @hfn: starting Hyper Frame Number to be used together with the SN from the
2145 * @sn_size: size of sequence numbers, only 5/12 bit sequence numbers are valid
2146 * @bearer: radio bearer ID
2147 * @direction: the direction of the PDCP frame (UL/DL)
2148 * @hfn_threshold: HFN value that once reached triggers a warning from SEC that
2149 * keys should be renegotiated at the earliest convenience.
2150 * @cipherdata: pointer to block cipher transform definitions
2151 * Valid algorithm values are those from cipher_type_pdcp enum.
2152 * @authdata: pointer to authentication transform definitions
2153 * Valid algorithm values are those from auth_type_pdcp enum.
2154 * @era_2_sw_hfn_ovrd: if software HFN override mechanism is desired for
2155 * this descriptor. Note: Can only be used for
2157 * Return: size of descriptor written in words or negative number on error.
2158 * Once the function returns, the value of this parameter can be used
2159 * for reclaiming the space that wasn't used for the descriptor.
2161 * Note: descbuf must be large enough to contain a full 256 byte long
2162 * descriptor; after the function returns, by subtracting the actual number of
2163 * bytes used, the user can reuse the remaining buffer space for other purposes.
2166 cnstr_shdsc_pdcp_c_plane_encap(uint32_t *descbuf,
2170 enum pdcp_sn_size sn_size,
2171 unsigned char bearer,
2172 unsigned char direction,
2173 uint32_t hfn_threshold,
2174 struct alginfo *cipherdata,
2175 struct alginfo *authdata,
2176 unsigned char era_2_sw_hfn_ovrd)
2179 (*pdcp_cp_fp[PDCP_CIPHER_TYPE_INVALID][PDCP_AUTH_TYPE_INVALID])
2180 (struct program*, bool swap, struct alginfo *,
2181 struct alginfo *, unsigned int, enum pdcp_sn_size,
2182 unsigned char __maybe_unused) = {
2184 pdcp_insert_cplane_null_op, /* NULL */
2185 pdcp_insert_cplane_int_only_op, /* SNOW f9 */
2186 pdcp_insert_cplane_int_only_op, /* AES CMAC */
2187 pdcp_insert_cplane_int_only_op /* ZUC-I */
2190 pdcp_insert_cplane_enc_only_op, /* NULL */
2191 pdcp_insert_cplane_acc_op, /* SNOW f9 */
2192 pdcp_insert_cplane_snow_aes_op, /* AES CMAC */
2193 pdcp_insert_cplane_snow_zuc_op /* ZUC-I */
2196 pdcp_insert_cplane_enc_only_op, /* NULL */
2197 pdcp_insert_cplane_aes_snow_op, /* SNOW f9 */
2198 pdcp_insert_cplane_acc_op, /* AES CMAC */
2199 pdcp_insert_cplane_aes_zuc_op /* ZUC-I */
2202 pdcp_insert_cplane_enc_only_op, /* NULL */
2203 pdcp_insert_cplane_zuc_snow_op, /* SNOW f9 */
2204 pdcp_insert_cplane_zuc_aes_op, /* AES CMAC */
2205 pdcp_insert_cplane_acc_op /* ZUC-I */
2208 static enum rta_share_type
2209 desc_share[PDCP_CIPHER_TYPE_INVALID][PDCP_AUTH_TYPE_INVALID] = {
2211 SHR_WAIT, /* NULL */
2212 SHR_ALWAYS, /* SNOW f9 */
2213 SHR_ALWAYS, /* AES CMAC */
2214 SHR_ALWAYS /* ZUC-I */
2217 SHR_ALWAYS, /* NULL */
2218 SHR_ALWAYS, /* SNOW f9 */
2219 SHR_WAIT, /* AES CMAC */
2220 SHR_WAIT /* ZUC-I */
2223 SHR_ALWAYS, /* NULL */
2224 SHR_ALWAYS, /* SNOW f9 */
2225 SHR_ALWAYS, /* AES CMAC */
2226 SHR_WAIT /* ZUC-I */
2229 SHR_ALWAYS, /* NULL */
2230 SHR_WAIT, /* SNOW f9 */
2231 SHR_WAIT, /* AES CMAC */
2232 SHR_ALWAYS /* ZUC-I */
2235 enum pdb_type_e pdb_type;
2237 struct program *p = &prg;
2241 if (rta_sec_era != RTA_SEC_ERA_2 && era_2_sw_hfn_ovrd) {
2242 pr_err("Cannot select SW HFN override for other era than 2");
2246 if (sn_size != PDCP_SN_SIZE_12 && sn_size != PDCP_SN_SIZE_5) {
2247 pr_err("C-plane supports only 5-bit and 12-bit sequence numbers\n");
2251 PROGRAM_CNTXT_INIT(p, descbuf, 0);
2253 PROGRAM_SET_BSWAP(p);
2255 PROGRAM_SET_36BIT_ADDR(p);
2257 SHR_HDR(p, desc_share[cipherdata->algtype][authdata->algtype], 0, 0);
2259 pdb_type = cnstr_pdcp_c_plane_pdb(p,
2268 SET_LABEL(p, pdb_end);
2270 err = insert_hfn_ov_op(p, sn_size, pdb_type,
2275 err = pdcp_cp_fp[cipherdata->algtype][authdata->algtype](p,
2279 OP_TYPE_ENCAP_PROTOCOL,
2285 PATCH_HDR(p, 0, pdb_end);
2287 return PROGRAM_FINALIZE(p);
2291 * cnstr_shdsc_pdcp_c_plane_decap - Function for creating a PDCP Control Plane
2292 * decapsulation descriptor.
2293 * @descbuf: pointer to buffer for descriptor construction
2294 * @ps: if 36/40bit addressing is desired, this parameter must be true
2295 * @swap: must be true when core endianness doesn't match SEC endianness
2296 * @hfn: starting Hyper Frame Number to be used together with the SN from the
2298 * @sn_size: size of sequence numbers, only 5/12 bit sequence numbers are valid
2299 * @bearer: radio bearer ID
2300 * @direction: the direction of the PDCP frame (UL/DL)
2301 * @hfn_threshold: HFN value that once reached triggers a warning from SEC that
2302 * keys should be renegotiated at the earliest convenience.
2303 * @cipherdata: pointer to block cipher transform definitions
2304 * Valid algorithm values are those from cipher_type_pdcp enum.
2305 * @authdata: pointer to authentication transform definitions
2306 * Valid algorithm values are those from auth_type_pdcp enum.
2307 * @era_2_sw_hfn_ovrd: if software HFN override mechanism is desired for
2308 * this descriptor. Note: Can only be used for
2311 * Return: size of descriptor written in words or negative number on error.
2312 * Once the function returns, the value of this parameter can be used
2313 * for reclaiming the space that wasn't used for the descriptor.
2315 * Note: descbuf must be large enough to contain a full 256 byte long
2316 * descriptor; after the function returns, by subtracting the actual number of
2317 * bytes used, the user can reuse the remaining buffer space for other purposes.
2320 cnstr_shdsc_pdcp_c_plane_decap(uint32_t *descbuf,
2324 enum pdcp_sn_size sn_size,
2325 unsigned char bearer,
2326 unsigned char direction,
2327 uint32_t hfn_threshold,
2328 struct alginfo *cipherdata,
2329 struct alginfo *authdata,
2330 unsigned char era_2_sw_hfn_ovrd)
2333 (*pdcp_cp_fp[PDCP_CIPHER_TYPE_INVALID][PDCP_AUTH_TYPE_INVALID])
2334 (struct program*, bool swap, struct alginfo *,
2335 struct alginfo *, unsigned int, enum pdcp_sn_size,
2338 pdcp_insert_cplane_null_op, /* NULL */
2339 pdcp_insert_cplane_int_only_op, /* SNOW f9 */
2340 pdcp_insert_cplane_int_only_op, /* AES CMAC */
2341 pdcp_insert_cplane_int_only_op /* ZUC-I */
2344 pdcp_insert_cplane_enc_only_op, /* NULL */
2345 pdcp_insert_cplane_acc_op, /* SNOW f9 */
2346 pdcp_insert_cplane_snow_aes_op, /* AES CMAC */
2347 pdcp_insert_cplane_snow_zuc_op /* ZUC-I */
2350 pdcp_insert_cplane_enc_only_op, /* NULL */
2351 pdcp_insert_cplane_aes_snow_op, /* SNOW f9 */
2352 pdcp_insert_cplane_acc_op, /* AES CMAC */
2353 pdcp_insert_cplane_aes_zuc_op /* ZUC-I */
2356 pdcp_insert_cplane_enc_only_op, /* NULL */
2357 pdcp_insert_cplane_zuc_snow_op, /* SNOW f9 */
2358 pdcp_insert_cplane_zuc_aes_op, /* AES CMAC */
2359 pdcp_insert_cplane_acc_op /* ZUC-I */
2362 static enum rta_share_type
2363 desc_share[PDCP_CIPHER_TYPE_INVALID][PDCP_AUTH_TYPE_INVALID] = {
2365 SHR_WAIT, /* NULL */
2366 SHR_ALWAYS, /* SNOW f9 */
2367 SHR_ALWAYS, /* AES CMAC */
2368 SHR_ALWAYS /* ZUC-I */
2371 SHR_ALWAYS, /* NULL */
2372 SHR_ALWAYS, /* SNOW f9 */
2373 SHR_WAIT, /* AES CMAC */
2374 SHR_WAIT /* ZUC-I */
2377 SHR_ALWAYS, /* NULL */
2378 SHR_ALWAYS, /* SNOW f9 */
2379 SHR_ALWAYS, /* AES CMAC */
2380 SHR_WAIT /* ZUC-I */
2383 SHR_ALWAYS, /* NULL */
2384 SHR_WAIT, /* SNOW f9 */
2385 SHR_WAIT, /* AES CMAC */
2386 SHR_ALWAYS /* ZUC-I */
2389 enum pdb_type_e pdb_type;
2391 struct program *p = &prg;
2395 if (rta_sec_era != RTA_SEC_ERA_2 && era_2_sw_hfn_ovrd) {
2396 pr_err("Cannot select SW HFN override for other era than 2");
2400 if (sn_size != PDCP_SN_SIZE_12 && sn_size != PDCP_SN_SIZE_5) {
2401 pr_err("C-plane supports only 5-bit and 12-bit sequence numbers\n");
2405 PROGRAM_CNTXT_INIT(p, descbuf, 0);
2407 PROGRAM_SET_BSWAP(p);
2409 PROGRAM_SET_36BIT_ADDR(p);
2411 SHR_HDR(p, desc_share[cipherdata->algtype][authdata->algtype], 0, 0);
2413 pdb_type = cnstr_pdcp_c_plane_pdb(p,
2422 SET_LABEL(p, pdb_end);
2424 err = insert_hfn_ov_op(p, sn_size, pdb_type,
2429 err = pdcp_cp_fp[cipherdata->algtype][authdata->algtype](p,
2433 OP_TYPE_DECAP_PROTOCOL,
2439 PATCH_HDR(p, 0, pdb_end);
2441 return PROGRAM_FINALIZE(p);
2445 * cnstr_shdsc_pdcp_u_plane_encap - Function for creating a PDCP User Plane
2446 * encapsulation descriptor.
2447 * @descbuf: pointer to buffer for descriptor construction
2448 * @ps: if 36/40bit addressing is desired, this parameter must be true
2449 * @swap: must be true when core endianness doesn't match SEC endianness
2450 * @sn_size: selects Sequence Number Size: 7/12/15 bits
2451 * @hfn: starting Hyper Frame Number to be used together with the SN from the
2453 * @bearer: radio bearer ID
2454 * @direction: the direction of the PDCP frame (UL/DL)
2455 * @hfn_threshold: HFN value that once reached triggers a warning from SEC that
2456 * keys should be renegotiated at the earliest convenience.
2457 * @cipherdata: pointer to block cipher transform definitions
2458 * Valid algorithm values are those from cipher_type_pdcp enum.
2459 * @era_2_sw_hfn_ovrd: if software HFN override mechanism is desired for
2460 * this descriptor. Note: Can only be used for
2463 * Return: size of descriptor written in words or negative number on error.
2464 * Once the function returns, the value of this parameter can be used
2465 * for reclaiming the space that wasn't used for the descriptor.
2467 * Note: descbuf must be large enough to contain a full 256 byte long
2468 * descriptor; after the function returns, by subtracting the actual number of
2469 * bytes used, the user can reuse the remaining buffer space for other purposes.
2472 cnstr_shdsc_pdcp_u_plane_encap(uint32_t *descbuf,
2475 enum pdcp_sn_size sn_size,
2477 unsigned short bearer,
2478 unsigned short direction,
2479 uint32_t hfn_threshold,
2480 struct alginfo *cipherdata,
2481 unsigned char era_2_sw_hfn_ovrd)
2484 struct program *p = &prg;
2488 if (rta_sec_era != RTA_SEC_ERA_2 && era_2_sw_hfn_ovrd) {
2489 pr_err("Cannot select SW HFN ovrd for other era than 2");
2493 PROGRAM_CNTXT_INIT(p, descbuf, 0);
2495 PROGRAM_SET_BSWAP(p);
2497 PROGRAM_SET_36BIT_ADDR(p);
2499 SHR_HDR(p, SHR_ALWAYS, 0, 0);
2500 if (cnstr_pdcp_u_plane_pdb(p, sn_size, hfn, bearer, direction,
2502 pr_err("Error creating PDCP UPlane PDB\n");
2505 SET_LABEL(p, pdb_end);
2507 err = insert_hfn_ov_op(p, sn_size, PDCP_PDB_TYPE_FULL_PDB,
2513 case PDCP_SN_SIZE_7:
2514 case PDCP_SN_SIZE_12:
2515 switch (cipherdata->algtype) {
2516 case PDCP_CIPHER_TYPE_ZUC:
2517 if (rta_sec_era < RTA_SEC_ERA_5) {
2518 pr_err("Invalid era for selected algorithm\n");
2521 case PDCP_CIPHER_TYPE_AES:
2522 case PDCP_CIPHER_TYPE_SNOW:
2523 /* Insert Cipher Key */
2524 KEY(p, KEY1, cipherdata->key_enc_flags,
2525 (uint64_t)cipherdata->key, cipherdata->keylen,
2526 INLINE_KEY(cipherdata));
2527 PROTOCOL(p, OP_TYPE_ENCAP_PROTOCOL,
2528 OP_PCLID_LTE_PDCP_USER,
2529 (uint16_t)cipherdata->algtype);
2531 case PDCP_CIPHER_TYPE_NULL:
2532 insert_copy_frame_op(p,
2534 OP_TYPE_ENCAP_PROTOCOL);
2537 pr_err("%s: Invalid encrypt algorithm selected: %d\n",
2538 "cnstr_pcl_shdsc_pdcp_u_plane_decap",
2539 cipherdata->algtype);
2544 case PDCP_SN_SIZE_15:
2545 switch (cipherdata->algtype) {
2546 case PDCP_CIPHER_TYPE_NULL:
2547 insert_copy_frame_op(p,
2549 OP_TYPE_ENCAP_PROTOCOL);
2553 err = pdcp_insert_uplane_15bit_op(p, swap, cipherdata,
2554 OP_TYPE_ENCAP_PROTOCOL);
2561 case PDCP_SN_SIZE_5:
2563 pr_err("Invalid SN size selected\n");
2567 PATCH_HDR(p, 0, pdb_end);
2568 return PROGRAM_FINALIZE(p);
2572 * cnstr_shdsc_pdcp_u_plane_decap - Function for creating a PDCP User Plane
2573 * decapsulation descriptor.
2574 * @descbuf: pointer to buffer for descriptor construction
2575 * @ps: if 36/40bit addressing is desired, this parameter must be true
2576 * @swap: must be true when core endianness doesn't match SEC endianness
2577 * @sn_size: selects Sequence Number Size: 7/12/15 bits
2578 * @hfn: starting Hyper Frame Number to be used together with the SN from the
2580 * @bearer: radio bearer ID
2581 * @direction: the direction of the PDCP frame (UL/DL)
2582 * @hfn_threshold: HFN value that once reached triggers a warning from SEC that
2583 * keys should be renegotiated at the earliest convenience.
2584 * @cipherdata: pointer to block cipher transform definitions
2585 * Valid algorithm values are those from cipher_type_pdcp enum.
2586 * @era_2_sw_hfn_ovrd: if software HFN override mechanism is desired for
2587 * this descriptor. Note: Can only be used for
2590 * Return: size of descriptor written in words or negative number on error.
2591 * Once the function returns, the value of this parameter can be used
2592 * for reclaiming the space that wasn't used for the descriptor.
2594 * Note: descbuf must be large enough to contain a full 256 byte long
2595 * descriptor; after the function returns, by subtracting the actual number of
2596 * bytes used, the user can reuse the remaining buffer space for other purposes.
2599 cnstr_shdsc_pdcp_u_plane_decap(uint32_t *descbuf,
2602 enum pdcp_sn_size sn_size,
2604 unsigned short bearer,
2605 unsigned short direction,
2606 uint32_t hfn_threshold,
2607 struct alginfo *cipherdata,
2608 unsigned char era_2_sw_hfn_ovrd)
2611 struct program *p = &prg;
2615 if (rta_sec_era != RTA_SEC_ERA_2 && era_2_sw_hfn_ovrd) {
2616 pr_err("Cannot select SW HFN override for other era than 2");
2620 PROGRAM_CNTXT_INIT(p, descbuf, 0);
2622 PROGRAM_SET_BSWAP(p);
2624 PROGRAM_SET_36BIT_ADDR(p);
2626 SHR_HDR(p, SHR_ALWAYS, 0, 0);
2627 if (cnstr_pdcp_u_plane_pdb(p, sn_size, hfn, bearer, direction,
2629 pr_err("Error creating PDCP UPlane PDB\n");
2632 SET_LABEL(p, pdb_end);
2634 err = insert_hfn_ov_op(p, sn_size, PDCP_PDB_TYPE_FULL_PDB,
2640 case PDCP_SN_SIZE_7:
2641 case PDCP_SN_SIZE_12:
2642 switch (cipherdata->algtype) {
2643 case PDCP_CIPHER_TYPE_ZUC:
2644 if (rta_sec_era < RTA_SEC_ERA_5) {
2645 pr_err("Invalid era for selected algorithm\n");
2648 case PDCP_CIPHER_TYPE_AES:
2649 case PDCP_CIPHER_TYPE_SNOW:
2650 /* Insert Cipher Key */
2651 KEY(p, KEY1, cipherdata->key_enc_flags,
2652 cipherdata->key, cipherdata->keylen,
2653 INLINE_KEY(cipherdata));
2654 PROTOCOL(p, OP_TYPE_DECAP_PROTOCOL,
2655 OP_PCLID_LTE_PDCP_USER,
2656 (uint16_t)cipherdata->algtype);
2658 case PDCP_CIPHER_TYPE_NULL:
2659 insert_copy_frame_op(p,
2661 OP_TYPE_DECAP_PROTOCOL);
2664 pr_err("%s: Invalid encrypt algorithm selected: %d\n",
2665 "cnstr_pcl_shdsc_pdcp_u_plane_decap",
2666 cipherdata->algtype);
2671 case PDCP_SN_SIZE_15:
2672 switch (cipherdata->algtype) {
2673 case PDCP_CIPHER_TYPE_NULL:
2674 insert_copy_frame_op(p,
2676 OP_TYPE_DECAP_PROTOCOL);
2680 err = pdcp_insert_uplane_15bit_op(p, swap, cipherdata,
2681 OP_TYPE_DECAP_PROTOCOL);
2688 case PDCP_SN_SIZE_5:
2690 pr_err("Invalid SN size selected\n");
2694 PATCH_HDR(p, 0, pdb_end);
2695 return PROGRAM_FINALIZE(p);
2699 * cnstr_shdsc_pdcp_short_mac - Function for creating a PDCP Short MAC
2701 * @descbuf: pointer to buffer for descriptor construction
2702 * @ps: if 36/40bit addressing is desired, this parameter must be true
2703 * @swap: must be true when core endianness doesn't match SEC endianness
2704 * @authdata: pointer to authentication transform definitions
2705 * Valid algorithm values are those from auth_type_pdcp enum.
2707 * Return: size of descriptor written in words or negative number on error.
2708 * Once the function returns, the value of this parameter can be used
2709 * for reclaiming the space that wasn't used for the descriptor.
2711 * Note: descbuf must be large enough to contain a full 256 byte long
2712 * descriptor; after the function returns, by subtracting the actual number of
2713 * bytes used, the user can reuse the remaining buffer space for other purposes.
2716 cnstr_shdsc_pdcp_short_mac(uint32_t *descbuf,
2719 struct alginfo *authdata)
2722 struct program *p = &prg;
2723 uint32_t iv[3] = {0, 0, 0};
2724 LABEL(local_offset);
2725 REFERENCE(move_cmd_read_descbuf);
2726 REFERENCE(move_cmd_write_descbuf);
2728 PROGRAM_CNTXT_INIT(p, descbuf, 0);
2730 PROGRAM_SET_BSWAP(p);
2732 PROGRAM_SET_36BIT_ADDR(p);
2734 SHR_HDR(p, SHR_ALWAYS, 1, 0);
2736 if (rta_sec_era > RTA_SEC_ERA_2) {
2737 MATHB(p, SEQINSZ, SUB, ZERO, VSEQINSZ, 4, 0);
2738 MATHB(p, SEQINSZ, SUB, ZERO, MATH1, 4, 0);
2740 MATHB(p, SEQINSZ, ADD, ONE, MATH1, 4, 0);
2741 MATHB(p, MATH1, SUB, ONE, MATH1, 4, 0);
2742 MATHB(p, ZERO, ADD, MATH1, VSEQINSZ, 4, 0);
2743 MOVE(p, MATH1, 0, MATH0, 0, 8, IMMED);
2746 * Since MOVELEN is available only starting with
2747 * SEC ERA 3, use poor man's MOVELEN: create a MOVE
2748 * command dynamically by writing the length from M1 by
2749 * OR-ing the command in the M1 register and MOVE the
2750 * result into the descriptor buffer. Care must be taken
2751 * wrt. the location of the command because of SEC
2752 * pipelining. The actual MOVEs are written at the end
2753 * of the descriptor due to calculations needed on the
2754 * offset in the descriptor for the MOVE command.
2756 move_cmd_read_descbuf = MOVE(p, DESCBUF, 0, MATH0, 0, 6,
2758 move_cmd_write_descbuf = MOVE(p, MATH0, 0, DESCBUF, 0, 8,
2761 MATHB(p, ZERO, ADD, MATH1, VSEQOUTSZ, 4, 0);
2763 switch (authdata->algtype) {
2764 case PDCP_AUTH_TYPE_NULL:
2765 SEQFIFOSTORE(p, MSG, 0, 0, VLF);
2766 if (rta_sec_era > RTA_SEC_ERA_2) {
2767 MOVE(p, AB1, 0, OFIFO, 0, MATH1, 0);
2769 SET_LABEL(p, local_offset);
2771 /* Shut off automatic Info FIFO entries */
2772 LOAD(p, 0, DCTRL, LDOFF_DISABLE_AUTO_NFIFO, 0, IMMED);
2774 /* Placeholder for MOVE command with length from M1
2777 MOVE(p, IFIFOAB1, 0, OFIFO, 0, 0, IMMED);
2779 /* Enable automatic Info FIFO entries */
2780 LOAD(p, 0, DCTRL, LDOFF_ENABLE_AUTO_NFIFO, 0, IMMED);
2783 LOAD(p, (uintptr_t)iv, MATH0, 0, 8, IMMED | COPY);
2784 SEQFIFOLOAD(p, MSG1, 0, VLF | LAST1 | LAST2 | FLUSH1);
2785 SEQSTORE(p, MATH0, 0, 4, 0);
2789 case PDCP_AUTH_TYPE_SNOW:
2791 iv[1] = swap ? swab32(0x04000000) : 0x04000000;
2792 iv[2] = swap ? swab32(0xF8000000) : 0xF8000000;
2794 KEY(p, KEY2, authdata->key_enc_flags, authdata->key,
2795 authdata->keylen, INLINE_KEY(authdata));
2796 LOAD(p, (uintptr_t)&iv, CONTEXT2, 0, 12, IMMED | COPY);
2797 ALG_OPERATION(p, OP_ALG_ALGSEL_SNOW_F9,
2799 OP_ALG_AS_INITFINAL,
2802 SEQFIFOSTORE(p, MSG, 0, 0, VLF);
2804 if (rta_sec_era > RTA_SEC_ERA_2) {
2805 MOVE(p, AB1, 0, OFIFO, 0, MATH1, 0);
2807 SET_LABEL(p, local_offset);
2810 /* Shut off automatic Info FIFO entries */
2811 LOAD(p, 0, DCTRL, LDOFF_DISABLE_AUTO_NFIFO, 0, IMMED);
2813 /* Placeholder for MOVE command with length from M1
2816 MOVE(p, IFIFOAB1, 0, OFIFO, 0, 0, IMMED);
2818 /* Enable automatic Info FIFO entries */
2819 LOAD(p, 0, DCTRL, LDOFF_ENABLE_AUTO_NFIFO, 0, IMMED);
2821 SEQFIFOLOAD(p, MSGINSNOOP, 0, VLF | LAST1 | LAST2 | FLUSH1);
2822 SEQSTORE(p, CONTEXT2, 0, 4, 0);
2826 case PDCP_AUTH_TYPE_AES:
2828 iv[1] = swap ? swab32(0xFC000000) : 0xFC000000;
2829 iv[2] = 0x00000000; /* unused */
2831 KEY(p, KEY1, authdata->key_enc_flags, authdata->key,
2832 authdata->keylen, INLINE_KEY(authdata));
2833 LOAD(p, (uintptr_t)&iv, MATH0, 0, 8, IMMED | COPY);
2834 MOVE(p, MATH0, 0, IFIFOAB1, 0, 8, IMMED);
2835 ALG_OPERATION(p, OP_ALG_ALGSEL_AES,
2837 OP_ALG_AS_INITFINAL,
2840 SEQFIFOSTORE(p, MSG, 0, 0, VLF);
2842 if (rta_sec_era > RTA_SEC_ERA_2) {
2843 MOVE(p, AB2, 0, OFIFO, 0, MATH1, 0);
2845 SET_LABEL(p, local_offset);
2847 /* Shut off automatic Info FIFO entries */
2848 LOAD(p, 0, DCTRL, LDOFF_DISABLE_AUTO_NFIFO, 0, IMMED);
2850 /* Placeholder for MOVE command with length from M1
2853 MOVE(p, IFIFOAB2, 0, OFIFO, 0, 0, IMMED);
2855 /* Enable automatic Info FIFO entries */
2856 LOAD(p, 0, DCTRL, LDOFF_ENABLE_AUTO_NFIFO, 0, IMMED);
2858 SEQFIFOLOAD(p, MSGINSNOOP, 0, VLF | LAST1 | LAST2 | FLUSH1);
2859 SEQSTORE(p, CONTEXT1, 0, 4, 0);
2863 case PDCP_AUTH_TYPE_ZUC:
2864 if (rta_sec_era < RTA_SEC_ERA_5) {
2865 pr_err("Invalid era for selected algorithm\n");
2869 iv[1] = swap ? swab32(0xFC000000) : 0xFC000000;
2870 iv[2] = 0x00000000; /* unused */
2872 KEY(p, KEY2, authdata->key_enc_flags, authdata->key,
2873 authdata->keylen, INLINE_KEY(authdata));
2874 LOAD(p, (uintptr_t)&iv, CONTEXT2, 0, 12, IMMED | COPY);
2875 ALG_OPERATION(p, OP_ALG_ALGSEL_ZUCA,
2877 OP_ALG_AS_INITFINAL,
2880 SEQFIFOSTORE(p, MSG, 0, 0, VLF);
2881 MOVE(p, AB1, 0, OFIFO, 0, MATH1, 0);
2882 SEQFIFOLOAD(p, MSGINSNOOP, 0, VLF | LAST1 | LAST2 | FLUSH1);
2883 SEQSTORE(p, CONTEXT2, 0, 4, 0);
2888 pr_err("%s: Invalid integrity algorithm selected: %d\n",
2889 "cnstr_shdsc_pdcp_short_mac", authdata->algtype);
2894 if (rta_sec_era < RTA_SEC_ERA_3) {
2895 PATCH_MOVE(p, move_cmd_read_descbuf, local_offset);
2896 PATCH_MOVE(p, move_cmd_write_descbuf, local_offset);
2899 return PROGRAM_FINALIZE(p);
2902 #endif /* __DESC_PDCP_H__ */