1 /* SPDX-License-Identifier: BSD-3-Clause
2 * Copyright 2020-2021 NXP
5 #ifndef __DESC_SDAP_H__
6 #define __DESC_SDAP_H__
12 /* The file defines all the functions to do PDCP without protocol support in
16 /* Enable SDAP support */
19 #define SDAP_BYTE_SIZE 1
20 #define SDAP_BITS_SIZE (SDAP_BYTE_SIZE * 8)
23 static inline void key_loading_opti(struct program *p,
24 struct alginfo *cipherdata,
25 struct alginfo *authdata)
27 LABEL(lbl_skip_key_loading_jump);
28 REFERENCE(ref_skip_key_loading_jump);
30 /* Optimisation to bypass key loading (and decryption of the keys):
31 * Jump command testing:
32 * - SHRD: Descriptor is shared
33 * - SELF: The shared descriptor is in the same DECO
34 * - BOTH: The Class 1 and 2 CHA have finished
35 * -> If this is true, we jump and skip loading of the keys as they are
38 ref_skip_key_loading_jump =
39 JUMP(p, lbl_skip_key_loading_jump, LOCAL_JUMP, ALL_TRUE,
44 KEY(p, KEY1, cipherdata->key_enc_flags, cipherdata->key,
45 cipherdata->keylen, INLINE_KEY(cipherdata));
49 KEY(p, KEY2, authdata->key_enc_flags, authdata->key,
50 authdata->keylen, INLINE_KEY(authdata));
53 /* Save the place where we want the jump to go */
54 SET_LABEL(p, lbl_skip_key_loading_jump);
55 /* Update the jump command with the position where to jump */
56 PATCH_JUMP(p, ref_skip_key_loading_jump, lbl_skip_key_loading_jump);
59 static inline int pdcp_sdap_get_sn_parameters(enum pdcp_sn_size sn_size,
60 bool swap, uint32_t *offset,
68 *sn_mask = (swap == false) ? PDCP_C_PLANE_SN_MASK :
69 PDCP_C_PLANE_SN_MASK_BE;
74 *sn_mask = (swap == false) ? PDCP_7BIT_SN_MASK :
80 *sn_mask = (swap == false) ? PDCP_12BIT_SN_MASK :
81 PDCP_12BIT_SN_MASK_BE;
86 *sn_mask = (swap == false) ? PDCP_U_PLANE_15BIT_SN_MASK :
87 PDCP_U_PLANE_15BIT_SN_MASK_BE;
92 *sn_mask = (swap == false) ? PDCP_U_PLANE_18BIT_SN_MASK :
93 PDCP_U_PLANE_18BIT_SN_MASK_BE;
96 pr_err("Invalid sn_size for %s\n", __func__);
101 *length += SDAP_BYTE_SIZE;
102 *offset -= SDAP_BYTE_SIZE;
108 static inline int pdcp_sdap_insert_no_int_op(struct program *p,
109 bool swap __maybe_unused,
110 struct alginfo *cipherdata,
112 enum pdcp_sn_size sn_size,
113 enum pdb_type_e pdb_type)
116 uint32_t sn_mask = 0;
119 int hfn_bearer_dir_offset_in_descbuf =
120 (pdb_type == PDCP_PDB_TYPE_FULL_PDB) ?
121 FULL_PDB_DESCBUF_HFN_BEARER_DIR_OFFSET :
122 REDUCED_PDB_DESCBUF_HFN_BEARER_DIR_OFFSET;
124 if (pdcp_sdap_get_sn_parameters(sn_size, swap, &offset, &length,
129 key_loading_opti(p, cipherdata, NULL);
131 SEQLOAD(p, MATH0, offset, length, 0);
132 JUMP(p, 1, LOCAL_JUMP, ALL_TRUE, CALM);
135 ((swap == true) ? MATH_FUN_RSHIFT : MATH_FUN_LSHIFT),
136 SDAP_BITS_SIZE, MATH1, 8, 0);
137 MATHB(p, MATH1, AND, sn_mask, MATH1, 8, IFB | IMMED2);
139 MATHB(p, MATH0, AND, sn_mask, MATH1, 8, IFB | IMMED2);
142 SEQSTORE(p, MATH0, offset, length, 0);
144 MATHB(p, MATH1, SHLD, MATH1, MATH1, 8, 0);
145 MOVEB(p, DESCBUF, hfn_bearer_dir_offset_in_descbuf,
146 MATH2, 0, 8, WAITCOMP | IMMED);
147 MATHB(p, MATH1, OR, MATH2, MATH2, 8, 0);
149 MATHB(p, SEQINSZ, SUB, MATH3, VSEQINSZ, 4, 0);
150 MATHB(p, SEQINSZ, SUB, MATH3, VSEQOUTSZ, 4, 0);
152 SEQFIFOSTORE(p, MSG, 0, 0, VLF);
154 op = dir == OP_TYPE_ENCAP_PROTOCOL ? DIR_ENC : DIR_DEC;
155 switch (cipherdata->algtype) {
156 case PDCP_CIPHER_TYPE_SNOW:
158 MOVEB(p, MATH2, 0, CONTEXT1, 0, 8, WAITCOMP | IMMED);
159 ALG_OPERATION(p, OP_ALG_ALGSEL_SNOW_F8, OP_ALG_AAI_F8,
160 OP_ALG_AS_INITFINAL, ICV_CHECK_DISABLE, op);
163 case PDCP_CIPHER_TYPE_AES:
164 /* The first 64 bits are 0 */
165 MOVEB(p, MATH2, 0, CONTEXT1, 16, 8, WAITCOMP | IMMED);
166 ALG_OPERATION(p, OP_ALG_ALGSEL_AES, OP_ALG_AAI_CTR,
167 OP_ALG_AS_INITFINAL, ICV_CHECK_DISABLE, op);
170 case PDCP_CIPHER_TYPE_ZUC:
171 if (rta_sec_era < RTA_SEC_ERA_5) {
172 pr_err("Invalid era for selected algorithm\n");
175 /* The LSB and MSB is the same for ZUC context */
176 MOVEB(p, MATH2, 0, CONTEXT1, 0, 0x08, IMMED);
177 MOVEB(p, MATH2, 0, CONTEXT1, 0x08, 0x08, WAITCOMP | IMMED);
179 ALG_OPERATION(p, OP_ALG_ALGSEL_ZUCE, OP_ALG_AAI_F8,
180 OP_ALG_AS_INITFINAL, ICV_CHECK_DISABLE, op);
184 pr_err("%s: Invalid encrypt algorithm selected: %d\n",
185 "pdcp_sdap_insert_15bit_op", cipherdata->algtype);
189 SEQFIFOLOAD(p, MSG1, 0, VLF | LAST1 | FLUSH1);
195 pdcp_sdap_insert_enc_only_op(struct program *p, bool swap __maybe_unused,
196 struct alginfo *cipherdata,
197 struct alginfo *authdata __maybe_unused,
198 unsigned int dir, enum pdcp_sn_size sn_size,
199 unsigned char era_2_sw_hfn_ovrd __maybe_unused,
200 enum pdb_type_e pdb_type)
202 uint32_t offset = 0, length = 0, sn_mask = 0;
203 int hfn_bearer_dir_offset_in_descbuf =
204 (pdb_type == PDCP_PDB_TYPE_FULL_PDB) ?
205 FULL_PDB_DESCBUF_HFN_BEARER_DIR_OFFSET :
206 REDUCED_PDB_DESCBUF_HFN_BEARER_DIR_OFFSET;
208 if (pdcp_sdap_get_sn_parameters(sn_size, swap, &offset, &length,
213 key_loading_opti(p, cipherdata, NULL);
216 SEQLOAD(p, MATH0, offset, length, 0);
217 JUMP(p, 1, LOCAL_JUMP, ALL_TRUE, CALM);
221 ((swap == true) ? MATH_FUN_RSHIFT : MATH_FUN_LSHIFT),
222 SDAP_BITS_SIZE, MATH1, 8, 0);
223 MATHB(p, MATH1, AND, sn_mask, MATH1, 8, IFB | IMMED2);
225 MATHB(p, MATH0, AND, sn_mask, MATH1, 8, IFB | IMMED2);
228 /* Word (32 bit) swap */
229 MATHB(p, MATH1, SHLD, MATH1, MATH1, 8, 0);
230 /* Load words from PDB: word 02 (HFN) + word 03 (bearer_dir)*/
231 MOVEB(p, DESCBUF, hfn_bearer_dir_offset_in_descbuf,
232 MATH2, 0, 8, WAITCOMP | IMMED);
233 /* Create basic IV */
234 MATHB(p, MATH1, OR, MATH2, MATH2, 8, 0);
237 SEQSTORE(p, MATH0, offset, length, 0);
239 if (rta_sec_era > RTA_SEC_ERA_2) {
240 MATHB(p, SEQINSZ, SUB, ZERO, VSEQINSZ, 4, 0);
242 MATHB(p, SEQINSZ, SUB, ONE, MATH1, 4, 0);
243 MATHB(p, MATH1, ADD, ONE, VSEQINSZ, 4, 0);
246 if (dir == OP_TYPE_ENCAP_PROTOCOL)
247 MATHB(p, SEQINSZ, ADD, PDCP_MAC_I_LEN, VSEQOUTSZ, 4, IMMED2);
249 MATHB(p, SEQINSZ, SUB, PDCP_MAC_I_LEN, VSEQOUTSZ, 4, IMMED2);
251 switch (cipherdata->algtype) {
252 case PDCP_CIPHER_TYPE_SNOW:
253 MOVEB(p, MATH2, 0, CONTEXT1, 0, 8, WAITCOMP | IMMED);
254 SEQFIFOSTORE(p, MSG, 0, 0, VLF | CONT);
255 ALG_OPERATION(p, OP_ALG_ALGSEL_SNOW_F8, OP_ALG_AAI_F8,
256 OP_ALG_AS_INITFINAL, ICV_CHECK_DISABLE,
257 dir == OP_TYPE_ENCAP_PROTOCOL ? DIR_ENC :
261 case PDCP_CIPHER_TYPE_AES:
262 MOVEB(p, MATH2, 0, CONTEXT1, 16, 8, WAITCOMP | IMMED);
264 SEQFIFOSTORE(p, MSG, 0, 0, VLF | CONT);
265 ALG_OPERATION(p, OP_ALG_ALGSEL_AES, OP_ALG_AAI_CTR,
266 OP_ALG_AS_INITFINAL, ICV_CHECK_DISABLE,
267 dir == OP_TYPE_ENCAP_PROTOCOL ? DIR_ENC :
271 case PDCP_CIPHER_TYPE_ZUC:
272 if (rta_sec_era < RTA_SEC_ERA_5) {
273 pr_err("Invalid era for selected algorithm\n");
277 MOVEB(p, MATH2, 0, CONTEXT1, 0, 0x08, IMMED);
278 MOVEB(p, MATH2, 0, CONTEXT1, 0x08, 0x08, WAITCOMP | IMMED);
280 SEQFIFOSTORE(p, MSG, 0, 0, VLF | CONT);
281 ALG_OPERATION(p, OP_ALG_ALGSEL_ZUCE, OP_ALG_AAI_F8,
282 OP_ALG_AS_INITFINAL, ICV_CHECK_DISABLE,
283 dir == OP_TYPE_ENCAP_PROTOCOL ? DIR_ENC :
288 pr_err("%s: Invalid encrypt algorithm selected: %d\n",
289 "pdcp_sdap_insert_enc_only_op", cipherdata->algtype);
293 if (dir == OP_TYPE_ENCAP_PROTOCOL) {
294 SEQFIFOLOAD(p, MSG1, 0, VLF);
295 FIFOLOAD(p, MSG1, PDCP_NULL_INT_MAC_I_VAL, 4,
296 LAST1 | FLUSH1 | IMMED);
298 SEQFIFOLOAD(p, MSG1, 0, VLF | LAST1 | FLUSH1);
299 MOVE(p, OFIFO, 0, MATH1, 4, PDCP_MAC_I_LEN, WAITCOMP | IMMED);
300 MATHB(p, MATH1, XOR, PDCP_NULL_INT_MAC_I_VAL, NONE, 4, IMMED2);
301 JUMP(p, PDCP_NULL_INT_ICV_CHECK_FAILED_STATUS, HALT_STATUS,
309 * This function leverage the use of in/out snooping as SNOW and ZUC both
310 * have a class 1 and class 2 CHA. It also supports AES as cipher.
321 pdcp_sdap_insert_snoop_op(struct program *p, bool swap __maybe_unused,
322 struct alginfo *cipherdata, struct alginfo *authdata,
323 unsigned int dir, enum pdcp_sn_size sn_size,
324 unsigned char era_2_sw_hfn_ovrd __maybe_unused,
325 enum pdb_type_e pdb_type)
327 uint32_t offset = 0, length = 0, sn_mask = 0;
328 uint32_t int_op_alg = 0;
329 uint32_t int_op_aai = 0;
330 uint32_t cipher_op_alg = 0;
331 uint32_t cipher_op_aai = 0;
332 int hfn_bearer_dir_offset_in_descbuf =
333 (pdb_type == PDCP_PDB_TYPE_FULL_PDB) ?
334 FULL_PDB_DESCBUF_HFN_BEARER_DIR_OFFSET :
335 REDUCED_PDB_DESCBUF_HFN_BEARER_DIR_OFFSET;
337 if (authdata->algtype == PDCP_CIPHER_TYPE_ZUC) {
338 if (rta_sec_era < RTA_SEC_ERA_5) {
339 pr_err("Invalid era for selected algorithm\n");
344 if (pdcp_sdap_get_sn_parameters(sn_size, swap, &offset, &length,
348 if (dir == OP_TYPE_ENCAP_PROTOCOL)
349 MATHB(p, SEQINSZ, SUB, length, VSEQINSZ, 4, IMMED2);
351 key_loading_opti(p, cipherdata, authdata);
353 /* Load the PDCP header from the input data
354 * Note: SEQINSZ is decremented by length
356 SEQLOAD(p, MATH0, offset, length, 0);
357 /* Wait the SN is loaded */
358 JUMP(p, 1, LOCAL_JUMP, ALL_TRUE, CALM);
360 /* Pass the PDCP header to integrity block */
361 MOVEB(p, MATH0, offset, IFIFOAB2, 0, length, IMMED);
364 /* If SDAP is enabled, the least significant byte is the SDAP header
365 * Remove it by shifting the register
368 ((swap == true) ? MATH_FUN_RSHIFT : MATH_FUN_LSHIFT),
369 SDAP_BITS_SIZE, MATH1, 8, 0);
370 /* Mask the PDCP header to keep only the SN */
371 MATHB(p, MATH1, AND, sn_mask, MATH1, 8, IFB | IMMED2);
373 /* Mask the PDCP header to keep only the SN */
374 MATHB(p, MATH0, AND, sn_mask, MATH1, 8, IFB | IMMED2);
377 /* Do a byte swap, it places the SN in upper part of the MATH reg */
378 MATHB(p, MATH1, SHLD, MATH1, MATH1, 8, 0);
380 /* Load the HFN / Beare / Dir from the PDB
381 * CAAM word are 32bit hence loading 8 byte loads 2 words:
382 * - The HFN at offset hfn_bearer_dir_offset_in_descbuf
383 * - The Bearer / Dir at next word
385 MOVEB(p, DESCBUF, hfn_bearer_dir_offset_in_descbuf,
386 MATH2, 0, 8, WAITCOMP | IMMED);
388 /* Create the 4 first byte of the ICV by or-ing the math registers */
389 MATHB(p, MATH1, OR, MATH2, MATH1, 8, 0);
391 /* Set the IV of class 1 CHA */
392 if (cipherdata->algtype == PDCP_CIPHER_TYPE_AES) {
393 MOVEB(p, MATH1, 0, CONTEXT1, 16, 8, IMMED);
395 /* Set the IV for the confidentiality CHA */
396 MOVEB(p, MATH1, 0, CONTEXT1, 0, 8, IMMED);
399 /* Set the IV of class 2 CHA */
400 if (authdata->algtype == PDCP_AUTH_TYPE_ZUC) {
401 /* Set the IV for the integrity CHA */
402 MOVEB(p, MATH1, 0, CONTEXT2, 0, 8, WAITCOMP | IMMED);
403 } else if (authdata->algtype == PDCP_AUTH_TYPE_SNOW) {
404 MOVEB(p, MATH1, 0, CONTEXT2, 0, 4, WAITCOMP | IMMED);
406 /* Generate the bottom snow IV for integrity
407 * Note: MATH1 lowest 32bits is as follow:
408 * | bearer (5) | Dir (1) | zero (26) |
409 * the resulting math regs will be:
411 * | zero (5) | Dir (1) | zero (26) | | Bearer (5) | zero (27) |
414 MATHB(p, MATH1, AND, upper_32_bits(PDCP_BEARER_MASK),
416 MATHB(p, MATH1, AND, lower_32_bits(PDCP_DIR_MASK),
419 MATHB(p, MATH1, AND, lower_32_bits(PDCP_BEARER_MASK_BE),
421 MATHB(p, MATH1, AND, upper_32_bits(PDCP_DIR_MASK_BE),
424 /* Word swap MATH3 reg */
425 MATHB(p, MATH3, SHLD, MATH3, MATH3, 8, 0);
427 /* Don't understand, seems to be doing a move of 12 byte
428 * (read MATH2 and overread MATH3)
430 MOVEB(p, MATH2, 4, OFIFO, 0, 12, IMMED);
432 /* Add the rest of the snow IV to the context */
433 MOVE(p, OFIFO, 0, CONTEXT2, 4, 12, IMMED);
436 /* Set the variable size of data the register will write */
437 if (dir == OP_TYPE_ENCAP_PROTOCOL) {
438 /* We will add the interity data so add its length */
439 MATHI(p, SEQINSZ, ADD, PDCP_MAC_I_LEN, VSEQOUTSZ, 4, IMMED2);
441 /* We will check the interity data so remove its length */
442 MATHI(p, SEQINSZ, SUB, PDCP_MAC_I_LEN, VSEQOUTSZ, 4, IMMED2);
443 /* Do not take the ICV in the out-snooping configuration */
444 MATHI(p, SEQINSZ, SUB, PDCP_MAC_I_LEN, VSEQINSZ, 4, IMMED2);
447 /* We write the PDCP header to output*/
448 SEQSTORE(p, MATH0, offset, length, 0);
450 /* Definition of the flow of output data */
451 if (dir == OP_TYPE_ENCAP_PROTOCOL) {
452 /* We write data according to VSEQOUTSZ */
453 SEQFIFOSTORE(p, MSG, 0, 0, VLF);
455 /* We write data according to VSEQOUTSZ */
456 SEQFIFOSTORE(p, MSG, 0, 0, VLF | CONT);
459 /* Get parameters for authentication */
460 if (authdata->algtype == PDCP_AUTH_TYPE_ZUC) {
461 int_op_alg = OP_ALG_ALGSEL_ZUCA;
462 int_op_aai = OP_ALG_AAI_F9;
463 } else if (authdata->algtype == PDCP_AUTH_TYPE_SNOW) {
464 int_op_alg = OP_ALG_ALGSEL_SNOW_F9;
465 int_op_aai = OP_ALG_AAI_F9;
467 pr_err("%s no support for auth alg: %d\n", __func__,
472 /* Get parameters for ciphering */
473 if (cipherdata->algtype == PDCP_CIPHER_TYPE_ZUC) {
474 cipher_op_alg = OP_ALG_ALGSEL_ZUCE;
475 cipher_op_aai = OP_ALG_AAI_F8;
476 } else if (cipherdata->algtype == PDCP_CIPHER_TYPE_SNOW) {
477 cipher_op_alg = OP_ALG_ALGSEL_SNOW_F8;
478 cipher_op_aai = OP_ALG_AAI_F8;
479 } else if (cipherdata->algtype == PDCP_CIPHER_TYPE_AES) {
480 cipher_op_alg = OP_ALG_ALGSEL_AES;
481 cipher_op_aai = OP_ALG_AAI_CTR;
483 pr_err("%s no support for cipher alg: %d\n", __func__,
488 /* Configure the CHA, the class 2 CHA must be configured first or an
489 * error will be generated
492 /* Configure the class 2 CHA (integrity )*/
493 ALG_OPERATION(p, int_op_alg, int_op_aai, OP_ALG_AS_INITFINAL,
494 dir == OP_TYPE_ENCAP_PROTOCOL ? ICV_CHECK_DISABLE :
498 /* Configure class 1 CHA (confidentiality)*/
499 ALG_OPERATION(p, cipher_op_alg, cipher_op_aai, OP_ALG_AS_INITFINAL,
501 dir == OP_TYPE_ENCAP_PROTOCOL ? DIR_ENC : DIR_DEC);
503 /* Definition of the flow of input data */
504 if (dir == OP_TYPE_ENCAP_PROTOCOL) {
505 /* We read data according to VSEQINSZ
506 * Note: we perform an in-snooping, eg the data will be read
507 * only once. they will be sent to both the integrity CHA and
508 * confidentiality CHA
510 SEQFIFOLOAD(p, MSGINSNOOP, 0, VLF | LAST2);
512 /* When the integrity CHA is finished, send the ICV stored in
513 * the context to the confidentiality CHA for encryption
515 MOVE(p, CONTEXT2, 0, IFIFOAB1, 0, 4, LAST1 | FLUSH1 | IMMED);
517 /* We read data according to VSEQINSZ
518 * Note: we perform an out-snooping, eg the data will be read
519 * only once. The will first be sent to the confidentiality
520 * CHA for decryption, then the CAAM will direct them to the
521 * integrity CHA to verify the ICV (which is at the end of the
524 SEQFIFOLOAD(p, MSGOUTSNOOP, 0, VLF | LAST2);
526 /* Process the ICV by class 1 CHA */
527 SEQFIFOLOAD(p, MSG1, 4, LAST1 | FLUSH1);
529 /* Wait for class 1 CHA to finish, the ICV data are stalling in
532 JUMP(p, 1, LOCAL_JUMP, ALL_TRUE, CLASS1 | NOP | NIFP);
534 if (rta_sec_era >= RTA_SEC_ERA_6)
535 LOAD(p, 0, DCTRL, 0, LDLEN_RST_CHA_OFIFO_PTR, IMMED);
537 /* Save the content left in the Output FIFO (the ICV) to MATH0
539 MOVE(p, OFIFO, 0, MATH0, 0, 4, WAITCOMP | IMMED);
541 /* Configure a NFIFO entry to take data from the altsource
542 * and send it to the class 2 CHA as an ICV
544 NFIFOADD(p, IFIFO, ICV2, 4, LAST2);
546 /* Move the content of MATH0 (OFIFO offset) to altsource
547 * Note: As configured by the altsource, this will send
550 if (rta_sec_era <= RTA_SEC_ERA_2) {
551 /* Shut off automatic Info FIFO entries */
552 LOAD(p, 0, DCTRL, LDOFF_DISABLE_AUTO_NFIFO, 0, IMMED);
553 MOVE(p, MATH0, 0, IFIFOAB2, 0, 4, WAITCOMP | IMMED);
555 MOVE(p, MATH0, 0, IFIFO, 0, 4, WAITCOMP | IMMED);
559 if (authdata->algtype == PDCP_CIPHER_TYPE_ZUC) {
560 /* Reset ZUCA mode and done interrupt
561 * Note: If it is not done, DECO generate an error: 200031ca
564 LOAD(p, CLRW_CLR_C2MODE, CLRW, 0, 4, IMMED);
565 LOAD(p, CIRQ_ZADI, ICTRL, 0, 4, IMMED);
571 /* Function used when the integrity algorithm is a class 1 CHA so outsnooping
581 static inline int pdcp_sdap_insert_no_snoop_op(
582 struct program *p, bool swap __maybe_unused, struct alginfo *cipherdata,
583 struct alginfo *authdata, unsigned int dir, enum pdcp_sn_size sn_size,
584 unsigned char era_2_sw_hfn_ovrd __maybe_unused,
585 enum pdb_type_e pdb_type)
587 uint32_t offset = 0, length = 0, sn_mask = 0;
588 uint32_t cipher_alg_op = 0;
589 uint32_t cipher_alg_aai = 0;
590 int hfn_bearer_dir_offset_in_descbuf =
591 (pdb_type == PDCP_PDB_TYPE_FULL_PDB) ?
592 FULL_PDB_DESCBUF_HFN_BEARER_DIR_OFFSET :
593 REDUCED_PDB_DESCBUF_HFN_BEARER_DIR_OFFSET;
595 if (authdata->algtype == PDCP_CIPHER_TYPE_ZUC) {
596 if (rta_sec_era < RTA_SEC_ERA_5) {
597 pr_err("Invalid era for selected algorithm\n");
602 if (pdcp_sdap_get_sn_parameters(sn_size, swap, &offset, &length,
606 SEQLOAD(p, MATH0, offset, length, 0);
607 JUMP(p, 1, LOCAL_JUMP, ALL_TRUE, CALM);
611 ((swap == true) ? MATH_FUN_RSHIFT : MATH_FUN_LSHIFT),
612 SDAP_BITS_SIZE, MATH1, 8, 0);
613 MATHB(p, MATH1, AND, sn_mask, MATH1, 8, IFB | IMMED2);
615 MATHB(p, MATH0, AND, sn_mask, MATH1, 8, IFB | IMMED2);
618 MATHB(p, MATH1, SHLD, MATH1, MATH1, 8, 0);
619 MOVEB(p, DESCBUF, hfn_bearer_dir_offset_in_descbuf,
620 MATH2, 0, 0x08, WAITCOMP | IMMED);
621 MATHB(p, MATH1, OR, MATH2, MATH2, 8, 0);
623 SEQSTORE(p, MATH0, offset, length, 0);
625 if (dir == OP_TYPE_ENCAP_PROTOCOL) {
626 /* Load authentication key */
627 KEY(p, KEY1, authdata->key_enc_flags, authdata->key,
628 authdata->keylen, INLINE_KEY(authdata));
630 /* Set the iv for AES authentication */
631 MOVEB(p, MATH2, 0, IFIFOAB1, 0, 8, IMMED);
633 /* Pass the header */
634 MOVEB(p, MATH0, offset, IFIFOAB1, 0, length, IMMED);
636 /* Configure variable size for I/O */
637 MATHB(p, SEQINSZ, SUB, ZERO, VSEQINSZ, 4, 0);
638 MATHB(p, VSEQINSZ, ADD, PDCP_MAC_I_LEN, VSEQOUTSZ, 4, IMMED2);
640 /* Perform the authentication */
641 ALG_OPERATION(p, OP_ALG_ALGSEL_AES, OP_ALG_AAI_CMAC,
642 OP_ALG_AS_INITFINAL, ICV_CHECK_DISABLE, DIR_DEC);
644 /* Configure the read of data */
645 SEQFIFOLOAD(p, MSG1, 0, VLF | LAST1 | FLUSH1);
647 /* Save the ICV generated */
648 MOVEB(p, CONTEXT1, 0, MATH3, 0, 4, WAITCOMP | IMMED);
650 /* The CHA will be reused so we need to clear it */
651 LOAD(p, CLRW_RESET_CLS1_CHA |
659 /* Load confidentiality key */
660 KEY(p, KEY1, cipherdata->key_enc_flags, cipherdata->key,
661 cipherdata->keylen, INLINE_KEY(cipherdata));
663 /* Load the IV for ciphering */
664 if (cipherdata->algtype == PDCP_CIPHER_TYPE_AES) {
665 MOVEB(p, MATH2, 0, CONTEXT1, 16, 8, IMMED);
666 cipher_alg_op = OP_ALG_ALGSEL_AES;
667 cipher_alg_aai = OP_ALG_AAI_CTR;
668 } else if (cipherdata->algtype == PDCP_CIPHER_TYPE_ZUC) {
669 /* Set the IV for the confidentiality CHA */
670 MOVEB(p, MATH2, 0, CONTEXT1, 0, 8, IMMED);
671 cipher_alg_op = OP_ALG_ALGSEL_ZUCE;
672 cipher_alg_aai = OP_ALG_AAI_F8;
673 } else if (cipherdata->algtype == PDCP_CIPHER_TYPE_SNOW) {
674 /* Set the IV for the confidentiality CHA */
675 MOVEB(p, MATH2, 0, CONTEXT1, 0, 8, IMMED);
676 cipher_alg_op = OP_ALG_ALGSEL_SNOW_F8;
677 cipher_alg_aai = OP_ALG_AAI_F8;
680 /* Rewind the pointer on input data to reread it */
681 SEQINPTR(p, 0, PDCP_NULL_MAX_FRAME_LEN, RTO);
683 /* Define the ciphering operation */
684 ALG_OPERATION(p, cipher_alg_op, cipher_alg_aai,
685 OP_ALG_AS_INITFINAL, ICV_CHECK_DISABLE, DIR_ENC);
687 /* Define the data to write */
688 SEQFIFOSTORE(p, MSG, 0, 0, VLF);
690 /* Skip the header which does not need to be encrypted */
691 SEQFIFOLOAD(p, SKIP, length, 0);
693 /* Read the rest of the data */
694 SEQFIFOLOAD(p, MSG1, 0, VLF);
696 /* Send the ICV stored in MATH3 for encryption */
697 MOVEB(p, MATH3, 0, IFIFOAB1, 0, 4, LAST1 | FLUSH1 | IMMED);
699 /* Load the IV for ciphering */
700 if (cipherdata->algtype == PDCP_CIPHER_TYPE_AES) {
701 MOVEB(p, MATH2, 0, CONTEXT1, 16, 8, IMMED);
702 cipher_alg_op = OP_ALG_ALGSEL_AES;
703 cipher_alg_aai = OP_ALG_AAI_CTR;
704 } else if (cipherdata->algtype == PDCP_CIPHER_TYPE_ZUC) {
705 /* Set the IV for the confidentiality CHA */
706 MOVEB(p, MATH2, 0, CONTEXT1, 0, 8, IMMED);
707 cipher_alg_op = OP_ALG_ALGSEL_ZUCE;
708 cipher_alg_aai = OP_ALG_AAI_F8;
709 } else if (cipherdata->algtype == PDCP_CIPHER_TYPE_SNOW) {
710 /* Set the IV for the confidentiality CHA */
711 MOVEB(p, MATH2, 0, CONTEXT1, 0, 8, IMMED);
712 cipher_alg_op = OP_ALG_ALGSEL_SNOW_F8;
713 cipher_alg_aai = OP_ALG_AAI_F8;
715 MOVEB(p, MATH2, 0, CONTEXT2, 0, 8, IMMED);
717 /* Read all the data */
718 MATHB(p, SEQINSZ, SUB, ZERO, VSEQINSZ, 4, 0);
720 /* Do not write back the ICV */
721 MATHB(p, SEQINSZ, SUB, PDCP_MAC_I_LEN, VSEQOUTSZ, 4, IMMED2);
723 /* Load the key for ciphering */
724 KEY(p, KEY1, cipherdata->key_enc_flags, cipherdata->key,
725 cipherdata->keylen, INLINE_KEY(cipherdata));
727 /* Write all the data */
728 SEQFIFOSTORE(p, MSG, 0, 0, VLF | CONT);
730 /* Define the ciphering algorithm */
731 ALG_OPERATION(p, cipher_alg_op, cipher_alg_aai,
732 OP_ALG_AS_INITFINAL, ICV_CHECK_DISABLE, DIR_DEC);
734 /* Read all the data */
735 SEQFIFOLOAD(p, MSG1, 0, VLF | LAST1 | FLUSH1);
737 /* Save the ICV which is stalling in output FIFO to MATH3 */
738 MOVEB(p, OFIFO, 0, MATH3, 0, 4, IMMED);
740 /* Reset class 1 CHA */
741 LOAD(p, CLRW_RESET_CLS1_CHA |
749 /* Load the key for authentcation */
750 KEY(p, KEY1, authdata->key_enc_flags, authdata->key,
751 authdata->keylen, INLINE_KEY(authdata));
753 /* Start a new sequence */
754 SEQINPTR(p, 0, 0, SOP);
756 /* Define the operation to verify the ICV */
757 ALG_OPERATION(p, OP_ALG_ALGSEL_AES, OP_ALG_AAI_CMAC,
758 OP_ALG_AS_INITFINAL, ICV_CHECK_ENABLE, DIR_DEC);
760 /* Set the variable size input */
761 MATHB(p, SEQINSZ, SUB, ZERO, VSEQINSZ, 4, 0);
763 MOVE(p, CONTEXT2, 0, IFIFOAB1, 0, 8, IMMED);
765 SEQFIFOLOAD(p, MSG1, 0, VLF | LAST1 | FLUSH1);
767 /* Define an NFIFO entry to load the ICV saved */
768 LOAD(p, NFIFOENTRY_STYPE_ALTSOURCE |
769 NFIFOENTRY_DEST_CLASS1 |
770 NFIFOENTRY_DTYPE_ICV |
772 NFIFOENTRY_FC1 | 4, NFIFO_SZL, 0, 4, IMMED);
775 MOVEB(p, MATH3, 0, ALTSOURCE, 0, 4, IMMED);
782 pdcp_sdap_insert_cplane_null_op(struct program *p,
783 bool swap __maybe_unused,
784 struct alginfo *cipherdata,
785 struct alginfo *authdata,
787 enum pdcp_sn_size sn_size,
788 unsigned char era_2_sw_hfn_ovrd,
789 enum pdb_type_e pdb_type __maybe_unused)
791 return pdcp_insert_cplane_int_only_op(p, swap, cipherdata, authdata,
792 dir, sn_size, era_2_sw_hfn_ovrd);
796 pdcp_sdap_insert_cplane_int_only_op(struct program *p,
797 bool swap __maybe_unused,
798 struct alginfo *cipherdata,
799 struct alginfo *authdata,
801 enum pdcp_sn_size sn_size,
802 unsigned char era_2_sw_hfn_ovrd,
803 enum pdb_type_e pdb_type __maybe_unused)
805 return pdcp_insert_cplane_int_only_op(p, swap, cipherdata, authdata,
806 dir, sn_size, era_2_sw_hfn_ovrd);
809 static int pdcp_sdap_insert_with_int_op(
810 struct program *p, bool swap __maybe_unused, struct alginfo *cipherdata,
811 struct alginfo *authdata, enum pdcp_sn_size sn_size,
812 unsigned char era_2_sw_hfn_ovrd, unsigned int dir,
813 enum pdb_type_e pdb_type)
816 *pdcp_cp_fp[PDCP_CIPHER_TYPE_INVALID][PDCP_AUTH_TYPE_INVALID])(
817 struct program *, bool swap, struct alginfo *, struct alginfo *,
818 unsigned int, enum pdcp_sn_size,
819 unsigned char __maybe_unused, enum pdb_type_e pdb_type) = {
822 pdcp_sdap_insert_cplane_null_op, /* NULL */
823 pdcp_sdap_insert_cplane_int_only_op, /* SNOW f9 */
824 pdcp_sdap_insert_cplane_int_only_op, /* AES CMAC */
825 pdcp_sdap_insert_cplane_int_only_op /* ZUC-I */
829 pdcp_sdap_insert_enc_only_op, /* NULL */
830 pdcp_sdap_insert_snoop_op, /* SNOW f9 */
831 pdcp_sdap_insert_no_snoop_op, /* AES CMAC */
832 pdcp_sdap_insert_snoop_op /* ZUC-I */
836 pdcp_sdap_insert_enc_only_op, /* NULL */
837 pdcp_sdap_insert_snoop_op, /* SNOW f9 */
838 pdcp_sdap_insert_no_snoop_op, /* AES CMAC */
839 pdcp_sdap_insert_snoop_op /* ZUC-I */
843 pdcp_sdap_insert_enc_only_op, /* NULL */
844 pdcp_sdap_insert_snoop_op, /* SNOW f9 */
845 pdcp_sdap_insert_no_snoop_op, /* AES CMAC */
846 pdcp_sdap_insert_snoop_op /* ZUC-I */
851 err = pdcp_cp_fp[cipherdata->algtype]
852 [authdata->algtype](p, swap, cipherdata, authdata, dir,
853 sn_size, era_2_sw_hfn_ovrd, pdb_type);
861 cnstr_shdsc_pdcp_sdap_u_plane(uint32_t *descbuf,
864 enum pdcp_sn_size sn_size,
866 unsigned short bearer,
867 unsigned short direction,
868 uint32_t hfn_threshold,
869 struct alginfo *cipherdata,
870 struct alginfo *authdata,
871 unsigned char era_2_sw_hfn_ovrd,
875 struct program *p = &prg;
877 enum pdb_type_e pdb_type;
878 static enum rta_share_type
879 desc_share[PDCP_CIPHER_TYPE_INVALID][PDCP_AUTH_TYPE_INVALID] = {
883 SHR_ALWAYS, /* SNOW f9 */
884 SHR_ALWAYS, /* AES CMAC */
885 SHR_ALWAYS /* ZUC-I */
889 SHR_ALWAYS, /* NULL */
890 SHR_ALWAYS, /* SNOW f9 */
891 SHR_WAIT, /* AES CMAC */
896 SHR_ALWAYS, /* NULL */
897 SHR_ALWAYS, /* SNOW f9 */
898 SHR_ALWAYS, /* AES CMAC */
903 SHR_ALWAYS, /* NULL */
904 SHR_WAIT, /* SNOW f9 */
905 SHR_WAIT, /* AES CMAC */
912 /* Check HFN override for ERA 2 */
913 if (rta_sec_era != RTA_SEC_ERA_2 && era_2_sw_hfn_ovrd) {
914 pr_err("Cannot select SW HFN ovrd for other era than 2");
918 /* Check the confidentiality algorithm is supported by the code */
919 switch (cipherdata->algtype) {
920 case PDCP_CIPHER_TYPE_NULL:
921 case PDCP_CIPHER_TYPE_SNOW:
922 case PDCP_CIPHER_TYPE_AES:
923 case PDCP_CIPHER_TYPE_ZUC:
926 pr_err("Cipher algorithm not supported: %d\n",
927 cipherdata->algtype);
931 /* Check the authentication algorithm is supported by the code */
933 switch (authdata->algtype) {
934 case PDCP_AUTH_TYPE_NULL:
935 case PDCP_AUTH_TYPE_SNOW:
936 case PDCP_AUTH_TYPE_AES:
937 case PDCP_AUTH_TYPE_ZUC:
940 pr_err("Auth algorithm not supported: %d\n",
946 /* Check the Sequence Number size is supported by the code */
950 case PDCP_SN_SIZE_12:
951 case PDCP_SN_SIZE_15:
952 case PDCP_SN_SIZE_18:
955 pr_err("SN size not supported: %d\n", sn_size);
959 /* Check that we are not performing ZUC algo on old platforms */
960 if (cipherdata->algtype == PDCP_CIPHER_TYPE_ZUC &&
961 rta_sec_era < RTA_SEC_ERA_5) {
962 pr_err("ZUC algorithm not supported for era: %d\n",
967 /* Initialize the program */
968 PROGRAM_CNTXT_INIT(p, descbuf, 0);
971 PROGRAM_SET_BSWAP(p);
974 PROGRAM_SET_36BIT_ADDR(p);
976 /* Select the shared descriptor sharing mode */
978 SHR_HDR(p, desc_share[cipherdata->algtype][authdata->algtype],
981 SHR_HDR(p, SHR_ALWAYS, 0, 0);
983 /* Construct the PDB */
984 pdb_type = cnstr_pdcp_u_plane_pdb(p, sn_size, hfn, bearer, direction,
985 hfn_threshold, cipherdata, authdata);
986 if (pdb_type == PDCP_PDB_TYPE_INVALID) {
987 pr_err("Error creating PDCP UPlane PDB\n");
990 SET_LABEL(p, pdb_end);
992 /* Inser the HFN override operation */
993 err = insert_hfn_ov_op(p, sn_size, pdb_type, era_2_sw_hfn_ovrd);
997 /* Create the descriptor */
999 if (cipherdata->algtype == PDCP_CIPHER_TYPE_NULL) {
1000 insert_copy_frame_op(p, cipherdata,
1001 OP_TYPE_ENCAP_PROTOCOL);
1003 err = pdcp_sdap_insert_no_int_op(p, swap, cipherdata,
1007 pr_err("Fail pdcp_sdap_insert_no_int_op\n");
1012 err = pdcp_sdap_insert_with_int_op(p, swap, cipherdata,
1015 caps_mode, pdb_type);
1017 pr_err("Fail pdcp_sdap_insert_with_int_op\n");
1022 PATCH_HDR(p, 0, pdb_end);
1024 return PROGRAM_FINALIZE(p);
1028 * cnstr_shdsc_pdcp_sdap_u_plane_encap - Function for creating a PDCP-SDAP
1029 * User Plane encapsulation descriptor.
1030 * @descbuf: pointer to buffer for descriptor construction
1031 * @ps: if 36/40bit addressing is desired, this parameter must be true
1032 * @swap: must be true when core endianness doesn't match SEC endianness
1033 * @sn_size: selects Sequence Number Size: 7/12/15 bits
1034 * @hfn: starting Hyper Frame Number to be used together with the SN from the
1036 * @bearer: radio bearer ID
1037 * @direction: the direction of the PDCP frame (UL/DL)
1038 * @hfn_threshold: HFN value that once reached triggers a warning from SEC that
1039 * keys should be renegotiated at the earliest convenience.
1040 * @cipherdata: pointer to block cipher transform definitions
1041 * Valid algorithm values are those from cipher_type_pdcp enum.
1042 * @era_2_sw_hfn_ovrd: if software HFN override mechanism is desired for
1043 * this descriptor. Note: Can only be used for
1046 * Return: size of descriptor written in words or negative number on error.
1047 * Once the function returns, the value of this parameter can be used
1048 * for reclaiming the space that wasn't used for the descriptor.
1050 * Note: descbuf must be large enough to contain a full 256 byte long
1051 * descriptor; after the function returns, by subtracting the actual number of
1052 * bytes used, the user can reuse the remaining buffer space for other purposes.
1055 cnstr_shdsc_pdcp_sdap_u_plane_encap(uint32_t *descbuf,
1058 enum pdcp_sn_size sn_size,
1060 unsigned short bearer,
1061 unsigned short direction,
1062 uint32_t hfn_threshold,
1063 struct alginfo *cipherdata,
1064 struct alginfo *authdata,
1065 unsigned char era_2_sw_hfn_ovrd)
1067 return cnstr_shdsc_pdcp_sdap_u_plane(descbuf, ps, swap, sn_size,
1068 hfn, bearer, direction, hfn_threshold, cipherdata,
1069 authdata, era_2_sw_hfn_ovrd, OP_TYPE_ENCAP_PROTOCOL);
1073 * cnstr_shdsc_pdcp_sdap_u_plane_decap - Function for creating a PDCP-SDAP
1074 * User Plane decapsulation descriptor.
1075 * @descbuf: pointer to buffer for descriptor construction
1076 * @ps: if 36/40bit addressing is desired, this parameter must be true
1077 * @swap: must be true when core endianness doesn't match SEC endianness
1078 * @sn_size: selects Sequence Number Size: 7/12/15 bits
1079 * @hfn: starting Hyper Frame Number to be used together with the SN from the
1081 * @bearer: radio bearer ID
1082 * @direction: the direction of the PDCP frame (UL/DL)
1083 * @hfn_threshold: HFN value that once reached triggers a warning from SEC that
1084 * keys should be renegotiated at the earliest convenience.
1085 * @cipherdata: pointer to block cipher transform definitions
1086 * Valid algorithm values are those from cipher_type_pdcp enum.
1087 * @era_2_sw_hfn_ovrd: if software HFN override mechanism is desired for
1088 * this descriptor. Note: Can only be used for
1091 * Return: size of descriptor written in words or negative number on error.
1092 * Once the function returns, the value of this parameter can be used
1093 * for reclaiming the space that wasn't used for the descriptor.
1095 * Note: descbuf must be large enough to contain a full 256 byte long
1096 * descriptor; after the function returns, by subtracting the actual number of
1097 * bytes used, the user can reuse the remaining buffer space for other purposes.
1100 cnstr_shdsc_pdcp_sdap_u_plane_decap(uint32_t *descbuf,
1103 enum pdcp_sn_size sn_size,
1105 unsigned short bearer,
1106 unsigned short direction,
1107 uint32_t hfn_threshold,
1108 struct alginfo *cipherdata,
1109 struct alginfo *authdata,
1110 unsigned char era_2_sw_hfn_ovrd)
1112 return cnstr_shdsc_pdcp_sdap_u_plane(descbuf, ps, swap, sn_size, hfn,
1113 bearer, direction, hfn_threshold, cipherdata, authdata,
1114 era_2_sw_hfn_ovrd, OP_TYPE_DECAP_PROTOCOL);
1117 #endif /* __DESC_SDAP_H__ */