1 /* SPDX-License-Identifier: BSD-3-Clause or GPL-2.0+
2 * Copyright 2008-2013 Freescale Semiconductor, Inc.
6 #ifndef __DESC_PDCP_H__
7 #define __DESC_PDCP_H__
13 * DOC: PDCP Shared Descriptor Constructors
15 * Shared descriptors for PDCP protocol.
19 * PDCP_NULL_MAX_FRAME_LEN - The maximum frame frame length that is supported by
22 #define PDCP_NULL_MAX_FRAME_LEN 0x00002FFF
25 * PDCP_MAC_I_LEN - The length of the MAC-I for PDCP protocol operation
27 #define PDCP_MAC_I_LEN 0x00000004
30 * PDCP_MAX_FRAME_LEN_STATUS - The status returned in FD status/command field in
31 * case the input frame is larger than
32 * PDCP_NULL_MAX_FRAME_LEN.
34 #define PDCP_MAX_FRAME_LEN_STATUS 0xF1
37 * PDCP_C_PLANE_SN_MASK - This mask is used in the PDCP descriptors for
38 * extracting the sequence number (SN) from the PDCP
39 * Control Plane header. For PDCP Control Plane, the SN
40 * is constant (5 bits) as opposed to PDCP Data Plane
43 #define PDCP_C_PLANE_SN_MASK 0x1F000000
44 #define PDCP_C_PLANE_SN_MASK_BE 0x0000001F
47 * PDCP_U_PLANE_15BIT_SN_MASK - This mask is used in the PDCP descriptors for
48 * extracting the sequence number (SN) from the
49 * PDCP User Plane header. For PDCP Control Plane,
50 * the SN is constant (5 bits) as opposed to PDCP
51 * Data Plane (7/12/15 bits).
53 #define PDCP_U_PLANE_15BIT_SN_MASK 0xFF7F0000
54 #define PDCP_U_PLANE_15BIT_SN_MASK_BE 0x00007FFF
57 * PDCP_U_PLANE_18BIT_SN_MASK - This mask is used in the PDCP descriptors for
58 * extracting the sequence number (SN) from the
59 * PDCP User Plane header.
61 #define PDCP_U_PLANE_18BIT_SN_MASK 0xFFFF0300
62 #define PDCP_U_PLANE_18BIT_SN_MASK_BE 0x0003FFFF
65 * PDCP_BEARER_MASK - This mask is used masking out the bearer for PDCP
66 * processing with SNOW f9 in LTE.
68 * The value on which this mask is applied is formatted as below:
69 * Count-C (32 bit) | Bearer (5 bit) | Direction (1 bit) | 0 (26 bits)
71 * Applying this mask is done for creating the upper 64 bits of the IV needed
74 * The lower 32 bits of the mask are used for masking the direction for AES
77 #define PDCP_BEARER_MASK 0x00000004FFFFFFFFull
78 #define PDCP_BEARER_MASK_BE 0xFFFFFFFF04000000ull
81 * PDCP_DIR_MASK - This mask is used masking out the direction for PDCP
82 * processing with SNOW f9 in LTE.
84 * The value on which this mask is applied is formatted as below:
85 * Bearer (5 bit) | Direction (1 bit) | 0 (26 bits)
87 * Applying this mask is done for creating the lower 32 bits of the IV needed
90 * The upper 32 bits of the mask are used for masking the direction for AES
93 #define PDCP_DIR_MASK 0x00000000000000F8ull
94 #define PDCP_DIR_MASK_BE 0xF800000000000000ull
97 * PDCP_NULL_INT_MAC_I_VAL - The value of the PDCP PDU MAC-I in case NULL
101 #define PDCP_NULL_INT_MAC_I_VAL 0x00000000
104 * PDCP_NULL_INT_ICV_CHECK_FAILED_STATUS - The status used to report ICV check
105 * failed in case of NULL integrity
106 * Control Plane processing.
108 #define PDCP_NULL_INT_ICV_CHECK_FAILED_STATUS 0x0A
110 * PDCP_DPOVRD_HFN_OV_EN - Value to be used in the FD status/cmd field to
111 * indicate the HFN override mechanism is active for the
114 #define PDCP_DPOVRD_HFN_OV_EN 0x80000000
117 * PDCP_P4080REV2_HFN_OV_BUFLEN - The length in bytes of the supplementary space
118 * that must be provided by the user at the
119 * beginning of the input frame buffer for
122 * The format of the frame buffer is the following:
124 * |<---PDCP_P4080REV2_HFN_OV_BUFLEN-->|
125 * //===================================||============||==============\\
126 * || PDCP_DPOVRD_HFN_OV_EN | HFN value || PDCP Header|| PDCP Payload ||
127 * \\===================================||============||==============//
129 * If HFN override mechanism is not desired, then the MSB of the first 4 bytes
132 #define PDCP_P4080REV2_HFN_OV_BUFLEN 4
135 * enum cipher_type_pdcp - Type selectors for cipher types in PDCP protocol OP
137 * @PDCP_CIPHER_TYPE_NULL: NULL
138 * @PDCP_CIPHER_TYPE_SNOW: SNOW F8
139 * @PDCP_CIPHER_TYPE_AES: AES
140 * @PDCP_CIPHER_TYPE_ZUC: ZUCE
141 * @PDCP_CIPHER_TYPE_INVALID: invalid option
143 enum cipher_type_pdcp {
144 PDCP_CIPHER_TYPE_NULL,
145 PDCP_CIPHER_TYPE_SNOW,
146 PDCP_CIPHER_TYPE_AES,
147 PDCP_CIPHER_TYPE_ZUC,
148 PDCP_CIPHER_TYPE_INVALID
152 * enum auth_type_pdcp - Type selectors for integrity types in PDCP protocol OP
154 * @PDCP_AUTH_TYPE_NULL: NULL
155 * @PDCP_AUTH_TYPE_SNOW: SNOW F9
156 * @PDCP_AUTH_TYPE_AES: AES CMAC
157 * @PDCP_AUTH_TYPE_ZUC: ZUCA
158 * @PDCP_AUTH_TYPE_INVALID: invalid option
160 enum auth_type_pdcp {
165 PDCP_AUTH_TYPE_INVALID
169 * enum pdcp_dir - Type selectors for direction for PDCP protocol
170 * @PDCP_DIR_UPLINK: uplink direction
171 * @PDCP_DIR_DOWNLINK: downlink direction
172 * @PDCP_DIR_INVALID: invalid option
176 PDCP_DIR_DOWNLINK = 1,
181 * enum pdcp_plane - PDCP domain selectors
182 * @PDCP_CONTROL_PLANE: Control Plane
183 * @PDCP_DATA_PLANE: Data Plane
184 * @PDCP_SHORT_MAC: Short MAC
193 * enum pdcp_sn_size - Sequence Number Size selectors for PDCP protocol
194 * @PDCP_SN_SIZE_5: 5bit sequence number
195 * @PDCP_SN_SIZE_7: 7bit sequence number
196 * @PDCP_SN_SIZE_12: 12bit sequence number
197 * @PDCP_SN_SIZE_15: 15bit sequence number
198 * @PDCP_SN_SIZE_18: 18bit sequence number
203 PDCP_SN_SIZE_12 = 12,
204 PDCP_SN_SIZE_15 = 15,
209 * PDCP Control Plane Protocol Data Blocks
211 #define PDCP_C_PLANE_PDB_HFN_SHIFT 5
212 #define PDCP_C_PLANE_PDB_BEARER_SHIFT 27
213 #define PDCP_C_PLANE_PDB_DIR_SHIFT 26
214 #define PDCP_C_PLANE_PDB_HFN_THR_SHIFT 5
216 #define PDCP_U_PLANE_PDB_OPT_SHORT_SN 0x2
217 #define PDCP_U_PLANE_PDB_OPT_15B_SN 0x4
218 #define PDCP_U_PLANE_PDB_OPT_18B_SN 0x6
219 #define PDCP_U_PLANE_PDB_SHORT_SN_HFN_SHIFT 7
220 #define PDCP_U_PLANE_PDB_LONG_SN_HFN_SHIFT 12
221 #define PDCP_U_PLANE_PDB_15BIT_SN_HFN_SHIFT 15
222 #define PDCP_U_PLANE_PDB_18BIT_SN_HFN_SHIFT 18
223 #define PDCP_U_PLANE_PDB_BEARER_SHIFT 27
224 #define PDCP_U_PLANE_PDB_DIR_SHIFT 26
225 #define PDCP_U_PLANE_PDB_SHORT_SN_HFN_THR_SHIFT 7
226 #define PDCP_U_PLANE_PDB_LONG_SN_HFN_THR_SHIFT 12
227 #define PDCP_U_PLANE_PDB_15BIT_SN_HFN_THR_SHIFT 15
228 #define PDCP_U_PLANE_PDB_18BIT_SN_HFN_THR_SHIFT 18
235 uint32_t hfn_res; /* HyperFrame number,(27, 25 or 21 bits),
236 * left aligned & right-padded with zeros.
238 uint32_t bearer_dir_res;/* Bearer(5 bits), packet direction (1 bit),
239 * left aligned & right-padded with zeros.
241 uint32_t hfn_thr_res; /* HyperFrame number threshold (27, 25 or 21
242 * bits), left aligned & right-padded with
248 * PDCP internal PDB types
251 PDCP_PDB_TYPE_NO_PDB,
252 PDCP_PDB_TYPE_FULL_PDB,
253 PDCP_PDB_TYPE_REDUCED_PDB,
254 PDCP_PDB_TYPE_INVALID
258 * Function for appending the portion of a PDCP Control Plane shared descriptor
259 * which performs NULL encryption and integrity (i.e. copies the input frame
260 * to the output frame, appending 32 bits of zeros at the end (MAC-I for
264 pdcp_insert_cplane_null_op(struct program *p,
265 bool swap __maybe_unused,
266 struct alginfo *cipherdata __maybe_unused,
267 struct alginfo *authdata __maybe_unused,
269 enum pdcp_sn_size sn_size __maybe_unused,
270 unsigned char era_2_sw_hfn_ovrd __maybe_unused)
273 REFERENCE(move_cmd_read_descbuf);
274 REFERENCE(move_cmd_write_descbuf);
276 if (rta_sec_era > RTA_SEC_ERA_2) {
277 MATHB(p, SEQINSZ, ADD, ZERO, VSEQINSZ, 4, 0);
278 if (dir == OP_TYPE_ENCAP_PROTOCOL)
279 MATHB(p, SEQINSZ, ADD, PDCP_MAC_I_LEN, VSEQOUTSZ, 4,
282 MATHB(p, SEQINSZ, SUB, PDCP_MAC_I_LEN, VSEQOUTSZ, 4,
285 MATHB(p, SEQINSZ, ADD, ONE, VSEQINSZ, 4, 0);
286 MATHB(p, VSEQINSZ, SUB, ONE, VSEQINSZ, 4, 0);
288 if (dir == OP_TYPE_ENCAP_PROTOCOL) {
289 MATHB(p, SEQINSZ, ADD, PDCP_MAC_I_LEN, VSEQOUTSZ, 4,
291 MATHB(p, VSEQINSZ, SUB, ONE, MATH0, 4, 0);
293 MATHB(p, VSEQINSZ, SUB, PDCP_MAC_I_LEN, VSEQINSZ, 4,
295 MATHB(p, SEQINSZ, SUB, PDCP_MAC_I_LEN, VSEQOUTSZ, 4,
297 MATHB(p, VSEQOUTSZ, SUB, ONE, MATH0, 4, 0);
300 MATHB(p, MATH0, ADD, ONE, MATH0, 4, 0);
303 * Since MOVELEN is available only starting with
304 * SEC ERA 3, use poor man's MOVELEN: create a MOVE
305 * command dynamically by writing the length from M1 by
306 * OR-ing the command in the M1 register and MOVE the
307 * result into the descriptor buffer. Care must be taken
308 * wrt. the location of the command because of SEC
309 * pipelining. The actual MOVEs are written at the end
310 * of the descriptor due to calculations needed on the
311 * offset in the descriptor for the MOVE command.
313 move_cmd_read_descbuf = MOVE(p, DESCBUF, 0, MATH0, 0, 6,
315 move_cmd_write_descbuf = MOVE(p, MATH0, 0, DESCBUF, 0, 8,
318 MATHB(p, VSEQINSZ, SUB, PDCP_NULL_MAX_FRAME_LEN, NONE, 4,
320 JUMP(p, PDCP_MAX_FRAME_LEN_STATUS, HALT_STATUS, ALL_FALSE, MATH_N);
322 if (rta_sec_era > RTA_SEC_ERA_2) {
323 if (dir == OP_TYPE_ENCAP_PROTOCOL)
324 MATHB(p, VSEQINSZ, ADD, ZERO, MATH0, 4, 0);
326 MATHB(p, VSEQOUTSZ, ADD, ZERO, MATH0, 4, 0);
328 SEQFIFOSTORE(p, MSG, 0, 0, VLF);
329 SEQFIFOLOAD(p, MSG1, 0, VLF | LAST1 | FLUSH1);
331 if (rta_sec_era > RTA_SEC_ERA_2) {
332 MOVE(p, AB1, 0, OFIFO, 0, MATH0, 0);
334 SET_LABEL(p, local_offset);
336 /* Shut off automatic Info FIFO entries */
337 LOAD(p, 0, DCTRL, LDOFF_DISABLE_AUTO_NFIFO, 0, IMMED);
338 /* Placeholder for MOVE command with length from M1 register */
339 MOVE(p, IFIFOAB1, 0, OFIFO, 0, 0, IMMED);
340 /* Enable automatic Info FIFO entries */
341 LOAD(p, 0, DCTRL, LDOFF_ENABLE_AUTO_NFIFO, 0, IMMED);
344 if (dir == OP_TYPE_ENCAP_PROTOCOL) {
345 MATHB(p, MATH1, XOR, MATH1, MATH0, 8, 0);
346 MOVE(p, MATH0, 0, OFIFO, 0, 4, IMMED);
349 if (rta_sec_era < RTA_SEC_ERA_3) {
350 PATCH_MOVE(p, move_cmd_read_descbuf, local_offset);
351 PATCH_MOVE(p, move_cmd_write_descbuf, local_offset);
358 insert_copy_frame_op(struct program *p,
359 struct alginfo *cipherdata __maybe_unused,
360 unsigned int dir __maybe_unused)
363 REFERENCE(move_cmd_read_descbuf);
364 REFERENCE(move_cmd_write_descbuf);
366 if (rta_sec_era > RTA_SEC_ERA_2) {
367 MATHB(p, SEQINSZ, ADD, ZERO, VSEQINSZ, 4, 0);
368 MATHB(p, SEQINSZ, ADD, ZERO, VSEQOUTSZ, 4, 0);
370 MATHB(p, SEQINSZ, ADD, ONE, VSEQINSZ, 4, 0);
371 MATHB(p, VSEQINSZ, SUB, ONE, VSEQINSZ, 4, 0);
372 MATHB(p, SEQINSZ, ADD, ONE, VSEQOUTSZ, 4, 0);
373 MATHB(p, VSEQOUTSZ, SUB, ONE, VSEQOUTSZ, 4, 0);
374 MATHB(p, VSEQINSZ, SUB, ONE, MATH0, 4, 0);
375 MATHB(p, MATH0, ADD, ONE, MATH0, 4, 0);
378 * Since MOVELEN is available only starting with
379 * SEC ERA 3, use poor man's MOVELEN: create a MOVE
380 * command dynamically by writing the length from M1 by
381 * OR-ing the command in the M1 register and MOVE the
382 * result into the descriptor buffer. Care must be taken
383 * wrt. the location of the command because of SEC
384 * pipelining. The actual MOVEs are written at the end
385 * of the descriptor due to calculations needed on the
386 * offset in the descriptor for the MOVE command.
388 move_cmd_read_descbuf = MOVE(p, DESCBUF, 0, MATH0, 0, 6,
390 move_cmd_write_descbuf = MOVE(p, MATH0, 0, DESCBUF, 0, 8,
393 MATHB(p, SEQINSZ, SUB, PDCP_NULL_MAX_FRAME_LEN, NONE, 4,
395 JUMP(p, PDCP_MAX_FRAME_LEN_STATUS, HALT_STATUS, ALL_FALSE, MATH_N);
397 if (rta_sec_era > RTA_SEC_ERA_2)
398 MATHB(p, VSEQINSZ, ADD, ZERO, MATH0, 4, 0);
400 SEQFIFOLOAD(p, MSG1, 0, VLF | LAST1 | FLUSH1);
401 if (rta_sec_era > RTA_SEC_ERA_2) {
402 MOVE(p, AB1, 0, OFIFO, 0, MATH0, 0);
404 SET_LABEL(p, local_offset);
406 /* Shut off automatic Info FIFO entries */
407 LOAD(p, 0, DCTRL, LDOFF_DISABLE_AUTO_NFIFO, 0, IMMED);
409 /* Placeholder for MOVE command with length from M0 register */
410 MOVE(p, IFIFOAB1, 0, OFIFO, 0, 0, IMMED);
412 /* Enable automatic Info FIFO entries */
413 LOAD(p, 0, DCTRL, LDOFF_ENABLE_AUTO_NFIFO, 0, IMMED);
416 SEQFIFOSTORE(p, MSG, 0, 0, VLF);
418 if (rta_sec_era < RTA_SEC_ERA_3) {
419 PATCH_MOVE(p, move_cmd_read_descbuf, local_offset);
420 PATCH_MOVE(p, move_cmd_write_descbuf, local_offset);
426 pdcp_insert_cplane_int_only_op(struct program *p,
427 bool swap __maybe_unused,
428 struct alginfo *cipherdata __maybe_unused,
429 struct alginfo *authdata, unsigned int dir,
430 enum pdcp_sn_size sn_size,
431 unsigned char era_2_sw_hfn_ovrd)
433 uint32_t offset = 0, length = 0, sn_mask = 0;
435 /* 12 bit SN is only supported for protocol offload case */
436 if (rta_sec_era >= RTA_SEC_ERA_8 && sn_size == PDCP_SN_SIZE_12) {
437 KEY(p, KEY2, authdata->key_enc_flags, authdata->key,
438 authdata->keylen, INLINE_KEY(authdata));
440 PROTOCOL(p, dir, OP_PCLID_LTE_PDCP_USER_RN,
441 (uint16_t)authdata->algtype);
445 /* Non-proto is supported only for 5bit cplane and 18bit uplane */
450 sn_mask = (swap == false) ? PDCP_C_PLANE_SN_MASK :
451 PDCP_C_PLANE_SN_MASK_BE;
453 case PDCP_SN_SIZE_18:
456 sn_mask = (swap == false) ? PDCP_U_PLANE_18BIT_SN_MASK :
457 PDCP_U_PLANE_18BIT_SN_MASK_BE;
460 case PDCP_SN_SIZE_12:
461 case PDCP_SN_SIZE_15:
462 pr_err("Invalid sn_size for %s\n", __func__);
467 REFERENCE(move_cmd_read_descbuf);
468 REFERENCE(move_cmd_write_descbuf);
470 switch (authdata->algtype) {
471 case PDCP_AUTH_TYPE_SNOW:
472 /* Insert Auth Key */
473 KEY(p, KEY2, authdata->key_enc_flags, authdata->key,
474 authdata->keylen, INLINE_KEY(authdata));
475 SEQLOAD(p, MATH0, offset, length, 0);
476 JUMP(p, 1, LOCAL_JUMP, ALL_TRUE, CALM);
478 if (rta_sec_era > RTA_SEC_ERA_2 ||
479 (rta_sec_era == RTA_SEC_ERA_2 &&
480 era_2_sw_hfn_ovrd == 0)) {
481 SEQINPTR(p, 0, length, RTO);
483 SEQINPTR(p, 0, 5, RTO);
484 SEQFIFOLOAD(p, SKIP, 4, 0);
488 MATHB(p, MATH0, AND, sn_mask, MATH1, 8,
490 MATHB(p, MATH1, SHLD, MATH1, MATH1, 8, 0);
492 MOVEB(p, DESCBUF, 8, MATH2, 0, 8, WAITCOMP | IMMED);
494 MATHB(p, MATH2, AND, PDCP_BEARER_MASK, MATH2, 8,
496 MOVEB(p, DESCBUF, 0x0C, MATH3, 0, 4, WAITCOMP | IMMED);
497 MATHB(p, MATH3, AND, PDCP_DIR_MASK, MATH3, 8, IMMED2);
498 MATHB(p, MATH1, OR, MATH2, MATH2, 8, 0);
499 MOVEB(p, MATH2, 0, CONTEXT2, 0, 0x0C, WAITCOMP | IMMED);
501 MATHB(p, MATH0, AND, sn_mask, MATH1, 8,
503 MATHB(p, MATH1, SHLD, MATH1, MATH1, 8, 0);
505 MOVE(p, DESCBUF, 8, MATH2, 0, 8, WAITCOMP | IMMED);
506 MATHB(p, MATH2, AND, PDCP_BEARER_MASK_BE, MATH2, 8,
509 MOVE(p, DESCBUF, 0x0C, MATH3, 0, 4, WAITCOMP | IMMED);
510 MATHB(p, MATH3, AND, PDCP_DIR_MASK_BE, MATH3, 8,
512 MATHB(p, MATH1, OR, MATH2, MATH2, 8, 0);
513 MOVE(p, MATH2, 0, CONTEXT2, 0, 0x0C, WAITCOMP | IMMED);
516 if (dir == OP_TYPE_DECAP_PROTOCOL) {
517 MATHB(p, SEQINSZ, SUB, PDCP_MAC_I_LEN, MATH1, 4,
520 if (rta_sec_era > RTA_SEC_ERA_2) {
521 MATHB(p, SEQINSZ, SUB, ZERO, MATH1, 4,
524 MATHB(p, SEQINSZ, ADD, ONE, MATH1, 4,
526 MATHB(p, MATH1, SUB, ONE, MATH1, 4,
531 if (rta_sec_era > RTA_SEC_ERA_2) {
532 MATHB(p, MATH1, SUB, ZERO, VSEQINSZ, 4, 0);
533 MATHB(p, MATH1, SUB, ZERO, VSEQOUTSZ, 4, 0);
535 MATHB(p, ZERO, ADD, MATH1, VSEQINSZ, 4, 0);
536 MATHB(p, ZERO, ADD, MATH1, VSEQOUTSZ, 4, 0);
539 * Since MOVELEN is available only starting with
540 * SEC ERA 3, use poor man's MOVELEN: create a MOVE
541 * command dynamically by writing the length from M1 by
542 * OR-ing the command in the M1 register and MOVE the
543 * result into the descriptor buffer. Care must be taken
544 * wrt. the location of the command because of SEC
545 * pipelining. The actual MOVEs are written at the end
546 * of the descriptor due to calculations needed on the
547 * offset in the descriptor for the MOVE command.
549 move_cmd_read_descbuf = MOVE(p, DESCBUF, 0, MATH1, 0, 6,
551 move_cmd_write_descbuf = MOVE(p, MATH1, 0, DESCBUF, 0,
552 8, WAITCOMP | IMMED);
555 SEQFIFOSTORE(p, MSG, 0, 0, VLF);
556 ALG_OPERATION(p, OP_ALG_ALGSEL_SNOW_F9, OP_ALG_AAI_F9,
558 dir == OP_TYPE_ENCAP_PROTOCOL ?
559 ICV_CHECK_DISABLE : ICV_CHECK_ENABLE,
562 if (rta_sec_era > RTA_SEC_ERA_2) {
563 SEQFIFOLOAD(p, MSGINSNOOP, 0,
564 VLF | LAST1 | LAST2 | FLUSH1);
565 MOVE(p, AB1, 0, OFIFO, 0, MATH1, 0);
567 SEQFIFOLOAD(p, MSGINSNOOP, 0,
568 VLF | LAST1 | LAST2 | FLUSH1);
569 SET_LABEL(p, local_offset);
571 /* Shut off automatic Info FIFO entries */
572 LOAD(p, 0, DCTRL, LDOFF_DISABLE_AUTO_NFIFO, 0, IMMED);
574 * Placeholder for MOVE command with length from M1
577 MOVE(p, IFIFOAB1, 0, OFIFO, 0, 0, IMMED);
578 /* Enable automatic Info FIFO entries */
579 LOAD(p, 0, DCTRL, LDOFF_ENABLE_AUTO_NFIFO, 0, IMMED);
582 if (dir == OP_TYPE_DECAP_PROTOCOL)
583 SEQFIFOLOAD(p, ICV2, 4, LAST2);
585 SEQSTORE(p, CONTEXT2, 0, 4, 0);
589 case PDCP_AUTH_TYPE_AES:
590 /* Insert Auth Key */
591 KEY(p, KEY1, authdata->key_enc_flags, authdata->key,
592 authdata->keylen, INLINE_KEY(authdata));
593 SEQLOAD(p, MATH0, offset, length, 0);
594 JUMP(p, 1, LOCAL_JUMP, ALL_TRUE, CALM);
595 if (rta_sec_era > RTA_SEC_ERA_2 ||
596 (rta_sec_era == RTA_SEC_ERA_2 &&
597 era_2_sw_hfn_ovrd == 0)) {
598 SEQINPTR(p, 0, length, RTO);
600 SEQINPTR(p, 0, 5, RTO);
601 SEQFIFOLOAD(p, SKIP, 4, 0);
605 MATHB(p, MATH0, AND, sn_mask, MATH1, 8,
607 MATHB(p, MATH1, SHLD, MATH1, MATH1, 8, 0);
609 MOVEB(p, DESCBUF, 8, MATH2, 0, 8, WAITCOMP | IMMED);
610 MATHB(p, MATH1, OR, MATH2, MATH2, 8, 0);
611 MOVEB(p, MATH2, 0, IFIFOAB1, 0, 8, IMMED);
613 MATHB(p, MATH0, AND, sn_mask, MATH1, 8,
615 MATHB(p, MATH1, SHLD, MATH1, MATH1, 8, 0);
617 MOVE(p, DESCBUF, 8, MATH2, 0, 8, WAITCOMP | IMMED);
618 MATHB(p, MATH1, OR, MATH2, MATH2, 8, 0);
619 MOVE(p, MATH2, 0, IFIFOAB1, 0, 8, IMMED);
622 if (dir == OP_TYPE_DECAP_PROTOCOL) {
623 MATHB(p, SEQINSZ, SUB, PDCP_MAC_I_LEN, MATH1, 4,
626 if (rta_sec_era > RTA_SEC_ERA_2) {
627 MATHB(p, SEQINSZ, SUB, ZERO, MATH1, 4,
630 MATHB(p, SEQINSZ, ADD, ONE, MATH1, 4,
632 MATHB(p, MATH1, SUB, ONE, MATH1, 4,
637 if (rta_sec_era > RTA_SEC_ERA_2) {
638 MATHB(p, MATH1, SUB, ZERO, VSEQINSZ, 4, 0);
639 MATHB(p, MATH1, SUB, ZERO, VSEQOUTSZ, 4, 0);
641 MATHB(p, ZERO, ADD, MATH1, VSEQINSZ, 4, 0);
642 MATHB(p, ZERO, ADD, MATH1, VSEQOUTSZ, 4, 0);
645 * Since MOVELEN is available only starting with
646 * SEC ERA 3, use poor man's MOVELEN: create a MOVE
647 * command dynamically by writing the length from M1 by
648 * OR-ing the command in the M1 register and MOVE the
649 * result into the descriptor buffer. Care must be taken
650 * wrt. the location of the command because of SEC
651 * pipelining. The actual MOVEs are written at the end
652 * of the descriptor due to calculations needed on the
653 * offset in the descriptor for the MOVE command.
655 move_cmd_read_descbuf = MOVE(p, DESCBUF, 0, MATH1, 0, 6,
657 move_cmd_write_descbuf = MOVE(p, MATH1, 0, DESCBUF, 0,
658 8, WAITCOMP | IMMED);
660 SEQFIFOSTORE(p, MSG, 0, 0, VLF);
661 ALG_OPERATION(p, OP_ALG_ALGSEL_AES,
664 dir == OP_TYPE_ENCAP_PROTOCOL ?
665 ICV_CHECK_DISABLE : ICV_CHECK_ENABLE,
668 if (rta_sec_era > RTA_SEC_ERA_2) {
669 MOVE(p, AB2, 0, OFIFO, 0, MATH1, 0);
670 SEQFIFOLOAD(p, MSGINSNOOP, 0,
671 VLF | LAST1 | LAST2 | FLUSH1);
673 SEQFIFOLOAD(p, MSGINSNOOP, 0,
674 VLF | LAST1 | LAST2 | FLUSH1);
675 SET_LABEL(p, local_offset);
677 /* Shut off automatic Info FIFO entries */
678 LOAD(p, 0, DCTRL, LDOFF_DISABLE_AUTO_NFIFO, 0, IMMED);
681 * Placeholder for MOVE command with length from
684 MOVE(p, IFIFOAB2, 0, OFIFO, 0, 0, IMMED);
686 /* Enable automatic Info FIFO entries */
687 LOAD(p, 0, DCTRL, LDOFF_ENABLE_AUTO_NFIFO, 0, IMMED);
690 if (dir == OP_TYPE_DECAP_PROTOCOL)
691 SEQFIFOLOAD(p, ICV1, 4, LAST1 | FLUSH1);
693 SEQSTORE(p, CONTEXT1, 0, 4, 0);
697 case PDCP_AUTH_TYPE_ZUC:
698 if (rta_sec_era < RTA_SEC_ERA_5) {
699 pr_err("Invalid era for selected algorithm\n");
702 /* Insert Auth Key */
703 KEY(p, KEY2, authdata->key_enc_flags, authdata->key,
704 authdata->keylen, INLINE_KEY(authdata));
705 SEQLOAD(p, MATH0, offset, length, 0);
706 JUMP(p, 1, LOCAL_JUMP, ALL_TRUE, CALM);
707 SEQINPTR(p, 0, length, RTO);
709 MATHB(p, MATH0, AND, sn_mask, MATH1, 8,
711 MATHB(p, MATH1, SHLD, MATH1, MATH1, 8, 0);
713 MOVEB(p, DESCBUF, 8, MATH2, 0, 8, WAITCOMP | IMMED);
714 MATHB(p, MATH1, OR, MATH2, MATH2, 8, 0);
715 MOVEB(p, MATH2, 0, CONTEXT2, 0, 8, IMMED);
718 MATHB(p, MATH0, AND, sn_mask, MATH1, 8,
720 MATHB(p, MATH1, SHLD, MATH1, MATH1, 8, 0);
722 MOVE(p, DESCBUF, 8, MATH2, 0, 8, WAITCOMP | IMMED);
723 MATHB(p, MATH1, OR, MATH2, MATH2, 8, 0);
724 MOVE(p, MATH2, 0, CONTEXT2, 0, 8, IMMED);
726 if (dir == OP_TYPE_DECAP_PROTOCOL)
727 MATHB(p, SEQINSZ, SUB, PDCP_MAC_I_LEN, MATH1, 4,
730 MATHB(p, SEQINSZ, SUB, ZERO, MATH1, 4, 0);
732 MATHB(p, MATH1, SUB, ZERO, VSEQINSZ, 4, 0);
733 MATHB(p, MATH1, SUB, ZERO, VSEQOUTSZ, 4, 0);
734 SEQFIFOSTORE(p, MSG, 0, 0, VLF);
735 ALG_OPERATION(p, OP_ALG_ALGSEL_ZUCA,
738 dir == OP_TYPE_ENCAP_PROTOCOL ?
739 ICV_CHECK_DISABLE : ICV_CHECK_ENABLE,
741 SEQFIFOLOAD(p, MSGINSNOOP, 0, VLF | LAST1 | LAST2 | FLUSH1);
742 MOVE(p, AB1, 0, OFIFO, 0, MATH1, 0);
744 if (dir == OP_TYPE_DECAP_PROTOCOL)
745 SEQFIFOLOAD(p, ICV2, 4, LAST2);
747 SEQSTORE(p, CONTEXT2, 0, 4, 0);
752 pr_err("%s: Invalid integrity algorithm selected: %d\n",
753 "pdcp_insert_cplane_int_only_op", authdata->algtype);
757 if (rta_sec_era < RTA_SEC_ERA_3) {
758 PATCH_MOVE(p, move_cmd_read_descbuf, local_offset);
759 PATCH_MOVE(p, move_cmd_write_descbuf, local_offset);
766 pdcp_insert_cplane_enc_only_op(struct program *p,
767 bool swap __maybe_unused,
768 struct alginfo *cipherdata,
769 struct alginfo *authdata __maybe_unused,
771 enum pdcp_sn_size sn_size,
772 unsigned char era_2_sw_hfn_ovrd __maybe_unused)
774 uint32_t offset = 0, length = 0, sn_mask = 0;
775 /* Insert Cipher Key */
776 KEY(p, KEY1, cipherdata->key_enc_flags, cipherdata->key,
777 cipherdata->keylen, INLINE_KEY(cipherdata));
779 if (rta_sec_era >= RTA_SEC_ERA_8 && sn_size != PDCP_SN_SIZE_18) {
780 if (sn_size == PDCP_SN_SIZE_5)
781 PROTOCOL(p, dir, OP_PCLID_LTE_PDCP_CTRL_MIXED,
782 (uint16_t)cipherdata->algtype << 8);
784 PROTOCOL(p, dir, OP_PCLID_LTE_PDCP_USER_RN,
785 (uint16_t)cipherdata->algtype << 8);
788 /* Non-proto is supported only for 5bit cplane and 18bit uplane */
793 sn_mask = (swap == false) ? PDCP_C_PLANE_SN_MASK :
794 PDCP_C_PLANE_SN_MASK_BE;
796 case PDCP_SN_SIZE_18:
799 sn_mask = (swap == false) ? PDCP_U_PLANE_18BIT_SN_MASK :
800 PDCP_U_PLANE_18BIT_SN_MASK_BE;
803 case PDCP_SN_SIZE_12:
804 case PDCP_SN_SIZE_15:
805 pr_err("Invalid sn_size for %s\n", __func__);
810 SEQLOAD(p, MATH0, offset, length, 0);
811 JUMP(p, 1, LOCAL_JUMP, ALL_TRUE, CALM);
812 MATHB(p, MATH0, AND, sn_mask, MATH1, 8, IFB | IMMED2);
813 SEQSTORE(p, MATH0, offset, length, 0);
814 MATHB(p, MATH1, SHLD, MATH1, MATH1, 8, 0);
815 MOVEB(p, DESCBUF, 8, MATH2, 0, 8, WAITCOMP | IMMED);
816 MATHB(p, MATH1, OR, MATH2, MATH2, 8, 0);
818 switch (cipherdata->algtype) {
819 case PDCP_CIPHER_TYPE_SNOW:
820 MOVEB(p, MATH2, 0, CONTEXT1, 0, 8, WAITCOMP | IMMED);
822 if (rta_sec_era > RTA_SEC_ERA_2) {
823 MATHB(p, SEQINSZ, SUB, ZERO, VSEQINSZ, 4, 0);
825 MATHB(p, SEQINSZ, SUB, ONE, MATH1, 4, 0);
826 MATHB(p, MATH1, ADD, ONE, VSEQINSZ, 4, 0);
829 if (dir == OP_TYPE_ENCAP_PROTOCOL)
830 MATHB(p, SEQINSZ, ADD, PDCP_MAC_I_LEN, VSEQOUTSZ, 4,
833 MATHB(p, SEQINSZ, SUB, PDCP_MAC_I_LEN, VSEQOUTSZ, 4,
835 SEQFIFOSTORE(p, MSG, 0, 0, VLF | CONT);
836 ALG_OPERATION(p, OP_ALG_ALGSEL_SNOW_F8,
838 OP_ALG_AS_INITFINAL, ICV_CHECK_DISABLE,
839 dir == OP_TYPE_ENCAP_PROTOCOL ?
843 case PDCP_CIPHER_TYPE_AES:
844 MOVEB(p, MATH2, 0, CONTEXT1, 0x10, 0x10, WAITCOMP | IMMED);
846 if (rta_sec_era > RTA_SEC_ERA_2) {
847 MATHB(p, SEQINSZ, SUB, ZERO, VSEQINSZ, 4, 0);
849 MATHB(p, SEQINSZ, SUB, ONE, MATH1, 4, 0);
850 MATHB(p, MATH1, ADD, ONE, VSEQINSZ, 4, 0);
853 if (dir == OP_TYPE_ENCAP_PROTOCOL)
854 MATHB(p, SEQINSZ, ADD, PDCP_MAC_I_LEN, VSEQOUTSZ, 4,
857 MATHB(p, SEQINSZ, SUB, PDCP_MAC_I_LEN, VSEQOUTSZ, 4,
860 SEQFIFOSTORE(p, MSG, 0, 0, VLF | CONT);
861 ALG_OPERATION(p, OP_ALG_ALGSEL_AES,
865 dir == OP_TYPE_ENCAP_PROTOCOL ?
869 case PDCP_CIPHER_TYPE_ZUC:
870 if (rta_sec_era < RTA_SEC_ERA_5) {
871 pr_err("Invalid era for selected algorithm\n");
875 MOVEB(p, MATH2, 0, CONTEXT1, 0, 0x08, IMMED);
876 MOVEB(p, MATH2, 0, CONTEXT1, 0x08, 0x08, WAITCOMP | IMMED);
877 MATHB(p, SEQINSZ, SUB, ZERO, VSEQINSZ, 4, 0);
878 if (dir == OP_TYPE_ENCAP_PROTOCOL)
879 MATHB(p, SEQINSZ, ADD, PDCP_MAC_I_LEN, VSEQOUTSZ, 4,
882 MATHB(p, SEQINSZ, SUB, PDCP_MAC_I_LEN, VSEQOUTSZ, 4,
885 SEQFIFOSTORE(p, MSG, 0, 0, VLF | CONT);
886 ALG_OPERATION(p, OP_ALG_ALGSEL_ZUCE,
890 dir == OP_TYPE_ENCAP_PROTOCOL ?
895 pr_err("%s: Invalid encrypt algorithm selected: %d\n",
896 "pdcp_insert_cplane_enc_only_op", cipherdata->algtype);
900 if (dir == OP_TYPE_ENCAP_PROTOCOL) {
901 SEQFIFOLOAD(p, MSG1, 0, VLF);
902 FIFOLOAD(p, MSG1, PDCP_NULL_INT_MAC_I_VAL, 4,
903 LAST1 | FLUSH1 | IMMED);
905 SEQFIFOLOAD(p, MSG1, 0, VLF | LAST1 | FLUSH1);
906 MOVE(p, OFIFO, 0, MATH1, 4, PDCP_MAC_I_LEN, WAITCOMP | IMMED);
907 MATHB(p, MATH1, XOR, PDCP_NULL_INT_MAC_I_VAL, NONE, 4, IMMED2);
908 JUMP(p, PDCP_NULL_INT_ICV_CHECK_FAILED_STATUS,
909 HALT_STATUS, ALL_FALSE, MATH_Z);
916 pdcp_insert_cplane_acc_op(struct program *p,
917 bool swap __maybe_unused,
918 struct alginfo *cipherdata,
919 struct alginfo *authdata,
921 enum pdcp_sn_size sn_size,
922 unsigned char era_2_hfn_ovrd __maybe_unused)
924 /* Insert Auth Key */
925 KEY(p, KEY2, authdata->key_enc_flags, authdata->key, authdata->keylen,
926 INLINE_KEY(authdata));
928 /* Insert Cipher Key */
929 KEY(p, KEY1, cipherdata->key_enc_flags, cipherdata->key,
930 cipherdata->keylen, INLINE_KEY(cipherdata));
932 if (sn_size == PDCP_SN_SIZE_5)
933 PROTOCOL(p, dir, OP_PCLID_LTE_PDCP_CTRL,
934 (uint16_t)cipherdata->algtype);
936 PROTOCOL(p, dir, OP_PCLID_LTE_PDCP_USER_RN,
937 ((uint16_t)cipherdata->algtype << 8) |
938 (uint16_t)authdata->algtype);
944 pdcp_insert_cplane_snow_aes_op(struct program *p,
945 bool swap __maybe_unused,
946 struct alginfo *cipherdata,
947 struct alginfo *authdata,
949 enum pdcp_sn_size sn_size,
950 unsigned char era_2_sw_hfn_ovrd)
952 uint32_t offset = 0, length = 0, sn_mask = 0;
954 LABEL(back_to_sd_offset);
957 LABEL(jump_to_beginning);
958 LABEL(fifo_load_mac_i_offset);
959 REFERENCE(seqin_ptr_read);
960 REFERENCE(seqin_ptr_write);
961 REFERENCE(seq_out_read);
962 REFERENCE(jump_back_to_sd_cmd);
963 REFERENCE(move_mac_i_to_desc_buf);
965 if (rta_sec_era >= RTA_SEC_ERA_8 && sn_size != PDCP_SN_SIZE_18) {
966 KEY(p, KEY1, cipherdata->key_enc_flags, cipherdata->key,
967 cipherdata->keylen, INLINE_KEY(cipherdata));
968 KEY(p, KEY2, authdata->key_enc_flags, authdata->key,
969 authdata->keylen, INLINE_KEY(authdata));
971 if (sn_size == PDCP_SN_SIZE_5)
972 PROTOCOL(p, dir, OP_PCLID_LTE_PDCP_CTRL_MIXED,
973 ((uint16_t)cipherdata->algtype << 8) |
974 (uint16_t)authdata->algtype);
976 PROTOCOL(p, dir, OP_PCLID_LTE_PDCP_USER_RN,
977 ((uint16_t)cipherdata->algtype << 8) |
978 (uint16_t)authdata->algtype);
982 /* Non-proto is supported only for 5bit cplane and 18bit uplane */
987 sn_mask = (swap == false) ? PDCP_C_PLANE_SN_MASK :
988 PDCP_C_PLANE_SN_MASK_BE;
990 case PDCP_SN_SIZE_18:
993 sn_mask = (swap == false) ? PDCP_U_PLANE_18BIT_SN_MASK :
994 PDCP_U_PLANE_18BIT_SN_MASK_BE;
997 case PDCP_SN_SIZE_12:
998 case PDCP_SN_SIZE_15:
999 pr_err("Invalid sn_size for %s\n", __func__);
1004 SEQLOAD(p, MATH0, offset, length, 0);
1005 JUMP(p, 1, LOCAL_JUMP, ALL_TRUE, CALM);
1006 MATHB(p, MATH0, AND, sn_mask, MATH1, 8, IFB | IMMED2);
1007 MATHB(p, MATH1, SHLD, MATH1, MATH1, 8, 0);
1008 MOVE(p, DESCBUF, 4, MATH2, 0, 0x08, WAITCOMP | IMMED);
1009 MATHB(p, MATH1, OR, MATH2, MATH2, 8, 0);
1010 SEQSTORE(p, MATH0, offset, length, 0);
1011 if (dir == OP_TYPE_ENCAP_PROTOCOL) {
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 SEQINPTR(p, 0, 1, RTO);
1017 SEQINPTR(p, 0, 5, RTO);
1018 SEQFIFOLOAD(p, SKIP, 4, 0);
1020 KEY(p, KEY1, authdata->key_enc_flags, authdata->key,
1021 authdata->keylen, INLINE_KEY(authdata));
1022 MOVE(p, MATH2, 0, IFIFOAB1, 0, 0x08, IMMED);
1024 if (rta_sec_era > RTA_SEC_ERA_2) {
1025 MATHB(p, SEQINSZ, SUB, ZERO, VSEQINSZ, 4, 0);
1026 MATHB(p, SEQINSZ, SUB, ZERO, MATH1, 4, 0);
1027 MATHB(p, VSEQINSZ, ADD, PDCP_MAC_I_LEN - 1, VSEQOUTSZ,
1030 MATHB(p, SEQINSZ, SUB, MATH3, VSEQINSZ, 4, 0);
1031 MATHB(p, VSEQINSZ, ADD, PDCP_MAC_I_LEN - 1, VSEQOUTSZ,
1034 * Note: Although the calculations below might seem a
1035 * little off, the logic is the following:
1037 * - SEQ IN PTR RTO below needs the full length of the
1038 * frame; in case of P4080_REV_2_HFN_OV_WORKAROUND,
1039 * this means the length of the frame to be processed
1040 * + 4 bytes (the HFN override flag and value).
1041 * The length of the frame to be processed minus 1
1042 * byte is in the VSIL register (because
1043 * VSIL = SIL + 3, due to 1 byte, the header being
1044 * already written by the SEQ STORE above). So for
1045 * calculating the length to use in RTO, I add one
1046 * to the VSIL value in order to obtain the total
1047 * frame length. This helps in case of P4080 which
1048 * can have the value 0 as an operand in a MATH
1049 * command only as SRC1 When the HFN override
1050 * workaround is not enabled, the length of the
1051 * frame is given by the SIL register; the
1052 * calculation is similar to the one in the SEC 4.2
1053 * and SEC 5.3 cases.
1055 if (era_2_sw_hfn_ovrd)
1056 MATHB(p, VSEQOUTSZ, ADD, ONE, MATH1, 4,
1059 MATHB(p, SEQINSZ, ADD, MATH3, MATH1, 4,
1063 * Placeholder for filling the length in
1064 * SEQIN PTR RTO below
1066 seqin_ptr_read = MOVE(p, DESCBUF, 0, MATH1, 0, 6, IMMED);
1067 seqin_ptr_write = MOVE(p, MATH1, 0, DESCBUF, 0, 8,
1069 ALG_OPERATION(p, OP_ALG_ALGSEL_AES,
1071 OP_ALG_AS_INITFINAL,
1074 SEQFIFOLOAD(p, MSG1, 0, VLF | LAST1 | FLUSH1);
1075 MOVE(p, CONTEXT1, 0, MATH3, 0, 4, WAITCOMP | IMMED);
1076 if (rta_sec_era <= RTA_SEC_ERA_3)
1077 LOAD(p, CLRW_CLR_C1KEY |
1084 LOAD(p, CLRW_RESET_CLS1_CHA |
1092 if (rta_sec_era <= RTA_SEC_ERA_3)
1093 LOAD(p, CCTRL_RESET_CHA_ALL, CCTRL, 0, 4, IMMED);
1095 KEY(p, KEY1, cipherdata->key_enc_flags, cipherdata->key,
1096 cipherdata->keylen, INLINE_KEY(cipherdata));
1097 SET_LABEL(p, local_offset);
1098 MOVE(p, MATH2, 0, CONTEXT1, 0, 8, IMMED);
1099 SEQINPTR(p, 0, 0, RTO);
1101 if (rta_sec_era == RTA_SEC_ERA_2 && era_2_sw_hfn_ovrd) {
1102 SEQFIFOLOAD(p, SKIP, 5, 0);
1103 MATHB(p, SEQINSZ, ADD, ONE, SEQINSZ, 4, 0);
1106 MATHB(p, SEQINSZ, SUB, ONE, VSEQINSZ, 4, 0);
1107 ALG_OPERATION(p, OP_ALG_ALGSEL_SNOW_F8,
1109 OP_ALG_AS_INITFINAL,
1112 SEQFIFOSTORE(p, MSG, 0, 0, VLF);
1114 if (rta_sec_era > RTA_SEC_ERA_2 ||
1115 (rta_sec_era == RTA_SEC_ERA_2 &&
1116 era_2_sw_hfn_ovrd == 0))
1117 SEQFIFOLOAD(p, SKIP, 1, 0);
1119 SEQFIFOLOAD(p, MSG1, 0, VLF);
1120 MOVE(p, MATH3, 0, IFIFOAB1, 0, 4, LAST1 | FLUSH1 | IMMED);
1121 PATCH_MOVE(p, seqin_ptr_read, local_offset);
1122 PATCH_MOVE(p, seqin_ptr_write, local_offset);
1124 MOVE(p, MATH2, 0, CONTEXT1, 0, 8, IMMED);
1126 if (rta_sec_era >= RTA_SEC_ERA_5)
1127 MOVE(p, CONTEXT1, 0, CONTEXT2, 0, 8, IMMED);
1129 if (rta_sec_era > RTA_SEC_ERA_2)
1130 MATHB(p, SEQINSZ, SUB, ZERO, VSEQINSZ, 4, 0);
1132 MATHB(p, SEQINSZ, SUB, MATH3, VSEQINSZ, 4, 0);
1134 MATHB(p, SEQINSZ, SUB, PDCP_MAC_I_LEN, VSEQOUTSZ, 4, IMMED2);
1136 * TODO: To be changed when proper support is added in RTA (can't load a
1137 * command that is also written by RTA (or patch it for that matter).
1138 * Change when proper RTA support is added.
1141 WORD(p, 0x168B0004);
1143 WORD(p, 0x16880404);
1145 jump_back_to_sd_cmd = JUMP(p, 0, LOCAL_JUMP, ALL_TRUE, 0);
1147 * Placeholder for command reading the SEQ OUT command in
1148 * JD. Done for rereading the decrypted data and performing
1149 * the integrity check
1152 * TODO: RTA currently doesn't support patching of length of a MOVE command
1153 * Thus, it is inserted as a raw word, as per PS setting.
1156 seq_out_read = MOVE(p, DESCBUF, 0, MATH1, 0, 20,
1159 seq_out_read = MOVE(p, DESCBUF, 0, MATH1, 0, 16,
1162 MATHB(p, MATH1, XOR, CMD_SEQ_IN_PTR ^ CMD_SEQ_OUT_PTR, MATH1, 4,
1164 /* Placeholder for overwriting the SEQ IN with SEQ OUT */
1166 * TODO: RTA currently doesn't support patching of length of a MOVE command
1167 * Thus, it is inserted as a raw word, as per PS setting.
1170 MOVE(p, MATH1, 0, DESCBUF, 0, 24, IMMED);
1172 MOVE(p, MATH1, 0, DESCBUF, 0, 20, IMMED);
1174 KEY(p, KEY1, cipherdata->key_enc_flags, cipherdata->key,
1175 cipherdata->keylen, INLINE_KEY(cipherdata));
1177 if (rta_sec_era >= RTA_SEC_ERA_4)
1178 MOVE(p, CONTEXT1, 0, CONTEXT2, 0, 8, IMMED);
1180 MOVE(p, CONTEXT1, 0, MATH3, 0, 8, IMMED);
1182 ALG_OPERATION(p, OP_ALG_ALGSEL_SNOW_F8,
1184 OP_ALG_AS_INITFINAL,
1187 SEQFIFOSTORE(p, MSG, 0, 0, VLF | CONT);
1188 SEQFIFOLOAD(p, MSG1, 0, VLF | LAST1 | FLUSH1);
1190 if (rta_sec_era <= RTA_SEC_ERA_3)
1191 move_mac_i_to_desc_buf = MOVE(p, OFIFO, 0, DESCBUF, 0,
1192 4, WAITCOMP | IMMED);
1194 MOVE(p, OFIFO, 0, MATH3, 0, 4, IMMED);
1196 if (rta_sec_era <= RTA_SEC_ERA_3)
1197 LOAD(p, CCTRL_RESET_CHA_ALL, CCTRL, 0, 4, IMMED);
1199 LOAD(p, CLRW_RESET_CLS1_CHA |
1207 KEY(p, KEY1, authdata->key_enc_flags, authdata->key,
1208 authdata->keylen, INLINE_KEY(authdata));
1210 * Placeholder for jump in SD for executing the new SEQ IN PTR
1211 * command (which is actually the old SEQ OUT PTR command
1212 * copied over from JD.
1214 SET_LABEL(p, jump_to_beginning);
1215 JUMP(p, 1 - jump_to_beginning, LOCAL_JUMP, ALL_TRUE, 0);
1216 SET_LABEL(p, back_to_sd_offset);
1217 ALG_OPERATION(p, OP_ALG_ALGSEL_AES,
1219 OP_ALG_AS_INITFINAL,
1223 /* Read the # of bytes written in the output buffer + 1 (HDR) */
1224 MATHB(p, VSEQOUTSZ, ADD, ONE, VSEQINSZ, 4, 0);
1226 if (rta_sec_era <= RTA_SEC_ERA_3)
1227 MOVE(p, MATH3, 0, IFIFOAB1, 0, 8, IMMED);
1229 MOVE(p, CONTEXT2, 0, IFIFOAB1, 0, 8, IMMED);
1231 if (rta_sec_era == RTA_SEC_ERA_2 && era_2_sw_hfn_ovrd)
1232 SEQFIFOLOAD(p, SKIP, 4, 0);
1234 SEQFIFOLOAD(p, MSG1, 0, VLF | LAST1 | FLUSH1);
1236 if (rta_sec_era >= RTA_SEC_ERA_4) {
1237 LOAD(p, NFIFOENTRY_STYPE_ALTSOURCE |
1238 NFIFOENTRY_DEST_CLASS1 |
1239 NFIFOENTRY_DTYPE_ICV |
1241 NFIFOENTRY_FC1 | 4, NFIFO_SZL, 0, 4, IMMED);
1242 MOVE(p, MATH3, 0, ALTSOURCE, 0, 4, IMMED);
1244 SET_LABEL(p, fifo_load_mac_i_offset);
1245 FIFOLOAD(p, ICV1, fifo_load_mac_i_offset, 4,
1246 LAST1 | FLUSH1 | IMMED);
1249 SET_LABEL(p, end_desc);
1252 PATCH_MOVE(p, seq_out_read, end_desc + 1);
1253 PATCH_JUMP(p, jump_back_to_sd_cmd,
1254 back_to_sd_offset + jump_back_to_sd_cmd - 5);
1256 if (rta_sec_era <= RTA_SEC_ERA_3)
1257 PATCH_MOVE(p, move_mac_i_to_desc_buf,
1258 fifo_load_mac_i_offset + 1);
1260 PATCH_MOVE(p, seq_out_read, end_desc + 2);
1261 PATCH_JUMP(p, jump_back_to_sd_cmd,
1262 back_to_sd_offset + jump_back_to_sd_cmd - 5);
1264 if (rta_sec_era <= RTA_SEC_ERA_3)
1265 PATCH_MOVE(p, move_mac_i_to_desc_buf,
1266 fifo_load_mac_i_offset + 1);
1274 pdcp_insert_cplane_aes_snow_op(struct program *p,
1275 bool swap __maybe_unused,
1276 struct alginfo *cipherdata,
1277 struct alginfo *authdata,
1279 enum pdcp_sn_size sn_size,
1280 unsigned char era_2_sw_hfn_ovrd __maybe_unused)
1282 uint32_t offset = 0, length = 0, sn_mask = 0;
1284 KEY(p, KEY1, cipherdata->key_enc_flags, cipherdata->key,
1285 cipherdata->keylen, INLINE_KEY(cipherdata));
1286 KEY(p, KEY2, authdata->key_enc_flags, authdata->key, authdata->keylen,
1287 INLINE_KEY(authdata));
1289 if (rta_sec_era >= RTA_SEC_ERA_8 && sn_size != PDCP_SN_SIZE_18) {
1292 if (sn_size == PDCP_SN_SIZE_5)
1293 pclid = OP_PCLID_LTE_PDCP_CTRL_MIXED;
1295 pclid = OP_PCLID_LTE_PDCP_USER_RN;
1297 PROTOCOL(p, dir, pclid,
1298 ((uint16_t)cipherdata->algtype << 8) |
1299 (uint16_t)authdata->algtype);
1303 /* Non-proto is supported only for 5bit cplane and 18bit uplane */
1305 case PDCP_SN_SIZE_5:
1308 sn_mask = (swap == false) ? PDCP_C_PLANE_SN_MASK :
1309 PDCP_C_PLANE_SN_MASK_BE;
1311 case PDCP_SN_SIZE_18:
1314 sn_mask = (swap == false) ? PDCP_U_PLANE_18BIT_SN_MASK :
1315 PDCP_U_PLANE_18BIT_SN_MASK_BE;
1317 case PDCP_SN_SIZE_7:
1318 case PDCP_SN_SIZE_12:
1319 case PDCP_SN_SIZE_15:
1320 pr_err("Invalid sn_size for %s\n", __func__);
1325 if (dir == OP_TYPE_ENCAP_PROTOCOL)
1326 MATHB(p, SEQINSZ, SUB, ONE, VSEQINSZ, 4, 0);
1328 SEQLOAD(p, MATH0, offset, length, 0);
1329 JUMP(p, 1, LOCAL_JUMP, ALL_TRUE, CALM);
1330 MOVE(p, MATH0, 7, IFIFOAB2, 0, 1, IMMED);
1331 MATHB(p, MATH0, AND, sn_mask, MATH1, 8, IFB | IMMED2);
1333 SEQSTORE(p, MATH0, offset, length, 0);
1334 MATHB(p, MATH1, SHLD, MATH1, MATH1, 8, 0);
1335 MOVE(p, DESCBUF, 4, MATH2, 0, 8, WAITCOMP | IMMED);
1336 MATHB(p, MATH1, OR, MATH2, MATH1, 8, 0);
1337 MOVE(p, MATH1, 0, CONTEXT1, 16, 8, IMMED);
1338 MOVE(p, MATH1, 0, CONTEXT2, 0, 4, IMMED);
1339 if (swap == false) {
1340 MATHB(p, MATH1, AND, lower_32_bits(PDCP_BEARER_MASK), MATH2, 4,
1342 MATHB(p, MATH1, AND, upper_32_bits(PDCP_DIR_MASK), MATH3, 4,
1345 MATHB(p, MATH1, AND, lower_32_bits(PDCP_BEARER_MASK_BE), MATH2,
1347 MATHB(p, MATH1, AND, upper_32_bits(PDCP_DIR_MASK_BE), MATH3,
1350 MATHB(p, MATH3, SHLD, MATH3, MATH3, 8, 0);
1351 MOVE(p, MATH2, 4, OFIFO, 0, 12, IMMED);
1352 MOVE(p, OFIFO, 0, CONTEXT2, 4, 12, IMMED);
1353 if (dir == OP_TYPE_ENCAP_PROTOCOL) {
1354 MATHB(p, SEQINSZ, ADD, PDCP_MAC_I_LEN, VSEQOUTSZ, 4, IMMED2);
1356 MATHB(p, SEQINSZ, SUB, PDCP_MAC_I_LEN, MATH1, 4, IMMED2);
1358 MATHB(p, ZERO, ADD, MATH1, VSEQOUTSZ, 4, 0);
1359 MATHB(p, ZERO, ADD, MATH1, VSEQINSZ, 4, 0);
1362 if (dir == OP_TYPE_ENCAP_PROTOCOL)
1363 SEQFIFOSTORE(p, MSG, 0, 0, VLF);
1365 SEQFIFOSTORE(p, MSG, 0, 0, VLF | CONT);
1367 ALG_OPERATION(p, OP_ALG_ALGSEL_SNOW_F9,
1369 OP_ALG_AS_INITFINAL,
1370 dir == OP_TYPE_ENCAP_PROTOCOL ?
1371 ICV_CHECK_DISABLE : ICV_CHECK_ENABLE,
1373 ALG_OPERATION(p, OP_ALG_ALGSEL_AES,
1375 OP_ALG_AS_INITFINAL,
1377 dir == OP_TYPE_ENCAP_PROTOCOL ? DIR_ENC : DIR_DEC);
1379 if (dir == OP_TYPE_ENCAP_PROTOCOL) {
1380 SEQFIFOLOAD(p, MSGINSNOOP, 0, VLF | LAST2);
1381 MOVE(p, CONTEXT2, 0, IFIFOAB1, 0, 4, LAST1 | FLUSH1 | IMMED);
1383 SEQFIFOLOAD(p, MSGOUTSNOOP, 0, VLF | LAST2);
1384 SEQFIFOLOAD(p, MSG1, 4, LAST1 | FLUSH1);
1385 JUMP(p, 1, LOCAL_JUMP, ALL_TRUE, CLASS1 | NOP | NIFP);
1387 if (rta_sec_era >= RTA_SEC_ERA_6)
1388 LOAD(p, 0, DCTRL, 0, LDLEN_RST_CHA_OFIFO_PTR, IMMED);
1390 MOVE(p, OFIFO, 0, MATH0, 0, 4, WAITCOMP | IMMED);
1392 NFIFOADD(p, IFIFO, ICV2, 4, LAST2);
1394 if (rta_sec_era <= RTA_SEC_ERA_2) {
1395 /* Shut off automatic Info FIFO entries */
1396 LOAD(p, 0, DCTRL, LDOFF_DISABLE_AUTO_NFIFO, 0, IMMED);
1397 MOVE(p, MATH0, 0, IFIFOAB2, 0, 4, WAITCOMP | IMMED);
1399 MOVE(p, MATH0, 0, IFIFO, 0, 4, WAITCOMP | IMMED);
1407 pdcp_insert_cplane_snow_zuc_op(struct program *p,
1408 bool swap __maybe_unused,
1409 struct alginfo *cipherdata,
1410 struct alginfo *authdata,
1412 enum pdcp_sn_size sn_size,
1413 unsigned char era_2_sw_hfn_ovrd __maybe_unused)
1415 uint32_t offset = 0, length = 0, sn_mask = 0;
1418 REFERENCE(pkeyjump);
1420 if (rta_sec_era < RTA_SEC_ERA_5) {
1421 pr_err("Invalid era for selected algorithm\n");
1425 pkeyjump = JUMP(p, keyjump, LOCAL_JUMP, ALL_TRUE, SHRD | SELF | BOTH);
1426 KEY(p, KEY1, cipherdata->key_enc_flags, cipherdata->key,
1427 cipherdata->keylen, INLINE_KEY(cipherdata));
1428 KEY(p, KEY2, authdata->key_enc_flags, authdata->key, authdata->keylen,
1429 INLINE_KEY(authdata));
1431 SET_LABEL(p, keyjump);
1433 if (rta_sec_era >= RTA_SEC_ERA_8 && sn_size != PDCP_SN_SIZE_18) {
1436 if (sn_size == PDCP_SN_SIZE_5)
1437 pclid = OP_PCLID_LTE_PDCP_CTRL_MIXED;
1439 pclid = OP_PCLID_LTE_PDCP_USER_RN;
1441 PROTOCOL(p, dir, pclid,
1442 ((uint16_t)cipherdata->algtype << 8) |
1443 (uint16_t)authdata->algtype);
1446 /* Non-proto is supported only for 5bit cplane and 18bit uplane */
1448 case PDCP_SN_SIZE_5:
1451 sn_mask = (swap == false) ? PDCP_C_PLANE_SN_MASK :
1452 PDCP_C_PLANE_SN_MASK_BE;
1454 case PDCP_SN_SIZE_18:
1457 sn_mask = (swap == false) ? PDCP_U_PLANE_18BIT_SN_MASK :
1458 PDCP_U_PLANE_18BIT_SN_MASK_BE;
1460 case PDCP_SN_SIZE_7:
1461 case PDCP_SN_SIZE_12:
1462 case PDCP_SN_SIZE_15:
1463 pr_err("Invalid sn_size for %s\n", __func__);
1468 SEQLOAD(p, MATH0, offset, length, 0);
1469 JUMP(p, 1, LOCAL_JUMP, ALL_TRUE, CALM);
1470 MOVE(p, MATH0, 7, IFIFOAB2, 0, 1, IMMED);
1471 MATHB(p, MATH0, AND, sn_mask, MATH1, 8, IFB | IMMED2);
1473 MATHB(p, MATH1, SHLD, MATH1, MATH1, 8, 0);
1474 MOVE(p, DESCBUF, 4, MATH2, 0, 8, WAITCOMP | IMMED);
1475 MATHB(p, MATH1, OR, MATH2, MATH2, 8, 0);
1476 MOVE(p, MATH2, 0, CONTEXT1, 0, 8, IMMED);
1477 MOVE(p, MATH2, 0, CONTEXT2, 0, 8, WAITCOMP | IMMED);
1479 if (dir == OP_TYPE_ENCAP_PROTOCOL)
1480 MATHB(p, SEQINSZ, ADD, PDCP_MAC_I_LEN, VSEQOUTSZ, 4, IMMED2);
1482 MATHB(p, SEQINSZ, SUB, PDCP_MAC_I_LEN, VSEQOUTSZ, 4, IMMED2);
1484 MATHB(p, SEQINSZ, SUB, ZERO, VSEQINSZ, 4, 0);
1485 SEQSTORE(p, MATH0, offset, length, 0);
1487 if (dir == OP_TYPE_ENCAP_PROTOCOL) {
1488 SEQFIFOSTORE(p, MSG, 0, 0, VLF);
1489 SEQFIFOLOAD(p, MSGINSNOOP, 0, VLF | LAST2);
1491 SEQFIFOSTORE(p, MSG, 0, 0, VLF | CONT);
1492 SEQFIFOLOAD(p, MSGOUTSNOOP, 0, VLF | LAST1 | FLUSH1);
1495 ALG_OPERATION(p, OP_ALG_ALGSEL_ZUCA,
1497 OP_ALG_AS_INITFINAL,
1498 dir == OP_TYPE_ENCAP_PROTOCOL ?
1499 ICV_CHECK_DISABLE : ICV_CHECK_ENABLE,
1502 ALG_OPERATION(p, OP_ALG_ALGSEL_SNOW_F8,
1504 OP_ALG_AS_INITFINAL,
1506 dir == OP_TYPE_ENCAP_PROTOCOL ? DIR_ENC : DIR_DEC);
1507 if (dir == OP_TYPE_ENCAP_PROTOCOL) {
1508 MOVE(p, CONTEXT2, 0, IFIFOAB1, 0, 4, LAST1 | FLUSH1 | IMMED);
1511 MOVE(p, OFIFO, 0, MATH0, 0, 4, IMMED);
1512 LOAD(p, NFIFOENTRY_STYPE_ALTSOURCE |
1513 NFIFOENTRY_DEST_CLASS2 |
1514 NFIFOENTRY_DTYPE_ICV |
1515 NFIFOENTRY_LC2 | 4, NFIFO_SZL, 0, 4, IMMED);
1516 MOVE(p, MATH0, 0, ALTSOURCE, 0, 4, WAITCOMP | IMMED);
1519 /* Reset ZUCA mode and done interrupt */
1520 LOAD(p, CLRW_CLR_C2MODE, CLRW, 0, 4, IMMED);
1521 LOAD(p, CIRQ_ZADI, ICTRL, 0, 4, IMMED);
1523 PATCH_JUMP(p, pkeyjump, keyjump);
1528 pdcp_insert_cplane_aes_zuc_op(struct program *p,
1529 bool swap __maybe_unused,
1530 struct alginfo *cipherdata,
1531 struct alginfo *authdata,
1533 enum pdcp_sn_size sn_size,
1534 unsigned char era_2_sw_hfn_ovrd __maybe_unused)
1536 uint32_t offset = 0, length = 0, sn_mask = 0;
1538 REFERENCE(pkeyjump);
1540 if (rta_sec_era < RTA_SEC_ERA_5) {
1541 pr_err("Invalid era for selected algorithm\n");
1545 pkeyjump = JUMP(p, keyjump, LOCAL_JUMP, ALL_TRUE, SHRD | SELF | BOTH);
1546 KEY(p, KEY1, cipherdata->key_enc_flags, cipherdata->key,
1547 cipherdata->keylen, INLINE_KEY(cipherdata));
1548 KEY(p, KEY2, authdata->key_enc_flags, authdata->key, authdata->keylen,
1549 INLINE_KEY(authdata));
1551 if (rta_sec_era >= RTA_SEC_ERA_8 && sn_size != PDCP_SN_SIZE_18) {
1554 if (sn_size == PDCP_SN_SIZE_5)
1555 pclid = OP_PCLID_LTE_PDCP_CTRL_MIXED;
1557 pclid = OP_PCLID_LTE_PDCP_USER_RN;
1559 PROTOCOL(p, dir, pclid,
1560 ((uint16_t)cipherdata->algtype << 8) |
1561 (uint16_t)authdata->algtype);
1565 /* Non-proto is supported only for 5bit cplane and 18bit uplane */
1567 case PDCP_SN_SIZE_5:
1570 sn_mask = (swap == false) ? PDCP_C_PLANE_SN_MASK :
1571 PDCP_C_PLANE_SN_MASK_BE;
1573 case PDCP_SN_SIZE_18:
1576 sn_mask = (swap == false) ? PDCP_U_PLANE_18BIT_SN_MASK :
1577 PDCP_U_PLANE_18BIT_SN_MASK_BE;
1579 case PDCP_SN_SIZE_7:
1580 case PDCP_SN_SIZE_12:
1581 case PDCP_SN_SIZE_15:
1582 pr_err("Invalid sn_size for %s\n", __func__);
1587 SET_LABEL(p, keyjump);
1588 SEQLOAD(p, MATH0, offset, length, 0);
1589 JUMP(p, 1, LOCAL_JUMP, ALL_TRUE, CALM);
1590 MOVE(p, MATH0, 7, IFIFOAB2, 0, 1, IMMED);
1591 MATHB(p, MATH0, AND, sn_mask, MATH1, 8, IFB | IMMED2);
1593 MATHB(p, MATH1, SHLD, MATH1, MATH1, 8, 0);
1594 MOVE(p, DESCBUF, 4, MATH2, 0, 8, WAITCOMP | IMMED);
1595 MATHB(p, MATH1, OR, MATH2, MATH2, 8, 0);
1596 MOVE(p, MATH2, 0, CONTEXT1, 16, 8, IMMED);
1597 MOVE(p, MATH2, 0, CONTEXT2, 0, 8, WAITCOMP | IMMED);
1599 if (dir == OP_TYPE_ENCAP_PROTOCOL)
1600 MATHB(p, SEQINSZ, ADD, PDCP_MAC_I_LEN, VSEQOUTSZ, 4, IMMED2);
1602 MATHB(p, SEQINSZ, SUB, PDCP_MAC_I_LEN, VSEQOUTSZ, 4, IMMED2);
1604 MATHB(p, SEQINSZ, SUB, ZERO, VSEQINSZ, 4, 0);
1605 SEQSTORE(p, MATH0, offset, length, 0);
1607 if (dir == OP_TYPE_ENCAP_PROTOCOL) {
1608 SEQFIFOSTORE(p, MSG, 0, 0, VLF);
1609 SEQFIFOLOAD(p, MSGINSNOOP, 0, VLF | LAST2);
1611 SEQFIFOSTORE(p, MSG, 0, 0, VLF | CONT);
1612 SEQFIFOLOAD(p, MSGOUTSNOOP, 0, VLF | LAST1 | FLUSH1);
1615 ALG_OPERATION(p, OP_ALG_ALGSEL_ZUCA,
1617 OP_ALG_AS_INITFINAL,
1618 dir == OP_TYPE_ENCAP_PROTOCOL ?
1619 ICV_CHECK_DISABLE : ICV_CHECK_ENABLE,
1622 ALG_OPERATION(p, OP_ALG_ALGSEL_AES,
1624 OP_ALG_AS_INITFINAL,
1626 dir == OP_TYPE_ENCAP_PROTOCOL ? DIR_ENC : DIR_DEC);
1628 if (dir == OP_TYPE_ENCAP_PROTOCOL) {
1629 MOVE(p, CONTEXT2, 0, IFIFOAB1, 0, 4, LAST1 | FLUSH1 | IMMED);
1632 MOVE(p, OFIFO, 0, MATH0, 0, 4, IMMED);
1634 LOAD(p, NFIFOENTRY_STYPE_ALTSOURCE |
1635 NFIFOENTRY_DEST_CLASS2 |
1636 NFIFOENTRY_DTYPE_ICV |
1637 NFIFOENTRY_LC2 | 4, NFIFO_SZL, 0, 4, IMMED);
1638 MOVE(p, MATH0, 0, ALTSOURCE, 0, 4, WAITCOMP | IMMED);
1641 /* Reset ZUCA mode and done interrupt */
1642 LOAD(p, CLRW_CLR_C2MODE, CLRW, 0, 4, IMMED);
1643 LOAD(p, CIRQ_ZADI, ICTRL, 0, 4, IMMED);
1645 PATCH_JUMP(p, pkeyjump, keyjump);
1651 pdcp_insert_cplane_zuc_snow_op(struct program *p,
1652 bool swap __maybe_unused,
1653 struct alginfo *cipherdata,
1654 struct alginfo *authdata,
1656 enum pdcp_sn_size sn_size,
1657 unsigned char era_2_sw_hfn_ovrd __maybe_unused)
1659 uint32_t offset = 0, length = 0, sn_mask = 0;
1661 REFERENCE(pkeyjump);
1663 if (rta_sec_era < RTA_SEC_ERA_5) {
1664 pr_err("Invalid era for selected algorithm\n");
1668 pkeyjump = JUMP(p, keyjump, LOCAL_JUMP, ALL_TRUE, SHRD | SELF | BOTH);
1669 KEY(p, KEY1, cipherdata->key_enc_flags, cipherdata->key,
1670 cipherdata->keylen, INLINE_KEY(cipherdata));
1671 KEY(p, KEY2, authdata->key_enc_flags, authdata->key, authdata->keylen,
1672 INLINE_KEY(authdata));
1674 if (rta_sec_era >= RTA_SEC_ERA_8 && sn_size != PDCP_SN_SIZE_18) {
1677 if (sn_size == PDCP_SN_SIZE_5)
1678 pclid = OP_PCLID_LTE_PDCP_CTRL_MIXED;
1680 pclid = OP_PCLID_LTE_PDCP_USER_RN;
1682 PROTOCOL(p, dir, pclid,
1683 ((uint16_t)cipherdata->algtype << 8) |
1684 (uint16_t)authdata->algtype);
1688 /* Non-proto is supported only for 5bit cplane and 18bit uplane */
1690 case PDCP_SN_SIZE_5:
1693 sn_mask = (swap == false) ? PDCP_C_PLANE_SN_MASK :
1694 PDCP_C_PLANE_SN_MASK_BE;
1696 case PDCP_SN_SIZE_18:
1699 sn_mask = (swap == false) ? PDCP_U_PLANE_18BIT_SN_MASK :
1700 PDCP_U_PLANE_18BIT_SN_MASK_BE;
1702 case PDCP_SN_SIZE_7:
1703 case PDCP_SN_SIZE_12:
1704 case PDCP_SN_SIZE_15:
1705 pr_err("Invalid sn_size for %s\n", __func__);
1709 SET_LABEL(p, keyjump);
1710 SEQLOAD(p, MATH0, offset, length, 0);
1711 JUMP(p, 1, LOCAL_JUMP, ALL_TRUE, CALM);
1712 MOVE(p, MATH0, 7, IFIFOAB2, 0, 1, IMMED);
1713 MATHB(p, MATH0, AND, sn_mask, MATH1, 8, IFB | IMMED2);
1715 MATHB(p, MATH1, SHLD, MATH1, MATH1, 8, 0);
1716 MOVE(p, DESCBUF, 4, MATH2, 0, 8, WAITCOMP | IMMED);
1717 MATHB(p, MATH1, OR, MATH2, MATH1, 8, 0);
1718 MOVE(p, MATH1, 0, CONTEXT1, 0, 8, IMMED);
1719 MOVE(p, MATH1, 0, CONTEXT2, 0, 4, IMMED);
1720 if (swap == false) {
1721 MATHB(p, MATH1, AND, lower_32_bits(PDCP_BEARER_MASK), MATH2,
1723 MATHB(p, MATH1, AND, upper_32_bits(PDCP_DIR_MASK), MATH3,
1726 MATHB(p, MATH1, AND, lower_32_bits(PDCP_BEARER_MASK_BE), MATH2,
1728 MATHB(p, MATH1, AND, upper_32_bits(PDCP_DIR_MASK_BE), MATH3,
1731 MATHB(p, MATH3, SHLD, MATH3, MATH3, 8, 0);
1732 MOVE(p, MATH2, 4, OFIFO, 0, 12, IMMED);
1733 MOVE(p, OFIFO, 0, CONTEXT2, 4, 12, IMMED);
1735 if (dir == OP_TYPE_ENCAP_PROTOCOL) {
1736 MATHB(p, SEQINSZ, ADD, PDCP_MAC_I_LEN, VSEQOUTSZ, 4, IMMED2);
1737 MATHB(p, SEQINSZ, SUB, ZERO, VSEQINSZ, 4, 0);
1739 MATHB(p, SEQINSZ, SUB, PDCP_MAC_I_LEN, VSEQOUTSZ, 4, IMMED2);
1740 MATHB(p, VSEQOUTSZ, SUB, ZERO, VSEQINSZ, 4, 0);
1743 SEQSTORE(p, MATH0, offset, length, 0);
1745 if (dir == OP_TYPE_ENCAP_PROTOCOL) {
1746 SEQFIFOSTORE(p, MSG, 0, 0, VLF);
1747 SEQFIFOLOAD(p, MSGINSNOOP, 0, VLF | LAST2);
1749 SEQFIFOSTORE(p, MSG, 0, 0, VLF | CONT);
1750 SEQFIFOLOAD(p, MSGOUTSNOOP, 0, VLF | LAST2);
1753 ALG_OPERATION(p, OP_ALG_ALGSEL_SNOW_F9,
1755 OP_ALG_AS_INITFINAL,
1756 dir == OP_TYPE_ENCAP_PROTOCOL ?
1757 ICV_CHECK_DISABLE : ICV_CHECK_ENABLE,
1760 ALG_OPERATION(p, OP_ALG_ALGSEL_ZUCE,
1762 OP_ALG_AS_INITFINAL,
1764 dir == OP_TYPE_ENCAP_PROTOCOL ? DIR_ENC : DIR_DEC);
1766 if (dir == OP_TYPE_ENCAP_PROTOCOL) {
1767 MOVE(p, CONTEXT2, 0, IFIFOAB1, 0, 4, LAST1 | FLUSH1 | IMMED);
1769 SEQFIFOLOAD(p, MSG1, 4, LAST1 | FLUSH1);
1770 JUMP(p, 1, LOCAL_JUMP, ALL_TRUE, CLASS1 | NOP | NIFP);
1772 if (rta_sec_era >= RTA_SEC_ERA_6)
1774 * For SEC ERA 6, there's a problem with the OFIFO
1775 * pointer, and thus it needs to be reset here before
1778 LOAD(p, 0, DCTRL, 0, LDLEN_RST_CHA_OFIFO_PTR, IMMED);
1780 /* Put ICV to M0 before sending it to C2 for comparison. */
1781 MOVE(p, OFIFO, 0, MATH0, 0, 4, WAITCOMP | IMMED);
1783 LOAD(p, NFIFOENTRY_STYPE_ALTSOURCE |
1784 NFIFOENTRY_DEST_CLASS2 |
1785 NFIFOENTRY_DTYPE_ICV |
1786 NFIFOENTRY_LC2 | 4, NFIFO_SZL, 0, 4, IMMED);
1787 MOVE(p, MATH0, 0, ALTSOURCE, 0, 4, IMMED);
1790 PATCH_JUMP(p, pkeyjump, keyjump);
1795 pdcp_insert_cplane_zuc_aes_op(struct program *p,
1796 bool swap __maybe_unused,
1797 struct alginfo *cipherdata,
1798 struct alginfo *authdata,
1800 enum pdcp_sn_size sn_size,
1801 unsigned char era_2_sw_hfn_ovrd __maybe_unused)
1803 uint32_t offset = 0, length = 0, sn_mask = 0;
1804 if (rta_sec_era < RTA_SEC_ERA_5) {
1805 pr_err("Invalid era for selected algorithm\n");
1809 if (rta_sec_era >= RTA_SEC_ERA_8 && sn_size != PDCP_SN_SIZE_18) {
1812 KEY(p, KEY1, cipherdata->key_enc_flags, cipherdata->key,
1813 cipherdata->keylen, INLINE_KEY(cipherdata));
1814 KEY(p, KEY2, authdata->key_enc_flags, authdata->key,
1815 authdata->keylen, INLINE_KEY(authdata));
1817 if (sn_size == PDCP_SN_SIZE_5)
1818 pclid = OP_PCLID_LTE_PDCP_CTRL_MIXED;
1820 pclid = OP_PCLID_LTE_PDCP_USER_RN;
1822 PROTOCOL(p, dir, pclid,
1823 ((uint16_t)cipherdata->algtype << 8) |
1824 (uint16_t)authdata->algtype);
1827 /* Non-proto is supported only for 5bit cplane and 18bit uplane */
1829 case PDCP_SN_SIZE_5:
1832 sn_mask = (swap == false) ? PDCP_C_PLANE_SN_MASK :
1833 PDCP_C_PLANE_SN_MASK_BE;
1835 case PDCP_SN_SIZE_18:
1838 sn_mask = (swap == false) ? PDCP_U_PLANE_18BIT_SN_MASK :
1839 PDCP_U_PLANE_18BIT_SN_MASK_BE;
1841 case PDCP_SN_SIZE_7:
1842 case PDCP_SN_SIZE_12:
1843 case PDCP_SN_SIZE_15:
1844 pr_err("Invalid sn_size for %s\n", __func__);
1848 SEQLOAD(p, MATH0, offset, length, 0);
1849 JUMP(p, 1, LOCAL_JUMP, ALL_TRUE, CALM);
1850 MATHB(p, MATH0, AND, sn_mask, MATH1, 8, IFB | IMMED2);
1852 MATHB(p, MATH1, SHLD, MATH1, MATH1, 8, 0);
1853 MOVE(p, DESCBUF, 4, MATH2, 0, 0x08, WAITCOMP | IMMED);
1854 MATHB(p, MATH1, OR, MATH2, MATH2, 8, 0);
1855 SEQSTORE(p, MATH0, offset, length, 0);
1856 if (dir == OP_TYPE_ENCAP_PROTOCOL) {
1857 KEY(p, KEY1, authdata->key_enc_flags, authdata->key,
1858 authdata->keylen, INLINE_KEY(authdata));
1859 MOVE(p, MATH2, 0, IFIFOAB1, 0, 0x08, IMMED);
1860 MOVE(p, MATH0, 7, IFIFOAB1, 0, 1, IMMED);
1862 MATHB(p, SEQINSZ, SUB, ZERO, VSEQINSZ, 4, 0);
1863 MATHB(p, VSEQINSZ, ADD, PDCP_MAC_I_LEN, VSEQOUTSZ, 4, IMMED2);
1865 ALG_OPERATION(p, OP_ALG_ALGSEL_AES,
1867 OP_ALG_AS_INITFINAL,
1870 SEQFIFOLOAD(p, MSG1, 0, VLF | LAST1 | FLUSH1);
1871 MOVE(p, CONTEXT1, 0, MATH3, 0, 4, WAITCOMP | IMMED);
1872 LOAD(p, CLRW_RESET_CLS1_CHA |
1880 KEY(p, KEY1, cipherdata->key_enc_flags, cipherdata->key,
1881 cipherdata->keylen, INLINE_KEY(cipherdata));
1883 MOVE(p, MATH2, 0, CONTEXT1, 0, 8, IMMED);
1884 SEQINPTR(p, 0, PDCP_NULL_MAX_FRAME_LEN, RTO);
1886 ALG_OPERATION(p, OP_ALG_ALGSEL_ZUCE,
1888 OP_ALG_AS_INITFINAL,
1891 SEQFIFOSTORE(p, MSG, 0, 0, VLF);
1893 SEQFIFOLOAD(p, SKIP, 1, 0);
1895 SEQFIFOLOAD(p, MSG1, 0, VLF);
1896 MOVE(p, MATH3, 0, IFIFOAB1, 0, 4, LAST1 | FLUSH1 | IMMED);
1898 MOVE(p, MATH2, 0, CONTEXT1, 0, 8, IMMED);
1900 MOVE(p, CONTEXT1, 0, CONTEXT2, 0, 8, IMMED);
1902 MATHB(p, SEQINSZ, SUB, ZERO, VSEQINSZ, 4, 0);
1904 MATHB(p, SEQINSZ, SUB, PDCP_MAC_I_LEN, VSEQOUTSZ, 4, IMMED2);
1906 KEY(p, KEY1, cipherdata->key_enc_flags, cipherdata->key,
1907 cipherdata->keylen, INLINE_KEY(cipherdata));
1909 MOVE(p, CONTEXT1, 0, CONTEXT2, 0, 8, IMMED);
1911 ALG_OPERATION(p, OP_ALG_ALGSEL_ZUCE,
1913 OP_ALG_AS_INITFINAL,
1916 SEQFIFOSTORE(p, MSG, 0, 0, VLF | CONT);
1917 SEQFIFOLOAD(p, MSG1, 0, VLF | LAST1 | FLUSH1);
1919 MOVE(p, OFIFO, 0, MATH3, 0, 4, IMMED);
1921 LOAD(p, CLRW_RESET_CLS1_CHA |
1929 KEY(p, KEY1, authdata->key_enc_flags, authdata->key,
1930 authdata->keylen, INLINE_KEY(authdata));
1932 SEQINPTR(p, 0, 0, SOP);
1934 ALG_OPERATION(p, OP_ALG_ALGSEL_AES,
1936 OP_ALG_AS_INITFINAL,
1940 MATHB(p, SEQINSZ, SUB, ZERO, VSEQINSZ, 4, 0);
1942 MOVE(p, CONTEXT2, 0, IFIFOAB1, 0, 8, IMMED);
1944 SEQFIFOLOAD(p, MSG1, 0, VLF | LAST1 | FLUSH1);
1946 LOAD(p, NFIFOENTRY_STYPE_ALTSOURCE |
1947 NFIFOENTRY_DEST_CLASS1 |
1948 NFIFOENTRY_DTYPE_ICV |
1950 NFIFOENTRY_FC1 | 4, NFIFO_SZL, 0, 4, IMMED);
1951 MOVE(p, MATH3, 0, ALTSOURCE, 0, 4, IMMED);
1958 pdcp_insert_uplane_no_int_op(struct program *p,
1959 bool swap __maybe_unused,
1960 struct alginfo *cipherdata,
1962 enum pdcp_sn_size sn_size)
1967 /* Insert Cipher Key */
1968 KEY(p, KEY1, cipherdata->key_enc_flags, cipherdata->key,
1969 cipherdata->keylen, INLINE_KEY(cipherdata));
1971 if ((rta_sec_era >= RTA_SEC_ERA_8 && sn_size == PDCP_SN_SIZE_15) ||
1972 (rta_sec_era >= RTA_SEC_ERA_10)) {
1973 PROTOCOL(p, dir, OP_PCLID_LTE_PDCP_USER,
1974 (uint16_t)cipherdata->algtype);
1978 if (sn_size == PDCP_SN_SIZE_15) {
1979 SEQLOAD(p, MATH0, 6, 2, 0);
1980 sn_mask = (swap == false) ? PDCP_U_PLANE_15BIT_SN_MASK :
1981 PDCP_U_PLANE_15BIT_SN_MASK_BE;
1982 } else { /* SN Size == PDCP_SN_SIZE_18 */
1983 SEQLOAD(p, MATH0, 5, 3, 0);
1984 sn_mask = (swap == false) ? PDCP_U_PLANE_18BIT_SN_MASK :
1985 PDCP_U_PLANE_18BIT_SN_MASK_BE;
1987 JUMP(p, 1, LOCAL_JUMP, ALL_TRUE, CALM);
1988 MATHB(p, MATH0, AND, sn_mask, MATH1, 8, IFB | IMMED2);
1990 if (sn_size == PDCP_SN_SIZE_15)
1991 SEQSTORE(p, MATH0, 6, 2, 0);
1992 else /* SN Size == PDCP_SN_SIZE_18 */
1993 SEQSTORE(p, MATH0, 5, 3, 0);
1995 MATHB(p, MATH1, SHLD, MATH1, MATH1, 8, 0);
1996 MOVEB(p, DESCBUF, 8, MATH2, 0, 8, WAITCOMP | IMMED);
1997 MATHB(p, MATH1, OR, MATH2, MATH2, 8, 0);
1999 MATHB(p, SEQINSZ, SUB, MATH3, VSEQINSZ, 4, 0);
2000 MATHB(p, SEQINSZ, SUB, MATH3, VSEQOUTSZ, 4, 0);
2002 SEQFIFOSTORE(p, MSG, 0, 0, VLF);
2004 op = dir == OP_TYPE_ENCAP_PROTOCOL ? DIR_ENC : DIR_DEC;
2005 switch (cipherdata->algtype) {
2006 case PDCP_CIPHER_TYPE_SNOW:
2007 MOVEB(p, MATH2, 0, CONTEXT1, 0, 8, WAITCOMP | IMMED);
2008 ALG_OPERATION(p, OP_ALG_ALGSEL_SNOW_F8,
2010 OP_ALG_AS_INITFINAL,
2015 case PDCP_CIPHER_TYPE_AES:
2016 MOVEB(p, MATH2, 0, CONTEXT1, 0x10, 0x10, WAITCOMP | IMMED);
2017 ALG_OPERATION(p, OP_ALG_ALGSEL_AES,
2019 OP_ALG_AS_INITFINAL,
2024 case PDCP_CIPHER_TYPE_ZUC:
2025 if (rta_sec_era < RTA_SEC_ERA_5) {
2026 pr_err("Invalid era for selected algorithm\n");
2029 MOVEB(p, MATH2, 0, CONTEXT1, 0, 0x08, IMMED);
2030 MOVEB(p, MATH2, 0, CONTEXT1, 0x08, 0x08, WAITCOMP | IMMED);
2032 ALG_OPERATION(p, OP_ALG_ALGSEL_ZUCE,
2034 OP_ALG_AS_INITFINAL,
2040 pr_err("%s: Invalid encrypt algorithm selected: %d\n",
2041 "pdcp_insert_uplane_15bit_op", cipherdata->algtype);
2045 SEQFIFOLOAD(p, MSG1, 0, VLF | LAST1 | FLUSH1);
2051 * Function for inserting the snippet of code responsible for creating
2052 * the HFN override code via either DPOVRD or via the input frame.
2055 insert_hfn_ov_op(struct program *p,
2057 enum pdb_type_e pdb_type,
2058 unsigned char era_2_sw_hfn_ovrd)
2060 uint32_t imm = PDCP_DPOVRD_HFN_OV_EN;
2061 uint16_t hfn_pdb_offset;
2063 if (rta_sec_era == RTA_SEC_ERA_2 && !era_2_sw_hfn_ovrd)
2067 case PDCP_PDB_TYPE_NO_PDB:
2069 * If there is no PDB, then HFN override mechanism does not
2070 * make any sense, thus in this case the function will
2071 * return the pointer to the current position in the
2076 case PDCP_PDB_TYPE_REDUCED_PDB:
2080 case PDCP_PDB_TYPE_FULL_PDB:
2088 if (rta_sec_era > RTA_SEC_ERA_2) {
2089 MATHB(p, DPOVRD, AND, imm, NONE, 8, IFB | IMMED2);
2091 SEQLOAD(p, MATH0, 4, 4, 0);
2092 JUMP(p, 1, LOCAL_JUMP, ALL_TRUE, CALM);
2093 MATHB(p, MATH0, AND, imm, NONE, 8, IFB | IMMED2);
2094 SEQSTORE(p, MATH0, 4, 4, 0);
2097 if (rta_sec_era >= RTA_SEC_ERA_8)
2098 JUMP(p, 6, LOCAL_JUMP, ALL_TRUE, MATH_Z);
2100 JUMP(p, 5, LOCAL_JUMP, ALL_TRUE, MATH_Z);
2102 if (rta_sec_era > RTA_SEC_ERA_2)
2103 MATHB(p, DPOVRD, LSHIFT, shift, MATH0, 4, IMMED2);
2105 MATHB(p, MATH0, LSHIFT, shift, MATH0, 4, IMMED2);
2107 MATHB(p, MATH0, SHLD, MATH0, MATH0, 8, 0);
2108 MOVE(p, MATH0, 0, DESCBUF, hfn_pdb_offset, 4, IMMED);
2110 if (rta_sec_era >= RTA_SEC_ERA_8)
2112 * For ERA8, DPOVRD could be handled by the PROTOCOL command
2113 * itself. For now, this is not done. Thus, clear DPOVRD here
2114 * to alleviate any side-effects.
2116 MATHB(p, DPOVRD, AND, ZERO, DPOVRD, 4, STL);
2122 * PDCP Control PDB creation function
2124 static inline enum pdb_type_e
2125 cnstr_pdcp_c_plane_pdb(struct program *p,
2127 enum pdcp_sn_size sn_size,
2128 unsigned char bearer,
2129 unsigned char direction,
2130 uint32_t hfn_threshold,
2131 struct alginfo *cipherdata,
2132 struct alginfo *authdata)
2134 struct pdcp_pdb pdb;
2136 pdb_mask[PDCP_CIPHER_TYPE_INVALID][PDCP_AUTH_TYPE_INVALID] = {
2138 PDCP_PDB_TYPE_NO_PDB, /* NULL */
2139 PDCP_PDB_TYPE_FULL_PDB, /* SNOW f9 */
2140 PDCP_PDB_TYPE_FULL_PDB, /* AES CMAC */
2141 PDCP_PDB_TYPE_FULL_PDB /* ZUC-I */
2144 PDCP_PDB_TYPE_FULL_PDB, /* NULL */
2145 PDCP_PDB_TYPE_FULL_PDB, /* SNOW f9 */
2146 PDCP_PDB_TYPE_REDUCED_PDB, /* AES CMAC */
2147 PDCP_PDB_TYPE_REDUCED_PDB /* ZUC-I */
2150 PDCP_PDB_TYPE_FULL_PDB, /* NULL */
2151 PDCP_PDB_TYPE_REDUCED_PDB, /* SNOW f9 */
2152 PDCP_PDB_TYPE_FULL_PDB, /* AES CMAC */
2153 PDCP_PDB_TYPE_REDUCED_PDB /* ZUC-I */
2156 PDCP_PDB_TYPE_FULL_PDB, /* NULL */
2157 PDCP_PDB_TYPE_REDUCED_PDB, /* SNOW f9 */
2158 PDCP_PDB_TYPE_REDUCED_PDB, /* AES CMAC */
2159 PDCP_PDB_TYPE_FULL_PDB /* ZUC-I */
2163 if (rta_sec_era >= RTA_SEC_ERA_8) {
2164 memset(&pdb, 0x00, sizeof(struct pdcp_pdb));
2166 /* To support 12-bit seq numbers, we use u-plane opt in pdb.
2167 * SEC supports 5-bit only with c-plane opt in pdb.
2169 if (sn_size == PDCP_SN_SIZE_12) {
2170 pdb.hfn_res = hfn << PDCP_U_PLANE_PDB_LONG_SN_HFN_SHIFT;
2171 pdb.bearer_dir_res = (uint32_t)
2172 ((bearer << PDCP_U_PLANE_PDB_BEARER_SHIFT) |
2173 (direction << PDCP_U_PLANE_PDB_DIR_SHIFT));
2176 hfn_threshold << PDCP_U_PLANE_PDB_LONG_SN_HFN_THR_SHIFT;
2179 /* This means 5-bit c-plane.
2180 * Here we use c-plane opt in pdb
2183 /* This is a HW issue. Bit 2 should be set to zero,
2184 * but it does not work this way. Override here.
2186 pdb.opt_res.rsvd = 0x00000002;
2188 /* Copy relevant information from user to PDB */
2189 pdb.hfn_res = hfn << PDCP_C_PLANE_PDB_HFN_SHIFT;
2190 pdb.bearer_dir_res = (uint32_t)
2191 ((bearer << PDCP_C_PLANE_PDB_BEARER_SHIFT) |
2192 (direction << PDCP_C_PLANE_PDB_DIR_SHIFT));
2194 hfn_threshold << PDCP_C_PLANE_PDB_HFN_THR_SHIFT;
2197 /* copy PDB in descriptor*/
2198 __rta_out32(p, pdb.opt_res.opt);
2199 __rta_out32(p, pdb.hfn_res);
2200 __rta_out32(p, pdb.bearer_dir_res);
2201 __rta_out32(p, pdb.hfn_thr_res);
2203 return PDCP_PDB_TYPE_FULL_PDB;
2206 switch (pdb_mask[cipherdata->algtype][authdata->algtype]) {
2207 case PDCP_PDB_TYPE_NO_PDB:
2210 case PDCP_PDB_TYPE_REDUCED_PDB:
2211 __rta_out32(p, (hfn << PDCP_C_PLANE_PDB_HFN_SHIFT));
2213 (uint32_t)((bearer <<
2214 PDCP_C_PLANE_PDB_BEARER_SHIFT) |
2216 PDCP_C_PLANE_PDB_DIR_SHIFT)));
2219 case PDCP_PDB_TYPE_FULL_PDB:
2220 memset(&pdb, 0x00, sizeof(struct pdcp_pdb));
2222 /* This is a HW issue. Bit 2 should be set to zero,
2223 * but it does not work this way. Override here.
2225 pdb.opt_res.rsvd = 0x00000002;
2227 /* Copy relevant information from user to PDB */
2228 pdb.hfn_res = hfn << PDCP_C_PLANE_PDB_HFN_SHIFT;
2229 pdb.bearer_dir_res = (uint32_t)
2230 ((bearer << PDCP_C_PLANE_PDB_BEARER_SHIFT) |
2231 (direction << PDCP_C_PLANE_PDB_DIR_SHIFT));
2233 hfn_threshold << PDCP_C_PLANE_PDB_HFN_THR_SHIFT;
2235 /* copy PDB in descriptor*/
2236 __rta_out32(p, pdb.opt_res.opt);
2237 __rta_out32(p, pdb.hfn_res);
2238 __rta_out32(p, pdb.bearer_dir_res);
2239 __rta_out32(p, pdb.hfn_thr_res);
2244 return PDCP_PDB_TYPE_INVALID;
2247 return pdb_mask[cipherdata->algtype][authdata->algtype];
2251 * PDCP UPlane PDB creation function
2254 cnstr_pdcp_u_plane_pdb(struct program *p,
2255 enum pdcp_sn_size sn_size,
2256 uint32_t hfn, unsigned short bearer,
2257 unsigned short direction,
2258 uint32_t hfn_threshold)
2260 struct pdcp_pdb pdb;
2261 /* Read options from user */
2262 /* Depending on sequence number length, the HFN and HFN threshold
2263 * have different lengths.
2265 memset(&pdb, 0x00, sizeof(struct pdcp_pdb));
2268 case PDCP_SN_SIZE_7:
2269 pdb.opt_res.opt |= PDCP_U_PLANE_PDB_OPT_SHORT_SN;
2270 pdb.hfn_res = hfn << PDCP_U_PLANE_PDB_SHORT_SN_HFN_SHIFT;
2272 hfn_threshold<<PDCP_U_PLANE_PDB_SHORT_SN_HFN_THR_SHIFT;
2275 case PDCP_SN_SIZE_12:
2276 pdb.opt_res.opt &= (uint32_t)(~PDCP_U_PLANE_PDB_OPT_SHORT_SN);
2277 pdb.hfn_res = hfn << PDCP_U_PLANE_PDB_LONG_SN_HFN_SHIFT;
2279 hfn_threshold<<PDCP_U_PLANE_PDB_LONG_SN_HFN_THR_SHIFT;
2282 case PDCP_SN_SIZE_15:
2283 pdb.opt_res.opt = (uint32_t)(PDCP_U_PLANE_PDB_OPT_15B_SN);
2284 pdb.hfn_res = hfn << PDCP_U_PLANE_PDB_15BIT_SN_HFN_SHIFT;
2286 hfn_threshold<<PDCP_U_PLANE_PDB_15BIT_SN_HFN_THR_SHIFT;
2289 case PDCP_SN_SIZE_18:
2290 pdb.opt_res.opt = (uint32_t)(PDCP_U_PLANE_PDB_OPT_18B_SN);
2291 pdb.hfn_res = hfn << PDCP_U_PLANE_PDB_18BIT_SN_HFN_SHIFT;
2293 hfn_threshold<<PDCP_U_PLANE_PDB_18BIT_SN_HFN_THR_SHIFT;
2297 pr_err("Invalid Sequence Number Size setting in PDB\n");
2301 pdb.bearer_dir_res = (uint32_t)
2302 ((bearer << PDCP_U_PLANE_PDB_BEARER_SHIFT) |
2303 (direction << PDCP_U_PLANE_PDB_DIR_SHIFT));
2305 /* copy PDB in descriptor*/
2306 __rta_out32(p, pdb.opt_res.opt);
2307 __rta_out32(p, pdb.hfn_res);
2308 __rta_out32(p, pdb.bearer_dir_res);
2309 __rta_out32(p, pdb.hfn_thr_res);
2314 * cnstr_shdsc_pdcp_c_plane_encap - Function for creating a PDCP Control Plane
2315 * encapsulation descriptor.
2316 * @descbuf: pointer to buffer for descriptor construction
2317 * @ps: if 36/40bit addressing is desired, this parameter must be true
2318 * @swap: must be true when core endianness doesn't match SEC endianness
2319 * @hfn: starting Hyper Frame Number to be used together with the SN from the
2321 * @sn_size: size of sequence numbers, only 5/12 bit sequence numbers are valid
2322 * @bearer: radio bearer ID
2323 * @direction: the direction of the PDCP frame (UL/DL)
2324 * @hfn_threshold: HFN value that once reached triggers a warning from SEC that
2325 * keys should be renegotiated at the earliest convenience.
2326 * @cipherdata: pointer to block cipher transform definitions
2327 * Valid algorithm values are those from cipher_type_pdcp enum.
2328 * @authdata: pointer to authentication transform definitions
2329 * Valid algorithm values are those from auth_type_pdcp enum.
2330 * @era_2_sw_hfn_ovrd: if software HFN override mechanism is desired for
2331 * this descriptor. Note: Can only be used for
2333 * Return: size of descriptor written in words or negative number on error.
2334 * Once the function returns, the value of this parameter can be used
2335 * for reclaiming the space that wasn't used for the descriptor.
2337 * Note: descbuf must be large enough to contain a full 256 byte long
2338 * descriptor; after the function returns, by subtracting the actual number of
2339 * bytes used, the user can reuse the remaining buffer space for other purposes.
2342 cnstr_shdsc_pdcp_c_plane_encap(uint32_t *descbuf,
2346 enum pdcp_sn_size sn_size,
2347 unsigned char bearer,
2348 unsigned char direction,
2349 uint32_t hfn_threshold,
2350 struct alginfo *cipherdata,
2351 struct alginfo *authdata,
2352 unsigned char era_2_sw_hfn_ovrd)
2355 (*pdcp_cp_fp[PDCP_CIPHER_TYPE_INVALID][PDCP_AUTH_TYPE_INVALID])
2356 (struct program*, bool swap, struct alginfo *,
2357 struct alginfo *, unsigned int, enum pdcp_sn_size,
2358 unsigned char __maybe_unused) = {
2360 pdcp_insert_cplane_null_op, /* NULL */
2361 pdcp_insert_cplane_int_only_op, /* SNOW f9 */
2362 pdcp_insert_cplane_int_only_op, /* AES CMAC */
2363 pdcp_insert_cplane_int_only_op /* ZUC-I */
2366 pdcp_insert_cplane_enc_only_op, /* NULL */
2367 pdcp_insert_cplane_acc_op, /* SNOW f9 */
2368 pdcp_insert_cplane_snow_aes_op, /* AES CMAC */
2369 pdcp_insert_cplane_snow_zuc_op /* ZUC-I */
2372 pdcp_insert_cplane_enc_only_op, /* NULL */
2373 pdcp_insert_cplane_aes_snow_op, /* SNOW f9 */
2374 pdcp_insert_cplane_acc_op, /* AES CMAC */
2375 pdcp_insert_cplane_aes_zuc_op /* ZUC-I */
2378 pdcp_insert_cplane_enc_only_op, /* NULL */
2379 pdcp_insert_cplane_zuc_snow_op, /* SNOW f9 */
2380 pdcp_insert_cplane_zuc_aes_op, /* AES CMAC */
2381 pdcp_insert_cplane_acc_op /* ZUC-I */
2384 static enum rta_share_type
2385 desc_share[PDCP_CIPHER_TYPE_INVALID][PDCP_AUTH_TYPE_INVALID] = {
2387 SHR_WAIT, /* NULL */
2388 SHR_ALWAYS, /* SNOW f9 */
2389 SHR_ALWAYS, /* AES CMAC */
2390 SHR_ALWAYS /* ZUC-I */
2393 SHR_ALWAYS, /* NULL */
2394 SHR_ALWAYS, /* SNOW f9 */
2395 SHR_WAIT, /* AES CMAC */
2396 SHR_WAIT /* ZUC-I */
2399 SHR_ALWAYS, /* NULL */
2400 SHR_ALWAYS, /* SNOW f9 */
2401 SHR_ALWAYS, /* AES CMAC */
2402 SHR_WAIT /* ZUC-I */
2405 SHR_ALWAYS, /* NULL */
2406 SHR_WAIT, /* SNOW f9 */
2407 SHR_WAIT, /* AES CMAC */
2408 SHR_ALWAYS /* ZUC-I */
2411 enum pdb_type_e pdb_type;
2413 struct program *p = &prg;
2417 if (rta_sec_era != RTA_SEC_ERA_2 && era_2_sw_hfn_ovrd) {
2418 pr_err("Cannot select SW HFN override for other era than 2");
2422 if (sn_size != PDCP_SN_SIZE_12 && sn_size != PDCP_SN_SIZE_5) {
2423 pr_err("C-plane supports only 5-bit and 12-bit sequence numbers\n");
2427 PROGRAM_CNTXT_INIT(p, descbuf, 0);
2429 PROGRAM_SET_BSWAP(p);
2431 PROGRAM_SET_36BIT_ADDR(p);
2433 SHR_HDR(p, desc_share[cipherdata->algtype][authdata->algtype], 0, 0);
2435 pdb_type = cnstr_pdcp_c_plane_pdb(p,
2444 SET_LABEL(p, pdb_end);
2446 err = insert_hfn_ov_op(p, sn_size, pdb_type,
2451 err = pdcp_cp_fp[cipherdata->algtype][authdata->algtype](p,
2455 OP_TYPE_ENCAP_PROTOCOL,
2461 PATCH_HDR(p, 0, pdb_end);
2463 return PROGRAM_FINALIZE(p);
2467 * cnstr_shdsc_pdcp_c_plane_decap - Function for creating a PDCP Control Plane
2468 * decapsulation descriptor.
2469 * @descbuf: pointer to buffer for descriptor construction
2470 * @ps: if 36/40bit addressing is desired, this parameter must be true
2471 * @swap: must be true when core endianness doesn't match SEC endianness
2472 * @hfn: starting Hyper Frame Number to be used together with the SN from the
2474 * @sn_size: size of sequence numbers, only 5/12 bit sequence numbers are valid
2475 * @bearer: radio bearer ID
2476 * @direction: the direction of the PDCP frame (UL/DL)
2477 * @hfn_threshold: HFN value that once reached triggers a warning from SEC that
2478 * keys should be renegotiated at the earliest convenience.
2479 * @cipherdata: pointer to block cipher transform definitions
2480 * Valid algorithm values are those from cipher_type_pdcp enum.
2481 * @authdata: pointer to authentication transform definitions
2482 * Valid algorithm values are those from auth_type_pdcp enum.
2483 * @era_2_sw_hfn_ovrd: if software HFN override mechanism is desired for
2484 * this descriptor. Note: Can only be used for
2487 * Return: size of descriptor written in words or negative number on error.
2488 * Once the function returns, the value of this parameter can be used
2489 * for reclaiming the space that wasn't used for the descriptor.
2491 * Note: descbuf must be large enough to contain a full 256 byte long
2492 * descriptor; after the function returns, by subtracting the actual number of
2493 * bytes used, the user can reuse the remaining buffer space for other purposes.
2496 cnstr_shdsc_pdcp_c_plane_decap(uint32_t *descbuf,
2500 enum pdcp_sn_size sn_size,
2501 unsigned char bearer,
2502 unsigned char direction,
2503 uint32_t hfn_threshold,
2504 struct alginfo *cipherdata,
2505 struct alginfo *authdata,
2506 unsigned char era_2_sw_hfn_ovrd)
2509 (*pdcp_cp_fp[PDCP_CIPHER_TYPE_INVALID][PDCP_AUTH_TYPE_INVALID])
2510 (struct program*, bool swap, struct alginfo *,
2511 struct alginfo *, unsigned int, enum pdcp_sn_size,
2514 pdcp_insert_cplane_null_op, /* NULL */
2515 pdcp_insert_cplane_int_only_op, /* SNOW f9 */
2516 pdcp_insert_cplane_int_only_op, /* AES CMAC */
2517 pdcp_insert_cplane_int_only_op /* ZUC-I */
2520 pdcp_insert_cplane_enc_only_op, /* NULL */
2521 pdcp_insert_cplane_acc_op, /* SNOW f9 */
2522 pdcp_insert_cplane_snow_aes_op, /* AES CMAC */
2523 pdcp_insert_cplane_snow_zuc_op /* ZUC-I */
2526 pdcp_insert_cplane_enc_only_op, /* NULL */
2527 pdcp_insert_cplane_aes_snow_op, /* SNOW f9 */
2528 pdcp_insert_cplane_acc_op, /* AES CMAC */
2529 pdcp_insert_cplane_aes_zuc_op /* ZUC-I */
2532 pdcp_insert_cplane_enc_only_op, /* NULL */
2533 pdcp_insert_cplane_zuc_snow_op, /* SNOW f9 */
2534 pdcp_insert_cplane_zuc_aes_op, /* AES CMAC */
2535 pdcp_insert_cplane_acc_op /* ZUC-I */
2538 static enum rta_share_type
2539 desc_share[PDCP_CIPHER_TYPE_INVALID][PDCP_AUTH_TYPE_INVALID] = {
2541 SHR_WAIT, /* NULL */
2542 SHR_ALWAYS, /* SNOW f9 */
2543 SHR_ALWAYS, /* AES CMAC */
2544 SHR_ALWAYS /* ZUC-I */
2547 SHR_ALWAYS, /* NULL */
2548 SHR_ALWAYS, /* SNOW f9 */
2549 SHR_WAIT, /* AES CMAC */
2550 SHR_WAIT /* ZUC-I */
2553 SHR_ALWAYS, /* NULL */
2554 SHR_ALWAYS, /* SNOW f9 */
2555 SHR_ALWAYS, /* AES CMAC */
2556 SHR_WAIT /* ZUC-I */
2559 SHR_ALWAYS, /* NULL */
2560 SHR_WAIT, /* SNOW f9 */
2561 SHR_WAIT, /* AES CMAC */
2562 SHR_ALWAYS /* ZUC-I */
2565 enum pdb_type_e pdb_type;
2567 struct program *p = &prg;
2571 if (rta_sec_era != RTA_SEC_ERA_2 && era_2_sw_hfn_ovrd) {
2572 pr_err("Cannot select SW HFN override for other era than 2");
2576 if (sn_size != PDCP_SN_SIZE_12 && sn_size != PDCP_SN_SIZE_5) {
2577 pr_err("C-plane supports only 5-bit and 12-bit sequence numbers\n");
2581 PROGRAM_CNTXT_INIT(p, descbuf, 0);
2583 PROGRAM_SET_BSWAP(p);
2585 PROGRAM_SET_36BIT_ADDR(p);
2587 SHR_HDR(p, desc_share[cipherdata->algtype][authdata->algtype], 0, 0);
2589 pdb_type = cnstr_pdcp_c_plane_pdb(p,
2598 SET_LABEL(p, pdb_end);
2600 err = insert_hfn_ov_op(p, sn_size, pdb_type,
2605 err = pdcp_cp_fp[cipherdata->algtype][authdata->algtype](p,
2609 OP_TYPE_DECAP_PROTOCOL,
2615 PATCH_HDR(p, 0, pdb_end);
2617 return PROGRAM_FINALIZE(p);
2621 pdcp_insert_uplane_with_int_op(struct program *p,
2622 bool swap __maybe_unused,
2623 struct alginfo *cipherdata,
2624 struct alginfo *authdata,
2625 enum pdcp_sn_size sn_size,
2626 unsigned char era_2_sw_hfn_ovrd,
2630 (*pdcp_cp_fp[PDCP_CIPHER_TYPE_INVALID][PDCP_AUTH_TYPE_INVALID])
2631 (struct program*, bool swap, struct alginfo *,
2632 struct alginfo *, unsigned int, enum pdcp_sn_size,
2633 unsigned char __maybe_unused) = {
2635 pdcp_insert_cplane_null_op, /* NULL */
2636 pdcp_insert_cplane_int_only_op, /* SNOW f9 */
2637 pdcp_insert_cplane_int_only_op, /* AES CMAC */
2638 pdcp_insert_cplane_int_only_op /* ZUC-I */
2641 pdcp_insert_cplane_enc_only_op, /* NULL */
2642 pdcp_insert_cplane_acc_op, /* SNOW f9 */
2643 pdcp_insert_cplane_snow_aes_op, /* AES CMAC */
2644 pdcp_insert_cplane_snow_zuc_op /* ZUC-I */
2647 pdcp_insert_cplane_enc_only_op, /* NULL */
2648 pdcp_insert_cplane_aes_snow_op, /* SNOW f9 */
2649 pdcp_insert_cplane_acc_op, /* AES CMAC */
2650 pdcp_insert_cplane_aes_zuc_op /* ZUC-I */
2653 pdcp_insert_cplane_enc_only_op, /* NULL */
2654 pdcp_insert_cplane_zuc_snow_op, /* SNOW f9 */
2655 pdcp_insert_cplane_zuc_aes_op, /* AES CMAC */
2656 pdcp_insert_cplane_acc_op /* ZUC-I */
2661 err = pdcp_cp_fp[cipherdata->algtype][authdata->algtype](p,
2676 * cnstr_shdsc_pdcp_u_plane_encap - Function for creating a PDCP User Plane
2677 * encapsulation descriptor.
2678 * @descbuf: pointer to buffer for descriptor construction
2679 * @ps: if 36/40bit addressing is desired, this parameter must be true
2680 * @swap: must be true when core endianness doesn't match SEC endianness
2681 * @sn_size: selects Sequence Number Size: 7/12/15 bits
2682 * @hfn: starting Hyper Frame Number to be used together with the SN from the
2684 * @bearer: radio bearer ID
2685 * @direction: the direction of the PDCP frame (UL/DL)
2686 * @hfn_threshold: HFN value that once reached triggers a warning from SEC that
2687 * keys should be renegotiated at the earliest convenience.
2688 * @cipherdata: pointer to block cipher transform definitions
2689 * Valid algorithm values are those from cipher_type_pdcp enum.
2690 * @era_2_sw_hfn_ovrd: if software HFN override mechanism is desired for
2691 * this descriptor. Note: Can only be used for
2694 * Return: size of descriptor written in words or negative number on error.
2695 * Once the function returns, the value of this parameter can be used
2696 * for reclaiming the space that wasn't used for the descriptor.
2698 * Note: descbuf must be large enough to contain a full 256 byte long
2699 * descriptor; after the function returns, by subtracting the actual number of
2700 * bytes used, the user can reuse the remaining buffer space for other purposes.
2703 cnstr_shdsc_pdcp_u_plane_encap(uint32_t *descbuf,
2706 enum pdcp_sn_size sn_size,
2708 unsigned short bearer,
2709 unsigned short direction,
2710 uint32_t hfn_threshold,
2711 struct alginfo *cipherdata,
2712 struct alginfo *authdata,
2713 unsigned char era_2_sw_hfn_ovrd)
2716 struct program *p = &prg;
2718 static enum rta_share_type
2719 desc_share[PDCP_CIPHER_TYPE_INVALID][PDCP_AUTH_TYPE_INVALID] = {
2721 SHR_WAIT, /* NULL */
2722 SHR_ALWAYS, /* SNOW f9 */
2723 SHR_ALWAYS, /* AES CMAC */
2724 SHR_ALWAYS /* ZUC-I */
2727 SHR_ALWAYS, /* NULL */
2728 SHR_ALWAYS, /* SNOW f9 */
2729 SHR_WAIT, /* AES CMAC */
2730 SHR_WAIT /* ZUC-I */
2733 SHR_ALWAYS, /* NULL */
2734 SHR_ALWAYS, /* SNOW f9 */
2735 SHR_ALWAYS, /* AES CMAC */
2736 SHR_WAIT /* ZUC-I */
2739 SHR_ALWAYS, /* NULL */
2740 SHR_WAIT, /* SNOW f9 */
2741 SHR_WAIT, /* AES CMAC */
2742 SHR_ALWAYS /* ZUC-I */
2747 if (rta_sec_era != RTA_SEC_ERA_2 && era_2_sw_hfn_ovrd) {
2748 pr_err("Cannot select SW HFN ovrd for other era than 2");
2752 if (authdata && !authdata->algtype && rta_sec_era < RTA_SEC_ERA_8) {
2753 pr_err("Cannot use u-plane auth with era < 8");
2757 PROGRAM_CNTXT_INIT(p, descbuf, 0);
2759 PROGRAM_SET_BSWAP(p);
2761 PROGRAM_SET_36BIT_ADDR(p);
2764 SHR_HDR(p, desc_share[cipherdata->algtype][authdata->algtype], 0, 0);
2766 SHR_HDR(p, SHR_ALWAYS, 0, 0);
2767 if (cnstr_pdcp_u_plane_pdb(p, sn_size, hfn, bearer, direction,
2769 pr_err("Error creating PDCP UPlane PDB\n");
2772 SET_LABEL(p, pdb_end);
2774 err = insert_hfn_ov_op(p, sn_size, PDCP_PDB_TYPE_FULL_PDB,
2780 case PDCP_SN_SIZE_7:
2781 case PDCP_SN_SIZE_12:
2782 switch (cipherdata->algtype) {
2783 case PDCP_CIPHER_TYPE_ZUC:
2784 if (rta_sec_era < RTA_SEC_ERA_5) {
2785 pr_err("Invalid era for selected algorithm\n");
2789 case PDCP_CIPHER_TYPE_AES:
2790 case PDCP_CIPHER_TYPE_SNOW:
2791 case PDCP_CIPHER_TYPE_NULL:
2792 /* Insert auth key if requested */
2793 if (authdata && authdata->algtype) {
2794 KEY(p, KEY2, authdata->key_enc_flags,
2795 (uint64_t)authdata->key, authdata->keylen,
2796 INLINE_KEY(authdata));
2798 /* Insert Cipher Key */
2799 KEY(p, KEY1, cipherdata->key_enc_flags,
2800 (uint64_t)cipherdata->key, cipherdata->keylen,
2801 INLINE_KEY(cipherdata));
2804 PROTOCOL(p, OP_TYPE_ENCAP_PROTOCOL,
2805 OP_PCLID_LTE_PDCP_USER_RN,
2806 ((uint16_t)cipherdata->algtype << 8) |
2807 (uint16_t)authdata->algtype);
2809 PROTOCOL(p, OP_TYPE_ENCAP_PROTOCOL,
2810 OP_PCLID_LTE_PDCP_USER,
2811 (uint16_t)cipherdata->algtype);
2814 pr_err("%s: Invalid encrypt algorithm selected: %d\n",
2815 "cnstr_pcl_shdsc_pdcp_u_plane_decap",
2816 cipherdata->algtype);
2821 case PDCP_SN_SIZE_15:
2822 case PDCP_SN_SIZE_18:
2824 err = pdcp_insert_uplane_with_int_op(p, swap,
2825 cipherdata, authdata,
2826 sn_size, era_2_sw_hfn_ovrd,
2827 OP_TYPE_ENCAP_PROTOCOL);
2834 switch (cipherdata->algtype) {
2835 case PDCP_CIPHER_TYPE_NULL:
2836 insert_copy_frame_op(p,
2838 OP_TYPE_ENCAP_PROTOCOL);
2842 err = pdcp_insert_uplane_no_int_op(p, swap, cipherdata,
2843 OP_TYPE_ENCAP_PROTOCOL, sn_size);
2850 case PDCP_SN_SIZE_5:
2852 pr_err("Invalid SN size selected\n");
2856 PATCH_HDR(p, 0, pdb_end);
2857 return PROGRAM_FINALIZE(p);
2861 * cnstr_shdsc_pdcp_u_plane_decap - Function for creating a PDCP User Plane
2862 * decapsulation descriptor.
2863 * @descbuf: pointer to buffer for descriptor construction
2864 * @ps: if 36/40bit addressing is desired, this parameter must be true
2865 * @swap: must be true when core endianness doesn't match SEC endianness
2866 * @sn_size: selects Sequence Number Size: 7/12/15 bits
2867 * @hfn: starting Hyper Frame Number to be used together with the SN from the
2869 * @bearer: radio bearer ID
2870 * @direction: the direction of the PDCP frame (UL/DL)
2871 * @hfn_threshold: HFN value that once reached triggers a warning from SEC that
2872 * keys should be renegotiated at the earliest convenience.
2873 * @cipherdata: pointer to block cipher transform definitions
2874 * Valid algorithm values are those from cipher_type_pdcp enum.
2875 * @era_2_sw_hfn_ovrd: if software HFN override mechanism is desired for
2876 * this descriptor. Note: Can only be used for
2879 * Return: size of descriptor written in words or negative number on error.
2880 * Once the function returns, the value of this parameter can be used
2881 * for reclaiming the space that wasn't used for the descriptor.
2883 * Note: descbuf must be large enough to contain a full 256 byte long
2884 * descriptor; after the function returns, by subtracting the actual number of
2885 * bytes used, the user can reuse the remaining buffer space for other purposes.
2888 cnstr_shdsc_pdcp_u_plane_decap(uint32_t *descbuf,
2891 enum pdcp_sn_size sn_size,
2893 unsigned short bearer,
2894 unsigned short direction,
2895 uint32_t hfn_threshold,
2896 struct alginfo *cipherdata,
2897 struct alginfo *authdata,
2898 unsigned char era_2_sw_hfn_ovrd)
2901 struct program *p = &prg;
2903 static enum rta_share_type
2904 desc_share[PDCP_CIPHER_TYPE_INVALID][PDCP_AUTH_TYPE_INVALID] = {
2906 SHR_WAIT, /* NULL */
2907 SHR_ALWAYS, /* SNOW f9 */
2908 SHR_ALWAYS, /* AES CMAC */
2909 SHR_ALWAYS /* ZUC-I */
2912 SHR_ALWAYS, /* NULL */
2913 SHR_ALWAYS, /* SNOW f9 */
2914 SHR_WAIT, /* AES CMAC */
2915 SHR_WAIT /* ZUC-I */
2918 SHR_ALWAYS, /* NULL */
2919 SHR_ALWAYS, /* SNOW f9 */
2920 SHR_ALWAYS, /* AES CMAC */
2921 SHR_WAIT /* ZUC-I */
2924 SHR_ALWAYS, /* NULL */
2925 SHR_WAIT, /* SNOW f9 */
2926 SHR_WAIT, /* AES CMAC */
2927 SHR_ALWAYS /* ZUC-I */
2933 if (rta_sec_era != RTA_SEC_ERA_2 && era_2_sw_hfn_ovrd) {
2934 pr_err("Cannot select SW HFN override for other era than 2");
2938 if (authdata && !authdata->algtype && rta_sec_era < RTA_SEC_ERA_8) {
2939 pr_err("Cannot use u-plane auth with era < 8");
2943 PROGRAM_CNTXT_INIT(p, descbuf, 0);
2945 PROGRAM_SET_BSWAP(p);
2947 PROGRAM_SET_36BIT_ADDR(p);
2949 SHR_HDR(p, desc_share[cipherdata->algtype][authdata->algtype], 0, 0);
2951 SHR_HDR(p, SHR_ALWAYS, 0, 0);
2953 if (cnstr_pdcp_u_plane_pdb(p, sn_size, hfn, bearer, direction,
2955 pr_err("Error creating PDCP UPlane PDB\n");
2958 SET_LABEL(p, pdb_end);
2960 err = insert_hfn_ov_op(p, sn_size, PDCP_PDB_TYPE_FULL_PDB,
2966 case PDCP_SN_SIZE_7:
2967 case PDCP_SN_SIZE_12:
2968 switch (cipherdata->algtype) {
2969 case PDCP_CIPHER_TYPE_ZUC:
2970 if (rta_sec_era < RTA_SEC_ERA_5) {
2971 pr_err("Invalid era for selected algorithm\n");
2975 case PDCP_CIPHER_TYPE_AES:
2976 case PDCP_CIPHER_TYPE_SNOW:
2977 case PDCP_CIPHER_TYPE_NULL:
2978 /* Insert auth key if requested */
2979 if (authdata && authdata->algtype)
2980 KEY(p, KEY2, authdata->key_enc_flags,
2981 (uint64_t)authdata->key, authdata->keylen,
2982 INLINE_KEY(authdata));
2984 /* Insert Cipher Key */
2985 KEY(p, KEY1, cipherdata->key_enc_flags,
2986 cipherdata->key, cipherdata->keylen,
2987 INLINE_KEY(cipherdata));
2989 PROTOCOL(p, OP_TYPE_DECAP_PROTOCOL,
2990 OP_PCLID_LTE_PDCP_USER_RN,
2991 ((uint16_t)cipherdata->algtype << 8) |
2992 (uint16_t)authdata->algtype);
2994 PROTOCOL(p, OP_TYPE_DECAP_PROTOCOL,
2995 OP_PCLID_LTE_PDCP_USER,
2996 (uint16_t)cipherdata->algtype);
2999 pr_err("%s: Invalid encrypt algorithm selected: %d\n",
3000 "cnstr_pcl_shdsc_pdcp_u_plane_decap",
3001 cipherdata->algtype);
3006 case PDCP_SN_SIZE_15:
3007 case PDCP_SN_SIZE_18:
3009 err = pdcp_insert_uplane_with_int_op(p, swap,
3010 cipherdata, authdata,
3011 sn_size, era_2_sw_hfn_ovrd,
3012 OP_TYPE_DECAP_PROTOCOL);
3019 switch (cipherdata->algtype) {
3020 case PDCP_CIPHER_TYPE_NULL:
3021 insert_copy_frame_op(p,
3023 OP_TYPE_DECAP_PROTOCOL);
3027 err = pdcp_insert_uplane_no_int_op(p, swap, cipherdata,
3028 OP_TYPE_DECAP_PROTOCOL, sn_size);
3035 case PDCP_SN_SIZE_5:
3037 pr_err("Invalid SN size selected\n");
3041 PATCH_HDR(p, 0, pdb_end);
3042 return PROGRAM_FINALIZE(p);
3046 * cnstr_shdsc_pdcp_short_mac - Function for creating a PDCP Short MAC
3048 * @descbuf: pointer to buffer for descriptor construction
3049 * @ps: if 36/40bit addressing is desired, this parameter must be true
3050 * @swap: must be true when core endianness doesn't match SEC endianness
3051 * @authdata: pointer to authentication transform definitions
3052 * Valid algorithm values are those from auth_type_pdcp enum.
3054 * Return: size of descriptor written in words or negative number on error.
3055 * Once the function returns, the value of this parameter can be used
3056 * for reclaiming the space that wasn't used for the descriptor.
3058 * Note: descbuf must be large enough to contain a full 256 byte long
3059 * descriptor; after the function returns, by subtracting the actual number of
3060 * bytes used, the user can reuse the remaining buffer space for other purposes.
3063 cnstr_shdsc_pdcp_short_mac(uint32_t *descbuf,
3066 struct alginfo *authdata)
3069 struct program *p = &prg;
3070 uint32_t iv[3] = {0, 0, 0};
3071 LABEL(local_offset);
3072 REFERENCE(move_cmd_read_descbuf);
3073 REFERENCE(move_cmd_write_descbuf);
3075 PROGRAM_CNTXT_INIT(p, descbuf, 0);
3077 PROGRAM_SET_BSWAP(p);
3079 PROGRAM_SET_36BIT_ADDR(p);
3081 SHR_HDR(p, SHR_ALWAYS, 1, 0);
3083 if (rta_sec_era > RTA_SEC_ERA_2) {
3084 MATHB(p, SEQINSZ, SUB, ZERO, VSEQINSZ, 4, 0);
3085 MATHB(p, SEQINSZ, SUB, ZERO, MATH1, 4, 0);
3087 MATHB(p, SEQINSZ, ADD, ONE, MATH1, 4, 0);
3088 MATHB(p, MATH1, SUB, ONE, MATH1, 4, 0);
3089 MATHB(p, ZERO, ADD, MATH1, VSEQINSZ, 4, 0);
3090 MOVE(p, MATH1, 0, MATH0, 0, 8, IMMED);
3093 * Since MOVELEN is available only starting with
3094 * SEC ERA 3, use poor man's MOVELEN: create a MOVE
3095 * command dynamically by writing the length from M1 by
3096 * OR-ing the command in the M1 register and MOVE the
3097 * result into the descriptor buffer. Care must be taken
3098 * wrt. the location of the command because of SEC
3099 * pipelining. The actual MOVEs are written at the end
3100 * of the descriptor due to calculations needed on the
3101 * offset in the descriptor for the MOVE command.
3103 move_cmd_read_descbuf = MOVE(p, DESCBUF, 0, MATH0, 0, 6,
3105 move_cmd_write_descbuf = MOVE(p, MATH0, 0, DESCBUF, 0, 8,
3108 MATHB(p, ZERO, ADD, MATH1, VSEQOUTSZ, 4, 0);
3110 switch (authdata->algtype) {
3111 case PDCP_AUTH_TYPE_NULL:
3112 SEQFIFOSTORE(p, MSG, 0, 0, VLF);
3113 if (rta_sec_era > RTA_SEC_ERA_2) {
3114 MOVE(p, AB1, 0, OFIFO, 0, MATH1, 0);
3116 SET_LABEL(p, local_offset);
3118 /* Shut off automatic Info FIFO entries */
3119 LOAD(p, 0, DCTRL, LDOFF_DISABLE_AUTO_NFIFO, 0, IMMED);
3121 /* Placeholder for MOVE command with length from M1
3124 MOVE(p, IFIFOAB1, 0, OFIFO, 0, 0, IMMED);
3126 /* Enable automatic Info FIFO entries */
3127 LOAD(p, 0, DCTRL, LDOFF_ENABLE_AUTO_NFIFO, 0, IMMED);
3130 LOAD(p, (uintptr_t)iv, MATH0, 0, 8, IMMED | COPY);
3131 SEQFIFOLOAD(p, MSG1, 0, VLF | LAST1 | LAST2 | FLUSH1);
3132 SEQSTORE(p, MATH0, 0, 4, 0);
3136 case PDCP_AUTH_TYPE_SNOW:
3138 iv[1] = swap ? swab32(0x04000000) : 0x04000000;
3139 iv[2] = swap ? swab32(0xF8000000) : 0xF8000000;
3141 KEY(p, KEY2, authdata->key_enc_flags, authdata->key,
3142 authdata->keylen, INLINE_KEY(authdata));
3143 LOAD(p, (uintptr_t)&iv, CONTEXT2, 0, 12, IMMED | COPY);
3144 ALG_OPERATION(p, OP_ALG_ALGSEL_SNOW_F9,
3146 OP_ALG_AS_INITFINAL,
3149 SEQFIFOSTORE(p, MSG, 0, 0, VLF);
3151 if (rta_sec_era > RTA_SEC_ERA_2) {
3152 MOVE(p, AB1, 0, OFIFO, 0, MATH1, 0);
3154 SET_LABEL(p, local_offset);
3157 /* Shut off automatic Info FIFO entries */
3158 LOAD(p, 0, DCTRL, LDOFF_DISABLE_AUTO_NFIFO, 0, IMMED);
3160 /* Placeholder for MOVE command with length from M1
3163 MOVE(p, IFIFOAB1, 0, OFIFO, 0, 0, IMMED);
3165 /* Enable automatic Info FIFO entries */
3166 LOAD(p, 0, DCTRL, LDOFF_ENABLE_AUTO_NFIFO, 0, IMMED);
3168 SEQFIFOLOAD(p, MSGINSNOOP, 0, VLF | LAST1 | LAST2 | FLUSH1);
3169 SEQSTORE(p, CONTEXT2, 0, 4, 0);
3173 case PDCP_AUTH_TYPE_AES:
3175 iv[1] = swap ? swab32(0xFC000000) : 0xFC000000;
3176 iv[2] = 0x00000000; /* unused */
3178 KEY(p, KEY1, authdata->key_enc_flags, authdata->key,
3179 authdata->keylen, INLINE_KEY(authdata));
3180 LOAD(p, (uintptr_t)&iv, MATH0, 0, 8, IMMED | COPY);
3181 MOVE(p, MATH0, 0, IFIFOAB1, 0, 8, IMMED);
3182 ALG_OPERATION(p, OP_ALG_ALGSEL_AES,
3184 OP_ALG_AS_INITFINAL,
3187 SEQFIFOSTORE(p, MSG, 0, 0, VLF);
3189 if (rta_sec_era > RTA_SEC_ERA_2) {
3190 MOVE(p, AB2, 0, OFIFO, 0, MATH1, 0);
3192 SET_LABEL(p, local_offset);
3194 /* Shut off automatic Info FIFO entries */
3195 LOAD(p, 0, DCTRL, LDOFF_DISABLE_AUTO_NFIFO, 0, IMMED);
3197 /* Placeholder for MOVE command with length from M1
3200 MOVE(p, IFIFOAB2, 0, OFIFO, 0, 0, IMMED);
3202 /* Enable automatic Info FIFO entries */
3203 LOAD(p, 0, DCTRL, LDOFF_ENABLE_AUTO_NFIFO, 0, IMMED);
3205 SEQFIFOLOAD(p, MSGINSNOOP, 0, VLF | LAST1 | LAST2 | FLUSH1);
3206 SEQSTORE(p, CONTEXT1, 0, 4, 0);
3210 case PDCP_AUTH_TYPE_ZUC:
3211 if (rta_sec_era < RTA_SEC_ERA_5) {
3212 pr_err("Invalid era for selected algorithm\n");
3216 iv[1] = swap ? swab32(0xFC000000) : 0xFC000000;
3217 iv[2] = 0x00000000; /* unused */
3219 KEY(p, KEY2, authdata->key_enc_flags, authdata->key,
3220 authdata->keylen, INLINE_KEY(authdata));
3221 LOAD(p, (uintptr_t)&iv, CONTEXT2, 0, 12, IMMED | COPY);
3222 ALG_OPERATION(p, OP_ALG_ALGSEL_ZUCA,
3224 OP_ALG_AS_INITFINAL,
3227 SEQFIFOSTORE(p, MSG, 0, 0, VLF);
3228 MOVE(p, AB1, 0, OFIFO, 0, MATH1, 0);
3229 SEQFIFOLOAD(p, MSGINSNOOP, 0, VLF | LAST1 | LAST2 | FLUSH1);
3230 SEQSTORE(p, CONTEXT2, 0, 4, 0);
3235 pr_err("%s: Invalid integrity algorithm selected: %d\n",
3236 "cnstr_shdsc_pdcp_short_mac", authdata->algtype);
3241 if (rta_sec_era < RTA_SEC_ERA_3) {
3242 PATCH_MOVE(p, move_cmd_read_descbuf, local_offset);
3243 PATCH_MOVE(p, move_cmd_write_descbuf, local_offset);
3246 return PROGRAM_FINALIZE(p);
3249 #endif /* __DESC_PDCP_H__ */