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,
1804 struct alginfo *authdata,
1809 /* Insert auth key if requested */
1810 if (authdata && authdata->algtype)
1811 KEY(p, KEY2, authdata->key_enc_flags, authdata->key,
1812 authdata->keylen, INLINE_KEY(authdata));
1814 /* Insert Cipher Key */
1815 KEY(p, KEY1, cipherdata->key_enc_flags, cipherdata->key,
1816 cipherdata->keylen, INLINE_KEY(cipherdata));
1818 if (rta_sec_era >= RTA_SEC_ERA_8) {
1819 PROTOCOL(p, dir, OP_PCLID_LTE_PDCP_USER,
1820 (uint16_t)cipherdata->algtype);
1824 SEQLOAD(p, MATH0, 6, 2, 0);
1825 JUMP(p, 1, LOCAL_JUMP, ALL_TRUE, CALM);
1827 MATHB(p, MATH0, AND, PDCP_U_PLANE_15BIT_SN_MASK, MATH1, 8,
1830 MATHB(p, MATH0, AND, PDCP_U_PLANE_15BIT_SN_MASK_BE, MATH1, 8,
1832 SEQSTORE(p, MATH0, 6, 2, 0);
1833 MATHB(p, MATH1, SHLD, MATH1, MATH1, 8, 0);
1834 MOVEB(p, DESCBUF, 8, MATH2, 0, 8, WAITCOMP | IMMED);
1835 MATHB(p, MATH1, OR, MATH2, MATH2, 8, 0);
1837 MATHB(p, SEQINSZ, SUB, MATH3, VSEQINSZ, 4, 0);
1838 MATHB(p, SEQINSZ, SUB, MATH3, VSEQOUTSZ, 4, 0);
1840 SEQFIFOSTORE(p, MSG, 0, 0, VLF);
1842 op = dir == OP_TYPE_ENCAP_PROTOCOL ? DIR_ENC : DIR_DEC;
1843 switch (cipherdata->algtype) {
1844 case PDCP_CIPHER_TYPE_SNOW:
1845 MOVEB(p, MATH2, 0, CONTEXT1, 0, 8, WAITCOMP | IMMED);
1846 ALG_OPERATION(p, OP_ALG_ALGSEL_SNOW_F8,
1848 OP_ALG_AS_INITFINAL,
1853 case PDCP_CIPHER_TYPE_AES:
1854 MOVEB(p, MATH2, 0, CONTEXT1, 0x10, 0x10, WAITCOMP | IMMED);
1855 ALG_OPERATION(p, OP_ALG_ALGSEL_AES,
1857 OP_ALG_AS_INITFINAL,
1862 case PDCP_CIPHER_TYPE_ZUC:
1863 if (rta_sec_era < RTA_SEC_ERA_5) {
1864 pr_err("Invalid era for selected algorithm\n");
1867 MOVEB(p, MATH2, 0, CONTEXT1, 0, 0x08, IMMED);
1868 MOVEB(p, MATH2, 0, CONTEXT1, 0x08, 0x08, WAITCOMP | IMMED);
1870 ALG_OPERATION(p, OP_ALG_ALGSEL_ZUCE,
1872 OP_ALG_AS_INITFINAL,
1878 pr_err("%s: Invalid encrypt algorithm selected: %d\n",
1879 "pdcp_insert_uplane_15bit_op", cipherdata->algtype);
1883 SEQFIFOLOAD(p, MSG1, 0, VLF | LAST1 | FLUSH1);
1889 * Function for inserting the snippet of code responsible for creating
1890 * the HFN override code via either DPOVRD or via the input frame.
1893 insert_hfn_ov_op(struct program *p,
1895 enum pdb_type_e pdb_type,
1896 unsigned char era_2_sw_hfn_ovrd)
1898 uint32_t imm = PDCP_DPOVRD_HFN_OV_EN;
1899 uint16_t hfn_pdb_offset;
1901 if (rta_sec_era == RTA_SEC_ERA_2 && !era_2_sw_hfn_ovrd)
1905 case PDCP_PDB_TYPE_NO_PDB:
1907 * If there is no PDB, then HFN override mechanism does not
1908 * make any sense, thus in this case the function will
1909 * return the pointer to the current position in the
1914 case PDCP_PDB_TYPE_REDUCED_PDB:
1918 case PDCP_PDB_TYPE_FULL_PDB:
1926 if (rta_sec_era > RTA_SEC_ERA_2) {
1927 MATHB(p, DPOVRD, AND, imm, NONE, 8, IFB | IMMED2);
1929 SEQLOAD(p, MATH0, 4, 4, 0);
1930 JUMP(p, 1, LOCAL_JUMP, ALL_TRUE, CALM);
1931 MATHB(p, MATH0, AND, imm, NONE, 8, IFB | IMMED2);
1932 SEQSTORE(p, MATH0, 4, 4, 0);
1935 if (rta_sec_era >= RTA_SEC_ERA_8)
1936 JUMP(p, 6, LOCAL_JUMP, ALL_TRUE, MATH_Z);
1938 JUMP(p, 5, LOCAL_JUMP, ALL_TRUE, MATH_Z);
1940 if (rta_sec_era > RTA_SEC_ERA_2)
1941 MATHB(p, DPOVRD, LSHIFT, shift, MATH0, 4, IMMED2);
1943 MATHB(p, MATH0, LSHIFT, shift, MATH0, 4, IMMED2);
1945 MATHB(p, MATH0, SHLD, MATH0, MATH0, 8, 0);
1946 MOVE(p, MATH0, 0, DESCBUF, hfn_pdb_offset, 4, IMMED);
1948 if (rta_sec_era >= RTA_SEC_ERA_8)
1950 * For ERA8, DPOVRD could be handled by the PROTOCOL command
1951 * itself. For now, this is not done. Thus, clear DPOVRD here
1952 * to alleviate any side-effects.
1954 MATHB(p, DPOVRD, AND, ZERO, DPOVRD, 4, STL);
1960 * PDCP Control PDB creation function
1962 static inline enum pdb_type_e
1963 cnstr_pdcp_c_plane_pdb(struct program *p,
1965 enum pdcp_sn_size sn_size,
1966 unsigned char bearer,
1967 unsigned char direction,
1968 uint32_t hfn_threshold,
1969 struct alginfo *cipherdata,
1970 struct alginfo *authdata)
1972 struct pdcp_pdb pdb;
1974 pdb_mask[PDCP_CIPHER_TYPE_INVALID][PDCP_AUTH_TYPE_INVALID] = {
1976 PDCP_PDB_TYPE_NO_PDB, /* NULL */
1977 PDCP_PDB_TYPE_FULL_PDB, /* SNOW f9 */
1978 PDCP_PDB_TYPE_FULL_PDB, /* AES CMAC */
1979 PDCP_PDB_TYPE_FULL_PDB /* ZUC-I */
1982 PDCP_PDB_TYPE_FULL_PDB, /* NULL */
1983 PDCP_PDB_TYPE_FULL_PDB, /* SNOW f9 */
1984 PDCP_PDB_TYPE_REDUCED_PDB, /* AES CMAC */
1985 PDCP_PDB_TYPE_REDUCED_PDB /* ZUC-I */
1988 PDCP_PDB_TYPE_FULL_PDB, /* NULL */
1989 PDCP_PDB_TYPE_REDUCED_PDB, /* SNOW f9 */
1990 PDCP_PDB_TYPE_FULL_PDB, /* AES CMAC */
1991 PDCP_PDB_TYPE_REDUCED_PDB /* ZUC-I */
1994 PDCP_PDB_TYPE_FULL_PDB, /* NULL */
1995 PDCP_PDB_TYPE_REDUCED_PDB, /* SNOW f9 */
1996 PDCP_PDB_TYPE_REDUCED_PDB, /* AES CMAC */
1997 PDCP_PDB_TYPE_FULL_PDB /* ZUC-I */
2001 if (rta_sec_era >= RTA_SEC_ERA_8) {
2002 memset(&pdb, 0x00, sizeof(struct pdcp_pdb));
2004 /* To support 12-bit seq numbers, we use u-plane opt in pdb.
2005 * SEC supports 5-bit only with c-plane opt in pdb.
2007 if (sn_size == PDCP_SN_SIZE_12) {
2008 pdb.hfn_res = hfn << PDCP_U_PLANE_PDB_LONG_SN_HFN_SHIFT;
2009 pdb.bearer_dir_res = (uint32_t)
2010 ((bearer << PDCP_U_PLANE_PDB_BEARER_SHIFT) |
2011 (direction << PDCP_U_PLANE_PDB_DIR_SHIFT));
2014 hfn_threshold << PDCP_U_PLANE_PDB_LONG_SN_HFN_THR_SHIFT;
2017 /* This means 5-bit c-plane.
2018 * Here we use c-plane opt in pdb
2021 /* This is a HW issue. Bit 2 should be set to zero,
2022 * but it does not work this way. Override here.
2024 pdb.opt_res.rsvd = 0x00000002;
2026 /* Copy relevant information from user to PDB */
2027 pdb.hfn_res = hfn << PDCP_C_PLANE_PDB_HFN_SHIFT;
2028 pdb.bearer_dir_res = (uint32_t)
2029 ((bearer << PDCP_C_PLANE_PDB_BEARER_SHIFT) |
2030 (direction << PDCP_C_PLANE_PDB_DIR_SHIFT));
2032 hfn_threshold << PDCP_C_PLANE_PDB_HFN_THR_SHIFT;
2035 /* copy PDB in descriptor*/
2036 __rta_out32(p, pdb.opt_res.opt);
2037 __rta_out32(p, pdb.hfn_res);
2038 __rta_out32(p, pdb.bearer_dir_res);
2039 __rta_out32(p, pdb.hfn_thr_res);
2041 return PDCP_PDB_TYPE_FULL_PDB;
2044 switch (pdb_mask[cipherdata->algtype][authdata->algtype]) {
2045 case PDCP_PDB_TYPE_NO_PDB:
2048 case PDCP_PDB_TYPE_REDUCED_PDB:
2049 __rta_out32(p, (hfn << PDCP_C_PLANE_PDB_HFN_SHIFT));
2051 (uint32_t)((bearer <<
2052 PDCP_C_PLANE_PDB_BEARER_SHIFT) |
2054 PDCP_C_PLANE_PDB_DIR_SHIFT)));
2057 case PDCP_PDB_TYPE_FULL_PDB:
2058 memset(&pdb, 0x00, sizeof(struct pdcp_pdb));
2060 /* This is a HW issue. Bit 2 should be set to zero,
2061 * but it does not work this way. Override here.
2063 pdb.opt_res.rsvd = 0x00000002;
2065 /* Copy relevant information from user to PDB */
2066 pdb.hfn_res = hfn << PDCP_C_PLANE_PDB_HFN_SHIFT;
2067 pdb.bearer_dir_res = (uint32_t)
2068 ((bearer << PDCP_C_PLANE_PDB_BEARER_SHIFT) |
2069 (direction << PDCP_C_PLANE_PDB_DIR_SHIFT));
2071 hfn_threshold << PDCP_C_PLANE_PDB_HFN_THR_SHIFT;
2073 /* copy PDB in descriptor*/
2074 __rta_out32(p, pdb.opt_res.opt);
2075 __rta_out32(p, pdb.hfn_res);
2076 __rta_out32(p, pdb.bearer_dir_res);
2077 __rta_out32(p, pdb.hfn_thr_res);
2082 return PDCP_PDB_TYPE_INVALID;
2085 return pdb_mask[cipherdata->algtype][authdata->algtype];
2089 * PDCP UPlane PDB creation function
2092 cnstr_pdcp_u_plane_pdb(struct program *p,
2093 enum pdcp_sn_size sn_size,
2094 uint32_t hfn, unsigned short bearer,
2095 unsigned short direction,
2096 uint32_t hfn_threshold)
2098 struct pdcp_pdb pdb;
2099 /* Read options from user */
2100 /* Depending on sequence number length, the HFN and HFN threshold
2101 * have different lengths.
2103 memset(&pdb, 0x00, sizeof(struct pdcp_pdb));
2106 case PDCP_SN_SIZE_7:
2107 pdb.opt_res.opt |= PDCP_U_PLANE_PDB_OPT_SHORT_SN;
2108 pdb.hfn_res = hfn << PDCP_U_PLANE_PDB_SHORT_SN_HFN_SHIFT;
2110 hfn_threshold<<PDCP_U_PLANE_PDB_SHORT_SN_HFN_THR_SHIFT;
2113 case PDCP_SN_SIZE_12:
2114 pdb.opt_res.opt &= (uint32_t)(~PDCP_U_PLANE_PDB_OPT_SHORT_SN);
2115 pdb.hfn_res = hfn << PDCP_U_PLANE_PDB_LONG_SN_HFN_SHIFT;
2117 hfn_threshold<<PDCP_U_PLANE_PDB_LONG_SN_HFN_THR_SHIFT;
2120 case PDCP_SN_SIZE_15:
2121 pdb.opt_res.opt = (uint32_t)(PDCP_U_PLANE_PDB_OPT_15B_SN);
2122 pdb.hfn_res = hfn << PDCP_U_PLANE_PDB_15BIT_SN_HFN_SHIFT;
2124 hfn_threshold<<PDCP_U_PLANE_PDB_15BIT_SN_HFN_THR_SHIFT;
2128 pr_err("Invalid Sequence Number Size setting in PDB\n");
2132 pdb.bearer_dir_res = (uint32_t)
2133 ((bearer << PDCP_U_PLANE_PDB_BEARER_SHIFT) |
2134 (direction << PDCP_U_PLANE_PDB_DIR_SHIFT));
2136 /* copy PDB in descriptor*/
2137 __rta_out32(p, pdb.opt_res.opt);
2138 __rta_out32(p, pdb.hfn_res);
2139 __rta_out32(p, pdb.bearer_dir_res);
2140 __rta_out32(p, pdb.hfn_thr_res);
2145 * cnstr_shdsc_pdcp_c_plane_encap - Function for creating a PDCP Control Plane
2146 * encapsulation descriptor.
2147 * @descbuf: pointer to buffer for descriptor construction
2148 * @ps: if 36/40bit addressing is desired, this parameter must be true
2149 * @swap: must be true when core endianness doesn't match SEC endianness
2150 * @hfn: starting Hyper Frame Number to be used together with the SN from the
2152 * @sn_size: size of sequence numbers, only 5/12 bit sequence numbers are valid
2153 * @bearer: radio bearer ID
2154 * @direction: the direction of the PDCP frame (UL/DL)
2155 * @hfn_threshold: HFN value that once reached triggers a warning from SEC that
2156 * keys should be renegotiated at the earliest convenience.
2157 * @cipherdata: pointer to block cipher transform definitions
2158 * Valid algorithm values are those from cipher_type_pdcp enum.
2159 * @authdata: pointer to authentication transform definitions
2160 * Valid algorithm values are those from auth_type_pdcp enum.
2161 * @era_2_sw_hfn_ovrd: if software HFN override mechanism is desired for
2162 * this descriptor. Note: Can only be used for
2164 * Return: size of descriptor written in words or negative number on error.
2165 * Once the function returns, the value of this parameter can be used
2166 * for reclaiming the space that wasn't used for the descriptor.
2168 * Note: descbuf must be large enough to contain a full 256 byte long
2169 * descriptor; after the function returns, by subtracting the actual number of
2170 * bytes used, the user can reuse the remaining buffer space for other purposes.
2173 cnstr_shdsc_pdcp_c_plane_encap(uint32_t *descbuf,
2177 enum pdcp_sn_size sn_size,
2178 unsigned char bearer,
2179 unsigned char direction,
2180 uint32_t hfn_threshold,
2181 struct alginfo *cipherdata,
2182 struct alginfo *authdata,
2183 unsigned char era_2_sw_hfn_ovrd)
2186 (*pdcp_cp_fp[PDCP_CIPHER_TYPE_INVALID][PDCP_AUTH_TYPE_INVALID])
2187 (struct program*, bool swap, struct alginfo *,
2188 struct alginfo *, unsigned int, enum pdcp_sn_size,
2189 unsigned char __maybe_unused) = {
2191 pdcp_insert_cplane_null_op, /* NULL */
2192 pdcp_insert_cplane_int_only_op, /* SNOW f9 */
2193 pdcp_insert_cplane_int_only_op, /* AES CMAC */
2194 pdcp_insert_cplane_int_only_op /* ZUC-I */
2197 pdcp_insert_cplane_enc_only_op, /* NULL */
2198 pdcp_insert_cplane_acc_op, /* SNOW f9 */
2199 pdcp_insert_cplane_snow_aes_op, /* AES CMAC */
2200 pdcp_insert_cplane_snow_zuc_op /* ZUC-I */
2203 pdcp_insert_cplane_enc_only_op, /* NULL */
2204 pdcp_insert_cplane_aes_snow_op, /* SNOW f9 */
2205 pdcp_insert_cplane_acc_op, /* AES CMAC */
2206 pdcp_insert_cplane_aes_zuc_op /* ZUC-I */
2209 pdcp_insert_cplane_enc_only_op, /* NULL */
2210 pdcp_insert_cplane_zuc_snow_op, /* SNOW f9 */
2211 pdcp_insert_cplane_zuc_aes_op, /* AES CMAC */
2212 pdcp_insert_cplane_acc_op /* ZUC-I */
2215 static enum rta_share_type
2216 desc_share[PDCP_CIPHER_TYPE_INVALID][PDCP_AUTH_TYPE_INVALID] = {
2218 SHR_WAIT, /* NULL */
2219 SHR_ALWAYS, /* SNOW f9 */
2220 SHR_ALWAYS, /* AES CMAC */
2221 SHR_ALWAYS /* ZUC-I */
2224 SHR_ALWAYS, /* NULL */
2225 SHR_ALWAYS, /* SNOW f9 */
2226 SHR_WAIT, /* AES CMAC */
2227 SHR_WAIT /* ZUC-I */
2230 SHR_ALWAYS, /* NULL */
2231 SHR_ALWAYS, /* SNOW f9 */
2232 SHR_ALWAYS, /* AES CMAC */
2233 SHR_WAIT /* ZUC-I */
2236 SHR_ALWAYS, /* NULL */
2237 SHR_WAIT, /* SNOW f9 */
2238 SHR_WAIT, /* AES CMAC */
2239 SHR_ALWAYS /* ZUC-I */
2242 enum pdb_type_e pdb_type;
2244 struct program *p = &prg;
2248 if (rta_sec_era != RTA_SEC_ERA_2 && era_2_sw_hfn_ovrd) {
2249 pr_err("Cannot select SW HFN override for other era than 2");
2253 if (sn_size != PDCP_SN_SIZE_12 && sn_size != PDCP_SN_SIZE_5) {
2254 pr_err("C-plane supports only 5-bit and 12-bit sequence numbers\n");
2258 PROGRAM_CNTXT_INIT(p, descbuf, 0);
2260 PROGRAM_SET_BSWAP(p);
2262 PROGRAM_SET_36BIT_ADDR(p);
2264 SHR_HDR(p, desc_share[cipherdata->algtype][authdata->algtype], 0, 0);
2266 pdb_type = cnstr_pdcp_c_plane_pdb(p,
2275 SET_LABEL(p, pdb_end);
2277 err = insert_hfn_ov_op(p, sn_size, pdb_type,
2282 err = pdcp_cp_fp[cipherdata->algtype][authdata->algtype](p,
2286 OP_TYPE_ENCAP_PROTOCOL,
2292 PATCH_HDR(p, 0, pdb_end);
2294 return PROGRAM_FINALIZE(p);
2298 * cnstr_shdsc_pdcp_c_plane_decap - Function for creating a PDCP Control Plane
2299 * decapsulation descriptor.
2300 * @descbuf: pointer to buffer for descriptor construction
2301 * @ps: if 36/40bit addressing is desired, this parameter must be true
2302 * @swap: must be true when core endianness doesn't match SEC endianness
2303 * @hfn: starting Hyper Frame Number to be used together with the SN from the
2305 * @sn_size: size of sequence numbers, only 5/12 bit sequence numbers are valid
2306 * @bearer: radio bearer ID
2307 * @direction: the direction of the PDCP frame (UL/DL)
2308 * @hfn_threshold: HFN value that once reached triggers a warning from SEC that
2309 * keys should be renegotiated at the earliest convenience.
2310 * @cipherdata: pointer to block cipher transform definitions
2311 * Valid algorithm values are those from cipher_type_pdcp enum.
2312 * @authdata: pointer to authentication transform definitions
2313 * Valid algorithm values are those from auth_type_pdcp enum.
2314 * @era_2_sw_hfn_ovrd: if software HFN override mechanism is desired for
2315 * this descriptor. Note: Can only be used for
2318 * Return: size of descriptor written in words or negative number on error.
2319 * Once the function returns, the value of this parameter can be used
2320 * for reclaiming the space that wasn't used for the descriptor.
2322 * Note: descbuf must be large enough to contain a full 256 byte long
2323 * descriptor; after the function returns, by subtracting the actual number of
2324 * bytes used, the user can reuse the remaining buffer space for other purposes.
2327 cnstr_shdsc_pdcp_c_plane_decap(uint32_t *descbuf,
2331 enum pdcp_sn_size sn_size,
2332 unsigned char bearer,
2333 unsigned char direction,
2334 uint32_t hfn_threshold,
2335 struct alginfo *cipherdata,
2336 struct alginfo *authdata,
2337 unsigned char era_2_sw_hfn_ovrd)
2340 (*pdcp_cp_fp[PDCP_CIPHER_TYPE_INVALID][PDCP_AUTH_TYPE_INVALID])
2341 (struct program*, bool swap, struct alginfo *,
2342 struct alginfo *, unsigned int, enum pdcp_sn_size,
2345 pdcp_insert_cplane_null_op, /* NULL */
2346 pdcp_insert_cplane_int_only_op, /* SNOW f9 */
2347 pdcp_insert_cplane_int_only_op, /* AES CMAC */
2348 pdcp_insert_cplane_int_only_op /* ZUC-I */
2351 pdcp_insert_cplane_enc_only_op, /* NULL */
2352 pdcp_insert_cplane_acc_op, /* SNOW f9 */
2353 pdcp_insert_cplane_snow_aes_op, /* AES CMAC */
2354 pdcp_insert_cplane_snow_zuc_op /* ZUC-I */
2357 pdcp_insert_cplane_enc_only_op, /* NULL */
2358 pdcp_insert_cplane_aes_snow_op, /* SNOW f9 */
2359 pdcp_insert_cplane_acc_op, /* AES CMAC */
2360 pdcp_insert_cplane_aes_zuc_op /* ZUC-I */
2363 pdcp_insert_cplane_enc_only_op, /* NULL */
2364 pdcp_insert_cplane_zuc_snow_op, /* SNOW f9 */
2365 pdcp_insert_cplane_zuc_aes_op, /* AES CMAC */
2366 pdcp_insert_cplane_acc_op /* ZUC-I */
2369 static enum rta_share_type
2370 desc_share[PDCP_CIPHER_TYPE_INVALID][PDCP_AUTH_TYPE_INVALID] = {
2372 SHR_WAIT, /* NULL */
2373 SHR_ALWAYS, /* SNOW f9 */
2374 SHR_ALWAYS, /* AES CMAC */
2375 SHR_ALWAYS /* ZUC-I */
2378 SHR_ALWAYS, /* NULL */
2379 SHR_ALWAYS, /* SNOW f9 */
2380 SHR_WAIT, /* AES CMAC */
2381 SHR_WAIT /* ZUC-I */
2384 SHR_ALWAYS, /* NULL */
2385 SHR_ALWAYS, /* SNOW f9 */
2386 SHR_ALWAYS, /* AES CMAC */
2387 SHR_WAIT /* ZUC-I */
2390 SHR_ALWAYS, /* NULL */
2391 SHR_WAIT, /* SNOW f9 */
2392 SHR_WAIT, /* AES CMAC */
2393 SHR_ALWAYS /* ZUC-I */
2396 enum pdb_type_e pdb_type;
2398 struct program *p = &prg;
2402 if (rta_sec_era != RTA_SEC_ERA_2 && era_2_sw_hfn_ovrd) {
2403 pr_err("Cannot select SW HFN override for other era than 2");
2407 if (sn_size != PDCP_SN_SIZE_12 && sn_size != PDCP_SN_SIZE_5) {
2408 pr_err("C-plane supports only 5-bit and 12-bit sequence numbers\n");
2412 PROGRAM_CNTXT_INIT(p, descbuf, 0);
2414 PROGRAM_SET_BSWAP(p);
2416 PROGRAM_SET_36BIT_ADDR(p);
2418 SHR_HDR(p, desc_share[cipherdata->algtype][authdata->algtype], 0, 0);
2420 pdb_type = cnstr_pdcp_c_plane_pdb(p,
2429 SET_LABEL(p, pdb_end);
2431 err = insert_hfn_ov_op(p, sn_size, pdb_type,
2436 err = pdcp_cp_fp[cipherdata->algtype][authdata->algtype](p,
2440 OP_TYPE_DECAP_PROTOCOL,
2446 PATCH_HDR(p, 0, pdb_end);
2448 return PROGRAM_FINALIZE(p);
2452 * cnstr_shdsc_pdcp_u_plane_encap - Function for creating a PDCP User Plane
2453 * encapsulation descriptor.
2454 * @descbuf: pointer to buffer for descriptor construction
2455 * @ps: if 36/40bit addressing is desired, this parameter must be true
2456 * @swap: must be true when core endianness doesn't match SEC endianness
2457 * @sn_size: selects Sequence Number Size: 7/12/15 bits
2458 * @hfn: starting Hyper Frame Number to be used together with the SN from the
2460 * @bearer: radio bearer ID
2461 * @direction: the direction of the PDCP frame (UL/DL)
2462 * @hfn_threshold: HFN value that once reached triggers a warning from SEC that
2463 * keys should be renegotiated at the earliest convenience.
2464 * @cipherdata: pointer to block cipher transform definitions
2465 * Valid algorithm values are those from cipher_type_pdcp enum.
2466 * @era_2_sw_hfn_ovrd: if software HFN override mechanism is desired for
2467 * this descriptor. Note: Can only be used for
2470 * Return: size of descriptor written in words or negative number on error.
2471 * Once the function returns, the value of this parameter can be used
2472 * for reclaiming the space that wasn't used for the descriptor.
2474 * Note: descbuf must be large enough to contain a full 256 byte long
2475 * descriptor; after the function returns, by subtracting the actual number of
2476 * bytes used, the user can reuse the remaining buffer space for other purposes.
2479 cnstr_shdsc_pdcp_u_plane_encap(uint32_t *descbuf,
2482 enum pdcp_sn_size sn_size,
2484 unsigned short bearer,
2485 unsigned short direction,
2486 uint32_t hfn_threshold,
2487 struct alginfo *cipherdata,
2488 struct alginfo *authdata,
2489 unsigned char era_2_sw_hfn_ovrd)
2492 struct program *p = &prg;
2496 if (rta_sec_era != RTA_SEC_ERA_2 && era_2_sw_hfn_ovrd) {
2497 pr_err("Cannot select SW HFN ovrd for other era than 2");
2501 if (authdata && !authdata->algtype && rta_sec_era < RTA_SEC_ERA_8) {
2502 pr_err("Cannot use u-plane auth with era < 8");
2506 PROGRAM_CNTXT_INIT(p, descbuf, 0);
2508 PROGRAM_SET_BSWAP(p);
2510 PROGRAM_SET_36BIT_ADDR(p);
2512 SHR_HDR(p, SHR_ALWAYS, 0, 0);
2513 if (cnstr_pdcp_u_plane_pdb(p, sn_size, hfn, bearer, direction,
2515 pr_err("Error creating PDCP UPlane PDB\n");
2518 SET_LABEL(p, pdb_end);
2520 err = insert_hfn_ov_op(p, sn_size, PDCP_PDB_TYPE_FULL_PDB,
2525 /* Insert auth key if requested */
2526 if (authdata && authdata->algtype) {
2527 KEY(p, KEY2, authdata->key_enc_flags,
2528 (uint64_t)authdata->key, authdata->keylen,
2529 INLINE_KEY(authdata));
2533 case PDCP_SN_SIZE_7:
2534 case PDCP_SN_SIZE_12:
2535 switch (cipherdata->algtype) {
2536 case PDCP_CIPHER_TYPE_ZUC:
2537 if (rta_sec_era < RTA_SEC_ERA_5) {
2538 pr_err("Invalid era for selected algorithm\n");
2542 case PDCP_CIPHER_TYPE_AES:
2543 case PDCP_CIPHER_TYPE_SNOW:
2544 case PDCP_CIPHER_TYPE_NULL:
2545 /* Insert Cipher Key */
2546 KEY(p, KEY1, cipherdata->key_enc_flags,
2547 (uint64_t)cipherdata->key, cipherdata->keylen,
2548 INLINE_KEY(cipherdata));
2551 PROTOCOL(p, OP_TYPE_ENCAP_PROTOCOL,
2552 OP_PCLID_LTE_PDCP_USER_RN,
2553 ((uint16_t)cipherdata->algtype << 8) |
2554 (uint16_t)authdata->algtype);
2556 PROTOCOL(p, OP_TYPE_ENCAP_PROTOCOL,
2557 OP_PCLID_LTE_PDCP_USER,
2558 (uint16_t)cipherdata->algtype);
2561 pr_err("%s: Invalid encrypt algorithm selected: %d\n",
2562 "cnstr_pcl_shdsc_pdcp_u_plane_decap",
2563 cipherdata->algtype);
2568 case PDCP_SN_SIZE_15:
2569 switch (cipherdata->algtype) {
2570 case PDCP_CIPHER_TYPE_NULL:
2571 insert_copy_frame_op(p,
2573 OP_TYPE_ENCAP_PROTOCOL);
2577 err = pdcp_insert_uplane_15bit_op(p, swap, cipherdata,
2578 authdata, OP_TYPE_ENCAP_PROTOCOL);
2585 case PDCP_SN_SIZE_5:
2587 pr_err("Invalid SN size selected\n");
2591 PATCH_HDR(p, 0, pdb_end);
2592 return PROGRAM_FINALIZE(p);
2596 * cnstr_shdsc_pdcp_u_plane_decap - Function for creating a PDCP User Plane
2597 * decapsulation descriptor.
2598 * @descbuf: pointer to buffer for descriptor construction
2599 * @ps: if 36/40bit addressing is desired, this parameter must be true
2600 * @swap: must be true when core endianness doesn't match SEC endianness
2601 * @sn_size: selects Sequence Number Size: 7/12/15 bits
2602 * @hfn: starting Hyper Frame Number to be used together with the SN from the
2604 * @bearer: radio bearer ID
2605 * @direction: the direction of the PDCP frame (UL/DL)
2606 * @hfn_threshold: HFN value that once reached triggers a warning from SEC that
2607 * keys should be renegotiated at the earliest convenience.
2608 * @cipherdata: pointer to block cipher transform definitions
2609 * Valid algorithm values are those from cipher_type_pdcp enum.
2610 * @era_2_sw_hfn_ovrd: if software HFN override mechanism is desired for
2611 * this descriptor. Note: Can only be used for
2614 * Return: size of descriptor written in words or negative number on error.
2615 * Once the function returns, the value of this parameter can be used
2616 * for reclaiming the space that wasn't used for the descriptor.
2618 * Note: descbuf must be large enough to contain a full 256 byte long
2619 * descriptor; after the function returns, by subtracting the actual number of
2620 * bytes used, the user can reuse the remaining buffer space for other purposes.
2623 cnstr_shdsc_pdcp_u_plane_decap(uint32_t *descbuf,
2626 enum pdcp_sn_size sn_size,
2628 unsigned short bearer,
2629 unsigned short direction,
2630 uint32_t hfn_threshold,
2631 struct alginfo *cipherdata,
2632 struct alginfo *authdata,
2633 unsigned char era_2_sw_hfn_ovrd)
2636 struct program *p = &prg;
2640 if (rta_sec_era != RTA_SEC_ERA_2 && era_2_sw_hfn_ovrd) {
2641 pr_err("Cannot select SW HFN override for other era than 2");
2645 if (authdata && !authdata->algtype && rta_sec_era < RTA_SEC_ERA_8) {
2646 pr_err("Cannot use u-plane auth with era < 8");
2650 PROGRAM_CNTXT_INIT(p, descbuf, 0);
2652 PROGRAM_SET_BSWAP(p);
2654 PROGRAM_SET_36BIT_ADDR(p);
2656 SHR_HDR(p, SHR_ALWAYS, 0, 0);
2657 if (cnstr_pdcp_u_plane_pdb(p, sn_size, hfn, bearer, direction,
2659 pr_err("Error creating PDCP UPlane PDB\n");
2662 SET_LABEL(p, pdb_end);
2664 err = insert_hfn_ov_op(p, sn_size, PDCP_PDB_TYPE_FULL_PDB,
2669 /* Insert auth key if requested */
2670 if (authdata && authdata->algtype)
2671 KEY(p, KEY2, authdata->key_enc_flags,
2672 (uint64_t)authdata->key, authdata->keylen,
2673 INLINE_KEY(authdata));
2676 case PDCP_SN_SIZE_7:
2677 case PDCP_SN_SIZE_12:
2678 switch (cipherdata->algtype) {
2679 case PDCP_CIPHER_TYPE_ZUC:
2680 if (rta_sec_era < RTA_SEC_ERA_5) {
2681 pr_err("Invalid era for selected algorithm\n");
2685 case PDCP_CIPHER_TYPE_AES:
2686 case PDCP_CIPHER_TYPE_SNOW:
2687 case PDCP_CIPHER_TYPE_NULL:
2688 /* Insert Cipher Key */
2689 KEY(p, KEY1, cipherdata->key_enc_flags,
2690 cipherdata->key, cipherdata->keylen,
2691 INLINE_KEY(cipherdata));
2693 PROTOCOL(p, OP_TYPE_DECAP_PROTOCOL,
2694 OP_PCLID_LTE_PDCP_USER_RN,
2695 ((uint16_t)cipherdata->algtype << 8) |
2696 (uint16_t)authdata->algtype);
2698 PROTOCOL(p, OP_TYPE_DECAP_PROTOCOL,
2699 OP_PCLID_LTE_PDCP_USER,
2700 (uint16_t)cipherdata->algtype);
2703 pr_err("%s: Invalid encrypt algorithm selected: %d\n",
2704 "cnstr_pcl_shdsc_pdcp_u_plane_decap",
2705 cipherdata->algtype);
2710 case PDCP_SN_SIZE_15:
2711 switch (cipherdata->algtype) {
2712 case PDCP_CIPHER_TYPE_NULL:
2713 insert_copy_frame_op(p,
2715 OP_TYPE_DECAP_PROTOCOL);
2719 err = pdcp_insert_uplane_15bit_op(p, swap, cipherdata,
2720 authdata, OP_TYPE_DECAP_PROTOCOL);
2727 case PDCP_SN_SIZE_5:
2729 pr_err("Invalid SN size selected\n");
2733 PATCH_HDR(p, 0, pdb_end);
2734 return PROGRAM_FINALIZE(p);
2738 * cnstr_shdsc_pdcp_short_mac - Function for creating a PDCP Short MAC
2740 * @descbuf: pointer to buffer for descriptor construction
2741 * @ps: if 36/40bit addressing is desired, this parameter must be true
2742 * @swap: must be true when core endianness doesn't match SEC endianness
2743 * @authdata: pointer to authentication transform definitions
2744 * Valid algorithm values are those from auth_type_pdcp enum.
2746 * Return: size of descriptor written in words or negative number on error.
2747 * Once the function returns, the value of this parameter can be used
2748 * for reclaiming the space that wasn't used for the descriptor.
2750 * Note: descbuf must be large enough to contain a full 256 byte long
2751 * descriptor; after the function returns, by subtracting the actual number of
2752 * bytes used, the user can reuse the remaining buffer space for other purposes.
2755 cnstr_shdsc_pdcp_short_mac(uint32_t *descbuf,
2758 struct alginfo *authdata)
2761 struct program *p = &prg;
2762 uint32_t iv[3] = {0, 0, 0};
2763 LABEL(local_offset);
2764 REFERENCE(move_cmd_read_descbuf);
2765 REFERENCE(move_cmd_write_descbuf);
2767 PROGRAM_CNTXT_INIT(p, descbuf, 0);
2769 PROGRAM_SET_BSWAP(p);
2771 PROGRAM_SET_36BIT_ADDR(p);
2773 SHR_HDR(p, SHR_ALWAYS, 1, 0);
2775 if (rta_sec_era > RTA_SEC_ERA_2) {
2776 MATHB(p, SEQINSZ, SUB, ZERO, VSEQINSZ, 4, 0);
2777 MATHB(p, SEQINSZ, SUB, ZERO, MATH1, 4, 0);
2779 MATHB(p, SEQINSZ, ADD, ONE, MATH1, 4, 0);
2780 MATHB(p, MATH1, SUB, ONE, MATH1, 4, 0);
2781 MATHB(p, ZERO, ADD, MATH1, VSEQINSZ, 4, 0);
2782 MOVE(p, MATH1, 0, MATH0, 0, 8, IMMED);
2785 * Since MOVELEN is available only starting with
2786 * SEC ERA 3, use poor man's MOVELEN: create a MOVE
2787 * command dynamically by writing the length from M1 by
2788 * OR-ing the command in the M1 register and MOVE the
2789 * result into the descriptor buffer. Care must be taken
2790 * wrt. the location of the command because of SEC
2791 * pipelining. The actual MOVEs are written at the end
2792 * of the descriptor due to calculations needed on the
2793 * offset in the descriptor for the MOVE command.
2795 move_cmd_read_descbuf = MOVE(p, DESCBUF, 0, MATH0, 0, 6,
2797 move_cmd_write_descbuf = MOVE(p, MATH0, 0, DESCBUF, 0, 8,
2800 MATHB(p, ZERO, ADD, MATH1, VSEQOUTSZ, 4, 0);
2802 switch (authdata->algtype) {
2803 case PDCP_AUTH_TYPE_NULL:
2804 SEQFIFOSTORE(p, MSG, 0, 0, VLF);
2805 if (rta_sec_era > RTA_SEC_ERA_2) {
2806 MOVE(p, AB1, 0, OFIFO, 0, MATH1, 0);
2808 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);
2822 LOAD(p, (uintptr_t)iv, MATH0, 0, 8, IMMED | COPY);
2823 SEQFIFOLOAD(p, MSG1, 0, VLF | LAST1 | LAST2 | FLUSH1);
2824 SEQSTORE(p, MATH0, 0, 4, 0);
2828 case PDCP_AUTH_TYPE_SNOW:
2830 iv[1] = swap ? swab32(0x04000000) : 0x04000000;
2831 iv[2] = swap ? swab32(0xF8000000) : 0xF8000000;
2833 KEY(p, KEY2, authdata->key_enc_flags, authdata->key,
2834 authdata->keylen, INLINE_KEY(authdata));
2835 LOAD(p, (uintptr_t)&iv, CONTEXT2, 0, 12, IMMED | COPY);
2836 ALG_OPERATION(p, OP_ALG_ALGSEL_SNOW_F9,
2838 OP_ALG_AS_INITFINAL,
2841 SEQFIFOSTORE(p, MSG, 0, 0, VLF);
2843 if (rta_sec_era > RTA_SEC_ERA_2) {
2844 MOVE(p, AB1, 0, OFIFO, 0, MATH1, 0);
2846 SET_LABEL(p, local_offset);
2849 /* Shut off automatic Info FIFO entries */
2850 LOAD(p, 0, DCTRL, LDOFF_DISABLE_AUTO_NFIFO, 0, IMMED);
2852 /* Placeholder for MOVE command with length from M1
2855 MOVE(p, IFIFOAB1, 0, OFIFO, 0, 0, IMMED);
2857 /* Enable automatic Info FIFO entries */
2858 LOAD(p, 0, DCTRL, LDOFF_ENABLE_AUTO_NFIFO, 0, IMMED);
2860 SEQFIFOLOAD(p, MSGINSNOOP, 0, VLF | LAST1 | LAST2 | FLUSH1);
2861 SEQSTORE(p, CONTEXT2, 0, 4, 0);
2865 case PDCP_AUTH_TYPE_AES:
2867 iv[1] = swap ? swab32(0xFC000000) : 0xFC000000;
2868 iv[2] = 0x00000000; /* unused */
2870 KEY(p, KEY1, authdata->key_enc_flags, authdata->key,
2871 authdata->keylen, INLINE_KEY(authdata));
2872 LOAD(p, (uintptr_t)&iv, MATH0, 0, 8, IMMED | COPY);
2873 MOVE(p, MATH0, 0, IFIFOAB1, 0, 8, IMMED);
2874 ALG_OPERATION(p, OP_ALG_ALGSEL_AES,
2876 OP_ALG_AS_INITFINAL,
2879 SEQFIFOSTORE(p, MSG, 0, 0, VLF);
2881 if (rta_sec_era > RTA_SEC_ERA_2) {
2882 MOVE(p, AB2, 0, OFIFO, 0, MATH1, 0);
2884 SET_LABEL(p, local_offset);
2886 /* Shut off automatic Info FIFO entries */
2887 LOAD(p, 0, DCTRL, LDOFF_DISABLE_AUTO_NFIFO, 0, IMMED);
2889 /* Placeholder for MOVE command with length from M1
2892 MOVE(p, IFIFOAB2, 0, OFIFO, 0, 0, IMMED);
2894 /* Enable automatic Info FIFO entries */
2895 LOAD(p, 0, DCTRL, LDOFF_ENABLE_AUTO_NFIFO, 0, IMMED);
2897 SEQFIFOLOAD(p, MSGINSNOOP, 0, VLF | LAST1 | LAST2 | FLUSH1);
2898 SEQSTORE(p, CONTEXT1, 0, 4, 0);
2902 case PDCP_AUTH_TYPE_ZUC:
2903 if (rta_sec_era < RTA_SEC_ERA_5) {
2904 pr_err("Invalid era for selected algorithm\n");
2908 iv[1] = swap ? swab32(0xFC000000) : 0xFC000000;
2909 iv[2] = 0x00000000; /* unused */
2911 KEY(p, KEY2, authdata->key_enc_flags, authdata->key,
2912 authdata->keylen, INLINE_KEY(authdata));
2913 LOAD(p, (uintptr_t)&iv, CONTEXT2, 0, 12, IMMED | COPY);
2914 ALG_OPERATION(p, OP_ALG_ALGSEL_ZUCA,
2916 OP_ALG_AS_INITFINAL,
2919 SEQFIFOSTORE(p, MSG, 0, 0, VLF);
2920 MOVE(p, AB1, 0, OFIFO, 0, MATH1, 0);
2921 SEQFIFOLOAD(p, MSGINSNOOP, 0, VLF | LAST1 | LAST2 | FLUSH1);
2922 SEQSTORE(p, CONTEXT2, 0, 4, 0);
2927 pr_err("%s: Invalid integrity algorithm selected: %d\n",
2928 "cnstr_shdsc_pdcp_short_mac", authdata->algtype);
2933 if (rta_sec_era < RTA_SEC_ERA_3) {
2934 PATCH_MOVE(p, move_cmd_read_descbuf, local_offset);
2935 PATCH_MOVE(p, move_cmd_write_descbuf, local_offset);
2938 return PROGRAM_FINALIZE(p);
2941 #endif /* __DESC_PDCP_H__ */