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 unsigned char era_2_sw_hfn_ovrd __maybe_unused)
259 REFERENCE(move_cmd_read_descbuf);
260 REFERENCE(move_cmd_write_descbuf);
262 if (rta_sec_era > RTA_SEC_ERA_2) {
263 MATHB(p, SEQINSZ, ADD, ZERO, VSEQINSZ, 4, 0);
264 if (dir == OP_TYPE_ENCAP_PROTOCOL)
265 MATHB(p, SEQINSZ, ADD, PDCP_MAC_I_LEN, VSEQOUTSZ, 4,
268 MATHB(p, SEQINSZ, SUB, PDCP_MAC_I_LEN, VSEQOUTSZ, 4,
271 MATHB(p, SEQINSZ, ADD, ONE, VSEQINSZ, 4, 0);
272 MATHB(p, VSEQINSZ, SUB, ONE, VSEQINSZ, 4, 0);
274 if (dir == OP_TYPE_ENCAP_PROTOCOL) {
275 MATHB(p, SEQINSZ, ADD, PDCP_MAC_I_LEN, VSEQOUTSZ, 4,
277 MATHB(p, VSEQINSZ, SUB, ONE, MATH0, 4, 0);
279 MATHB(p, VSEQINSZ, SUB, PDCP_MAC_I_LEN, VSEQINSZ, 4,
281 MATHB(p, SEQINSZ, SUB, PDCP_MAC_I_LEN, VSEQOUTSZ, 4,
283 MATHB(p, VSEQOUTSZ, SUB, ONE, MATH0, 4, 0);
286 MATHB(p, MATH0, ADD, ONE, MATH0, 4, 0);
289 * Since MOVELEN is available only starting with
290 * SEC ERA 3, use poor man's MOVELEN: create a MOVE
291 * command dynamically by writing the length from M1 by
292 * OR-ing the command in the M1 register and MOVE the
293 * result into the descriptor buffer. Care must be taken
294 * wrt. the location of the command because of SEC
295 * pipelining. The actual MOVEs are written at the end
296 * of the descriptor due to calculations needed on the
297 * offset in the descriptor for the MOVE command.
299 move_cmd_read_descbuf = MOVE(p, DESCBUF, 0, MATH0, 0, 6,
301 move_cmd_write_descbuf = MOVE(p, MATH0, 0, DESCBUF, 0, 8,
304 MATHB(p, VSEQINSZ, SUB, PDCP_NULL_MAX_FRAME_LEN, NONE, 4,
306 JUMP(p, PDCP_MAX_FRAME_LEN_STATUS, HALT_STATUS, ALL_FALSE, MATH_N);
308 if (rta_sec_era > RTA_SEC_ERA_2) {
309 if (dir == OP_TYPE_ENCAP_PROTOCOL)
310 MATHB(p, VSEQINSZ, ADD, ZERO, MATH0, 4, 0);
312 MATHB(p, VSEQOUTSZ, ADD, ZERO, MATH0, 4, 0);
314 SEQFIFOSTORE(p, MSG, 0, 0, VLF);
315 SEQFIFOLOAD(p, MSG1, 0, VLF | LAST1 | FLUSH1);
317 if (rta_sec_era > RTA_SEC_ERA_2) {
318 MOVE(p, AB1, 0, OFIFO, 0, MATH0, 0);
320 SET_LABEL(p, local_offset);
322 /* Shut off automatic Info FIFO entries */
323 LOAD(p, 0, DCTRL, LDOFF_DISABLE_AUTO_NFIFO, 0, IMMED);
324 /* Placeholder for MOVE command with length from M1 register */
325 MOVE(p, IFIFOAB1, 0, OFIFO, 0, 0, IMMED);
326 /* Enable automatic Info FIFO entries */
327 LOAD(p, 0, DCTRL, LDOFF_ENABLE_AUTO_NFIFO, 0, IMMED);
330 if (dir == OP_TYPE_ENCAP_PROTOCOL) {
331 MATHB(p, MATH1, XOR, MATH1, MATH0, 8, 0);
332 MOVE(p, MATH0, 0, OFIFO, 0, 4, IMMED);
335 if (rta_sec_era < RTA_SEC_ERA_3) {
336 PATCH_MOVE(p, move_cmd_read_descbuf, local_offset);
337 PATCH_MOVE(p, move_cmd_write_descbuf, local_offset);
344 insert_copy_frame_op(struct program *p,
345 struct alginfo *cipherdata __maybe_unused,
346 unsigned int dir __maybe_unused)
349 REFERENCE(move_cmd_read_descbuf);
350 REFERENCE(move_cmd_write_descbuf);
352 if (rta_sec_era > RTA_SEC_ERA_2) {
353 MATHB(p, SEQINSZ, ADD, ZERO, VSEQINSZ, 4, 0);
354 MATHB(p, SEQINSZ, ADD, ZERO, VSEQOUTSZ, 4, 0);
356 MATHB(p, SEQINSZ, ADD, ONE, VSEQINSZ, 4, 0);
357 MATHB(p, VSEQINSZ, SUB, ONE, VSEQINSZ, 4, 0);
358 MATHB(p, SEQINSZ, ADD, ONE, VSEQOUTSZ, 4, 0);
359 MATHB(p, VSEQOUTSZ, SUB, ONE, VSEQOUTSZ, 4, 0);
360 MATHB(p, VSEQINSZ, SUB, ONE, MATH0, 4, 0);
361 MATHB(p, MATH0, ADD, ONE, MATH0, 4, 0);
364 * Since MOVELEN is available only starting with
365 * SEC ERA 3, use poor man's MOVELEN: create a MOVE
366 * command dynamically by writing the length from M1 by
367 * OR-ing the command in the M1 register and MOVE the
368 * result into the descriptor buffer. Care must be taken
369 * wrt. the location of the command because of SEC
370 * pipelining. The actual MOVEs are written at the end
371 * of the descriptor due to calculations needed on the
372 * offset in the descriptor for the MOVE command.
374 move_cmd_read_descbuf = MOVE(p, DESCBUF, 0, MATH0, 0, 6,
376 move_cmd_write_descbuf = MOVE(p, MATH0, 0, DESCBUF, 0, 8,
379 MATHB(p, SEQINSZ, SUB, PDCP_NULL_MAX_FRAME_LEN, NONE, 4,
381 JUMP(p, PDCP_MAX_FRAME_LEN_STATUS, HALT_STATUS, ALL_FALSE, MATH_N);
383 if (rta_sec_era > RTA_SEC_ERA_2)
384 MATHB(p, VSEQINSZ, ADD, ZERO, MATH0, 4, 0);
386 SEQFIFOLOAD(p, MSG1, 0, VLF | LAST1 | FLUSH1);
387 if (rta_sec_era > RTA_SEC_ERA_2) {
388 MOVE(p, AB1, 0, OFIFO, 0, MATH0, 0);
390 SET_LABEL(p, local_offset);
392 /* Shut off automatic Info FIFO entries */
393 LOAD(p, 0, DCTRL, LDOFF_DISABLE_AUTO_NFIFO, 0, IMMED);
395 /* Placeholder for MOVE command with length from M0 register */
396 MOVE(p, IFIFOAB1, 0, OFIFO, 0, 0, IMMED);
398 /* Enable automatic Info FIFO entries */
399 LOAD(p, 0, DCTRL, LDOFF_ENABLE_AUTO_NFIFO, 0, IMMED);
402 SEQFIFOSTORE(p, MSG, 0, 0, VLF);
404 if (rta_sec_era < RTA_SEC_ERA_3) {
405 PATCH_MOVE(p, move_cmd_read_descbuf, local_offset);
406 PATCH_MOVE(p, move_cmd_write_descbuf, local_offset);
412 pdcp_insert_cplane_int_only_op(struct program *p,
413 bool swap __maybe_unused,
414 struct alginfo *cipherdata __maybe_unused,
415 struct alginfo *authdata, unsigned int dir,
416 unsigned char era_2_sw_hfn_ovrd)
419 REFERENCE(move_cmd_read_descbuf);
420 REFERENCE(move_cmd_write_descbuf);
422 switch (authdata->algtype) {
423 case PDCP_AUTH_TYPE_SNOW:
424 /* Insert Auth Key */
425 KEY(p, KEY2, authdata->key_enc_flags, authdata->key,
426 authdata->keylen, INLINE_KEY(authdata));
427 SEQLOAD(p, MATH0, 7, 1, 0);
428 JUMP(p, 1, LOCAL_JUMP, ALL_TRUE, CALM);
430 if (rta_sec_era > RTA_SEC_ERA_2 ||
431 (rta_sec_era == RTA_SEC_ERA_2 &&
432 era_2_sw_hfn_ovrd == 0)) {
433 SEQINPTR(p, 0, 1, RTO);
435 SEQINPTR(p, 0, 5, RTO);
436 SEQFIFOLOAD(p, SKIP, 4, 0);
440 MATHB(p, MATH0, AND, PDCP_C_PLANE_SN_MASK, MATH1, 8,
442 MATHB(p, MATH1, SHLD, MATH1, MATH1, 8, 0);
444 MOVEB(p, DESCBUF, 8, MATH2, 0, 8, WAITCOMP | IMMED);
446 MATHB(p, MATH2, AND, PDCP_BEARER_MASK, MATH2, 8,
448 MOVEB(p, DESCBUF, 0x0C, MATH3, 0, 4, WAITCOMP | IMMED);
449 MATHB(p, MATH3, AND, PDCP_DIR_MASK, MATH3, 8, IMMED2);
450 MATHB(p, MATH1, OR, MATH2, MATH2, 8, 0);
451 MOVEB(p, MATH2, 0, CONTEXT2, 0, 0x0C, WAITCOMP | IMMED);
453 MATHB(p, MATH0, AND, PDCP_C_PLANE_SN_MASK_BE, MATH1, 8,
455 MATHB(p, MATH1, SHLD, MATH1, MATH1, 8, 0);
457 MOVE(p, DESCBUF, 8, MATH2, 0, 8, WAITCOMP | IMMED);
458 MATHB(p, MATH2, AND, PDCP_BEARER_MASK_BE, MATH2, 8,
461 MOVE(p, DESCBUF, 0x0C, MATH3, 0, 4, WAITCOMP | IMMED);
462 MATHB(p, MATH3, AND, PDCP_DIR_MASK_BE, MATH3, 8,
464 MATHB(p, MATH1, OR, MATH2, MATH2, 8, 0);
465 MOVE(p, MATH2, 0, CONTEXT2, 0, 0x0C, WAITCOMP | IMMED);
468 if (dir == OP_TYPE_DECAP_PROTOCOL) {
469 MATHB(p, SEQINSZ, SUB, PDCP_MAC_I_LEN, MATH1, 4,
472 if (rta_sec_era > RTA_SEC_ERA_2) {
473 MATHB(p, SEQINSZ, SUB, ZERO, MATH1, 4,
476 MATHB(p, SEQINSZ, ADD, ONE, MATH1, 4,
478 MATHB(p, MATH1, SUB, ONE, MATH1, 4,
483 if (rta_sec_era > RTA_SEC_ERA_2) {
484 MATHB(p, MATH1, SUB, ZERO, VSEQINSZ, 4, 0);
485 MATHB(p, MATH1, SUB, ZERO, VSEQOUTSZ, 4, 0);
487 MATHB(p, ZERO, ADD, MATH1, VSEQINSZ, 4, 0);
488 MATHB(p, ZERO, ADD, MATH1, VSEQOUTSZ, 4, 0);
491 * Since MOVELEN is available only starting with
492 * SEC ERA 3, use poor man's MOVELEN: create a MOVE
493 * command dynamically by writing the length from M1 by
494 * OR-ing the command in the M1 register and MOVE the
495 * result into the descriptor buffer. Care must be taken
496 * wrt. the location of the command because of SEC
497 * pipelining. The actual MOVEs are written at the end
498 * of the descriptor due to calculations needed on the
499 * offset in the descriptor for the MOVE command.
501 move_cmd_read_descbuf = MOVE(p, DESCBUF, 0, MATH1, 0, 6,
503 move_cmd_write_descbuf = MOVE(p, MATH1, 0, DESCBUF, 0,
504 8, WAITCOMP | IMMED);
507 SEQFIFOSTORE(p, MSG, 0, 0, VLF);
508 ALG_OPERATION(p, OP_ALG_ALGSEL_SNOW_F9, OP_ALG_AAI_F9,
510 dir == OP_TYPE_ENCAP_PROTOCOL ?
511 ICV_CHECK_DISABLE : ICV_CHECK_ENABLE,
514 if (rta_sec_era > RTA_SEC_ERA_2) {
515 SEQFIFOLOAD(p, MSGINSNOOP, 0,
516 VLF | LAST1 | LAST2 | FLUSH1);
517 MOVE(p, AB1, 0, OFIFO, 0, MATH1, 0);
519 SEQFIFOLOAD(p, MSGINSNOOP, 0,
520 VLF | LAST1 | LAST2 | FLUSH1);
521 SET_LABEL(p, local_offset);
523 /* Shut off automatic Info FIFO entries */
524 LOAD(p, 0, DCTRL, LDOFF_DISABLE_AUTO_NFIFO, 0, IMMED);
526 * Placeholder for MOVE command with length from M1
529 MOVE(p, IFIFOAB1, 0, OFIFO, 0, 0, IMMED);
530 /* Enable automatic Info FIFO entries */
531 LOAD(p, 0, DCTRL, LDOFF_ENABLE_AUTO_NFIFO, 0, IMMED);
534 if (dir == OP_TYPE_DECAP_PROTOCOL)
535 SEQFIFOLOAD(p, ICV2, 4, LAST2);
537 SEQSTORE(p, CONTEXT2, 0, 4, 0);
541 case PDCP_AUTH_TYPE_AES:
542 /* Insert Auth Key */
543 KEY(p, KEY1, authdata->key_enc_flags, authdata->key,
544 authdata->keylen, INLINE_KEY(authdata));
545 SEQLOAD(p, MATH0, 7, 1, 0);
546 JUMP(p, 1, LOCAL_JUMP, ALL_TRUE, CALM);
547 if (rta_sec_era > RTA_SEC_ERA_2 ||
548 (rta_sec_era == RTA_SEC_ERA_2 &&
549 era_2_sw_hfn_ovrd == 0)) {
550 SEQINPTR(p, 0, 1, RTO);
552 SEQINPTR(p, 0, 5, RTO);
553 SEQFIFOLOAD(p, SKIP, 4, 0);
557 MATHB(p, MATH0, AND, PDCP_C_PLANE_SN_MASK, MATH1, 8,
559 MATHB(p, MATH1, SHLD, MATH1, MATH1, 8, 0);
561 MOVEB(p, DESCBUF, 8, MATH2, 0, 8, WAITCOMP | IMMED);
562 MATHB(p, MATH1, OR, MATH2, MATH2, 8, 0);
563 MOVEB(p, MATH2, 0, IFIFOAB1, 0, 8, IMMED);
565 MATHB(p, MATH0, AND, PDCP_C_PLANE_SN_MASK_BE, MATH1, 8,
567 MATHB(p, MATH1, SHLD, MATH1, MATH1, 8, 0);
569 MOVE(p, DESCBUF, 8, MATH2, 0, 8, WAITCOMP | IMMED);
570 MATHB(p, MATH1, OR, MATH2, MATH2, 8, 0);
571 MOVE(p, MATH2, 0, IFIFOAB1, 0, 8, IMMED);
574 if (dir == OP_TYPE_DECAP_PROTOCOL) {
575 MATHB(p, SEQINSZ, SUB, PDCP_MAC_I_LEN, MATH1, 4,
578 if (rta_sec_era > RTA_SEC_ERA_2) {
579 MATHB(p, SEQINSZ, SUB, ZERO, MATH1, 4,
582 MATHB(p, SEQINSZ, ADD, ONE, MATH1, 4,
584 MATHB(p, MATH1, SUB, ONE, MATH1, 4,
589 if (rta_sec_era > RTA_SEC_ERA_2) {
590 MATHB(p, MATH1, SUB, ZERO, VSEQINSZ, 4, 0);
591 MATHB(p, MATH1, SUB, ZERO, VSEQOUTSZ, 4, 0);
593 MATHB(p, ZERO, ADD, MATH1, VSEQINSZ, 4, 0);
594 MATHB(p, ZERO, ADD, MATH1, VSEQOUTSZ, 4, 0);
597 * Since MOVELEN is available only starting with
598 * SEC ERA 3, use poor man's MOVELEN: create a MOVE
599 * command dynamically by writing the length from M1 by
600 * OR-ing the command in the M1 register and MOVE the
601 * result into the descriptor buffer. Care must be taken
602 * wrt. the location of the command because of SEC
603 * pipelining. The actual MOVEs are written at the end
604 * of the descriptor due to calculations needed on the
605 * offset in the descriptor for the MOVE command.
607 move_cmd_read_descbuf = MOVE(p, DESCBUF, 0, MATH1, 0, 6,
609 move_cmd_write_descbuf = MOVE(p, MATH1, 0, DESCBUF, 0,
610 8, WAITCOMP | IMMED);
612 SEQFIFOSTORE(p, MSG, 0, 0, VLF);
613 ALG_OPERATION(p, OP_ALG_ALGSEL_AES,
616 dir == OP_TYPE_ENCAP_PROTOCOL ?
617 ICV_CHECK_DISABLE : ICV_CHECK_ENABLE,
620 if (rta_sec_era > RTA_SEC_ERA_2) {
621 MOVE(p, AB2, 0, OFIFO, 0, MATH1, 0);
622 SEQFIFOLOAD(p, MSGINSNOOP, 0,
623 VLF | LAST1 | LAST2 | FLUSH1);
625 SEQFIFOLOAD(p, MSGINSNOOP, 0,
626 VLF | LAST1 | LAST2 | FLUSH1);
627 SET_LABEL(p, local_offset);
629 /* Shut off automatic Info FIFO entries */
630 LOAD(p, 0, DCTRL, LDOFF_DISABLE_AUTO_NFIFO, 0, IMMED);
633 * Placeholder for MOVE command with length from
636 MOVE(p, IFIFOAB2, 0, OFIFO, 0, 0, IMMED);
638 /* Enable automatic Info FIFO entries */
639 LOAD(p, 0, DCTRL, LDOFF_ENABLE_AUTO_NFIFO, 0, IMMED);
642 if (dir == OP_TYPE_DECAP_PROTOCOL)
643 SEQFIFOLOAD(p, ICV1, 4, LAST1 | FLUSH1);
645 SEQSTORE(p, CONTEXT1, 0, 4, 0);
649 case PDCP_AUTH_TYPE_ZUC:
650 if (rta_sec_era < RTA_SEC_ERA_5) {
651 pr_err("Invalid era for selected algorithm\n");
654 /* Insert Auth Key */
655 KEY(p, KEY2, authdata->key_enc_flags, authdata->key,
656 authdata->keylen, INLINE_KEY(authdata));
657 SEQLOAD(p, MATH0, 7, 1, 0);
658 JUMP(p, 1, LOCAL_JUMP, ALL_TRUE, CALM);
659 SEQINPTR(p, 0, 1, RTO);
661 MATHB(p, MATH0, AND, PDCP_C_PLANE_SN_MASK, MATH1, 8,
663 MATHB(p, MATH1, SHLD, MATH1, MATH1, 8, 0);
665 MOVEB(p, DESCBUF, 8, MATH2, 0, 8, WAITCOMP | IMMED);
666 MATHB(p, MATH1, OR, MATH2, MATH2, 8, 0);
667 MOVEB(p, MATH2, 0, CONTEXT2, 0, 8, IMMED);
670 MATHB(p, MATH0, AND, PDCP_C_PLANE_SN_MASK_BE, MATH1, 8,
672 MATHB(p, MATH1, SHLD, MATH1, MATH1, 8, 0);
674 MOVE(p, DESCBUF, 8, MATH2, 0, 8, WAITCOMP | IMMED);
675 MATHB(p, MATH1, OR, MATH2, MATH2, 8, 0);
676 MOVE(p, MATH2, 0, CONTEXT2, 0, 8, IMMED);
678 if (dir == OP_TYPE_DECAP_PROTOCOL)
679 MATHB(p, SEQINSZ, SUB, PDCP_MAC_I_LEN, MATH1, 4,
682 MATHB(p, SEQINSZ, SUB, ZERO, MATH1, 4, 0);
684 MATHB(p, MATH1, SUB, ZERO, VSEQINSZ, 4, 0);
685 MATHB(p, MATH1, SUB, ZERO, VSEQOUTSZ, 4, 0);
686 SEQFIFOSTORE(p, MSG, 0, 0, VLF);
687 ALG_OPERATION(p, OP_ALG_ALGSEL_ZUCA,
690 dir == OP_TYPE_ENCAP_PROTOCOL ?
691 ICV_CHECK_DISABLE : ICV_CHECK_ENABLE,
693 SEQFIFOLOAD(p, MSGINSNOOP, 0, VLF | LAST1 | LAST2 | FLUSH1);
694 MOVE(p, AB1, 0, OFIFO, 0, MATH1, 0);
696 if (dir == OP_TYPE_DECAP_PROTOCOL)
697 SEQFIFOLOAD(p, ICV2, 4, LAST2);
699 SEQSTORE(p, CONTEXT2, 0, 4, 0);
704 pr_err("%s: Invalid integrity algorithm selected: %d\n",
705 "pdcp_insert_cplane_int_only_op", authdata->algtype);
709 if (rta_sec_era < RTA_SEC_ERA_3) {
710 PATCH_MOVE(p, move_cmd_read_descbuf, local_offset);
711 PATCH_MOVE(p, move_cmd_write_descbuf, local_offset);
718 pdcp_insert_cplane_enc_only_op(struct program *p,
719 bool swap __maybe_unused,
720 struct alginfo *cipherdata,
721 struct alginfo *authdata __maybe_unused,
723 unsigned char era_2_sw_hfn_ovrd __maybe_unused)
725 /* Insert Cipher Key */
726 KEY(p, KEY1, cipherdata->key_enc_flags, cipherdata->key,
727 cipherdata->keylen, INLINE_KEY(cipherdata));
729 if (rta_sec_era >= RTA_SEC_ERA_8) {
730 PROTOCOL(p, dir, OP_PCLID_LTE_PDCP_CTRL_MIXED,
731 (uint16_t)cipherdata->algtype << 8);
735 SEQLOAD(p, MATH0, 7, 1, 0);
736 JUMP(p, 1, LOCAL_JUMP, ALL_TRUE, CALM);
738 MATHB(p, MATH0, AND, PDCP_C_PLANE_SN_MASK, MATH1, 8,
741 MATHB(p, MATH0, AND, PDCP_C_PLANE_SN_MASK_BE, MATH1, 8,
743 SEQSTORE(p, MATH0, 7, 1, 0);
744 MATHB(p, MATH1, SHLD, MATH1, MATH1, 8, 0);
745 MOVE(p, DESCBUF, 8, MATH2, 0, 8, WAITCOMP | IMMED);
746 MATHB(p, MATH1, OR, MATH2, MATH2, 8, 0);
748 switch (cipherdata->algtype) {
749 case PDCP_CIPHER_TYPE_SNOW:
750 MOVE(p, MATH2, 0, CONTEXT1, 0, 8, WAITCOMP | IMMED);
752 if (rta_sec_era > RTA_SEC_ERA_2) {
753 MATHB(p, SEQINSZ, SUB, ZERO, VSEQINSZ, 4, 0);
755 MATHB(p, SEQINSZ, SUB, ONE, MATH1, 4, 0);
756 MATHB(p, MATH1, ADD, ONE, VSEQINSZ, 4, 0);
759 if (dir == OP_TYPE_ENCAP_PROTOCOL)
760 MATHB(p, SEQINSZ, ADD, PDCP_MAC_I_LEN, VSEQOUTSZ, 4,
763 MATHB(p, SEQINSZ, SUB, PDCP_MAC_I_LEN, VSEQOUTSZ, 4,
765 SEQFIFOSTORE(p, MSG, 0, 0, VLF | CONT);
766 ALG_OPERATION(p, OP_ALG_ALGSEL_SNOW_F8,
768 OP_ALG_AS_INITFINAL, ICV_CHECK_DISABLE,
769 dir == OP_TYPE_ENCAP_PROTOCOL ?
773 case PDCP_CIPHER_TYPE_AES:
774 MOVE(p, MATH2, 0, CONTEXT1, 0x10, 0x10, WAITCOMP | IMMED);
776 if (rta_sec_era > RTA_SEC_ERA_2) {
777 MATHB(p, SEQINSZ, SUB, ZERO, VSEQINSZ, 4, 0);
779 MATHB(p, SEQINSZ, SUB, ONE, MATH1, 4, 0);
780 MATHB(p, MATH1, ADD, ONE, VSEQINSZ, 4, 0);
783 if (dir == OP_TYPE_ENCAP_PROTOCOL)
784 MATHB(p, SEQINSZ, ADD, PDCP_MAC_I_LEN, VSEQOUTSZ, 4,
787 MATHB(p, SEQINSZ, SUB, PDCP_MAC_I_LEN, VSEQOUTSZ, 4,
790 SEQFIFOSTORE(p, MSG, 0, 0, VLF | CONT);
791 ALG_OPERATION(p, OP_ALG_ALGSEL_AES,
795 dir == OP_TYPE_ENCAP_PROTOCOL ?
799 case PDCP_CIPHER_TYPE_ZUC:
800 if (rta_sec_era < RTA_SEC_ERA_5) {
801 pr_err("Invalid era for selected algorithm\n");
805 MOVE(p, MATH2, 0, CONTEXT1, 0, 0x08, IMMED);
806 MOVE(p, MATH2, 0, CONTEXT1, 0x08, 0x08, WAITCOMP | IMMED);
807 MATHB(p, SEQINSZ, SUB, ZERO, VSEQINSZ, 4, 0);
808 if (dir == OP_TYPE_ENCAP_PROTOCOL)
809 MATHB(p, SEQINSZ, ADD, PDCP_MAC_I_LEN, VSEQOUTSZ, 4,
812 MATHB(p, SEQINSZ, SUB, PDCP_MAC_I_LEN, VSEQOUTSZ, 4,
815 SEQFIFOSTORE(p, MSG, 0, 0, VLF | CONT);
816 ALG_OPERATION(p, OP_ALG_ALGSEL_ZUCE,
820 dir == OP_TYPE_ENCAP_PROTOCOL ?
825 pr_err("%s: Invalid encrypt algorithm selected: %d\n",
826 "pdcp_insert_cplane_enc_only_op", cipherdata->algtype);
830 if (dir == OP_TYPE_ENCAP_PROTOCOL) {
831 SEQFIFOLOAD(p, MSG1, 0, VLF);
832 FIFOLOAD(p, MSG1, PDCP_NULL_INT_MAC_I_VAL, 4,
833 LAST1 | FLUSH1 | IMMED);
835 SEQFIFOLOAD(p, MSG1, 0, VLF | LAST1 | FLUSH1);
836 MOVE(p, OFIFO, 0, MATH1, 4, PDCP_MAC_I_LEN, WAITCOMP | IMMED);
837 MATHB(p, MATH1, XOR, PDCP_NULL_INT_MAC_I_VAL, NONE, 4, IMMED2);
838 JUMP(p, PDCP_NULL_INT_ICV_CHECK_FAILED_STATUS,
839 HALT_STATUS, ALL_FALSE, MATH_Z);
846 pdcp_insert_cplane_acc_op(struct program *p,
847 bool swap __maybe_unused,
848 struct alginfo *cipherdata,
849 struct alginfo *authdata,
851 unsigned char era_2_hfn_ovrd __maybe_unused)
853 /* Insert Auth Key */
854 KEY(p, KEY2, authdata->key_enc_flags, authdata->key, authdata->keylen,
855 INLINE_KEY(authdata));
857 /* Insert Cipher Key */
858 KEY(p, KEY1, cipherdata->key_enc_flags, cipherdata->key,
859 cipherdata->keylen, INLINE_KEY(cipherdata));
860 PROTOCOL(p, dir, OP_PCLID_LTE_PDCP_CTRL, (uint16_t)cipherdata->algtype);
866 pdcp_insert_cplane_snow_aes_op(struct program *p,
867 bool swap __maybe_unused,
868 struct alginfo *cipherdata,
869 struct alginfo *authdata,
871 unsigned char era_2_sw_hfn_ovrd)
873 LABEL(back_to_sd_offset);
876 LABEL(jump_to_beginning);
877 LABEL(fifo_load_mac_i_offset);
878 REFERENCE(seqin_ptr_read);
879 REFERENCE(seqin_ptr_write);
880 REFERENCE(seq_out_read);
881 REFERENCE(jump_back_to_sd_cmd);
882 REFERENCE(move_mac_i_to_desc_buf);
884 if (rta_sec_era >= RTA_SEC_ERA_8) {
885 KEY(p, KEY1, cipherdata->key_enc_flags, cipherdata->key,
886 cipherdata->keylen, INLINE_KEY(cipherdata));
887 KEY(p, KEY2, authdata->key_enc_flags, authdata->key,
888 authdata->keylen, INLINE_KEY(authdata));
890 PROTOCOL(p, dir, OP_PCLID_LTE_PDCP_CTRL_MIXED,
891 ((uint16_t)cipherdata->algtype << 8) |
892 (uint16_t)authdata->algtype);
897 SEQLOAD(p, MATH0, 7, 1, 0);
898 JUMP(p, 1, LOCAL_JUMP, ALL_TRUE, CALM);
900 MATHB(p, MATH0, AND, PDCP_C_PLANE_SN_MASK, MATH1, 8,
903 MATHB(p, MATH0, AND, PDCP_C_PLANE_SN_MASK_BE, MATH1, 8,
905 MATHB(p, MATH1, SHLD, MATH1, MATH1, 8, 0);
906 MOVE(p, DESCBUF, 4, MATH2, 0, 0x08, WAITCOMP | IMMED);
907 MATHB(p, MATH1, OR, MATH2, MATH2, 8, 0);
908 SEQSTORE(p, MATH0, 7, 1, 0);
909 if (dir == OP_TYPE_ENCAP_PROTOCOL) {
910 if (rta_sec_era > RTA_SEC_ERA_2 ||
911 (rta_sec_era == RTA_SEC_ERA_2 &&
912 era_2_sw_hfn_ovrd == 0)) {
913 SEQINPTR(p, 0, 1, RTO);
915 SEQINPTR(p, 0, 5, RTO);
916 SEQFIFOLOAD(p, SKIP, 4, 0);
918 KEY(p, KEY1, authdata->key_enc_flags, authdata->key,
919 authdata->keylen, INLINE_KEY(authdata));
920 MOVE(p, MATH2, 0, IFIFOAB1, 0, 0x08, IMMED);
922 if (rta_sec_era > RTA_SEC_ERA_2) {
923 MATHB(p, SEQINSZ, SUB, ZERO, VSEQINSZ, 4, 0);
924 MATHB(p, SEQINSZ, SUB, ZERO, MATH1, 4, 0);
925 MATHB(p, VSEQINSZ, ADD, PDCP_MAC_I_LEN - 1, VSEQOUTSZ,
928 MATHB(p, SEQINSZ, SUB, MATH3, VSEQINSZ, 4, 0);
929 MATHB(p, VSEQINSZ, ADD, PDCP_MAC_I_LEN - 1, VSEQOUTSZ,
932 * Note: Although the calculations below might seem a
933 * little off, the logic is the following:
935 * - SEQ IN PTR RTO below needs the full length of the
936 * frame; in case of P4080_REV_2_HFN_OV_WORKAROUND,
937 * this means the length of the frame to be processed
938 * + 4 bytes (the HFN override flag and value).
939 * The length of the frame to be processed minus 1
940 * byte is in the VSIL register (because
941 * VSIL = SIL + 3, due to 1 byte, the header being
942 * already written by the SEQ STORE above). So for
943 * calculating the length to use in RTO, I add one
944 * to the VSIL value in order to obtain the total
945 * frame length. This helps in case of P4080 which
946 * can have the value 0 as an operand in a MATH
947 * command only as SRC1 When the HFN override
948 * workaround is not enabled, the length of the
949 * frame is given by the SIL register; the
950 * calculation is similar to the one in the SEC 4.2
953 if (era_2_sw_hfn_ovrd)
954 MATHB(p, VSEQOUTSZ, ADD, ONE, MATH1, 4,
957 MATHB(p, SEQINSZ, ADD, MATH3, MATH1, 4,
961 * Placeholder for filling the length in
962 * SEQIN PTR RTO below
964 seqin_ptr_read = MOVE(p, DESCBUF, 0, MATH1, 0, 6, IMMED);
965 seqin_ptr_write = MOVE(p, MATH1, 0, DESCBUF, 0, 8,
967 ALG_OPERATION(p, OP_ALG_ALGSEL_AES,
972 SEQFIFOLOAD(p, MSG1, 0, VLF | LAST1 | FLUSH1);
973 MOVE(p, CONTEXT1, 0, MATH3, 0, 4, WAITCOMP | IMMED);
974 if (rta_sec_era <= RTA_SEC_ERA_3)
975 LOAD(p, CLRW_CLR_C1KEY |
982 LOAD(p, CLRW_RESET_CLS1_CHA |
990 if (rta_sec_era <= RTA_SEC_ERA_3)
991 LOAD(p, CCTRL_RESET_CHA_ALL, CCTRL, 0, 4, IMMED);
993 KEY(p, KEY1, cipherdata->key_enc_flags, cipherdata->key,
994 cipherdata->keylen, INLINE_KEY(cipherdata));
995 SET_LABEL(p, local_offset);
996 MOVE(p, MATH2, 0, CONTEXT1, 0, 8, IMMED);
997 SEQINPTR(p, 0, 0, RTO);
999 if (rta_sec_era == RTA_SEC_ERA_2 && era_2_sw_hfn_ovrd) {
1000 SEQFIFOLOAD(p, SKIP, 5, 0);
1001 MATHB(p, SEQINSZ, ADD, ONE, SEQINSZ, 4, 0);
1004 MATHB(p, SEQINSZ, SUB, ONE, VSEQINSZ, 4, 0);
1005 ALG_OPERATION(p, OP_ALG_ALGSEL_SNOW_F8,
1007 OP_ALG_AS_INITFINAL,
1010 SEQFIFOSTORE(p, MSG, 0, 0, VLF);
1012 if (rta_sec_era > RTA_SEC_ERA_2 ||
1013 (rta_sec_era == RTA_SEC_ERA_2 &&
1014 era_2_sw_hfn_ovrd == 0))
1015 SEQFIFOLOAD(p, SKIP, 1, 0);
1017 SEQFIFOLOAD(p, MSG1, 0, VLF);
1018 MOVE(p, MATH3, 0, IFIFOAB1, 0, 4, LAST1 | FLUSH1 | IMMED);
1019 PATCH_MOVE(p, seqin_ptr_read, local_offset);
1020 PATCH_MOVE(p, seqin_ptr_write, local_offset);
1022 MOVE(p, MATH2, 0, CONTEXT1, 0, 8, IMMED);
1024 if (rta_sec_era >= RTA_SEC_ERA_5)
1025 MOVE(p, CONTEXT1, 0, CONTEXT2, 0, 8, IMMED);
1027 if (rta_sec_era > RTA_SEC_ERA_2)
1028 MATHB(p, SEQINSZ, SUB, ZERO, VSEQINSZ, 4, 0);
1030 MATHB(p, SEQINSZ, SUB, MATH3, VSEQINSZ, 4, 0);
1032 MATHB(p, SEQINSZ, SUB, PDCP_MAC_I_LEN, VSEQOUTSZ, 4, IMMED2);
1034 * TODO: To be changed when proper support is added in RTA (can't load a
1035 * command that is also written by RTA (or patch it for that matter).
1036 * Change when proper RTA support is added.
1039 WORD(p, 0x168B0004);
1041 WORD(p, 0x16880404);
1043 jump_back_to_sd_cmd = JUMP(p, 0, LOCAL_JUMP, ALL_TRUE, 0);
1045 * Placeholder for command reading the SEQ OUT command in
1046 * JD. Done for rereading the decrypted data and performing
1047 * the integrity check
1050 * TODO: RTA currently doesn't support patching of length of a MOVE command
1051 * Thus, it is inserted as a raw word, as per PS setting.
1054 seq_out_read = MOVE(p, DESCBUF, 0, MATH1, 0, 20,
1057 seq_out_read = MOVE(p, DESCBUF, 0, MATH1, 0, 16,
1060 MATHB(p, MATH1, XOR, CMD_SEQ_IN_PTR ^ CMD_SEQ_OUT_PTR, MATH1, 4,
1062 /* Placeholder for overwriting the SEQ IN with SEQ OUT */
1064 * TODO: RTA currently doesn't support patching of length of a MOVE command
1065 * Thus, it is inserted as a raw word, as per PS setting.
1068 MOVE(p, MATH1, 0, DESCBUF, 0, 24, IMMED);
1070 MOVE(p, MATH1, 0, DESCBUF, 0, 20, IMMED);
1072 KEY(p, KEY1, cipherdata->key_enc_flags, cipherdata->key,
1073 cipherdata->keylen, INLINE_KEY(cipherdata));
1075 if (rta_sec_era >= RTA_SEC_ERA_4)
1076 MOVE(p, CONTEXT1, 0, CONTEXT2, 0, 8, IMMED);
1078 MOVE(p, CONTEXT1, 0, MATH3, 0, 8, IMMED);
1080 ALG_OPERATION(p, OP_ALG_ALGSEL_SNOW_F8,
1082 OP_ALG_AS_INITFINAL,
1085 SEQFIFOSTORE(p, MSG, 0, 0, VLF | CONT);
1086 SEQFIFOLOAD(p, MSG1, 0, VLF | LAST1 | FLUSH1);
1088 if (rta_sec_era <= RTA_SEC_ERA_3)
1089 move_mac_i_to_desc_buf = MOVE(p, OFIFO, 0, DESCBUF, 0,
1090 4, WAITCOMP | IMMED);
1092 MOVE(p, OFIFO, 0, MATH3, 0, 4, IMMED);
1094 if (rta_sec_era <= RTA_SEC_ERA_3)
1095 LOAD(p, CCTRL_RESET_CHA_ALL, CCTRL, 0, 4, IMMED);
1097 LOAD(p, CLRW_RESET_CLS1_CHA |
1105 KEY(p, KEY1, authdata->key_enc_flags, authdata->key,
1106 authdata->keylen, INLINE_KEY(authdata));
1108 * Placeholder for jump in SD for executing the new SEQ IN PTR
1109 * command (which is actually the old SEQ OUT PTR command
1110 * copied over from JD.
1112 SET_LABEL(p, jump_to_beginning);
1113 JUMP(p, 1 - jump_to_beginning, LOCAL_JUMP, ALL_TRUE, 0);
1114 SET_LABEL(p, back_to_sd_offset);
1115 ALG_OPERATION(p, OP_ALG_ALGSEL_AES,
1117 OP_ALG_AS_INITFINAL,
1121 /* Read the # of bytes written in the output buffer + 1 (HDR) */
1122 MATHB(p, VSEQOUTSZ, ADD, ONE, VSEQINSZ, 4, 0);
1124 if (rta_sec_era <= RTA_SEC_ERA_3)
1125 MOVE(p, MATH3, 0, IFIFOAB1, 0, 8, IMMED);
1127 MOVE(p, CONTEXT2, 0, IFIFOAB1, 0, 8, IMMED);
1129 if (rta_sec_era == RTA_SEC_ERA_2 && era_2_sw_hfn_ovrd)
1130 SEQFIFOLOAD(p, SKIP, 4, 0);
1132 SEQFIFOLOAD(p, MSG1, 0, VLF | LAST1 | FLUSH1);
1134 if (rta_sec_era >= RTA_SEC_ERA_4) {
1135 LOAD(p, NFIFOENTRY_STYPE_ALTSOURCE |
1136 NFIFOENTRY_DEST_CLASS1 |
1137 NFIFOENTRY_DTYPE_ICV |
1139 NFIFOENTRY_FC1 | 4, NFIFO_SZL, 0, 4, IMMED);
1140 MOVE(p, MATH3, 0, ALTSOURCE, 0, 4, IMMED);
1142 SET_LABEL(p, fifo_load_mac_i_offset);
1143 FIFOLOAD(p, ICV1, fifo_load_mac_i_offset, 4,
1144 LAST1 | FLUSH1 | IMMED);
1147 SET_LABEL(p, end_desc);
1150 PATCH_MOVE(p, seq_out_read, end_desc + 1);
1151 PATCH_JUMP(p, jump_back_to_sd_cmd,
1152 back_to_sd_offset + jump_back_to_sd_cmd - 5);
1154 if (rta_sec_era <= RTA_SEC_ERA_3)
1155 PATCH_MOVE(p, move_mac_i_to_desc_buf,
1156 fifo_load_mac_i_offset + 1);
1158 PATCH_MOVE(p, seq_out_read, end_desc + 2);
1159 PATCH_JUMP(p, jump_back_to_sd_cmd,
1160 back_to_sd_offset + jump_back_to_sd_cmd - 5);
1162 if (rta_sec_era <= RTA_SEC_ERA_3)
1163 PATCH_MOVE(p, move_mac_i_to_desc_buf,
1164 fifo_load_mac_i_offset + 1);
1172 pdcp_insert_cplane_aes_snow_op(struct program *p,
1173 bool swap __maybe_unused,
1174 struct alginfo *cipherdata,
1175 struct alginfo *authdata,
1177 unsigned char era_2_sw_hfn_ovrd __maybe_unused)
1179 KEY(p, KEY1, cipherdata->key_enc_flags, cipherdata->key,
1180 cipherdata->keylen, INLINE_KEY(cipherdata));
1181 KEY(p, KEY2, authdata->key_enc_flags, authdata->key, authdata->keylen,
1182 INLINE_KEY(authdata));
1184 if (rta_sec_era >= RTA_SEC_ERA_8) {
1185 PROTOCOL(p, dir, OP_PCLID_LTE_PDCP_CTRL_MIXED,
1186 ((uint16_t)cipherdata->algtype << 8) |
1187 (uint16_t)authdata->algtype);
1192 if (dir == OP_TYPE_ENCAP_PROTOCOL)
1193 MATHB(p, SEQINSZ, SUB, ONE, VSEQINSZ, 4, 0);
1195 SEQLOAD(p, MATH0, 7, 1, 0);
1196 JUMP(p, 1, LOCAL_JUMP, ALL_TRUE, CALM);
1197 MOVE(p, MATH0, 7, IFIFOAB2, 0, 1, IMMED);
1199 MATHB(p, MATH0, AND, PDCP_C_PLANE_SN_MASK, MATH1, 8,
1202 MATHB(p, MATH0, AND, PDCP_C_PLANE_SN_MASK_BE, MATH1, 8,
1205 SEQSTORE(p, MATH0, 7, 1, 0);
1206 MATHB(p, MATH1, SHLD, MATH1, MATH1, 8, 0);
1207 MOVE(p, DESCBUF, 4, MATH2, 0, 8, WAITCOMP | IMMED);
1208 MATHB(p, MATH1, OR, MATH2, MATH1, 8, 0);
1209 MOVE(p, MATH1, 0, CONTEXT1, 16, 8, IMMED);
1210 MOVE(p, MATH1, 0, CONTEXT2, 0, 4, IMMED);
1211 if (swap == false) {
1212 MATHB(p, MATH1, AND, lower_32_bits(PDCP_BEARER_MASK), MATH2, 4,
1214 MATHB(p, MATH1, AND, upper_32_bits(PDCP_DIR_MASK), MATH3, 4,
1217 MATHB(p, MATH1, AND, lower_32_bits(PDCP_BEARER_MASK_BE), MATH2,
1219 MATHB(p, MATH1, AND, upper_32_bits(PDCP_DIR_MASK_BE), MATH3,
1222 MATHB(p, MATH3, SHLD, MATH3, MATH3, 8, 0);
1223 MOVE(p, MATH2, 4, OFIFO, 0, 12, IMMED);
1224 MOVE(p, OFIFO, 0, CONTEXT2, 4, 12, IMMED);
1225 if (dir == OP_TYPE_ENCAP_PROTOCOL) {
1226 MATHB(p, SEQINSZ, ADD, PDCP_MAC_I_LEN, VSEQOUTSZ, 4, IMMED2);
1228 MATHB(p, SEQINSZ, SUB, PDCP_MAC_I_LEN, MATH1, 4, IMMED2);
1230 MATHB(p, ZERO, ADD, MATH1, VSEQOUTSZ, 4, 0);
1231 MATHB(p, ZERO, ADD, MATH1, VSEQINSZ, 4, 0);
1234 if (dir == OP_TYPE_ENCAP_PROTOCOL)
1235 SEQFIFOSTORE(p, MSG, 0, 0, VLF);
1237 SEQFIFOSTORE(p, MSG, 0, 0, VLF | CONT);
1239 ALG_OPERATION(p, OP_ALG_ALGSEL_SNOW_F9,
1241 OP_ALG_AS_INITFINAL,
1242 dir == OP_TYPE_ENCAP_PROTOCOL ?
1243 ICV_CHECK_DISABLE : ICV_CHECK_ENABLE,
1245 ALG_OPERATION(p, OP_ALG_ALGSEL_AES,
1247 OP_ALG_AS_INITFINAL,
1249 dir == OP_TYPE_ENCAP_PROTOCOL ? DIR_ENC : DIR_DEC);
1251 if (dir == OP_TYPE_ENCAP_PROTOCOL) {
1252 SEQFIFOLOAD(p, MSGINSNOOP, 0, VLF | LAST2);
1253 MOVE(p, CONTEXT2, 0, IFIFOAB1, 0, 4, LAST1 | FLUSH1 | IMMED);
1255 SEQFIFOLOAD(p, MSGOUTSNOOP, 0, VLF | LAST2);
1256 SEQFIFOLOAD(p, MSG1, 4, LAST1 | FLUSH1);
1257 JUMP(p, 1, LOCAL_JUMP, ALL_TRUE, CLASS1 | NOP | NIFP);
1259 if (rta_sec_era >= RTA_SEC_ERA_6)
1260 LOAD(p, 0, DCTRL, 0, LDLEN_RST_CHA_OFIFO_PTR, IMMED);
1262 MOVE(p, OFIFO, 0, MATH0, 0, 4, WAITCOMP | IMMED);
1264 NFIFOADD(p, IFIFO, ICV2, 4, LAST2);
1266 if (rta_sec_era <= RTA_SEC_ERA_2) {
1267 /* Shut off automatic Info FIFO entries */
1268 LOAD(p, 0, DCTRL, LDOFF_DISABLE_AUTO_NFIFO, 0, IMMED);
1269 MOVE(p, MATH0, 0, IFIFOAB2, 0, 4, WAITCOMP | IMMED);
1271 MOVE(p, MATH0, 0, IFIFO, 0, 4, WAITCOMP | IMMED);
1279 pdcp_insert_cplane_snow_zuc_op(struct program *p,
1280 bool swap __maybe_unused,
1281 struct alginfo *cipherdata,
1282 struct alginfo *authdata,
1284 unsigned char era_2_sw_hfn_ovrd __maybe_unused)
1287 REFERENCE(pkeyjump);
1289 if (rta_sec_era < RTA_SEC_ERA_5) {
1290 pr_err("Invalid era for selected algorithm\n");
1294 pkeyjump = JUMP(p, keyjump, LOCAL_JUMP, ALL_TRUE, SHRD | SELF | BOTH);
1295 KEY(p, KEY1, cipherdata->key_enc_flags, cipherdata->key,
1296 cipherdata->keylen, INLINE_KEY(cipherdata));
1297 KEY(p, KEY2, authdata->key_enc_flags, authdata->key, authdata->keylen,
1298 INLINE_KEY(authdata));
1300 SET_LABEL(p, keyjump);
1302 if (rta_sec_era >= RTA_SEC_ERA_8) {
1303 PROTOCOL(p, dir, OP_PCLID_LTE_PDCP_CTRL_MIXED,
1304 ((uint16_t)cipherdata->algtype << 8) |
1305 (uint16_t)authdata->algtype);
1309 SEQLOAD(p, MATH0, 7, 1, 0);
1310 JUMP(p, 1, LOCAL_JUMP, ALL_TRUE, CALM);
1311 MOVE(p, MATH0, 7, IFIFOAB2, 0, 1, IMMED);
1313 MATHB(p, MATH0, AND, PDCP_C_PLANE_SN_MASK, MATH1, 8,
1316 MATHB(p, MATH0, AND, PDCP_C_PLANE_SN_MASK, MATH1, 8,
1319 MATHB(p, MATH1, SHLD, MATH1, MATH1, 8, 0);
1320 MOVE(p, DESCBUF, 4, MATH2, 0, 8, WAITCOMP | IMMED);
1321 MATHB(p, MATH1, OR, MATH2, MATH2, 8, 0);
1322 MOVE(p, MATH2, 0, CONTEXT1, 0, 8, IMMED);
1323 MOVE(p, MATH2, 0, CONTEXT2, 0, 8, WAITCOMP | IMMED);
1325 if (dir == OP_TYPE_ENCAP_PROTOCOL)
1326 MATHB(p, SEQINSZ, ADD, PDCP_MAC_I_LEN, VSEQOUTSZ, 4, IMMED2);
1328 MATHB(p, SEQINSZ, SUB, PDCP_MAC_I_LEN, VSEQOUTSZ, 4, IMMED2);
1330 MATHB(p, SEQINSZ, SUB, ZERO, VSEQINSZ, 4, 0);
1331 SEQSTORE(p, MATH0, 7, 1, 0);
1333 if (dir == OP_TYPE_ENCAP_PROTOCOL) {
1334 SEQFIFOSTORE(p, MSG, 0, 0, VLF);
1335 SEQFIFOLOAD(p, MSGINSNOOP, 0, VLF | LAST2);
1337 SEQFIFOSTORE(p, MSG, 0, 0, VLF | CONT);
1338 SEQFIFOLOAD(p, MSGOUTSNOOP, 0, VLF | LAST1 | FLUSH1);
1341 ALG_OPERATION(p, OP_ALG_ALGSEL_ZUCA,
1343 OP_ALG_AS_INITFINAL,
1344 dir == OP_TYPE_ENCAP_PROTOCOL ?
1345 ICV_CHECK_DISABLE : ICV_CHECK_ENABLE,
1348 ALG_OPERATION(p, OP_ALG_ALGSEL_SNOW_F8,
1350 OP_ALG_AS_INITFINAL,
1352 dir == OP_TYPE_ENCAP_PROTOCOL ? DIR_ENC : DIR_DEC);
1353 if (dir == OP_TYPE_ENCAP_PROTOCOL) {
1354 MOVE(p, CONTEXT2, 0, IFIFOAB1, 0, 4, LAST1 | FLUSH1 | IMMED);
1357 MOVE(p, OFIFO, 0, MATH0, 0, 4, IMMED);
1358 LOAD(p, NFIFOENTRY_STYPE_ALTSOURCE |
1359 NFIFOENTRY_DEST_CLASS2 |
1360 NFIFOENTRY_DTYPE_ICV |
1361 NFIFOENTRY_LC2 | 4, NFIFO_SZL, 0, 4, IMMED);
1362 MOVE(p, MATH0, 0, ALTSOURCE, 0, 4, WAITCOMP | IMMED);
1365 /* Reset ZUCA mode and done interrupt */
1366 LOAD(p, CLRW_CLR_C2MODE, CLRW, 0, 4, IMMED);
1367 LOAD(p, CIRQ_ZADI, ICTRL, 0, 4, IMMED);
1369 PATCH_JUMP(p, pkeyjump, keyjump);
1374 pdcp_insert_cplane_aes_zuc_op(struct program *p,
1375 bool swap __maybe_unused,
1376 struct alginfo *cipherdata,
1377 struct alginfo *authdata,
1379 unsigned char era_2_sw_hfn_ovrd __maybe_unused)
1382 REFERENCE(pkeyjump);
1384 if (rta_sec_era < RTA_SEC_ERA_5) {
1385 pr_err("Invalid era for selected algorithm\n");
1389 pkeyjump = JUMP(p, keyjump, LOCAL_JUMP, ALL_TRUE, SHRD | SELF | BOTH);
1390 KEY(p, KEY1, cipherdata->key_enc_flags, cipherdata->key,
1391 cipherdata->keylen, INLINE_KEY(cipherdata));
1392 KEY(p, KEY2, authdata->key_enc_flags, authdata->key, authdata->keylen,
1393 INLINE_KEY(authdata));
1395 if (rta_sec_era >= RTA_SEC_ERA_8) {
1396 PROTOCOL(p, dir, OP_PCLID_LTE_PDCP_CTRL_MIXED,
1397 ((uint16_t)cipherdata->algtype << 8) |
1398 (uint16_t)authdata->algtype);
1403 SET_LABEL(p, keyjump);
1404 SEQLOAD(p, MATH0, 7, 1, 0);
1405 JUMP(p, 1, LOCAL_JUMP, ALL_TRUE, CALM);
1406 MOVE(p, MATH0, 7, IFIFOAB2, 0, 1, IMMED);
1408 MATHB(p, MATH0, AND, PDCP_C_PLANE_SN_MASK, MATH1, 8,
1411 MATHB(p, MATH0, AND, PDCP_C_PLANE_SN_MASK, MATH1, 8,
1414 MATHB(p, MATH1, SHLD, MATH1, MATH1, 8, 0);
1415 MOVE(p, DESCBUF, 4, MATH2, 0, 8, WAITCOMP | IMMED);
1416 MATHB(p, MATH1, OR, MATH2, MATH2, 8, 0);
1417 MOVE(p, MATH2, 0, CONTEXT1, 16, 8, IMMED);
1418 MOVE(p, MATH2, 0, CONTEXT2, 0, 8, WAITCOMP | IMMED);
1420 if (dir == OP_TYPE_ENCAP_PROTOCOL)
1421 MATHB(p, SEQINSZ, ADD, PDCP_MAC_I_LEN, VSEQOUTSZ, 4, IMMED2);
1423 MATHB(p, SEQINSZ, SUB, PDCP_MAC_I_LEN, VSEQOUTSZ, 4, IMMED2);
1425 MATHB(p, SEQINSZ, SUB, ZERO, VSEQINSZ, 4, 0);
1426 SEQSTORE(p, MATH0, 7, 1, 0);
1428 if (dir == OP_TYPE_ENCAP_PROTOCOL) {
1429 SEQFIFOSTORE(p, MSG, 0, 0, VLF);
1430 SEQFIFOLOAD(p, MSGINSNOOP, 0, VLF | LAST2);
1432 SEQFIFOSTORE(p, MSG, 0, 0, VLF | CONT);
1433 SEQFIFOLOAD(p, MSGOUTSNOOP, 0, VLF | LAST1 | FLUSH1);
1436 ALG_OPERATION(p, OP_ALG_ALGSEL_ZUCA,
1438 OP_ALG_AS_INITFINAL,
1439 dir == OP_TYPE_ENCAP_PROTOCOL ?
1440 ICV_CHECK_DISABLE : ICV_CHECK_ENABLE,
1443 ALG_OPERATION(p, OP_ALG_ALGSEL_AES,
1445 OP_ALG_AS_INITFINAL,
1447 dir == OP_TYPE_ENCAP_PROTOCOL ? DIR_ENC : DIR_DEC);
1449 if (dir == OP_TYPE_ENCAP_PROTOCOL) {
1450 MOVE(p, CONTEXT2, 0, IFIFOAB1, 0, 4, LAST1 | FLUSH1 | IMMED);
1453 MOVE(p, OFIFO, 0, MATH0, 0, 4, IMMED);
1455 LOAD(p, NFIFOENTRY_STYPE_ALTSOURCE |
1456 NFIFOENTRY_DEST_CLASS2 |
1457 NFIFOENTRY_DTYPE_ICV |
1458 NFIFOENTRY_LC2 | 4, NFIFO_SZL, 0, 4, IMMED);
1459 MOVE(p, MATH0, 0, ALTSOURCE, 0, 4, WAITCOMP | IMMED);
1462 /* Reset ZUCA mode and done interrupt */
1463 LOAD(p, CLRW_CLR_C2MODE, CLRW, 0, 4, IMMED);
1464 LOAD(p, CIRQ_ZADI, ICTRL, 0, 4, IMMED);
1466 PATCH_JUMP(p, pkeyjump, keyjump);
1472 pdcp_insert_cplane_zuc_snow_op(struct program *p,
1473 bool swap __maybe_unused,
1474 struct alginfo *cipherdata,
1475 struct alginfo *authdata,
1477 unsigned char era_2_sw_hfn_ovrd __maybe_unused)
1480 REFERENCE(pkeyjump);
1482 if (rta_sec_era < RTA_SEC_ERA_5) {
1483 pr_err("Invalid era for selected algorithm\n");
1487 pkeyjump = JUMP(p, keyjump, LOCAL_JUMP, ALL_TRUE, SHRD | SELF | BOTH);
1488 KEY(p, KEY1, cipherdata->key_enc_flags, cipherdata->key,
1489 cipherdata->keylen, INLINE_KEY(cipherdata));
1490 KEY(p, KEY2, authdata->key_enc_flags, authdata->key, authdata->keylen,
1491 INLINE_KEY(authdata));
1493 if (rta_sec_era >= RTA_SEC_ERA_8) {
1494 PROTOCOL(p, dir, OP_PCLID_LTE_PDCP_CTRL_MIXED,
1495 ((uint16_t)cipherdata->algtype << 8) |
1496 (uint16_t)authdata->algtype);
1501 SET_LABEL(p, keyjump);
1502 SEQLOAD(p, MATH0, 7, 1, 0);
1503 JUMP(p, 1, LOCAL_JUMP, ALL_TRUE, CALM);
1504 MOVE(p, MATH0, 7, IFIFOAB2, 0, 1, IMMED);
1506 MATHB(p, MATH0, AND, PDCP_C_PLANE_SN_MASK, MATH1, 8,
1509 MATHB(p, MATH0, AND, PDCP_C_PLANE_SN_MASK, MATH1, 8,
1512 MATHB(p, MATH1, SHLD, MATH1, MATH1, 8, 0);
1513 MOVE(p, DESCBUF, 4, MATH2, 0, 8, WAITCOMP | IMMED);
1514 MATHB(p, MATH1, OR, MATH2, MATH1, 8, 0);
1515 MOVE(p, MATH1, 0, CONTEXT1, 0, 8, IMMED);
1516 MOVE(p, MATH1, 0, CONTEXT2, 0, 4, IMMED);
1517 if (swap == false) {
1518 MATHB(p, MATH1, AND, lower_32_bits(PDCP_BEARER_MASK), MATH2,
1520 MATHB(p, MATH1, AND, upper_32_bits(PDCP_DIR_MASK), MATH3,
1523 MATHB(p, MATH1, AND, lower_32_bits(PDCP_BEARER_MASK_BE), MATH2,
1525 MATHB(p, MATH1, AND, upper_32_bits(PDCP_DIR_MASK_BE), MATH3,
1528 MATHB(p, MATH3, SHLD, MATH3, MATH3, 8, 0);
1529 MOVE(p, MATH2, 4, OFIFO, 0, 12, IMMED);
1530 MOVE(p, OFIFO, 0, CONTEXT2, 4, 12, IMMED);
1532 if (dir == OP_TYPE_ENCAP_PROTOCOL) {
1533 MATHB(p, SEQINSZ, ADD, PDCP_MAC_I_LEN, VSEQOUTSZ, 4, IMMED2);
1534 MATHB(p, SEQINSZ, SUB, ZERO, VSEQINSZ, 4, 0);
1536 MATHB(p, SEQINSZ, SUB, PDCP_MAC_I_LEN, VSEQOUTSZ, 4, IMMED2);
1537 MATHB(p, VSEQOUTSZ, SUB, ZERO, VSEQINSZ, 4, 0);
1540 SEQSTORE(p, MATH0, 7, 1, 0);
1542 if (dir == OP_TYPE_ENCAP_PROTOCOL) {
1543 SEQFIFOSTORE(p, MSG, 0, 0, VLF);
1544 SEQFIFOLOAD(p, MSGINSNOOP, 0, VLF | LAST2);
1546 SEQFIFOSTORE(p, MSG, 0, 0, VLF | CONT);
1547 SEQFIFOLOAD(p, MSGOUTSNOOP, 0, VLF | LAST2);
1550 ALG_OPERATION(p, OP_ALG_ALGSEL_SNOW_F9,
1552 OP_ALG_AS_INITFINAL,
1553 dir == OP_TYPE_ENCAP_PROTOCOL ?
1554 ICV_CHECK_DISABLE : ICV_CHECK_ENABLE,
1557 ALG_OPERATION(p, OP_ALG_ALGSEL_ZUCE,
1559 OP_ALG_AS_INITFINAL,
1561 dir == OP_TYPE_ENCAP_PROTOCOL ? DIR_ENC : DIR_DEC);
1563 if (dir == OP_TYPE_ENCAP_PROTOCOL) {
1564 MOVE(p, CONTEXT2, 0, IFIFOAB1, 0, 4, LAST1 | FLUSH1 | IMMED);
1566 SEQFIFOLOAD(p, MSG1, 4, LAST1 | FLUSH1);
1567 JUMP(p, 1, LOCAL_JUMP, ALL_TRUE, CLASS1 | NOP | NIFP);
1569 if (rta_sec_era >= RTA_SEC_ERA_6)
1571 * For SEC ERA 6, there's a problem with the OFIFO
1572 * pointer, and thus it needs to be reset here before
1575 LOAD(p, 0, DCTRL, 0, LDLEN_RST_CHA_OFIFO_PTR, IMMED);
1577 /* Put ICV to M0 before sending it to C2 for comparison. */
1578 MOVE(p, OFIFO, 0, MATH0, 0, 4, WAITCOMP | IMMED);
1580 LOAD(p, NFIFOENTRY_STYPE_ALTSOURCE |
1581 NFIFOENTRY_DEST_CLASS2 |
1582 NFIFOENTRY_DTYPE_ICV |
1583 NFIFOENTRY_LC2 | 4, NFIFO_SZL, 0, 4, IMMED);
1584 MOVE(p, MATH0, 0, ALTSOURCE, 0, 4, IMMED);
1587 PATCH_JUMP(p, pkeyjump, keyjump);
1592 pdcp_insert_cplane_zuc_aes_op(struct program *p,
1593 bool swap __maybe_unused,
1594 struct alginfo *cipherdata,
1595 struct alginfo *authdata,
1597 unsigned char era_2_sw_hfn_ovrd __maybe_unused)
1599 if (rta_sec_era < RTA_SEC_ERA_5) {
1600 pr_err("Invalid era for selected algorithm\n");
1604 if (rta_sec_era >= RTA_SEC_ERA_8) {
1605 KEY(p, KEY1, cipherdata->key_enc_flags, cipherdata->key,
1606 cipherdata->keylen, INLINE_KEY(cipherdata));
1607 KEY(p, KEY2, authdata->key_enc_flags, authdata->key,
1608 authdata->keylen, INLINE_KEY(authdata));
1610 PROTOCOL(p, dir, OP_PCLID_LTE_PDCP_CTRL_MIXED,
1611 ((uint16_t)cipherdata->algtype << 8) |
1612 (uint16_t)authdata->algtype);
1616 SEQLOAD(p, MATH0, 7, 1, 0);
1617 JUMP(p, 1, LOCAL_JUMP, ALL_TRUE, CALM);
1619 MATHB(p, MATH0, AND, PDCP_C_PLANE_SN_MASK, MATH1, 8,
1622 MATHB(p, MATH0, AND, PDCP_C_PLANE_SN_MASK, MATH1, 8,
1625 MATHB(p, MATH1, SHLD, MATH1, MATH1, 8, 0);
1626 MOVE(p, DESCBUF, 4, MATH2, 0, 0x08, WAITCOMP | IMMED);
1627 MATHB(p, MATH1, OR, MATH2, MATH2, 8, 0);
1628 SEQSTORE(p, MATH0, 7, 1, 0);
1629 if (dir == OP_TYPE_ENCAP_PROTOCOL) {
1630 KEY(p, KEY1, authdata->key_enc_flags, authdata->key,
1631 authdata->keylen, INLINE_KEY(authdata));
1632 MOVE(p, MATH2, 0, IFIFOAB1, 0, 0x08, IMMED);
1633 MOVE(p, MATH0, 7, IFIFOAB1, 0, 1, IMMED);
1635 MATHB(p, SEQINSZ, SUB, ZERO, VSEQINSZ, 4, 0);
1636 MATHB(p, VSEQINSZ, ADD, PDCP_MAC_I_LEN, VSEQOUTSZ, 4, IMMED2);
1638 ALG_OPERATION(p, OP_ALG_ALGSEL_AES,
1640 OP_ALG_AS_INITFINAL,
1643 SEQFIFOLOAD(p, MSG1, 0, VLF | LAST1 | FLUSH1);
1644 MOVE(p, CONTEXT1, 0, MATH3, 0, 4, WAITCOMP | IMMED);
1645 LOAD(p, CLRW_RESET_CLS1_CHA |
1653 KEY(p, KEY1, cipherdata->key_enc_flags, cipherdata->key,
1654 cipherdata->keylen, INLINE_KEY(cipherdata));
1656 MOVE(p, MATH2, 0, CONTEXT1, 0, 8, IMMED);
1657 SEQINPTR(p, 0, PDCP_NULL_MAX_FRAME_LEN, RTO);
1659 ALG_OPERATION(p, OP_ALG_ALGSEL_ZUCE,
1661 OP_ALG_AS_INITFINAL,
1664 SEQFIFOSTORE(p, MSG, 0, 0, VLF);
1666 SEQFIFOLOAD(p, SKIP, 1, 0);
1668 SEQFIFOLOAD(p, MSG1, 0, VLF);
1669 MOVE(p, MATH3, 0, IFIFOAB1, 0, 4, LAST1 | FLUSH1 | IMMED);
1671 MOVE(p, MATH2, 0, CONTEXT1, 0, 8, IMMED);
1673 MOVE(p, CONTEXT1, 0, CONTEXT2, 0, 8, IMMED);
1675 MATHB(p, SEQINSZ, SUB, ZERO, VSEQINSZ, 4, 0);
1677 MATHB(p, SEQINSZ, SUB, PDCP_MAC_I_LEN, VSEQOUTSZ, 4, IMMED2);
1679 KEY(p, KEY1, cipherdata->key_enc_flags, cipherdata->key,
1680 cipherdata->keylen, INLINE_KEY(cipherdata));
1682 MOVE(p, CONTEXT1, 0, CONTEXT2, 0, 8, IMMED);
1684 ALG_OPERATION(p, OP_ALG_ALGSEL_ZUCE,
1686 OP_ALG_AS_INITFINAL,
1689 SEQFIFOSTORE(p, MSG, 0, 0, VLF | CONT);
1690 SEQFIFOLOAD(p, MSG1, 0, VLF | LAST1 | FLUSH1);
1692 MOVE(p, OFIFO, 0, MATH3, 0, 4, IMMED);
1694 LOAD(p, CLRW_RESET_CLS1_CHA |
1702 KEY(p, KEY1, authdata->key_enc_flags, authdata->key,
1703 authdata->keylen, INLINE_KEY(authdata));
1705 SEQINPTR(p, 0, 0, SOP);
1707 ALG_OPERATION(p, OP_ALG_ALGSEL_AES,
1709 OP_ALG_AS_INITFINAL,
1713 MATHB(p, SEQINSZ, SUB, ZERO, VSEQINSZ, 4, 0);
1715 MOVE(p, CONTEXT2, 0, IFIFOAB1, 0, 8, IMMED);
1717 SEQFIFOLOAD(p, MSG1, 0, VLF | LAST1 | FLUSH1);
1719 LOAD(p, NFIFOENTRY_STYPE_ALTSOURCE |
1720 NFIFOENTRY_DEST_CLASS1 |
1721 NFIFOENTRY_DTYPE_ICV |
1723 NFIFOENTRY_FC1 | 4, NFIFO_SZL, 0, 4, IMMED);
1724 MOVE(p, MATH3, 0, ALTSOURCE, 0, 4, IMMED);
1731 pdcp_insert_uplane_15bit_op(struct program *p,
1732 bool swap __maybe_unused,
1733 struct alginfo *cipherdata,
1737 /* Insert Cipher Key */
1738 KEY(p, KEY1, cipherdata->key_enc_flags, cipherdata->key,
1739 cipherdata->keylen, INLINE_KEY(cipherdata));
1741 if (rta_sec_era >= RTA_SEC_ERA_8) {
1742 PROTOCOL(p, dir, OP_PCLID_LTE_PDCP_USER,
1743 (uint16_t)cipherdata->algtype);
1747 SEQLOAD(p, MATH0, 6, 2, 0);
1748 JUMP(p, 1, LOCAL_JUMP, ALL_TRUE, CALM);
1750 MATHB(p, MATH0, AND, PDCP_U_PLANE_15BIT_SN_MASK, MATH1, 8,
1753 MATHB(p, MATH0, AND, PDCP_U_PLANE_15BIT_SN_MASK_BE, MATH1, 8,
1755 SEQSTORE(p, MATH0, 6, 2, 0);
1756 MATHB(p, MATH1, SHLD, MATH1, MATH1, 8, 0);
1757 MOVE(p, DESCBUF, 8, MATH2, 0, 8, WAITCOMP | IMMED);
1758 MATHB(p, MATH1, OR, MATH2, MATH2, 8, 0);
1760 MATHB(p, SEQINSZ, SUB, MATH3, VSEQINSZ, 4, 0);
1761 MATHB(p, SEQINSZ, SUB, MATH3, VSEQOUTSZ, 4, 0);
1763 SEQFIFOSTORE(p, MSG, 0, 0, VLF);
1765 op = dir == OP_TYPE_ENCAP_PROTOCOL ? DIR_ENC : DIR_DEC;
1766 switch (cipherdata->algtype) {
1767 case PDCP_CIPHER_TYPE_SNOW:
1768 MOVE(p, MATH2, 0, CONTEXT1, 0, 8, WAITCOMP | IMMED);
1769 ALG_OPERATION(p, OP_ALG_ALGSEL_SNOW_F8,
1771 OP_ALG_AS_INITFINAL,
1776 case PDCP_CIPHER_TYPE_AES:
1777 MOVE(p, MATH2, 0, CONTEXT1, 0x10, 0x10, WAITCOMP | IMMED);
1778 ALG_OPERATION(p, OP_ALG_ALGSEL_AES,
1780 OP_ALG_AS_INITFINAL,
1785 case PDCP_CIPHER_TYPE_ZUC:
1786 if (rta_sec_era < RTA_SEC_ERA_5) {
1787 pr_err("Invalid era for selected algorithm\n");
1790 MOVE(p, MATH2, 0, CONTEXT1, 0, 0x08, IMMED);
1791 MOVE(p, MATH2, 0, CONTEXT1, 0x08, 0x08, WAITCOMP | IMMED);
1793 ALG_OPERATION(p, OP_ALG_ALGSEL_ZUCE,
1795 OP_ALG_AS_INITFINAL,
1801 pr_err("%s: Invalid encrypt algorithm selected: %d\n",
1802 "pdcp_insert_uplane_15bit_op", cipherdata->algtype);
1806 SEQFIFOLOAD(p, MSG1, 0, VLF | LAST1 | FLUSH1);
1812 * Function for inserting the snippet of code responsible for creating
1813 * the HFN override code via either DPOVRD or via the input frame.
1816 insert_hfn_ov_op(struct program *p,
1818 enum pdb_type_e pdb_type,
1819 unsigned char era_2_sw_hfn_ovrd)
1821 uint32_t imm = PDCP_DPOVRD_HFN_OV_EN;
1822 uint16_t hfn_pdb_offset;
1824 if (rta_sec_era == RTA_SEC_ERA_2 && !era_2_sw_hfn_ovrd)
1828 case PDCP_PDB_TYPE_NO_PDB:
1830 * If there is no PDB, then HFN override mechanism does not
1831 * make any sense, thus in this case the function will
1832 * return the pointer to the current position in the
1837 case PDCP_PDB_TYPE_REDUCED_PDB:
1841 case PDCP_PDB_TYPE_FULL_PDB:
1849 if (rta_sec_era > RTA_SEC_ERA_2) {
1850 MATHB(p, DPOVRD, AND, imm, NONE, 8, IFB | IMMED2);
1852 SEQLOAD(p, MATH0, 4, 4, 0);
1853 JUMP(p, 1, LOCAL_JUMP, ALL_TRUE, CALM);
1854 MATHB(p, MATH0, AND, imm, NONE, 8, IFB | IMMED2);
1855 SEQSTORE(p, MATH0, 4, 4, 0);
1858 if (rta_sec_era >= RTA_SEC_ERA_8)
1859 JUMP(p, 6, LOCAL_JUMP, ALL_TRUE, MATH_Z);
1861 JUMP(p, 5, LOCAL_JUMP, ALL_TRUE, MATH_Z);
1863 if (rta_sec_era > RTA_SEC_ERA_2)
1864 MATHB(p, DPOVRD, LSHIFT, shift, MATH0, 4, IMMED2);
1866 MATHB(p, MATH0, LSHIFT, shift, MATH0, 4, IMMED2);
1868 MATHB(p, MATH0, SHLD, MATH0, MATH0, 8, 0);
1869 MOVE(p, MATH0, 0, DESCBUF, hfn_pdb_offset, 4, IMMED);
1871 if (rta_sec_era >= RTA_SEC_ERA_8)
1873 * For ERA8, DPOVRD could be handled by the PROTOCOL command
1874 * itself. For now, this is not done. Thus, clear DPOVRD here
1875 * to alleviate any side-effects.
1877 MATHB(p, DPOVRD, AND, ZERO, DPOVRD, 4, STL);
1883 * PDCP Control PDB creation function
1885 static inline enum pdb_type_e
1886 cnstr_pdcp_c_plane_pdb(struct program *p,
1888 unsigned char bearer,
1889 unsigned char direction,
1890 uint32_t hfn_threshold,
1891 struct alginfo *cipherdata,
1892 struct alginfo *authdata)
1894 struct pdcp_pdb pdb;
1896 pdb_mask[PDCP_CIPHER_TYPE_INVALID][PDCP_AUTH_TYPE_INVALID] = {
1898 PDCP_PDB_TYPE_NO_PDB, /* NULL */
1899 PDCP_PDB_TYPE_FULL_PDB, /* SNOW f9 */
1900 PDCP_PDB_TYPE_FULL_PDB, /* AES CMAC */
1901 PDCP_PDB_TYPE_FULL_PDB /* ZUC-I */
1904 PDCP_PDB_TYPE_FULL_PDB, /* NULL */
1905 PDCP_PDB_TYPE_FULL_PDB, /* SNOW f9 */
1906 PDCP_PDB_TYPE_REDUCED_PDB, /* AES CMAC */
1907 PDCP_PDB_TYPE_REDUCED_PDB /* ZUC-I */
1910 PDCP_PDB_TYPE_FULL_PDB, /* NULL */
1911 PDCP_PDB_TYPE_REDUCED_PDB, /* SNOW f9 */
1912 PDCP_PDB_TYPE_FULL_PDB, /* AES CMAC */
1913 PDCP_PDB_TYPE_REDUCED_PDB /* ZUC-I */
1916 PDCP_PDB_TYPE_FULL_PDB, /* NULL */
1917 PDCP_PDB_TYPE_REDUCED_PDB, /* SNOW f9 */
1918 PDCP_PDB_TYPE_REDUCED_PDB, /* AES CMAC */
1919 PDCP_PDB_TYPE_FULL_PDB /* ZUC-I */
1923 if (rta_sec_era >= RTA_SEC_ERA_8) {
1924 memset(&pdb, 0x00, sizeof(struct pdcp_pdb));
1926 /* This is a HW issue. Bit 2 should be set to zero,
1927 * but it does not work this way. Override here.
1929 pdb.opt_res.rsvd = 0x00000002;
1931 /* Copy relevant information from user to PDB */
1932 pdb.hfn_res = hfn << PDCP_C_PLANE_PDB_HFN_SHIFT;
1933 pdb.bearer_dir_res = (uint32_t)
1934 ((bearer << PDCP_C_PLANE_PDB_BEARER_SHIFT) |
1935 (direction << PDCP_C_PLANE_PDB_DIR_SHIFT));
1937 hfn_threshold << PDCP_C_PLANE_PDB_HFN_THR_SHIFT;
1939 /* copy PDB in descriptor*/
1940 __rta_out32(p, pdb.opt_res.opt);
1941 __rta_out32(p, pdb.hfn_res);
1942 __rta_out32(p, pdb.bearer_dir_res);
1943 __rta_out32(p, pdb.hfn_thr_res);
1945 return PDCP_PDB_TYPE_FULL_PDB;
1948 switch (pdb_mask[cipherdata->algtype][authdata->algtype]) {
1949 case PDCP_PDB_TYPE_NO_PDB:
1952 case PDCP_PDB_TYPE_REDUCED_PDB:
1953 __rta_out32(p, (hfn << PDCP_C_PLANE_PDB_HFN_SHIFT));
1955 (uint32_t)((bearer <<
1956 PDCP_C_PLANE_PDB_BEARER_SHIFT) |
1958 PDCP_C_PLANE_PDB_DIR_SHIFT)));
1961 case PDCP_PDB_TYPE_FULL_PDB:
1962 memset(&pdb, 0x00, sizeof(struct pdcp_pdb));
1964 /* This is a HW issue. Bit 2 should be set to zero,
1965 * but it does not work this way. Override here.
1967 pdb.opt_res.rsvd = 0x00000002;
1969 /* Copy relevant information from user to PDB */
1970 pdb.hfn_res = hfn << PDCP_C_PLANE_PDB_HFN_SHIFT;
1971 pdb.bearer_dir_res = (uint32_t)
1972 ((bearer << PDCP_C_PLANE_PDB_BEARER_SHIFT) |
1973 (direction << PDCP_C_PLANE_PDB_DIR_SHIFT));
1975 hfn_threshold << PDCP_C_PLANE_PDB_HFN_THR_SHIFT;
1977 /* copy PDB in descriptor*/
1978 __rta_out32(p, pdb.opt_res.opt);
1979 __rta_out32(p, pdb.hfn_res);
1980 __rta_out32(p, pdb.bearer_dir_res);
1981 __rta_out32(p, pdb.hfn_thr_res);
1986 return PDCP_PDB_TYPE_INVALID;
1989 return pdb_mask[cipherdata->algtype][authdata->algtype];
1993 * PDCP UPlane PDB creation function
1996 cnstr_pdcp_u_plane_pdb(struct program *p,
1997 enum pdcp_sn_size sn_size,
1998 uint32_t hfn, unsigned short bearer,
1999 unsigned short direction,
2000 uint32_t hfn_threshold)
2002 struct pdcp_pdb pdb;
2003 /* Read options from user */
2004 /* Depending on sequence number length, the HFN and HFN threshold
2005 * have different lengths.
2007 memset(&pdb, 0x00, sizeof(struct pdcp_pdb));
2010 case PDCP_SN_SIZE_7:
2011 pdb.opt_res.opt |= PDCP_U_PLANE_PDB_OPT_SHORT_SN;
2012 pdb.hfn_res = hfn << PDCP_U_PLANE_PDB_SHORT_SN_HFN_SHIFT;
2014 hfn_threshold<<PDCP_U_PLANE_PDB_SHORT_SN_HFN_THR_SHIFT;
2017 case PDCP_SN_SIZE_12:
2018 pdb.opt_res.opt &= (uint32_t)(~PDCP_U_PLANE_PDB_OPT_SHORT_SN);
2019 pdb.hfn_res = hfn << PDCP_U_PLANE_PDB_LONG_SN_HFN_SHIFT;
2021 hfn_threshold<<PDCP_U_PLANE_PDB_LONG_SN_HFN_THR_SHIFT;
2024 case PDCP_SN_SIZE_15:
2025 pdb.opt_res.opt = (uint32_t)(PDCP_U_PLANE_PDB_OPT_15B_SN);
2026 pdb.hfn_res = hfn << PDCP_U_PLANE_PDB_15BIT_SN_HFN_SHIFT;
2028 hfn_threshold<<PDCP_U_PLANE_PDB_15BIT_SN_HFN_THR_SHIFT;
2032 pr_err("Invalid Sequence Number Size setting in PDB\n");
2036 pdb.bearer_dir_res = (uint32_t)
2037 ((bearer << PDCP_U_PLANE_PDB_BEARER_SHIFT) |
2038 (direction << PDCP_U_PLANE_PDB_DIR_SHIFT));
2040 /* copy PDB in descriptor*/
2041 __rta_out32(p, pdb.opt_res.opt);
2042 __rta_out32(p, pdb.hfn_res);
2043 __rta_out32(p, pdb.bearer_dir_res);
2044 __rta_out32(p, pdb.hfn_thr_res);
2049 * cnstr_shdsc_pdcp_c_plane_encap - Function for creating a PDCP Control Plane
2050 * encapsulation descriptor.
2051 * @descbuf: pointer to buffer for descriptor construction
2052 * @ps: if 36/40bit addressing is desired, this parameter must be true
2053 * @swap: must be true when core endianness doesn't match SEC endianness
2054 * @hfn: starting Hyper Frame Number to be used together with the SN from the
2056 * @bearer: radio bearer ID
2057 * @direction: the direction of the PDCP frame (UL/DL)
2058 * @hfn_threshold: HFN value that once reached triggers a warning from SEC that
2059 * keys should be renegotiated at the earliest convenience.
2060 * @cipherdata: pointer to block cipher transform definitions
2061 * Valid algorithm values are those from cipher_type_pdcp enum.
2062 * @authdata: pointer to authentication transform definitions
2063 * Valid algorithm values are those from auth_type_pdcp enum.
2064 * @era_2_sw_hfn_ovrd: if software HFN override mechanism is desired for
2065 * this descriptor. Note: Can only be used for
2067 * Return: size of descriptor written in words or negative number on error.
2068 * Once the function returns, the value of this parameter can be used
2069 * for reclaiming the space that wasn't used for the descriptor.
2071 * Note: descbuf must be large enough to contain a full 256 byte long
2072 * descriptor; after the function returns, by subtracting the actual number of
2073 * bytes used, the user can reuse the remaining buffer space for other purposes.
2076 cnstr_shdsc_pdcp_c_plane_encap(uint32_t *descbuf,
2080 unsigned char bearer,
2081 unsigned char direction,
2082 uint32_t hfn_threshold,
2083 struct alginfo *cipherdata,
2084 struct alginfo *authdata,
2085 unsigned char era_2_sw_hfn_ovrd)
2088 (*pdcp_cp_fp[PDCP_CIPHER_TYPE_INVALID][PDCP_AUTH_TYPE_INVALID])
2089 (struct program*, bool swap, struct alginfo *,
2090 struct alginfo *, unsigned int,
2091 unsigned char __maybe_unused) = {
2093 pdcp_insert_cplane_null_op, /* NULL */
2094 pdcp_insert_cplane_int_only_op, /* SNOW f9 */
2095 pdcp_insert_cplane_int_only_op, /* AES CMAC */
2096 pdcp_insert_cplane_int_only_op /* ZUC-I */
2099 pdcp_insert_cplane_enc_only_op, /* NULL */
2100 pdcp_insert_cplane_acc_op, /* SNOW f9 */
2101 pdcp_insert_cplane_snow_aes_op, /* AES CMAC */
2102 pdcp_insert_cplane_snow_zuc_op /* ZUC-I */
2105 pdcp_insert_cplane_enc_only_op, /* NULL */
2106 pdcp_insert_cplane_aes_snow_op, /* SNOW f9 */
2107 pdcp_insert_cplane_acc_op, /* AES CMAC */
2108 pdcp_insert_cplane_aes_zuc_op /* ZUC-I */
2111 pdcp_insert_cplane_enc_only_op, /* NULL */
2112 pdcp_insert_cplane_zuc_snow_op, /* SNOW f9 */
2113 pdcp_insert_cplane_zuc_aes_op, /* AES CMAC */
2114 pdcp_insert_cplane_acc_op /* ZUC-I */
2117 static enum rta_share_type
2118 desc_share[PDCP_CIPHER_TYPE_INVALID][PDCP_AUTH_TYPE_INVALID] = {
2120 SHR_WAIT, /* NULL */
2121 SHR_ALWAYS, /* SNOW f9 */
2122 SHR_ALWAYS, /* AES CMAC */
2123 SHR_ALWAYS /* ZUC-I */
2126 SHR_ALWAYS, /* NULL */
2127 SHR_ALWAYS, /* SNOW f9 */
2128 SHR_WAIT, /* AES CMAC */
2129 SHR_WAIT /* ZUC-I */
2132 SHR_ALWAYS, /* NULL */
2133 SHR_ALWAYS, /* SNOW f9 */
2134 SHR_ALWAYS, /* AES CMAC */
2135 SHR_WAIT /* ZUC-I */
2138 SHR_ALWAYS, /* NULL */
2139 SHR_WAIT, /* SNOW f9 */
2140 SHR_WAIT, /* AES CMAC */
2141 SHR_ALWAYS /* ZUC-I */
2144 enum pdb_type_e pdb_type;
2146 struct program *p = &prg;
2150 if (rta_sec_era != RTA_SEC_ERA_2 && era_2_sw_hfn_ovrd) {
2151 pr_err("Cannot select SW HFN override for other era than 2");
2155 PROGRAM_CNTXT_INIT(p, descbuf, 0);
2157 PROGRAM_SET_BSWAP(p);
2159 PROGRAM_SET_36BIT_ADDR(p);
2161 SHR_HDR(p, desc_share[cipherdata->algtype][authdata->algtype], 0, 0);
2163 pdb_type = cnstr_pdcp_c_plane_pdb(p,
2171 SET_LABEL(p, pdb_end);
2173 err = insert_hfn_ov_op(p, PDCP_SN_SIZE_5, pdb_type,
2178 err = pdcp_cp_fp[cipherdata->algtype][authdata->algtype](p,
2182 OP_TYPE_ENCAP_PROTOCOL,
2187 PATCH_HDR(p, 0, pdb_end);
2189 return PROGRAM_FINALIZE(p);
2193 * cnstr_shdsc_pdcp_c_plane_decap - Function for creating a PDCP Control Plane
2194 * decapsulation descriptor.
2195 * @descbuf: pointer to buffer for descriptor construction
2196 * @ps: if 36/40bit addressing is desired, this parameter must be true
2197 * @swap: must be true when core endianness doesn't match SEC endianness
2198 * @hfn: starting Hyper Frame Number to be used together with the SN from the
2200 * @bearer: radio bearer ID
2201 * @direction: the direction of the PDCP frame (UL/DL)
2202 * @hfn_threshold: HFN value that once reached triggers a warning from SEC that
2203 * keys should be renegotiated at the earliest convenience.
2204 * @cipherdata: pointer to block cipher transform definitions
2205 * Valid algorithm values are those from cipher_type_pdcp enum.
2206 * @authdata: pointer to authentication transform definitions
2207 * Valid algorithm values are those from auth_type_pdcp enum.
2208 * @era_2_sw_hfn_ovrd: if software HFN override mechanism is desired for
2209 * this descriptor. Note: Can only be used for
2212 * Return: size of descriptor written in words or negative number on error.
2213 * Once the function returns, the value of this parameter can be used
2214 * for reclaiming the space that wasn't used for the descriptor.
2216 * Note: descbuf must be large enough to contain a full 256 byte long
2217 * descriptor; after the function returns, by subtracting the actual number of
2218 * bytes used, the user can reuse the remaining buffer space for other purposes.
2221 cnstr_shdsc_pdcp_c_plane_decap(uint32_t *descbuf,
2225 unsigned char bearer,
2226 unsigned char direction,
2227 uint32_t hfn_threshold,
2228 struct alginfo *cipherdata,
2229 struct alginfo *authdata,
2230 unsigned char era_2_sw_hfn_ovrd)
2233 (*pdcp_cp_fp[PDCP_CIPHER_TYPE_INVALID][PDCP_AUTH_TYPE_INVALID])
2234 (struct program*, bool swap, struct alginfo *,
2235 struct alginfo *, unsigned int, unsigned char) = {
2237 pdcp_insert_cplane_null_op, /* NULL */
2238 pdcp_insert_cplane_int_only_op, /* SNOW f9 */
2239 pdcp_insert_cplane_int_only_op, /* AES CMAC */
2240 pdcp_insert_cplane_int_only_op /* ZUC-I */
2243 pdcp_insert_cplane_enc_only_op, /* NULL */
2244 pdcp_insert_cplane_acc_op, /* SNOW f9 */
2245 pdcp_insert_cplane_snow_aes_op, /* AES CMAC */
2246 pdcp_insert_cplane_snow_zuc_op /* ZUC-I */
2249 pdcp_insert_cplane_enc_only_op, /* NULL */
2250 pdcp_insert_cplane_aes_snow_op, /* SNOW f9 */
2251 pdcp_insert_cplane_acc_op, /* AES CMAC */
2252 pdcp_insert_cplane_aes_zuc_op /* ZUC-I */
2255 pdcp_insert_cplane_enc_only_op, /* NULL */
2256 pdcp_insert_cplane_zuc_snow_op, /* SNOW f9 */
2257 pdcp_insert_cplane_zuc_aes_op, /* AES CMAC */
2258 pdcp_insert_cplane_acc_op /* ZUC-I */
2261 static enum rta_share_type
2262 desc_share[PDCP_CIPHER_TYPE_INVALID][PDCP_AUTH_TYPE_INVALID] = {
2264 SHR_WAIT, /* NULL */
2265 SHR_ALWAYS, /* SNOW f9 */
2266 SHR_ALWAYS, /* AES CMAC */
2267 SHR_ALWAYS /* ZUC-I */
2270 SHR_ALWAYS, /* NULL */
2271 SHR_ALWAYS, /* SNOW f9 */
2272 SHR_WAIT, /* AES CMAC */
2273 SHR_WAIT /* ZUC-I */
2276 SHR_ALWAYS, /* NULL */
2277 SHR_ALWAYS, /* SNOW f9 */
2278 SHR_ALWAYS, /* AES CMAC */
2279 SHR_WAIT /* ZUC-I */
2282 SHR_ALWAYS, /* NULL */
2283 SHR_WAIT, /* SNOW f9 */
2284 SHR_WAIT, /* AES CMAC */
2285 SHR_ALWAYS /* ZUC-I */
2288 enum pdb_type_e pdb_type;
2290 struct program *p = &prg;
2294 if (rta_sec_era != RTA_SEC_ERA_2 && era_2_sw_hfn_ovrd) {
2295 pr_err("Cannot select SW HFN override for other era than 2");
2299 PROGRAM_CNTXT_INIT(p, descbuf, 0);
2301 PROGRAM_SET_BSWAP(p);
2303 PROGRAM_SET_36BIT_ADDR(p);
2305 SHR_HDR(p, desc_share[cipherdata->algtype][authdata->algtype], 0, 0);
2307 pdb_type = cnstr_pdcp_c_plane_pdb(p,
2315 SET_LABEL(p, pdb_end);
2317 err = insert_hfn_ov_op(p, PDCP_SN_SIZE_5, pdb_type,
2322 err = pdcp_cp_fp[cipherdata->algtype][authdata->algtype](p,
2326 OP_TYPE_DECAP_PROTOCOL,
2331 PATCH_HDR(p, 0, pdb_end);
2333 return PROGRAM_FINALIZE(p);
2337 * cnstr_shdsc_pdcp_u_plane_encap - Function for creating a PDCP User Plane
2338 * encapsulation descriptor.
2339 * @descbuf: pointer to buffer for descriptor construction
2340 * @ps: if 36/40bit addressing is desired, this parameter must be true
2341 * @swap: must be true when core endianness doesn't match SEC endianness
2342 * @sn_size: selects Sequence Number Size: 7/12/15 bits
2343 * @hfn: starting Hyper Frame Number to be used together with the SN from the
2345 * @bearer: radio bearer ID
2346 * @direction: the direction of the PDCP frame (UL/DL)
2347 * @hfn_threshold: HFN value that once reached triggers a warning from SEC that
2348 * keys should be renegotiated at the earliest convenience.
2349 * @cipherdata: pointer to block cipher transform definitions
2350 * Valid algorithm values are those from cipher_type_pdcp enum.
2351 * @era_2_sw_hfn_ovrd: if software HFN override mechanism is desired for
2352 * this descriptor. Note: Can only be used for
2355 * Return: size of descriptor written in words or negative number on error.
2356 * Once the function returns, the value of this parameter can be used
2357 * for reclaiming the space that wasn't used for the descriptor.
2359 * Note: descbuf must be large enough to contain a full 256 byte long
2360 * descriptor; after the function returns, by subtracting the actual number of
2361 * bytes used, the user can reuse the remaining buffer space for other purposes.
2364 cnstr_shdsc_pdcp_u_plane_encap(uint32_t *descbuf,
2367 enum pdcp_sn_size sn_size,
2369 unsigned short bearer,
2370 unsigned short direction,
2371 uint32_t hfn_threshold,
2372 struct alginfo *cipherdata,
2373 unsigned char era_2_sw_hfn_ovrd)
2376 struct program *p = &prg;
2380 if (rta_sec_era != RTA_SEC_ERA_2 && era_2_sw_hfn_ovrd) {
2381 pr_err("Cannot select SW HFN ovrd for other era than 2");
2385 PROGRAM_CNTXT_INIT(p, descbuf, 0);
2387 PROGRAM_SET_BSWAP(p);
2389 PROGRAM_SET_36BIT_ADDR(p);
2391 SHR_HDR(p, SHR_ALWAYS, 0, 0);
2392 if (cnstr_pdcp_u_plane_pdb(p, sn_size, hfn, bearer, direction,
2394 pr_err("Error creating PDCP UPlane PDB\n");
2397 SET_LABEL(p, pdb_end);
2399 err = insert_hfn_ov_op(p, sn_size, PDCP_PDB_TYPE_FULL_PDB,
2405 case PDCP_SN_SIZE_7:
2406 case PDCP_SN_SIZE_12:
2407 switch (cipherdata->algtype) {
2408 case PDCP_CIPHER_TYPE_ZUC:
2409 if (rta_sec_era < RTA_SEC_ERA_5) {
2410 pr_err("Invalid era for selected algorithm\n");
2413 case PDCP_CIPHER_TYPE_AES:
2414 case PDCP_CIPHER_TYPE_SNOW:
2415 /* Insert Cipher Key */
2416 KEY(p, KEY1, cipherdata->key_enc_flags,
2417 (uint64_t)cipherdata->key, cipherdata->keylen,
2418 INLINE_KEY(cipherdata));
2419 PROTOCOL(p, OP_TYPE_ENCAP_PROTOCOL,
2420 OP_PCLID_LTE_PDCP_USER,
2421 (uint16_t)cipherdata->algtype);
2423 case PDCP_CIPHER_TYPE_NULL:
2424 insert_copy_frame_op(p,
2426 OP_TYPE_ENCAP_PROTOCOL);
2429 pr_err("%s: Invalid encrypt algorithm selected: %d\n",
2430 "cnstr_pcl_shdsc_pdcp_u_plane_decap",
2431 cipherdata->algtype);
2436 case PDCP_SN_SIZE_15:
2437 switch (cipherdata->algtype) {
2438 case PDCP_CIPHER_TYPE_NULL:
2439 insert_copy_frame_op(p,
2441 OP_TYPE_ENCAP_PROTOCOL);
2445 err = pdcp_insert_uplane_15bit_op(p, swap, cipherdata,
2446 OP_TYPE_ENCAP_PROTOCOL);
2453 case PDCP_SN_SIZE_5:
2455 pr_err("Invalid SN size selected\n");
2459 PATCH_HDR(p, 0, pdb_end);
2460 return PROGRAM_FINALIZE(p);
2464 * cnstr_shdsc_pdcp_u_plane_decap - Function for creating a PDCP User Plane
2465 * decapsulation descriptor.
2466 * @descbuf: pointer to buffer for descriptor construction
2467 * @ps: if 36/40bit addressing is desired, this parameter must be true
2468 * @swap: must be true when core endianness doesn't match SEC endianness
2469 * @sn_size: selects Sequence Number Size: 7/12/15 bits
2470 * @hfn: starting Hyper Frame Number to be used together with the SN from the
2472 * @bearer: radio bearer ID
2473 * @direction: the direction of the PDCP frame (UL/DL)
2474 * @hfn_threshold: HFN value that once reached triggers a warning from SEC that
2475 * keys should be renegotiated at the earliest convenience.
2476 * @cipherdata: pointer to block cipher transform definitions
2477 * Valid algorithm values are those from cipher_type_pdcp enum.
2478 * @era_2_sw_hfn_ovrd: if software HFN override mechanism is desired for
2479 * this descriptor. Note: Can only be used for
2482 * Return: size of descriptor written in words or negative number on error.
2483 * Once the function returns, the value of this parameter can be used
2484 * for reclaiming the space that wasn't used for the descriptor.
2486 * Note: descbuf must be large enough to contain a full 256 byte long
2487 * descriptor; after the function returns, by subtracting the actual number of
2488 * bytes used, the user can reuse the remaining buffer space for other purposes.
2491 cnstr_shdsc_pdcp_u_plane_decap(uint32_t *descbuf,
2494 enum pdcp_sn_size sn_size,
2496 unsigned short bearer,
2497 unsigned short direction,
2498 uint32_t hfn_threshold,
2499 struct alginfo *cipherdata,
2500 unsigned char era_2_sw_hfn_ovrd)
2503 struct program *p = &prg;
2507 if (rta_sec_era != RTA_SEC_ERA_2 && era_2_sw_hfn_ovrd) {
2508 pr_err("Cannot select SW HFN override for other era than 2");
2512 PROGRAM_CNTXT_INIT(p, descbuf, 0);
2514 PROGRAM_SET_BSWAP(p);
2516 PROGRAM_SET_36BIT_ADDR(p);
2518 SHR_HDR(p, SHR_ALWAYS, 0, 0);
2519 if (cnstr_pdcp_u_plane_pdb(p, sn_size, hfn, bearer, direction,
2521 pr_err("Error creating PDCP UPlane PDB\n");
2524 SET_LABEL(p, pdb_end);
2526 err = insert_hfn_ov_op(p, sn_size, PDCP_PDB_TYPE_FULL_PDB,
2532 case PDCP_SN_SIZE_7:
2533 case PDCP_SN_SIZE_12:
2534 switch (cipherdata->algtype) {
2535 case PDCP_CIPHER_TYPE_ZUC:
2536 if (rta_sec_era < RTA_SEC_ERA_5) {
2537 pr_err("Invalid era for selected algorithm\n");
2540 case PDCP_CIPHER_TYPE_AES:
2541 case PDCP_CIPHER_TYPE_SNOW:
2542 /* Insert Cipher Key */
2543 KEY(p, KEY1, cipherdata->key_enc_flags,
2544 cipherdata->key, cipherdata->keylen,
2545 INLINE_KEY(cipherdata));
2546 PROTOCOL(p, OP_TYPE_DECAP_PROTOCOL,
2547 OP_PCLID_LTE_PDCP_USER,
2548 (uint16_t)cipherdata->algtype);
2550 case PDCP_CIPHER_TYPE_NULL:
2551 insert_copy_frame_op(p,
2553 OP_TYPE_DECAP_PROTOCOL);
2556 pr_err("%s: Invalid encrypt algorithm selected: %d\n",
2557 "cnstr_pcl_shdsc_pdcp_u_plane_decap",
2558 cipherdata->algtype);
2563 case PDCP_SN_SIZE_15:
2564 switch (cipherdata->algtype) {
2565 case PDCP_CIPHER_TYPE_NULL:
2566 insert_copy_frame_op(p,
2568 OP_TYPE_DECAP_PROTOCOL);
2572 err = pdcp_insert_uplane_15bit_op(p, swap, cipherdata,
2573 OP_TYPE_DECAP_PROTOCOL);
2580 case PDCP_SN_SIZE_5:
2582 pr_err("Invalid SN size selected\n");
2586 PATCH_HDR(p, 0, pdb_end);
2587 return PROGRAM_FINALIZE(p);
2591 * cnstr_shdsc_pdcp_short_mac - Function for creating a PDCP Short MAC
2593 * @descbuf: pointer to buffer for descriptor construction
2594 * @ps: if 36/40bit addressing is desired, this parameter must be true
2595 * @swap: must be true when core endianness doesn't match SEC endianness
2596 * @authdata: pointer to authentication transform definitions
2597 * Valid algorithm values are those from auth_type_pdcp enum.
2599 * Return: size of descriptor written in words or negative number on error.
2600 * Once the function returns, the value of this parameter can be used
2601 * for reclaiming the space that wasn't used for the descriptor.
2603 * Note: descbuf must be large enough to contain a full 256 byte long
2604 * descriptor; after the function returns, by subtracting the actual number of
2605 * bytes used, the user can reuse the remaining buffer space for other purposes.
2608 cnstr_shdsc_pdcp_short_mac(uint32_t *descbuf,
2611 struct alginfo *authdata)
2614 struct program *p = &prg;
2615 uint32_t iv[3] = {0, 0, 0};
2616 LABEL(local_offset);
2617 REFERENCE(move_cmd_read_descbuf);
2618 REFERENCE(move_cmd_write_descbuf);
2620 PROGRAM_CNTXT_INIT(p, descbuf, 0);
2622 PROGRAM_SET_BSWAP(p);
2624 PROGRAM_SET_36BIT_ADDR(p);
2626 SHR_HDR(p, SHR_ALWAYS, 1, 0);
2628 if (rta_sec_era > RTA_SEC_ERA_2) {
2629 MATHB(p, SEQINSZ, SUB, ZERO, VSEQINSZ, 4, 0);
2630 MATHB(p, SEQINSZ, SUB, ZERO, MATH1, 4, 0);
2632 MATHB(p, SEQINSZ, ADD, ONE, MATH1, 4, 0);
2633 MATHB(p, MATH1, SUB, ONE, MATH1, 4, 0);
2634 MATHB(p, ZERO, ADD, MATH1, VSEQINSZ, 4, 0);
2635 MOVE(p, MATH1, 0, MATH0, 0, 8, IMMED);
2638 * Since MOVELEN is available only starting with
2639 * SEC ERA 3, use poor man's MOVELEN: create a MOVE
2640 * command dynamically by writing the length from M1 by
2641 * OR-ing the command in the M1 register and MOVE the
2642 * result into the descriptor buffer. Care must be taken
2643 * wrt. the location of the command because of SEC
2644 * pipelining. The actual MOVEs are written at the end
2645 * of the descriptor due to calculations needed on the
2646 * offset in the descriptor for the MOVE command.
2648 move_cmd_read_descbuf = MOVE(p, DESCBUF, 0, MATH0, 0, 6,
2650 move_cmd_write_descbuf = MOVE(p, MATH0, 0, DESCBUF, 0, 8,
2653 MATHB(p, ZERO, ADD, MATH1, VSEQOUTSZ, 4, 0);
2655 switch (authdata->algtype) {
2656 case PDCP_AUTH_TYPE_NULL:
2657 SEQFIFOSTORE(p, MSG, 0, 0, VLF);
2658 if (rta_sec_era > RTA_SEC_ERA_2) {
2659 MOVE(p, AB1, 0, OFIFO, 0, MATH1, 0);
2661 SET_LABEL(p, local_offset);
2663 /* Shut off automatic Info FIFO entries */
2664 LOAD(p, 0, DCTRL, LDOFF_DISABLE_AUTO_NFIFO, 0, IMMED);
2666 /* Placeholder for MOVE command with length from M1
2669 MOVE(p, IFIFOAB1, 0, OFIFO, 0, 0, IMMED);
2671 /* Enable automatic Info FIFO entries */
2672 LOAD(p, 0, DCTRL, LDOFF_ENABLE_AUTO_NFIFO, 0, IMMED);
2675 LOAD(p, (uintptr_t)iv, MATH0, 0, 8, IMMED | COPY);
2676 SEQFIFOLOAD(p, MSG1, 0, VLF | LAST1 | LAST2 | FLUSH1);
2677 SEQSTORE(p, MATH0, 0, 4, 0);
2681 case PDCP_AUTH_TYPE_SNOW:
2683 iv[1] = swap ? swab32(0x04000000) : 0x04000000;
2684 iv[2] = swap ? swab32(0xF8000000) : 0xF8000000;
2686 KEY(p, KEY2, authdata->key_enc_flags, authdata->key,
2687 authdata->keylen, INLINE_KEY(authdata));
2688 LOAD(p, (uintptr_t)&iv, CONTEXT2, 0, 12, IMMED | COPY);
2689 ALG_OPERATION(p, OP_ALG_ALGSEL_SNOW_F9,
2691 OP_ALG_AS_INITFINAL,
2694 SEQFIFOSTORE(p, MSG, 0, 0, VLF);
2696 if (rta_sec_era > RTA_SEC_ERA_2) {
2697 MOVE(p, AB1, 0, OFIFO, 0, MATH1, 0);
2699 SET_LABEL(p, local_offset);
2702 /* Shut off automatic Info FIFO entries */
2703 LOAD(p, 0, DCTRL, LDOFF_DISABLE_AUTO_NFIFO, 0, IMMED);
2705 /* Placeholder for MOVE command with length from M1
2708 MOVE(p, IFIFOAB1, 0, OFIFO, 0, 0, IMMED);
2710 /* Enable automatic Info FIFO entries */
2711 LOAD(p, 0, DCTRL, LDOFF_ENABLE_AUTO_NFIFO, 0, IMMED);
2713 SEQFIFOLOAD(p, MSGINSNOOP, 0, VLF | LAST1 | LAST2 | FLUSH1);
2714 SEQSTORE(p, CONTEXT2, 0, 4, 0);
2718 case PDCP_AUTH_TYPE_AES:
2720 iv[1] = swap ? swab32(0xFC000000) : 0xFC000000;
2721 iv[2] = 0x00000000; /* unused */
2723 KEY(p, KEY1, authdata->key_enc_flags, authdata->key,
2724 authdata->keylen, INLINE_KEY(authdata));
2725 LOAD(p, (uintptr_t)&iv, MATH0, 0, 8, IMMED | COPY);
2726 MOVE(p, MATH0, 0, IFIFOAB1, 0, 8, IMMED);
2727 ALG_OPERATION(p, OP_ALG_ALGSEL_AES,
2729 OP_ALG_AS_INITFINAL,
2732 SEQFIFOSTORE(p, MSG, 0, 0, VLF);
2734 if (rta_sec_era > RTA_SEC_ERA_2) {
2735 MOVE(p, AB2, 0, OFIFO, 0, MATH1, 0);
2737 SET_LABEL(p, local_offset);
2739 /* Shut off automatic Info FIFO entries */
2740 LOAD(p, 0, DCTRL, LDOFF_DISABLE_AUTO_NFIFO, 0, IMMED);
2742 /* Placeholder for MOVE command with length from M1
2745 MOVE(p, IFIFOAB2, 0, OFIFO, 0, 0, IMMED);
2747 /* Enable automatic Info FIFO entries */
2748 LOAD(p, 0, DCTRL, LDOFF_ENABLE_AUTO_NFIFO, 0, IMMED);
2750 SEQFIFOLOAD(p, MSGINSNOOP, 0, VLF | LAST1 | LAST2 | FLUSH1);
2751 SEQSTORE(p, CONTEXT1, 0, 4, 0);
2755 case PDCP_AUTH_TYPE_ZUC:
2756 if (rta_sec_era < RTA_SEC_ERA_5) {
2757 pr_err("Invalid era for selected algorithm\n");
2761 iv[1] = swap ? swab32(0xFC000000) : 0xFC000000;
2762 iv[2] = 0x00000000; /* unused */
2764 KEY(p, KEY2, authdata->key_enc_flags, authdata->key,
2765 authdata->keylen, INLINE_KEY(authdata));
2766 LOAD(p, (uintptr_t)&iv, CONTEXT2, 0, 12, IMMED | COPY);
2767 ALG_OPERATION(p, OP_ALG_ALGSEL_ZUCA,
2769 OP_ALG_AS_INITFINAL,
2772 SEQFIFOSTORE(p, MSG, 0, 0, VLF);
2773 MOVE(p, AB1, 0, OFIFO, 0, MATH1, 0);
2774 SEQFIFOLOAD(p, MSGINSNOOP, 0, VLF | LAST1 | LAST2 | FLUSH1);
2775 SEQSTORE(p, CONTEXT2, 0, 4, 0);
2780 pr_err("%s: Invalid integrity algorithm selected: %d\n",
2781 "cnstr_shdsc_pdcp_short_mac", authdata->algtype);
2786 if (rta_sec_era < RTA_SEC_ERA_3) {
2787 PATCH_MOVE(p, move_cmd_read_descbuf, local_offset);
2788 PATCH_MOVE(p, move_cmd_write_descbuf, local_offset);
2791 return PROGRAM_FINALIZE(p);
2794 #endif /* __DESC_PDCP_H__ */