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_12BIT_SN_MASK - This mask is used in the PDCP descriptors for
48 * extracting the sequence number (SN) from the
49 * PDCP User Plane header.
51 #define PDCP_12BIT_SN_MASK 0xFF0F0000
52 #define PDCP_12BIT_SN_MASK_BE 0x00000FFF
55 * PDCP_U_PLANE_15BIT_SN_MASK - This mask is used in the PDCP descriptors for
56 * extracting the sequence number (SN) from the
57 * PDCP User Plane header. For PDCP Control Plane,
58 * the SN is constant (5 bits) as opposed to PDCP
59 * Data Plane (7/12/15 bits).
61 #define PDCP_U_PLANE_15BIT_SN_MASK 0xFF7F0000
62 #define PDCP_U_PLANE_15BIT_SN_MASK_BE 0x00007FFF
65 * PDCP_U_PLANE_18BIT_SN_MASK - This mask is used in the PDCP descriptors for
66 * extracting the sequence number (SN) from the
67 * PDCP User Plane header.
69 #define PDCP_U_PLANE_18BIT_SN_MASK 0xFFFF0300
70 #define PDCP_U_PLANE_18BIT_SN_MASK_BE 0x0003FFFF
73 * PDCP_BEARER_MASK - This mask is used masking out the bearer for PDCP
74 * processing with SNOW f9 in LTE.
76 * The value on which this mask is applied is formatted as below:
77 * Count-C (32 bit) | Bearer (5 bit) | Direction (1 bit) | 0 (26 bits)
79 * Applying this mask is done for creating the upper 64 bits of the IV needed
82 * The lower 32 bits of the mask are used for masking the direction for AES
85 #define PDCP_BEARER_MASK 0x00000004FFFFFFFFull
86 #define PDCP_BEARER_MASK_BE 0xFFFFFFFF04000000ull
89 * PDCP_DIR_MASK - This mask is used masking out the direction for PDCP
90 * processing with SNOW f9 in LTE.
92 * The value on which this mask is applied is formatted as below:
93 * Bearer (5 bit) | Direction (1 bit) | 0 (26 bits)
95 * Applying this mask is done for creating the lower 32 bits of the IV needed
98 * The upper 32 bits of the mask are used for masking the direction for AES
101 #define PDCP_DIR_MASK 0x00000000000000F8ull
102 #define PDCP_DIR_MASK_BE 0xF800000000000000ull
105 * PDCP_NULL_INT_MAC_I_VAL - The value of the PDCP PDU MAC-I in case NULL
109 #define PDCP_NULL_INT_MAC_I_VAL 0x00000000
112 * PDCP_NULL_INT_ICV_CHECK_FAILED_STATUS - The status used to report ICV check
113 * failed in case of NULL integrity
114 * Control Plane processing.
116 #define PDCP_NULL_INT_ICV_CHECK_FAILED_STATUS 0x0A
118 * PDCP_DPOVRD_HFN_OV_EN - Value to be used in the FD status/cmd field to
119 * indicate the HFN override mechanism is active for the
122 #define PDCP_DPOVRD_HFN_OV_EN 0x80000000
125 * PDCP_P4080REV2_HFN_OV_BUFLEN - The length in bytes of the supplementary space
126 * that must be provided by the user at the
127 * beginning of the input frame buffer for
130 * The format of the frame buffer is the following:
132 * |<---PDCP_P4080REV2_HFN_OV_BUFLEN-->|
133 * //===================================||============||==============\\
134 * || PDCP_DPOVRD_HFN_OV_EN | HFN value || PDCP Header|| PDCP Payload ||
135 * \\===================================||============||==============//
137 * If HFN override mechanism is not desired, then the MSB of the first 4 bytes
140 #define PDCP_P4080REV2_HFN_OV_BUFLEN 4
143 * enum cipher_type_pdcp - Type selectors for cipher types in PDCP protocol OP
145 * @PDCP_CIPHER_TYPE_NULL: NULL
146 * @PDCP_CIPHER_TYPE_SNOW: SNOW F8
147 * @PDCP_CIPHER_TYPE_AES: AES
148 * @PDCP_CIPHER_TYPE_ZUC: ZUCE
149 * @PDCP_CIPHER_TYPE_INVALID: invalid option
151 enum cipher_type_pdcp {
152 PDCP_CIPHER_TYPE_NULL,
153 PDCP_CIPHER_TYPE_SNOW,
154 PDCP_CIPHER_TYPE_AES,
155 PDCP_CIPHER_TYPE_ZUC,
156 PDCP_CIPHER_TYPE_INVALID
160 * enum auth_type_pdcp - Type selectors for integrity types in PDCP protocol OP
162 * @PDCP_AUTH_TYPE_NULL: NULL
163 * @PDCP_AUTH_TYPE_SNOW: SNOW F9
164 * @PDCP_AUTH_TYPE_AES: AES CMAC
165 * @PDCP_AUTH_TYPE_ZUC: ZUCA
166 * @PDCP_AUTH_TYPE_INVALID: invalid option
168 enum auth_type_pdcp {
173 PDCP_AUTH_TYPE_INVALID
177 * enum pdcp_dir - Type selectors for direction for PDCP protocol
178 * @PDCP_DIR_UPLINK: uplink direction
179 * @PDCP_DIR_DOWNLINK: downlink direction
180 * @PDCP_DIR_INVALID: invalid option
184 PDCP_DIR_DOWNLINK = 1,
189 * enum pdcp_plane - PDCP domain selectors
190 * @PDCP_CONTROL_PLANE: Control Plane
191 * @PDCP_DATA_PLANE: Data Plane
192 * @PDCP_SHORT_MAC: Short MAC
201 * enum pdcp_sn_size - Sequence Number Size selectors for PDCP protocol
202 * @PDCP_SN_SIZE_5: 5bit sequence number
203 * @PDCP_SN_SIZE_7: 7bit sequence number
204 * @PDCP_SN_SIZE_12: 12bit sequence number
205 * @PDCP_SN_SIZE_15: 15bit sequence number
206 * @PDCP_SN_SIZE_18: 18bit sequence number
211 PDCP_SN_SIZE_12 = 12,
212 PDCP_SN_SIZE_15 = 15,
217 * PDCP Control Plane Protocol Data Blocks
219 #define PDCP_C_PLANE_PDB_HFN_SHIFT 5
220 #define PDCP_C_PLANE_PDB_BEARER_SHIFT 27
221 #define PDCP_C_PLANE_PDB_DIR_SHIFT 26
222 #define PDCP_C_PLANE_PDB_HFN_THR_SHIFT 5
224 #define PDCP_U_PLANE_PDB_OPT_SHORT_SN 0x2
225 #define PDCP_U_PLANE_PDB_OPT_15B_SN 0x4
226 #define PDCP_U_PLANE_PDB_OPT_18B_SN 0x6
227 #define PDCP_U_PLANE_PDB_SHORT_SN_HFN_SHIFT 7
228 #define PDCP_U_PLANE_PDB_LONG_SN_HFN_SHIFT 12
229 #define PDCP_U_PLANE_PDB_15BIT_SN_HFN_SHIFT 15
230 #define PDCP_U_PLANE_PDB_18BIT_SN_HFN_SHIFT 18
231 #define PDCP_U_PLANE_PDB_BEARER_SHIFT 27
232 #define PDCP_U_PLANE_PDB_DIR_SHIFT 26
233 #define PDCP_U_PLANE_PDB_SHORT_SN_HFN_THR_SHIFT 7
234 #define PDCP_U_PLANE_PDB_LONG_SN_HFN_THR_SHIFT 12
235 #define PDCP_U_PLANE_PDB_15BIT_SN_HFN_THR_SHIFT 15
236 #define PDCP_U_PLANE_PDB_18BIT_SN_HFN_THR_SHIFT 18
243 uint32_t hfn_res; /* HyperFrame number,(27, 25 or 21 bits),
244 * left aligned & right-padded with zeros.
246 uint32_t bearer_dir_res;/* Bearer(5 bits), packet direction (1 bit),
247 * left aligned & right-padded with zeros.
249 uint32_t hfn_thr_res; /* HyperFrame number threshold (27, 25 or 21
250 * bits), left aligned & right-padded with
256 * PDCP internal PDB types
259 PDCP_PDB_TYPE_NO_PDB,
260 PDCP_PDB_TYPE_FULL_PDB,
261 PDCP_PDB_TYPE_REDUCED_PDB,
262 PDCP_PDB_TYPE_INVALID
266 * Function for appending the portion of a PDCP Control Plane shared descriptor
267 * which performs NULL encryption and integrity (i.e. copies the input frame
268 * to the output frame, appending 32 bits of zeros at the end (MAC-I for
272 pdcp_insert_cplane_null_op(struct program *p,
273 bool swap __maybe_unused,
274 struct alginfo *cipherdata __maybe_unused,
275 struct alginfo *authdata __maybe_unused,
277 enum pdcp_sn_size sn_size __maybe_unused,
278 unsigned char era_2_sw_hfn_ovrd __maybe_unused)
281 REFERENCE(move_cmd_read_descbuf);
282 REFERENCE(move_cmd_write_descbuf);
284 if (rta_sec_era > RTA_SEC_ERA_2) {
285 MATHB(p, SEQINSZ, ADD, ZERO, VSEQINSZ, 4, 0);
286 if (dir == OP_TYPE_ENCAP_PROTOCOL)
287 MATHB(p, SEQINSZ, ADD, PDCP_MAC_I_LEN, VSEQOUTSZ, 4,
290 MATHB(p, SEQINSZ, SUB, PDCP_MAC_I_LEN, VSEQOUTSZ, 4,
293 MATHB(p, SEQINSZ, ADD, ONE, VSEQINSZ, 4, 0);
294 MATHB(p, VSEQINSZ, SUB, ONE, VSEQINSZ, 4, 0);
296 if (dir == OP_TYPE_ENCAP_PROTOCOL) {
297 MATHB(p, SEQINSZ, ADD, PDCP_MAC_I_LEN, VSEQOUTSZ, 4,
299 MATHB(p, VSEQINSZ, SUB, ONE, MATH0, 4, 0);
301 MATHB(p, VSEQINSZ, SUB, PDCP_MAC_I_LEN, VSEQINSZ, 4,
303 MATHB(p, SEQINSZ, SUB, PDCP_MAC_I_LEN, VSEQOUTSZ, 4,
305 MATHB(p, VSEQOUTSZ, SUB, ONE, MATH0, 4, 0);
308 MATHB(p, MATH0, ADD, ONE, MATH0, 4, 0);
311 * Since MOVELEN is available only starting with
312 * SEC ERA 3, use poor man's MOVELEN: create a MOVE
313 * command dynamically by writing the length from M1 by
314 * OR-ing the command in the M1 register and MOVE the
315 * result into the descriptor buffer. Care must be taken
316 * wrt. the location of the command because of SEC
317 * pipelining. The actual MOVEs are written at the end
318 * of the descriptor due to calculations needed on the
319 * offset in the descriptor for the MOVE command.
321 move_cmd_read_descbuf = MOVE(p, DESCBUF, 0, MATH0, 0, 6,
323 move_cmd_write_descbuf = MOVE(p, MATH0, 0, DESCBUF, 0, 8,
326 MATHB(p, VSEQINSZ, SUB, PDCP_NULL_MAX_FRAME_LEN, NONE, 4,
328 JUMP(p, PDCP_MAX_FRAME_LEN_STATUS, HALT_STATUS, ALL_FALSE, MATH_N);
330 if (rta_sec_era > RTA_SEC_ERA_2) {
331 if (dir == OP_TYPE_ENCAP_PROTOCOL)
332 MATHB(p, VSEQINSZ, ADD, ZERO, MATH0, 4, 0);
334 MATHB(p, VSEQOUTSZ, ADD, ZERO, MATH0, 4, 0);
336 SEQFIFOSTORE(p, MSG, 0, 0, VLF);
337 SEQFIFOLOAD(p, MSG1, 0, VLF | LAST1 | FLUSH1);
339 if (rta_sec_era > RTA_SEC_ERA_2) {
340 MOVE(p, AB1, 0, OFIFO, 0, MATH0, 0);
342 SET_LABEL(p, local_offset);
344 /* Shut off automatic Info FIFO entries */
345 LOAD(p, 0, DCTRL, LDOFF_DISABLE_AUTO_NFIFO, 0, IMMED);
346 /* Placeholder for MOVE command with length from M1 register */
347 MOVE(p, IFIFOAB1, 0, OFIFO, 0, 0, IMMED);
348 /* Enable automatic Info FIFO entries */
349 LOAD(p, 0, DCTRL, LDOFF_ENABLE_AUTO_NFIFO, 0, IMMED);
352 if (dir == OP_TYPE_ENCAP_PROTOCOL) {
353 MATHB(p, MATH1, XOR, MATH1, MATH0, 8, 0);
354 MOVE(p, MATH0, 0, OFIFO, 0, 4, IMMED);
357 if (rta_sec_era < RTA_SEC_ERA_3) {
358 PATCH_MOVE(p, move_cmd_read_descbuf, local_offset);
359 PATCH_MOVE(p, move_cmd_write_descbuf, local_offset);
366 insert_copy_frame_op(struct program *p,
367 struct alginfo *cipherdata __maybe_unused,
368 unsigned int dir __maybe_unused)
371 REFERENCE(move_cmd_read_descbuf);
372 REFERENCE(move_cmd_write_descbuf);
374 if (rta_sec_era > RTA_SEC_ERA_2) {
375 MATHB(p, SEQINSZ, ADD, ZERO, VSEQINSZ, 4, 0);
376 MATHB(p, SEQINSZ, ADD, ZERO, VSEQOUTSZ, 4, 0);
378 MATHB(p, SEQINSZ, ADD, ONE, VSEQINSZ, 4, 0);
379 MATHB(p, VSEQINSZ, SUB, ONE, VSEQINSZ, 4, 0);
380 MATHB(p, SEQINSZ, ADD, ONE, VSEQOUTSZ, 4, 0);
381 MATHB(p, VSEQOUTSZ, SUB, ONE, VSEQOUTSZ, 4, 0);
382 MATHB(p, VSEQINSZ, SUB, ONE, MATH0, 4, 0);
383 MATHB(p, MATH0, ADD, ONE, MATH0, 4, 0);
386 * Since MOVELEN is available only starting with
387 * SEC ERA 3, use poor man's MOVELEN: create a MOVE
388 * command dynamically by writing the length from M1 by
389 * OR-ing the command in the M1 register and MOVE the
390 * result into the descriptor buffer. Care must be taken
391 * wrt. the location of the command because of SEC
392 * pipelining. The actual MOVEs are written at the end
393 * of the descriptor due to calculations needed on the
394 * offset in the descriptor for the MOVE command.
396 move_cmd_read_descbuf = MOVE(p, DESCBUF, 0, MATH0, 0, 6,
398 move_cmd_write_descbuf = MOVE(p, MATH0, 0, DESCBUF, 0, 8,
401 MATHB(p, SEQINSZ, SUB, PDCP_NULL_MAX_FRAME_LEN, NONE, 4,
403 JUMP(p, PDCP_MAX_FRAME_LEN_STATUS, HALT_STATUS, ALL_FALSE, MATH_N);
405 if (rta_sec_era > RTA_SEC_ERA_2)
406 MATHB(p, VSEQINSZ, ADD, ZERO, MATH0, 4, 0);
408 SEQFIFOLOAD(p, MSG1, 0, VLF | LAST1 | FLUSH1);
409 if (rta_sec_era > RTA_SEC_ERA_2) {
410 MOVE(p, AB1, 0, OFIFO, 0, MATH0, 0);
412 SET_LABEL(p, local_offset);
414 /* Shut off automatic Info FIFO entries */
415 LOAD(p, 0, DCTRL, LDOFF_DISABLE_AUTO_NFIFO, 0, IMMED);
417 /* Placeholder for MOVE command with length from M0 register */
418 MOVE(p, IFIFOAB1, 0, OFIFO, 0, 0, IMMED);
420 /* Enable automatic Info FIFO entries */
421 LOAD(p, 0, DCTRL, LDOFF_ENABLE_AUTO_NFIFO, 0, IMMED);
424 SEQFIFOSTORE(p, MSG, 0, 0, VLF);
426 if (rta_sec_era < RTA_SEC_ERA_3) {
427 PATCH_MOVE(p, move_cmd_read_descbuf, local_offset);
428 PATCH_MOVE(p, move_cmd_write_descbuf, local_offset);
434 pdcp_insert_cplane_int_only_op(struct program *p,
435 bool swap __maybe_unused,
436 struct alginfo *cipherdata __maybe_unused,
437 struct alginfo *authdata, unsigned int dir,
438 enum pdcp_sn_size sn_size,
439 unsigned char era_2_sw_hfn_ovrd)
441 uint32_t offset = 0, length = 0, sn_mask = 0;
443 /* 12 bit SN is only supported for protocol offload case */
444 if (rta_sec_era >= RTA_SEC_ERA_8 && sn_size == PDCP_SN_SIZE_12) {
445 KEY(p, KEY2, authdata->key_enc_flags, authdata->key,
446 authdata->keylen, INLINE_KEY(authdata));
448 PROTOCOL(p, dir, OP_PCLID_LTE_PDCP_USER_RN,
449 (uint16_t)authdata->algtype);
453 /* Non-proto is supported only for 5bit cplane and 18bit uplane */
458 sn_mask = (swap == false) ? PDCP_C_PLANE_SN_MASK :
459 PDCP_C_PLANE_SN_MASK_BE;
461 case PDCP_SN_SIZE_18:
464 sn_mask = (swap == false) ? PDCP_U_PLANE_18BIT_SN_MASK :
465 PDCP_U_PLANE_18BIT_SN_MASK_BE;
468 case PDCP_SN_SIZE_12:
469 case PDCP_SN_SIZE_15:
470 pr_err("Invalid sn_size for %s\n", __func__);
475 REFERENCE(move_cmd_read_descbuf);
476 REFERENCE(move_cmd_write_descbuf);
478 switch (authdata->algtype) {
479 case PDCP_AUTH_TYPE_SNOW:
480 /* Insert Auth Key */
481 KEY(p, KEY2, authdata->key_enc_flags, authdata->key,
482 authdata->keylen, INLINE_KEY(authdata));
483 SEQLOAD(p, MATH0, offset, length, 0);
484 JUMP(p, 1, LOCAL_JUMP, ALL_TRUE, CALM);
486 if (rta_sec_era > RTA_SEC_ERA_2 ||
487 (rta_sec_era == RTA_SEC_ERA_2 &&
488 era_2_sw_hfn_ovrd == 0)) {
489 SEQINPTR(p, 0, length, RTO);
491 SEQINPTR(p, 0, 5, RTO);
492 SEQFIFOLOAD(p, SKIP, 4, 0);
496 MATHB(p, MATH0, AND, sn_mask, MATH1, 8,
498 MATHB(p, MATH1, SHLD, MATH1, MATH1, 8, 0);
500 MOVEB(p, DESCBUF, 8, MATH2, 0, 8, WAITCOMP | IMMED);
502 MATHB(p, MATH2, AND, PDCP_BEARER_MASK, MATH2, 8,
504 MOVEB(p, DESCBUF, 0x0C, MATH3, 0, 4, WAITCOMP | IMMED);
505 MATHB(p, MATH3, AND, PDCP_DIR_MASK, MATH3, 8, IMMED2);
506 MATHB(p, MATH1, OR, MATH2, MATH2, 8, 0);
507 MOVEB(p, MATH2, 0, CONTEXT2, 0, 0x0C, WAITCOMP | IMMED);
509 MATHB(p, MATH0, AND, sn_mask, MATH1, 8,
511 MATHB(p, MATH1, SHLD, MATH1, MATH1, 8, 0);
513 MOVE(p, DESCBUF, 8, MATH2, 0, 8, WAITCOMP | IMMED);
514 MATHB(p, MATH2, AND, PDCP_BEARER_MASK_BE, MATH2, 8,
517 MOVE(p, DESCBUF, 0x0C, MATH3, 0, 4, WAITCOMP | IMMED);
518 MATHB(p, MATH3, AND, PDCP_DIR_MASK_BE, MATH3, 8,
520 MATHB(p, MATH1, OR, MATH2, MATH2, 8, 0);
521 MOVE(p, MATH2, 0, CONTEXT2, 0, 0x0C, WAITCOMP | IMMED);
524 if (dir == OP_TYPE_DECAP_PROTOCOL) {
525 MATHB(p, SEQINSZ, SUB, PDCP_MAC_I_LEN, MATH1, 4,
528 if (rta_sec_era > RTA_SEC_ERA_2) {
529 MATHB(p, SEQINSZ, SUB, ZERO, MATH1, 4,
532 MATHB(p, SEQINSZ, ADD, ONE, MATH1, 4,
534 MATHB(p, MATH1, SUB, ONE, MATH1, 4,
539 if (rta_sec_era > RTA_SEC_ERA_2) {
540 MATHB(p, MATH1, SUB, ZERO, VSEQINSZ, 4, 0);
541 MATHB(p, MATH1, SUB, ZERO, VSEQOUTSZ, 4, 0);
543 MATHB(p, ZERO, ADD, MATH1, VSEQINSZ, 4, 0);
544 MATHB(p, ZERO, ADD, MATH1, VSEQOUTSZ, 4, 0);
547 * Since MOVELEN is available only starting with
548 * SEC ERA 3, use poor man's MOVELEN: create a MOVE
549 * command dynamically by writing the length from M1 by
550 * OR-ing the command in the M1 register and MOVE the
551 * result into the descriptor buffer. Care must be taken
552 * wrt. the location of the command because of SEC
553 * pipelining. The actual MOVEs are written at the end
554 * of the descriptor due to calculations needed on the
555 * offset in the descriptor for the MOVE command.
557 move_cmd_read_descbuf = MOVE(p, DESCBUF, 0, MATH1, 0, 6,
559 move_cmd_write_descbuf = MOVE(p, MATH1, 0, DESCBUF, 0,
560 8, WAITCOMP | IMMED);
563 SEQFIFOSTORE(p, MSG, 0, 0, VLF);
564 ALG_OPERATION(p, OP_ALG_ALGSEL_SNOW_F9, OP_ALG_AAI_F9,
566 dir == OP_TYPE_ENCAP_PROTOCOL ?
567 ICV_CHECK_DISABLE : ICV_CHECK_ENABLE,
570 if (rta_sec_era > RTA_SEC_ERA_2) {
571 SEQFIFOLOAD(p, MSGINSNOOP, 0,
572 VLF | LAST1 | LAST2 | FLUSH1);
573 MOVE(p, AB1, 0, OFIFO, 0, MATH1, 0);
575 SEQFIFOLOAD(p, MSGINSNOOP, 0,
576 VLF | LAST1 | LAST2 | FLUSH1);
577 SET_LABEL(p, local_offset);
579 /* Shut off automatic Info FIFO entries */
580 LOAD(p, 0, DCTRL, LDOFF_DISABLE_AUTO_NFIFO, 0, IMMED);
582 * Placeholder for MOVE command with length from M1
585 MOVE(p, IFIFOAB1, 0, OFIFO, 0, 0, IMMED);
586 /* Enable automatic Info FIFO entries */
587 LOAD(p, 0, DCTRL, LDOFF_ENABLE_AUTO_NFIFO, 0, IMMED);
590 if (dir == OP_TYPE_DECAP_PROTOCOL)
591 SEQFIFOLOAD(p, ICV2, 4, LAST2);
593 SEQSTORE(p, CONTEXT2, 0, 4, 0);
597 case PDCP_AUTH_TYPE_AES:
598 /* Insert Auth Key */
599 KEY(p, KEY1, authdata->key_enc_flags, authdata->key,
600 authdata->keylen, INLINE_KEY(authdata));
601 SEQLOAD(p, MATH0, offset, length, 0);
602 JUMP(p, 1, LOCAL_JUMP, ALL_TRUE, CALM);
603 if (rta_sec_era > RTA_SEC_ERA_2 ||
604 (rta_sec_era == RTA_SEC_ERA_2 &&
605 era_2_sw_hfn_ovrd == 0)) {
606 SEQINPTR(p, 0, length, RTO);
608 SEQINPTR(p, 0, 5, RTO);
609 SEQFIFOLOAD(p, SKIP, 4, 0);
613 MATHB(p, MATH0, AND, sn_mask, MATH1, 8,
615 MATHB(p, MATH1, SHLD, MATH1, MATH1, 8, 0);
617 MOVEB(p, DESCBUF, 8, MATH2, 0, 8, WAITCOMP | IMMED);
618 MATHB(p, MATH1, OR, MATH2, MATH2, 8, 0);
619 MOVEB(p, MATH2, 0, IFIFOAB1, 0, 8, IMMED);
621 MATHB(p, MATH0, AND, sn_mask, MATH1, 8,
623 MATHB(p, MATH1, SHLD, MATH1, MATH1, 8, 0);
625 MOVE(p, DESCBUF, 8, MATH2, 0, 8, WAITCOMP | IMMED);
626 MATHB(p, MATH1, OR, MATH2, MATH2, 8, 0);
627 MOVE(p, MATH2, 0, IFIFOAB1, 0, 8, IMMED);
630 if (dir == OP_TYPE_DECAP_PROTOCOL) {
631 MATHB(p, SEQINSZ, SUB, PDCP_MAC_I_LEN, MATH1, 4,
634 if (rta_sec_era > RTA_SEC_ERA_2) {
635 MATHB(p, SEQINSZ, SUB, ZERO, MATH1, 4,
638 MATHB(p, SEQINSZ, ADD, ONE, MATH1, 4,
640 MATHB(p, MATH1, SUB, ONE, MATH1, 4,
645 if (rta_sec_era > RTA_SEC_ERA_2) {
646 MATHB(p, MATH1, SUB, ZERO, VSEQINSZ, 4, 0);
647 MATHB(p, MATH1, SUB, ZERO, VSEQOUTSZ, 4, 0);
649 MATHB(p, ZERO, ADD, MATH1, VSEQINSZ, 4, 0);
650 MATHB(p, ZERO, ADD, MATH1, VSEQOUTSZ, 4, 0);
653 * Since MOVELEN is available only starting with
654 * SEC ERA 3, use poor man's MOVELEN: create a MOVE
655 * command dynamically by writing the length from M1 by
656 * OR-ing the command in the M1 register and MOVE the
657 * result into the descriptor buffer. Care must be taken
658 * wrt. the location of the command because of SEC
659 * pipelining. The actual MOVEs are written at the end
660 * of the descriptor due to calculations needed on the
661 * offset in the descriptor for the MOVE command.
663 move_cmd_read_descbuf = MOVE(p, DESCBUF, 0, MATH1, 0, 6,
665 move_cmd_write_descbuf = MOVE(p, MATH1, 0, DESCBUF, 0,
666 8, WAITCOMP | IMMED);
668 SEQFIFOSTORE(p, MSG, 0, 0, VLF);
669 ALG_OPERATION(p, OP_ALG_ALGSEL_AES,
672 dir == OP_TYPE_ENCAP_PROTOCOL ?
673 ICV_CHECK_DISABLE : ICV_CHECK_ENABLE,
676 if (rta_sec_era > RTA_SEC_ERA_2) {
677 MOVE(p, AB2, 0, OFIFO, 0, MATH1, 0);
678 SEQFIFOLOAD(p, MSGINSNOOP, 0,
679 VLF | LAST1 | LAST2 | FLUSH1);
681 SEQFIFOLOAD(p, MSGINSNOOP, 0,
682 VLF | LAST1 | LAST2 | FLUSH1);
683 SET_LABEL(p, local_offset);
685 /* Shut off automatic Info FIFO entries */
686 LOAD(p, 0, DCTRL, LDOFF_DISABLE_AUTO_NFIFO, 0, IMMED);
689 * Placeholder for MOVE command with length from
692 MOVE(p, IFIFOAB2, 0, OFIFO, 0, 0, IMMED);
694 /* Enable automatic Info FIFO entries */
695 LOAD(p, 0, DCTRL, LDOFF_ENABLE_AUTO_NFIFO, 0, IMMED);
698 if (dir == OP_TYPE_DECAP_PROTOCOL)
699 SEQFIFOLOAD(p, ICV1, 4, LAST1 | FLUSH1);
701 SEQSTORE(p, CONTEXT1, 0, 4, 0);
705 case PDCP_AUTH_TYPE_ZUC:
706 if (rta_sec_era < RTA_SEC_ERA_5) {
707 pr_err("Invalid era for selected algorithm\n");
710 /* Insert Auth Key */
711 KEY(p, KEY2, authdata->key_enc_flags, authdata->key,
712 authdata->keylen, INLINE_KEY(authdata));
713 SEQLOAD(p, MATH0, offset, length, 0);
714 JUMP(p, 1, LOCAL_JUMP, ALL_TRUE, CALM);
715 SEQINPTR(p, 0, length, RTO);
717 MATHB(p, MATH0, AND, sn_mask, MATH1, 8,
719 MATHB(p, MATH1, SHLD, MATH1, MATH1, 8, 0);
721 MOVEB(p, DESCBUF, 8, MATH2, 0, 8, WAITCOMP | IMMED);
722 MATHB(p, MATH1, OR, MATH2, MATH2, 8, 0);
723 MOVEB(p, MATH2, 0, CONTEXT2, 0, 8, IMMED);
726 MATHB(p, MATH0, AND, sn_mask, MATH1, 8,
728 MATHB(p, MATH1, SHLD, MATH1, MATH1, 8, 0);
730 MOVE(p, DESCBUF, 8, MATH2, 0, 8, WAITCOMP | IMMED);
731 MATHB(p, MATH1, OR, MATH2, MATH2, 8, 0);
732 MOVE(p, MATH2, 0, CONTEXT2, 0, 8, IMMED);
734 if (dir == OP_TYPE_DECAP_PROTOCOL)
735 MATHB(p, SEQINSZ, SUB, PDCP_MAC_I_LEN, MATH1, 4,
738 MATHB(p, SEQINSZ, SUB, ZERO, MATH1, 4, 0);
740 MATHB(p, MATH1, SUB, ZERO, VSEQINSZ, 4, 0);
741 MATHB(p, MATH1, SUB, ZERO, VSEQOUTSZ, 4, 0);
742 SEQFIFOSTORE(p, MSG, 0, 0, VLF);
743 ALG_OPERATION(p, OP_ALG_ALGSEL_ZUCA,
746 dir == OP_TYPE_ENCAP_PROTOCOL ?
747 ICV_CHECK_DISABLE : ICV_CHECK_ENABLE,
749 SEQFIFOLOAD(p, MSGINSNOOP, 0, VLF | LAST1 | LAST2 | FLUSH1);
750 MOVE(p, AB1, 0, OFIFO, 0, MATH1, 0);
752 if (dir == OP_TYPE_DECAP_PROTOCOL)
753 SEQFIFOLOAD(p, ICV2, 4, LAST2);
755 SEQSTORE(p, CONTEXT2, 0, 4, 0);
760 pr_err("%s: Invalid integrity algorithm selected: %d\n",
761 "pdcp_insert_cplane_int_only_op", authdata->algtype);
765 if (rta_sec_era < RTA_SEC_ERA_3) {
766 PATCH_MOVE(p, move_cmd_read_descbuf, local_offset);
767 PATCH_MOVE(p, move_cmd_write_descbuf, local_offset);
774 pdcp_insert_cplane_enc_only_op(struct program *p,
775 bool swap __maybe_unused,
776 struct alginfo *cipherdata,
777 struct alginfo *authdata __maybe_unused,
779 enum pdcp_sn_size sn_size,
780 unsigned char era_2_sw_hfn_ovrd __maybe_unused)
782 uint32_t offset = 0, length = 0, sn_mask = 0;
783 /* Insert Cipher Key */
784 KEY(p, KEY1, cipherdata->key_enc_flags, cipherdata->key,
785 cipherdata->keylen, INLINE_KEY(cipherdata));
787 if ((rta_sec_era >= RTA_SEC_ERA_8 && sn_size != PDCP_SN_SIZE_18 &&
788 !(rta_sec_era == RTA_SEC_ERA_8 &&
789 authdata->algtype == 0))
790 || (rta_sec_era == RTA_SEC_ERA_10)) {
791 if (sn_size == PDCP_SN_SIZE_5)
792 PROTOCOL(p, dir, OP_PCLID_LTE_PDCP_CTRL_MIXED,
793 (uint16_t)cipherdata->algtype << 8);
795 PROTOCOL(p, dir, OP_PCLID_LTE_PDCP_USER_RN,
796 (uint16_t)cipherdata->algtype << 8);
799 /* Non-proto is supported only for 5bit cplane and 18bit uplane */
804 sn_mask = (swap == false) ? PDCP_C_PLANE_SN_MASK :
805 PDCP_C_PLANE_SN_MASK_BE;
807 case PDCP_SN_SIZE_18:
810 sn_mask = (swap == false) ? PDCP_U_PLANE_18BIT_SN_MASK :
811 PDCP_U_PLANE_18BIT_SN_MASK_BE;
813 case PDCP_SN_SIZE_12:
816 sn_mask = (swap == false) ? PDCP_12BIT_SN_MASK :
817 PDCP_12BIT_SN_MASK_BE;
820 case PDCP_SN_SIZE_15:
821 pr_err("Invalid sn_size for %s\n", __func__);
825 SEQLOAD(p, MATH0, offset, length, 0);
826 JUMP(p, 1, LOCAL_JUMP, ALL_TRUE, CALM);
827 MATHB(p, MATH0, AND, sn_mask, MATH1, 8, IFB | IMMED2);
828 SEQSTORE(p, MATH0, offset, length, 0);
829 MATHB(p, MATH1, SHLD, MATH1, MATH1, 8, 0);
830 MOVEB(p, DESCBUF, 8, MATH2, 0, 8, WAITCOMP | IMMED);
831 MATHB(p, MATH1, OR, MATH2, MATH2, 8, 0);
833 switch (cipherdata->algtype) {
834 case PDCP_CIPHER_TYPE_SNOW:
835 MOVEB(p, MATH2, 0, CONTEXT1, 0, 8, WAITCOMP | IMMED);
837 if (rta_sec_era > RTA_SEC_ERA_2) {
838 MATHB(p, SEQINSZ, SUB, ZERO, VSEQINSZ, 4, 0);
840 MATHB(p, SEQINSZ, SUB, ONE, MATH1, 4, 0);
841 MATHB(p, MATH1, ADD, ONE, VSEQINSZ, 4, 0);
844 if (dir == OP_TYPE_ENCAP_PROTOCOL)
845 MATHB(p, SEQINSZ, ADD, PDCP_MAC_I_LEN, VSEQOUTSZ, 4,
848 MATHB(p, SEQINSZ, SUB, PDCP_MAC_I_LEN, VSEQOUTSZ, 4,
850 SEQFIFOSTORE(p, MSG, 0, 0, VLF | CONT);
851 ALG_OPERATION(p, OP_ALG_ALGSEL_SNOW_F8,
853 OP_ALG_AS_INITFINAL, ICV_CHECK_DISABLE,
854 dir == OP_TYPE_ENCAP_PROTOCOL ?
858 case PDCP_CIPHER_TYPE_AES:
859 MOVEB(p, MATH2, 0, CONTEXT1, 0x10, 0x10, WAITCOMP | IMMED);
861 if (rta_sec_era > RTA_SEC_ERA_2) {
862 MATHB(p, SEQINSZ, SUB, ZERO, VSEQINSZ, 4, 0);
864 MATHB(p, SEQINSZ, SUB, ONE, MATH1, 4, 0);
865 MATHB(p, MATH1, ADD, ONE, VSEQINSZ, 4, 0);
868 if (dir == OP_TYPE_ENCAP_PROTOCOL)
869 MATHB(p, SEQINSZ, ADD, PDCP_MAC_I_LEN, VSEQOUTSZ, 4,
872 MATHB(p, SEQINSZ, SUB, PDCP_MAC_I_LEN, VSEQOUTSZ, 4,
875 SEQFIFOSTORE(p, MSG, 0, 0, VLF | CONT);
876 ALG_OPERATION(p, OP_ALG_ALGSEL_AES,
880 dir == OP_TYPE_ENCAP_PROTOCOL ?
884 case PDCP_CIPHER_TYPE_ZUC:
885 if (rta_sec_era < RTA_SEC_ERA_5) {
886 pr_err("Invalid era for selected algorithm\n");
890 MOVEB(p, MATH2, 0, CONTEXT1, 0, 0x08, IMMED);
891 MOVEB(p, MATH2, 0, CONTEXT1, 0x08, 0x08, WAITCOMP | IMMED);
892 MATHB(p, SEQINSZ, SUB, ZERO, VSEQINSZ, 4, 0);
893 if (dir == OP_TYPE_ENCAP_PROTOCOL)
894 MATHB(p, SEQINSZ, ADD, PDCP_MAC_I_LEN, VSEQOUTSZ, 4,
897 MATHB(p, SEQINSZ, SUB, PDCP_MAC_I_LEN, VSEQOUTSZ, 4,
900 SEQFIFOSTORE(p, MSG, 0, 0, VLF | CONT);
901 ALG_OPERATION(p, OP_ALG_ALGSEL_ZUCE,
905 dir == OP_TYPE_ENCAP_PROTOCOL ?
910 pr_err("%s: Invalid encrypt algorithm selected: %d\n",
911 "pdcp_insert_cplane_enc_only_op", cipherdata->algtype);
915 if (dir == OP_TYPE_ENCAP_PROTOCOL) {
916 SEQFIFOLOAD(p, MSG1, 0, VLF);
917 FIFOLOAD(p, MSG1, PDCP_NULL_INT_MAC_I_VAL, 4,
918 LAST1 | FLUSH1 | IMMED);
920 SEQFIFOLOAD(p, MSG1, 0, VLF | LAST1 | FLUSH1);
921 MOVE(p, OFIFO, 0, MATH1, 4, PDCP_MAC_I_LEN, WAITCOMP | IMMED);
922 MATHB(p, MATH1, XOR, PDCP_NULL_INT_MAC_I_VAL, NONE, 4, IMMED2);
923 JUMP(p, PDCP_NULL_INT_ICV_CHECK_FAILED_STATUS,
924 HALT_STATUS, ALL_FALSE, MATH_Z);
931 pdcp_insert_uplane_snow_snow_op(struct program *p,
932 bool swap __maybe_unused,
933 struct alginfo *cipherdata,
934 struct alginfo *authdata,
936 enum pdcp_sn_size sn_size,
937 unsigned char era_2_sw_hfn_ovrd __maybe_unused)
939 uint32_t offset = 0, length = 0, sn_mask = 0;
941 KEY(p, KEY1, cipherdata->key_enc_flags, cipherdata->key,
942 cipherdata->keylen, INLINE_KEY(cipherdata));
943 KEY(p, KEY2, authdata->key_enc_flags, authdata->key, authdata->keylen,
944 INLINE_KEY(authdata));
946 if (rta_sec_era >= RTA_SEC_ERA_8 && sn_size != PDCP_SN_SIZE_18) {
949 if (sn_size == PDCP_SN_SIZE_5)
950 pclid = OP_PCLID_LTE_PDCP_CTRL_MIXED;
952 pclid = OP_PCLID_LTE_PDCP_USER_RN;
954 PROTOCOL(p, dir, pclid,
955 ((uint16_t)cipherdata->algtype << 8) |
956 (uint16_t)authdata->algtype);
960 /* Non-proto is supported only for 5bit cplane and 18bit uplane */
965 sn_mask = (swap == false) ? PDCP_C_PLANE_SN_MASK :
966 PDCP_C_PLANE_SN_MASK_BE;
968 case PDCP_SN_SIZE_18:
971 sn_mask = (swap == false) ? PDCP_U_PLANE_18BIT_SN_MASK :
972 PDCP_U_PLANE_18BIT_SN_MASK_BE;
975 case PDCP_SN_SIZE_12:
976 case PDCP_SN_SIZE_15:
977 pr_err("Invalid sn_size for %s\n", __func__);
981 if (dir == OP_TYPE_ENCAP_PROTOCOL)
982 MATHB(p, SEQINSZ, SUB, length, VSEQINSZ, 4, IMMED2);
984 SEQLOAD(p, MATH0, offset, length, 0);
985 JUMP(p, 1, LOCAL_JUMP, ALL_TRUE, CALM);
986 MOVEB(p, MATH0, offset, IFIFOAB2, 0, length, IMMED);
987 MATHB(p, MATH0, AND, sn_mask, MATH1, 8, IFB | IMMED2);
989 SEQSTORE(p, MATH0, offset, length, 0);
990 MATHB(p, MATH1, SHLD, MATH1, MATH1, 8, 0);
991 MOVEB(p, DESCBUF, 8, MATH2, 0, 8, WAITCOMP | IMMED);
992 MATHB(p, MATH1, OR, MATH2, MATH1, 8, 0);
993 MOVEB(p, MATH1, 0, CONTEXT1, 0, 8, IMMED);
994 MOVEB(p, MATH1, 0, CONTEXT2, 0, 4, WAITCOMP | IMMED);
996 MATHB(p, MATH1, AND, upper_32_bits(PDCP_BEARER_MASK),
998 MATHB(p, MATH1, AND, lower_32_bits(PDCP_DIR_MASK),
1001 MATHB(p, MATH1, AND, lower_32_bits(PDCP_BEARER_MASK_BE),
1003 MATHB(p, MATH1, AND, upper_32_bits(PDCP_DIR_MASK_BE),
1006 MATHB(p, MATH3, SHLD, MATH3, MATH3, 8, 0);
1008 MOVEB(p, MATH2, 4, OFIFO, 0, 12, IMMED);
1009 MOVE(p, OFIFO, 0, CONTEXT2, 4, 12, IMMED);
1010 if (dir == OP_TYPE_ENCAP_PROTOCOL) {
1011 MATHB(p, SEQINSZ, ADD, PDCP_MAC_I_LEN, VSEQOUTSZ, 4, IMMED2);
1013 MATHI(p, SEQINSZ, SUB, PDCP_MAC_I_LEN, VSEQOUTSZ, 4, IMMED2);
1014 MATHI(p, SEQINSZ, SUB, PDCP_MAC_I_LEN, VSEQINSZ, 4, IMMED2);
1017 if (dir == OP_TYPE_ENCAP_PROTOCOL)
1018 SEQFIFOSTORE(p, MSG, 0, 0, VLF);
1020 SEQFIFOSTORE(p, MSG, 0, 0, VLF | CONT);
1022 ALG_OPERATION(p, OP_ALG_ALGSEL_SNOW_F9,
1024 OP_ALG_AS_INITFINAL,
1025 dir == OP_TYPE_ENCAP_PROTOCOL ?
1026 ICV_CHECK_DISABLE : ICV_CHECK_ENABLE,
1028 ALG_OPERATION(p, OP_ALG_ALGSEL_SNOW_F8,
1030 OP_ALG_AS_INITFINAL,
1032 dir == OP_TYPE_ENCAP_PROTOCOL ? DIR_ENC : DIR_DEC);
1034 if (dir == OP_TYPE_ENCAP_PROTOCOL) {
1035 SEQFIFOLOAD(p, MSGINSNOOP, 0, VLF | LAST2);
1036 MOVE(p, CONTEXT2, 0, IFIFOAB1, 0, 4, LAST1 | FLUSH1 | IMMED);
1038 SEQFIFOLOAD(p, MSGOUTSNOOP, 0, VLF | LAST2);
1039 SEQFIFOLOAD(p, MSG1, 4, LAST1 | FLUSH1);
1040 JUMP(p, 1, LOCAL_JUMP, ALL_TRUE, CLASS1 | NOP | NIFP);
1042 if (rta_sec_era >= RTA_SEC_ERA_6)
1043 LOAD(p, 0, DCTRL, 0, LDLEN_RST_CHA_OFIFO_PTR, IMMED);
1045 MOVE(p, OFIFO, 0, MATH0, 0, 4, WAITCOMP | IMMED);
1047 NFIFOADD(p, IFIFO, ICV2, 4, LAST2);
1049 if (rta_sec_era <= RTA_SEC_ERA_2) {
1050 /* Shut off automatic Info FIFO entries */
1051 LOAD(p, 0, DCTRL, LDOFF_DISABLE_AUTO_NFIFO, 0, IMMED);
1052 MOVE(p, MATH0, 0, IFIFOAB2, 0, 4, WAITCOMP | IMMED);
1054 MOVE(p, MATH0, 0, IFIFO, 0, 4, WAITCOMP | IMMED);
1062 pdcp_insert_uplane_zuc_zuc_op(struct program *p,
1063 bool swap __maybe_unused,
1064 struct alginfo *cipherdata,
1065 struct alginfo *authdata,
1067 enum pdcp_sn_size sn_size,
1068 unsigned char era_2_sw_hfn_ovrd __maybe_unused)
1070 uint32_t offset = 0, length = 0, sn_mask = 0;
1073 REFERENCE(pkeyjump);
1075 if (rta_sec_era < RTA_SEC_ERA_5) {
1076 pr_err("Invalid era for selected algorithm\n");
1080 pkeyjump = JUMP(p, keyjump, LOCAL_JUMP, ALL_TRUE, SHRD | SELF | BOTH);
1081 KEY(p, KEY1, cipherdata->key_enc_flags, cipherdata->key,
1082 cipherdata->keylen, INLINE_KEY(cipherdata));
1083 KEY(p, KEY2, authdata->key_enc_flags, authdata->key, authdata->keylen,
1084 INLINE_KEY(authdata));
1086 SET_LABEL(p, keyjump);
1087 PATCH_JUMP(p, pkeyjump, keyjump);
1089 if (rta_sec_era >= RTA_SEC_ERA_8 && sn_size != PDCP_SN_SIZE_18) {
1092 if (sn_size == PDCP_SN_SIZE_5)
1093 pclid = OP_PCLID_LTE_PDCP_CTRL_MIXED;
1095 pclid = OP_PCLID_LTE_PDCP_USER_RN;
1097 PROTOCOL(p, dir, pclid,
1098 ((uint16_t)cipherdata->algtype << 8) |
1099 (uint16_t)authdata->algtype);
1103 /* Non-proto is supported only for 5bit cplane and 18bit uplane */
1105 case PDCP_SN_SIZE_5:
1108 sn_mask = (swap == false) ? PDCP_C_PLANE_SN_MASK :
1109 PDCP_C_PLANE_SN_MASK_BE;
1111 case PDCP_SN_SIZE_18:
1114 sn_mask = (swap == false) ? PDCP_U_PLANE_18BIT_SN_MASK :
1115 PDCP_U_PLANE_18BIT_SN_MASK_BE;
1117 case PDCP_SN_SIZE_7:
1118 case PDCP_SN_SIZE_12:
1119 case PDCP_SN_SIZE_15:
1120 pr_err("Invalid sn_size for %s\n", __func__);
1124 SEQLOAD(p, MATH0, offset, length, 0);
1125 JUMP(p, 1, LOCAL_JUMP, ALL_TRUE, CALM);
1126 MOVEB(p, MATH0, offset, IFIFOAB2, 0, length, IMMED);
1127 MATHB(p, MATH0, AND, sn_mask, MATH1, 8, IFB | IMMED2);
1128 MATHB(p, MATH1, SHLD, MATH1, MATH1, 8, 0);
1130 MOVEB(p, DESCBUF, 8, MATH2, 0, 8, WAITCOMP | IMMED);
1131 MATHB(p, MATH1, OR, MATH2, MATH2, 8, 0);
1132 MOVEB(p, MATH2, 0, CONTEXT1, 0, 8, IMMED);
1134 MOVEB(p, MATH2, 0, CONTEXT2, 0, 8, WAITCOMP | IMMED);
1136 if (dir == OP_TYPE_ENCAP_PROTOCOL)
1137 MATHB(p, SEQINSZ, ADD, PDCP_MAC_I_LEN, VSEQOUTSZ, 4, IMMED2);
1139 MATHB(p, SEQINSZ, SUB, PDCP_MAC_I_LEN, VSEQOUTSZ, 4, IMMED2);
1141 MATHB(p, SEQINSZ, SUB, ZERO, VSEQINSZ, 4, 0);
1142 SEQSTORE(p, MATH0, offset, length, 0);
1144 if (dir == OP_TYPE_ENCAP_PROTOCOL) {
1145 SEQFIFOSTORE(p, MSG, 0, 0, VLF);
1146 SEQFIFOLOAD(p, MSGINSNOOP, 0, VLF | LAST2);
1148 SEQFIFOSTORE(p, MSG, 0, 0, VLF | CONT);
1149 SEQFIFOLOAD(p, MSGOUTSNOOP, 0, VLF | LAST1 | FLUSH1);
1152 ALG_OPERATION(p, OP_ALG_ALGSEL_ZUCA,
1154 OP_ALG_AS_INITFINAL,
1155 dir == OP_TYPE_ENCAP_PROTOCOL ?
1156 ICV_CHECK_DISABLE : ICV_CHECK_ENABLE,
1159 ALG_OPERATION(p, OP_ALG_ALGSEL_ZUCE,
1161 OP_ALG_AS_INITFINAL,
1163 dir == OP_TYPE_ENCAP_PROTOCOL ? DIR_ENC : DIR_DEC);
1165 if (dir == OP_TYPE_ENCAP_PROTOCOL) {
1166 MOVE(p, CONTEXT2, 0, IFIFOAB1, 0, 4, LAST1 | FLUSH1 | IMMED);
1169 MOVEB(p, OFIFO, 0, MATH0, 0, 4, IMMED);
1171 LOAD(p, NFIFOENTRY_STYPE_ALTSOURCE |
1172 NFIFOENTRY_DEST_CLASS2 |
1173 NFIFOENTRY_DTYPE_ICV |
1174 NFIFOENTRY_LC2 | 4, NFIFO_SZL, 0, 4, IMMED);
1175 MOVEB(p, MATH0, 0, ALTSOURCE, 0, 4, WAITCOMP | IMMED);
1178 /* Reset ZUCA mode and done interrupt */
1179 LOAD(p, CLRW_CLR_C2MODE, CLRW, 0, 4, IMMED);
1180 LOAD(p, CIRQ_ZADI, ICTRL, 0, 4, IMMED);
1186 pdcp_insert_uplane_aes_aes_op(struct program *p,
1187 bool swap __maybe_unused,
1188 struct alginfo *cipherdata,
1189 struct alginfo *authdata,
1191 enum pdcp_sn_size sn_size,
1192 unsigned char era_2_sw_hfn_ovrd __maybe_unused)
1194 uint32_t offset = 0, length = 0, sn_mask = 0;
1196 if ((rta_sec_era >= RTA_SEC_ERA_8 && sn_size != PDCP_SN_SIZE_18)) {
1197 /* Insert Auth Key */
1198 KEY(p, KEY2, authdata->key_enc_flags, authdata->key,
1199 authdata->keylen, INLINE_KEY(authdata));
1201 /* Insert Cipher Key */
1202 KEY(p, KEY1, cipherdata->key_enc_flags, cipherdata->key,
1203 cipherdata->keylen, INLINE_KEY(cipherdata));
1205 PROTOCOL(p, dir, OP_PCLID_LTE_PDCP_USER_RN,
1206 ((uint16_t)cipherdata->algtype << 8) |
1207 (uint16_t)authdata->algtype);
1211 /* Non-proto is supported only for 5bit cplane and 18bit uplane */
1213 case PDCP_SN_SIZE_18:
1216 sn_mask = (swap == false) ? PDCP_U_PLANE_18BIT_SN_MASK :
1217 PDCP_U_PLANE_18BIT_SN_MASK_BE;
1221 pr_err("Invalid sn_size for %s\n", __func__);
1225 SEQLOAD(p, MATH0, offset, length, 0);
1226 JUMP(p, 1, LOCAL_JUMP, ALL_TRUE, CALM);
1227 MATHB(p, MATH0, AND, sn_mask, MATH1, 8, IFB | IMMED2);
1229 MATHB(p, MATH1, SHLD, MATH1, MATH1, 8, 0);
1230 MOVEB(p, DESCBUF, 8, MATH2, 0, 0x08, WAITCOMP | IMMED);
1231 MATHB(p, MATH1, OR, MATH2, MATH2, 8, 0);
1232 SEQSTORE(p, MATH0, offset, length, 0);
1234 if (dir == OP_TYPE_ENCAP_PROTOCOL) {
1235 KEY(p, KEY1, authdata->key_enc_flags, authdata->key,
1236 authdata->keylen, INLINE_KEY(authdata));
1237 MOVEB(p, MATH2, 0, IFIFOAB1, 0, 0x08, IMMED);
1238 MOVEB(p, MATH0, offset, IFIFOAB1, 0, length, IMMED);
1240 MATHB(p, SEQINSZ, SUB, ZERO, VSEQINSZ, 4, 0);
1241 MATHB(p, VSEQINSZ, ADD, PDCP_MAC_I_LEN, VSEQOUTSZ, 4, IMMED2);
1243 ALG_OPERATION(p, OP_ALG_ALGSEL_AES,
1245 OP_ALG_AS_INITFINAL,
1248 SEQFIFOLOAD(p, MSG1, 0, VLF | LAST1 | FLUSH1);
1249 MOVEB(p, CONTEXT1, 0, MATH3, 0, 4, WAITCOMP | IMMED);
1251 LOAD(p, CLRW_RESET_CLS1_CHA |
1259 KEY(p, KEY1, cipherdata->key_enc_flags, cipherdata->key,
1260 cipherdata->keylen, INLINE_KEY(cipherdata));
1262 MOVEB(p, MATH2, 0, CONTEXT1, 16, 8, IMMED);
1263 SEQINPTR(p, 0, PDCP_NULL_MAX_FRAME_LEN, RTO);
1265 ALG_OPERATION(p, OP_ALG_ALGSEL_AES,
1267 OP_ALG_AS_INITFINAL,
1271 SEQFIFOSTORE(p, MSG, 0, 0, VLF);
1273 SEQFIFOLOAD(p, SKIP, length, 0);
1275 SEQFIFOLOAD(p, MSG1, 0, VLF);
1276 MOVEB(p, MATH3, 0, IFIFOAB1, 0, 4, LAST1 | FLUSH1 | IMMED);
1278 MOVEB(p, MATH2, 0, CONTEXT1, 16, 8, IMMED);
1279 MOVEB(p, MATH2, 0, CONTEXT2, 0, 8, IMMED);
1281 MATHB(p, SEQINSZ, SUB, ZERO, VSEQINSZ, 4, 0);
1282 MATHB(p, SEQINSZ, SUB, PDCP_MAC_I_LEN, VSEQOUTSZ, 4, IMMED2);
1284 KEY(p, KEY1, cipherdata->key_enc_flags, cipherdata->key,
1285 cipherdata->keylen, INLINE_KEY(cipherdata));
1287 ALG_OPERATION(p, OP_ALG_ALGSEL_AES,
1289 OP_ALG_AS_INITFINAL,
1293 SEQFIFOSTORE(p, MSG, 0, 0, VLF | CONT);
1294 SEQFIFOLOAD(p, MSG1, 0, VLF | LAST1 | FLUSH1);
1296 MOVEB(p, OFIFO, 0, MATH3, 0, 4, IMMED);
1298 LOAD(p, CLRW_RESET_CLS1_CHA |
1306 KEY(p, KEY1, authdata->key_enc_flags, authdata->key,
1307 authdata->keylen, INLINE_KEY(authdata));
1309 SEQINPTR(p, 0, 0, SOP);
1311 ALG_OPERATION(p, OP_ALG_ALGSEL_AES,
1313 OP_ALG_AS_INITFINAL,
1317 MATHB(p, SEQINSZ, SUB, ZERO, VSEQINSZ, 4, 0);
1319 MOVE(p, CONTEXT2, 0, IFIFOAB1, 0, 8, IMMED);
1321 SEQFIFOLOAD(p, MSG1, 0, VLF | LAST1 | FLUSH1);
1323 LOAD(p, NFIFOENTRY_STYPE_ALTSOURCE |
1324 NFIFOENTRY_DEST_CLASS1 |
1325 NFIFOENTRY_DTYPE_ICV |
1327 NFIFOENTRY_FC1 | 4, NFIFO_SZL, 0, 4, IMMED);
1328 MOVEB(p, MATH3, 0, ALTSOURCE, 0, 4, IMMED);
1335 pdcp_insert_cplane_acc_op(struct program *p,
1336 bool swap __maybe_unused,
1337 struct alginfo *cipherdata,
1338 struct alginfo *authdata,
1340 enum pdcp_sn_size sn_size,
1341 unsigned char era_2_hfn_ovrd __maybe_unused)
1343 /* Insert Auth Key */
1344 KEY(p, KEY2, authdata->key_enc_flags, authdata->key, authdata->keylen,
1345 INLINE_KEY(authdata));
1347 /* Insert Cipher Key */
1348 KEY(p, KEY1, cipherdata->key_enc_flags, cipherdata->key,
1349 cipherdata->keylen, INLINE_KEY(cipherdata));
1351 if (sn_size == PDCP_SN_SIZE_5)
1352 PROTOCOL(p, dir, OP_PCLID_LTE_PDCP_CTRL,
1353 (uint16_t)cipherdata->algtype);
1355 PROTOCOL(p, dir, OP_PCLID_LTE_PDCP_USER_RN,
1356 ((uint16_t)cipherdata->algtype << 8) |
1357 (uint16_t)authdata->algtype);
1363 pdcp_insert_cplane_snow_aes_op(struct program *p,
1364 bool swap __maybe_unused,
1365 struct alginfo *cipherdata,
1366 struct alginfo *authdata,
1368 enum pdcp_sn_size sn_size,
1369 unsigned char era_2_sw_hfn_ovrd)
1371 uint32_t offset = 0, length = 0, sn_mask = 0;
1373 LABEL(back_to_sd_offset);
1375 LABEL(local_offset);
1376 LABEL(jump_to_beginning);
1377 LABEL(fifo_load_mac_i_offset);
1378 REFERENCE(seqin_ptr_read);
1379 REFERENCE(seqin_ptr_write);
1380 REFERENCE(seq_out_read);
1381 REFERENCE(jump_back_to_sd_cmd);
1382 REFERENCE(move_mac_i_to_desc_buf);
1384 if ((rta_sec_era >= RTA_SEC_ERA_8 && sn_size != PDCP_SN_SIZE_18) ||
1385 (rta_sec_era == RTA_SEC_ERA_10)) {
1386 KEY(p, KEY1, cipherdata->key_enc_flags, cipherdata->key,
1387 cipherdata->keylen, INLINE_KEY(cipherdata));
1388 KEY(p, KEY2, authdata->key_enc_flags, authdata->key,
1389 authdata->keylen, INLINE_KEY(authdata));
1391 if (sn_size == PDCP_SN_SIZE_5)
1392 PROTOCOL(p, dir, OP_PCLID_LTE_PDCP_CTRL_MIXED,
1393 ((uint16_t)cipherdata->algtype << 8) |
1394 (uint16_t)authdata->algtype);
1396 PROTOCOL(p, dir, OP_PCLID_LTE_PDCP_USER_RN,
1397 ((uint16_t)cipherdata->algtype << 8) |
1398 (uint16_t)authdata->algtype);
1402 /* Non-proto is supported only for 5bit cplane and 18bit uplane */
1404 case PDCP_SN_SIZE_5:
1407 sn_mask = (swap == false) ? PDCP_C_PLANE_SN_MASK :
1408 PDCP_C_PLANE_SN_MASK_BE;
1410 case PDCP_SN_SIZE_18:
1413 sn_mask = (swap == false) ? PDCP_U_PLANE_18BIT_SN_MASK :
1414 PDCP_U_PLANE_18BIT_SN_MASK_BE;
1416 case PDCP_SN_SIZE_7:
1417 case PDCP_SN_SIZE_12:
1418 case PDCP_SN_SIZE_15:
1419 pr_err("Invalid sn_size for %s\n", __func__);
1424 SEQLOAD(p, MATH0, offset, length, 0);
1425 JUMP(p, 1, LOCAL_JUMP, ALL_TRUE, CALM);
1426 MATHB(p, MATH0, AND, sn_mask, MATH1, 8, IFB | IMMED2);
1427 MATHB(p, MATH1, SHLD, MATH1, MATH1, 8, 0);
1428 MOVEB(p, DESCBUF, 4, MATH2, 0, 0x08, WAITCOMP | IMMED);
1429 MATHB(p, MATH1, OR, MATH2, MATH2, 8, 0);
1430 SEQSTORE(p, MATH0, offset, length, 0);
1431 if (dir == OP_TYPE_ENCAP_PROTOCOL) {
1432 if (rta_sec_era > RTA_SEC_ERA_2 ||
1433 (rta_sec_era == RTA_SEC_ERA_2 &&
1434 era_2_sw_hfn_ovrd == 0)) {
1435 SEQINPTR(p, 0, length, RTO);
1437 SEQINPTR(p, 0, 5, RTO);
1438 SEQFIFOLOAD(p, SKIP, 4, 0);
1440 KEY(p, KEY1, authdata->key_enc_flags, authdata->key,
1441 authdata->keylen, INLINE_KEY(authdata));
1442 MOVEB(p, MATH2, 0, IFIFOAB1, 0, 0x08, IMMED);
1444 if (rta_sec_era > RTA_SEC_ERA_2) {
1445 MATHB(p, SEQINSZ, SUB, ZERO, VSEQINSZ, 4, 0);
1446 MATHB(p, SEQINSZ, SUB, ZERO, MATH1, 4, 0);
1447 MATHB(p, VSEQINSZ, ADD, PDCP_MAC_I_LEN - 1, VSEQOUTSZ,
1450 MATHB(p, SEQINSZ, SUB, MATH3, VSEQINSZ, 4, 0);
1451 MATHB(p, VSEQINSZ, ADD, PDCP_MAC_I_LEN - 1, VSEQOUTSZ,
1454 * Note: Although the calculations below might seem a
1455 * little off, the logic is the following:
1457 * - SEQ IN PTR RTO below needs the full length of the
1458 * frame; in case of P4080_REV_2_HFN_OV_WORKAROUND,
1459 * this means the length of the frame to be processed
1460 * + 4 bytes (the HFN override flag and value).
1461 * The length of the frame to be processed minus 1
1462 * byte is in the VSIL register (because
1463 * VSIL = SIL + 3, due to 1 byte, the header being
1464 * already written by the SEQ STORE above). So for
1465 * calculating the length to use in RTO, I add one
1466 * to the VSIL value in order to obtain the total
1467 * frame length. This helps in case of P4080 which
1468 * can have the value 0 as an operand in a MATH
1469 * command only as SRC1 When the HFN override
1470 * workaround is not enabled, the length of the
1471 * frame is given by the SIL register; the
1472 * calculation is similar to the one in the SEC 4.2
1473 * and SEC 5.3 cases.
1475 if (era_2_sw_hfn_ovrd)
1476 MATHB(p, VSEQOUTSZ, ADD, ONE, MATH1, 4,
1479 MATHB(p, SEQINSZ, ADD, MATH3, MATH1, 4,
1483 * Placeholder for filling the length in
1484 * SEQIN PTR RTO below
1486 seqin_ptr_read = MOVE(p, DESCBUF, 0, MATH1, 0, 6, IMMED);
1487 seqin_ptr_write = MOVE(p, MATH1, 0, DESCBUF, 0, 8,
1489 ALG_OPERATION(p, OP_ALG_ALGSEL_AES,
1491 OP_ALG_AS_INITFINAL,
1494 SEQFIFOLOAD(p, MSG1, 0, VLF | LAST1 | FLUSH1);
1495 MOVEB(p, CONTEXT1, 0, MATH3, 0, 4, WAITCOMP | IMMED);
1496 if (rta_sec_era <= RTA_SEC_ERA_3)
1497 LOAD(p, CLRW_CLR_C1KEY |
1504 LOAD(p, CLRW_RESET_CLS1_CHA |
1512 if (rta_sec_era <= RTA_SEC_ERA_3)
1513 LOAD(p, CCTRL_RESET_CHA_ALL, CCTRL, 0, 4, IMMED);
1515 KEY(p, KEY1, cipherdata->key_enc_flags, cipherdata->key,
1516 cipherdata->keylen, INLINE_KEY(cipherdata));
1517 SET_LABEL(p, local_offset);
1518 MOVEB(p, MATH2, 0, CONTEXT1, 0, 8, IMMED);
1519 SEQINPTR(p, 0, 0, RTO);
1521 if (rta_sec_era == RTA_SEC_ERA_2 && era_2_sw_hfn_ovrd) {
1522 SEQFIFOLOAD(p, SKIP, 5, 0);
1523 MATHB(p, SEQINSZ, ADD, ONE, SEQINSZ, 4, 0);
1526 MATHB(p, SEQINSZ, SUB, length, VSEQINSZ, 4, IMMED2);
1527 ALG_OPERATION(p, OP_ALG_ALGSEL_SNOW_F8,
1529 OP_ALG_AS_INITFINAL,
1532 SEQFIFOSTORE(p, MSG, 0, 0, VLF);
1534 if (rta_sec_era > RTA_SEC_ERA_2 ||
1535 (rta_sec_era == RTA_SEC_ERA_2 &&
1536 era_2_sw_hfn_ovrd == 0))
1537 SEQFIFOLOAD(p, SKIP, length, 0);
1539 SEQFIFOLOAD(p, MSG1, 0, VLF);
1540 MOVEB(p, MATH3, 0, IFIFOAB1, 0, 4, LAST1 | FLUSH1 | IMMED);
1541 PATCH_MOVE(p, seqin_ptr_read, local_offset);
1542 PATCH_MOVE(p, seqin_ptr_write, local_offset);
1544 MOVEB(p, MATH2, 0, CONTEXT1, 0, 8, IMMED);
1546 if (rta_sec_era >= RTA_SEC_ERA_5)
1547 MOVE(p, CONTEXT1, 0, CONTEXT2, 0, 8, IMMED);
1549 if (rta_sec_era > RTA_SEC_ERA_2)
1550 MATHB(p, SEQINSZ, SUB, ZERO, VSEQINSZ, 4, 0);
1552 MATHB(p, SEQINSZ, SUB, MATH3, VSEQINSZ, 4, 0);
1554 MATHI(p, SEQINSZ, SUB, PDCP_MAC_I_LEN, VSEQOUTSZ, 4, IMMED2);
1556 * TODO: To be changed when proper support is added in RTA (can't load a
1557 * command that is also written by RTA (or patch it for that matter).
1558 * Change when proper RTA support is added.
1561 WORD(p, 0x168B0004);
1563 WORD(p, 0x16880404);
1565 jump_back_to_sd_cmd = JUMP(p, 0, LOCAL_JUMP, ALL_TRUE, 0);
1567 * Placeholder for command reading the SEQ OUT command in
1568 * JD. Done for rereading the decrypted data and performing
1569 * the integrity check
1572 * TODO: RTA currently doesn't support patching of length of a MOVE command
1573 * Thus, it is inserted as a raw word, as per PS setting.
1576 seq_out_read = MOVE(p, DESCBUF, 0, MATH1, 0, 20,
1579 seq_out_read = MOVE(p, DESCBUF, 0, MATH1, 0, 16,
1582 MATHB(p, MATH1, XOR, CMD_SEQ_IN_PTR ^ CMD_SEQ_OUT_PTR, MATH1, 4,
1584 /* Placeholder for overwriting the SEQ IN with SEQ OUT */
1586 * TODO: RTA currently doesn't support patching of length of a MOVE command
1587 * Thus, it is inserted as a raw word, as per PS setting.
1590 MOVE(p, MATH1, 0, DESCBUF, 0, 24, IMMED);
1592 MOVE(p, MATH1, 0, DESCBUF, 0, 20, IMMED);
1594 KEY(p, KEY1, cipherdata->key_enc_flags, cipherdata->key,
1595 cipherdata->keylen, INLINE_KEY(cipherdata));
1597 if (rta_sec_era >= RTA_SEC_ERA_4)
1598 MOVE(p, CONTEXT1, 0, CONTEXT2, 0, 8, IMMED);
1600 MOVE(p, CONTEXT1, 0, MATH3, 0, 8, IMMED);
1602 ALG_OPERATION(p, OP_ALG_ALGSEL_SNOW_F8,
1604 OP_ALG_AS_INITFINAL,
1607 SEQFIFOSTORE(p, MSG, 0, 0, VLF | CONT);
1608 SEQFIFOLOAD(p, MSG1, 0, VLF | LAST1 | FLUSH1);
1610 if (rta_sec_era <= RTA_SEC_ERA_3)
1611 move_mac_i_to_desc_buf = MOVE(p, OFIFO, 0, DESCBUF, 0,
1612 4, WAITCOMP | IMMED);
1614 MOVE(p, OFIFO, 0, MATH3, 0, 4, IMMED);
1616 if (rta_sec_era <= RTA_SEC_ERA_3)
1617 LOAD(p, CCTRL_RESET_CHA_ALL, CCTRL, 0, 4, IMMED);
1619 LOAD(p, CLRW_RESET_CLS1_CHA |
1627 KEY(p, KEY1, authdata->key_enc_flags, authdata->key,
1628 authdata->keylen, INLINE_KEY(authdata));
1630 * Placeholder for jump in SD for executing the new SEQ IN PTR
1631 * command (which is actually the old SEQ OUT PTR command
1632 * copied over from JD.
1634 SET_LABEL(p, jump_to_beginning);
1635 JUMP(p, 1 - jump_to_beginning, LOCAL_JUMP, ALL_TRUE, 0);
1636 SET_LABEL(p, back_to_sd_offset);
1637 ALG_OPERATION(p, OP_ALG_ALGSEL_AES,
1639 OP_ALG_AS_INITFINAL,
1643 /* Read the # of bytes written in the output buffer + 1 (HDR) */
1644 MATHI(p, VSEQOUTSZ, ADD, length, VSEQINSZ, 4, IMMED2);
1646 if (rta_sec_era <= RTA_SEC_ERA_3)
1647 MOVE(p, MATH3, 0, IFIFOAB1, 0, 8, IMMED);
1649 MOVE(p, CONTEXT2, 0, IFIFOAB1, 0, 8, IMMED);
1651 if (rta_sec_era == RTA_SEC_ERA_2 && era_2_sw_hfn_ovrd)
1652 SEQFIFOLOAD(p, SKIP, 4, 0);
1654 SEQFIFOLOAD(p, MSG1, 0, VLF | LAST1 | FLUSH1);
1656 if (rta_sec_era >= RTA_SEC_ERA_4) {
1657 LOAD(p, NFIFOENTRY_STYPE_ALTSOURCE |
1658 NFIFOENTRY_DEST_CLASS1 |
1659 NFIFOENTRY_DTYPE_ICV |
1661 NFIFOENTRY_FC1 | 4, NFIFO_SZL, 0, 4, IMMED);
1662 MOVE(p, MATH3, 0, ALTSOURCE, 0, 4, IMMED);
1664 SET_LABEL(p, fifo_load_mac_i_offset);
1665 FIFOLOAD(p, ICV1, fifo_load_mac_i_offset, 4,
1666 LAST1 | FLUSH1 | IMMED);
1669 SET_LABEL(p, end_desc);
1672 PATCH_MOVE(p, seq_out_read, end_desc + 1);
1673 PATCH_JUMP(p, jump_back_to_sd_cmd,
1674 back_to_sd_offset + jump_back_to_sd_cmd - 5);
1676 if (rta_sec_era <= RTA_SEC_ERA_3)
1677 PATCH_MOVE(p, move_mac_i_to_desc_buf,
1678 fifo_load_mac_i_offset + 1);
1680 PATCH_MOVE(p, seq_out_read, end_desc + 2);
1681 PATCH_JUMP(p, jump_back_to_sd_cmd,
1682 back_to_sd_offset + jump_back_to_sd_cmd - 5);
1684 if (rta_sec_era <= RTA_SEC_ERA_3)
1685 PATCH_MOVE(p, move_mac_i_to_desc_buf,
1686 fifo_load_mac_i_offset + 1);
1694 pdcp_insert_cplane_aes_snow_op(struct program *p,
1695 bool swap __maybe_unused,
1696 struct alginfo *cipherdata,
1697 struct alginfo *authdata,
1699 enum pdcp_sn_size sn_size,
1700 unsigned char era_2_sw_hfn_ovrd __maybe_unused)
1702 uint32_t offset = 0, length = 0, sn_mask = 0;
1704 KEY(p, KEY1, cipherdata->key_enc_flags, cipherdata->key,
1705 cipherdata->keylen, INLINE_KEY(cipherdata));
1706 KEY(p, KEY2, authdata->key_enc_flags, authdata->key, authdata->keylen,
1707 INLINE_KEY(authdata));
1709 if ((rta_sec_era >= RTA_SEC_ERA_8 && sn_size != PDCP_SN_SIZE_18) ||
1710 (rta_sec_era == RTA_SEC_ERA_10)) {
1713 if (sn_size == PDCP_SN_SIZE_5)
1714 pclid = OP_PCLID_LTE_PDCP_CTRL_MIXED;
1716 pclid = OP_PCLID_LTE_PDCP_USER_RN;
1718 PROTOCOL(p, dir, pclid,
1719 ((uint16_t)cipherdata->algtype << 8) |
1720 (uint16_t)authdata->algtype);
1724 /* Non-proto is supported only for 5bit cplane and 18bit uplane */
1726 case PDCP_SN_SIZE_5:
1729 sn_mask = (swap == false) ? PDCP_C_PLANE_SN_MASK :
1730 PDCP_C_PLANE_SN_MASK_BE;
1732 case PDCP_SN_SIZE_18:
1735 sn_mask = (swap == false) ? PDCP_U_PLANE_18BIT_SN_MASK :
1736 PDCP_U_PLANE_18BIT_SN_MASK_BE;
1738 case PDCP_SN_SIZE_7:
1739 case PDCP_SN_SIZE_12:
1740 case PDCP_SN_SIZE_15:
1741 pr_err("Invalid sn_size for %s\n", __func__);
1746 if (dir == OP_TYPE_ENCAP_PROTOCOL)
1747 MATHB(p, SEQINSZ, SUB, length, VSEQINSZ, 4, IMMED2);
1749 SEQLOAD(p, MATH0, offset, length, 0);
1750 JUMP(p, 1, LOCAL_JUMP, ALL_TRUE, CALM);
1751 MOVEB(p, MATH0, offset, IFIFOAB2, 0, length, IMMED);
1752 MATHB(p, MATH0, AND, sn_mask, MATH1, 8, IFB | IMMED2);
1754 SEQSTORE(p, MATH0, offset, length, 0);
1755 MATHB(p, MATH1, SHLD, MATH1, MATH1, 8, 0);
1756 MOVEB(p, DESCBUF, 4, MATH2, 0, 8, WAITCOMP | IMMED);
1757 MATHB(p, MATH1, OR, MATH2, MATH1, 8, 0);
1758 MOVEB(p, MATH1, 0, CONTEXT1, 16, 8, IMMED);
1759 MOVEB(p, MATH1, 0, CONTEXT2, 0, 4, IMMED);
1760 if (swap == false) {
1761 MATHB(p, MATH1, AND, upper_32_bits(PDCP_BEARER_MASK), MATH2, 4,
1763 MATHB(p, MATH1, AND, lower_32_bits(PDCP_DIR_MASK), MATH3, 4,
1766 MATHB(p, MATH1, AND, lower_32_bits(PDCP_BEARER_MASK_BE), MATH2,
1768 MATHB(p, MATH1, AND, upper_32_bits(PDCP_DIR_MASK_BE), MATH3,
1771 MATHB(p, MATH3, SHLD, MATH3, MATH3, 8, 0);
1772 MOVEB(p, MATH2, 4, OFIFO, 0, 12, IMMED);
1773 MOVE(p, OFIFO, 0, CONTEXT2, 4, 12, IMMED);
1774 if (dir == OP_TYPE_ENCAP_PROTOCOL) {
1775 MATHB(p, SEQINSZ, ADD, PDCP_MAC_I_LEN, VSEQOUTSZ, 4, IMMED2);
1777 MATHB(p, SEQINSZ, SUB, PDCP_MAC_I_LEN, MATH1, 4, IMMED2);
1779 MATHB(p, ZERO, ADD, MATH1, VSEQOUTSZ, 4, 0);
1780 MATHB(p, ZERO, ADD, MATH1, VSEQINSZ, 4, 0);
1783 if (dir == OP_TYPE_ENCAP_PROTOCOL)
1784 SEQFIFOSTORE(p, MSG, 0, 0, VLF);
1786 SEQFIFOSTORE(p, MSG, 0, 0, VLF | CONT);
1788 ALG_OPERATION(p, OP_ALG_ALGSEL_SNOW_F9,
1790 OP_ALG_AS_INITFINAL,
1791 dir == OP_TYPE_ENCAP_PROTOCOL ?
1792 ICV_CHECK_DISABLE : ICV_CHECK_ENABLE,
1794 ALG_OPERATION(p, OP_ALG_ALGSEL_AES,
1796 OP_ALG_AS_INITFINAL,
1798 dir == OP_TYPE_ENCAP_PROTOCOL ? DIR_ENC : DIR_DEC);
1800 if (dir == OP_TYPE_ENCAP_PROTOCOL) {
1801 SEQFIFOLOAD(p, MSGINSNOOP, 0, VLF | LAST2);
1802 MOVE(p, CONTEXT2, 0, IFIFOAB1, 0, 4, LAST1 | FLUSH1 | IMMED);
1804 SEQFIFOLOAD(p, MSGOUTSNOOP, 0, VLF | LAST2);
1805 SEQFIFOLOAD(p, MSG1, 4, LAST1 | FLUSH1);
1806 JUMP(p, 1, LOCAL_JUMP, ALL_TRUE, CLASS1 | NOP | NIFP);
1808 if (rta_sec_era >= RTA_SEC_ERA_6)
1809 LOAD(p, 0, DCTRL, 0, LDLEN_RST_CHA_OFIFO_PTR, IMMED);
1811 MOVE(p, OFIFO, 0, MATH0, 0, 4, WAITCOMP | IMMED);
1813 NFIFOADD(p, IFIFO, ICV2, 4, LAST2);
1815 if (rta_sec_era <= RTA_SEC_ERA_2) {
1816 /* Shut off automatic Info FIFO entries */
1817 LOAD(p, 0, DCTRL, LDOFF_DISABLE_AUTO_NFIFO, 0, IMMED);
1818 MOVE(p, MATH0, 0, IFIFOAB2, 0, 4, WAITCOMP | IMMED);
1820 MOVE(p, MATH0, 0, IFIFO, 0, 4, WAITCOMP | IMMED);
1828 pdcp_insert_cplane_snow_zuc_op(struct program *p,
1829 bool swap __maybe_unused,
1830 struct alginfo *cipherdata,
1831 struct alginfo *authdata,
1833 enum pdcp_sn_size sn_size,
1834 unsigned char era_2_sw_hfn_ovrd __maybe_unused)
1836 uint32_t offset = 0, length = 0, sn_mask = 0;
1839 REFERENCE(pkeyjump);
1841 if (rta_sec_era < RTA_SEC_ERA_5) {
1842 pr_err("Invalid era for selected algorithm\n");
1846 pkeyjump = JUMP(p, keyjump, LOCAL_JUMP, ALL_TRUE, SHRD | SELF | BOTH);
1847 KEY(p, KEY1, cipherdata->key_enc_flags, cipherdata->key,
1848 cipherdata->keylen, INLINE_KEY(cipherdata));
1849 KEY(p, KEY2, authdata->key_enc_flags, authdata->key, authdata->keylen,
1850 INLINE_KEY(authdata));
1852 SET_LABEL(p, keyjump);
1854 if ((rta_sec_era >= RTA_SEC_ERA_8 && sn_size != PDCP_SN_SIZE_18) ||
1855 (rta_sec_era == RTA_SEC_ERA_10)) {
1858 if (sn_size == PDCP_SN_SIZE_5)
1859 pclid = OP_PCLID_LTE_PDCP_CTRL_MIXED;
1861 pclid = OP_PCLID_LTE_PDCP_USER_RN;
1863 PROTOCOL(p, dir, pclid,
1864 ((uint16_t)cipherdata->algtype << 8) |
1865 (uint16_t)authdata->algtype);
1868 /* Non-proto is supported only for 5bit cplane and 18bit uplane */
1870 case PDCP_SN_SIZE_5:
1873 sn_mask = (swap == false) ? PDCP_C_PLANE_SN_MASK :
1874 PDCP_C_PLANE_SN_MASK_BE;
1876 case PDCP_SN_SIZE_18:
1879 sn_mask = (swap == false) ? PDCP_U_PLANE_18BIT_SN_MASK :
1880 PDCP_U_PLANE_18BIT_SN_MASK_BE;
1882 case PDCP_SN_SIZE_7:
1883 case PDCP_SN_SIZE_12:
1884 case PDCP_SN_SIZE_15:
1885 pr_err("Invalid sn_size for %s\n", __func__);
1890 SEQLOAD(p, MATH0, offset, length, 0);
1891 JUMP(p, 1, LOCAL_JUMP, ALL_TRUE, CALM);
1892 MOVEB(p, MATH0, offset, IFIFOAB2, 0, length, IMMED);
1893 MATHB(p, MATH0, AND, sn_mask, MATH1, 8, IFB | IMMED2);
1895 MATHB(p, MATH1, SHLD, MATH1, MATH1, 8, 0);
1896 MOVEB(p, DESCBUF, 4, MATH2, 0, 8, WAITCOMP | IMMED);
1897 MATHB(p, MATH1, OR, MATH2, MATH2, 8, 0);
1898 MOVEB(p, MATH2, 0, CONTEXT1, 0, 8, IMMED);
1899 MOVEB(p, MATH2, 0, CONTEXT2, 0, 8, WAITCOMP | IMMED);
1901 if (dir == OP_TYPE_ENCAP_PROTOCOL)
1902 MATHB(p, SEQINSZ, ADD, PDCP_MAC_I_LEN, VSEQOUTSZ, 4, IMMED2);
1904 MATHB(p, SEQINSZ, SUB, PDCP_MAC_I_LEN, VSEQOUTSZ, 4, IMMED2);
1906 MATHB(p, SEQINSZ, SUB, ZERO, VSEQINSZ, 4, 0);
1907 SEQSTORE(p, MATH0, offset, length, 0);
1909 if (dir == OP_TYPE_ENCAP_PROTOCOL) {
1910 SEQFIFOSTORE(p, MSG, 0, 0, VLF);
1911 SEQFIFOLOAD(p, MSGINSNOOP, 0, VLF | LAST2);
1913 SEQFIFOSTORE(p, MSG, 0, 0, VLF | CONT);
1914 SEQFIFOLOAD(p, MSGOUTSNOOP, 0, VLF | LAST1 | FLUSH1);
1917 ALG_OPERATION(p, OP_ALG_ALGSEL_ZUCA,
1919 OP_ALG_AS_INITFINAL,
1920 dir == OP_TYPE_ENCAP_PROTOCOL ?
1921 ICV_CHECK_DISABLE : ICV_CHECK_ENABLE,
1924 ALG_OPERATION(p, OP_ALG_ALGSEL_SNOW_F8,
1926 OP_ALG_AS_INITFINAL,
1928 dir == OP_TYPE_ENCAP_PROTOCOL ? DIR_ENC : DIR_DEC);
1929 if (dir == OP_TYPE_ENCAP_PROTOCOL) {
1930 MOVE(p, CONTEXT2, 0, IFIFOAB1, 0, 4, LAST1 | FLUSH1 | IMMED);
1933 MOVE(p, OFIFO, 0, MATH0, 0, 4, IMMED);
1934 LOAD(p, NFIFOENTRY_STYPE_ALTSOURCE |
1935 NFIFOENTRY_DEST_CLASS2 |
1936 NFIFOENTRY_DTYPE_ICV |
1937 NFIFOENTRY_LC2 | 4, NFIFO_SZL, 0, 4, IMMED);
1938 MOVE(p, MATH0, 0, ALTSOURCE, 0, 4, WAITCOMP | IMMED);
1941 /* Reset ZUCA mode and done interrupt */
1942 LOAD(p, CLRW_CLR_C2MODE, CLRW, 0, 4, IMMED);
1943 LOAD(p, CIRQ_ZADI, ICTRL, 0, 4, IMMED);
1945 PATCH_JUMP(p, pkeyjump, keyjump);
1950 pdcp_insert_cplane_aes_zuc_op(struct program *p,
1951 bool swap __maybe_unused,
1952 struct alginfo *cipherdata,
1953 struct alginfo *authdata,
1955 enum pdcp_sn_size sn_size,
1956 unsigned char era_2_sw_hfn_ovrd __maybe_unused)
1958 uint32_t offset = 0, length = 0, sn_mask = 0;
1960 REFERENCE(pkeyjump);
1962 if (rta_sec_era < RTA_SEC_ERA_5) {
1963 pr_err("Invalid era for selected algorithm\n");
1967 pkeyjump = JUMP(p, keyjump, LOCAL_JUMP, ALL_TRUE, SHRD | SELF | BOTH);
1968 KEY(p, KEY1, cipherdata->key_enc_flags, cipherdata->key,
1969 cipherdata->keylen, INLINE_KEY(cipherdata));
1970 KEY(p, KEY2, authdata->key_enc_flags, authdata->key, authdata->keylen,
1971 INLINE_KEY(authdata));
1973 if ((rta_sec_era >= RTA_SEC_ERA_8 && sn_size != PDCP_SN_SIZE_18) ||
1974 (rta_sec_era == RTA_SEC_ERA_10)) {
1977 if (sn_size == PDCP_SN_SIZE_5)
1978 pclid = OP_PCLID_LTE_PDCP_CTRL_MIXED;
1980 pclid = OP_PCLID_LTE_PDCP_USER_RN;
1982 PROTOCOL(p, dir, pclid,
1983 ((uint16_t)cipherdata->algtype << 8) |
1984 (uint16_t)authdata->algtype);
1988 /* Non-proto is supported only for 5bit cplane and 18bit uplane */
1990 case PDCP_SN_SIZE_5:
1993 sn_mask = (swap == false) ? PDCP_C_PLANE_SN_MASK :
1994 PDCP_C_PLANE_SN_MASK_BE;
1996 case PDCP_SN_SIZE_18:
1999 sn_mask = (swap == false) ? PDCP_U_PLANE_18BIT_SN_MASK :
2000 PDCP_U_PLANE_18BIT_SN_MASK_BE;
2002 case PDCP_SN_SIZE_7:
2003 case PDCP_SN_SIZE_12:
2004 case PDCP_SN_SIZE_15:
2005 pr_err("Invalid sn_size for %s\n", __func__);
2010 SET_LABEL(p, keyjump);
2011 SEQLOAD(p, MATH0, offset, length, 0);
2012 JUMP(p, 1, LOCAL_JUMP, ALL_TRUE, CALM);
2013 MOVEB(p, MATH0, offset, IFIFOAB2, 0, length, IMMED);
2014 MATHB(p, MATH0, AND, sn_mask, MATH1, 8, IFB | IMMED2);
2016 MATHB(p, MATH1, SHLD, MATH1, MATH1, 8, 0);
2017 MOVEB(p, DESCBUF, 4, MATH2, 0, 8, WAITCOMP | IMMED);
2018 MATHB(p, MATH1, OR, MATH2, MATH2, 8, 0);
2019 MOVEB(p, MATH2, 0, CONTEXT1, 16, 8, IMMED);
2020 MOVEB(p, MATH2, 0, CONTEXT2, 0, 8, WAITCOMP | IMMED);
2022 if (dir == OP_TYPE_ENCAP_PROTOCOL)
2023 MATHB(p, SEQINSZ, ADD, PDCP_MAC_I_LEN, VSEQOUTSZ, 4, IMMED2);
2025 MATHB(p, SEQINSZ, SUB, PDCP_MAC_I_LEN, VSEQOUTSZ, 4, IMMED2);
2027 MATHB(p, SEQINSZ, SUB, ZERO, VSEQINSZ, 4, 0);
2028 SEQSTORE(p, MATH0, offset, length, 0);
2030 if (dir == OP_TYPE_ENCAP_PROTOCOL) {
2031 SEQFIFOSTORE(p, MSG, 0, 0, VLF);
2032 SEQFIFOLOAD(p, MSGINSNOOP, 0, VLF | LAST2);
2034 SEQFIFOSTORE(p, MSG, 0, 0, VLF | CONT);
2035 SEQFIFOLOAD(p, MSGOUTSNOOP, 0, VLF | LAST1 | FLUSH1);
2038 ALG_OPERATION(p, OP_ALG_ALGSEL_ZUCA,
2040 OP_ALG_AS_INITFINAL,
2041 dir == OP_TYPE_ENCAP_PROTOCOL ?
2042 ICV_CHECK_DISABLE : ICV_CHECK_ENABLE,
2045 ALG_OPERATION(p, OP_ALG_ALGSEL_AES,
2047 OP_ALG_AS_INITFINAL,
2049 dir == OP_TYPE_ENCAP_PROTOCOL ? DIR_ENC : DIR_DEC);
2051 if (dir == OP_TYPE_ENCAP_PROTOCOL) {
2052 MOVE(p, CONTEXT2, 0, IFIFOAB1, 0, 4, LAST1 | FLUSH1 | IMMED);
2055 MOVE(p, OFIFO, 0, MATH0, 0, 4, IMMED);
2057 LOAD(p, NFIFOENTRY_STYPE_ALTSOURCE |
2058 NFIFOENTRY_DEST_CLASS2 |
2059 NFIFOENTRY_DTYPE_ICV |
2060 NFIFOENTRY_LC2 | 4, NFIFO_SZL, 0, 4, IMMED);
2061 MOVE(p, MATH0, 0, ALTSOURCE, 0, 4, WAITCOMP | IMMED);
2064 /* Reset ZUCA mode and done interrupt */
2065 LOAD(p, CLRW_CLR_C2MODE, CLRW, 0, 4, IMMED);
2066 LOAD(p, CIRQ_ZADI, ICTRL, 0, 4, IMMED);
2068 PATCH_JUMP(p, pkeyjump, keyjump);
2074 pdcp_insert_cplane_zuc_snow_op(struct program *p,
2075 bool swap __maybe_unused,
2076 struct alginfo *cipherdata,
2077 struct alginfo *authdata,
2079 enum pdcp_sn_size sn_size,
2080 unsigned char era_2_sw_hfn_ovrd __maybe_unused)
2082 uint32_t offset = 0, length = 0, sn_mask = 0;
2084 REFERENCE(pkeyjump);
2086 if (rta_sec_era < RTA_SEC_ERA_5) {
2087 pr_err("Invalid era for selected algorithm\n");
2091 pkeyjump = JUMP(p, keyjump, LOCAL_JUMP, ALL_TRUE, SHRD | SELF | BOTH);
2092 KEY(p, KEY1, cipherdata->key_enc_flags, cipherdata->key,
2093 cipherdata->keylen, INLINE_KEY(cipherdata));
2094 KEY(p, KEY2, authdata->key_enc_flags, authdata->key, authdata->keylen,
2095 INLINE_KEY(authdata));
2097 if ((rta_sec_era >= RTA_SEC_ERA_8 && sn_size != PDCP_SN_SIZE_18) ||
2098 (rta_sec_era == RTA_SEC_ERA_10)) {
2101 if (sn_size == PDCP_SN_SIZE_5)
2102 pclid = OP_PCLID_LTE_PDCP_CTRL_MIXED;
2104 pclid = OP_PCLID_LTE_PDCP_USER_RN;
2106 PROTOCOL(p, dir, pclid,
2107 ((uint16_t)cipherdata->algtype << 8) |
2108 (uint16_t)authdata->algtype);
2112 /* Non-proto is supported only for 5bit cplane and 18bit uplane */
2114 case PDCP_SN_SIZE_5:
2117 sn_mask = (swap == false) ? PDCP_C_PLANE_SN_MASK :
2118 PDCP_C_PLANE_SN_MASK_BE;
2120 case PDCP_SN_SIZE_18:
2123 sn_mask = (swap == false) ? PDCP_U_PLANE_18BIT_SN_MASK :
2124 PDCP_U_PLANE_18BIT_SN_MASK_BE;
2126 case PDCP_SN_SIZE_7:
2127 case PDCP_SN_SIZE_12:
2128 case PDCP_SN_SIZE_15:
2129 pr_err("Invalid sn_size for %s\n", __func__);
2133 SET_LABEL(p, keyjump);
2134 SEQLOAD(p, MATH0, offset, length, 0);
2135 JUMP(p, 1, LOCAL_JUMP, ALL_TRUE, CALM);
2136 MOVEB(p, MATH0, offset, IFIFOAB2, 0, length, IMMED);
2137 MATHB(p, MATH0, AND, sn_mask, MATH1, 8, IFB | IMMED2);
2139 MATHB(p, MATH1, SHLD, MATH1, MATH1, 8, 0);
2140 MOVEB(p, DESCBUF, 4, MATH2, 0, 8, WAITCOMP | IMMED);
2141 MATHB(p, MATH1, OR, MATH2, MATH1, 8, 0);
2142 MOVEB(p, MATH1, 0, CONTEXT1, 0, 8, IMMED);
2143 MOVEB(p, MATH1, 0, CONTEXT2, 0, 4, IMMED);
2144 if (swap == false) {
2145 MATHB(p, MATH1, AND, upper_32_bits(PDCP_BEARER_MASK), MATH2,
2147 MATHB(p, MATH1, AND, lower_32_bits(PDCP_DIR_MASK), MATH3,
2150 MATHB(p, MATH1, AND, lower_32_bits(PDCP_BEARER_MASK_BE), MATH2,
2152 MATHB(p, MATH1, AND, upper_32_bits(PDCP_DIR_MASK_BE), MATH3,
2155 MATHB(p, MATH3, SHLD, MATH3, MATH3, 8, 0);
2156 MOVEB(p, MATH2, 4, OFIFO, 0, 12, IMMED);
2157 MOVE(p, OFIFO, 0, CONTEXT2, 4, 12, IMMED);
2159 if (dir == OP_TYPE_ENCAP_PROTOCOL) {
2160 MATHB(p, SEQINSZ, ADD, PDCP_MAC_I_LEN, VSEQOUTSZ, 4, IMMED2);
2161 MATHB(p, SEQINSZ, SUB, ZERO, VSEQINSZ, 4, 0);
2163 MATHB(p, SEQINSZ, SUB, PDCP_MAC_I_LEN, VSEQOUTSZ, 4, IMMED2);
2164 MATHB(p, VSEQOUTSZ, SUB, ZERO, VSEQINSZ, 4, 0);
2167 SEQSTORE(p, MATH0, offset, length, 0);
2169 if (dir == OP_TYPE_ENCAP_PROTOCOL) {
2170 SEQFIFOSTORE(p, MSG, 0, 0, VLF);
2171 SEQFIFOLOAD(p, MSGINSNOOP, 0, VLF | LAST2);
2173 SEQFIFOSTORE(p, MSG, 0, 0, VLF | CONT);
2174 SEQFIFOLOAD(p, MSGOUTSNOOP, 0, VLF | LAST2);
2177 ALG_OPERATION(p, OP_ALG_ALGSEL_SNOW_F9,
2179 OP_ALG_AS_INITFINAL,
2180 dir == OP_TYPE_ENCAP_PROTOCOL ?
2181 ICV_CHECK_DISABLE : ICV_CHECK_ENABLE,
2184 ALG_OPERATION(p, OP_ALG_ALGSEL_ZUCE,
2186 OP_ALG_AS_INITFINAL,
2188 dir == OP_TYPE_ENCAP_PROTOCOL ? DIR_ENC : DIR_DEC);
2190 if (dir == OP_TYPE_ENCAP_PROTOCOL) {
2191 MOVE(p, CONTEXT2, 0, IFIFOAB1, 0, 4, LAST1 | FLUSH1 | IMMED);
2193 SEQFIFOLOAD(p, MSG1, 4, LAST1 | FLUSH1);
2194 JUMP(p, 1, LOCAL_JUMP, ALL_TRUE, CLASS1 | NOP | NIFP);
2196 if (rta_sec_era >= RTA_SEC_ERA_6)
2198 * For SEC ERA 6, there's a problem with the OFIFO
2199 * pointer, and thus it needs to be reset here before
2202 LOAD(p, 0, DCTRL, 0, LDLEN_RST_CHA_OFIFO_PTR, IMMED);
2204 /* Put ICV to M0 before sending it to C2 for comparison. */
2205 MOVEB(p, OFIFO, 0, MATH0, 0, 4, WAITCOMP | IMMED);
2207 LOAD(p, NFIFOENTRY_STYPE_ALTSOURCE |
2208 NFIFOENTRY_DEST_CLASS2 |
2209 NFIFOENTRY_DTYPE_ICV |
2210 NFIFOENTRY_LC2 | 4, NFIFO_SZL, 0, 4, IMMED);
2211 MOVEB(p, MATH0, 0, ALTSOURCE, 0, 4, IMMED);
2214 PATCH_JUMP(p, pkeyjump, keyjump);
2219 pdcp_insert_cplane_zuc_aes_op(struct program *p,
2220 bool swap __maybe_unused,
2221 struct alginfo *cipherdata,
2222 struct alginfo *authdata,
2224 enum pdcp_sn_size sn_size,
2225 unsigned char era_2_sw_hfn_ovrd __maybe_unused)
2227 uint32_t offset = 0, length = 0, sn_mask = 0;
2228 if (rta_sec_era < RTA_SEC_ERA_5) {
2229 pr_err("Invalid era for selected algorithm\n");
2233 if ((rta_sec_era >= RTA_SEC_ERA_8 && sn_size != PDCP_SN_SIZE_18) ||
2234 (rta_sec_era == RTA_SEC_ERA_10)) {
2237 KEY(p, KEY1, cipherdata->key_enc_flags, cipherdata->key,
2238 cipherdata->keylen, INLINE_KEY(cipherdata));
2239 KEY(p, KEY2, authdata->key_enc_flags, authdata->key,
2240 authdata->keylen, INLINE_KEY(authdata));
2242 if (sn_size == PDCP_SN_SIZE_5)
2243 pclid = OP_PCLID_LTE_PDCP_CTRL_MIXED;
2245 pclid = OP_PCLID_LTE_PDCP_USER_RN;
2247 PROTOCOL(p, dir, pclid,
2248 ((uint16_t)cipherdata->algtype << 8) |
2249 (uint16_t)authdata->algtype);
2252 /* Non-proto is supported only for 5bit cplane and 18bit uplane */
2254 case PDCP_SN_SIZE_5:
2257 sn_mask = (swap == false) ? PDCP_C_PLANE_SN_MASK :
2258 PDCP_C_PLANE_SN_MASK_BE;
2260 case PDCP_SN_SIZE_18:
2263 sn_mask = (swap == false) ? PDCP_U_PLANE_18BIT_SN_MASK :
2264 PDCP_U_PLANE_18BIT_SN_MASK_BE;
2266 case PDCP_SN_SIZE_7:
2267 case PDCP_SN_SIZE_12:
2268 case PDCP_SN_SIZE_15:
2269 pr_err("Invalid sn_size for %s\n", __func__);
2273 SEQLOAD(p, MATH0, offset, length, 0);
2274 JUMP(p, 1, LOCAL_JUMP, ALL_TRUE, CALM);
2275 MATHB(p, MATH0, AND, sn_mask, MATH1, 8, IFB | IMMED2);
2277 MATHB(p, MATH1, SHLD, MATH1, MATH1, 8, 0);
2278 MOVEB(p, DESCBUF, 4, MATH2, 0, 0x08, WAITCOMP | IMMED);
2279 MATHB(p, MATH1, OR, MATH2, MATH2, 8, 0);
2280 SEQSTORE(p, MATH0, offset, length, 0);
2281 if (dir == OP_TYPE_ENCAP_PROTOCOL) {
2282 KEY(p, KEY1, authdata->key_enc_flags, authdata->key,
2283 authdata->keylen, INLINE_KEY(authdata));
2284 MOVEB(p, MATH2, 0, IFIFOAB1, 0, 0x08, IMMED);
2285 MOVEB(p, MATH0, offset, IFIFOAB1, 0, length, IMMED);
2287 MATHB(p, SEQINSZ, SUB, ZERO, VSEQINSZ, 4, 0);
2288 MATHB(p, VSEQINSZ, ADD, PDCP_MAC_I_LEN, VSEQOUTSZ, 4, IMMED2);
2290 ALG_OPERATION(p, OP_ALG_ALGSEL_AES,
2292 OP_ALG_AS_INITFINAL,
2295 SEQFIFOLOAD(p, MSG1, 0, VLF | LAST1 | FLUSH1);
2296 MOVEB(p, CONTEXT1, 0, MATH3, 0, 4, WAITCOMP | IMMED);
2297 LOAD(p, CLRW_RESET_CLS1_CHA |
2305 KEY(p, KEY1, cipherdata->key_enc_flags, cipherdata->key,
2306 cipherdata->keylen, INLINE_KEY(cipherdata));
2308 MOVEB(p, MATH2, 0, CONTEXT1, 0, 8, IMMED);
2309 SEQINPTR(p, 0, PDCP_NULL_MAX_FRAME_LEN, RTO);
2311 ALG_OPERATION(p, OP_ALG_ALGSEL_ZUCE,
2313 OP_ALG_AS_INITFINAL,
2316 SEQFIFOSTORE(p, MSG, 0, 0, VLF);
2318 SEQFIFOLOAD(p, SKIP, length, 0);
2320 SEQFIFOLOAD(p, MSG1, 0, VLF);
2321 MOVEB(p, MATH3, 0, IFIFOAB1, 0, 4, LAST1 | FLUSH1 | IMMED);
2323 MOVEB(p, MATH2, 0, CONTEXT1, 0, 8, IMMED);
2325 MOVE(p, CONTEXT1, 0, CONTEXT2, 0, 8, IMMED);
2327 MATHB(p, SEQINSZ, SUB, ZERO, VSEQINSZ, 4, 0);
2329 MATHB(p, SEQINSZ, SUB, PDCP_MAC_I_LEN, VSEQOUTSZ, 4, IMMED2);
2331 KEY(p, KEY1, cipherdata->key_enc_flags, cipherdata->key,
2332 cipherdata->keylen, INLINE_KEY(cipherdata));
2334 MOVE(p, CONTEXT1, 0, CONTEXT2, 0, 8, IMMED);
2336 ALG_OPERATION(p, OP_ALG_ALGSEL_ZUCE,
2338 OP_ALG_AS_INITFINAL,
2341 SEQFIFOSTORE(p, MSG, 0, 0, VLF | CONT);
2342 SEQFIFOLOAD(p, MSG1, 0, VLF | LAST1 | FLUSH1);
2344 MOVEB(p, OFIFO, 0, MATH3, 0, 4, IMMED);
2346 LOAD(p, CLRW_RESET_CLS1_CHA |
2354 KEY(p, KEY1, authdata->key_enc_flags, authdata->key,
2355 authdata->keylen, INLINE_KEY(authdata));
2357 SEQINPTR(p, 0, 0, SOP);
2359 ALG_OPERATION(p, OP_ALG_ALGSEL_AES,
2361 OP_ALG_AS_INITFINAL,
2365 MATHB(p, SEQINSZ, SUB, ZERO, VSEQINSZ, 4, 0);
2367 MOVE(p, CONTEXT2, 0, IFIFOAB1, 0, 8, IMMED);
2369 SEQFIFOLOAD(p, MSG1, 0, VLF | LAST1 | FLUSH1);
2371 LOAD(p, NFIFOENTRY_STYPE_ALTSOURCE |
2372 NFIFOENTRY_DEST_CLASS1 |
2373 NFIFOENTRY_DTYPE_ICV |
2375 NFIFOENTRY_FC1 | 4, NFIFO_SZL, 0, 4, IMMED);
2376 MOVEB(p, MATH3, 0, ALTSOURCE, 0, 4, IMMED);
2383 pdcp_insert_uplane_no_int_op(struct program *p,
2384 bool swap __maybe_unused,
2385 struct alginfo *cipherdata,
2387 enum pdcp_sn_size sn_size)
2392 /* Insert Cipher Key */
2393 KEY(p, KEY1, cipherdata->key_enc_flags, cipherdata->key,
2394 cipherdata->keylen, INLINE_KEY(cipherdata));
2396 if ((rta_sec_era >= RTA_SEC_ERA_8 && sn_size == PDCP_SN_SIZE_15) ||
2397 (rta_sec_era >= RTA_SEC_ERA_10)) {
2398 PROTOCOL(p, dir, OP_PCLID_LTE_PDCP_USER,
2399 (uint16_t)cipherdata->algtype);
2403 if (sn_size == PDCP_SN_SIZE_15) {
2404 SEQLOAD(p, MATH0, 6, 2, 0);
2405 sn_mask = (swap == false) ? PDCP_U_PLANE_15BIT_SN_MASK :
2406 PDCP_U_PLANE_15BIT_SN_MASK_BE;
2407 } else { /* SN Size == PDCP_SN_SIZE_18 */
2408 SEQLOAD(p, MATH0, 5, 3, 0);
2409 sn_mask = (swap == false) ? PDCP_U_PLANE_18BIT_SN_MASK :
2410 PDCP_U_PLANE_18BIT_SN_MASK_BE;
2412 JUMP(p, 1, LOCAL_JUMP, ALL_TRUE, CALM);
2413 MATHB(p, MATH0, AND, sn_mask, MATH1, 8, IFB | IMMED2);
2415 if (sn_size == PDCP_SN_SIZE_15)
2416 SEQSTORE(p, MATH0, 6, 2, 0);
2417 else /* SN Size == PDCP_SN_SIZE_18 */
2418 SEQSTORE(p, MATH0, 5, 3, 0);
2420 MATHB(p, MATH1, SHLD, MATH1, MATH1, 8, 0);
2421 MOVEB(p, DESCBUF, 8, MATH2, 0, 8, WAITCOMP | IMMED);
2422 MATHB(p, MATH1, OR, MATH2, MATH2, 8, 0);
2424 MATHB(p, SEQINSZ, SUB, MATH3, VSEQINSZ, 4, 0);
2425 MATHB(p, SEQINSZ, SUB, MATH3, VSEQOUTSZ, 4, 0);
2427 SEQFIFOSTORE(p, MSG, 0, 0, VLF);
2429 op = dir == OP_TYPE_ENCAP_PROTOCOL ? DIR_ENC : DIR_DEC;
2430 switch (cipherdata->algtype) {
2431 case PDCP_CIPHER_TYPE_SNOW:
2432 MOVEB(p, MATH2, 0, CONTEXT1, 0, 8, WAITCOMP | IMMED);
2433 ALG_OPERATION(p, OP_ALG_ALGSEL_SNOW_F8,
2435 OP_ALG_AS_INITFINAL,
2440 case PDCP_CIPHER_TYPE_AES:
2441 MOVEB(p, MATH2, 0, CONTEXT1, 0x10, 0x10, WAITCOMP | IMMED);
2442 ALG_OPERATION(p, OP_ALG_ALGSEL_AES,
2444 OP_ALG_AS_INITFINAL,
2449 case PDCP_CIPHER_TYPE_ZUC:
2450 if (rta_sec_era < RTA_SEC_ERA_5) {
2451 pr_err("Invalid era for selected algorithm\n");
2454 MOVEB(p, MATH2, 0, CONTEXT1, 0, 0x08, IMMED);
2455 MOVEB(p, MATH2, 0, CONTEXT1, 0x08, 0x08, WAITCOMP | IMMED);
2457 ALG_OPERATION(p, OP_ALG_ALGSEL_ZUCE,
2459 OP_ALG_AS_INITFINAL,
2465 pr_err("%s: Invalid encrypt algorithm selected: %d\n",
2466 "pdcp_insert_uplane_15bit_op", cipherdata->algtype);
2470 SEQFIFOLOAD(p, MSG1, 0, VLF | LAST1 | FLUSH1);
2476 * Function for inserting the snippet of code responsible for creating
2477 * the HFN override code via either DPOVRD or via the input frame.
2480 insert_hfn_ov_op(struct program *p,
2482 enum pdb_type_e pdb_type,
2483 unsigned char era_2_sw_hfn_ovrd)
2485 uint32_t imm = PDCP_DPOVRD_HFN_OV_EN;
2486 uint16_t hfn_pdb_offset;
2488 REFERENCE(pkeyjump);
2490 if (rta_sec_era == RTA_SEC_ERA_2 && !era_2_sw_hfn_ovrd)
2494 case PDCP_PDB_TYPE_NO_PDB:
2496 * If there is no PDB, then HFN override mechanism does not
2497 * make any sense, thus in this case the function will
2498 * return the pointer to the current position in the
2503 case PDCP_PDB_TYPE_REDUCED_PDB:
2507 case PDCP_PDB_TYPE_FULL_PDB:
2515 if (rta_sec_era > RTA_SEC_ERA_2) {
2516 MATHB(p, DPOVRD, AND, imm, NONE, 8, IFB | IMMED2);
2518 SEQLOAD(p, MATH0, 4, 4, 0);
2519 JUMP(p, 1, LOCAL_JUMP, ALL_TRUE, CALM);
2520 MATHB(p, MATH0, AND, imm, NONE, 8, IFB | IMMED2);
2521 SEQSTORE(p, MATH0, 4, 4, 0);
2524 pkeyjump = JUMP(p, keyjump, LOCAL_JUMP, ALL_TRUE, MATH_Z);
2526 if (rta_sec_era > RTA_SEC_ERA_2)
2527 MATHI(p, DPOVRD, LSHIFT, shift, MATH0, 4, IMMED2);
2529 MATHB(p, MATH0, LSHIFT, shift, MATH0, 4, IMMED2);
2531 MATHB(p, MATH0, SHLD, MATH0, MATH0, 8, 0);
2532 MOVE(p, MATH0, 0, DESCBUF, hfn_pdb_offset, 4, IMMED);
2534 if (rta_sec_era >= RTA_SEC_ERA_8)
2536 * For ERA8, DPOVRD could be handled by the PROTOCOL command
2537 * itself. For now, this is not done. Thus, clear DPOVRD here
2538 * to alleviate any side-effects.
2540 MATHB(p, DPOVRD, AND, ZERO, DPOVRD, 4, STL);
2542 SET_LABEL(p, keyjump);
2543 PATCH_JUMP(p, pkeyjump, keyjump);
2548 * PDCP Control PDB creation function
2550 static inline enum pdb_type_e
2551 cnstr_pdcp_c_plane_pdb(struct program *p,
2553 enum pdcp_sn_size sn_size,
2554 unsigned char bearer,
2555 unsigned char direction,
2556 uint32_t hfn_threshold,
2557 struct alginfo *cipherdata,
2558 struct alginfo *authdata)
2560 struct pdcp_pdb pdb;
2562 pdb_mask[PDCP_CIPHER_TYPE_INVALID][PDCP_AUTH_TYPE_INVALID] = {
2564 PDCP_PDB_TYPE_NO_PDB, /* NULL */
2565 PDCP_PDB_TYPE_FULL_PDB, /* SNOW f9 */
2566 PDCP_PDB_TYPE_FULL_PDB, /* AES CMAC */
2567 PDCP_PDB_TYPE_FULL_PDB /* ZUC-I */
2570 PDCP_PDB_TYPE_FULL_PDB, /* NULL */
2571 PDCP_PDB_TYPE_FULL_PDB, /* SNOW f9 */
2572 PDCP_PDB_TYPE_REDUCED_PDB, /* AES CMAC */
2573 PDCP_PDB_TYPE_REDUCED_PDB /* ZUC-I */
2576 PDCP_PDB_TYPE_FULL_PDB, /* NULL */
2577 PDCP_PDB_TYPE_REDUCED_PDB, /* SNOW f9 */
2578 PDCP_PDB_TYPE_FULL_PDB, /* AES CMAC */
2579 PDCP_PDB_TYPE_REDUCED_PDB /* ZUC-I */
2582 PDCP_PDB_TYPE_FULL_PDB, /* NULL */
2583 PDCP_PDB_TYPE_REDUCED_PDB, /* SNOW f9 */
2584 PDCP_PDB_TYPE_REDUCED_PDB, /* AES CMAC */
2585 PDCP_PDB_TYPE_FULL_PDB /* ZUC-I */
2589 if (rta_sec_era >= RTA_SEC_ERA_8) {
2590 memset(&pdb, 0x00, sizeof(struct pdcp_pdb));
2592 /* To support 12-bit seq numbers, we use u-plane opt in pdb.
2593 * SEC supports 5-bit only with c-plane opt in pdb.
2595 if (sn_size == PDCP_SN_SIZE_12) {
2596 pdb.hfn_res = hfn << PDCP_U_PLANE_PDB_LONG_SN_HFN_SHIFT;
2597 pdb.bearer_dir_res = (uint32_t)
2598 ((bearer << PDCP_U_PLANE_PDB_BEARER_SHIFT) |
2599 (direction << PDCP_U_PLANE_PDB_DIR_SHIFT));
2602 hfn_threshold << PDCP_U_PLANE_PDB_LONG_SN_HFN_THR_SHIFT;
2605 /* This means 5-bit c-plane.
2606 * Here we use c-plane opt in pdb
2609 /* This is a HW issue. Bit 2 should be set to zero,
2610 * but it does not work this way. Override here.
2612 pdb.opt_res.rsvd = 0x00000002;
2614 /* Copy relevant information from user to PDB */
2615 pdb.hfn_res = hfn << PDCP_C_PLANE_PDB_HFN_SHIFT;
2616 pdb.bearer_dir_res = (uint32_t)
2617 ((bearer << PDCP_C_PLANE_PDB_BEARER_SHIFT) |
2618 (direction << PDCP_C_PLANE_PDB_DIR_SHIFT));
2620 hfn_threshold << PDCP_C_PLANE_PDB_HFN_THR_SHIFT;
2623 /* copy PDB in descriptor*/
2624 __rta_out32(p, pdb.opt_res.opt);
2625 __rta_out32(p, pdb.hfn_res);
2626 __rta_out32(p, pdb.bearer_dir_res);
2627 __rta_out32(p, pdb.hfn_thr_res);
2629 return PDCP_PDB_TYPE_FULL_PDB;
2632 switch (pdb_mask[cipherdata->algtype][authdata->algtype]) {
2633 case PDCP_PDB_TYPE_NO_PDB:
2636 case PDCP_PDB_TYPE_REDUCED_PDB:
2637 __rta_out32(p, (hfn << PDCP_C_PLANE_PDB_HFN_SHIFT));
2639 (uint32_t)((bearer <<
2640 PDCP_C_PLANE_PDB_BEARER_SHIFT) |
2642 PDCP_C_PLANE_PDB_DIR_SHIFT)));
2645 case PDCP_PDB_TYPE_FULL_PDB:
2646 memset(&pdb, 0x00, sizeof(struct pdcp_pdb));
2648 /* This is a HW issue. Bit 2 should be set to zero,
2649 * but it does not work this way. Override here.
2651 pdb.opt_res.rsvd = 0x00000002;
2653 /* Copy relevant information from user to PDB */
2654 pdb.hfn_res = hfn << PDCP_C_PLANE_PDB_HFN_SHIFT;
2655 pdb.bearer_dir_res = (uint32_t)
2656 ((bearer << PDCP_C_PLANE_PDB_BEARER_SHIFT) |
2657 (direction << PDCP_C_PLANE_PDB_DIR_SHIFT));
2659 hfn_threshold << PDCP_C_PLANE_PDB_HFN_THR_SHIFT;
2661 /* copy PDB in descriptor*/
2662 __rta_out32(p, pdb.opt_res.opt);
2663 __rta_out32(p, pdb.hfn_res);
2664 __rta_out32(p, pdb.bearer_dir_res);
2665 __rta_out32(p, pdb.hfn_thr_res);
2670 return PDCP_PDB_TYPE_INVALID;
2673 return pdb_mask[cipherdata->algtype][authdata->algtype];
2677 * PDCP UPlane PDB creation function
2679 static inline enum pdb_type_e
2680 cnstr_pdcp_u_plane_pdb(struct program *p,
2681 enum pdcp_sn_size sn_size,
2682 uint32_t hfn, unsigned short bearer,
2683 unsigned short direction,
2684 uint32_t hfn_threshold,
2685 struct alginfo *cipherdata,
2686 struct alginfo *authdata)
2688 struct pdcp_pdb pdb;
2689 enum pdb_type_e pdb_type = PDCP_PDB_TYPE_FULL_PDB;
2691 pdb_mask[PDCP_CIPHER_TYPE_INVALID][PDCP_AUTH_TYPE_INVALID] = {
2693 PDCP_PDB_TYPE_NO_PDB, /* NULL */
2694 PDCP_PDB_TYPE_FULL_PDB, /* SNOW f9 */
2695 PDCP_PDB_TYPE_FULL_PDB, /* AES CMAC */
2696 PDCP_PDB_TYPE_FULL_PDB /* ZUC-I */
2699 PDCP_PDB_TYPE_FULL_PDB, /* NULL */
2700 PDCP_PDB_TYPE_FULL_PDB, /* SNOW f9 */
2701 PDCP_PDB_TYPE_REDUCED_PDB, /* AES CMAC */
2702 PDCP_PDB_TYPE_REDUCED_PDB /* ZUC-I */
2705 PDCP_PDB_TYPE_FULL_PDB, /* NULL */
2706 PDCP_PDB_TYPE_REDUCED_PDB, /* SNOW f9 */
2707 PDCP_PDB_TYPE_FULL_PDB, /* AES CMAC */
2708 PDCP_PDB_TYPE_REDUCED_PDB /* ZUC-I */
2711 PDCP_PDB_TYPE_FULL_PDB, /* NULL */
2712 PDCP_PDB_TYPE_REDUCED_PDB, /* SNOW f9 */
2713 PDCP_PDB_TYPE_REDUCED_PDB, /* AES CMAC */
2714 PDCP_PDB_TYPE_FULL_PDB /* ZUC-I */
2718 /* Read options from user */
2719 /* Depending on sequence number length, the HFN and HFN threshold
2720 * have different lengths.
2722 memset(&pdb, 0x00, sizeof(struct pdcp_pdb));
2725 case PDCP_SN_SIZE_7:
2726 pdb.opt_res.opt |= PDCP_U_PLANE_PDB_OPT_SHORT_SN;
2727 pdb.hfn_res = hfn << PDCP_U_PLANE_PDB_SHORT_SN_HFN_SHIFT;
2729 hfn_threshold<<PDCP_U_PLANE_PDB_SHORT_SN_HFN_THR_SHIFT;
2732 case PDCP_SN_SIZE_12:
2733 pdb.opt_res.opt &= (uint32_t)(~PDCP_U_PLANE_PDB_OPT_SHORT_SN);
2734 pdb.hfn_res = hfn << PDCP_U_PLANE_PDB_LONG_SN_HFN_SHIFT;
2736 hfn_threshold<<PDCP_U_PLANE_PDB_LONG_SN_HFN_THR_SHIFT;
2739 case PDCP_SN_SIZE_15:
2740 pdb.opt_res.opt = (uint32_t)(PDCP_U_PLANE_PDB_OPT_15B_SN);
2741 pdb.hfn_res = hfn << PDCP_U_PLANE_PDB_15BIT_SN_HFN_SHIFT;
2743 hfn_threshold<<PDCP_U_PLANE_PDB_15BIT_SN_HFN_THR_SHIFT;
2746 case PDCP_SN_SIZE_18:
2747 pdb.opt_res.opt = (uint32_t)(PDCP_U_PLANE_PDB_OPT_18B_SN);
2748 pdb.hfn_res = hfn << PDCP_U_PLANE_PDB_18BIT_SN_HFN_SHIFT;
2750 hfn_threshold<<PDCP_U_PLANE_PDB_18BIT_SN_HFN_THR_SHIFT;
2752 if (rta_sec_era <= RTA_SEC_ERA_8) {
2753 if (cipherdata && authdata)
2754 pdb_type = pdb_mask[cipherdata->algtype]
2755 [authdata->algtype];
2760 pr_err("Invalid Sequence Number Size setting in PDB\n");
2764 pdb.bearer_dir_res = (uint32_t)
2765 ((bearer << PDCP_U_PLANE_PDB_BEARER_SHIFT) |
2766 (direction << PDCP_U_PLANE_PDB_DIR_SHIFT));
2769 case PDCP_PDB_TYPE_NO_PDB:
2772 case PDCP_PDB_TYPE_REDUCED_PDB:
2773 __rta_out32(p, pdb.hfn_res);
2774 __rta_out32(p, pdb.bearer_dir_res);
2777 case PDCP_PDB_TYPE_FULL_PDB:
2778 /* copy PDB in descriptor*/
2779 __rta_out32(p, pdb.opt_res.opt);
2780 __rta_out32(p, pdb.hfn_res);
2781 __rta_out32(p, pdb.bearer_dir_res);
2782 __rta_out32(p, pdb.hfn_thr_res);
2787 return PDCP_PDB_TYPE_INVALID;
2793 * cnstr_shdsc_pdcp_c_plane_encap - Function for creating a PDCP Control Plane
2794 * encapsulation descriptor.
2795 * @descbuf: pointer to buffer for descriptor construction
2796 * @ps: if 36/40bit addressing is desired, this parameter must be true
2797 * @swap: must be true when core endianness doesn't match SEC endianness
2798 * @hfn: starting Hyper Frame Number to be used together with the SN from the
2800 * @sn_size: size of sequence numbers, only 5/12 bit sequence numbers are valid
2801 * @bearer: radio bearer ID
2802 * @direction: the direction of the PDCP frame (UL/DL)
2803 * @hfn_threshold: HFN value that once reached triggers a warning from SEC that
2804 * keys should be renegotiated at the earliest convenience.
2805 * @cipherdata: pointer to block cipher transform definitions
2806 * Valid algorithm values are those from cipher_type_pdcp enum.
2807 * @authdata: pointer to authentication transform definitions
2808 * Valid algorithm values are those from auth_type_pdcp enum.
2809 * @era_2_sw_hfn_ovrd: if software HFN override mechanism is desired for
2810 * this descriptor. Note: Can only be used for
2812 * Return: size of descriptor written in words or negative number on error.
2813 * Once the function returns, the value of this parameter can be used
2814 * for reclaiming the space that wasn't used for the descriptor.
2816 * Note: descbuf must be large enough to contain a full 256 byte long
2817 * descriptor; after the function returns, by subtracting the actual number of
2818 * bytes used, the user can reuse the remaining buffer space for other purposes.
2821 cnstr_shdsc_pdcp_c_plane_encap(uint32_t *descbuf,
2825 enum pdcp_sn_size sn_size,
2826 unsigned char bearer,
2827 unsigned char direction,
2828 uint32_t hfn_threshold,
2829 struct alginfo *cipherdata,
2830 struct alginfo *authdata,
2831 unsigned char era_2_sw_hfn_ovrd)
2834 (*pdcp_cp_fp[PDCP_CIPHER_TYPE_INVALID][PDCP_AUTH_TYPE_INVALID])
2835 (struct program*, bool swap, struct alginfo *,
2836 struct alginfo *, unsigned int, enum pdcp_sn_size,
2837 unsigned char __maybe_unused) = {
2839 pdcp_insert_cplane_null_op, /* NULL */
2840 pdcp_insert_cplane_int_only_op, /* SNOW f9 */
2841 pdcp_insert_cplane_int_only_op, /* AES CMAC */
2842 pdcp_insert_cplane_int_only_op /* ZUC-I */
2845 pdcp_insert_cplane_enc_only_op, /* NULL */
2846 pdcp_insert_cplane_acc_op, /* SNOW f9 */
2847 pdcp_insert_cplane_snow_aes_op, /* AES CMAC */
2848 pdcp_insert_cplane_snow_zuc_op /* ZUC-I */
2851 pdcp_insert_cplane_enc_only_op, /* NULL */
2852 pdcp_insert_cplane_aes_snow_op, /* SNOW f9 */
2853 pdcp_insert_cplane_acc_op, /* AES CMAC */
2854 pdcp_insert_cplane_aes_zuc_op /* ZUC-I */
2857 pdcp_insert_cplane_enc_only_op, /* NULL */
2858 pdcp_insert_cplane_zuc_snow_op, /* SNOW f9 */
2859 pdcp_insert_cplane_zuc_aes_op, /* AES CMAC */
2860 pdcp_insert_cplane_acc_op /* ZUC-I */
2863 static enum rta_share_type
2864 desc_share[PDCP_CIPHER_TYPE_INVALID][PDCP_AUTH_TYPE_INVALID] = {
2866 SHR_WAIT, /* NULL */
2867 SHR_ALWAYS, /* SNOW f9 */
2868 SHR_ALWAYS, /* AES CMAC */
2869 SHR_ALWAYS /* ZUC-I */
2872 SHR_ALWAYS, /* NULL */
2873 SHR_ALWAYS, /* SNOW f9 */
2874 SHR_WAIT, /* AES CMAC */
2875 SHR_WAIT /* ZUC-I */
2878 SHR_ALWAYS, /* NULL */
2879 SHR_ALWAYS, /* SNOW f9 */
2880 SHR_ALWAYS, /* AES CMAC */
2881 SHR_WAIT /* ZUC-I */
2884 SHR_ALWAYS, /* NULL */
2885 SHR_WAIT, /* SNOW f9 */
2886 SHR_WAIT, /* AES CMAC */
2887 SHR_ALWAYS /* ZUC-I */
2890 enum pdb_type_e pdb_type;
2892 struct program *p = &prg;
2896 if (rta_sec_era != RTA_SEC_ERA_2 && era_2_sw_hfn_ovrd) {
2897 pr_err("Cannot select SW HFN override for other era than 2");
2901 if (sn_size != PDCP_SN_SIZE_12 && sn_size != PDCP_SN_SIZE_5) {
2902 pr_err("C-plane supports only 5-bit and 12-bit sequence numbers\n");
2906 PROGRAM_CNTXT_INIT(p, descbuf, 0);
2908 PROGRAM_SET_BSWAP(p);
2910 PROGRAM_SET_36BIT_ADDR(p);
2912 SHR_HDR(p, desc_share[cipherdata->algtype][authdata->algtype], 0, 0);
2914 pdb_type = cnstr_pdcp_c_plane_pdb(p,
2923 SET_LABEL(p, pdb_end);
2925 err = insert_hfn_ov_op(p, sn_size, pdb_type,
2930 err = pdcp_cp_fp[cipherdata->algtype][authdata->algtype](p,
2934 OP_TYPE_ENCAP_PROTOCOL,
2940 PATCH_HDR(p, 0, pdb_end);
2942 return PROGRAM_FINALIZE(p);
2946 * cnstr_shdsc_pdcp_c_plane_decap - Function for creating a PDCP Control Plane
2947 * decapsulation descriptor.
2948 * @descbuf: pointer to buffer for descriptor construction
2949 * @ps: if 36/40bit addressing is desired, this parameter must be true
2950 * @swap: must be true when core endianness doesn't match SEC endianness
2951 * @hfn: starting Hyper Frame Number to be used together with the SN from the
2953 * @sn_size: size of sequence numbers, only 5/12 bit sequence numbers are valid
2954 * @bearer: radio bearer ID
2955 * @direction: the direction of the PDCP frame (UL/DL)
2956 * @hfn_threshold: HFN value that once reached triggers a warning from SEC that
2957 * keys should be renegotiated at the earliest convenience.
2958 * @cipherdata: pointer to block cipher transform definitions
2959 * Valid algorithm values are those from cipher_type_pdcp enum.
2960 * @authdata: pointer to authentication transform definitions
2961 * Valid algorithm values are those from auth_type_pdcp enum.
2962 * @era_2_sw_hfn_ovrd: if software HFN override mechanism is desired for
2963 * this descriptor. Note: Can only be used for
2966 * Return: size of descriptor written in words or negative number on error.
2967 * Once the function returns, the value of this parameter can be used
2968 * for reclaiming the space that wasn't used for the descriptor.
2970 * Note: descbuf must be large enough to contain a full 256 byte long
2971 * descriptor; after the function returns, by subtracting the actual number of
2972 * bytes used, the user can reuse the remaining buffer space for other purposes.
2975 cnstr_shdsc_pdcp_c_plane_decap(uint32_t *descbuf,
2979 enum pdcp_sn_size sn_size,
2980 unsigned char bearer,
2981 unsigned char direction,
2982 uint32_t hfn_threshold,
2983 struct alginfo *cipherdata,
2984 struct alginfo *authdata,
2985 unsigned char era_2_sw_hfn_ovrd)
2988 (*pdcp_cp_fp[PDCP_CIPHER_TYPE_INVALID][PDCP_AUTH_TYPE_INVALID])
2989 (struct program*, bool swap, struct alginfo *,
2990 struct alginfo *, unsigned int, enum pdcp_sn_size,
2993 pdcp_insert_cplane_null_op, /* NULL */
2994 pdcp_insert_cplane_int_only_op, /* SNOW f9 */
2995 pdcp_insert_cplane_int_only_op, /* AES CMAC */
2996 pdcp_insert_cplane_int_only_op /* ZUC-I */
2999 pdcp_insert_cplane_enc_only_op, /* NULL */
3000 pdcp_insert_cplane_acc_op, /* SNOW f9 */
3001 pdcp_insert_cplane_snow_aes_op, /* AES CMAC */
3002 pdcp_insert_cplane_snow_zuc_op /* ZUC-I */
3005 pdcp_insert_cplane_enc_only_op, /* NULL */
3006 pdcp_insert_cplane_aes_snow_op, /* SNOW f9 */
3007 pdcp_insert_cplane_acc_op, /* AES CMAC */
3008 pdcp_insert_cplane_aes_zuc_op /* ZUC-I */
3011 pdcp_insert_cplane_enc_only_op, /* NULL */
3012 pdcp_insert_cplane_zuc_snow_op, /* SNOW f9 */
3013 pdcp_insert_cplane_zuc_aes_op, /* AES CMAC */
3014 pdcp_insert_cplane_acc_op /* ZUC-I */
3017 static enum rta_share_type
3018 desc_share[PDCP_CIPHER_TYPE_INVALID][PDCP_AUTH_TYPE_INVALID] = {
3020 SHR_WAIT, /* NULL */
3021 SHR_ALWAYS, /* SNOW f9 */
3022 SHR_ALWAYS, /* AES CMAC */
3023 SHR_ALWAYS /* ZUC-I */
3026 SHR_ALWAYS, /* NULL */
3027 SHR_ALWAYS, /* SNOW f9 */
3028 SHR_WAIT, /* AES CMAC */
3029 SHR_WAIT /* ZUC-I */
3032 SHR_ALWAYS, /* NULL */
3033 SHR_ALWAYS, /* SNOW f9 */
3034 SHR_ALWAYS, /* AES CMAC */
3035 SHR_WAIT /* ZUC-I */
3038 SHR_ALWAYS, /* NULL */
3039 SHR_WAIT, /* SNOW f9 */
3040 SHR_WAIT, /* AES CMAC */
3041 SHR_ALWAYS /* ZUC-I */
3044 enum pdb_type_e pdb_type;
3046 struct program *p = &prg;
3050 if (rta_sec_era != RTA_SEC_ERA_2 && era_2_sw_hfn_ovrd) {
3051 pr_err("Cannot select SW HFN override for other era than 2");
3055 if (sn_size != PDCP_SN_SIZE_12 && sn_size != PDCP_SN_SIZE_5) {
3056 pr_err("C-plane supports only 5-bit and 12-bit sequence numbers\n");
3060 PROGRAM_CNTXT_INIT(p, descbuf, 0);
3062 PROGRAM_SET_BSWAP(p);
3064 PROGRAM_SET_36BIT_ADDR(p);
3066 SHR_HDR(p, desc_share[cipherdata->algtype][authdata->algtype], 0, 0);
3068 pdb_type = cnstr_pdcp_c_plane_pdb(p,
3077 SET_LABEL(p, pdb_end);
3079 err = insert_hfn_ov_op(p, sn_size, pdb_type,
3084 err = pdcp_cp_fp[cipherdata->algtype][authdata->algtype](p,
3088 OP_TYPE_DECAP_PROTOCOL,
3094 PATCH_HDR(p, 0, pdb_end);
3096 return PROGRAM_FINALIZE(p);
3100 pdcp_insert_uplane_with_int_op(struct program *p,
3101 bool swap __maybe_unused,
3102 struct alginfo *cipherdata,
3103 struct alginfo *authdata,
3104 enum pdcp_sn_size sn_size,
3105 unsigned char era_2_sw_hfn_ovrd,
3109 (*pdcp_cp_fp[PDCP_CIPHER_TYPE_INVALID][PDCP_AUTH_TYPE_INVALID])
3110 (struct program*, bool swap, struct alginfo *,
3111 struct alginfo *, unsigned int, enum pdcp_sn_size,
3112 unsigned char __maybe_unused) = {
3114 pdcp_insert_cplane_null_op, /* NULL */
3115 pdcp_insert_cplane_int_only_op, /* SNOW f9 */
3116 pdcp_insert_cplane_int_only_op, /* AES CMAC */
3117 pdcp_insert_cplane_int_only_op /* ZUC-I */
3120 pdcp_insert_cplane_enc_only_op, /* NULL */
3121 pdcp_insert_uplane_snow_snow_op, /* SNOW f9 */
3122 pdcp_insert_cplane_snow_aes_op, /* AES CMAC */
3123 pdcp_insert_cplane_snow_zuc_op /* ZUC-I */
3126 pdcp_insert_cplane_enc_only_op, /* NULL */
3127 pdcp_insert_cplane_aes_snow_op, /* SNOW f9 */
3128 pdcp_insert_uplane_aes_aes_op, /* AES CMAC */
3129 pdcp_insert_cplane_aes_zuc_op /* ZUC-I */
3132 pdcp_insert_cplane_enc_only_op, /* NULL */
3133 pdcp_insert_cplane_zuc_snow_op, /* SNOW f9 */
3134 pdcp_insert_cplane_zuc_aes_op, /* AES CMAC */
3135 pdcp_insert_uplane_zuc_zuc_op /* ZUC-I */
3140 err = pdcp_cp_fp[cipherdata->algtype][authdata->algtype](p,
3155 * cnstr_shdsc_pdcp_u_plane_encap - Function for creating a PDCP User Plane
3156 * encapsulation descriptor.
3157 * @descbuf: pointer to buffer for descriptor construction
3158 * @ps: if 36/40bit addressing is desired, this parameter must be true
3159 * @swap: must be true when core endianness doesn't match SEC endianness
3160 * @sn_size: selects Sequence Number Size: 7/12/15 bits
3161 * @hfn: starting Hyper Frame Number to be used together with the SN from the
3163 * @bearer: radio bearer ID
3164 * @direction: the direction of the PDCP frame (UL/DL)
3165 * @hfn_threshold: HFN value that once reached triggers a warning from SEC that
3166 * keys should be renegotiated at the earliest convenience.
3167 * @cipherdata: pointer to block cipher transform definitions
3168 * Valid algorithm values are those from cipher_type_pdcp enum.
3169 * @era_2_sw_hfn_ovrd: if software HFN override mechanism is desired for
3170 * this descriptor. Note: Can only be used for
3173 * Return: size of descriptor written in words or negative number on error.
3174 * Once the function returns, the value of this parameter can be used
3175 * for reclaiming the space that wasn't used for the descriptor.
3177 * Note: descbuf must be large enough to contain a full 256 byte long
3178 * descriptor; after the function returns, by subtracting the actual number of
3179 * bytes used, the user can reuse the remaining buffer space for other purposes.
3182 cnstr_shdsc_pdcp_u_plane_encap(uint32_t *descbuf,
3185 enum pdcp_sn_size sn_size,
3187 unsigned short bearer,
3188 unsigned short direction,
3189 uint32_t hfn_threshold,
3190 struct alginfo *cipherdata,
3191 struct alginfo *authdata,
3192 unsigned char era_2_sw_hfn_ovrd)
3195 struct program *p = &prg;
3197 enum pdb_type_e pdb_type;
3198 static enum rta_share_type
3199 desc_share[PDCP_CIPHER_TYPE_INVALID][PDCP_AUTH_TYPE_INVALID] = {
3201 SHR_WAIT, /* NULL */
3202 SHR_ALWAYS, /* SNOW f9 */
3203 SHR_ALWAYS, /* AES CMAC */
3204 SHR_ALWAYS /* ZUC-I */
3207 SHR_ALWAYS, /* NULL */
3208 SHR_ALWAYS, /* SNOW f9 */
3209 SHR_WAIT, /* AES CMAC */
3210 SHR_WAIT /* ZUC-I */
3213 SHR_ALWAYS, /* NULL */
3214 SHR_ALWAYS, /* SNOW f9 */
3215 SHR_ALWAYS, /* AES CMAC */
3216 SHR_WAIT /* ZUC-I */
3219 SHR_ALWAYS, /* NULL */
3220 SHR_WAIT, /* SNOW f9 */
3221 SHR_WAIT, /* AES CMAC */
3222 SHR_ALWAYS /* ZUC-I */
3227 if (rta_sec_era != RTA_SEC_ERA_2 && era_2_sw_hfn_ovrd) {
3228 pr_err("Cannot select SW HFN ovrd for other era than 2");
3232 if (authdata && !authdata->algtype && rta_sec_era < RTA_SEC_ERA_8) {
3233 pr_err("Cannot use u-plane auth with era < 8");
3237 PROGRAM_CNTXT_INIT(p, descbuf, 0);
3239 PROGRAM_SET_BSWAP(p);
3241 PROGRAM_SET_36BIT_ADDR(p);
3244 SHR_HDR(p, desc_share[cipherdata->algtype][authdata->algtype], 0, 0);
3246 SHR_HDR(p, SHR_ALWAYS, 0, 0);
3247 pdb_type = cnstr_pdcp_u_plane_pdb(p, sn_size, hfn,
3248 bearer, direction, hfn_threshold,
3249 cipherdata, authdata);
3250 if (pdb_type == PDCP_PDB_TYPE_INVALID) {
3251 pr_err("Error creating PDCP UPlane PDB\n");
3254 SET_LABEL(p, pdb_end);
3256 err = insert_hfn_ov_op(p, sn_size, pdb_type, era_2_sw_hfn_ovrd);
3261 case PDCP_SN_SIZE_7:
3262 case PDCP_SN_SIZE_12:
3263 switch (cipherdata->algtype) {
3264 case PDCP_CIPHER_TYPE_ZUC:
3265 if (rta_sec_era < RTA_SEC_ERA_5) {
3266 pr_err("Invalid era for selected algorithm\n");
3270 case PDCP_CIPHER_TYPE_AES:
3271 case PDCP_CIPHER_TYPE_SNOW:
3272 case PDCP_CIPHER_TYPE_NULL:
3273 if (rta_sec_era == RTA_SEC_ERA_8 &&
3274 authdata && authdata->algtype == 0){
3275 err = pdcp_insert_uplane_with_int_op(p, swap,
3276 cipherdata, authdata,
3277 sn_size, era_2_sw_hfn_ovrd,
3278 OP_TYPE_ENCAP_PROTOCOL);
3284 if (pdb_type != PDCP_PDB_TYPE_FULL_PDB) {
3285 pr_err("PDB type must be FULL for PROTO desc\n");
3289 /* Insert auth key if requested */
3290 if (authdata && authdata->algtype) {
3291 KEY(p, KEY2, authdata->key_enc_flags,
3292 (uint64_t)authdata->key, authdata->keylen,
3293 INLINE_KEY(authdata));
3295 /* Insert Cipher Key */
3296 KEY(p, KEY1, cipherdata->key_enc_flags,
3297 (uint64_t)cipherdata->key, cipherdata->keylen,
3298 INLINE_KEY(cipherdata));
3301 PROTOCOL(p, OP_TYPE_ENCAP_PROTOCOL,
3302 OP_PCLID_LTE_PDCP_USER_RN,
3303 ((uint16_t)cipherdata->algtype << 8) |
3304 (uint16_t)authdata->algtype);
3306 PROTOCOL(p, OP_TYPE_ENCAP_PROTOCOL,
3307 OP_PCLID_LTE_PDCP_USER,
3308 (uint16_t)cipherdata->algtype);
3311 pr_err("%s: Invalid encrypt algorithm selected: %d\n",
3312 "cnstr_pcl_shdsc_pdcp_u_plane_decap",
3313 cipherdata->algtype);
3318 case PDCP_SN_SIZE_15:
3319 case PDCP_SN_SIZE_18:
3321 err = pdcp_insert_uplane_with_int_op(p, swap,
3322 cipherdata, authdata,
3323 sn_size, era_2_sw_hfn_ovrd,
3324 OP_TYPE_ENCAP_PROTOCOL);
3331 switch (cipherdata->algtype) {
3332 case PDCP_CIPHER_TYPE_NULL:
3333 insert_copy_frame_op(p,
3335 OP_TYPE_ENCAP_PROTOCOL);
3339 err = pdcp_insert_uplane_no_int_op(p, swap, cipherdata,
3340 OP_TYPE_ENCAP_PROTOCOL, sn_size);
3347 case PDCP_SN_SIZE_5:
3349 pr_err("Invalid SN size selected\n");
3353 PATCH_HDR(p, 0, pdb_end);
3354 return PROGRAM_FINALIZE(p);
3358 * cnstr_shdsc_pdcp_u_plane_decap - Function for creating a PDCP User Plane
3359 * decapsulation descriptor.
3360 * @descbuf: pointer to buffer for descriptor construction
3361 * @ps: if 36/40bit addressing is desired, this parameter must be true
3362 * @swap: must be true when core endianness doesn't match SEC endianness
3363 * @sn_size: selects Sequence Number Size: 7/12/15 bits
3364 * @hfn: starting Hyper Frame Number to be used together with the SN from the
3366 * @bearer: radio bearer ID
3367 * @direction: the direction of the PDCP frame (UL/DL)
3368 * @hfn_threshold: HFN value that once reached triggers a warning from SEC that
3369 * keys should be renegotiated at the earliest convenience.
3370 * @cipherdata: pointer to block cipher transform definitions
3371 * Valid algorithm values are those from cipher_type_pdcp enum.
3372 * @era_2_sw_hfn_ovrd: if software HFN override mechanism is desired for
3373 * this descriptor. Note: Can only be used for
3376 * Return: size of descriptor written in words or negative number on error.
3377 * Once the function returns, the value of this parameter can be used
3378 * for reclaiming the space that wasn't used for the descriptor.
3380 * Note: descbuf must be large enough to contain a full 256 byte long
3381 * descriptor; after the function returns, by subtracting the actual number of
3382 * bytes used, the user can reuse the remaining buffer space for other purposes.
3385 cnstr_shdsc_pdcp_u_plane_decap(uint32_t *descbuf,
3388 enum pdcp_sn_size sn_size,
3390 unsigned short bearer,
3391 unsigned short direction,
3392 uint32_t hfn_threshold,
3393 struct alginfo *cipherdata,
3394 struct alginfo *authdata,
3395 unsigned char era_2_sw_hfn_ovrd)
3398 struct program *p = &prg;
3400 enum pdb_type_e pdb_type;
3401 static enum rta_share_type
3402 desc_share[PDCP_CIPHER_TYPE_INVALID][PDCP_AUTH_TYPE_INVALID] = {
3404 SHR_WAIT, /* NULL */
3405 SHR_ALWAYS, /* SNOW f9 */
3406 SHR_ALWAYS, /* AES CMAC */
3407 SHR_ALWAYS /* ZUC-I */
3410 SHR_ALWAYS, /* NULL */
3411 SHR_ALWAYS, /* SNOW f9 */
3412 SHR_WAIT, /* AES CMAC */
3413 SHR_WAIT /* ZUC-I */
3416 SHR_ALWAYS, /* NULL */
3417 SHR_ALWAYS, /* SNOW f9 */
3418 SHR_ALWAYS, /* AES CMAC */
3419 SHR_WAIT /* ZUC-I */
3422 SHR_ALWAYS, /* NULL */
3423 SHR_WAIT, /* SNOW f9 */
3424 SHR_WAIT, /* AES CMAC */
3425 SHR_ALWAYS /* ZUC-I */
3431 if (rta_sec_era != RTA_SEC_ERA_2 && era_2_sw_hfn_ovrd) {
3432 pr_err("Cannot select SW HFN override for other era than 2");
3436 if (authdata && !authdata->algtype && rta_sec_era < RTA_SEC_ERA_8) {
3437 pr_err("Cannot use u-plane auth with era < 8");
3441 PROGRAM_CNTXT_INIT(p, descbuf, 0);
3443 PROGRAM_SET_BSWAP(p);
3445 PROGRAM_SET_36BIT_ADDR(p);
3447 SHR_HDR(p, desc_share[cipherdata->algtype][authdata->algtype], 0, 0);
3449 SHR_HDR(p, SHR_ALWAYS, 0, 0);
3451 pdb_type = cnstr_pdcp_u_plane_pdb(p, sn_size, hfn, bearer,
3452 direction, hfn_threshold,
3453 cipherdata, authdata);
3454 if (pdb_type == PDCP_PDB_TYPE_INVALID) {
3455 pr_err("Error creating PDCP UPlane PDB\n");
3458 SET_LABEL(p, pdb_end);
3460 err = insert_hfn_ov_op(p, sn_size, pdb_type, era_2_sw_hfn_ovrd);
3465 case PDCP_SN_SIZE_7:
3466 case PDCP_SN_SIZE_12:
3467 switch (cipherdata->algtype) {
3468 case PDCP_CIPHER_TYPE_ZUC:
3469 if (rta_sec_era < RTA_SEC_ERA_5) {
3470 pr_err("Invalid era for selected algorithm\n");
3474 case PDCP_CIPHER_TYPE_AES:
3475 case PDCP_CIPHER_TYPE_SNOW:
3476 case PDCP_CIPHER_TYPE_NULL:
3477 if (pdb_type != PDCP_PDB_TYPE_FULL_PDB) {
3478 pr_err("PDB type must be FULL for PROTO desc\n");
3482 /* Insert auth key if requested */
3483 if (authdata && authdata->algtype)
3484 KEY(p, KEY2, authdata->key_enc_flags,
3485 (uint64_t)authdata->key, authdata->keylen,
3486 INLINE_KEY(authdata));
3488 /* Insert Cipher Key */
3489 KEY(p, KEY1, cipherdata->key_enc_flags,
3490 cipherdata->key, cipherdata->keylen,
3491 INLINE_KEY(cipherdata));
3493 PROTOCOL(p, OP_TYPE_DECAP_PROTOCOL,
3494 OP_PCLID_LTE_PDCP_USER_RN,
3495 ((uint16_t)cipherdata->algtype << 8) |
3496 (uint16_t)authdata->algtype);
3498 PROTOCOL(p, OP_TYPE_DECAP_PROTOCOL,
3499 OP_PCLID_LTE_PDCP_USER,
3500 (uint16_t)cipherdata->algtype);
3503 pr_err("%s: Invalid encrypt algorithm selected: %d\n",
3504 "cnstr_pcl_shdsc_pdcp_u_plane_decap",
3505 cipherdata->algtype);
3510 case PDCP_SN_SIZE_15:
3511 case PDCP_SN_SIZE_18:
3513 err = pdcp_insert_uplane_with_int_op(p, swap,
3514 cipherdata, authdata,
3515 sn_size, era_2_sw_hfn_ovrd,
3516 OP_TYPE_DECAP_PROTOCOL);
3523 switch (cipherdata->algtype) {
3524 case PDCP_CIPHER_TYPE_NULL:
3525 insert_copy_frame_op(p,
3527 OP_TYPE_DECAP_PROTOCOL);
3531 err = pdcp_insert_uplane_no_int_op(p, swap, cipherdata,
3532 OP_TYPE_DECAP_PROTOCOL, sn_size);
3539 case PDCP_SN_SIZE_5:
3541 pr_err("Invalid SN size selected\n");
3545 PATCH_HDR(p, 0, pdb_end);
3546 return PROGRAM_FINALIZE(p);
3550 * cnstr_shdsc_pdcp_short_mac - Function for creating a PDCP Short MAC
3552 * @descbuf: pointer to buffer for descriptor construction
3553 * @ps: if 36/40bit addressing is desired, this parameter must be true
3554 * @swap: must be true when core endianness doesn't match SEC endianness
3555 * @authdata: pointer to authentication transform definitions
3556 * Valid algorithm values are those from auth_type_pdcp enum.
3558 * Return: size of descriptor written in words or negative number on error.
3559 * Once the function returns, the value of this parameter can be used
3560 * for reclaiming the space that wasn't used for the descriptor.
3562 * Note: descbuf must be large enough to contain a full 256 byte long
3563 * descriptor; after the function returns, by subtracting the actual number of
3564 * bytes used, the user can reuse the remaining buffer space for other purposes.
3567 cnstr_shdsc_pdcp_short_mac(uint32_t *descbuf,
3570 struct alginfo *authdata)
3573 struct program *p = &prg;
3574 uint32_t iv[3] = {0, 0, 0};
3575 LABEL(local_offset);
3576 REFERENCE(move_cmd_read_descbuf);
3577 REFERENCE(move_cmd_write_descbuf);
3579 PROGRAM_CNTXT_INIT(p, descbuf, 0);
3581 PROGRAM_SET_BSWAP(p);
3583 PROGRAM_SET_36BIT_ADDR(p);
3585 SHR_HDR(p, SHR_ALWAYS, 1, 0);
3587 if (rta_sec_era > RTA_SEC_ERA_2) {
3588 MATHB(p, SEQINSZ, SUB, ZERO, VSEQINSZ, 4, 0);
3589 MATHB(p, SEQINSZ, SUB, ZERO, MATH1, 4, 0);
3591 MATHB(p, SEQINSZ, ADD, ONE, MATH1, 4, 0);
3592 MATHB(p, MATH1, SUB, ONE, MATH1, 4, 0);
3593 MATHB(p, ZERO, ADD, MATH1, VSEQINSZ, 4, 0);
3594 MOVE(p, MATH1, 0, MATH0, 0, 8, IMMED);
3597 * Since MOVELEN is available only starting with
3598 * SEC ERA 3, use poor man's MOVELEN: create a MOVE
3599 * command dynamically by writing the length from M1 by
3600 * OR-ing the command in the M1 register and MOVE the
3601 * result into the descriptor buffer. Care must be taken
3602 * wrt. the location of the command because of SEC
3603 * pipelining. The actual MOVEs are written at the end
3604 * of the descriptor due to calculations needed on the
3605 * offset in the descriptor for the MOVE command.
3607 move_cmd_read_descbuf = MOVE(p, DESCBUF, 0, MATH0, 0, 6,
3609 move_cmd_write_descbuf = MOVE(p, MATH0, 0, DESCBUF, 0, 8,
3612 MATHB(p, ZERO, ADD, MATH1, VSEQOUTSZ, 4, 0);
3614 switch (authdata->algtype) {
3615 case PDCP_AUTH_TYPE_NULL:
3616 SEQFIFOSTORE(p, MSG, 0, 0, VLF);
3617 if (rta_sec_era > RTA_SEC_ERA_2) {
3618 MOVE(p, AB1, 0, OFIFO, 0, MATH1, 0);
3620 SET_LABEL(p, local_offset);
3622 /* Shut off automatic Info FIFO entries */
3623 LOAD(p, 0, DCTRL, LDOFF_DISABLE_AUTO_NFIFO, 0, IMMED);
3625 /* Placeholder for MOVE command with length from M1
3628 MOVE(p, IFIFOAB1, 0, OFIFO, 0, 0, IMMED);
3630 /* Enable automatic Info FIFO entries */
3631 LOAD(p, 0, DCTRL, LDOFF_ENABLE_AUTO_NFIFO, 0, IMMED);
3634 LOAD(p, (uintptr_t)iv, MATH0, 0, 8, IMMED | COPY);
3635 SEQFIFOLOAD(p, MSG1, 0, VLF | LAST1 | LAST2 | FLUSH1);
3636 SEQSTORE(p, MATH0, 0, 4, 0);
3640 case PDCP_AUTH_TYPE_SNOW:
3642 iv[1] = swap ? swab32(0x04000000) : 0x04000000;
3643 iv[2] = swap ? swab32(0xF8000000) : 0xF8000000;
3645 KEY(p, KEY2, authdata->key_enc_flags, authdata->key,
3646 authdata->keylen, INLINE_KEY(authdata));
3647 LOAD(p, (uintptr_t)&iv, CONTEXT2, 0, 12, IMMED | COPY);
3648 ALG_OPERATION(p, OP_ALG_ALGSEL_SNOW_F9,
3650 OP_ALG_AS_INITFINAL,
3653 SEQFIFOSTORE(p, MSG, 0, 0, VLF);
3655 if (rta_sec_era > RTA_SEC_ERA_2) {
3656 MOVE(p, AB1, 0, OFIFO, 0, MATH1, 0);
3658 SET_LABEL(p, local_offset);
3661 /* Shut off automatic Info FIFO entries */
3662 LOAD(p, 0, DCTRL, LDOFF_DISABLE_AUTO_NFIFO, 0, IMMED);
3664 /* Placeholder for MOVE command with length from M1
3667 MOVE(p, IFIFOAB1, 0, OFIFO, 0, 0, IMMED);
3669 /* Enable automatic Info FIFO entries */
3670 LOAD(p, 0, DCTRL, LDOFF_ENABLE_AUTO_NFIFO, 0, IMMED);
3672 SEQFIFOLOAD(p, MSGINSNOOP, 0, VLF | LAST1 | LAST2 | FLUSH1);
3673 SEQSTORE(p, CONTEXT2, 0, 4, 0);
3677 case PDCP_AUTH_TYPE_AES:
3679 iv[1] = swap ? swab32(0xFC000000) : 0xFC000000;
3680 iv[2] = 0x00000000; /* unused */
3682 KEY(p, KEY1, authdata->key_enc_flags, authdata->key,
3683 authdata->keylen, INLINE_KEY(authdata));
3684 LOAD(p, (uintptr_t)&iv, MATH0, 0, 8, IMMED | COPY);
3685 MOVE(p, MATH0, 0, IFIFOAB1, 0, 8, IMMED);
3686 ALG_OPERATION(p, OP_ALG_ALGSEL_AES,
3688 OP_ALG_AS_INITFINAL,
3691 SEQFIFOSTORE(p, MSG, 0, 0, VLF);
3693 if (rta_sec_era > RTA_SEC_ERA_2) {
3694 MOVE(p, AB2, 0, OFIFO, 0, MATH1, 0);
3696 SET_LABEL(p, local_offset);
3698 /* Shut off automatic Info FIFO entries */
3699 LOAD(p, 0, DCTRL, LDOFF_DISABLE_AUTO_NFIFO, 0, IMMED);
3701 /* Placeholder for MOVE command with length from M1
3704 MOVE(p, IFIFOAB2, 0, OFIFO, 0, 0, IMMED);
3706 /* Enable automatic Info FIFO entries */
3707 LOAD(p, 0, DCTRL, LDOFF_ENABLE_AUTO_NFIFO, 0, IMMED);
3709 SEQFIFOLOAD(p, MSGINSNOOP, 0, VLF | LAST1 | LAST2 | FLUSH1);
3710 SEQSTORE(p, CONTEXT1, 0, 4, 0);
3714 case PDCP_AUTH_TYPE_ZUC:
3715 if (rta_sec_era < RTA_SEC_ERA_5) {
3716 pr_err("Invalid era for selected algorithm\n");
3720 iv[1] = swap ? swab32(0xFC000000) : 0xFC000000;
3721 iv[2] = 0x00000000; /* unused */
3723 KEY(p, KEY2, authdata->key_enc_flags, authdata->key,
3724 authdata->keylen, INLINE_KEY(authdata));
3725 LOAD(p, (uintptr_t)&iv, CONTEXT2, 0, 12, IMMED | COPY);
3726 ALG_OPERATION(p, OP_ALG_ALGSEL_ZUCA,
3728 OP_ALG_AS_INITFINAL,
3731 SEQFIFOSTORE(p, MSG, 0, 0, VLF);
3732 MOVE(p, AB1, 0, OFIFO, 0, MATH1, 0);
3733 SEQFIFOLOAD(p, MSGINSNOOP, 0, VLF | LAST1 | LAST2 | FLUSH1);
3734 SEQSTORE(p, CONTEXT2, 0, 4, 0);
3739 pr_err("%s: Invalid integrity algorithm selected: %d\n",
3740 "cnstr_shdsc_pdcp_short_mac", authdata->algtype);
3745 if (rta_sec_era < RTA_SEC_ERA_3) {
3746 PATCH_MOVE(p, move_cmd_read_descbuf, local_offset);
3747 PATCH_MOVE(p, move_cmd_write_descbuf, local_offset);
3750 return PROGRAM_FINALIZE(p);
3753 #endif /* __DESC_PDCP_H__ */