2 * Copyright 2008-2013 Freescale Semiconductor, Inc.
4 * SPDX-License-Identifier: BSD-3-Clause or GPL-2.0+
7 #ifndef __DESC_PDCP_H__
8 #define __DESC_PDCP_H__
14 * DOC: PDCP Shared Descriptor Constructors
16 * Shared descriptors for PDCP protocol.
20 * PDCP_NULL_MAX_FRAME_LEN - The maximum frame frame length that is supported by
23 #define PDCP_NULL_MAX_FRAME_LEN 0x00002FFF
26 * PDCP_MAC_I_LEN - The length of the MAC-I for PDCP protocol operation
28 #define PDCP_MAC_I_LEN 0x00000004
31 * PDCP_MAX_FRAME_LEN_STATUS - The status returned in FD status/command field in
32 * case the input frame is larger than
33 * PDCP_NULL_MAX_FRAME_LEN.
35 #define PDCP_MAX_FRAME_LEN_STATUS 0xF1
38 * PDCP_C_PLANE_SN_MASK - This mask is used in the PDCP descriptors for
39 * extracting the sequence number (SN) from the PDCP
40 * Control Plane header. For PDCP Control Plane, the SN
41 * is constant (5 bits) as opposed to PDCP Data Plane
44 #define PDCP_C_PLANE_SN_MASK 0x1F000000
45 #define PDCP_C_PLANE_SN_MASK_BE 0x0000001F
48 * PDCP_U_PLANE_15BIT_SN_MASK - This mask is used in the PDCP descriptors for
49 * extracting the sequence number (SN) from the
50 * PDCP User Plane header. For PDCP Control Plane,
51 * the SN is constant (5 bits) as opposed to PDCP
52 * Data Plane (7/12/15 bits).
54 #define PDCP_U_PLANE_15BIT_SN_MASK 0xFF7F0000
55 #define PDCP_U_PLANE_15BIT_SN_MASK_BE 0x00007FFF
58 * PDCP_BEARER_MASK - This mask is used masking out the bearer for PDCP
59 * processing with SNOW f9 in LTE.
61 * The value on which this mask is applied is formatted as below:
62 * Count-C (32 bit) | Bearer (5 bit) | Direction (1 bit) | 0 (26 bits)
64 * Applying this mask is done for creating the upper 64 bits of the IV needed
67 * The lower 32 bits of the mask are used for masking the direction for AES
70 #define PDCP_BEARER_MASK 0x00000004FFFFFFFFull
71 #define PDCP_BEARER_MASK_BE 0xFFFFFFFF04000000ull
74 * PDCP_DIR_MASK - This mask is used masking out the direction for PDCP
75 * processing with SNOW f9 in LTE.
77 * The value on which this mask is applied is formatted as below:
78 * Bearer (5 bit) | Direction (1 bit) | 0 (26 bits)
80 * Applying this mask is done for creating the lower 32 bits of the IV needed
83 * The upper 32 bits of the mask are used for masking the direction for AES
86 #define PDCP_DIR_MASK 0x00000000000000F8ull
87 #define PDCP_DIR_MASK_BE 0xF800000000000000ull
90 * PDCP_NULL_INT_MAC_I_VAL - The value of the PDCP PDU MAC-I in case NULL
94 #define PDCP_NULL_INT_MAC_I_VAL 0x00000000
97 * PDCP_NULL_INT_ICV_CHECK_FAILED_STATUS - The status used to report ICV check
98 * failed in case of NULL integrity
99 * Control Plane processing.
101 #define PDCP_NULL_INT_ICV_CHECK_FAILED_STATUS 0x0A
103 * PDCP_DPOVRD_HFN_OV_EN - Value to be used in the FD status/cmd field to
104 * indicate the HFN override mechanism is active for the
107 #define PDCP_DPOVRD_HFN_OV_EN 0x80000000
110 * PDCP_P4080REV2_HFN_OV_BUFLEN - The length in bytes of the supplementary space
111 * that must be provided by the user at the
112 * beginning of the input frame buffer for
115 * The format of the frame buffer is the following:
117 * |<---PDCP_P4080REV2_HFN_OV_BUFLEN-->|
118 * //===================================||============||==============\\
119 * || PDCP_DPOVRD_HFN_OV_EN | HFN value || PDCP Header|| PDCP Payload ||
120 * \\===================================||============||==============//
122 * If HFN override mechanism is not desired, then the MSB of the first 4 bytes
125 #define PDCP_P4080REV2_HFN_OV_BUFLEN 4
128 * enum cipher_type_pdcp - Type selectors for cipher types in PDCP protocol OP
130 * @PDCP_CIPHER_TYPE_NULL: NULL
131 * @PDCP_CIPHER_TYPE_SNOW: SNOW F8
132 * @PDCP_CIPHER_TYPE_AES: AES
133 * @PDCP_CIPHER_TYPE_ZUC: ZUCE
134 * @PDCP_CIPHER_TYPE_INVALID: invalid option
136 enum cipher_type_pdcp {
137 PDCP_CIPHER_TYPE_NULL,
138 PDCP_CIPHER_TYPE_SNOW,
139 PDCP_CIPHER_TYPE_AES,
140 PDCP_CIPHER_TYPE_ZUC,
141 PDCP_CIPHER_TYPE_INVALID
145 * enum auth_type_pdcp - Type selectors for integrity types in PDCP protocol OP
147 * @PDCP_AUTH_TYPE_NULL: NULL
148 * @PDCP_AUTH_TYPE_SNOW: SNOW F9
149 * @PDCP_AUTH_TYPE_AES: AES CMAC
150 * @PDCP_AUTH_TYPE_ZUC: ZUCA
151 * @PDCP_AUTH_TYPE_INVALID: invalid option
153 enum auth_type_pdcp {
158 PDCP_AUTH_TYPE_INVALID
162 * enum pdcp_dir - Type selectors for direction for PDCP protocol
163 * @PDCP_DIR_UPLINK: uplink direction
164 * @PDCP_DIR_DOWNLINK: downlink direction
165 * @PDCP_DIR_INVALID: invalid option
169 PDCP_DIR_DOWNLINK = 1,
174 * enum pdcp_plane - PDCP domain selectors
175 * @PDCP_CONTROL_PLANE: Control Plane
176 * @PDCP_DATA_PLANE: Data Plane
177 * @PDCP_SHORT_MAC: Short MAC
186 * enum pdcp_sn_size - Sequence Number Size selectors for PDCP protocol
187 * @PDCP_SN_SIZE_5: 5bit sequence number
188 * @PDCP_SN_SIZE_7: 7bit sequence number
189 * @PDCP_SN_SIZE_12: 12bit sequence number
190 * @PDCP_SN_SIZE_15: 15bit sequence number
191 * @PDCP_SN_SIZE_18: 18bit sequence number
196 PDCP_SN_SIZE_12 = 12,
201 * PDCP Control Plane Protocol Data Blocks
203 #define PDCP_C_PLANE_PDB_HFN_SHIFT 5
204 #define PDCP_C_PLANE_PDB_BEARER_SHIFT 27
205 #define PDCP_C_PLANE_PDB_DIR_SHIFT 26
206 #define PDCP_C_PLANE_PDB_HFN_THR_SHIFT 5
208 #define PDCP_U_PLANE_PDB_OPT_SHORT_SN 0x2
209 #define PDCP_U_PLANE_PDB_OPT_15B_SN 0x4
210 #define PDCP_U_PLANE_PDB_SHORT_SN_HFN_SHIFT 7
211 #define PDCP_U_PLANE_PDB_LONG_SN_HFN_SHIFT 12
212 #define PDCP_U_PLANE_PDB_15BIT_SN_HFN_SHIFT 15
213 #define PDCP_U_PLANE_PDB_BEARER_SHIFT 27
214 #define PDCP_U_PLANE_PDB_DIR_SHIFT 26
215 #define PDCP_U_PLANE_PDB_SHORT_SN_HFN_THR_SHIFT 7
216 #define PDCP_U_PLANE_PDB_LONG_SN_HFN_THR_SHIFT 12
217 #define PDCP_U_PLANE_PDB_15BIT_SN_HFN_THR_SHIFT 15
224 uint32_t hfn_res; /* HyperFrame number,(27, 25 or 21 bits),
225 * left aligned & right-padded with zeros.
227 uint32_t bearer_dir_res;/* Bearer(5 bits), packet direction (1 bit),
228 * left aligned & right-padded with zeros.
230 uint32_t hfn_thr_res; /* HyperFrame number threshold (27, 25 or 21
231 * bits), left aligned & right-padded with
237 * PDCP internal PDB types
240 PDCP_PDB_TYPE_NO_PDB,
241 PDCP_PDB_TYPE_FULL_PDB,
242 PDCP_PDB_TYPE_REDUCED_PDB,
243 PDCP_PDB_TYPE_INVALID
247 * Function for appending the portion of a PDCP Control Plane shared descriptor
248 * which performs NULL encryption and integrity (i.e. copies the input frame
249 * to the output frame, appending 32 bits of zeros at the end (MAC-I for
253 pdcp_insert_cplane_null_op(struct program *p,
254 bool swap __maybe_unused,
255 struct alginfo *cipherdata __maybe_unused,
256 struct alginfo *authdata __maybe_unused,
258 unsigned char era_2_sw_hfn_ovrd __maybe_unused)
261 REFERENCE(move_cmd_read_descbuf);
262 REFERENCE(move_cmd_write_descbuf);
264 if (rta_sec_era > RTA_SEC_ERA_2) {
265 MATHB(p, SEQINSZ, ADD, ZERO, VSEQINSZ, 4, 0);
266 if (dir == OP_TYPE_ENCAP_PROTOCOL)
267 MATHB(p, SEQINSZ, ADD, PDCP_MAC_I_LEN, VSEQOUTSZ, 4,
270 MATHB(p, SEQINSZ, SUB, PDCP_MAC_I_LEN, VSEQOUTSZ, 4,
273 MATHB(p, SEQINSZ, ADD, ONE, VSEQINSZ, 4, 0);
274 MATHB(p, VSEQINSZ, SUB, ONE, VSEQINSZ, 4, 0);
276 if (dir == OP_TYPE_ENCAP_PROTOCOL) {
277 MATHB(p, SEQINSZ, ADD, PDCP_MAC_I_LEN, VSEQOUTSZ, 4,
279 MATHB(p, VSEQINSZ, SUB, ONE, MATH0, 4, 0);
281 MATHB(p, VSEQINSZ, SUB, PDCP_MAC_I_LEN, VSEQINSZ, 4,
283 MATHB(p, SEQINSZ, SUB, PDCP_MAC_I_LEN, VSEQOUTSZ, 4,
285 MATHB(p, VSEQOUTSZ, SUB, ONE, MATH0, 4, 0);
288 MATHB(p, MATH0, ADD, ONE, MATH0, 4, 0);
291 * Since MOVELEN is available only starting with
292 * SEC ERA 3, use poor man's MOVELEN: create a MOVE
293 * command dynamically by writing the length from M1 by
294 * OR-ing the command in the M1 register and MOVE the
295 * result into the descriptor buffer. Care must be taken
296 * wrt. the location of the command because of SEC
297 * pipelining. The actual MOVEs are written at the end
298 * of the descriptor due to calculations needed on the
299 * offset in the descriptor for the MOVE command.
301 move_cmd_read_descbuf = MOVE(p, DESCBUF, 0, MATH0, 0, 6,
303 move_cmd_write_descbuf = MOVE(p, MATH0, 0, DESCBUF, 0, 8,
306 MATHB(p, VSEQINSZ, SUB, PDCP_NULL_MAX_FRAME_LEN, NONE, 4,
308 JUMP(p, PDCP_MAX_FRAME_LEN_STATUS, HALT_STATUS, ALL_FALSE, MATH_N);
310 if (rta_sec_era > RTA_SEC_ERA_2) {
311 if (dir == OP_TYPE_ENCAP_PROTOCOL)
312 MATHB(p, VSEQINSZ, ADD, ZERO, MATH0, 4, 0);
314 MATHB(p, VSEQOUTSZ, ADD, ZERO, MATH0, 4, 0);
316 SEQFIFOSTORE(p, MSG, 0, 0, VLF);
317 SEQFIFOLOAD(p, MSG1, 0, VLF | LAST1 | FLUSH1);
319 if (rta_sec_era > RTA_SEC_ERA_2) {
320 MOVE(p, AB1, 0, OFIFO, 0, MATH0, 0);
322 SET_LABEL(p, local_offset);
324 /* Shut off automatic Info FIFO entries */
325 LOAD(p, 0, DCTRL, LDOFF_DISABLE_AUTO_NFIFO, 0, IMMED);
326 /* Placeholder for MOVE command with length from M1 register */
327 MOVE(p, IFIFOAB1, 0, OFIFO, 0, 0, IMMED);
328 /* Enable automatic Info FIFO entries */
329 LOAD(p, 0, DCTRL, LDOFF_ENABLE_AUTO_NFIFO, 0, IMMED);
332 if (dir == OP_TYPE_ENCAP_PROTOCOL) {
333 MATHB(p, MATH1, XOR, MATH1, MATH0, 8, 0);
334 MOVE(p, MATH0, 0, OFIFO, 0, 4, IMMED);
337 if (rta_sec_era < RTA_SEC_ERA_3) {
338 PATCH_MOVE(p, move_cmd_read_descbuf, local_offset);
339 PATCH_MOVE(p, move_cmd_write_descbuf, local_offset);
346 insert_copy_frame_op(struct program *p,
347 struct alginfo *cipherdata __maybe_unused,
348 unsigned int dir __maybe_unused)
351 REFERENCE(move_cmd_read_descbuf);
352 REFERENCE(move_cmd_write_descbuf);
354 if (rta_sec_era > RTA_SEC_ERA_2) {
355 MATHB(p, SEQINSZ, ADD, ZERO, VSEQINSZ, 4, 0);
356 MATHB(p, SEQINSZ, ADD, ZERO, VSEQOUTSZ, 4, 0);
358 MATHB(p, SEQINSZ, ADD, ONE, VSEQINSZ, 4, 0);
359 MATHB(p, VSEQINSZ, SUB, ONE, VSEQINSZ, 4, 0);
360 MATHB(p, SEQINSZ, ADD, ONE, VSEQOUTSZ, 4, 0);
361 MATHB(p, VSEQOUTSZ, SUB, ONE, VSEQOUTSZ, 4, 0);
362 MATHB(p, VSEQINSZ, SUB, ONE, MATH0, 4, 0);
363 MATHB(p, MATH0, ADD, ONE, MATH0, 4, 0);
366 * Since MOVELEN is available only starting with
367 * SEC ERA 3, use poor man's MOVELEN: create a MOVE
368 * command dynamically by writing the length from M1 by
369 * OR-ing the command in the M1 register and MOVE the
370 * result into the descriptor buffer. Care must be taken
371 * wrt. the location of the command because of SEC
372 * pipelining. The actual MOVEs are written at the end
373 * of the descriptor due to calculations needed on the
374 * offset in the descriptor for the MOVE command.
376 move_cmd_read_descbuf = MOVE(p, DESCBUF, 0, MATH0, 0, 6,
378 move_cmd_write_descbuf = MOVE(p, MATH0, 0, DESCBUF, 0, 8,
381 MATHB(p, SEQINSZ, SUB, PDCP_NULL_MAX_FRAME_LEN, NONE, 4,
383 JUMP(p, PDCP_MAX_FRAME_LEN_STATUS, HALT_STATUS, ALL_FALSE, MATH_N);
385 if (rta_sec_era > RTA_SEC_ERA_2)
386 MATHB(p, VSEQINSZ, ADD, ZERO, MATH0, 4, 0);
388 SEQFIFOLOAD(p, MSG1, 0, VLF | LAST1 | FLUSH1);
389 if (rta_sec_era > RTA_SEC_ERA_2) {
390 MOVE(p, AB1, 0, OFIFO, 0, MATH0, 0);
392 SET_LABEL(p, local_offset);
394 /* Shut off automatic Info FIFO entries */
395 LOAD(p, 0, DCTRL, LDOFF_DISABLE_AUTO_NFIFO, 0, IMMED);
397 /* Placeholder for MOVE command with length from M0 register */
398 MOVE(p, IFIFOAB1, 0, OFIFO, 0, 0, IMMED);
400 /* Enable automatic Info FIFO entries */
401 LOAD(p, 0, DCTRL, LDOFF_ENABLE_AUTO_NFIFO, 0, IMMED);
404 SEQFIFOSTORE(p, MSG, 0, 0, VLF);
406 if (rta_sec_era < RTA_SEC_ERA_3) {
407 PATCH_MOVE(p, move_cmd_read_descbuf, local_offset);
408 PATCH_MOVE(p, move_cmd_write_descbuf, local_offset);
414 pdcp_insert_cplane_int_only_op(struct program *p,
415 bool swap __maybe_unused,
416 struct alginfo *cipherdata __maybe_unused,
417 struct alginfo *authdata, unsigned int dir,
418 unsigned char era_2_sw_hfn_ovrd)
421 REFERENCE(move_cmd_read_descbuf);
422 REFERENCE(move_cmd_write_descbuf);
424 switch (authdata->algtype) {
425 case PDCP_AUTH_TYPE_SNOW:
426 /* Insert Auth Key */
427 KEY(p, KEY2, authdata->key_enc_flags, authdata->key,
428 authdata->keylen, INLINE_KEY(authdata));
429 SEQLOAD(p, MATH0, 7, 1, 0);
430 JUMP(p, 1, LOCAL_JUMP, ALL_TRUE, CALM);
432 if (rta_sec_era > RTA_SEC_ERA_2 ||
433 (rta_sec_era == RTA_SEC_ERA_2 &&
434 era_2_sw_hfn_ovrd == 0)) {
435 SEQINPTR(p, 0, 1, RTO);
437 SEQINPTR(p, 0, 5, RTO);
438 SEQFIFOLOAD(p, SKIP, 4, 0);
442 MATHB(p, MATH0, AND, PDCP_C_PLANE_SN_MASK, MATH1, 8,
444 MATHB(p, MATH1, SHLD, MATH1, MATH1, 8, 0);
446 MOVEB(p, DESCBUF, 8, MATH2, 0, 8, WAITCOMP | IMMED);
448 MATHB(p, MATH2, AND, PDCP_BEARER_MASK, MATH2, 8,
450 MOVEB(p, DESCBUF, 0x0C, MATH3, 0, 4, WAITCOMP | IMMED);
451 MATHB(p, MATH3, AND, PDCP_DIR_MASK, MATH3, 8, IMMED2);
452 MATHB(p, MATH1, OR, MATH2, MATH2, 8, 0);
453 MOVEB(p, MATH2, 0, CONTEXT2, 0, 0x0C, WAITCOMP | IMMED);
455 MATHB(p, MATH0, AND, PDCP_C_PLANE_SN_MASK_BE, MATH1, 8,
457 MATHB(p, MATH1, SHLD, MATH1, MATH1, 8, 0);
459 MOVE(p, DESCBUF, 8, MATH2, 0, 8, WAITCOMP | IMMED);
460 MATHB(p, MATH2, AND, PDCP_BEARER_MASK_BE, MATH2, 8,
463 MOVE(p, DESCBUF, 0x0C, MATH3, 0, 4, WAITCOMP | IMMED);
464 MATHB(p, MATH3, AND, PDCP_DIR_MASK_BE, MATH3, 8,
466 MATHB(p, MATH1, OR, MATH2, MATH2, 8, 0);
467 MOVE(p, MATH2, 0, CONTEXT2, 0, 0x0C, WAITCOMP | IMMED);
470 if (dir == OP_TYPE_DECAP_PROTOCOL) {
471 MATHB(p, SEQINSZ, SUB, PDCP_MAC_I_LEN, MATH1, 4,
474 if (rta_sec_era > RTA_SEC_ERA_2) {
475 MATHB(p, SEQINSZ, SUB, ZERO, MATH1, 4,
478 MATHB(p, SEQINSZ, ADD, ONE, MATH1, 4,
480 MATHB(p, MATH1, SUB, ONE, MATH1, 4,
485 if (rta_sec_era > RTA_SEC_ERA_2) {
486 MATHB(p, MATH1, SUB, ZERO, VSEQINSZ, 4, 0);
487 MATHB(p, MATH1, SUB, ZERO, VSEQOUTSZ, 4, 0);
489 MATHB(p, ZERO, ADD, MATH1, VSEQINSZ, 4, 0);
490 MATHB(p, ZERO, ADD, MATH1, VSEQOUTSZ, 4, 0);
493 * Since MOVELEN is available only starting with
494 * SEC ERA 3, use poor man's MOVELEN: create a MOVE
495 * command dynamically by writing the length from M1 by
496 * OR-ing the command in the M1 register and MOVE the
497 * result into the descriptor buffer. Care must be taken
498 * wrt. the location of the command because of SEC
499 * pipelining. The actual MOVEs are written at the end
500 * of the descriptor due to calculations needed on the
501 * offset in the descriptor for the MOVE command.
503 move_cmd_read_descbuf = MOVE(p, DESCBUF, 0, MATH1, 0, 6,
505 move_cmd_write_descbuf = MOVE(p, MATH1, 0, DESCBUF, 0,
506 8, WAITCOMP | IMMED);
509 SEQFIFOSTORE(p, MSG, 0, 0, VLF);
510 ALG_OPERATION(p, OP_ALG_ALGSEL_SNOW_F9, OP_ALG_AAI_F9,
512 dir == OP_TYPE_ENCAP_PROTOCOL ?
513 ICV_CHECK_DISABLE : ICV_CHECK_ENABLE,
516 if (rta_sec_era > RTA_SEC_ERA_2) {
517 SEQFIFOLOAD(p, MSGINSNOOP, 0,
518 VLF | LAST1 | LAST2 | FLUSH1);
519 MOVE(p, AB1, 0, OFIFO, 0, MATH1, 0);
521 SEQFIFOLOAD(p, MSGINSNOOP, 0,
522 VLF | LAST1 | LAST2 | FLUSH1);
523 SET_LABEL(p, local_offset);
525 /* Shut off automatic Info FIFO entries */
526 LOAD(p, 0, DCTRL, LDOFF_DISABLE_AUTO_NFIFO, 0, IMMED);
528 * Placeholder for MOVE command with length from M1
531 MOVE(p, IFIFOAB1, 0, OFIFO, 0, 0, IMMED);
532 /* Enable automatic Info FIFO entries */
533 LOAD(p, 0, DCTRL, LDOFF_ENABLE_AUTO_NFIFO, 0, IMMED);
536 if (dir == OP_TYPE_DECAP_PROTOCOL)
537 SEQFIFOLOAD(p, ICV2, 4, LAST2);
539 SEQSTORE(p, CONTEXT2, 0, 4, 0);
543 case PDCP_AUTH_TYPE_AES:
544 /* Insert Auth Key */
545 KEY(p, KEY1, authdata->key_enc_flags, authdata->key,
546 authdata->keylen, INLINE_KEY(authdata));
547 SEQLOAD(p, MATH0, 7, 1, 0);
548 JUMP(p, 1, LOCAL_JUMP, ALL_TRUE, CALM);
549 if (rta_sec_era > RTA_SEC_ERA_2 ||
550 (rta_sec_era == RTA_SEC_ERA_2 &&
551 era_2_sw_hfn_ovrd == 0)) {
552 SEQINPTR(p, 0, 1, RTO);
554 SEQINPTR(p, 0, 5, RTO);
555 SEQFIFOLOAD(p, SKIP, 4, 0);
559 MATHB(p, MATH0, AND, PDCP_C_PLANE_SN_MASK, MATH1, 8,
561 MATHB(p, MATH1, SHLD, MATH1, MATH1, 8, 0);
563 MOVEB(p, DESCBUF, 8, MATH2, 0, 8, WAITCOMP | IMMED);
564 MATHB(p, MATH1, OR, MATH2, MATH2, 8, 0);
565 MOVEB(p, MATH2, 0, IFIFOAB1, 0, 8, IMMED);
567 MATHB(p, MATH0, AND, PDCP_C_PLANE_SN_MASK_BE, MATH1, 8,
569 MATHB(p, MATH1, SHLD, MATH1, MATH1, 8, 0);
571 MOVE(p, DESCBUF, 8, MATH2, 0, 8, WAITCOMP | IMMED);
572 MATHB(p, MATH1, OR, MATH2, MATH2, 8, 0);
573 MOVE(p, MATH2, 0, IFIFOAB1, 0, 8, IMMED);
576 if (dir == OP_TYPE_DECAP_PROTOCOL) {
577 MATHB(p, SEQINSZ, SUB, PDCP_MAC_I_LEN, MATH1, 4,
580 if (rta_sec_era > RTA_SEC_ERA_2) {
581 MATHB(p, SEQINSZ, SUB, ZERO, MATH1, 4,
584 MATHB(p, SEQINSZ, ADD, ONE, MATH1, 4,
586 MATHB(p, MATH1, SUB, ONE, MATH1, 4,
591 if (rta_sec_era > RTA_SEC_ERA_2) {
592 MATHB(p, MATH1, SUB, ZERO, VSEQINSZ, 4, 0);
593 MATHB(p, MATH1, SUB, ZERO, VSEQOUTSZ, 4, 0);
595 MATHB(p, ZERO, ADD, MATH1, VSEQINSZ, 4, 0);
596 MATHB(p, ZERO, ADD, MATH1, VSEQOUTSZ, 4, 0);
599 * Since MOVELEN is available only starting with
600 * SEC ERA 3, use poor man's MOVELEN: create a MOVE
601 * command dynamically by writing the length from M1 by
602 * OR-ing the command in the M1 register and MOVE the
603 * result into the descriptor buffer. Care must be taken
604 * wrt. the location of the command because of SEC
605 * pipelining. The actual MOVEs are written at the end
606 * of the descriptor due to calculations needed on the
607 * offset in the descriptor for the MOVE command.
609 move_cmd_read_descbuf = MOVE(p, DESCBUF, 0, MATH1, 0, 6,
611 move_cmd_write_descbuf = MOVE(p, MATH1, 0, DESCBUF, 0,
612 8, WAITCOMP | IMMED);
614 SEQFIFOSTORE(p, MSG, 0, 0, VLF);
615 ALG_OPERATION(p, OP_ALG_ALGSEL_AES,
618 dir == OP_TYPE_ENCAP_PROTOCOL ?
619 ICV_CHECK_DISABLE : ICV_CHECK_ENABLE,
622 if (rta_sec_era > RTA_SEC_ERA_2) {
623 MOVE(p, AB2, 0, OFIFO, 0, MATH1, 0);
624 SEQFIFOLOAD(p, MSGINSNOOP, 0,
625 VLF | LAST1 | LAST2 | FLUSH1);
627 SEQFIFOLOAD(p, MSGINSNOOP, 0,
628 VLF | LAST1 | LAST2 | FLUSH1);
629 SET_LABEL(p, local_offset);
631 /* Shut off automatic Info FIFO entries */
632 LOAD(p, 0, DCTRL, LDOFF_DISABLE_AUTO_NFIFO, 0, IMMED);
635 * Placeholder for MOVE command with length from
638 MOVE(p, IFIFOAB2, 0, OFIFO, 0, 0, IMMED);
640 /* Enable automatic Info FIFO entries */
641 LOAD(p, 0, DCTRL, LDOFF_ENABLE_AUTO_NFIFO, 0, IMMED);
644 if (dir == OP_TYPE_DECAP_PROTOCOL)
645 SEQFIFOLOAD(p, ICV1, 4, LAST1 | FLUSH1);
647 SEQSTORE(p, CONTEXT1, 0, 4, 0);
651 case PDCP_AUTH_TYPE_ZUC:
652 if (rta_sec_era < RTA_SEC_ERA_5) {
653 pr_err("Invalid era for selected algorithm\n");
656 /* Insert Auth Key */
657 KEY(p, KEY2, authdata->key_enc_flags, authdata->key,
658 authdata->keylen, INLINE_KEY(authdata));
659 SEQLOAD(p, MATH0, 7, 1, 0);
660 JUMP(p, 1, LOCAL_JUMP, ALL_TRUE, CALM);
661 SEQINPTR(p, 0, 1, RTO);
663 MATHB(p, MATH0, AND, PDCP_C_PLANE_SN_MASK, MATH1, 8,
665 MATHB(p, MATH1, SHLD, MATH1, MATH1, 8, 0);
667 MOVEB(p, DESCBUF, 8, MATH2, 0, 8, WAITCOMP | IMMED);
668 MATHB(p, MATH1, OR, MATH2, MATH2, 8, 0);
669 MOVEB(p, MATH2, 0, CONTEXT2, 0, 8, IMMED);
672 MATHB(p, MATH0, AND, PDCP_C_PLANE_SN_MASK_BE, MATH1, 8,
674 MATHB(p, MATH1, SHLD, MATH1, MATH1, 8, 0);
676 MOVE(p, DESCBUF, 8, MATH2, 0, 8, WAITCOMP | IMMED);
677 MATHB(p, MATH1, OR, MATH2, MATH2, 8, 0);
678 MOVE(p, MATH2, 0, CONTEXT2, 0, 8, IMMED);
680 if (dir == OP_TYPE_DECAP_PROTOCOL)
681 MATHB(p, SEQINSZ, SUB, PDCP_MAC_I_LEN, MATH1, 4,
684 MATHB(p, SEQINSZ, SUB, ZERO, MATH1, 4, 0);
686 MATHB(p, MATH1, SUB, ZERO, VSEQINSZ, 4, 0);
687 MATHB(p, MATH1, SUB, ZERO, VSEQOUTSZ, 4, 0);
688 SEQFIFOSTORE(p, MSG, 0, 0, VLF);
689 ALG_OPERATION(p, OP_ALG_ALGSEL_ZUCA,
692 dir == OP_TYPE_ENCAP_PROTOCOL ?
693 ICV_CHECK_DISABLE : ICV_CHECK_ENABLE,
695 SEQFIFOLOAD(p, MSGINSNOOP, 0, VLF | LAST1 | LAST2 | FLUSH1);
696 MOVE(p, AB1, 0, OFIFO, 0, MATH1, 0);
698 if (dir == OP_TYPE_DECAP_PROTOCOL)
699 SEQFIFOLOAD(p, ICV2, 4, LAST2);
701 SEQSTORE(p, CONTEXT2, 0, 4, 0);
706 pr_err("%s: Invalid integrity algorithm selected: %d\n",
707 "pdcp_insert_cplane_int_only_op", authdata->algtype);
711 if (rta_sec_era < RTA_SEC_ERA_3) {
712 PATCH_MOVE(p, move_cmd_read_descbuf, local_offset);
713 PATCH_MOVE(p, move_cmd_write_descbuf, local_offset);
720 pdcp_insert_cplane_enc_only_op(struct program *p,
721 bool swap __maybe_unused,
722 struct alginfo *cipherdata,
723 struct alginfo *authdata __maybe_unused,
725 unsigned char era_2_sw_hfn_ovrd __maybe_unused)
727 /* Insert Cipher Key */
728 KEY(p, KEY1, cipherdata->key_enc_flags, cipherdata->key,
729 cipherdata->keylen, INLINE_KEY(cipherdata));
731 if (rta_sec_era >= RTA_SEC_ERA_8) {
732 PROTOCOL(p, dir, OP_PCLID_LTE_PDCP_CTRL_MIXED,
733 (uint16_t)cipherdata->algtype << 8);
737 SEQLOAD(p, MATH0, 7, 1, 0);
738 JUMP(p, 1, LOCAL_JUMP, ALL_TRUE, CALM);
740 MATHB(p, MATH0, AND, PDCP_C_PLANE_SN_MASK, MATH1, 8,
743 MATHB(p, MATH0, AND, PDCP_C_PLANE_SN_MASK_BE, MATH1, 8,
745 SEQSTORE(p, MATH0, 7, 1, 0);
746 MATHB(p, MATH1, SHLD, MATH1, MATH1, 8, 0);
747 MOVE(p, DESCBUF, 8, MATH2, 0, 8, WAITCOMP | IMMED);
748 MATHB(p, MATH1, OR, MATH2, MATH2, 8, 0);
750 switch (cipherdata->algtype) {
751 case PDCP_CIPHER_TYPE_SNOW:
752 MOVE(p, MATH2, 0, CONTEXT1, 0, 8, WAITCOMP | IMMED);
754 if (rta_sec_era > RTA_SEC_ERA_2) {
755 MATHB(p, SEQINSZ, SUB, ZERO, VSEQINSZ, 4, 0);
757 MATHB(p, SEQINSZ, SUB, ONE, MATH1, 4, 0);
758 MATHB(p, MATH1, ADD, ONE, VSEQINSZ, 4, 0);
761 if (dir == OP_TYPE_ENCAP_PROTOCOL)
762 MATHB(p, SEQINSZ, ADD, PDCP_MAC_I_LEN, VSEQOUTSZ, 4,
765 MATHB(p, SEQINSZ, SUB, PDCP_MAC_I_LEN, VSEQOUTSZ, 4,
767 SEQFIFOSTORE(p, MSG, 0, 0, VLF | CONT);
768 ALG_OPERATION(p, OP_ALG_ALGSEL_SNOW_F8,
770 OP_ALG_AS_INITFINAL, ICV_CHECK_DISABLE,
771 dir == OP_TYPE_ENCAP_PROTOCOL ?
775 case PDCP_CIPHER_TYPE_AES:
776 MOVE(p, MATH2, 0, CONTEXT1, 0x10, 0x10, WAITCOMP | IMMED);
778 if (rta_sec_era > RTA_SEC_ERA_2) {
779 MATHB(p, SEQINSZ, SUB, ZERO, VSEQINSZ, 4, 0);
781 MATHB(p, SEQINSZ, SUB, ONE, MATH1, 4, 0);
782 MATHB(p, MATH1, ADD, ONE, VSEQINSZ, 4, 0);
785 if (dir == OP_TYPE_ENCAP_PROTOCOL)
786 MATHB(p, SEQINSZ, ADD, PDCP_MAC_I_LEN, VSEQOUTSZ, 4,
789 MATHB(p, SEQINSZ, SUB, PDCP_MAC_I_LEN, VSEQOUTSZ, 4,
792 SEQFIFOSTORE(p, MSG, 0, 0, VLF | CONT);
793 ALG_OPERATION(p, OP_ALG_ALGSEL_AES,
797 dir == OP_TYPE_ENCAP_PROTOCOL ?
801 case PDCP_CIPHER_TYPE_ZUC:
802 if (rta_sec_era < RTA_SEC_ERA_5) {
803 pr_err("Invalid era for selected algorithm\n");
807 MOVE(p, MATH2, 0, CONTEXT1, 0, 0x08, IMMED);
808 MOVE(p, MATH2, 0, CONTEXT1, 0x08, 0x08, WAITCOMP | IMMED);
809 MATHB(p, SEQINSZ, SUB, ZERO, VSEQINSZ, 4, 0);
810 if (dir == OP_TYPE_ENCAP_PROTOCOL)
811 MATHB(p, SEQINSZ, ADD, PDCP_MAC_I_LEN, VSEQOUTSZ, 4,
814 MATHB(p, SEQINSZ, SUB, PDCP_MAC_I_LEN, VSEQOUTSZ, 4,
817 SEQFIFOSTORE(p, MSG, 0, 0, VLF | CONT);
818 ALG_OPERATION(p, OP_ALG_ALGSEL_ZUCE,
822 dir == OP_TYPE_ENCAP_PROTOCOL ?
827 pr_err("%s: Invalid encrypt algorithm selected: %d\n",
828 "pdcp_insert_cplane_enc_only_op", cipherdata->algtype);
832 if (dir == OP_TYPE_ENCAP_PROTOCOL) {
833 SEQFIFOLOAD(p, MSG1, 0, VLF);
834 FIFOLOAD(p, MSG1, PDCP_NULL_INT_MAC_I_VAL, 4,
835 LAST1 | FLUSH1 | IMMED);
837 SEQFIFOLOAD(p, MSG1, 0, VLF | LAST1 | FLUSH1);
838 MOVE(p, OFIFO, 0, MATH1, 4, PDCP_MAC_I_LEN, WAITCOMP | IMMED);
839 MATHB(p, MATH1, XOR, PDCP_NULL_INT_MAC_I_VAL, NONE, 4, IMMED2);
840 JUMP(p, PDCP_NULL_INT_ICV_CHECK_FAILED_STATUS,
841 HALT_STATUS, ALL_FALSE, MATH_Z);
848 pdcp_insert_cplane_acc_op(struct program *p,
849 bool swap __maybe_unused,
850 struct alginfo *cipherdata,
851 struct alginfo *authdata,
853 unsigned char era_2_hfn_ovrd __maybe_unused)
855 /* Insert Auth Key */
856 KEY(p, KEY2, authdata->key_enc_flags, authdata->key, authdata->keylen,
857 INLINE_KEY(authdata));
859 /* Insert Cipher Key */
860 KEY(p, KEY1, cipherdata->key_enc_flags, cipherdata->key,
861 cipherdata->keylen, INLINE_KEY(cipherdata));
862 PROTOCOL(p, dir, OP_PCLID_LTE_PDCP_CTRL, (uint16_t)cipherdata->algtype);
868 pdcp_insert_cplane_snow_aes_op(struct program *p,
869 bool swap __maybe_unused,
870 struct alginfo *cipherdata,
871 struct alginfo *authdata,
873 unsigned char era_2_sw_hfn_ovrd)
875 LABEL(back_to_sd_offset);
878 LABEL(jump_to_beginning);
879 LABEL(fifo_load_mac_i_offset);
880 REFERENCE(seqin_ptr_read);
881 REFERENCE(seqin_ptr_write);
882 REFERENCE(seq_out_read);
883 REFERENCE(jump_back_to_sd_cmd);
884 REFERENCE(move_mac_i_to_desc_buf);
886 if (rta_sec_era >= RTA_SEC_ERA_8) {
887 KEY(p, KEY1, cipherdata->key_enc_flags, cipherdata->key,
888 cipherdata->keylen, INLINE_KEY(cipherdata));
889 KEY(p, KEY2, authdata->key_enc_flags, authdata->key,
890 authdata->keylen, INLINE_KEY(authdata));
892 PROTOCOL(p, dir, OP_PCLID_LTE_PDCP_CTRL_MIXED,
893 ((uint16_t)cipherdata->algtype << 8) |
894 (uint16_t)authdata->algtype);
899 SEQLOAD(p, MATH0, 7, 1, 0);
900 JUMP(p, 1, LOCAL_JUMP, ALL_TRUE, CALM);
902 MATHB(p, MATH0, AND, PDCP_C_PLANE_SN_MASK, MATH1, 8,
905 MATHB(p, MATH0, AND, PDCP_C_PLANE_SN_MASK_BE, MATH1, 8,
907 MATHB(p, MATH1, SHLD, MATH1, MATH1, 8, 0);
908 MOVE(p, DESCBUF, 4, MATH2, 0, 0x08, WAITCOMP | IMMED);
909 MATHB(p, MATH1, OR, MATH2, MATH2, 8, 0);
910 SEQSTORE(p, MATH0, 7, 1, 0);
911 if (dir == OP_TYPE_ENCAP_PROTOCOL) {
912 if (rta_sec_era > RTA_SEC_ERA_2 ||
913 (rta_sec_era == RTA_SEC_ERA_2 &&
914 era_2_sw_hfn_ovrd == 0)) {
915 SEQINPTR(p, 0, 1, RTO);
917 SEQINPTR(p, 0, 5, RTO);
918 SEQFIFOLOAD(p, SKIP, 4, 0);
920 KEY(p, KEY1, authdata->key_enc_flags, authdata->key,
921 authdata->keylen, INLINE_KEY(authdata));
922 MOVE(p, MATH2, 0, IFIFOAB1, 0, 0x08, IMMED);
924 if (rta_sec_era > RTA_SEC_ERA_2) {
925 MATHB(p, SEQINSZ, SUB, ZERO, VSEQINSZ, 4, 0);
926 MATHB(p, SEQINSZ, SUB, ZERO, MATH1, 4, 0);
927 MATHB(p, VSEQINSZ, ADD, PDCP_MAC_I_LEN - 1, VSEQOUTSZ,
930 MATHB(p, SEQINSZ, SUB, MATH3, VSEQINSZ, 4, 0);
931 MATHB(p, VSEQINSZ, ADD, PDCP_MAC_I_LEN - 1, VSEQOUTSZ,
934 * Note: Although the calculations below might seem a
935 * little off, the logic is the following:
937 * - SEQ IN PTR RTO below needs the full length of the
938 * frame; in case of P4080_REV_2_HFN_OV_WORKAROUND,
939 * this means the length of the frame to be processed
940 * + 4 bytes (the HFN override flag and value).
941 * The length of the frame to be processed minus 1
942 * byte is in the VSIL register (because
943 * VSIL = SIL + 3, due to 1 byte, the header being
944 * already written by the SEQ STORE above). So for
945 * calculating the length to use in RTO, I add one
946 * to the VSIL value in order to obtain the total
947 * frame length. This helps in case of P4080 which
948 * can have the value 0 as an operand in a MATH
949 * command only as SRC1 When the HFN override
950 * workaround is not enabled, the length of the
951 * frame is given by the SIL register; the
952 * calculation is similar to the one in the SEC 4.2
955 if (era_2_sw_hfn_ovrd)
956 MATHB(p, VSEQOUTSZ, ADD, ONE, MATH1, 4,
959 MATHB(p, SEQINSZ, ADD, MATH3, MATH1, 4,
963 * Placeholder for filling the length in
964 * SEQIN PTR RTO below
966 seqin_ptr_read = MOVE(p, DESCBUF, 0, MATH1, 0, 6, IMMED);
967 seqin_ptr_write = MOVE(p, MATH1, 0, DESCBUF, 0, 8,
969 ALG_OPERATION(p, OP_ALG_ALGSEL_AES,
974 SEQFIFOLOAD(p, MSG1, 0, VLF | LAST1 | FLUSH1);
975 MOVE(p, CONTEXT1, 0, MATH3, 0, 4, WAITCOMP | IMMED);
976 if (rta_sec_era <= RTA_SEC_ERA_3)
977 LOAD(p, CLRW_CLR_C1KEY |
984 LOAD(p, CLRW_RESET_CLS1_CHA |
992 if (rta_sec_era <= RTA_SEC_ERA_3)
993 LOAD(p, CCTRL_RESET_CHA_ALL, CCTRL, 0, 4, IMMED);
995 KEY(p, KEY1, cipherdata->key_enc_flags, cipherdata->key,
996 cipherdata->keylen, INLINE_KEY(cipherdata));
997 SET_LABEL(p, local_offset);
998 MOVE(p, MATH2, 0, CONTEXT1, 0, 8, IMMED);
999 SEQINPTR(p, 0, 0, RTO);
1001 if (rta_sec_era == RTA_SEC_ERA_2 && era_2_sw_hfn_ovrd) {
1002 SEQFIFOLOAD(p, SKIP, 5, 0);
1003 MATHB(p, SEQINSZ, ADD, ONE, SEQINSZ, 4, 0);
1006 MATHB(p, SEQINSZ, SUB, ONE, VSEQINSZ, 4, 0);
1007 ALG_OPERATION(p, OP_ALG_ALGSEL_SNOW_F8,
1009 OP_ALG_AS_INITFINAL,
1012 SEQFIFOSTORE(p, MSG, 0, 0, VLF);
1014 if (rta_sec_era > RTA_SEC_ERA_2 ||
1015 (rta_sec_era == RTA_SEC_ERA_2 &&
1016 era_2_sw_hfn_ovrd == 0))
1017 SEQFIFOLOAD(p, SKIP, 1, 0);
1019 SEQFIFOLOAD(p, MSG1, 0, VLF);
1020 MOVE(p, MATH3, 0, IFIFOAB1, 0, 4, LAST1 | FLUSH1 | IMMED);
1021 PATCH_MOVE(p, seqin_ptr_read, local_offset);
1022 PATCH_MOVE(p, seqin_ptr_write, local_offset);
1024 MOVE(p, MATH2, 0, CONTEXT1, 0, 8, IMMED);
1026 if (rta_sec_era >= RTA_SEC_ERA_5)
1027 MOVE(p, CONTEXT1, 0, CONTEXT2, 0, 8, IMMED);
1029 if (rta_sec_era > RTA_SEC_ERA_2)
1030 MATHB(p, SEQINSZ, SUB, ZERO, VSEQINSZ, 4, 0);
1032 MATHB(p, SEQINSZ, SUB, MATH3, VSEQINSZ, 4, 0);
1034 MATHB(p, SEQINSZ, SUB, PDCP_MAC_I_LEN, VSEQOUTSZ, 4, IMMED2);
1036 * TODO: To be changed when proper support is added in RTA (can't load a
1037 * command that is also written by RTA (or patch it for that matter).
1038 * Change when proper RTA support is added.
1041 WORD(p, 0x168B0004);
1043 WORD(p, 0x16880404);
1045 jump_back_to_sd_cmd = JUMP(p, 0, LOCAL_JUMP, ALL_TRUE, 0);
1047 * Placeholder for command reading the SEQ OUT command in
1048 * JD. Done for rereading the decrypted data and performing
1049 * the integrity check
1052 * TODO: RTA currently doesn't support patching of length of a MOVE command
1053 * Thus, it is inserted as a raw word, as per PS setting.
1056 seq_out_read = MOVE(p, DESCBUF, 0, MATH1, 0, 20,
1059 seq_out_read = MOVE(p, DESCBUF, 0, MATH1, 0, 16,
1062 MATHB(p, MATH1, XOR, CMD_SEQ_IN_PTR ^ CMD_SEQ_OUT_PTR, MATH1, 4,
1064 /* Placeholder for overwriting the SEQ IN with SEQ OUT */
1066 * TODO: RTA currently doesn't support patching of length of a MOVE command
1067 * Thus, it is inserted as a raw word, as per PS setting.
1070 MOVE(p, MATH1, 0, DESCBUF, 0, 24, IMMED);
1072 MOVE(p, MATH1, 0, DESCBUF, 0, 20, IMMED);
1074 KEY(p, KEY1, cipherdata->key_enc_flags, cipherdata->key,
1075 cipherdata->keylen, INLINE_KEY(cipherdata));
1077 if (rta_sec_era >= RTA_SEC_ERA_4)
1078 MOVE(p, CONTEXT1, 0, CONTEXT2, 0, 8, IMMED);
1080 MOVE(p, CONTEXT1, 0, MATH3, 0, 8, IMMED);
1082 ALG_OPERATION(p, OP_ALG_ALGSEL_SNOW_F8,
1084 OP_ALG_AS_INITFINAL,
1087 SEQFIFOSTORE(p, MSG, 0, 0, VLF | CONT);
1088 SEQFIFOLOAD(p, MSG1, 0, VLF | LAST1 | FLUSH1);
1090 if (rta_sec_era <= RTA_SEC_ERA_3)
1091 move_mac_i_to_desc_buf = MOVE(p, OFIFO, 0, DESCBUF, 0,
1092 4, WAITCOMP | IMMED);
1094 MOVE(p, OFIFO, 0, MATH3, 0, 4, IMMED);
1096 if (rta_sec_era <= RTA_SEC_ERA_3)
1097 LOAD(p, CCTRL_RESET_CHA_ALL, CCTRL, 0, 4, IMMED);
1099 LOAD(p, CLRW_RESET_CLS1_CHA |
1107 KEY(p, KEY1, authdata->key_enc_flags, authdata->key,
1108 authdata->keylen, INLINE_KEY(authdata));
1110 * Placeholder for jump in SD for executing the new SEQ IN PTR
1111 * command (which is actually the old SEQ OUT PTR command
1112 * copied over from JD.
1114 SET_LABEL(p, jump_to_beginning);
1115 JUMP(p, 1 - jump_to_beginning, LOCAL_JUMP, ALL_TRUE, 0);
1116 SET_LABEL(p, back_to_sd_offset);
1117 ALG_OPERATION(p, OP_ALG_ALGSEL_AES,
1119 OP_ALG_AS_INITFINAL,
1123 /* Read the # of bytes written in the output buffer + 1 (HDR) */
1124 MATHB(p, VSEQOUTSZ, ADD, ONE, VSEQINSZ, 4, 0);
1126 if (rta_sec_era <= RTA_SEC_ERA_3)
1127 MOVE(p, MATH3, 0, IFIFOAB1, 0, 8, IMMED);
1129 MOVE(p, CONTEXT2, 0, IFIFOAB1, 0, 8, IMMED);
1131 if (rta_sec_era == RTA_SEC_ERA_2 && era_2_sw_hfn_ovrd)
1132 SEQFIFOLOAD(p, SKIP, 4, 0);
1134 SEQFIFOLOAD(p, MSG1, 0, VLF | LAST1 | FLUSH1);
1136 if (rta_sec_era >= RTA_SEC_ERA_4) {
1137 LOAD(p, NFIFOENTRY_STYPE_ALTSOURCE |
1138 NFIFOENTRY_DEST_CLASS1 |
1139 NFIFOENTRY_DTYPE_ICV |
1141 NFIFOENTRY_FC1 | 4, NFIFO_SZL, 0, 4, IMMED);
1142 MOVE(p, MATH3, 0, ALTSOURCE, 0, 4, IMMED);
1144 SET_LABEL(p, fifo_load_mac_i_offset);
1145 FIFOLOAD(p, ICV1, fifo_load_mac_i_offset, 4,
1146 LAST1 | FLUSH1 | IMMED);
1149 SET_LABEL(p, end_desc);
1152 PATCH_MOVE(p, seq_out_read, end_desc + 1);
1153 PATCH_JUMP(p, jump_back_to_sd_cmd,
1154 back_to_sd_offset + jump_back_to_sd_cmd - 5);
1156 if (rta_sec_era <= RTA_SEC_ERA_3)
1157 PATCH_MOVE(p, move_mac_i_to_desc_buf,
1158 fifo_load_mac_i_offset + 1);
1160 PATCH_MOVE(p, seq_out_read, end_desc + 2);
1161 PATCH_JUMP(p, jump_back_to_sd_cmd,
1162 back_to_sd_offset + jump_back_to_sd_cmd - 5);
1164 if (rta_sec_era <= RTA_SEC_ERA_3)
1165 PATCH_MOVE(p, move_mac_i_to_desc_buf,
1166 fifo_load_mac_i_offset + 1);
1174 pdcp_insert_cplane_aes_snow_op(struct program *p,
1175 bool swap __maybe_unused,
1176 struct alginfo *cipherdata,
1177 struct alginfo *authdata,
1179 unsigned char era_2_sw_hfn_ovrd __maybe_unused)
1181 KEY(p, KEY1, cipherdata->key_enc_flags, cipherdata->key,
1182 cipherdata->keylen, INLINE_KEY(cipherdata));
1183 KEY(p, KEY2, authdata->key_enc_flags, authdata->key, authdata->keylen,
1184 INLINE_KEY(authdata));
1186 if (rta_sec_era >= RTA_SEC_ERA_8) {
1187 PROTOCOL(p, dir, OP_PCLID_LTE_PDCP_CTRL_MIXED,
1188 ((uint16_t)cipherdata->algtype << 8) |
1189 (uint16_t)authdata->algtype);
1194 if (dir == OP_TYPE_ENCAP_PROTOCOL)
1195 MATHB(p, SEQINSZ, SUB, ONE, VSEQINSZ, 4, 0);
1197 SEQLOAD(p, MATH0, 7, 1, 0);
1198 JUMP(p, 1, LOCAL_JUMP, ALL_TRUE, CALM);
1199 MOVE(p, MATH0, 7, IFIFOAB2, 0, 1, IMMED);
1201 MATHB(p, MATH0, AND, PDCP_C_PLANE_SN_MASK, MATH1, 8,
1204 MATHB(p, MATH0, AND, PDCP_C_PLANE_SN_MASK_BE, MATH1, 8,
1207 SEQSTORE(p, MATH0, 7, 1, 0);
1208 MATHB(p, MATH1, SHLD, MATH1, MATH1, 8, 0);
1209 MOVE(p, DESCBUF, 4, MATH2, 0, 8, WAITCOMP | IMMED);
1210 MATHB(p, MATH1, OR, MATH2, MATH1, 8, 0);
1211 MOVE(p, MATH1, 0, CONTEXT1, 16, 8, IMMED);
1212 MOVE(p, MATH1, 0, CONTEXT2, 0, 4, IMMED);
1213 if (swap == false) {
1214 MATHB(p, MATH1, AND, lower_32_bits(PDCP_BEARER_MASK), MATH2, 4,
1216 MATHB(p, MATH1, AND, upper_32_bits(PDCP_DIR_MASK), MATH3, 4,
1219 MATHB(p, MATH1, AND, lower_32_bits(PDCP_BEARER_MASK_BE), MATH2,
1221 MATHB(p, MATH1, AND, upper_32_bits(PDCP_DIR_MASK_BE), MATH3,
1224 MATHB(p, MATH3, SHLD, MATH3, MATH3, 8, 0);
1225 MOVE(p, MATH2, 4, OFIFO, 0, 12, IMMED);
1226 MOVE(p, OFIFO, 0, CONTEXT2, 4, 12, IMMED);
1227 if (dir == OP_TYPE_ENCAP_PROTOCOL) {
1228 MATHB(p, SEQINSZ, ADD, PDCP_MAC_I_LEN, VSEQOUTSZ, 4, IMMED2);
1230 MATHB(p, SEQINSZ, SUB, PDCP_MAC_I_LEN, MATH1, 4, IMMED2);
1232 MATHB(p, ZERO, ADD, MATH1, VSEQOUTSZ, 4, 0);
1233 MATHB(p, ZERO, ADD, MATH1, VSEQINSZ, 4, 0);
1236 if (dir == OP_TYPE_ENCAP_PROTOCOL)
1237 SEQFIFOSTORE(p, MSG, 0, 0, VLF);
1239 SEQFIFOSTORE(p, MSG, 0, 0, VLF | CONT);
1241 ALG_OPERATION(p, OP_ALG_ALGSEL_SNOW_F9,
1243 OP_ALG_AS_INITFINAL,
1244 dir == OP_TYPE_ENCAP_PROTOCOL ?
1245 ICV_CHECK_DISABLE : ICV_CHECK_ENABLE,
1247 ALG_OPERATION(p, OP_ALG_ALGSEL_AES,
1249 OP_ALG_AS_INITFINAL,
1251 dir == OP_TYPE_ENCAP_PROTOCOL ? DIR_ENC : DIR_DEC);
1253 if (dir == OP_TYPE_ENCAP_PROTOCOL) {
1254 SEQFIFOLOAD(p, MSGINSNOOP, 0, VLF | LAST2);
1255 MOVE(p, CONTEXT2, 0, IFIFOAB1, 0, 4, LAST1 | FLUSH1 | IMMED);
1257 SEQFIFOLOAD(p, MSGOUTSNOOP, 0, VLF | LAST2);
1258 SEQFIFOLOAD(p, MSG1, 4, LAST1 | FLUSH1);
1259 JUMP(p, 1, LOCAL_JUMP, ALL_TRUE, CLASS1 | NOP | NIFP);
1261 if (rta_sec_era >= RTA_SEC_ERA_6)
1262 LOAD(p, 0, DCTRL, 0, LDLEN_RST_CHA_OFIFO_PTR, IMMED);
1264 MOVE(p, OFIFO, 0, MATH0, 0, 4, WAITCOMP | IMMED);
1266 NFIFOADD(p, IFIFO, ICV2, 4, LAST2);
1268 if (rta_sec_era <= RTA_SEC_ERA_2) {
1269 /* Shut off automatic Info FIFO entries */
1270 LOAD(p, 0, DCTRL, LDOFF_DISABLE_AUTO_NFIFO, 0, IMMED);
1271 MOVE(p, MATH0, 0, IFIFOAB2, 0, 4, WAITCOMP | IMMED);
1273 MOVE(p, MATH0, 0, IFIFO, 0, 4, WAITCOMP | IMMED);
1281 pdcp_insert_cplane_snow_zuc_op(struct program *p,
1282 bool swap __maybe_unused,
1283 struct alginfo *cipherdata,
1284 struct alginfo *authdata,
1286 unsigned char era_2_sw_hfn_ovrd __maybe_unused)
1289 REFERENCE(pkeyjump);
1291 if (rta_sec_era < RTA_SEC_ERA_5) {
1292 pr_err("Invalid era for selected algorithm\n");
1296 pkeyjump = JUMP(p, keyjump, LOCAL_JUMP, ALL_TRUE, SHRD | SELF | BOTH);
1297 KEY(p, KEY1, cipherdata->key_enc_flags, cipherdata->key,
1298 cipherdata->keylen, INLINE_KEY(cipherdata));
1299 KEY(p, KEY2, authdata->key_enc_flags, authdata->key, authdata->keylen,
1300 INLINE_KEY(authdata));
1302 SET_LABEL(p, keyjump);
1304 if (rta_sec_era >= RTA_SEC_ERA_8) {
1305 PROTOCOL(p, dir, OP_PCLID_LTE_PDCP_CTRL_MIXED,
1306 ((uint16_t)cipherdata->algtype << 8) |
1307 (uint16_t)authdata->algtype);
1311 SEQLOAD(p, MATH0, 7, 1, 0);
1312 JUMP(p, 1, LOCAL_JUMP, ALL_TRUE, CALM);
1313 MOVE(p, MATH0, 7, IFIFOAB2, 0, 1, IMMED);
1315 MATHB(p, MATH0, AND, PDCP_C_PLANE_SN_MASK, MATH1, 8,
1318 MATHB(p, MATH0, AND, PDCP_C_PLANE_SN_MASK, MATH1, 8,
1321 MATHB(p, MATH1, SHLD, MATH1, MATH1, 8, 0);
1322 MOVE(p, DESCBUF, 4, MATH2, 0, 8, WAITCOMP | IMMED);
1323 MATHB(p, MATH1, OR, MATH2, MATH2, 8, 0);
1324 MOVE(p, MATH2, 0, CONTEXT1, 0, 8, IMMED);
1325 MOVE(p, MATH2, 0, CONTEXT2, 0, 8, WAITCOMP | IMMED);
1327 if (dir == OP_TYPE_ENCAP_PROTOCOL)
1328 MATHB(p, SEQINSZ, ADD, PDCP_MAC_I_LEN, VSEQOUTSZ, 4, IMMED2);
1330 MATHB(p, SEQINSZ, SUB, PDCP_MAC_I_LEN, VSEQOUTSZ, 4, IMMED2);
1332 MATHB(p, SEQINSZ, SUB, ZERO, VSEQINSZ, 4, 0);
1333 SEQSTORE(p, MATH0, 7, 1, 0);
1335 if (dir == OP_TYPE_ENCAP_PROTOCOL) {
1336 SEQFIFOSTORE(p, MSG, 0, 0, VLF);
1337 SEQFIFOLOAD(p, MSGINSNOOP, 0, VLF | LAST2);
1339 SEQFIFOSTORE(p, MSG, 0, 0, VLF | CONT);
1340 SEQFIFOLOAD(p, MSGOUTSNOOP, 0, VLF | LAST1 | FLUSH1);
1343 ALG_OPERATION(p, OP_ALG_ALGSEL_ZUCA,
1345 OP_ALG_AS_INITFINAL,
1346 dir == OP_TYPE_ENCAP_PROTOCOL ?
1347 ICV_CHECK_DISABLE : ICV_CHECK_ENABLE,
1350 ALG_OPERATION(p, OP_ALG_ALGSEL_SNOW_F8,
1352 OP_ALG_AS_INITFINAL,
1354 dir == OP_TYPE_ENCAP_PROTOCOL ? DIR_ENC : DIR_DEC);
1355 if (dir == OP_TYPE_ENCAP_PROTOCOL) {
1356 MOVE(p, CONTEXT2, 0, IFIFOAB1, 0, 4, LAST1 | FLUSH1 | IMMED);
1359 MOVE(p, OFIFO, 0, MATH0, 0, 4, IMMED);
1360 LOAD(p, NFIFOENTRY_STYPE_ALTSOURCE |
1361 NFIFOENTRY_DEST_CLASS2 |
1362 NFIFOENTRY_DTYPE_ICV |
1363 NFIFOENTRY_LC2 | 4, NFIFO_SZL, 0, 4, IMMED);
1364 MOVE(p, MATH0, 0, ALTSOURCE, 0, 4, WAITCOMP | IMMED);
1367 /* Reset ZUCA mode and done interrupt */
1368 LOAD(p, CLRW_CLR_C2MODE, CLRW, 0, 4, IMMED);
1369 LOAD(p, CIRQ_ZADI, ICTRL, 0, 4, IMMED);
1371 PATCH_JUMP(p, pkeyjump, keyjump);
1376 pdcp_insert_cplane_aes_zuc_op(struct program *p,
1377 bool swap __maybe_unused,
1378 struct alginfo *cipherdata,
1379 struct alginfo *authdata,
1381 unsigned char era_2_sw_hfn_ovrd __maybe_unused)
1384 REFERENCE(pkeyjump);
1386 if (rta_sec_era < RTA_SEC_ERA_5) {
1387 pr_err("Invalid era for selected algorithm\n");
1391 pkeyjump = JUMP(p, keyjump, LOCAL_JUMP, ALL_TRUE, SHRD | SELF | BOTH);
1392 KEY(p, KEY1, cipherdata->key_enc_flags, cipherdata->key,
1393 cipherdata->keylen, INLINE_KEY(cipherdata));
1394 KEY(p, KEY2, authdata->key_enc_flags, authdata->key, authdata->keylen,
1395 INLINE_KEY(authdata));
1397 if (rta_sec_era >= RTA_SEC_ERA_8) {
1398 PROTOCOL(p, dir, OP_PCLID_LTE_PDCP_CTRL_MIXED,
1399 ((uint16_t)cipherdata->algtype << 8) |
1400 (uint16_t)authdata->algtype);
1405 SET_LABEL(p, keyjump);
1406 SEQLOAD(p, MATH0, 7, 1, 0);
1407 JUMP(p, 1, LOCAL_JUMP, ALL_TRUE, CALM);
1408 MOVE(p, MATH0, 7, IFIFOAB2, 0, 1, IMMED);
1410 MATHB(p, MATH0, AND, PDCP_C_PLANE_SN_MASK, MATH1, 8,
1413 MATHB(p, MATH0, AND, PDCP_C_PLANE_SN_MASK, MATH1, 8,
1416 MATHB(p, MATH1, SHLD, MATH1, MATH1, 8, 0);
1417 MOVE(p, DESCBUF, 4, MATH2, 0, 8, WAITCOMP | IMMED);
1418 MATHB(p, MATH1, OR, MATH2, MATH2, 8, 0);
1419 MOVE(p, MATH2, 0, CONTEXT1, 16, 8, IMMED);
1420 MOVE(p, MATH2, 0, CONTEXT2, 0, 8, WAITCOMP | IMMED);
1422 if (dir == OP_TYPE_ENCAP_PROTOCOL)
1423 MATHB(p, SEQINSZ, ADD, PDCP_MAC_I_LEN, VSEQOUTSZ, 4, IMMED2);
1425 MATHB(p, SEQINSZ, SUB, PDCP_MAC_I_LEN, VSEQOUTSZ, 4, IMMED2);
1427 MATHB(p, SEQINSZ, SUB, ZERO, VSEQINSZ, 4, 0);
1428 SEQSTORE(p, MATH0, 7, 1, 0);
1430 if (dir == OP_TYPE_ENCAP_PROTOCOL) {
1431 SEQFIFOSTORE(p, MSG, 0, 0, VLF);
1432 SEQFIFOLOAD(p, MSGINSNOOP, 0, VLF | LAST2);
1434 SEQFIFOSTORE(p, MSG, 0, 0, VLF | CONT);
1435 SEQFIFOLOAD(p, MSGOUTSNOOP, 0, VLF | LAST1 | FLUSH1);
1438 ALG_OPERATION(p, OP_ALG_ALGSEL_ZUCA,
1440 OP_ALG_AS_INITFINAL,
1441 dir == OP_TYPE_ENCAP_PROTOCOL ?
1442 ICV_CHECK_DISABLE : ICV_CHECK_ENABLE,
1445 ALG_OPERATION(p, OP_ALG_ALGSEL_AES,
1447 OP_ALG_AS_INITFINAL,
1449 dir == OP_TYPE_ENCAP_PROTOCOL ? DIR_ENC : DIR_DEC);
1451 if (dir == OP_TYPE_ENCAP_PROTOCOL) {
1452 MOVE(p, CONTEXT2, 0, IFIFOAB1, 0, 4, LAST1 | FLUSH1 | IMMED);
1455 MOVE(p, OFIFO, 0, MATH0, 0, 4, IMMED);
1457 LOAD(p, NFIFOENTRY_STYPE_ALTSOURCE |
1458 NFIFOENTRY_DEST_CLASS2 |
1459 NFIFOENTRY_DTYPE_ICV |
1460 NFIFOENTRY_LC2 | 4, NFIFO_SZL, 0, 4, IMMED);
1461 MOVE(p, MATH0, 0, ALTSOURCE, 0, 4, WAITCOMP | IMMED);
1464 /* Reset ZUCA mode and done interrupt */
1465 LOAD(p, CLRW_CLR_C2MODE, CLRW, 0, 4, IMMED);
1466 LOAD(p, CIRQ_ZADI, ICTRL, 0, 4, IMMED);
1468 PATCH_JUMP(p, pkeyjump, keyjump);
1474 pdcp_insert_cplane_zuc_snow_op(struct program *p,
1475 bool swap __maybe_unused,
1476 struct alginfo *cipherdata,
1477 struct alginfo *authdata,
1479 unsigned char era_2_sw_hfn_ovrd __maybe_unused)
1482 REFERENCE(pkeyjump);
1484 if (rta_sec_era < RTA_SEC_ERA_5) {
1485 pr_err("Invalid era for selected algorithm\n");
1489 pkeyjump = JUMP(p, keyjump, LOCAL_JUMP, ALL_TRUE, SHRD | SELF | BOTH);
1490 KEY(p, KEY1, cipherdata->key_enc_flags, cipherdata->key,
1491 cipherdata->keylen, INLINE_KEY(cipherdata));
1492 KEY(p, KEY2, authdata->key_enc_flags, authdata->key, authdata->keylen,
1493 INLINE_KEY(authdata));
1495 if (rta_sec_era >= RTA_SEC_ERA_8) {
1496 PROTOCOL(p, dir, OP_PCLID_LTE_PDCP_CTRL_MIXED,
1497 ((uint16_t)cipherdata->algtype << 8) |
1498 (uint16_t)authdata->algtype);
1503 SET_LABEL(p, keyjump);
1504 SEQLOAD(p, MATH0, 7, 1, 0);
1505 JUMP(p, 1, LOCAL_JUMP, ALL_TRUE, CALM);
1506 MOVE(p, MATH0, 7, IFIFOAB2, 0, 1, IMMED);
1508 MATHB(p, MATH0, AND, PDCP_C_PLANE_SN_MASK, MATH1, 8,
1511 MATHB(p, MATH0, AND, PDCP_C_PLANE_SN_MASK, MATH1, 8,
1514 MATHB(p, MATH1, SHLD, MATH1, MATH1, 8, 0);
1515 MOVE(p, DESCBUF, 4, MATH2, 0, 8, WAITCOMP | IMMED);
1516 MATHB(p, MATH1, OR, MATH2, MATH1, 8, 0);
1517 MOVE(p, MATH1, 0, CONTEXT1, 0, 8, IMMED);
1518 MOVE(p, MATH1, 0, CONTEXT2, 0, 4, IMMED);
1519 if (swap == false) {
1520 MATHB(p, MATH1, AND, lower_32_bits(PDCP_BEARER_MASK), MATH2,
1522 MATHB(p, MATH1, AND, upper_32_bits(PDCP_DIR_MASK), MATH3,
1525 MATHB(p, MATH1, AND, lower_32_bits(PDCP_BEARER_MASK_BE), MATH2,
1527 MATHB(p, MATH1, AND, upper_32_bits(PDCP_DIR_MASK_BE), MATH3,
1530 MATHB(p, MATH3, SHLD, MATH3, MATH3, 8, 0);
1531 MOVE(p, MATH2, 4, OFIFO, 0, 12, IMMED);
1532 MOVE(p, OFIFO, 0, CONTEXT2, 4, 12, IMMED);
1534 if (dir == OP_TYPE_ENCAP_PROTOCOL) {
1535 MATHB(p, SEQINSZ, ADD, PDCP_MAC_I_LEN, VSEQOUTSZ, 4, IMMED2);
1536 MATHB(p, SEQINSZ, SUB, ZERO, VSEQINSZ, 4, 0);
1538 MATHB(p, SEQINSZ, SUB, PDCP_MAC_I_LEN, VSEQOUTSZ, 4, IMMED2);
1539 MATHB(p, VSEQOUTSZ, SUB, ZERO, VSEQINSZ, 4, 0);
1542 SEQSTORE(p, MATH0, 7, 1, 0);
1544 if (dir == OP_TYPE_ENCAP_PROTOCOL) {
1545 SEQFIFOSTORE(p, MSG, 0, 0, VLF);
1546 SEQFIFOLOAD(p, MSGINSNOOP, 0, VLF | LAST2);
1548 SEQFIFOSTORE(p, MSG, 0, 0, VLF | CONT);
1549 SEQFIFOLOAD(p, MSGOUTSNOOP, 0, VLF | LAST2);
1552 ALG_OPERATION(p, OP_ALG_ALGSEL_SNOW_F9,
1554 OP_ALG_AS_INITFINAL,
1555 dir == OP_TYPE_ENCAP_PROTOCOL ?
1556 ICV_CHECK_DISABLE : ICV_CHECK_ENABLE,
1559 ALG_OPERATION(p, OP_ALG_ALGSEL_ZUCE,
1561 OP_ALG_AS_INITFINAL,
1563 dir == OP_TYPE_ENCAP_PROTOCOL ? DIR_ENC : DIR_DEC);
1565 if (dir == OP_TYPE_ENCAP_PROTOCOL) {
1566 MOVE(p, CONTEXT2, 0, IFIFOAB1, 0, 4, LAST1 | FLUSH1 | IMMED);
1568 SEQFIFOLOAD(p, MSG1, 4, LAST1 | FLUSH1);
1569 JUMP(p, 1, LOCAL_JUMP, ALL_TRUE, CLASS1 | NOP | NIFP);
1571 if (rta_sec_era >= RTA_SEC_ERA_6)
1573 * For SEC ERA 6, there's a problem with the OFIFO
1574 * pointer, and thus it needs to be reset here before
1577 LOAD(p, 0, DCTRL, 0, LDLEN_RST_CHA_OFIFO_PTR, IMMED);
1579 /* Put ICV to M0 before sending it to C2 for comparison. */
1580 MOVE(p, OFIFO, 0, MATH0, 0, 4, WAITCOMP | IMMED);
1582 LOAD(p, NFIFOENTRY_STYPE_ALTSOURCE |
1583 NFIFOENTRY_DEST_CLASS2 |
1584 NFIFOENTRY_DTYPE_ICV |
1585 NFIFOENTRY_LC2 | 4, NFIFO_SZL, 0, 4, IMMED);
1586 MOVE(p, MATH0, 0, ALTSOURCE, 0, 4, IMMED);
1589 PATCH_JUMP(p, pkeyjump, keyjump);
1594 pdcp_insert_cplane_zuc_aes_op(struct program *p,
1595 bool swap __maybe_unused,
1596 struct alginfo *cipherdata,
1597 struct alginfo *authdata,
1599 unsigned char era_2_sw_hfn_ovrd __maybe_unused)
1601 if (rta_sec_era < RTA_SEC_ERA_5) {
1602 pr_err("Invalid era for selected algorithm\n");
1606 if (rta_sec_era >= RTA_SEC_ERA_8) {
1607 KEY(p, KEY1, cipherdata->key_enc_flags, cipherdata->key,
1608 cipherdata->keylen, INLINE_KEY(cipherdata));
1609 KEY(p, KEY2, authdata->key_enc_flags, authdata->key,
1610 authdata->keylen, INLINE_KEY(authdata));
1612 PROTOCOL(p, dir, OP_PCLID_LTE_PDCP_CTRL_MIXED,
1613 ((uint16_t)cipherdata->algtype << 8) |
1614 (uint16_t)authdata->algtype);
1618 SEQLOAD(p, MATH0, 7, 1, 0);
1619 JUMP(p, 1, LOCAL_JUMP, ALL_TRUE, CALM);
1621 MATHB(p, MATH0, AND, PDCP_C_PLANE_SN_MASK, MATH1, 8,
1624 MATHB(p, MATH0, AND, PDCP_C_PLANE_SN_MASK, MATH1, 8,
1627 MATHB(p, MATH1, SHLD, MATH1, MATH1, 8, 0);
1628 MOVE(p, DESCBUF, 4, MATH2, 0, 0x08, WAITCOMP | IMMED);
1629 MATHB(p, MATH1, OR, MATH2, MATH2, 8, 0);
1630 SEQSTORE(p, MATH0, 7, 1, 0);
1631 if (dir == OP_TYPE_ENCAP_PROTOCOL) {
1632 KEY(p, KEY1, authdata->key_enc_flags, authdata->key,
1633 authdata->keylen, INLINE_KEY(authdata));
1634 MOVE(p, MATH2, 0, IFIFOAB1, 0, 0x08, IMMED);
1635 MOVE(p, MATH0, 7, IFIFOAB1, 0, 1, IMMED);
1637 MATHB(p, SEQINSZ, SUB, ZERO, VSEQINSZ, 4, 0);
1638 MATHB(p, VSEQINSZ, ADD, PDCP_MAC_I_LEN, VSEQOUTSZ, 4, IMMED2);
1640 ALG_OPERATION(p, OP_ALG_ALGSEL_AES,
1642 OP_ALG_AS_INITFINAL,
1645 SEQFIFOLOAD(p, MSG1, 0, VLF | LAST1 | FLUSH1);
1646 MOVE(p, CONTEXT1, 0, MATH3, 0, 4, WAITCOMP | IMMED);
1647 LOAD(p, CLRW_RESET_CLS1_CHA |
1655 KEY(p, KEY1, cipherdata->key_enc_flags, cipherdata->key,
1656 cipherdata->keylen, INLINE_KEY(cipherdata));
1658 MOVE(p, MATH2, 0, CONTEXT1, 0, 8, IMMED);
1659 SEQINPTR(p, 0, PDCP_NULL_MAX_FRAME_LEN, RTO);
1661 ALG_OPERATION(p, OP_ALG_ALGSEL_ZUCE,
1663 OP_ALG_AS_INITFINAL,
1666 SEQFIFOSTORE(p, MSG, 0, 0, VLF);
1668 SEQFIFOLOAD(p, SKIP, 1, 0);
1670 SEQFIFOLOAD(p, MSG1, 0, VLF);
1671 MOVE(p, MATH3, 0, IFIFOAB1, 0, 4, LAST1 | FLUSH1 | IMMED);
1673 MOVE(p, MATH2, 0, CONTEXT1, 0, 8, IMMED);
1675 MOVE(p, CONTEXT1, 0, CONTEXT2, 0, 8, IMMED);
1677 MATHB(p, SEQINSZ, SUB, ZERO, VSEQINSZ, 4, 0);
1679 MATHB(p, SEQINSZ, SUB, PDCP_MAC_I_LEN, VSEQOUTSZ, 4, IMMED2);
1681 KEY(p, KEY1, cipherdata->key_enc_flags, cipherdata->key,
1682 cipherdata->keylen, INLINE_KEY(cipherdata));
1684 MOVE(p, CONTEXT1, 0, CONTEXT2, 0, 8, IMMED);
1686 ALG_OPERATION(p, OP_ALG_ALGSEL_ZUCE,
1688 OP_ALG_AS_INITFINAL,
1691 SEQFIFOSTORE(p, MSG, 0, 0, VLF | CONT);
1692 SEQFIFOLOAD(p, MSG1, 0, VLF | LAST1 | FLUSH1);
1694 MOVE(p, OFIFO, 0, MATH3, 0, 4, IMMED);
1696 LOAD(p, CLRW_RESET_CLS1_CHA |
1704 KEY(p, KEY1, authdata->key_enc_flags, authdata->key,
1705 authdata->keylen, INLINE_KEY(authdata));
1707 SEQINPTR(p, 0, 0, SOP);
1709 ALG_OPERATION(p, OP_ALG_ALGSEL_AES,
1711 OP_ALG_AS_INITFINAL,
1715 MATHB(p, SEQINSZ, SUB, ZERO, VSEQINSZ, 4, 0);
1717 MOVE(p, CONTEXT2, 0, IFIFOAB1, 0, 8, IMMED);
1719 SEQFIFOLOAD(p, MSG1, 0, VLF | LAST1 | FLUSH1);
1721 LOAD(p, NFIFOENTRY_STYPE_ALTSOURCE |
1722 NFIFOENTRY_DEST_CLASS1 |
1723 NFIFOENTRY_DTYPE_ICV |
1725 NFIFOENTRY_FC1 | 4, NFIFO_SZL, 0, 4, IMMED);
1726 MOVE(p, MATH3, 0, ALTSOURCE, 0, 4, IMMED);
1733 pdcp_insert_uplane_15bit_op(struct program *p,
1734 bool swap __maybe_unused,
1735 struct alginfo *cipherdata,
1739 /* Insert Cipher Key */
1740 KEY(p, KEY1, cipherdata->key_enc_flags, cipherdata->key,
1741 cipherdata->keylen, INLINE_KEY(cipherdata));
1743 if (rta_sec_era >= RTA_SEC_ERA_8) {
1744 PROTOCOL(p, dir, OP_PCLID_LTE_PDCP_USER,
1745 (uint16_t)cipherdata->algtype);
1749 SEQLOAD(p, MATH0, 6, 2, 0);
1750 JUMP(p, 1, LOCAL_JUMP, ALL_TRUE, CALM);
1752 MATHB(p, MATH0, AND, PDCP_U_PLANE_15BIT_SN_MASK, MATH1, 8,
1755 MATHB(p, MATH0, AND, PDCP_U_PLANE_15BIT_SN_MASK_BE, MATH1, 8,
1757 SEQSTORE(p, MATH0, 6, 2, 0);
1758 MATHB(p, MATH1, SHLD, MATH1, MATH1, 8, 0);
1759 MOVE(p, DESCBUF, 8, MATH2, 0, 8, WAITCOMP | IMMED);
1760 MATHB(p, MATH1, OR, MATH2, MATH2, 8, 0);
1762 MATHB(p, SEQINSZ, SUB, MATH3, VSEQINSZ, 4, 0);
1763 MATHB(p, SEQINSZ, SUB, MATH3, VSEQOUTSZ, 4, 0);
1765 SEQFIFOSTORE(p, MSG, 0, 0, VLF);
1767 op = dir == OP_TYPE_ENCAP_PROTOCOL ? DIR_ENC : DIR_DEC;
1768 switch (cipherdata->algtype) {
1769 case PDCP_CIPHER_TYPE_SNOW:
1770 MOVE(p, MATH2, 0, CONTEXT1, 0, 8, WAITCOMP | IMMED);
1771 ALG_OPERATION(p, OP_ALG_ALGSEL_SNOW_F8,
1773 OP_ALG_AS_INITFINAL,
1778 case PDCP_CIPHER_TYPE_AES:
1779 MOVE(p, MATH2, 0, CONTEXT1, 0x10, 0x10, WAITCOMP | IMMED);
1780 ALG_OPERATION(p, OP_ALG_ALGSEL_AES,
1782 OP_ALG_AS_INITFINAL,
1787 case PDCP_CIPHER_TYPE_ZUC:
1788 if (rta_sec_era < RTA_SEC_ERA_5) {
1789 pr_err("Invalid era for selected algorithm\n");
1792 MOVE(p, MATH2, 0, CONTEXT1, 0, 0x08, IMMED);
1793 MOVE(p, MATH2, 0, CONTEXT1, 0x08, 0x08, WAITCOMP | IMMED);
1795 ALG_OPERATION(p, OP_ALG_ALGSEL_ZUCE,
1797 OP_ALG_AS_INITFINAL,
1803 pr_err("%s: Invalid encrypt algorithm selected: %d\n",
1804 "pdcp_insert_uplane_15bit_op", cipherdata->algtype);
1808 SEQFIFOLOAD(p, MSG1, 0, VLF | LAST1 | FLUSH1);
1814 * Function for inserting the snippet of code responsible for creating
1815 * the HFN override code via either DPOVRD or via the input frame.
1818 insert_hfn_ov_op(struct program *p,
1820 enum pdb_type_e pdb_type,
1821 unsigned char era_2_sw_hfn_ovrd)
1823 uint32_t imm = PDCP_DPOVRD_HFN_OV_EN;
1824 uint16_t hfn_pdb_offset;
1826 if (rta_sec_era == RTA_SEC_ERA_2 && !era_2_sw_hfn_ovrd)
1830 case PDCP_PDB_TYPE_NO_PDB:
1832 * If there is no PDB, then HFN override mechanism does not
1833 * make any sense, thus in this case the function will
1834 * return the pointer to the current position in the
1839 case PDCP_PDB_TYPE_REDUCED_PDB:
1843 case PDCP_PDB_TYPE_FULL_PDB:
1851 if (rta_sec_era > RTA_SEC_ERA_2) {
1852 MATHB(p, DPOVRD, AND, imm, NONE, 8, IFB | IMMED2);
1854 SEQLOAD(p, MATH0, 4, 4, 0);
1855 JUMP(p, 1, LOCAL_JUMP, ALL_TRUE, CALM);
1856 MATHB(p, MATH0, AND, imm, NONE, 8, IFB | IMMED2);
1857 SEQSTORE(p, MATH0, 4, 4, 0);
1860 if (rta_sec_era >= RTA_SEC_ERA_8)
1861 JUMP(p, 6, LOCAL_JUMP, ALL_TRUE, MATH_Z);
1863 JUMP(p, 5, LOCAL_JUMP, ALL_TRUE, MATH_Z);
1865 if (rta_sec_era > RTA_SEC_ERA_2)
1866 MATHB(p, DPOVRD, LSHIFT, shift, MATH0, 4, IMMED2);
1868 MATHB(p, MATH0, LSHIFT, shift, MATH0, 4, IMMED2);
1870 MATHB(p, MATH0, SHLD, MATH0, MATH0, 8, 0);
1871 MOVE(p, MATH0, 0, DESCBUF, hfn_pdb_offset, 4, IMMED);
1873 if (rta_sec_era >= RTA_SEC_ERA_8)
1875 * For ERA8, DPOVRD could be handled by the PROTOCOL command
1876 * itself. For now, this is not done. Thus, clear DPOVRD here
1877 * to alleviate any side-effects.
1879 MATHB(p, DPOVRD, AND, ZERO, DPOVRD, 4, STL);
1885 * PDCP Control PDB creation function
1887 static inline enum pdb_type_e
1888 cnstr_pdcp_c_plane_pdb(struct program *p,
1890 unsigned char bearer,
1891 unsigned char direction,
1892 uint32_t hfn_threshold,
1893 struct alginfo *cipherdata,
1894 struct alginfo *authdata)
1896 struct pdcp_pdb pdb;
1898 pdb_mask[PDCP_CIPHER_TYPE_INVALID][PDCP_AUTH_TYPE_INVALID] = {
1900 PDCP_PDB_TYPE_NO_PDB, /* NULL */
1901 PDCP_PDB_TYPE_FULL_PDB, /* SNOW f9 */
1902 PDCP_PDB_TYPE_FULL_PDB, /* AES CMAC */
1903 PDCP_PDB_TYPE_FULL_PDB /* ZUC-I */
1906 PDCP_PDB_TYPE_FULL_PDB, /* NULL */
1907 PDCP_PDB_TYPE_FULL_PDB, /* SNOW f9 */
1908 PDCP_PDB_TYPE_REDUCED_PDB, /* AES CMAC */
1909 PDCP_PDB_TYPE_REDUCED_PDB /* ZUC-I */
1912 PDCP_PDB_TYPE_FULL_PDB, /* NULL */
1913 PDCP_PDB_TYPE_REDUCED_PDB, /* SNOW f9 */
1914 PDCP_PDB_TYPE_FULL_PDB, /* AES CMAC */
1915 PDCP_PDB_TYPE_REDUCED_PDB /* ZUC-I */
1918 PDCP_PDB_TYPE_FULL_PDB, /* NULL */
1919 PDCP_PDB_TYPE_REDUCED_PDB, /* SNOW f9 */
1920 PDCP_PDB_TYPE_REDUCED_PDB, /* AES CMAC */
1921 PDCP_PDB_TYPE_FULL_PDB /* ZUC-I */
1925 if (rta_sec_era >= RTA_SEC_ERA_8) {
1926 memset(&pdb, 0x00, sizeof(struct pdcp_pdb));
1928 /* This is a HW issue. Bit 2 should be set to zero,
1929 * but it does not work this way. Override here.
1931 pdb.opt_res.rsvd = 0x00000002;
1933 /* Copy relevant information from user to PDB */
1934 pdb.hfn_res = hfn << PDCP_C_PLANE_PDB_HFN_SHIFT;
1935 pdb.bearer_dir_res = (uint32_t)
1936 ((bearer << PDCP_C_PLANE_PDB_BEARER_SHIFT) |
1937 (direction << PDCP_C_PLANE_PDB_DIR_SHIFT));
1939 hfn_threshold << PDCP_C_PLANE_PDB_HFN_THR_SHIFT;
1941 /* copy PDB in descriptor*/
1942 __rta_out32(p, pdb.opt_res.opt);
1943 __rta_out32(p, pdb.hfn_res);
1944 __rta_out32(p, pdb.bearer_dir_res);
1945 __rta_out32(p, pdb.hfn_thr_res);
1947 return PDCP_PDB_TYPE_FULL_PDB;
1950 switch (pdb_mask[cipherdata->algtype][authdata->algtype]) {
1951 case PDCP_PDB_TYPE_NO_PDB:
1954 case PDCP_PDB_TYPE_REDUCED_PDB:
1955 __rta_out32(p, (hfn << PDCP_C_PLANE_PDB_HFN_SHIFT));
1957 (uint32_t)((bearer <<
1958 PDCP_C_PLANE_PDB_BEARER_SHIFT) |
1960 PDCP_C_PLANE_PDB_DIR_SHIFT)));
1963 case PDCP_PDB_TYPE_FULL_PDB:
1964 memset(&pdb, 0x00, sizeof(struct pdcp_pdb));
1966 /* This is a HW issue. Bit 2 should be set to zero,
1967 * but it does not work this way. Override here.
1969 pdb.opt_res.rsvd = 0x00000002;
1971 /* Copy relevant information from user to PDB */
1972 pdb.hfn_res = hfn << PDCP_C_PLANE_PDB_HFN_SHIFT;
1973 pdb.bearer_dir_res = (uint32_t)
1974 ((bearer << PDCP_C_PLANE_PDB_BEARER_SHIFT) |
1975 (direction << PDCP_C_PLANE_PDB_DIR_SHIFT));
1977 hfn_threshold << PDCP_C_PLANE_PDB_HFN_THR_SHIFT;
1979 /* copy PDB in descriptor*/
1980 __rta_out32(p, pdb.opt_res.opt);
1981 __rta_out32(p, pdb.hfn_res);
1982 __rta_out32(p, pdb.bearer_dir_res);
1983 __rta_out32(p, pdb.hfn_thr_res);
1988 return PDCP_PDB_TYPE_INVALID;
1991 return pdb_mask[cipherdata->algtype][authdata->algtype];
1995 * PDCP UPlane PDB creation function
1998 cnstr_pdcp_u_plane_pdb(struct program *p,
1999 enum pdcp_sn_size sn_size,
2000 uint32_t hfn, unsigned short bearer,
2001 unsigned short direction,
2002 uint32_t hfn_threshold)
2004 struct pdcp_pdb pdb;
2005 /* Read options from user */
2006 /* Depending on sequence number length, the HFN and HFN threshold
2007 * have different lengths.
2009 memset(&pdb, 0x00, sizeof(struct pdcp_pdb));
2012 case PDCP_SN_SIZE_7:
2013 pdb.opt_res.opt |= PDCP_U_PLANE_PDB_OPT_SHORT_SN;
2014 pdb.hfn_res = hfn << PDCP_U_PLANE_PDB_SHORT_SN_HFN_SHIFT;
2016 hfn_threshold<<PDCP_U_PLANE_PDB_SHORT_SN_HFN_THR_SHIFT;
2019 case PDCP_SN_SIZE_12:
2020 pdb.opt_res.opt &= (uint32_t)(~PDCP_U_PLANE_PDB_OPT_SHORT_SN);
2021 pdb.hfn_res = hfn << PDCP_U_PLANE_PDB_LONG_SN_HFN_SHIFT;
2023 hfn_threshold<<PDCP_U_PLANE_PDB_LONG_SN_HFN_THR_SHIFT;
2026 case PDCP_SN_SIZE_15:
2027 pdb.opt_res.opt = (uint32_t)(PDCP_U_PLANE_PDB_OPT_15B_SN);
2028 pdb.hfn_res = hfn << PDCP_U_PLANE_PDB_15BIT_SN_HFN_SHIFT;
2030 hfn_threshold<<PDCP_U_PLANE_PDB_15BIT_SN_HFN_THR_SHIFT;
2034 pr_err("Invalid Sequence Number Size setting in PDB\n");
2038 pdb.bearer_dir_res = (uint32_t)
2039 ((bearer << PDCP_U_PLANE_PDB_BEARER_SHIFT) |
2040 (direction << PDCP_U_PLANE_PDB_DIR_SHIFT));
2042 /* copy PDB in descriptor*/
2043 __rta_out32(p, pdb.opt_res.opt);
2044 __rta_out32(p, pdb.hfn_res);
2045 __rta_out32(p, pdb.bearer_dir_res);
2046 __rta_out32(p, pdb.hfn_thr_res);
2051 * cnstr_shdsc_pdcp_c_plane_encap - Function for creating a PDCP Control Plane
2052 * encapsulation descriptor.
2053 * @descbuf: pointer to buffer for descriptor construction
2054 * @ps: if 36/40bit addressing is desired, this parameter must be true
2055 * @swap: must be true when core endianness doesn't match SEC endianness
2056 * @hfn: starting Hyper Frame Number to be used together with the SN from the
2058 * @bearer: radio bearer ID
2059 * @direction: the direction of the PDCP frame (UL/DL)
2060 * @hfn_threshold: HFN value that once reached triggers a warning from SEC that
2061 * keys should be renegotiated at the earliest convenience.
2062 * @cipherdata: pointer to block cipher transform definitions
2063 * Valid algorithm values are those from cipher_type_pdcp enum.
2064 * @authdata: pointer to authentication transform definitions
2065 * Valid algorithm values are those from auth_type_pdcp enum.
2066 * @era_2_sw_hfn_ovrd: if software HFN override mechanism is desired for
2067 * this descriptor. Note: Can only be used for
2069 * Return: size of descriptor written in words or negative number on error.
2070 * Once the function returns, the value of this parameter can be used
2071 * for reclaiming the space that wasn't used for the descriptor.
2073 * Note: descbuf must be large enough to contain a full 256 byte long
2074 * descriptor; after the function returns, by subtracting the actual number of
2075 * bytes used, the user can reuse the remaining buffer space for other purposes.
2078 cnstr_shdsc_pdcp_c_plane_encap(uint32_t *descbuf,
2082 unsigned char bearer,
2083 unsigned char direction,
2084 uint32_t hfn_threshold,
2085 struct alginfo *cipherdata,
2086 struct alginfo *authdata,
2087 unsigned char era_2_sw_hfn_ovrd)
2090 (*pdcp_cp_fp[PDCP_CIPHER_TYPE_INVALID][PDCP_AUTH_TYPE_INVALID])
2091 (struct program*, bool swap, struct alginfo *,
2092 struct alginfo *, unsigned int,
2093 unsigned char __maybe_unused) = {
2095 pdcp_insert_cplane_null_op, /* NULL */
2096 pdcp_insert_cplane_int_only_op, /* SNOW f9 */
2097 pdcp_insert_cplane_int_only_op, /* AES CMAC */
2098 pdcp_insert_cplane_int_only_op /* ZUC-I */
2101 pdcp_insert_cplane_enc_only_op, /* NULL */
2102 pdcp_insert_cplane_acc_op, /* SNOW f9 */
2103 pdcp_insert_cplane_snow_aes_op, /* AES CMAC */
2104 pdcp_insert_cplane_snow_zuc_op /* ZUC-I */
2107 pdcp_insert_cplane_enc_only_op, /* NULL */
2108 pdcp_insert_cplane_aes_snow_op, /* SNOW f9 */
2109 pdcp_insert_cplane_acc_op, /* AES CMAC */
2110 pdcp_insert_cplane_aes_zuc_op /* ZUC-I */
2113 pdcp_insert_cplane_enc_only_op, /* NULL */
2114 pdcp_insert_cplane_zuc_snow_op, /* SNOW f9 */
2115 pdcp_insert_cplane_zuc_aes_op, /* AES CMAC */
2116 pdcp_insert_cplane_acc_op /* ZUC-I */
2119 static enum rta_share_type
2120 desc_share[PDCP_CIPHER_TYPE_INVALID][PDCP_AUTH_TYPE_INVALID] = {
2122 SHR_WAIT, /* NULL */
2123 SHR_ALWAYS, /* SNOW f9 */
2124 SHR_ALWAYS, /* AES CMAC */
2125 SHR_ALWAYS /* ZUC-I */
2128 SHR_ALWAYS, /* NULL */
2129 SHR_ALWAYS, /* SNOW f9 */
2130 SHR_WAIT, /* AES CMAC */
2131 SHR_WAIT /* ZUC-I */
2134 SHR_ALWAYS, /* NULL */
2135 SHR_ALWAYS, /* SNOW f9 */
2136 SHR_ALWAYS, /* AES CMAC */
2137 SHR_WAIT /* ZUC-I */
2140 SHR_ALWAYS, /* NULL */
2141 SHR_WAIT, /* SNOW f9 */
2142 SHR_WAIT, /* AES CMAC */
2143 SHR_ALWAYS /* ZUC-I */
2146 enum pdb_type_e pdb_type;
2148 struct program *p = &prg;
2152 if (rta_sec_era != RTA_SEC_ERA_2 && era_2_sw_hfn_ovrd) {
2153 pr_err("Cannot select SW HFN override for other era than 2");
2157 PROGRAM_CNTXT_INIT(p, descbuf, 0);
2159 PROGRAM_SET_BSWAP(p);
2161 PROGRAM_SET_36BIT_ADDR(p);
2163 SHR_HDR(p, desc_share[cipherdata->algtype][authdata->algtype], 0, 0);
2165 pdb_type = cnstr_pdcp_c_plane_pdb(p,
2173 SET_LABEL(p, pdb_end);
2175 err = insert_hfn_ov_op(p, PDCP_SN_SIZE_5, pdb_type,
2180 err = pdcp_cp_fp[cipherdata->algtype][authdata->algtype](p,
2184 OP_TYPE_ENCAP_PROTOCOL,
2189 PATCH_HDR(p, 0, pdb_end);
2191 return PROGRAM_FINALIZE(p);
2195 * cnstr_shdsc_pdcp_c_plane_decap - Function for creating a PDCP Control Plane
2196 * decapsulation descriptor.
2197 * @descbuf: pointer to buffer for descriptor construction
2198 * @ps: if 36/40bit addressing is desired, this parameter must be true
2199 * @swap: must be true when core endianness doesn't match SEC endianness
2200 * @hfn: starting Hyper Frame Number to be used together with the SN from the
2202 * @bearer: radio bearer ID
2203 * @direction: the direction of the PDCP frame (UL/DL)
2204 * @hfn_threshold: HFN value that once reached triggers a warning from SEC that
2205 * keys should be renegotiated at the earliest convenience.
2206 * @cipherdata: pointer to block cipher transform definitions
2207 * Valid algorithm values are those from cipher_type_pdcp enum.
2208 * @authdata: pointer to authentication transform definitions
2209 * Valid algorithm values are those from auth_type_pdcp enum.
2210 * @era_2_sw_hfn_ovrd: if software HFN override mechanism is desired for
2211 * this descriptor. Note: Can only be used for
2214 * Return: size of descriptor written in words or negative number on error.
2215 * Once the function returns, the value of this parameter can be used
2216 * for reclaiming the space that wasn't used for the descriptor.
2218 * Note: descbuf must be large enough to contain a full 256 byte long
2219 * descriptor; after the function returns, by subtracting the actual number of
2220 * bytes used, the user can reuse the remaining buffer space for other purposes.
2223 cnstr_shdsc_pdcp_c_plane_decap(uint32_t *descbuf,
2227 unsigned char bearer,
2228 unsigned char direction,
2229 uint32_t hfn_threshold,
2230 struct alginfo *cipherdata,
2231 struct alginfo *authdata,
2232 unsigned char era_2_sw_hfn_ovrd)
2235 (*pdcp_cp_fp[PDCP_CIPHER_TYPE_INVALID][PDCP_AUTH_TYPE_INVALID])
2236 (struct program*, bool swap, struct alginfo *,
2237 struct alginfo *, unsigned int, unsigned char) = {
2239 pdcp_insert_cplane_null_op, /* NULL */
2240 pdcp_insert_cplane_int_only_op, /* SNOW f9 */
2241 pdcp_insert_cplane_int_only_op, /* AES CMAC */
2242 pdcp_insert_cplane_int_only_op /* ZUC-I */
2245 pdcp_insert_cplane_enc_only_op, /* NULL */
2246 pdcp_insert_cplane_acc_op, /* SNOW f9 */
2247 pdcp_insert_cplane_snow_aes_op, /* AES CMAC */
2248 pdcp_insert_cplane_snow_zuc_op /* ZUC-I */
2251 pdcp_insert_cplane_enc_only_op, /* NULL */
2252 pdcp_insert_cplane_aes_snow_op, /* SNOW f9 */
2253 pdcp_insert_cplane_acc_op, /* AES CMAC */
2254 pdcp_insert_cplane_aes_zuc_op /* ZUC-I */
2257 pdcp_insert_cplane_enc_only_op, /* NULL */
2258 pdcp_insert_cplane_zuc_snow_op, /* SNOW f9 */
2259 pdcp_insert_cplane_zuc_aes_op, /* AES CMAC */
2260 pdcp_insert_cplane_acc_op /* ZUC-I */
2263 static enum rta_share_type
2264 desc_share[PDCP_CIPHER_TYPE_INVALID][PDCP_AUTH_TYPE_INVALID] = {
2266 SHR_WAIT, /* NULL */
2267 SHR_ALWAYS, /* SNOW f9 */
2268 SHR_ALWAYS, /* AES CMAC */
2269 SHR_ALWAYS /* ZUC-I */
2272 SHR_ALWAYS, /* NULL */
2273 SHR_ALWAYS, /* SNOW f9 */
2274 SHR_WAIT, /* AES CMAC */
2275 SHR_WAIT /* ZUC-I */
2278 SHR_ALWAYS, /* NULL */
2279 SHR_ALWAYS, /* SNOW f9 */
2280 SHR_ALWAYS, /* AES CMAC */
2281 SHR_WAIT /* ZUC-I */
2284 SHR_ALWAYS, /* NULL */
2285 SHR_WAIT, /* SNOW f9 */
2286 SHR_WAIT, /* AES CMAC */
2287 SHR_ALWAYS /* ZUC-I */
2290 enum pdb_type_e pdb_type;
2292 struct program *p = &prg;
2296 if (rta_sec_era != RTA_SEC_ERA_2 && era_2_sw_hfn_ovrd) {
2297 pr_err("Cannot select SW HFN override for other era than 2");
2301 PROGRAM_CNTXT_INIT(p, descbuf, 0);
2303 PROGRAM_SET_BSWAP(p);
2305 PROGRAM_SET_36BIT_ADDR(p);
2307 SHR_HDR(p, desc_share[cipherdata->algtype][authdata->algtype], 0, 0);
2309 pdb_type = cnstr_pdcp_c_plane_pdb(p,
2317 SET_LABEL(p, pdb_end);
2319 err = insert_hfn_ov_op(p, PDCP_SN_SIZE_5, pdb_type,
2324 err = pdcp_cp_fp[cipherdata->algtype][authdata->algtype](p,
2328 OP_TYPE_DECAP_PROTOCOL,
2333 PATCH_HDR(p, 0, pdb_end);
2335 return PROGRAM_FINALIZE(p);
2339 * cnstr_shdsc_pdcp_u_plane_encap - Function for creating a PDCP User Plane
2340 * encapsulation descriptor.
2341 * @descbuf: pointer to buffer for descriptor construction
2342 * @ps: if 36/40bit addressing is desired, this parameter must be true
2343 * @swap: must be true when core endianness doesn't match SEC endianness
2344 * @sn_size: selects Sequence Number Size: 7/12/15 bits
2345 * @hfn: starting Hyper Frame Number to be used together with the SN from the
2347 * @bearer: radio bearer ID
2348 * @direction: the direction of the PDCP frame (UL/DL)
2349 * @hfn_threshold: HFN value that once reached triggers a warning from SEC that
2350 * keys should be renegotiated at the earliest convenience.
2351 * @cipherdata: pointer to block cipher transform definitions
2352 * Valid algorithm values are those from cipher_type_pdcp enum.
2353 * @era_2_sw_hfn_ovrd: if software HFN override mechanism is desired for
2354 * this descriptor. Note: Can only be used for
2357 * Return: size of descriptor written in words or negative number on error.
2358 * Once the function returns, the value of this parameter can be used
2359 * for reclaiming the space that wasn't used for the descriptor.
2361 * Note: descbuf must be large enough to contain a full 256 byte long
2362 * descriptor; after the function returns, by subtracting the actual number of
2363 * bytes used, the user can reuse the remaining buffer space for other purposes.
2366 cnstr_shdsc_pdcp_u_plane_encap(uint32_t *descbuf,
2369 enum pdcp_sn_size sn_size,
2371 unsigned short bearer,
2372 unsigned short direction,
2373 uint32_t hfn_threshold,
2374 struct alginfo *cipherdata,
2375 unsigned char era_2_sw_hfn_ovrd)
2378 struct program *p = &prg;
2382 if (rta_sec_era != RTA_SEC_ERA_2 && era_2_sw_hfn_ovrd) {
2383 pr_err("Cannot select SW HFN ovrd for other era than 2");
2387 PROGRAM_CNTXT_INIT(p, descbuf, 0);
2389 PROGRAM_SET_BSWAP(p);
2391 PROGRAM_SET_36BIT_ADDR(p);
2393 SHR_HDR(p, SHR_ALWAYS, 0, 0);
2394 if (cnstr_pdcp_u_plane_pdb(p, sn_size, hfn, bearer, direction,
2396 pr_err("Error creating PDCP UPlane PDB\n");
2399 SET_LABEL(p, pdb_end);
2401 err = insert_hfn_ov_op(p, sn_size, PDCP_PDB_TYPE_FULL_PDB,
2407 case PDCP_SN_SIZE_7:
2408 case PDCP_SN_SIZE_12:
2409 switch (cipherdata->algtype) {
2410 case PDCP_CIPHER_TYPE_ZUC:
2411 if (rta_sec_era < RTA_SEC_ERA_5) {
2412 pr_err("Invalid era for selected algorithm\n");
2415 case PDCP_CIPHER_TYPE_AES:
2416 case PDCP_CIPHER_TYPE_SNOW:
2417 /* Insert Cipher Key */
2418 KEY(p, KEY1, cipherdata->key_enc_flags,
2419 (uint64_t)cipherdata->key, cipherdata->keylen,
2420 INLINE_KEY(cipherdata));
2421 PROTOCOL(p, OP_TYPE_ENCAP_PROTOCOL,
2422 OP_PCLID_LTE_PDCP_USER,
2423 (uint16_t)cipherdata->algtype);
2425 case PDCP_CIPHER_TYPE_NULL:
2426 insert_copy_frame_op(p,
2428 OP_TYPE_ENCAP_PROTOCOL);
2431 pr_err("%s: Invalid encrypt algorithm selected: %d\n",
2432 "cnstr_pcl_shdsc_pdcp_u_plane_decap",
2433 cipherdata->algtype);
2438 case PDCP_SN_SIZE_15:
2439 switch (cipherdata->algtype) {
2440 case PDCP_CIPHER_TYPE_NULL:
2441 insert_copy_frame_op(p,
2443 OP_TYPE_ENCAP_PROTOCOL);
2447 err = pdcp_insert_uplane_15bit_op(p, swap, cipherdata,
2448 OP_TYPE_ENCAP_PROTOCOL);
2455 case PDCP_SN_SIZE_5:
2457 pr_err("Invalid SN size selected\n");
2461 PATCH_HDR(p, 0, pdb_end);
2462 return PROGRAM_FINALIZE(p);
2466 * cnstr_shdsc_pdcp_u_plane_decap - Function for creating a PDCP User Plane
2467 * decapsulation descriptor.
2468 * @descbuf: pointer to buffer for descriptor construction
2469 * @ps: if 36/40bit addressing is desired, this parameter must be true
2470 * @swap: must be true when core endianness doesn't match SEC endianness
2471 * @sn_size: selects Sequence Number Size: 7/12/15 bits
2472 * @hfn: starting Hyper Frame Number to be used together with the SN from the
2474 * @bearer: radio bearer ID
2475 * @direction: the direction of the PDCP frame (UL/DL)
2476 * @hfn_threshold: HFN value that once reached triggers a warning from SEC that
2477 * keys should be renegotiated at the earliest convenience.
2478 * @cipherdata: pointer to block cipher transform definitions
2479 * Valid algorithm values are those from cipher_type_pdcp enum.
2480 * @era_2_sw_hfn_ovrd: if software HFN override mechanism is desired for
2481 * this descriptor. Note: Can only be used for
2484 * Return: size of descriptor written in words or negative number on error.
2485 * Once the function returns, the value of this parameter can be used
2486 * for reclaiming the space that wasn't used for the descriptor.
2488 * Note: descbuf must be large enough to contain a full 256 byte long
2489 * descriptor; after the function returns, by subtracting the actual number of
2490 * bytes used, the user can reuse the remaining buffer space for other purposes.
2493 cnstr_shdsc_pdcp_u_plane_decap(uint32_t *descbuf,
2496 enum pdcp_sn_size sn_size,
2498 unsigned short bearer,
2499 unsigned short direction,
2500 uint32_t hfn_threshold,
2501 struct alginfo *cipherdata,
2502 unsigned char era_2_sw_hfn_ovrd)
2505 struct program *p = &prg;
2509 if (rta_sec_era != RTA_SEC_ERA_2 && era_2_sw_hfn_ovrd) {
2510 pr_err("Cannot select SW HFN override for other era than 2");
2514 PROGRAM_CNTXT_INIT(p, descbuf, 0);
2516 PROGRAM_SET_BSWAP(p);
2518 PROGRAM_SET_36BIT_ADDR(p);
2520 SHR_HDR(p, SHR_ALWAYS, 0, 0);
2521 if (cnstr_pdcp_u_plane_pdb(p, sn_size, hfn, bearer, direction,
2523 pr_err("Error creating PDCP UPlane PDB\n");
2526 SET_LABEL(p, pdb_end);
2528 err = insert_hfn_ov_op(p, sn_size, PDCP_PDB_TYPE_FULL_PDB,
2534 case PDCP_SN_SIZE_7:
2535 case PDCP_SN_SIZE_12:
2536 switch (cipherdata->algtype) {
2537 case PDCP_CIPHER_TYPE_ZUC:
2538 if (rta_sec_era < RTA_SEC_ERA_5) {
2539 pr_err("Invalid era for selected algorithm\n");
2542 case PDCP_CIPHER_TYPE_AES:
2543 case PDCP_CIPHER_TYPE_SNOW:
2544 /* Insert Cipher Key */
2545 KEY(p, KEY1, cipherdata->key_enc_flags,
2546 cipherdata->key, cipherdata->keylen,
2547 INLINE_KEY(cipherdata));
2548 PROTOCOL(p, OP_TYPE_DECAP_PROTOCOL,
2549 OP_PCLID_LTE_PDCP_USER,
2550 (uint16_t)cipherdata->algtype);
2552 case PDCP_CIPHER_TYPE_NULL:
2553 insert_copy_frame_op(p,
2555 OP_TYPE_DECAP_PROTOCOL);
2558 pr_err("%s: Invalid encrypt algorithm selected: %d\n",
2559 "cnstr_pcl_shdsc_pdcp_u_plane_decap",
2560 cipherdata->algtype);
2565 case PDCP_SN_SIZE_15:
2566 switch (cipherdata->algtype) {
2567 case PDCP_CIPHER_TYPE_NULL:
2568 insert_copy_frame_op(p,
2570 OP_TYPE_DECAP_PROTOCOL);
2574 err = pdcp_insert_uplane_15bit_op(p, swap, cipherdata,
2575 OP_TYPE_DECAP_PROTOCOL);
2582 case PDCP_SN_SIZE_5:
2584 pr_err("Invalid SN size selected\n");
2588 PATCH_HDR(p, 0, pdb_end);
2589 return PROGRAM_FINALIZE(p);
2593 * cnstr_shdsc_pdcp_short_mac - Function for creating a PDCP Short MAC
2595 * @descbuf: pointer to buffer for descriptor construction
2596 * @ps: if 36/40bit addressing is desired, this parameter must be true
2597 * @swap: must be true when core endianness doesn't match SEC endianness
2598 * @authdata: pointer to authentication transform definitions
2599 * Valid algorithm values are those from auth_type_pdcp enum.
2601 * Return: size of descriptor written in words or negative number on error.
2602 * Once the function returns, the value of this parameter can be used
2603 * for reclaiming the space that wasn't used for the descriptor.
2605 * Note: descbuf must be large enough to contain a full 256 byte long
2606 * descriptor; after the function returns, by subtracting the actual number of
2607 * bytes used, the user can reuse the remaining buffer space for other purposes.
2610 cnstr_shdsc_pdcp_short_mac(uint32_t *descbuf,
2613 struct alginfo *authdata)
2616 struct program *p = &prg;
2617 uint32_t iv[3] = {0, 0, 0};
2618 LABEL(local_offset);
2619 REFERENCE(move_cmd_read_descbuf);
2620 REFERENCE(move_cmd_write_descbuf);
2622 PROGRAM_CNTXT_INIT(p, descbuf, 0);
2624 PROGRAM_SET_BSWAP(p);
2626 PROGRAM_SET_36BIT_ADDR(p);
2628 SHR_HDR(p, SHR_ALWAYS, 1, 0);
2630 if (rta_sec_era > RTA_SEC_ERA_2) {
2631 MATHB(p, SEQINSZ, SUB, ZERO, VSEQINSZ, 4, 0);
2632 MATHB(p, SEQINSZ, SUB, ZERO, MATH1, 4, 0);
2634 MATHB(p, SEQINSZ, ADD, ONE, MATH1, 4, 0);
2635 MATHB(p, MATH1, SUB, ONE, MATH1, 4, 0);
2636 MATHB(p, ZERO, ADD, MATH1, VSEQINSZ, 4, 0);
2637 MOVE(p, MATH1, 0, MATH0, 0, 8, IMMED);
2640 * Since MOVELEN is available only starting with
2641 * SEC ERA 3, use poor man's MOVELEN: create a MOVE
2642 * command dynamically by writing the length from M1 by
2643 * OR-ing the command in the M1 register and MOVE the
2644 * result into the descriptor buffer. Care must be taken
2645 * wrt. the location of the command because of SEC
2646 * pipelining. The actual MOVEs are written at the end
2647 * of the descriptor due to calculations needed on the
2648 * offset in the descriptor for the MOVE command.
2650 move_cmd_read_descbuf = MOVE(p, DESCBUF, 0, MATH0, 0, 6,
2652 move_cmd_write_descbuf = MOVE(p, MATH0, 0, DESCBUF, 0, 8,
2655 MATHB(p, ZERO, ADD, MATH1, VSEQOUTSZ, 4, 0);
2657 switch (authdata->algtype) {
2658 case PDCP_AUTH_TYPE_NULL:
2659 SEQFIFOSTORE(p, MSG, 0, 0, VLF);
2660 if (rta_sec_era > RTA_SEC_ERA_2) {
2661 MOVE(p, AB1, 0, OFIFO, 0, MATH1, 0);
2663 SET_LABEL(p, local_offset);
2665 /* Shut off automatic Info FIFO entries */
2666 LOAD(p, 0, DCTRL, LDOFF_DISABLE_AUTO_NFIFO, 0, IMMED);
2668 /* Placeholder for MOVE command with length from M1
2671 MOVE(p, IFIFOAB1, 0, OFIFO, 0, 0, IMMED);
2673 /* Enable automatic Info FIFO entries */
2674 LOAD(p, 0, DCTRL, LDOFF_ENABLE_AUTO_NFIFO, 0, IMMED);
2677 LOAD(p, (uintptr_t)iv, MATH0, 0, 8, IMMED | COPY);
2678 SEQFIFOLOAD(p, MSG1, 0, VLF | LAST1 | LAST2 | FLUSH1);
2679 SEQSTORE(p, MATH0, 0, 4, 0);
2683 case PDCP_AUTH_TYPE_SNOW:
2685 iv[1] = swap ? swab32(0x04000000) : 0x04000000;
2686 iv[2] = swap ? swab32(0xF8000000) : 0xF8000000;
2688 KEY(p, KEY2, authdata->key_enc_flags, authdata->key,
2689 authdata->keylen, INLINE_KEY(authdata));
2690 LOAD(p, (uintptr_t)&iv, CONTEXT2, 0, 12, IMMED | COPY);
2691 ALG_OPERATION(p, OP_ALG_ALGSEL_SNOW_F9,
2693 OP_ALG_AS_INITFINAL,
2696 SEQFIFOSTORE(p, MSG, 0, 0, VLF);
2698 if (rta_sec_era > RTA_SEC_ERA_2) {
2699 MOVE(p, AB1, 0, OFIFO, 0, MATH1, 0);
2701 SET_LABEL(p, local_offset);
2704 /* Shut off automatic Info FIFO entries */
2705 LOAD(p, 0, DCTRL, LDOFF_DISABLE_AUTO_NFIFO, 0, IMMED);
2707 /* Placeholder for MOVE command with length from M1
2710 MOVE(p, IFIFOAB1, 0, OFIFO, 0, 0, IMMED);
2712 /* Enable automatic Info FIFO entries */
2713 LOAD(p, 0, DCTRL, LDOFF_ENABLE_AUTO_NFIFO, 0, IMMED);
2715 SEQFIFOLOAD(p, MSGINSNOOP, 0, VLF | LAST1 | LAST2 | FLUSH1);
2716 SEQSTORE(p, CONTEXT2, 0, 4, 0);
2720 case PDCP_AUTH_TYPE_AES:
2722 iv[1] = swap ? swab32(0xFC000000) : 0xFC000000;
2723 iv[2] = 0x00000000; /* unused */
2725 KEY(p, KEY1, authdata->key_enc_flags, authdata->key,
2726 authdata->keylen, INLINE_KEY(authdata));
2727 LOAD(p, (uintptr_t)&iv, MATH0, 0, 8, IMMED | COPY);
2728 MOVE(p, MATH0, 0, IFIFOAB1, 0, 8, IMMED);
2729 ALG_OPERATION(p, OP_ALG_ALGSEL_AES,
2731 OP_ALG_AS_INITFINAL,
2734 SEQFIFOSTORE(p, MSG, 0, 0, VLF);
2736 if (rta_sec_era > RTA_SEC_ERA_2) {
2737 MOVE(p, AB2, 0, OFIFO, 0, MATH1, 0);
2739 SET_LABEL(p, local_offset);
2741 /* Shut off automatic Info FIFO entries */
2742 LOAD(p, 0, DCTRL, LDOFF_DISABLE_AUTO_NFIFO, 0, IMMED);
2744 /* Placeholder for MOVE command with length from M1
2747 MOVE(p, IFIFOAB2, 0, OFIFO, 0, 0, IMMED);
2749 /* Enable automatic Info FIFO entries */
2750 LOAD(p, 0, DCTRL, LDOFF_ENABLE_AUTO_NFIFO, 0, IMMED);
2752 SEQFIFOLOAD(p, MSGINSNOOP, 0, VLF | LAST1 | LAST2 | FLUSH1);
2753 SEQSTORE(p, CONTEXT1, 0, 4, 0);
2757 case PDCP_AUTH_TYPE_ZUC:
2758 if (rta_sec_era < RTA_SEC_ERA_5) {
2759 pr_err("Invalid era for selected algorithm\n");
2763 iv[1] = swap ? swab32(0xFC000000) : 0xFC000000;
2764 iv[2] = 0x00000000; /* unused */
2766 KEY(p, KEY2, authdata->key_enc_flags, authdata->key,
2767 authdata->keylen, INLINE_KEY(authdata));
2768 LOAD(p, (uintptr_t)&iv, CONTEXT2, 0, 12, IMMED | COPY);
2769 ALG_OPERATION(p, OP_ALG_ALGSEL_ZUCA,
2771 OP_ALG_AS_INITFINAL,
2774 SEQFIFOSTORE(p, MSG, 0, 0, VLF);
2775 MOVE(p, AB1, 0, OFIFO, 0, MATH1, 0);
2776 SEQFIFOLOAD(p, MSGINSNOOP, 0, VLF | LAST1 | LAST2 | FLUSH1);
2777 SEQSTORE(p, CONTEXT2, 0, 4, 0);
2782 pr_err("%s: Invalid integrity algorithm selected: %d\n",
2783 "cnstr_shdsc_pdcp_short_mac", authdata->algtype);
2788 if (rta_sec_era < RTA_SEC_ERA_3) {
2789 PATCH_MOVE(p, move_cmd_read_descbuf, local_offset);
2790 PATCH_MOVE(p, move_cmd_write_descbuf, local_offset);
2793 return PROGRAM_FINALIZE(p);
2796 #endif /* __DESC_PDCP_H__ */