1 /* SPDX-License-Identifier: BSD-3-Clause or GPL-2.0+ 2 * Copyright 2008-2013 Freescale Semiconductor, Inc. 3 * Copyright 2019-2020 NXP 4 */ 5 6 #ifndef __DESC_PDCP_H__ 7 #define __DESC_PDCP_H__ 8 9 #include "rta.h" 10 #include "common.h" 11 12 /** 13 * DOC: PDCP Shared Descriptor Constructors 14 * 15 * Shared descriptors for PDCP protocol. 16 */ 17 18 /** 19 * PDCP_NULL_MAX_FRAME_LEN - The maximum frame frame length that is supported by 20 * PDCP NULL protocol. 21 */ 22 #define PDCP_NULL_MAX_FRAME_LEN 0x00002FFF 23 24 /** 25 * PDCP_MAC_I_LEN - The length of the MAC-I for PDCP protocol operation 26 */ 27 #define PDCP_MAC_I_LEN 0x00000004 28 29 /** 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. 33 */ 34 #define PDCP_MAX_FRAME_LEN_STATUS 0xF1 35 36 /** 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 41 * (7/12/15 bits). 42 */ 43 #define PDCP_C_PLANE_SN_MASK 0x1F000000 44 #define PDCP_C_PLANE_SN_MASK_BE 0x0000001F 45 46 /** 47 * PDCP_7BIT_SN_MASK - This mask is used in the PDCP descriptors for 48 * extracting the sequence number (SN) from the 49 * PDCP User Plane header. 50 */ 51 #define PDCP_7BIT_SN_MASK 0x7F000000 52 #define PDCP_7BIT_SN_MASK_BE 0x0000007F 53 54 /** 55 * PDCP_12BIT_SN_MASK - This mask is used in the PDCP descriptors for 56 * extracting the sequence number (SN) from the 57 * PDCP User Plane header. 58 */ 59 #define PDCP_12BIT_SN_MASK 0xFF0F0000 60 #define PDCP_12BIT_SN_MASK_BE 0x00000FFF 61 62 /** 63 * PDCP_U_PLANE_15BIT_SN_MASK - This mask is used in the PDCP descriptors for 64 * extracting the sequence number (SN) from the 65 * PDCP User Plane header. For PDCP Control Plane, 66 * the SN is constant (5 bits) as opposed to PDCP 67 * Data Plane (7/12/15 bits). 68 */ 69 #define PDCP_U_PLANE_15BIT_SN_MASK 0xFF7F0000 70 #define PDCP_U_PLANE_15BIT_SN_MASK_BE 0x00007FFF 71 72 /** 73 * PDCP_U_PLANE_18BIT_SN_MASK - This mask is used in the PDCP descriptors for 74 * extracting the sequence number (SN) from the 75 * PDCP User Plane header. 76 */ 77 #define PDCP_U_PLANE_18BIT_SN_MASK 0xFFFF0300 78 #define PDCP_U_PLANE_18BIT_SN_MASK_BE 0x0003FFFF 79 80 /** 81 * PDCP_BEARER_MASK - This mask is used masking out the bearer for PDCP 82 * processing with SNOW f9 in LTE. 83 * 84 * The value on which this mask is applied is formatted as below: 85 * Count-C (32 bit) | Bearer (5 bit) | Direction (1 bit) | 0 (26 bits) 86 * 87 * Applying this mask is done for creating the upper 64 bits of the IV needed 88 * for SNOW f9. 89 * 90 * The lower 32 bits of the mask are used for masking the direction for AES 91 * CMAC IV. 92 */ 93 #define PDCP_BEARER_MASK 0x00000004FFFFFFFFull 94 #define PDCP_BEARER_MASK_BE 0xFFFFFFFF04000000ull 95 96 /** 97 * PDCP_DIR_MASK - This mask is used masking out the direction for PDCP 98 * processing with SNOW f9 in LTE. 99 * 100 * The value on which this mask is applied is formatted as below: 101 * Bearer (5 bit) | Direction (1 bit) | 0 (26 bits) 102 * 103 * Applying this mask is done for creating the lower 32 bits of the IV needed 104 * for SNOW f9. 105 * 106 * The upper 32 bits of the mask are used for masking the direction for AES 107 * CMAC IV. 108 */ 109 #define PDCP_DIR_MASK 0x00000000000000F8ull 110 #define PDCP_DIR_MASK_BE 0xF800000000000000ull 111 112 /** 113 * PDCP_NULL_INT_MAC_I_VAL - The value of the PDCP PDU MAC-I in case NULL 114 * integrity is used. 115 */ 116 117 #define PDCP_NULL_INT_MAC_I_VAL 0x00000000 118 119 /** 120 * PDCP_NULL_INT_ICV_CHECK_FAILED_STATUS - The status used to report ICV check 121 * failed in case of NULL integrity 122 * Control Plane processing. 123 */ 124 #define PDCP_NULL_INT_ICV_CHECK_FAILED_STATUS 0x0A 125 /** 126 * PDCP_DPOVRD_HFN_OV_EN - Value to be used in the FD status/cmd field to 127 * indicate the HFN override mechanism is active for the 128 * frame. 129 */ 130 #define PDCP_DPOVRD_HFN_OV_EN 0x80000000 131 132 /** 133 * PDCP_P4080REV2_HFN_OV_BUFLEN - The length in bytes of the supplementary space 134 * that must be provided by the user at the 135 * beginning of the input frame buffer for 136 * P4080 REV 2. 137 * 138 * The format of the frame buffer is the following: 139 * 140 * |<---PDCP_P4080REV2_HFN_OV_BUFLEN-->| 141 * //===================================||============||==============\\ 142 * || PDCP_DPOVRD_HFN_OV_EN | HFN value || PDCP Header|| PDCP Payload || 143 * \\===================================||============||==============// 144 * 145 * If HFN override mechanism is not desired, then the MSB of the first 4 bytes 146 * must be set to 0b. 147 */ 148 #define PDCP_P4080REV2_HFN_OV_BUFLEN 4 149 150 /** 151 * enum cipher_type_pdcp - Type selectors for cipher types in PDCP protocol OP 152 * instructions. 153 * @PDCP_CIPHER_TYPE_NULL: NULL 154 * @PDCP_CIPHER_TYPE_SNOW: SNOW F8 155 * @PDCP_CIPHER_TYPE_AES: AES 156 * @PDCP_CIPHER_TYPE_ZUC: ZUCE 157 * @PDCP_CIPHER_TYPE_INVALID: invalid option 158 */ 159 enum cipher_type_pdcp { 160 PDCP_CIPHER_TYPE_NULL, 161 PDCP_CIPHER_TYPE_SNOW, 162 PDCP_CIPHER_TYPE_AES, 163 PDCP_CIPHER_TYPE_ZUC, 164 PDCP_CIPHER_TYPE_INVALID 165 }; 166 167 /** 168 * enum auth_type_pdcp - Type selectors for integrity types in PDCP protocol OP 169 * instructions. 170 * @PDCP_AUTH_TYPE_NULL: NULL 171 * @PDCP_AUTH_TYPE_SNOW: SNOW F9 172 * @PDCP_AUTH_TYPE_AES: AES CMAC 173 * @PDCP_AUTH_TYPE_ZUC: ZUCA 174 * @PDCP_AUTH_TYPE_INVALID: invalid option 175 */ 176 enum auth_type_pdcp { 177 PDCP_AUTH_TYPE_NULL, 178 PDCP_AUTH_TYPE_SNOW, 179 PDCP_AUTH_TYPE_AES, 180 PDCP_AUTH_TYPE_ZUC, 181 PDCP_AUTH_TYPE_INVALID 182 }; 183 184 /** 185 * enum pdcp_dir - Type selectors for direction for PDCP protocol 186 * @PDCP_DIR_UPLINK: uplink direction 187 * @PDCP_DIR_DOWNLINK: downlink direction 188 * @PDCP_DIR_INVALID: invalid option 189 */ 190 enum pdcp_dir { 191 PDCP_DIR_UPLINK = 0, 192 PDCP_DIR_DOWNLINK = 1, 193 PDCP_DIR_INVALID 194 }; 195 196 /** 197 * enum pdcp_plane - PDCP domain selectors 198 * @PDCP_CONTROL_PLANE: Control Plane 199 * @PDCP_DATA_PLANE: Data Plane 200 * @PDCP_SHORT_MAC: Short MAC 201 */ 202 enum pdcp_plane { 203 PDCP_CONTROL_PLANE, 204 PDCP_DATA_PLANE, 205 PDCP_SHORT_MAC 206 }; 207 208 /** 209 * enum pdcp_sn_size - Sequence Number Size selectors for PDCP protocol 210 * @PDCP_SN_SIZE_5: 5bit sequence number 211 * @PDCP_SN_SIZE_7: 7bit sequence number 212 * @PDCP_SN_SIZE_12: 12bit sequence number 213 * @PDCP_SN_SIZE_15: 15bit sequence number 214 * @PDCP_SN_SIZE_18: 18bit sequence number 215 */ 216 enum pdcp_sn_size { 217 PDCP_SN_SIZE_5 = 5, 218 PDCP_SN_SIZE_7 = 7, 219 PDCP_SN_SIZE_12 = 12, 220 PDCP_SN_SIZE_15 = 15, 221 PDCP_SN_SIZE_18 = 18 222 }; 223 224 /* 225 * PDCP Control Plane Protocol Data Blocks 226 */ 227 #define PDCP_C_PLANE_PDB_HFN_SHIFT 5 228 #define PDCP_C_PLANE_PDB_BEARER_SHIFT 27 229 #define PDCP_C_PLANE_PDB_DIR_SHIFT 26 230 #define PDCP_C_PLANE_PDB_HFN_THR_SHIFT 5 231 232 #define PDCP_U_PLANE_PDB_OPT_SHORT_SN 0x2 233 #define PDCP_U_PLANE_PDB_OPT_15B_SN 0x4 234 #define PDCP_U_PLANE_PDB_OPT_18B_SN 0x6 235 #define PDCP_U_PLANE_PDB_SHORT_SN_HFN_SHIFT 7 236 #define PDCP_U_PLANE_PDB_LONG_SN_HFN_SHIFT 12 237 #define PDCP_U_PLANE_PDB_15BIT_SN_HFN_SHIFT 15 238 #define PDCP_U_PLANE_PDB_18BIT_SN_HFN_SHIFT 18 239 #define PDCP_U_PLANE_PDB_BEARER_SHIFT 27 240 #define PDCP_U_PLANE_PDB_DIR_SHIFT 26 241 #define PDCP_U_PLANE_PDB_SHORT_SN_HFN_THR_SHIFT 7 242 #define PDCP_U_PLANE_PDB_LONG_SN_HFN_THR_SHIFT 12 243 #define PDCP_U_PLANE_PDB_15BIT_SN_HFN_THR_SHIFT 15 244 #define PDCP_U_PLANE_PDB_18BIT_SN_HFN_THR_SHIFT 18 245 246 struct pdcp_pdb { 247 union { 248 uint32_t opt; 249 uint32_t rsvd; 250 } opt_res; 251 uint32_t hfn_res; /* HyperFrame number,(27, 25 or 21 bits), 252 * left aligned & right-padded with zeros. 253 */ 254 uint32_t bearer_dir_res;/* Bearer(5 bits), packet direction (1 bit), 255 * left aligned & right-padded with zeros. 256 */ 257 uint32_t hfn_thr_res; /* HyperFrame number threshold (27, 25 or 21 258 * bits), left aligned & right-padded with 259 * zeros. 260 */ 261 }; 262 263 /* 264 * PDCP internal PDB types 265 */ 266 enum pdb_type_e { 267 PDCP_PDB_TYPE_NO_PDB, 268 PDCP_PDB_TYPE_FULL_PDB, 269 PDCP_PDB_TYPE_REDUCED_PDB, 270 PDCP_PDB_TYPE_INVALID 271 }; 272 273 /** 274 * rta_inline_pdcp_query() - Provide indications if a key can be passed as 275 * immediate data or shall be referenced in a 276 * shared descriptor. 277 * Return: 0 if data can be inlined or 1 if referenced. 278 */ 279 static inline int 280 rta_inline_pdcp_query(enum auth_type_pdcp auth_alg, 281 enum cipher_type_pdcp cipher_alg, 282 enum pdcp_sn_size sn_size, 283 int8_t hfn_ovd) 284 { 285 /** 286 * Shared Descriptors for some of the cases does not fit in the 287 * MAX_DESC_SIZE of the descriptor especially when non-protocol 288 * descriptors are formed as in 18bit cases and when HFN override 289 * is enabled as 2 extra words are added in the job descriptor. 290 * The cases which exceed are for RTA_SEC_ERA=8 and HFN override 291 * enabled and 18bit uplane and either of following Algo combinations. 292 * - SNOW-AES 293 * - AES-SNOW 294 * - SNOW-SNOW 295 * - ZUC-SNOW 296 * 297 * We cannot make inline for all cases, as this will impact performance 298 * due to extra memory accesses for the keys. 299 */ 300 if ((rta_sec_era == RTA_SEC_ERA_8) && hfn_ovd && 301 (sn_size == PDCP_SN_SIZE_18) && 302 ((cipher_alg == PDCP_CIPHER_TYPE_SNOW && 303 auth_alg == PDCP_AUTH_TYPE_AES) || 304 (cipher_alg == PDCP_CIPHER_TYPE_AES && 305 auth_alg == PDCP_AUTH_TYPE_SNOW) || 306 (cipher_alg == PDCP_CIPHER_TYPE_SNOW && 307 auth_alg == PDCP_AUTH_TYPE_SNOW) || 308 (cipher_alg == PDCP_CIPHER_TYPE_ZUC && 309 auth_alg == PDCP_AUTH_TYPE_SNOW))) { 310 311 return 1; 312 } 313 314 return 0; 315 } 316 317 /* 318 * Function for appending the portion of a PDCP Control Plane shared descriptor 319 * which performs NULL encryption and integrity (i.e. copies the input frame 320 * to the output frame, appending 32 bits of zeros at the end (MAC-I for 321 * NULL integrity). 322 */ 323 static inline int 324 pdcp_insert_cplane_null_op(struct program *p, 325 bool swap __maybe_unused, 326 struct alginfo *cipherdata __maybe_unused, 327 struct alginfo *authdata __maybe_unused, 328 unsigned int dir, 329 enum pdcp_sn_size sn_size __maybe_unused, 330 unsigned char era_2_sw_hfn_ovrd __maybe_unused) 331 { 332 LABEL(local_offset); 333 REFERENCE(move_cmd_read_descbuf); 334 REFERENCE(move_cmd_write_descbuf); 335 336 if (rta_sec_era > RTA_SEC_ERA_2) { 337 MATHB(p, SEQINSZ, ADD, ZERO, VSEQINSZ, 4, 0); 338 if (dir == OP_TYPE_ENCAP_PROTOCOL) 339 MATHB(p, SEQINSZ, ADD, PDCP_MAC_I_LEN, VSEQOUTSZ, 4, 340 IMMED2); 341 else 342 MATHB(p, SEQINSZ, SUB, PDCP_MAC_I_LEN, VSEQOUTSZ, 4, 343 IMMED2); 344 } else { 345 MATHB(p, SEQINSZ, ADD, ONE, VSEQINSZ, 4, 0); 346 MATHB(p, VSEQINSZ, SUB, ONE, VSEQINSZ, 4, 0); 347 348 if (dir == OP_TYPE_ENCAP_PROTOCOL) { 349 MATHB(p, SEQINSZ, ADD, PDCP_MAC_I_LEN, VSEQOUTSZ, 4, 350 IMMED2); 351 MATHB(p, VSEQINSZ, SUB, ONE, MATH0, 4, 0); 352 } else { 353 MATHB(p, VSEQINSZ, SUB, PDCP_MAC_I_LEN, VSEQINSZ, 4, 354 IMMED2); 355 MATHB(p, SEQINSZ, SUB, PDCP_MAC_I_LEN, VSEQOUTSZ, 4, 356 IMMED2); 357 MATHB(p, VSEQOUTSZ, SUB, ONE, MATH0, 4, 0); 358 } 359 360 MATHB(p, MATH0, ADD, ONE, MATH0, 4, 0); 361 362 /* 363 * Since MOVELEN is available only starting with 364 * SEC ERA 3, use poor man's MOVELEN: create a MOVE 365 * command dynamically by writing the length from M1 by 366 * OR-ing the command in the M1 register and MOVE the 367 * result into the descriptor buffer. Care must be taken 368 * wrt. the location of the command because of SEC 369 * pipelining. The actual MOVEs are written at the end 370 * of the descriptor due to calculations needed on the 371 * offset in the descriptor for the MOVE command. 372 */ 373 move_cmd_read_descbuf = MOVE(p, DESCBUF, 0, MATH0, 0, 6, 374 IMMED); 375 move_cmd_write_descbuf = MOVE(p, MATH0, 0, DESCBUF, 0, 8, 376 WAITCOMP | IMMED); 377 } 378 MATHB(p, VSEQINSZ, SUB, PDCP_NULL_MAX_FRAME_LEN, NONE, 4, 379 IMMED2); 380 JUMP(p, PDCP_MAX_FRAME_LEN_STATUS, HALT_STATUS, ALL_FALSE, MATH_N); 381 382 if (rta_sec_era > RTA_SEC_ERA_2) { 383 if (dir == OP_TYPE_ENCAP_PROTOCOL) 384 MATHB(p, VSEQINSZ, ADD, ZERO, MATH0, 4, 0); 385 else 386 MATHB(p, VSEQOUTSZ, ADD, ZERO, MATH0, 4, 0); 387 } 388 SEQFIFOSTORE(p, MSG, 0, 0, VLF); 389 SEQFIFOLOAD(p, MSG1, 0, VLF | LAST1 | FLUSH1); 390 391 if (rta_sec_era > RTA_SEC_ERA_2) { 392 MOVE(p, AB1, 0, OFIFO, 0, MATH0, 0); 393 } else { 394 SET_LABEL(p, local_offset); 395 396 /* Shut off automatic Info FIFO entries */ 397 LOAD(p, 0, DCTRL, LDOFF_DISABLE_AUTO_NFIFO, 0, IMMED); 398 /* Placeholder for MOVE command with length from M1 register */ 399 MOVE(p, IFIFOAB1, 0, OFIFO, 0, 0, IMMED); 400 /* Enable automatic Info FIFO entries */ 401 LOAD(p, 0, DCTRL, LDOFF_ENABLE_AUTO_NFIFO, 0, IMMED); 402 } 403 404 if (dir == OP_TYPE_ENCAP_PROTOCOL) { 405 MATHB(p, MATH1, XOR, MATH1, MATH0, 8, 0); 406 MOVE(p, MATH0, 0, OFIFO, 0, 4, IMMED); 407 } 408 409 if (rta_sec_era < RTA_SEC_ERA_3) { 410 PATCH_MOVE(p, move_cmd_read_descbuf, local_offset); 411 PATCH_MOVE(p, move_cmd_write_descbuf, local_offset); 412 } 413 414 return 0; 415 } 416 417 static inline int 418 insert_copy_frame_op(struct program *p, 419 struct alginfo *cipherdata __maybe_unused, 420 unsigned int dir __maybe_unused) 421 { 422 LABEL(local_offset); 423 REFERENCE(move_cmd_read_descbuf); 424 REFERENCE(move_cmd_write_descbuf); 425 426 if (rta_sec_era > RTA_SEC_ERA_2) { 427 MATHB(p, SEQINSZ, ADD, ZERO, VSEQINSZ, 4, 0); 428 MATHB(p, SEQINSZ, ADD, ZERO, VSEQOUTSZ, 4, 0); 429 } else { 430 MATHB(p, SEQINSZ, ADD, ONE, VSEQINSZ, 4, 0); 431 MATHB(p, VSEQINSZ, SUB, ONE, VSEQINSZ, 4, 0); 432 MATHB(p, SEQINSZ, ADD, ONE, VSEQOUTSZ, 4, 0); 433 MATHB(p, VSEQOUTSZ, SUB, ONE, VSEQOUTSZ, 4, 0); 434 MATHB(p, VSEQINSZ, SUB, ONE, MATH0, 4, 0); 435 MATHB(p, MATH0, ADD, ONE, MATH0, 4, 0); 436 437 /* 438 * Since MOVELEN is available only starting with 439 * SEC ERA 3, use poor man's MOVELEN: create a MOVE 440 * command dynamically by writing the length from M1 by 441 * OR-ing the command in the M1 register and MOVE the 442 * result into the descriptor buffer. Care must be taken 443 * wrt. the location of the command because of SEC 444 * pipelining. The actual MOVEs are written at the end 445 * of the descriptor due to calculations needed on the 446 * offset in the descriptor for the MOVE command. 447 */ 448 move_cmd_read_descbuf = MOVE(p, DESCBUF, 0, MATH0, 0, 6, 449 IMMED); 450 move_cmd_write_descbuf = MOVE(p, MATH0, 0, DESCBUF, 0, 8, 451 WAITCOMP | IMMED); 452 } 453 MATHB(p, SEQINSZ, SUB, PDCP_NULL_MAX_FRAME_LEN, NONE, 4, 454 IFB | IMMED2); 455 JUMP(p, PDCP_MAX_FRAME_LEN_STATUS, HALT_STATUS, ALL_FALSE, MATH_N); 456 457 if (rta_sec_era > RTA_SEC_ERA_2) 458 MATHB(p, VSEQINSZ, ADD, ZERO, MATH0, 4, 0); 459 460 SEQFIFOLOAD(p, MSG1, 0, VLF | LAST1 | FLUSH1); 461 if (rta_sec_era > RTA_SEC_ERA_2) { 462 MOVE(p, AB1, 0, OFIFO, 0, MATH0, 0); 463 } else { 464 SET_LABEL(p, local_offset); 465 466 /* Shut off automatic Info FIFO entries */ 467 LOAD(p, 0, DCTRL, LDOFF_DISABLE_AUTO_NFIFO, 0, IMMED); 468 469 /* Placeholder for MOVE command with length from M0 register */ 470 MOVE(p, IFIFOAB1, 0, OFIFO, 0, 0, IMMED); 471 472 /* Enable automatic Info FIFO entries */ 473 LOAD(p, 0, DCTRL, LDOFF_ENABLE_AUTO_NFIFO, 0, IMMED); 474 } 475 476 SEQFIFOSTORE(p, MSG, 0, 0, VLF); 477 478 if (rta_sec_era < RTA_SEC_ERA_3) { 479 PATCH_MOVE(p, move_cmd_read_descbuf, local_offset); 480 PATCH_MOVE(p, move_cmd_write_descbuf, local_offset); 481 } 482 return 0; 483 } 484 485 static inline int 486 pdcp_insert_cplane_int_only_op(struct program *p, 487 bool swap __maybe_unused, 488 struct alginfo *cipherdata __maybe_unused, 489 struct alginfo *authdata, unsigned int dir, 490 enum pdcp_sn_size sn_size, 491 unsigned char era_2_sw_hfn_ovrd) 492 { 493 uint32_t offset = 0, length = 0, sn_mask = 0; 494 495 /* 12 bit SN is only supported for protocol offload case */ 496 if (rta_sec_era >= RTA_SEC_ERA_8 && sn_size == PDCP_SN_SIZE_12) { 497 KEY(p, KEY2, authdata->key_enc_flags, authdata->key, 498 authdata->keylen, INLINE_KEY(authdata)); 499 500 PROTOCOL(p, dir, OP_PCLID_LTE_PDCP_USER_RN, 501 (uint16_t)authdata->algtype); 502 return 0; 503 } 504 505 /* Non-proto is supported only for 5bit cplane and 18bit uplane */ 506 switch (sn_size) { 507 case PDCP_SN_SIZE_5: 508 offset = 7; 509 length = 1; 510 sn_mask = (swap == false) ? PDCP_C_PLANE_SN_MASK : 511 PDCP_C_PLANE_SN_MASK_BE; 512 break; 513 case PDCP_SN_SIZE_18: 514 offset = 5; 515 length = 3; 516 sn_mask = (swap == false) ? PDCP_U_PLANE_18BIT_SN_MASK : 517 PDCP_U_PLANE_18BIT_SN_MASK_BE; 518 break; 519 case PDCP_SN_SIZE_7: 520 case PDCP_SN_SIZE_12: 521 case PDCP_SN_SIZE_15: 522 pr_err("Invalid sn_size for %s\n", __func__); 523 return -ENOTSUP; 524 525 } 526 LABEL(local_offset); 527 REFERENCE(move_cmd_read_descbuf); 528 REFERENCE(move_cmd_write_descbuf); 529 530 switch (authdata->algtype) { 531 case PDCP_AUTH_TYPE_SNOW: 532 /* Insert Auth Key */ 533 KEY(p, KEY2, authdata->key_enc_flags, authdata->key, 534 authdata->keylen, INLINE_KEY(authdata)); 535 SEQLOAD(p, MATH0, offset, length, 0); 536 JUMP(p, 1, LOCAL_JUMP, ALL_TRUE, CALM); 537 538 if (rta_sec_era > RTA_SEC_ERA_2 || 539 (rta_sec_era == RTA_SEC_ERA_2 && 540 era_2_sw_hfn_ovrd == 0)) { 541 SEQINPTR(p, 0, length, RTO); 542 } else { 543 SEQINPTR(p, 0, 5, RTO); 544 SEQFIFOLOAD(p, SKIP, 4, 0); 545 } 546 547 if (swap == false) { 548 MATHB(p, MATH0, AND, sn_mask, MATH1, 8, 549 IFB | IMMED2); 550 MATHB(p, MATH1, SHLD, MATH1, MATH1, 8, 0); 551 552 MOVEB(p, DESCBUF, 8, MATH2, 0, 8, WAITCOMP | IMMED); 553 554 MATHB(p, MATH2, AND, PDCP_BEARER_MASK, MATH2, 8, 555 IMMED2); 556 MOVEB(p, DESCBUF, 0x0C, MATH3, 0, 4, WAITCOMP | IMMED); 557 MATHB(p, MATH3, AND, PDCP_DIR_MASK, MATH3, 8, IMMED2); 558 MATHB(p, MATH1, OR, MATH2, MATH2, 8, 0); 559 MOVEB(p, MATH2, 0, CONTEXT2, 0, 0x0C, WAITCOMP | IMMED); 560 } else { 561 MATHB(p, MATH0, AND, sn_mask, MATH1, 8, 562 IFB | IMMED2); 563 MATHB(p, MATH1, SHLD, MATH1, MATH1, 8, 0); 564 565 MOVE(p, DESCBUF, 8, MATH2, 0, 8, WAITCOMP | IMMED); 566 MATHB(p, MATH2, AND, PDCP_BEARER_MASK_BE, MATH2, 8, 567 IMMED2); 568 569 MOVE(p, DESCBUF, 0x0C, MATH3, 0, 4, WAITCOMP | IMMED); 570 MATHB(p, MATH3, AND, PDCP_DIR_MASK_BE, MATH3, 8, 571 IMMED2); 572 MATHB(p, MATH1, OR, MATH2, MATH2, 8, 0); 573 MOVE(p, MATH2, 0, CONTEXT2, 0, 0x0C, WAITCOMP | IMMED); 574 } 575 576 if (dir == OP_TYPE_DECAP_PROTOCOL) { 577 MATHB(p, SEQINSZ, SUB, PDCP_MAC_I_LEN, MATH1, 4, 578 IMMED2); 579 } else { 580 if (rta_sec_era > RTA_SEC_ERA_2) { 581 MATHB(p, SEQINSZ, SUB, ZERO, MATH1, 4, 582 0); 583 } else { 584 MATHB(p, SEQINSZ, ADD, ONE, MATH1, 4, 585 0); 586 MATHB(p, MATH1, SUB, ONE, MATH1, 4, 587 0); 588 } 589 } 590 591 if (rta_sec_era > RTA_SEC_ERA_2) { 592 MATHB(p, MATH1, SUB, ZERO, VSEQINSZ, 4, 0); 593 MATHB(p, MATH1, SUB, ZERO, VSEQOUTSZ, 4, 0); 594 } else { 595 MATHB(p, ZERO, ADD, MATH1, VSEQINSZ, 4, 0); 596 MATHB(p, ZERO, ADD, MATH1, VSEQOUTSZ, 4, 0); 597 598 /* 599 * Since MOVELEN is available only starting with 600 * SEC ERA 3, use poor man's MOVELEN: create a MOVE 601 * command dynamically by writing the length from M1 by 602 * OR-ing the command in the M1 register and MOVE the 603 * result into the descriptor buffer. Care must be taken 604 * wrt. the location of the command because of SEC 605 * pipelining. The actual MOVEs are written at the end 606 * of the descriptor due to calculations needed on the 607 * offset in the descriptor for the MOVE command. 608 */ 609 move_cmd_read_descbuf = MOVE(p, DESCBUF, 0, MATH1, 0, 6, 610 IMMED); 611 move_cmd_write_descbuf = MOVE(p, MATH1, 0, DESCBUF, 0, 612 8, WAITCOMP | IMMED); 613 } 614 615 SEQFIFOSTORE(p, MSG, 0, 0, VLF); 616 ALG_OPERATION(p, OP_ALG_ALGSEL_SNOW_F9, OP_ALG_AAI_F9, 617 OP_ALG_AS_INITFINAL, 618 dir == OP_TYPE_ENCAP_PROTOCOL ? 619 ICV_CHECK_DISABLE : ICV_CHECK_ENABLE, 620 DIR_ENC); 621 622 if (rta_sec_era > RTA_SEC_ERA_2) { 623 SEQFIFOLOAD(p, MSGINSNOOP, 0, 624 VLF | LAST1 | LAST2 | FLUSH1); 625 MOVE(p, AB1, 0, OFIFO, 0, MATH1, 0); 626 } else { 627 SEQFIFOLOAD(p, MSGINSNOOP, 0, 628 VLF | LAST1 | LAST2 | FLUSH1); 629 SET_LABEL(p, local_offset); 630 631 /* Shut off automatic Info FIFO entries */ 632 LOAD(p, 0, DCTRL, LDOFF_DISABLE_AUTO_NFIFO, 0, IMMED); 633 /* 634 * Placeholder for MOVE command with length from M1 635 * register 636 */ 637 MOVE(p, IFIFOAB1, 0, OFIFO, 0, 0, IMMED); 638 /* Enable automatic Info FIFO entries */ 639 LOAD(p, 0, DCTRL, LDOFF_ENABLE_AUTO_NFIFO, 0, IMMED); 640 } 641 642 if (dir == OP_TYPE_DECAP_PROTOCOL) 643 SEQFIFOLOAD(p, ICV2, 4, LAST2); 644 else 645 SEQSTORE(p, CONTEXT2, 0, 4, 0); 646 647 break; 648 649 case PDCP_AUTH_TYPE_AES: 650 /* Insert Auth Key */ 651 KEY(p, KEY1, authdata->key_enc_flags, authdata->key, 652 authdata->keylen, INLINE_KEY(authdata)); 653 SEQLOAD(p, MATH0, offset, length, 0); 654 JUMP(p, 1, LOCAL_JUMP, ALL_TRUE, CALM); 655 if (rta_sec_era > RTA_SEC_ERA_2 || 656 (rta_sec_era == RTA_SEC_ERA_2 && 657 era_2_sw_hfn_ovrd == 0)) { 658 SEQINPTR(p, 0, length, RTO); 659 } else { 660 SEQINPTR(p, 0, 5, RTO); 661 SEQFIFOLOAD(p, SKIP, 4, 0); 662 } 663 664 if (swap == false) { 665 MATHB(p, MATH0, AND, sn_mask, MATH1, 8, 666 IFB | IMMED2); 667 MATHB(p, MATH1, SHLD, MATH1, MATH1, 8, 0); 668 669 MOVEB(p, DESCBUF, 8, MATH2, 0, 8, WAITCOMP | IMMED); 670 MATHB(p, MATH1, OR, MATH2, MATH2, 8, 0); 671 MOVEB(p, MATH2, 0, IFIFOAB1, 0, 8, IMMED); 672 } else { 673 MATHB(p, MATH0, AND, sn_mask, MATH1, 8, 674 IFB | IMMED2); 675 MATHB(p, MATH1, SHLD, MATH1, MATH1, 8, 0); 676 677 MOVE(p, DESCBUF, 8, MATH2, 0, 8, WAITCOMP | IMMED); 678 MATHB(p, MATH1, OR, MATH2, MATH2, 8, 0); 679 MOVE(p, MATH2, 0, IFIFOAB1, 0, 8, IMMED); 680 } 681 682 if (dir == OP_TYPE_DECAP_PROTOCOL) { 683 MATHB(p, SEQINSZ, SUB, PDCP_MAC_I_LEN, MATH1, 4, 684 IMMED2); 685 } else { 686 if (rta_sec_era > RTA_SEC_ERA_2) { 687 MATHB(p, SEQINSZ, SUB, ZERO, MATH1, 4, 688 0); 689 } else { 690 MATHB(p, SEQINSZ, ADD, ONE, MATH1, 4, 691 0); 692 MATHB(p, MATH1, SUB, ONE, MATH1, 4, 693 0); 694 } 695 } 696 697 if (rta_sec_era > RTA_SEC_ERA_2) { 698 MATHB(p, MATH1, SUB, ZERO, VSEQINSZ, 4, 0); 699 MATHB(p, MATH1, SUB, ZERO, VSEQOUTSZ, 4, 0); 700 } else { 701 MATHB(p, ZERO, ADD, MATH1, VSEQINSZ, 4, 0); 702 MATHB(p, ZERO, ADD, MATH1, VSEQOUTSZ, 4, 0); 703 704 /* 705 * Since MOVELEN is available only starting with 706 * SEC ERA 3, use poor man's MOVELEN: create a MOVE 707 * command dynamically by writing the length from M1 by 708 * OR-ing the command in the M1 register and MOVE the 709 * result into the descriptor buffer. Care must be taken 710 * wrt. the location of the command because of SEC 711 * pipelining. The actual MOVEs are written at the end 712 * of the descriptor due to calculations needed on the 713 * offset in the descriptor for the MOVE command. 714 */ 715 move_cmd_read_descbuf = MOVE(p, DESCBUF, 0, MATH1, 0, 6, 716 IMMED); 717 move_cmd_write_descbuf = MOVE(p, MATH1, 0, DESCBUF, 0, 718 8, WAITCOMP | IMMED); 719 } 720 SEQFIFOSTORE(p, MSG, 0, 0, VLF); 721 ALG_OPERATION(p, OP_ALG_ALGSEL_AES, 722 OP_ALG_AAI_CMAC, 723 OP_ALG_AS_INITFINAL, 724 dir == OP_TYPE_ENCAP_PROTOCOL ? 725 ICV_CHECK_DISABLE : ICV_CHECK_ENABLE, 726 DIR_ENC); 727 728 if (rta_sec_era > RTA_SEC_ERA_2) { 729 MOVE(p, AB2, 0, OFIFO, 0, MATH1, 0); 730 SEQFIFOLOAD(p, MSGINSNOOP, 0, 731 VLF | LAST1 | LAST2 | FLUSH1); 732 } else { 733 SEQFIFOLOAD(p, MSGINSNOOP, 0, 734 VLF | LAST1 | LAST2 | FLUSH1); 735 SET_LABEL(p, local_offset); 736 737 /* Shut off automatic Info FIFO entries */ 738 LOAD(p, 0, DCTRL, LDOFF_DISABLE_AUTO_NFIFO, 0, IMMED); 739 740 /* 741 * Placeholder for MOVE command with length from 742 * M1 register 743 */ 744 MOVE(p, IFIFOAB2, 0, OFIFO, 0, 0, IMMED); 745 746 /* Enable automatic Info FIFO entries */ 747 LOAD(p, 0, DCTRL, LDOFF_ENABLE_AUTO_NFIFO, 0, IMMED); 748 } 749 750 if (dir == OP_TYPE_DECAP_PROTOCOL) 751 SEQFIFOLOAD(p, ICV1, 4, LAST1 | FLUSH1); 752 else 753 SEQSTORE(p, CONTEXT1, 0, 4, 0); 754 755 break; 756 757 case PDCP_AUTH_TYPE_ZUC: 758 if (rta_sec_era < RTA_SEC_ERA_5) { 759 pr_err("Invalid era for selected algorithm\n"); 760 return -ENOTSUP; 761 } 762 /* Insert Auth Key */ 763 KEY(p, KEY2, authdata->key_enc_flags, authdata->key, 764 authdata->keylen, INLINE_KEY(authdata)); 765 SEQLOAD(p, MATH0, offset, length, 0); 766 JUMP(p, 1, LOCAL_JUMP, ALL_TRUE, CALM); 767 SEQINPTR(p, 0, length, RTO); 768 if (swap == false) { 769 MATHB(p, MATH0, AND, sn_mask, MATH1, 8, 770 IFB | IMMED2); 771 MATHB(p, MATH1, SHLD, MATH1, MATH1, 8, 0); 772 773 MOVEB(p, DESCBUF, 8, MATH2, 0, 8, WAITCOMP | IMMED); 774 MATHB(p, MATH1, OR, MATH2, MATH2, 8, 0); 775 MOVEB(p, MATH2, 0, CONTEXT2, 0, 8, IMMED); 776 777 } else { 778 MATHB(p, MATH0, AND, sn_mask, MATH1, 8, 779 IFB | IMMED2); 780 MATHB(p, MATH1, SHLD, MATH1, MATH1, 8, 0); 781 782 MOVE(p, DESCBUF, 8, MATH2, 0, 8, WAITCOMP | IMMED); 783 MATHB(p, MATH1, OR, MATH2, MATH2, 8, 0); 784 MOVE(p, MATH2, 0, CONTEXT2, 0, 8, IMMED); 785 } 786 if (dir == OP_TYPE_DECAP_PROTOCOL) 787 MATHB(p, SEQINSZ, SUB, PDCP_MAC_I_LEN, MATH1, 4, 788 IMMED2); 789 else 790 MATHB(p, SEQINSZ, SUB, ZERO, MATH1, 4, 0); 791 792 MATHB(p, MATH1, SUB, ZERO, VSEQINSZ, 4, 0); 793 MATHB(p, MATH1, SUB, ZERO, VSEQOUTSZ, 4, 0); 794 SEQFIFOSTORE(p, MSG, 0, 0, VLF); 795 ALG_OPERATION(p, OP_ALG_ALGSEL_ZUCA, 796 OP_ALG_AAI_F9, 797 OP_ALG_AS_INITFINAL, 798 dir == OP_TYPE_ENCAP_PROTOCOL ? 799 ICV_CHECK_DISABLE : ICV_CHECK_ENABLE, 800 DIR_ENC); 801 SEQFIFOLOAD(p, MSGINSNOOP, 0, VLF | LAST1 | LAST2 | FLUSH1); 802 MOVE(p, AB1, 0, OFIFO, 0, MATH1, 0); 803 804 if (dir == OP_TYPE_DECAP_PROTOCOL) 805 SEQFIFOLOAD(p, ICV2, 4, LAST2); 806 else 807 SEQSTORE(p, CONTEXT2, 0, 4, 0); 808 809 break; 810 811 default: 812 pr_err("%s: Invalid integrity algorithm selected: %d\n", 813 "pdcp_insert_cplane_int_only_op", authdata->algtype); 814 return -EINVAL; 815 } 816 817 if (rta_sec_era < RTA_SEC_ERA_3) { 818 PATCH_MOVE(p, move_cmd_read_descbuf, local_offset); 819 PATCH_MOVE(p, move_cmd_write_descbuf, local_offset); 820 } 821 822 return 0; 823 } 824 825 static inline int 826 pdcp_insert_cplane_enc_only_op(struct program *p, 827 bool swap __maybe_unused, 828 struct alginfo *cipherdata, 829 struct alginfo *authdata __maybe_unused, 830 unsigned int dir, 831 enum pdcp_sn_size sn_size, 832 unsigned char era_2_sw_hfn_ovrd __maybe_unused) 833 { 834 uint32_t offset = 0, length = 0, sn_mask = 0; 835 /* Insert Cipher Key */ 836 KEY(p, KEY1, cipherdata->key_enc_flags, cipherdata->key, 837 cipherdata->keylen, INLINE_KEY(cipherdata)); 838 839 if ((rta_sec_era >= RTA_SEC_ERA_8 && sn_size != PDCP_SN_SIZE_18 && 840 !(rta_sec_era == RTA_SEC_ERA_8 && 841 authdata->algtype == 0)) 842 || (rta_sec_era == RTA_SEC_ERA_10)) { 843 if (sn_size == PDCP_SN_SIZE_5) 844 PROTOCOL(p, dir, OP_PCLID_LTE_PDCP_CTRL_MIXED, 845 (uint16_t)cipherdata->algtype << 8); 846 else 847 PROTOCOL(p, dir, OP_PCLID_LTE_PDCP_USER_RN, 848 (uint16_t)cipherdata->algtype << 8); 849 return 0; 850 } 851 /* Non-proto is supported only for 5bit cplane and 18bit uplane */ 852 switch (sn_size) { 853 case PDCP_SN_SIZE_5: 854 offset = 7; 855 length = 1; 856 sn_mask = (swap == false) ? PDCP_C_PLANE_SN_MASK : 857 PDCP_C_PLANE_SN_MASK_BE; 858 break; 859 case PDCP_SN_SIZE_18: 860 offset = 5; 861 length = 3; 862 sn_mask = (swap == false) ? PDCP_U_PLANE_18BIT_SN_MASK : 863 PDCP_U_PLANE_18BIT_SN_MASK_BE; 864 break; 865 case PDCP_SN_SIZE_12: 866 offset = 6; 867 length = 2; 868 sn_mask = (swap == false) ? PDCP_12BIT_SN_MASK : 869 PDCP_12BIT_SN_MASK_BE; 870 break; 871 case PDCP_SN_SIZE_7: 872 case PDCP_SN_SIZE_15: 873 pr_err("Invalid sn_size for %s\n", __func__); 874 return -ENOTSUP; 875 } 876 877 SEQLOAD(p, MATH0, offset, length, 0); 878 JUMP(p, 1, LOCAL_JUMP, ALL_TRUE, CALM); 879 MATHB(p, MATH0, AND, sn_mask, MATH1, 8, IFB | IMMED2); 880 SEQSTORE(p, MATH0, offset, length, 0); 881 MATHB(p, MATH1, SHLD, MATH1, MATH1, 8, 0); 882 MOVEB(p, DESCBUF, 8, MATH2, 0, 8, WAITCOMP | IMMED); 883 MATHB(p, MATH1, OR, MATH2, MATH2, 8, 0); 884 885 switch (cipherdata->algtype) { 886 case PDCP_CIPHER_TYPE_SNOW: 887 MOVEB(p, MATH2, 0, CONTEXT1, 0, 8, WAITCOMP | IMMED); 888 889 if (rta_sec_era > RTA_SEC_ERA_2) { 890 MATHB(p, SEQINSZ, SUB, ZERO, VSEQINSZ, 4, 0); 891 } else { 892 MATHB(p, SEQINSZ, SUB, ONE, MATH1, 4, 0); 893 MATHB(p, MATH1, ADD, ONE, VSEQINSZ, 4, 0); 894 } 895 896 if (dir == OP_TYPE_ENCAP_PROTOCOL) 897 MATHB(p, SEQINSZ, ADD, PDCP_MAC_I_LEN, VSEQOUTSZ, 4, 898 IMMED2); 899 else 900 MATHB(p, SEQINSZ, SUB, PDCP_MAC_I_LEN, VSEQOUTSZ, 4, 901 IMMED2); 902 SEQFIFOSTORE(p, MSG, 0, 0, VLF | CONT); 903 ALG_OPERATION(p, OP_ALG_ALGSEL_SNOW_F8, 904 OP_ALG_AAI_F8, 905 OP_ALG_AS_INITFINAL, ICV_CHECK_DISABLE, 906 dir == OP_TYPE_ENCAP_PROTOCOL ? 907 DIR_ENC : DIR_DEC); 908 break; 909 910 case PDCP_CIPHER_TYPE_AES: 911 MOVEB(p, MATH2, 0, CONTEXT1, 0x10, 0x10, WAITCOMP | IMMED); 912 913 if (rta_sec_era > RTA_SEC_ERA_2) { 914 MATHB(p, SEQINSZ, SUB, ZERO, VSEQINSZ, 4, 0); 915 } else { 916 MATHB(p, SEQINSZ, SUB, ONE, MATH1, 4, 0); 917 MATHB(p, MATH1, ADD, ONE, VSEQINSZ, 4, 0); 918 } 919 920 if (dir == OP_TYPE_ENCAP_PROTOCOL) 921 MATHB(p, SEQINSZ, ADD, PDCP_MAC_I_LEN, VSEQOUTSZ, 4, 922 IMMED2); 923 else 924 MATHB(p, SEQINSZ, SUB, PDCP_MAC_I_LEN, VSEQOUTSZ, 4, 925 IMMED2); 926 927 SEQFIFOSTORE(p, MSG, 0, 0, VLF | CONT); 928 ALG_OPERATION(p, OP_ALG_ALGSEL_AES, 929 OP_ALG_AAI_CTR, 930 OP_ALG_AS_INITFINAL, 931 ICV_CHECK_DISABLE, 932 dir == OP_TYPE_ENCAP_PROTOCOL ? 933 DIR_ENC : DIR_DEC); 934 break; 935 936 case PDCP_CIPHER_TYPE_ZUC: 937 if (rta_sec_era < RTA_SEC_ERA_5) { 938 pr_err("Invalid era for selected algorithm\n"); 939 return -ENOTSUP; 940 } 941 942 MOVEB(p, MATH2, 0, CONTEXT1, 0, 0x08, IMMED); 943 MOVEB(p, MATH2, 0, CONTEXT1, 0x08, 0x08, WAITCOMP | IMMED); 944 MATHB(p, SEQINSZ, SUB, ZERO, VSEQINSZ, 4, 0); 945 if (dir == OP_TYPE_ENCAP_PROTOCOL) 946 MATHB(p, SEQINSZ, ADD, PDCP_MAC_I_LEN, VSEQOUTSZ, 4, 947 IMMED2); 948 else 949 MATHB(p, SEQINSZ, SUB, PDCP_MAC_I_LEN, VSEQOUTSZ, 4, 950 IMMED2); 951 952 SEQFIFOSTORE(p, MSG, 0, 0, VLF | CONT); 953 ALG_OPERATION(p, OP_ALG_ALGSEL_ZUCE, 954 OP_ALG_AAI_F8, 955 OP_ALG_AS_INITFINAL, 956 ICV_CHECK_DISABLE, 957 dir == OP_TYPE_ENCAP_PROTOCOL ? 958 DIR_ENC : DIR_DEC); 959 break; 960 961 default: 962 pr_err("%s: Invalid encrypt algorithm selected: %d\n", 963 "pdcp_insert_cplane_enc_only_op", cipherdata->algtype); 964 return -EINVAL; 965 } 966 967 if (dir == OP_TYPE_ENCAP_PROTOCOL) { 968 SEQFIFOLOAD(p, MSG1, 0, VLF); 969 FIFOLOAD(p, MSG1, PDCP_NULL_INT_MAC_I_VAL, 4, 970 LAST1 | FLUSH1 | IMMED); 971 } else { 972 SEQFIFOLOAD(p, MSG1, 0, VLF | LAST1 | FLUSH1); 973 MOVE(p, OFIFO, 0, MATH1, 4, PDCP_MAC_I_LEN, WAITCOMP | IMMED); 974 MATHB(p, MATH1, XOR, PDCP_NULL_INT_MAC_I_VAL, NONE, 4, IMMED2); 975 JUMP(p, PDCP_NULL_INT_ICV_CHECK_FAILED_STATUS, 976 HALT_STATUS, ALL_FALSE, MATH_Z); 977 } 978 979 return 0; 980 } 981 982 static inline int 983 pdcp_insert_uplane_snow_snow_op(struct program *p, 984 bool swap __maybe_unused, 985 struct alginfo *cipherdata, 986 struct alginfo *authdata, 987 unsigned int dir, 988 enum pdcp_sn_size sn_size, 989 unsigned char era_2_sw_hfn_ovrd __maybe_unused) 990 { 991 uint32_t offset = 0, length = 0, sn_mask = 0; 992 993 KEY(p, KEY1, cipherdata->key_enc_flags, cipherdata->key, 994 cipherdata->keylen, INLINE_KEY(cipherdata)); 995 KEY(p, KEY2, authdata->key_enc_flags, authdata->key, authdata->keylen, 996 INLINE_KEY(authdata)); 997 998 if (rta_sec_era >= RTA_SEC_ERA_8 && sn_size != PDCP_SN_SIZE_18) { 999 int pclid; 1000 1001 if (sn_size == PDCP_SN_SIZE_5) 1002 pclid = OP_PCLID_LTE_PDCP_CTRL_MIXED; 1003 else 1004 pclid = OP_PCLID_LTE_PDCP_USER_RN; 1005 1006 PROTOCOL(p, dir, pclid, 1007 ((uint16_t)cipherdata->algtype << 8) | 1008 (uint16_t)authdata->algtype); 1009 1010 return 0; 1011 } 1012 /* Non-proto is supported only for 5bit cplane and 18bit uplane */ 1013 switch (sn_size) { 1014 case PDCP_SN_SIZE_5: 1015 offset = 7; 1016 length = 1; 1017 sn_mask = (swap == false) ? PDCP_C_PLANE_SN_MASK : 1018 PDCP_C_PLANE_SN_MASK_BE; 1019 break; 1020 case PDCP_SN_SIZE_18: 1021 offset = 5; 1022 length = 3; 1023 sn_mask = (swap == false) ? PDCP_U_PLANE_18BIT_SN_MASK : 1024 PDCP_U_PLANE_18BIT_SN_MASK_BE; 1025 break; 1026 case PDCP_SN_SIZE_7: 1027 case PDCP_SN_SIZE_12: 1028 case PDCP_SN_SIZE_15: 1029 pr_err("Invalid sn_size for %s\n", __func__); 1030 return -ENOTSUP; 1031 } 1032 1033 if (dir == OP_TYPE_ENCAP_PROTOCOL) 1034 MATHB(p, SEQINSZ, SUB, length, VSEQINSZ, 4, IMMED2); 1035 1036 SEQLOAD(p, MATH0, offset, length, 0); 1037 JUMP(p, 1, LOCAL_JUMP, ALL_TRUE, CALM); 1038 MOVEB(p, MATH0, offset, IFIFOAB2, 0, length, IMMED); 1039 MATHB(p, MATH0, AND, sn_mask, MATH1, 8, IFB | IMMED2); 1040 1041 SEQSTORE(p, MATH0, offset, length, 0); 1042 MATHB(p, MATH1, SHLD, MATH1, MATH1, 8, 0); 1043 MOVEB(p, DESCBUF, 8, MATH2, 0, 8, WAITCOMP | IMMED); 1044 MATHB(p, MATH1, OR, MATH2, MATH1, 8, 0); 1045 MOVEB(p, MATH1, 0, CONTEXT1, 0, 8, IMMED); 1046 MOVEB(p, MATH1, 0, CONTEXT2, 0, 4, WAITCOMP | IMMED); 1047 if (swap == false) { 1048 MATHB(p, MATH1, AND, upper_32_bits(PDCP_BEARER_MASK), 1049 MATH2, 4, IMMED2); 1050 MATHB(p, MATH1, AND, lower_32_bits(PDCP_DIR_MASK), 1051 MATH3, 4, IMMED2); 1052 } else { 1053 MATHB(p, MATH1, AND, lower_32_bits(PDCP_BEARER_MASK_BE), 1054 MATH2, 4, IMMED2); 1055 MATHB(p, MATH1, AND, upper_32_bits(PDCP_DIR_MASK_BE), 1056 MATH3, 4, IMMED2); 1057 } 1058 MATHB(p, MATH3, SHLD, MATH3, MATH3, 8, 0); 1059 1060 MOVEB(p, MATH2, 4, OFIFO, 0, 12, IMMED); 1061 MOVE(p, OFIFO, 0, CONTEXT2, 4, 12, IMMED); 1062 if (dir == OP_TYPE_ENCAP_PROTOCOL) { 1063 MATHB(p, SEQINSZ, ADD, PDCP_MAC_I_LEN, VSEQOUTSZ, 4, IMMED2); 1064 } else { 1065 MATHI(p, SEQINSZ, SUB, PDCP_MAC_I_LEN, VSEQOUTSZ, 4, IMMED2); 1066 MATHI(p, SEQINSZ, SUB, PDCP_MAC_I_LEN, VSEQINSZ, 4, IMMED2); 1067 } 1068 1069 if (dir == OP_TYPE_ENCAP_PROTOCOL) 1070 SEQFIFOSTORE(p, MSG, 0, 0, VLF); 1071 else 1072 SEQFIFOSTORE(p, MSG, 0, 0, VLF | CONT); 1073 1074 ALG_OPERATION(p, OP_ALG_ALGSEL_SNOW_F9, 1075 OP_ALG_AAI_F9, 1076 OP_ALG_AS_INITFINAL, 1077 dir == OP_TYPE_ENCAP_PROTOCOL ? 1078 ICV_CHECK_DISABLE : ICV_CHECK_ENABLE, 1079 DIR_DEC); 1080 ALG_OPERATION(p, OP_ALG_ALGSEL_SNOW_F8, 1081 OP_ALG_AAI_F8, 1082 OP_ALG_AS_INITFINAL, 1083 ICV_CHECK_DISABLE, 1084 dir == OP_TYPE_ENCAP_PROTOCOL ? DIR_ENC : DIR_DEC); 1085 1086 if (dir == OP_TYPE_ENCAP_PROTOCOL) { 1087 SEQFIFOLOAD(p, MSGINSNOOP, 0, VLF | LAST2); 1088 MOVE(p, CONTEXT2, 0, IFIFOAB1, 0, 4, LAST1 | FLUSH1 | IMMED); 1089 } else { 1090 SEQFIFOLOAD(p, MSGOUTSNOOP, 0, VLF | LAST2); 1091 SEQFIFOLOAD(p, MSG1, 4, LAST1 | FLUSH1); 1092 JUMP(p, 1, LOCAL_JUMP, ALL_TRUE, CLASS1 | NOP | NIFP); 1093 1094 if (rta_sec_era >= RTA_SEC_ERA_6) 1095 LOAD(p, 0, DCTRL, 0, LDLEN_RST_CHA_OFIFO_PTR, IMMED); 1096 1097 MOVE(p, OFIFO, 0, MATH0, 0, 4, WAITCOMP | IMMED); 1098 1099 NFIFOADD(p, IFIFO, ICV2, 4, LAST2); 1100 1101 if (rta_sec_era <= RTA_SEC_ERA_2) { 1102 /* Shut off automatic Info FIFO entries */ 1103 LOAD(p, 0, DCTRL, LDOFF_DISABLE_AUTO_NFIFO, 0, IMMED); 1104 MOVE(p, MATH0, 0, IFIFOAB2, 0, 4, WAITCOMP | IMMED); 1105 } else { 1106 MOVE(p, MATH0, 0, IFIFO, 0, 4, WAITCOMP | IMMED); 1107 } 1108 } 1109 1110 return 0; 1111 } 1112 1113 static inline int 1114 pdcp_insert_uplane_zuc_zuc_op(struct program *p, 1115 bool swap __maybe_unused, 1116 struct alginfo *cipherdata, 1117 struct alginfo *authdata, 1118 unsigned int dir, 1119 enum pdcp_sn_size sn_size, 1120 unsigned char era_2_sw_hfn_ovrd __maybe_unused) 1121 { 1122 uint32_t offset = 0, length = 0, sn_mask = 0; 1123 1124 LABEL(keyjump); 1125 REFERENCE(pkeyjump); 1126 1127 if (rta_sec_era < RTA_SEC_ERA_5) { 1128 pr_err("Invalid era for selected algorithm\n"); 1129 return -ENOTSUP; 1130 } 1131 1132 pkeyjump = JUMP(p, keyjump, LOCAL_JUMP, ALL_TRUE, SHRD | SELF | BOTH); 1133 KEY(p, KEY1, cipherdata->key_enc_flags, cipherdata->key, 1134 cipherdata->keylen, INLINE_KEY(cipherdata)); 1135 KEY(p, KEY2, authdata->key_enc_flags, authdata->key, authdata->keylen, 1136 INLINE_KEY(authdata)); 1137 1138 SET_LABEL(p, keyjump); 1139 PATCH_JUMP(p, pkeyjump, keyjump); 1140 1141 if (rta_sec_era >= RTA_SEC_ERA_8 && sn_size != PDCP_SN_SIZE_18) { 1142 int pclid; 1143 1144 if (sn_size == PDCP_SN_SIZE_5) 1145 pclid = OP_PCLID_LTE_PDCP_CTRL_MIXED; 1146 else 1147 pclid = OP_PCLID_LTE_PDCP_USER_RN; 1148 1149 PROTOCOL(p, dir, pclid, 1150 ((uint16_t)cipherdata->algtype << 8) | 1151 (uint16_t)authdata->algtype); 1152 1153 return 0; 1154 } 1155 /* Non-proto is supported only for 5bit cplane and 18bit uplane */ 1156 switch (sn_size) { 1157 case PDCP_SN_SIZE_5: 1158 offset = 7; 1159 length = 1; 1160 sn_mask = (swap == false) ? PDCP_C_PLANE_SN_MASK : 1161 PDCP_C_PLANE_SN_MASK_BE; 1162 break; 1163 case PDCP_SN_SIZE_18: 1164 offset = 5; 1165 length = 3; 1166 sn_mask = (swap == false) ? PDCP_U_PLANE_18BIT_SN_MASK : 1167 PDCP_U_PLANE_18BIT_SN_MASK_BE; 1168 break; 1169 case PDCP_SN_SIZE_7: 1170 case PDCP_SN_SIZE_12: 1171 case PDCP_SN_SIZE_15: 1172 pr_err("Invalid sn_size for %s\n", __func__); 1173 return -ENOTSUP; 1174 } 1175 1176 SEQLOAD(p, MATH0, offset, length, 0); 1177 JUMP(p, 1, LOCAL_JUMP, ALL_TRUE, CALM); 1178 MOVEB(p, MATH0, offset, IFIFOAB2, 0, length, IMMED); 1179 MATHB(p, MATH0, AND, sn_mask, MATH1, 8, IFB | IMMED2); 1180 MATHB(p, MATH1, SHLD, MATH1, MATH1, 8, 0); 1181 1182 MOVEB(p, DESCBUF, 8, MATH2, 0, 8, WAITCOMP | IMMED); 1183 MATHB(p, MATH1, OR, MATH2, MATH2, 8, 0); 1184 MOVEB(p, MATH2, 0, CONTEXT1, 0, 8, IMMED); 1185 1186 MOVEB(p, MATH2, 0, CONTEXT2, 0, 8, WAITCOMP | IMMED); 1187 1188 if (dir == OP_TYPE_ENCAP_PROTOCOL) 1189 MATHB(p, SEQINSZ, ADD, PDCP_MAC_I_LEN, VSEQOUTSZ, 4, IMMED2); 1190 else 1191 MATHB(p, SEQINSZ, SUB, PDCP_MAC_I_LEN, VSEQOUTSZ, 4, IMMED2); 1192 1193 MATHB(p, SEQINSZ, SUB, ZERO, VSEQINSZ, 4, 0); 1194 SEQSTORE(p, MATH0, offset, length, 0); 1195 1196 if (dir == OP_TYPE_ENCAP_PROTOCOL) { 1197 SEQFIFOSTORE(p, MSG, 0, 0, VLF); 1198 SEQFIFOLOAD(p, MSGINSNOOP, 0, VLF | LAST2); 1199 } else { 1200 SEQFIFOSTORE(p, MSG, 0, 0, VLF | CONT); 1201 SEQFIFOLOAD(p, MSGOUTSNOOP, 0, VLF | LAST1 | FLUSH1); 1202 } 1203 1204 ALG_OPERATION(p, OP_ALG_ALGSEL_ZUCA, 1205 OP_ALG_AAI_F9, 1206 OP_ALG_AS_INITFINAL, 1207 dir == OP_TYPE_ENCAP_PROTOCOL ? 1208 ICV_CHECK_DISABLE : ICV_CHECK_ENABLE, 1209 DIR_ENC); 1210 1211 ALG_OPERATION(p, OP_ALG_ALGSEL_ZUCE, 1212 OP_ALG_AAI_F8, 1213 OP_ALG_AS_INITFINAL, 1214 ICV_CHECK_DISABLE, 1215 dir == OP_TYPE_ENCAP_PROTOCOL ? DIR_ENC : DIR_DEC); 1216 1217 if (dir == OP_TYPE_ENCAP_PROTOCOL) { 1218 MOVE(p, CONTEXT2, 0, IFIFOAB1, 0, 4, LAST1 | FLUSH1 | IMMED); 1219 } else { 1220 /* Save ICV */ 1221 MOVEB(p, OFIFO, 0, MATH0, 0, 4, IMMED); 1222 1223 LOAD(p, NFIFOENTRY_STYPE_ALTSOURCE | 1224 NFIFOENTRY_DEST_CLASS2 | 1225 NFIFOENTRY_DTYPE_ICV | 1226 NFIFOENTRY_LC2 | 4, NFIFO_SZL, 0, 4, IMMED); 1227 MOVEB(p, MATH0, 0, ALTSOURCE, 0, 4, WAITCOMP | IMMED); 1228 } 1229 1230 /* Reset ZUCA mode and done interrupt */ 1231 LOAD(p, CLRW_CLR_C2MODE, CLRW, 0, 4, IMMED); 1232 LOAD(p, CIRQ_ZADI, ICTRL, 0, 4, IMMED); 1233 1234 return 0; 1235 } 1236 1237 static inline int 1238 pdcp_insert_uplane_aes_aes_op(struct program *p, 1239 bool swap __maybe_unused, 1240 struct alginfo *cipherdata, 1241 struct alginfo *authdata, 1242 unsigned int dir, 1243 enum pdcp_sn_size sn_size, 1244 unsigned char era_2_sw_hfn_ovrd __maybe_unused) 1245 { 1246 uint32_t offset = 0, length = 0, sn_mask = 0; 1247 1248 if ((rta_sec_era >= RTA_SEC_ERA_8 && sn_size != PDCP_SN_SIZE_18)) { 1249 /* Insert Auth Key */ 1250 KEY(p, KEY2, authdata->key_enc_flags, authdata->key, 1251 authdata->keylen, INLINE_KEY(authdata)); 1252 1253 /* Insert Cipher Key */ 1254 KEY(p, KEY1, cipherdata->key_enc_flags, cipherdata->key, 1255 cipherdata->keylen, INLINE_KEY(cipherdata)); 1256 1257 PROTOCOL(p, dir, OP_PCLID_LTE_PDCP_USER_RN, 1258 ((uint16_t)cipherdata->algtype << 8) | 1259 (uint16_t)authdata->algtype); 1260 return 0; 1261 } 1262 1263 /* Non-proto is supported only for 5bit cplane and 18bit uplane */ 1264 switch (sn_size) { 1265 case PDCP_SN_SIZE_18: 1266 offset = 5; 1267 length = 3; 1268 sn_mask = (swap == false) ? PDCP_U_PLANE_18BIT_SN_MASK : 1269 PDCP_U_PLANE_18BIT_SN_MASK_BE; 1270 break; 1271 1272 default: 1273 pr_err("Invalid sn_size for %s\n", __func__); 1274 return -ENOTSUP; 1275 } 1276 1277 SEQLOAD(p, MATH0, offset, length, 0); 1278 JUMP(p, 1, LOCAL_JUMP, ALL_TRUE, CALM); 1279 MATHB(p, MATH0, AND, sn_mask, MATH1, 8, IFB | IMMED2); 1280 1281 MATHB(p, MATH1, SHLD, MATH1, MATH1, 8, 0); 1282 MOVEB(p, DESCBUF, 8, MATH2, 0, 0x08, WAITCOMP | IMMED); 1283 MATHB(p, MATH1, OR, MATH2, MATH2, 8, 0); 1284 SEQSTORE(p, MATH0, offset, length, 0); 1285 1286 if (dir == OP_TYPE_ENCAP_PROTOCOL) { 1287 KEY(p, KEY1, authdata->key_enc_flags, authdata->key, 1288 authdata->keylen, INLINE_KEY(authdata)); 1289 MOVEB(p, MATH2, 0, IFIFOAB1, 0, 0x08, IMMED); 1290 MOVEB(p, MATH0, offset, IFIFOAB1, 0, length, IMMED); 1291 1292 MATHB(p, SEQINSZ, SUB, ZERO, VSEQINSZ, 4, 0); 1293 MATHB(p, VSEQINSZ, ADD, PDCP_MAC_I_LEN, VSEQOUTSZ, 4, IMMED2); 1294 1295 ALG_OPERATION(p, OP_ALG_ALGSEL_AES, 1296 OP_ALG_AAI_CMAC, 1297 OP_ALG_AS_INITFINAL, 1298 ICV_CHECK_DISABLE, 1299 DIR_DEC); 1300 SEQFIFOLOAD(p, MSG1, 0, VLF | LAST1 | FLUSH1); 1301 MOVEB(p, CONTEXT1, 0, MATH3, 0, 4, WAITCOMP | IMMED); 1302 1303 LOAD(p, CLRW_RESET_CLS1_CHA | 1304 CLRW_CLR_C1KEY | 1305 CLRW_CLR_C1CTX | 1306 CLRW_CLR_C1ICV | 1307 CLRW_CLR_C1DATAS | 1308 CLRW_CLR_C1MODE, 1309 CLRW, 0, 4, IMMED); 1310 1311 KEY(p, KEY1, cipherdata->key_enc_flags, cipherdata->key, 1312 cipherdata->keylen, INLINE_KEY(cipherdata)); 1313 1314 MOVEB(p, MATH2, 0, CONTEXT1, 16, 8, IMMED); 1315 SEQINPTR(p, 0, PDCP_NULL_MAX_FRAME_LEN, RTO); 1316 1317 ALG_OPERATION(p, OP_ALG_ALGSEL_AES, 1318 OP_ALG_AAI_CTR, 1319 OP_ALG_AS_INITFINAL, 1320 ICV_CHECK_DISABLE, 1321 DIR_ENC); 1322 1323 SEQFIFOSTORE(p, MSG, 0, 0, VLF); 1324 1325 SEQFIFOLOAD(p, SKIP, length, 0); 1326 1327 SEQFIFOLOAD(p, MSG1, 0, VLF); 1328 MOVEB(p, MATH3, 0, IFIFOAB1, 0, 4, LAST1 | FLUSH1 | IMMED); 1329 } else { 1330 MOVEB(p, MATH2, 0, CONTEXT1, 16, 8, IMMED); 1331 MOVEB(p, MATH2, 0, CONTEXT2, 0, 8, IMMED); 1332 1333 MATHB(p, SEQINSZ, SUB, ZERO, VSEQINSZ, 4, 0); 1334 MATHB(p, SEQINSZ, SUB, PDCP_MAC_I_LEN, VSEQOUTSZ, 4, IMMED2); 1335 1336 KEY(p, KEY1, cipherdata->key_enc_flags, cipherdata->key, 1337 cipherdata->keylen, INLINE_KEY(cipherdata)); 1338 1339 ALG_OPERATION(p, OP_ALG_ALGSEL_AES, 1340 OP_ALG_AAI_CTR, 1341 OP_ALG_AS_INITFINAL, 1342 ICV_CHECK_DISABLE, 1343 DIR_DEC); 1344 1345 SEQFIFOSTORE(p, MSG, 0, 0, VLF | CONT); 1346 SEQFIFOLOAD(p, MSG1, 0, VLF | LAST1 | FLUSH1); 1347 1348 MOVEB(p, OFIFO, 0, MATH3, 0, 4, IMMED); 1349 1350 LOAD(p, CLRW_RESET_CLS1_CHA | 1351 CLRW_CLR_C1KEY | 1352 CLRW_CLR_C1CTX | 1353 CLRW_CLR_C1ICV | 1354 CLRW_CLR_C1DATAS | 1355 CLRW_CLR_C1MODE, 1356 CLRW, 0, 4, IMMED); 1357 1358 KEY(p, KEY1, authdata->key_enc_flags, authdata->key, 1359 authdata->keylen, INLINE_KEY(authdata)); 1360 1361 SEQINPTR(p, 0, 0, SOP); 1362 1363 ALG_OPERATION(p, OP_ALG_ALGSEL_AES, 1364 OP_ALG_AAI_CMAC, 1365 OP_ALG_AS_INITFINAL, 1366 ICV_CHECK_ENABLE, 1367 DIR_DEC); 1368 1369 MATHB(p, SEQINSZ, SUB, ZERO, VSEQINSZ, 4, 0); 1370 1371 MOVE(p, CONTEXT2, 0, IFIFOAB1, 0, 8, IMMED); 1372 1373 SEQFIFOLOAD(p, MSG1, 0, VLF | LAST1 | FLUSH1); 1374 1375 LOAD(p, NFIFOENTRY_STYPE_ALTSOURCE | 1376 NFIFOENTRY_DEST_CLASS1 | 1377 NFIFOENTRY_DTYPE_ICV | 1378 NFIFOENTRY_LC1 | 1379 NFIFOENTRY_FC1 | 4, NFIFO_SZL, 0, 4, IMMED); 1380 MOVEB(p, MATH3, 0, ALTSOURCE, 0, 4, IMMED); 1381 } 1382 1383 return 0; 1384 } 1385 1386 static inline int 1387 pdcp_insert_cplane_acc_op(struct program *p, 1388 bool swap __maybe_unused, 1389 struct alginfo *cipherdata, 1390 struct alginfo *authdata, 1391 unsigned int dir, 1392 enum pdcp_sn_size sn_size, 1393 unsigned char era_2_hfn_ovrd __maybe_unused) 1394 { 1395 /* Insert Auth Key */ 1396 KEY(p, KEY2, authdata->key_enc_flags, authdata->key, authdata->keylen, 1397 INLINE_KEY(authdata)); 1398 1399 /* Insert Cipher Key */ 1400 KEY(p, KEY1, cipherdata->key_enc_flags, cipherdata->key, 1401 cipherdata->keylen, INLINE_KEY(cipherdata)); 1402 1403 if (sn_size == PDCP_SN_SIZE_5) 1404 PROTOCOL(p, dir, OP_PCLID_LTE_PDCP_CTRL, 1405 (uint16_t)cipherdata->algtype); 1406 else 1407 PROTOCOL(p, dir, OP_PCLID_LTE_PDCP_USER_RN, 1408 ((uint16_t)cipherdata->algtype << 8) | 1409 (uint16_t)authdata->algtype); 1410 1411 return 0; 1412 } 1413 1414 static inline int 1415 pdcp_insert_cplane_snow_aes_op(struct program *p, 1416 bool swap __maybe_unused, 1417 struct alginfo *cipherdata, 1418 struct alginfo *authdata, 1419 unsigned int dir, 1420 enum pdcp_sn_size sn_size, 1421 unsigned char era_2_sw_hfn_ovrd) 1422 { 1423 uint32_t offset = 0, length = 0, sn_mask = 0; 1424 1425 LABEL(back_to_sd_offset); 1426 LABEL(end_desc); 1427 LABEL(local_offset); 1428 LABEL(jump_to_beginning); 1429 LABEL(fifo_load_mac_i_offset); 1430 REFERENCE(seqin_ptr_read); 1431 REFERENCE(seqin_ptr_write); 1432 REFERENCE(seq_out_read); 1433 REFERENCE(jump_back_to_sd_cmd); 1434 REFERENCE(move_mac_i_to_desc_buf); 1435 1436 if ((rta_sec_era >= RTA_SEC_ERA_8 && sn_size != PDCP_SN_SIZE_18) || 1437 (rta_sec_era == RTA_SEC_ERA_10)) { 1438 KEY(p, KEY1, cipherdata->key_enc_flags, cipherdata->key, 1439 cipherdata->keylen, INLINE_KEY(cipherdata)); 1440 KEY(p, KEY2, authdata->key_enc_flags, authdata->key, 1441 authdata->keylen, INLINE_KEY(authdata)); 1442 1443 if (sn_size == PDCP_SN_SIZE_5) 1444 PROTOCOL(p, dir, OP_PCLID_LTE_PDCP_CTRL_MIXED, 1445 ((uint16_t)cipherdata->algtype << 8) | 1446 (uint16_t)authdata->algtype); 1447 else 1448 PROTOCOL(p, dir, OP_PCLID_LTE_PDCP_USER_RN, 1449 ((uint16_t)cipherdata->algtype << 8) | 1450 (uint16_t)authdata->algtype); 1451 1452 return 0; 1453 } 1454 /* Non-proto is supported only for 5bit cplane and 18bit uplane */ 1455 switch (sn_size) { 1456 case PDCP_SN_SIZE_5: 1457 offset = 7; 1458 length = 1; 1459 sn_mask = (swap == false) ? PDCP_C_PLANE_SN_MASK : 1460 PDCP_C_PLANE_SN_MASK_BE; 1461 break; 1462 case PDCP_SN_SIZE_18: 1463 offset = 5; 1464 length = 3; 1465 sn_mask = (swap == false) ? PDCP_U_PLANE_18BIT_SN_MASK : 1466 PDCP_U_PLANE_18BIT_SN_MASK_BE; 1467 break; 1468 case PDCP_SN_SIZE_7: 1469 case PDCP_SN_SIZE_12: 1470 case PDCP_SN_SIZE_15: 1471 pr_err("Invalid sn_size for %s\n", __func__); 1472 return -ENOTSUP; 1473 1474 } 1475 1476 SEQLOAD(p, MATH0, offset, length, 0); 1477 JUMP(p, 1, LOCAL_JUMP, ALL_TRUE, CALM); 1478 MATHB(p, MATH0, AND, sn_mask, MATH1, 8, IFB | IMMED2); 1479 MATHB(p, MATH1, SHLD, MATH1, MATH1, 8, 0); 1480 MOVEB(p, DESCBUF, 4, MATH2, 0, 0x08, WAITCOMP | IMMED); 1481 MATHB(p, MATH1, OR, MATH2, MATH2, 8, 0); 1482 SEQSTORE(p, MATH0, offset, length, 0); 1483 if (dir == OP_TYPE_ENCAP_PROTOCOL) { 1484 if (rta_sec_era > RTA_SEC_ERA_2 || 1485 (rta_sec_era == RTA_SEC_ERA_2 && 1486 era_2_sw_hfn_ovrd == 0)) { 1487 SEQINPTR(p, 0, length, RTO); 1488 } else { 1489 SEQINPTR(p, 0, 5, RTO); 1490 SEQFIFOLOAD(p, SKIP, 4, 0); 1491 } 1492 KEY(p, KEY1, authdata->key_enc_flags, authdata->key, 1493 authdata->keylen, INLINE_KEY(authdata)); 1494 MOVEB(p, MATH2, 0, IFIFOAB1, 0, 0x08, IMMED); 1495 1496 if (rta_sec_era > RTA_SEC_ERA_2) { 1497 MATHB(p, SEQINSZ, SUB, ZERO, VSEQINSZ, 4, 0); 1498 MATHB(p, SEQINSZ, SUB, ZERO, MATH1, 4, 0); 1499 MATHB(p, VSEQINSZ, ADD, PDCP_MAC_I_LEN - 1, VSEQOUTSZ, 1500 4, IMMED2); 1501 } else { 1502 MATHB(p, SEQINSZ, SUB, MATH3, VSEQINSZ, 4, 0); 1503 MATHB(p, VSEQINSZ, ADD, PDCP_MAC_I_LEN - 1, VSEQOUTSZ, 1504 4, IMMED2); 1505 /* 1506 * Note: Although the calculations below might seem a 1507 * little off, the logic is the following: 1508 * 1509 * - SEQ IN PTR RTO below needs the full length of the 1510 * frame; in case of P4080_REV_2_HFN_OV_WORKAROUND, 1511 * this means the length of the frame to be processed 1512 * + 4 bytes (the HFN override flag and value). 1513 * The length of the frame to be processed minus 1 1514 * byte is in the VSIL register (because 1515 * VSIL = SIL + 3, due to 1 byte, the header being 1516 * already written by the SEQ STORE above). So for 1517 * calculating the length to use in RTO, I add one 1518 * to the VSIL value in order to obtain the total 1519 * frame length. This helps in case of P4080 which 1520 * can have the value 0 as an operand in a MATH 1521 * command only as SRC1 When the HFN override 1522 * workaround is not enabled, the length of the 1523 * frame is given by the SIL register; the 1524 * calculation is similar to the one in the SEC 4.2 1525 * and SEC 5.3 cases. 1526 */ 1527 if (era_2_sw_hfn_ovrd) 1528 MATHB(p, VSEQOUTSZ, ADD, ONE, MATH1, 4, 1529 0); 1530 else 1531 MATHB(p, SEQINSZ, ADD, MATH3, MATH1, 4, 1532 0); 1533 } 1534 /* 1535 * Placeholder for filling the length in 1536 * SEQIN PTR RTO below 1537 */ 1538 seqin_ptr_read = MOVE(p, DESCBUF, 0, MATH1, 0, 6, IMMED); 1539 seqin_ptr_write = MOVE(p, MATH1, 0, DESCBUF, 0, 8, 1540 WAITCOMP | IMMED); 1541 ALG_OPERATION(p, OP_ALG_ALGSEL_AES, 1542 OP_ALG_AAI_CMAC, 1543 OP_ALG_AS_INITFINAL, 1544 ICV_CHECK_DISABLE, 1545 DIR_DEC); 1546 SEQFIFOLOAD(p, MSG1, 0, VLF | LAST1 | FLUSH1); 1547 MOVEB(p, CONTEXT1, 0, MATH3, 0, 4, WAITCOMP | IMMED); 1548 if (rta_sec_era <= RTA_SEC_ERA_3) 1549 LOAD(p, CLRW_CLR_C1KEY | 1550 CLRW_CLR_C1CTX | 1551 CLRW_CLR_C1ICV | 1552 CLRW_CLR_C1DATAS | 1553 CLRW_CLR_C1MODE, 1554 CLRW, 0, 4, IMMED); 1555 else 1556 LOAD(p, CLRW_RESET_CLS1_CHA | 1557 CLRW_CLR_C1KEY | 1558 CLRW_CLR_C1CTX | 1559 CLRW_CLR_C1ICV | 1560 CLRW_CLR_C1DATAS | 1561 CLRW_CLR_C1MODE, 1562 CLRW, 0, 4, IMMED); 1563 1564 if (rta_sec_era <= RTA_SEC_ERA_3) 1565 LOAD(p, CCTRL_RESET_CHA_ALL, CCTRL, 0, 4, IMMED); 1566 1567 KEY(p, KEY1, cipherdata->key_enc_flags, cipherdata->key, 1568 cipherdata->keylen, INLINE_KEY(cipherdata)); 1569 SET_LABEL(p, local_offset); 1570 MOVEB(p, MATH2, 0, CONTEXT1, 0, 8, IMMED); 1571 SEQINPTR(p, 0, 0, RTO); 1572 1573 if (rta_sec_era == RTA_SEC_ERA_2 && era_2_sw_hfn_ovrd) { 1574 SEQFIFOLOAD(p, SKIP, 5, 0); 1575 MATHB(p, SEQINSZ, ADD, ONE, SEQINSZ, 4, 0); 1576 } 1577 1578 MATHB(p, SEQINSZ, SUB, length, VSEQINSZ, 4, IMMED2); 1579 ALG_OPERATION(p, OP_ALG_ALGSEL_SNOW_F8, 1580 OP_ALG_AAI_F8, 1581 OP_ALG_AS_INITFINAL, 1582 ICV_CHECK_DISABLE, 1583 DIR_ENC); 1584 SEQFIFOSTORE(p, MSG, 0, 0, VLF); 1585 1586 if (rta_sec_era > RTA_SEC_ERA_2 || 1587 (rta_sec_era == RTA_SEC_ERA_2 && 1588 era_2_sw_hfn_ovrd == 0)) 1589 SEQFIFOLOAD(p, SKIP, length, 0); 1590 1591 SEQFIFOLOAD(p, MSG1, 0, VLF); 1592 MOVEB(p, MATH3, 0, IFIFOAB1, 0, 4, LAST1 | FLUSH1 | IMMED); 1593 PATCH_MOVE(p, seqin_ptr_read, local_offset); 1594 PATCH_MOVE(p, seqin_ptr_write, local_offset); 1595 } else { 1596 MOVEB(p, MATH2, 0, CONTEXT1, 0, 8, IMMED); 1597 1598 if (rta_sec_era >= RTA_SEC_ERA_5) 1599 MOVE(p, CONTEXT1, 0, CONTEXT2, 0, 8, IMMED); 1600 1601 if (rta_sec_era > RTA_SEC_ERA_2) 1602 MATHB(p, SEQINSZ, SUB, ZERO, VSEQINSZ, 4, 0); 1603 else 1604 MATHB(p, SEQINSZ, SUB, MATH3, VSEQINSZ, 4, 0); 1605 1606 MATHI(p, SEQINSZ, SUB, PDCP_MAC_I_LEN, VSEQOUTSZ, 4, IMMED2); 1607 /* 1608 * TODO: To be changed when proper support is added in RTA (can't load a 1609 * command that is also written by RTA (or patch it for that matter). 1610 * Change when proper RTA support is added. 1611 */ 1612 if (p->ps) 1613 WORD(p, 0x168B0004); 1614 else 1615 WORD(p, 0x16880404); 1616 1617 jump_back_to_sd_cmd = JUMP(p, 0, LOCAL_JUMP, ALL_TRUE, 0); 1618 /* 1619 * Placeholder for command reading the SEQ OUT command in 1620 * JD. Done for rereading the decrypted data and performing 1621 * the integrity check 1622 */ 1623 /* 1624 * TODO: RTA currently doesn't support patching of length of a MOVE command 1625 * Thus, it is inserted as a raw word, as per PS setting. 1626 */ 1627 if (p->ps) 1628 seq_out_read = MOVE(p, DESCBUF, 0, MATH1, 0, 20, 1629 WAITCOMP | IMMED); 1630 else 1631 seq_out_read = MOVE(p, DESCBUF, 0, MATH1, 0, 16, 1632 WAITCOMP | IMMED); 1633 1634 MATHB(p, MATH1, XOR, CMD_SEQ_IN_PTR ^ CMD_SEQ_OUT_PTR, MATH1, 4, 1635 IMMED2); 1636 /* Placeholder for overwriting the SEQ IN with SEQ OUT */ 1637 /* 1638 * TODO: RTA currently doesn't support patching of length of a MOVE command 1639 * Thus, it is inserted as a raw word, as per PS setting. 1640 */ 1641 if (p->ps) 1642 MOVE(p, MATH1, 0, DESCBUF, 0, 24, IMMED); 1643 else 1644 MOVE(p, MATH1, 0, DESCBUF, 0, 20, IMMED); 1645 1646 KEY(p, KEY1, cipherdata->key_enc_flags, cipherdata->key, 1647 cipherdata->keylen, INLINE_KEY(cipherdata)); 1648 1649 if (rta_sec_era >= RTA_SEC_ERA_4) 1650 MOVE(p, CONTEXT1, 0, CONTEXT2, 0, 8, IMMED); 1651 else 1652 MOVE(p, CONTEXT1, 0, MATH3, 0, 8, IMMED); 1653 1654 ALG_OPERATION(p, OP_ALG_ALGSEL_SNOW_F8, 1655 OP_ALG_AAI_F8, 1656 OP_ALG_AS_INITFINAL, 1657 ICV_CHECK_DISABLE, 1658 DIR_DEC); 1659 SEQFIFOSTORE(p, MSG, 0, 0, VLF | CONT); 1660 SEQFIFOLOAD(p, MSG1, 0, VLF | LAST1 | FLUSH1); 1661 1662 if (rta_sec_era <= RTA_SEC_ERA_3) 1663 move_mac_i_to_desc_buf = MOVE(p, OFIFO, 0, DESCBUF, 0, 1664 4, WAITCOMP | IMMED); 1665 else 1666 MOVE(p, OFIFO, 0, MATH3, 0, 4, IMMED); 1667 1668 if (rta_sec_era <= RTA_SEC_ERA_3) 1669 LOAD(p, CCTRL_RESET_CHA_ALL, CCTRL, 0, 4, IMMED); 1670 else 1671 LOAD(p, CLRW_RESET_CLS1_CHA | 1672 CLRW_CLR_C1KEY | 1673 CLRW_CLR_C1CTX | 1674 CLRW_CLR_C1ICV | 1675 CLRW_CLR_C1DATAS | 1676 CLRW_CLR_C1MODE, 1677 CLRW, 0, 4, IMMED); 1678 1679 KEY(p, KEY1, authdata->key_enc_flags, authdata->key, 1680 authdata->keylen, INLINE_KEY(authdata)); 1681 /* 1682 * Placeholder for jump in SD for executing the new SEQ IN PTR 1683 * command (which is actually the old SEQ OUT PTR command 1684 * copied over from JD. 1685 */ 1686 SET_LABEL(p, jump_to_beginning); 1687 JUMP(p, 1 - jump_to_beginning, LOCAL_JUMP, ALL_TRUE, 0); 1688 SET_LABEL(p, back_to_sd_offset); 1689 ALG_OPERATION(p, OP_ALG_ALGSEL_AES, 1690 OP_ALG_AAI_CMAC, 1691 OP_ALG_AS_INITFINAL, 1692 ICV_CHECK_ENABLE, 1693 DIR_DEC); 1694 1695 /* Read the # of bytes written in the output buffer + 1 (HDR) */ 1696 MATHI(p, VSEQOUTSZ, ADD, length, VSEQINSZ, 4, IMMED2); 1697 1698 if (rta_sec_era <= RTA_SEC_ERA_3) 1699 MOVE(p, MATH3, 0, IFIFOAB1, 0, 8, IMMED); 1700 else 1701 MOVE(p, CONTEXT2, 0, IFIFOAB1, 0, 8, IMMED); 1702 1703 if (rta_sec_era == RTA_SEC_ERA_2 && era_2_sw_hfn_ovrd) 1704 SEQFIFOLOAD(p, SKIP, 4, 0); 1705 1706 SEQFIFOLOAD(p, MSG1, 0, VLF | LAST1 | FLUSH1); 1707 1708 if (rta_sec_era >= RTA_SEC_ERA_4) { 1709 LOAD(p, NFIFOENTRY_STYPE_ALTSOURCE | 1710 NFIFOENTRY_DEST_CLASS1 | 1711 NFIFOENTRY_DTYPE_ICV | 1712 NFIFOENTRY_LC1 | 1713 NFIFOENTRY_FC1 | 4, NFIFO_SZL, 0, 4, IMMED); 1714 MOVE(p, MATH3, 0, ALTSOURCE, 0, 4, IMMED); 1715 } else { 1716 SET_LABEL(p, fifo_load_mac_i_offset); 1717 FIFOLOAD(p, ICV1, fifo_load_mac_i_offset, 4, 1718 LAST1 | FLUSH1 | IMMED); 1719 } 1720 1721 SET_LABEL(p, end_desc); 1722 1723 if (!p->ps) { 1724 PATCH_MOVE(p, seq_out_read, end_desc + 1); 1725 PATCH_JUMP(p, jump_back_to_sd_cmd, 1726 back_to_sd_offset + jump_back_to_sd_cmd - 5); 1727 1728 if (rta_sec_era <= RTA_SEC_ERA_3) 1729 PATCH_MOVE(p, move_mac_i_to_desc_buf, 1730 fifo_load_mac_i_offset + 1); 1731 } else { 1732 PATCH_MOVE(p, seq_out_read, end_desc + 2); 1733 PATCH_JUMP(p, jump_back_to_sd_cmd, 1734 back_to_sd_offset + jump_back_to_sd_cmd - 5); 1735 1736 if (rta_sec_era <= RTA_SEC_ERA_3) 1737 PATCH_MOVE(p, move_mac_i_to_desc_buf, 1738 fifo_load_mac_i_offset + 1); 1739 } 1740 } 1741 1742 return 0; 1743 } 1744 1745 static inline int 1746 pdcp_insert_cplane_aes_snow_op(struct program *p, 1747 bool swap __maybe_unused, 1748 struct alginfo *cipherdata, 1749 struct alginfo *authdata, 1750 unsigned int dir, 1751 enum pdcp_sn_size sn_size, 1752 unsigned char era_2_sw_hfn_ovrd __maybe_unused) 1753 { 1754 uint32_t offset = 0, length = 0, sn_mask = 0; 1755 1756 KEY(p, KEY1, cipherdata->key_enc_flags, cipherdata->key, 1757 cipherdata->keylen, INLINE_KEY(cipherdata)); 1758 KEY(p, KEY2, authdata->key_enc_flags, authdata->key, authdata->keylen, 1759 INLINE_KEY(authdata)); 1760 1761 if ((rta_sec_era >= RTA_SEC_ERA_8 && sn_size != PDCP_SN_SIZE_18) || 1762 (rta_sec_era == RTA_SEC_ERA_10)) { 1763 int pclid; 1764 1765 if (sn_size == PDCP_SN_SIZE_5) 1766 pclid = OP_PCLID_LTE_PDCP_CTRL_MIXED; 1767 else 1768 pclid = OP_PCLID_LTE_PDCP_USER_RN; 1769 1770 PROTOCOL(p, dir, pclid, 1771 ((uint16_t)cipherdata->algtype << 8) | 1772 (uint16_t)authdata->algtype); 1773 1774 return 0; 1775 } 1776 /* Non-proto is supported only for 5bit cplane and 18bit uplane */ 1777 switch (sn_size) { 1778 case PDCP_SN_SIZE_5: 1779 offset = 7; 1780 length = 1; 1781 sn_mask = (swap == false) ? PDCP_C_PLANE_SN_MASK : 1782 PDCP_C_PLANE_SN_MASK_BE; 1783 break; 1784 case PDCP_SN_SIZE_18: 1785 offset = 5; 1786 length = 3; 1787 sn_mask = (swap == false) ? PDCP_U_PLANE_18BIT_SN_MASK : 1788 PDCP_U_PLANE_18BIT_SN_MASK_BE; 1789 break; 1790 case PDCP_SN_SIZE_7: 1791 case PDCP_SN_SIZE_12: 1792 case PDCP_SN_SIZE_15: 1793 pr_err("Invalid sn_size for %s\n", __func__); 1794 return -ENOTSUP; 1795 1796 } 1797 1798 if (dir == OP_TYPE_ENCAP_PROTOCOL) 1799 MATHB(p, SEQINSZ, SUB, length, VSEQINSZ, 4, IMMED2); 1800 1801 SEQLOAD(p, MATH0, offset, length, 0); 1802 JUMP(p, 1, LOCAL_JUMP, ALL_TRUE, CALM); 1803 MOVEB(p, MATH0, offset, IFIFOAB2, 0, length, IMMED); 1804 MATHB(p, MATH0, AND, sn_mask, MATH1, 8, IFB | IMMED2); 1805 1806 SEQSTORE(p, MATH0, offset, length, 0); 1807 MATHB(p, MATH1, SHLD, MATH1, MATH1, 8, 0); 1808 MOVEB(p, DESCBUF, 4, MATH2, 0, 8, WAITCOMP | IMMED); 1809 MATHB(p, MATH1, OR, MATH2, MATH1, 8, 0); 1810 MOVEB(p, MATH1, 0, CONTEXT1, 16, 8, IMMED); 1811 MOVEB(p, MATH1, 0, CONTEXT2, 0, 4, IMMED); 1812 if (swap == false) { 1813 MATHB(p, MATH1, AND, upper_32_bits(PDCP_BEARER_MASK), MATH2, 4, 1814 IMMED2); 1815 MATHB(p, MATH1, AND, lower_32_bits(PDCP_DIR_MASK), MATH3, 4, 1816 IMMED2); 1817 } else { 1818 MATHB(p, MATH1, AND, lower_32_bits(PDCP_BEARER_MASK_BE), MATH2, 1819 4, IMMED2); 1820 MATHB(p, MATH1, AND, upper_32_bits(PDCP_DIR_MASK_BE), MATH3, 1821 4, IMMED2); 1822 } 1823 MATHB(p, MATH3, SHLD, MATH3, MATH3, 8, 0); 1824 MOVEB(p, MATH2, 4, OFIFO, 0, 12, IMMED); 1825 MOVE(p, OFIFO, 0, CONTEXT2, 4, 12, IMMED); 1826 if (dir == OP_TYPE_ENCAP_PROTOCOL) { 1827 MATHB(p, SEQINSZ, ADD, PDCP_MAC_I_LEN, VSEQOUTSZ, 4, IMMED2); 1828 } else { 1829 MATHB(p, SEQINSZ, SUB, PDCP_MAC_I_LEN, MATH1, 4, IMMED2); 1830 1831 MATHB(p, ZERO, ADD, MATH1, VSEQOUTSZ, 4, 0); 1832 MATHB(p, ZERO, ADD, MATH1, VSEQINSZ, 4, 0); 1833 } 1834 1835 if (dir == OP_TYPE_ENCAP_PROTOCOL) 1836 SEQFIFOSTORE(p, MSG, 0, 0, VLF); 1837 else 1838 SEQFIFOSTORE(p, MSG, 0, 0, VLF | CONT); 1839 1840 ALG_OPERATION(p, OP_ALG_ALGSEL_SNOW_F9, 1841 OP_ALG_AAI_F9, 1842 OP_ALG_AS_INITFINAL, 1843 dir == OP_TYPE_ENCAP_PROTOCOL ? 1844 ICV_CHECK_DISABLE : ICV_CHECK_ENABLE, 1845 DIR_DEC); 1846 ALG_OPERATION(p, OP_ALG_ALGSEL_AES, 1847 OP_ALG_AAI_CTR, 1848 OP_ALG_AS_INITFINAL, 1849 ICV_CHECK_DISABLE, 1850 dir == OP_TYPE_ENCAP_PROTOCOL ? DIR_ENC : DIR_DEC); 1851 1852 if (dir == OP_TYPE_ENCAP_PROTOCOL) { 1853 SEQFIFOLOAD(p, MSGINSNOOP, 0, VLF | LAST2); 1854 MOVE(p, CONTEXT2, 0, IFIFOAB1, 0, 4, LAST1 | FLUSH1 | IMMED); 1855 } else { 1856 SEQFIFOLOAD(p, MSGOUTSNOOP, 0, VLF | LAST2); 1857 SEQFIFOLOAD(p, MSG1, 4, LAST1 | FLUSH1); 1858 JUMP(p, 1, LOCAL_JUMP, ALL_TRUE, CLASS1 | NOP | NIFP); 1859 1860 if (rta_sec_era >= RTA_SEC_ERA_6) 1861 LOAD(p, 0, DCTRL, 0, LDLEN_RST_CHA_OFIFO_PTR, IMMED); 1862 1863 MOVE(p, OFIFO, 0, MATH0, 0, 4, WAITCOMP | IMMED); 1864 1865 NFIFOADD(p, IFIFO, ICV2, 4, LAST2); 1866 1867 if (rta_sec_era <= RTA_SEC_ERA_2) { 1868 /* Shut off automatic Info FIFO entries */ 1869 LOAD(p, 0, DCTRL, LDOFF_DISABLE_AUTO_NFIFO, 0, IMMED); 1870 MOVE(p, MATH0, 0, IFIFOAB2, 0, 4, WAITCOMP | IMMED); 1871 } else { 1872 MOVE(p, MATH0, 0, IFIFO, 0, 4, WAITCOMP | IMMED); 1873 } 1874 } 1875 1876 return 0; 1877 } 1878 1879 static inline int 1880 pdcp_insert_cplane_snow_zuc_op(struct program *p, 1881 bool swap __maybe_unused, 1882 struct alginfo *cipherdata, 1883 struct alginfo *authdata, 1884 unsigned int dir, 1885 enum pdcp_sn_size sn_size, 1886 unsigned char era_2_sw_hfn_ovrd __maybe_unused) 1887 { 1888 uint32_t offset = 0, length = 0, sn_mask = 0; 1889 1890 LABEL(keyjump); 1891 REFERENCE(pkeyjump); 1892 1893 if (rta_sec_era < RTA_SEC_ERA_5) { 1894 pr_err("Invalid era for selected algorithm\n"); 1895 return -ENOTSUP; 1896 } 1897 1898 if ((rta_sec_era >= RTA_SEC_ERA_8 && sn_size != PDCP_SN_SIZE_18) || 1899 (rta_sec_era == RTA_SEC_ERA_10)) { 1900 int pclid; 1901 KEY(p, KEY1, cipherdata->key_enc_flags, cipherdata->key, 1902 cipherdata->keylen, INLINE_KEY(cipherdata)); 1903 KEY(p, KEY2, authdata->key_enc_flags, authdata->key, authdata->keylen, 1904 INLINE_KEY(authdata)); 1905 1906 if (sn_size == PDCP_SN_SIZE_5) 1907 pclid = OP_PCLID_LTE_PDCP_CTRL_MIXED; 1908 else 1909 pclid = OP_PCLID_LTE_PDCP_USER_RN; 1910 1911 PROTOCOL(p, dir, pclid, 1912 ((uint16_t)cipherdata->algtype << 8) | 1913 (uint16_t)authdata->algtype); 1914 return 0; 1915 } 1916 /* Non-proto is supported only for 5bit cplane and 18bit uplane */ 1917 switch (sn_size) { 1918 case PDCP_SN_SIZE_5: 1919 offset = 7; 1920 length = 1; 1921 sn_mask = (swap == false) ? PDCP_C_PLANE_SN_MASK : 1922 PDCP_C_PLANE_SN_MASK_BE; 1923 break; 1924 case PDCP_SN_SIZE_18: 1925 offset = 5; 1926 length = 3; 1927 sn_mask = (swap == false) ? PDCP_U_PLANE_18BIT_SN_MASK : 1928 PDCP_U_PLANE_18BIT_SN_MASK_BE; 1929 break; 1930 case PDCP_SN_SIZE_7: 1931 case PDCP_SN_SIZE_12: 1932 case PDCP_SN_SIZE_15: 1933 pr_err("Invalid sn_size for %s\n", __func__); 1934 return -ENOTSUP; 1935 1936 } 1937 1938 pkeyjump = JUMP(p, keyjump, LOCAL_JUMP, ALL_TRUE, SHRD | SELF | BOTH); 1939 KEY(p, KEY1, cipherdata->key_enc_flags, cipherdata->key, 1940 cipherdata->keylen, INLINE_KEY(cipherdata)); 1941 KEY(p, KEY2, authdata->key_enc_flags, authdata->key, authdata->keylen, 1942 INLINE_KEY(authdata)); 1943 1944 SET_LABEL(p, keyjump); 1945 SEQLOAD(p, MATH0, offset, length, 0); 1946 JUMP(p, 1, LOCAL_JUMP, ALL_TRUE, CALM); 1947 MOVEB(p, MATH0, offset, IFIFOAB2, 0, length, IMMED); 1948 MATHB(p, MATH0, AND, sn_mask, MATH1, 8, IFB | IMMED2); 1949 1950 MATHB(p, MATH1, SHLD, MATH1, MATH1, 8, 0); 1951 MOVEB(p, DESCBUF, 4, MATH2, 0, 8, WAITCOMP | IMMED); 1952 MATHB(p, MATH1, OR, MATH2, MATH2, 8, 0); 1953 MOVEB(p, MATH2, 0, CONTEXT1, 0, 8, IMMED); 1954 MOVEB(p, MATH2, 0, CONTEXT2, 0, 8, WAITCOMP | IMMED); 1955 1956 if (dir == OP_TYPE_ENCAP_PROTOCOL) 1957 MATHB(p, SEQINSZ, ADD, PDCP_MAC_I_LEN, VSEQOUTSZ, 4, IMMED2); 1958 else 1959 MATHB(p, SEQINSZ, SUB, PDCP_MAC_I_LEN, VSEQOUTSZ, 4, IMMED2); 1960 1961 MATHB(p, SEQINSZ, SUB, ZERO, VSEQINSZ, 4, 0); 1962 SEQSTORE(p, MATH0, offset, length, 0); 1963 1964 if (dir == OP_TYPE_ENCAP_PROTOCOL) { 1965 SEQFIFOSTORE(p, MSG, 0, 0, VLF); 1966 SEQFIFOLOAD(p, MSGINSNOOP, 0, VLF | LAST2); 1967 } else { 1968 SEQFIFOSTORE(p, MSG, 0, 0, VLF | CONT); 1969 SEQFIFOLOAD(p, MSGOUTSNOOP, 0, VLF | LAST1 | FLUSH1); 1970 } 1971 1972 ALG_OPERATION(p, OP_ALG_ALGSEL_ZUCA, 1973 OP_ALG_AAI_F9, 1974 OP_ALG_AS_INITFINAL, 1975 dir == OP_TYPE_ENCAP_PROTOCOL ? 1976 ICV_CHECK_DISABLE : ICV_CHECK_ENABLE, 1977 DIR_ENC); 1978 1979 ALG_OPERATION(p, OP_ALG_ALGSEL_SNOW_F8, 1980 OP_ALG_AAI_F8, 1981 OP_ALG_AS_INITFINAL, 1982 ICV_CHECK_DISABLE, 1983 dir == OP_TYPE_ENCAP_PROTOCOL ? DIR_ENC : DIR_DEC); 1984 if (dir == OP_TYPE_ENCAP_PROTOCOL) { 1985 MOVE(p, CONTEXT2, 0, IFIFOAB1, 0, 4, LAST1 | FLUSH1 | IMMED); 1986 } else { 1987 /* Save ICV */ 1988 MOVE(p, OFIFO, 0, MATH0, 0, 4, IMMED); 1989 LOAD(p, NFIFOENTRY_STYPE_ALTSOURCE | 1990 NFIFOENTRY_DEST_CLASS2 | 1991 NFIFOENTRY_DTYPE_ICV | 1992 NFIFOENTRY_LC2 | 4, NFIFO_SZL, 0, 4, IMMED); 1993 MOVE(p, MATH0, 0, ALTSOURCE, 0, 4, WAITCOMP | IMMED); 1994 } 1995 1996 /* Reset ZUCA mode and done interrupt */ 1997 LOAD(p, CLRW_CLR_C2MODE, CLRW, 0, 4, IMMED); 1998 LOAD(p, CIRQ_ZADI, ICTRL, 0, 4, IMMED); 1999 2000 PATCH_JUMP(p, pkeyjump, keyjump); 2001 return 0; 2002 } 2003 2004 static inline int 2005 pdcp_insert_cplane_aes_zuc_op(struct program *p, 2006 bool swap __maybe_unused, 2007 struct alginfo *cipherdata, 2008 struct alginfo *authdata, 2009 unsigned int dir, 2010 enum pdcp_sn_size sn_size, 2011 unsigned char era_2_sw_hfn_ovrd __maybe_unused) 2012 { 2013 uint32_t offset = 0, length = 0, sn_mask = 0; 2014 LABEL(keyjump); 2015 REFERENCE(pkeyjump); 2016 2017 if (rta_sec_era < RTA_SEC_ERA_5) { 2018 pr_err("Invalid era for selected algorithm\n"); 2019 return -ENOTSUP; 2020 } 2021 2022 if ((rta_sec_era >= RTA_SEC_ERA_8 && sn_size != PDCP_SN_SIZE_18) || 2023 (rta_sec_era == RTA_SEC_ERA_10)) { 2024 int pclid; 2025 KEY(p, KEY1, cipherdata->key_enc_flags, cipherdata->key, 2026 cipherdata->keylen, INLINE_KEY(cipherdata)); 2027 KEY(p, KEY2, authdata->key_enc_flags, authdata->key, authdata->keylen, 2028 INLINE_KEY(authdata)); 2029 2030 if (sn_size == PDCP_SN_SIZE_5) 2031 pclid = OP_PCLID_LTE_PDCP_CTRL_MIXED; 2032 else 2033 pclid = OP_PCLID_LTE_PDCP_USER_RN; 2034 2035 PROTOCOL(p, dir, pclid, 2036 ((uint16_t)cipherdata->algtype << 8) | 2037 (uint16_t)authdata->algtype); 2038 2039 return 0; 2040 } 2041 /* Non-proto is supported only for 5bit cplane and 18bit uplane */ 2042 switch (sn_size) { 2043 case PDCP_SN_SIZE_5: 2044 offset = 7; 2045 length = 1; 2046 sn_mask = (swap == false) ? PDCP_C_PLANE_SN_MASK : 2047 PDCP_C_PLANE_SN_MASK_BE; 2048 break; 2049 case PDCP_SN_SIZE_18: 2050 offset = 5; 2051 length = 3; 2052 sn_mask = (swap == false) ? PDCP_U_PLANE_18BIT_SN_MASK : 2053 PDCP_U_PLANE_18BIT_SN_MASK_BE; 2054 break; 2055 case PDCP_SN_SIZE_7: 2056 case PDCP_SN_SIZE_12: 2057 case PDCP_SN_SIZE_15: 2058 pr_err("Invalid sn_size for %s\n", __func__); 2059 return -ENOTSUP; 2060 2061 } 2062 pkeyjump = JUMP(p, keyjump, LOCAL_JUMP, ALL_TRUE, SHRD | SELF | BOTH); 2063 KEY(p, KEY1, cipherdata->key_enc_flags, cipherdata->key, 2064 cipherdata->keylen, INLINE_KEY(cipherdata)); 2065 KEY(p, KEY2, authdata->key_enc_flags, authdata->key, authdata->keylen, 2066 INLINE_KEY(authdata)); 2067 2068 SET_LABEL(p, keyjump); 2069 2070 SEQLOAD(p, MATH0, offset, length, 0); 2071 JUMP(p, 1, LOCAL_JUMP, ALL_TRUE, CALM); 2072 MOVEB(p, MATH0, offset, IFIFOAB2, 0, length, IMMED); 2073 MATHB(p, MATH0, AND, sn_mask, MATH1, 8, IFB | IMMED2); 2074 2075 MATHB(p, MATH1, SHLD, MATH1, MATH1, 8, 0); 2076 MOVEB(p, DESCBUF, 4, MATH2, 0, 8, WAITCOMP | IMMED); 2077 MATHB(p, MATH1, OR, MATH2, MATH2, 8, 0); 2078 MOVEB(p, MATH2, 0, CONTEXT1, 16, 8, IMMED); 2079 MOVEB(p, MATH2, 0, CONTEXT2, 0, 8, WAITCOMP | IMMED); 2080 2081 if (dir == OP_TYPE_ENCAP_PROTOCOL) 2082 MATHB(p, SEQINSZ, ADD, PDCP_MAC_I_LEN, VSEQOUTSZ, 4, IMMED2); 2083 else 2084 MATHB(p, SEQINSZ, SUB, PDCP_MAC_I_LEN, VSEQOUTSZ, 4, IMMED2); 2085 2086 MATHB(p, SEQINSZ, SUB, ZERO, VSEQINSZ, 4, 0); 2087 SEQSTORE(p, MATH0, offset, length, 0); 2088 2089 if (dir == OP_TYPE_ENCAP_PROTOCOL) { 2090 SEQFIFOSTORE(p, MSG, 0, 0, VLF); 2091 SEQFIFOLOAD(p, MSGINSNOOP, 0, VLF | LAST2); 2092 } else { 2093 SEQFIFOSTORE(p, MSG, 0, 0, VLF | CONT); 2094 SEQFIFOLOAD(p, MSGOUTSNOOP, 0, VLF | LAST1 | FLUSH1); 2095 } 2096 2097 ALG_OPERATION(p, OP_ALG_ALGSEL_ZUCA, 2098 OP_ALG_AAI_F9, 2099 OP_ALG_AS_INITFINAL, 2100 dir == OP_TYPE_ENCAP_PROTOCOL ? 2101 ICV_CHECK_DISABLE : ICV_CHECK_ENABLE, 2102 DIR_ENC); 2103 2104 ALG_OPERATION(p, OP_ALG_ALGSEL_AES, 2105 OP_ALG_AAI_CTR, 2106 OP_ALG_AS_INITFINAL, 2107 ICV_CHECK_DISABLE, 2108 dir == OP_TYPE_ENCAP_PROTOCOL ? DIR_ENC : DIR_DEC); 2109 2110 if (dir == OP_TYPE_ENCAP_PROTOCOL) { 2111 MOVE(p, CONTEXT2, 0, IFIFOAB1, 0, 4, LAST1 | FLUSH1 | IMMED); 2112 } else { 2113 /* Save ICV */ 2114 MOVE(p, OFIFO, 0, MATH0, 0, 4, IMMED); 2115 2116 LOAD(p, NFIFOENTRY_STYPE_ALTSOURCE | 2117 NFIFOENTRY_DEST_CLASS2 | 2118 NFIFOENTRY_DTYPE_ICV | 2119 NFIFOENTRY_LC2 | 4, NFIFO_SZL, 0, 4, IMMED); 2120 MOVE(p, MATH0, 0, ALTSOURCE, 0, 4, WAITCOMP | IMMED); 2121 } 2122 2123 /* Reset ZUCA mode and done interrupt */ 2124 LOAD(p, CLRW_CLR_C2MODE, CLRW, 0, 4, IMMED); 2125 LOAD(p, CIRQ_ZADI, ICTRL, 0, 4, IMMED); 2126 2127 PATCH_JUMP(p, pkeyjump, keyjump); 2128 2129 return 0; 2130 } 2131 2132 static inline int 2133 pdcp_insert_cplane_zuc_snow_op(struct program *p, 2134 bool swap __maybe_unused, 2135 struct alginfo *cipherdata, 2136 struct alginfo *authdata, 2137 unsigned int dir, 2138 enum pdcp_sn_size sn_size, 2139 unsigned char era_2_sw_hfn_ovrd __maybe_unused) 2140 { 2141 uint32_t offset = 0, length = 0, sn_mask = 0; 2142 LABEL(keyjump); 2143 REFERENCE(pkeyjump); 2144 2145 if (rta_sec_era < RTA_SEC_ERA_5) { 2146 pr_err("Invalid era for selected algorithm\n"); 2147 return -ENOTSUP; 2148 } 2149 2150 if ((rta_sec_era >= RTA_SEC_ERA_8 && sn_size != PDCP_SN_SIZE_18) || 2151 (rta_sec_era == RTA_SEC_ERA_10)) { 2152 int pclid; 2153 KEY(p, KEY1, cipherdata->key_enc_flags, cipherdata->key, 2154 cipherdata->keylen, INLINE_KEY(cipherdata)); 2155 KEY(p, KEY2, authdata->key_enc_flags, authdata->key, authdata->keylen, 2156 INLINE_KEY(authdata)); 2157 2158 if (sn_size == PDCP_SN_SIZE_5) 2159 pclid = OP_PCLID_LTE_PDCP_CTRL_MIXED; 2160 else 2161 pclid = OP_PCLID_LTE_PDCP_USER_RN; 2162 2163 PROTOCOL(p, dir, pclid, 2164 ((uint16_t)cipherdata->algtype << 8) | 2165 (uint16_t)authdata->algtype); 2166 2167 return 0; 2168 } 2169 /* Non-proto is supported only for 5bit cplane and 18bit uplane */ 2170 switch (sn_size) { 2171 case PDCP_SN_SIZE_5: 2172 offset = 7; 2173 length = 1; 2174 sn_mask = (swap == false) ? PDCP_C_PLANE_SN_MASK : 2175 PDCP_C_PLANE_SN_MASK_BE; 2176 break; 2177 case PDCP_SN_SIZE_18: 2178 offset = 5; 2179 length = 3; 2180 sn_mask = (swap == false) ? PDCP_U_PLANE_18BIT_SN_MASK : 2181 PDCP_U_PLANE_18BIT_SN_MASK_BE; 2182 break; 2183 case PDCP_SN_SIZE_7: 2184 case PDCP_SN_SIZE_12: 2185 case PDCP_SN_SIZE_15: 2186 pr_err("Invalid sn_size for %s\n", __func__); 2187 return -ENOTSUP; 2188 2189 } 2190 pkeyjump = JUMP(p, keyjump, LOCAL_JUMP, ALL_TRUE, SHRD | SELF | BOTH); 2191 KEY(p, KEY1, cipherdata->key_enc_flags, cipherdata->key, 2192 cipherdata->keylen, INLINE_KEY(cipherdata)); 2193 KEY(p, KEY2, authdata->key_enc_flags, authdata->key, authdata->keylen, 2194 INLINE_KEY(authdata)); 2195 2196 SET_LABEL(p, keyjump); 2197 SEQLOAD(p, MATH0, offset, length, 0); 2198 JUMP(p, 1, LOCAL_JUMP, ALL_TRUE, CALM); 2199 MOVEB(p, MATH0, offset, IFIFOAB2, 0, length, IMMED); 2200 MATHB(p, MATH0, AND, sn_mask, MATH1, 8, IFB | IMMED2); 2201 2202 MATHB(p, MATH1, SHLD, MATH1, MATH1, 8, 0); 2203 MOVEB(p, DESCBUF, 4, MATH2, 0, 8, WAITCOMP | IMMED); 2204 MATHB(p, MATH1, OR, MATH2, MATH1, 8, 0); 2205 MOVEB(p, MATH1, 0, CONTEXT1, 0, 8, IMMED); 2206 MOVEB(p, MATH1, 0, CONTEXT2, 0, 4, IMMED); 2207 if (swap == false) { 2208 MATHB(p, MATH1, AND, upper_32_bits(PDCP_BEARER_MASK), MATH2, 2209 4, IMMED2); 2210 MATHB(p, MATH1, AND, lower_32_bits(PDCP_DIR_MASK), MATH3, 2211 4, IMMED2); 2212 } else { 2213 MATHB(p, MATH1, AND, lower_32_bits(PDCP_BEARER_MASK_BE), MATH2, 2214 4, IMMED2); 2215 MATHB(p, MATH1, AND, upper_32_bits(PDCP_DIR_MASK_BE), MATH3, 2216 4, IMMED2); 2217 } 2218 MATHB(p, MATH3, SHLD, MATH3, MATH3, 8, 0); 2219 MOVEB(p, MATH2, 4, OFIFO, 0, 12, IMMED); 2220 MOVE(p, OFIFO, 0, CONTEXT2, 4, 12, IMMED); 2221 2222 if (dir == OP_TYPE_ENCAP_PROTOCOL) { 2223 MATHB(p, SEQINSZ, ADD, PDCP_MAC_I_LEN, VSEQOUTSZ, 4, IMMED2); 2224 MATHB(p, SEQINSZ, SUB, ZERO, VSEQINSZ, 4, 0); 2225 } else { 2226 MATHB(p, SEQINSZ, SUB, PDCP_MAC_I_LEN, VSEQOUTSZ, 4, IMMED2); 2227 MATHB(p, VSEQOUTSZ, SUB, ZERO, VSEQINSZ, 4, 0); 2228 } 2229 2230 SEQSTORE(p, MATH0, offset, length, 0); 2231 2232 if (dir == OP_TYPE_ENCAP_PROTOCOL) { 2233 SEQFIFOSTORE(p, MSG, 0, 0, VLF); 2234 SEQFIFOLOAD(p, MSGINSNOOP, 0, VLF | LAST2); 2235 } else { 2236 SEQFIFOSTORE(p, MSG, 0, 0, VLF | CONT); 2237 SEQFIFOLOAD(p, MSGOUTSNOOP, 0, VLF | LAST2); 2238 } 2239 2240 ALG_OPERATION(p, OP_ALG_ALGSEL_SNOW_F9, 2241 OP_ALG_AAI_F9, 2242 OP_ALG_AS_INITFINAL, 2243 dir == OP_TYPE_ENCAP_PROTOCOL ? 2244 ICV_CHECK_DISABLE : ICV_CHECK_ENABLE, 2245 DIR_DEC); 2246 2247 ALG_OPERATION(p, OP_ALG_ALGSEL_ZUCE, 2248 OP_ALG_AAI_F8, 2249 OP_ALG_AS_INITFINAL, 2250 ICV_CHECK_DISABLE, 2251 dir == OP_TYPE_ENCAP_PROTOCOL ? DIR_ENC : DIR_DEC); 2252 2253 if (dir == OP_TYPE_ENCAP_PROTOCOL) { 2254 MOVE(p, CONTEXT2, 0, IFIFOAB1, 0, 4, LAST1 | FLUSH1 | IMMED); 2255 } else { 2256 SEQFIFOLOAD(p, MSG1, 4, LAST1 | FLUSH1); 2257 JUMP(p, 1, LOCAL_JUMP, ALL_TRUE, CLASS1 | NOP | NIFP); 2258 2259 if (rta_sec_era >= RTA_SEC_ERA_6) 2260 /* 2261 * For SEC ERA 6, there's a problem with the OFIFO 2262 * pointer, and thus it needs to be reset here before 2263 * moving to M0. 2264 */ 2265 LOAD(p, 0, DCTRL, 0, LDLEN_RST_CHA_OFIFO_PTR, IMMED); 2266 2267 /* Put ICV to M0 before sending it to C2 for comparison. */ 2268 MOVEB(p, OFIFO, 0, MATH0, 0, 4, WAITCOMP | IMMED); 2269 2270 LOAD(p, NFIFOENTRY_STYPE_ALTSOURCE | 2271 NFIFOENTRY_DEST_CLASS2 | 2272 NFIFOENTRY_DTYPE_ICV | 2273 NFIFOENTRY_LC2 | 4, NFIFO_SZL, 0, 4, IMMED); 2274 MOVEB(p, MATH0, 0, ALTSOURCE, 0, 4, IMMED); 2275 } 2276 2277 PATCH_JUMP(p, pkeyjump, keyjump); 2278 return 0; 2279 } 2280 2281 static inline int 2282 pdcp_insert_cplane_zuc_aes_op(struct program *p, 2283 bool swap __maybe_unused, 2284 struct alginfo *cipherdata, 2285 struct alginfo *authdata, 2286 unsigned int dir, 2287 enum pdcp_sn_size sn_size, 2288 unsigned char era_2_sw_hfn_ovrd __maybe_unused) 2289 { 2290 uint32_t offset = 0, length = 0, sn_mask = 0; 2291 if (rta_sec_era < RTA_SEC_ERA_5) { 2292 pr_err("Invalid era for selected algorithm\n"); 2293 return -ENOTSUP; 2294 } 2295 2296 if ((rta_sec_era >= RTA_SEC_ERA_8 && sn_size != PDCP_SN_SIZE_18) || 2297 (rta_sec_era == RTA_SEC_ERA_10)) { 2298 int pclid; 2299 2300 KEY(p, KEY1, cipherdata->key_enc_flags, cipherdata->key, 2301 cipherdata->keylen, INLINE_KEY(cipherdata)); 2302 KEY(p, KEY2, authdata->key_enc_flags, authdata->key, 2303 authdata->keylen, INLINE_KEY(authdata)); 2304 2305 if (sn_size == PDCP_SN_SIZE_5) 2306 pclid = OP_PCLID_LTE_PDCP_CTRL_MIXED; 2307 else 2308 pclid = OP_PCLID_LTE_PDCP_USER_RN; 2309 2310 PROTOCOL(p, dir, pclid, 2311 ((uint16_t)cipherdata->algtype << 8) | 2312 (uint16_t)authdata->algtype); 2313 return 0; 2314 } 2315 /* Non-proto is supported only for 5bit cplane and 18bit uplane */ 2316 switch (sn_size) { 2317 case PDCP_SN_SIZE_5: 2318 offset = 7; 2319 length = 1; 2320 sn_mask = (swap == false) ? PDCP_C_PLANE_SN_MASK : 2321 PDCP_C_PLANE_SN_MASK_BE; 2322 break; 2323 case PDCP_SN_SIZE_18: 2324 offset = 5; 2325 length = 3; 2326 sn_mask = (swap == false) ? PDCP_U_PLANE_18BIT_SN_MASK : 2327 PDCP_U_PLANE_18BIT_SN_MASK_BE; 2328 break; 2329 case PDCP_SN_SIZE_7: 2330 case PDCP_SN_SIZE_12: 2331 case PDCP_SN_SIZE_15: 2332 pr_err("Invalid sn_size for %s\n", __func__); 2333 return -ENOTSUP; 2334 } 2335 2336 SEQLOAD(p, MATH0, offset, length, 0); 2337 JUMP(p, 1, LOCAL_JUMP, ALL_TRUE, CALM); 2338 MATHB(p, MATH0, AND, sn_mask, MATH1, 8, IFB | IMMED2); 2339 2340 MATHB(p, MATH1, SHLD, MATH1, MATH1, 8, 0); 2341 MOVEB(p, DESCBUF, 4, MATH2, 0, 0x08, WAITCOMP | IMMED); 2342 MATHB(p, MATH1, OR, MATH2, MATH2, 8, 0); 2343 SEQSTORE(p, MATH0, offset, length, 0); 2344 if (dir == OP_TYPE_ENCAP_PROTOCOL) { 2345 KEY(p, KEY1, authdata->key_enc_flags, authdata->key, 2346 authdata->keylen, INLINE_KEY(authdata)); 2347 MOVEB(p, MATH2, 0, IFIFOAB1, 0, 0x08, IMMED); 2348 MOVEB(p, MATH0, offset, IFIFOAB1, 0, length, IMMED); 2349 2350 MATHB(p, SEQINSZ, SUB, ZERO, VSEQINSZ, 4, 0); 2351 MATHB(p, VSEQINSZ, ADD, PDCP_MAC_I_LEN, VSEQOUTSZ, 4, IMMED2); 2352 2353 ALG_OPERATION(p, OP_ALG_ALGSEL_AES, 2354 OP_ALG_AAI_CMAC, 2355 OP_ALG_AS_INITFINAL, 2356 ICV_CHECK_DISABLE, 2357 DIR_DEC); 2358 SEQFIFOLOAD(p, MSG1, 0, VLF | LAST1 | FLUSH1); 2359 MOVEB(p, CONTEXT1, 0, MATH3, 0, 4, WAITCOMP | IMMED); 2360 LOAD(p, CLRW_RESET_CLS1_CHA | 2361 CLRW_CLR_C1KEY | 2362 CLRW_CLR_C1CTX | 2363 CLRW_CLR_C1ICV | 2364 CLRW_CLR_C1DATAS | 2365 CLRW_CLR_C1MODE, 2366 CLRW, 0, 4, IMMED); 2367 2368 KEY(p, KEY1, cipherdata->key_enc_flags, cipherdata->key, 2369 cipherdata->keylen, INLINE_KEY(cipherdata)); 2370 2371 MOVEB(p, MATH2, 0, CONTEXT1, 0, 8, IMMED); 2372 SEQINPTR(p, 0, PDCP_NULL_MAX_FRAME_LEN, RTO); 2373 2374 ALG_OPERATION(p, OP_ALG_ALGSEL_ZUCE, 2375 OP_ALG_AAI_F8, 2376 OP_ALG_AS_INITFINAL, 2377 ICV_CHECK_DISABLE, 2378 DIR_ENC); 2379 SEQFIFOSTORE(p, MSG, 0, 0, VLF); 2380 2381 SEQFIFOLOAD(p, SKIP, length, 0); 2382 2383 SEQFIFOLOAD(p, MSG1, 0, VLF); 2384 MOVEB(p, MATH3, 0, IFIFOAB1, 0, 4, LAST1 | FLUSH1 | IMMED); 2385 } else { 2386 MOVEB(p, MATH2, 0, CONTEXT1, 0, 8, IMMED); 2387 2388 MOVE(p, CONTEXT1, 0, CONTEXT2, 0, 8, IMMED); 2389 2390 MATHB(p, SEQINSZ, SUB, ZERO, VSEQINSZ, 4, 0); 2391 2392 MATHB(p, SEQINSZ, SUB, PDCP_MAC_I_LEN, VSEQOUTSZ, 4, IMMED2); 2393 2394 KEY(p, KEY1, cipherdata->key_enc_flags, cipherdata->key, 2395 cipherdata->keylen, INLINE_KEY(cipherdata)); 2396 2397 MOVE(p, CONTEXT1, 0, CONTEXT2, 0, 8, IMMED); 2398 2399 ALG_OPERATION(p, OP_ALG_ALGSEL_ZUCE, 2400 OP_ALG_AAI_F8, 2401 OP_ALG_AS_INITFINAL, 2402 ICV_CHECK_DISABLE, 2403 DIR_DEC); 2404 SEQFIFOSTORE(p, MSG, 0, 0, VLF | CONT); 2405 SEQFIFOLOAD(p, MSG1, 0, VLF | LAST1 | FLUSH1); 2406 2407 MOVEB(p, OFIFO, 0, MATH3, 0, 4, IMMED); 2408 2409 LOAD(p, CLRW_RESET_CLS1_CHA | 2410 CLRW_CLR_C1KEY | 2411 CLRW_CLR_C1CTX | 2412 CLRW_CLR_C1ICV | 2413 CLRW_CLR_C1DATAS | 2414 CLRW_CLR_C1MODE, 2415 CLRW, 0, 4, IMMED); 2416 2417 KEY(p, KEY1, authdata->key_enc_flags, authdata->key, 2418 authdata->keylen, INLINE_KEY(authdata)); 2419 2420 SEQINPTR(p, 0, 0, SOP); 2421 2422 ALG_OPERATION(p, OP_ALG_ALGSEL_AES, 2423 OP_ALG_AAI_CMAC, 2424 OP_ALG_AS_INITFINAL, 2425 ICV_CHECK_ENABLE, 2426 DIR_DEC); 2427 2428 MATHB(p, SEQINSZ, SUB, ZERO, VSEQINSZ, 4, 0); 2429 2430 MOVE(p, CONTEXT2, 0, IFIFOAB1, 0, 8, IMMED); 2431 2432 SEQFIFOLOAD(p, MSG1, 0, VLF | LAST1 | FLUSH1); 2433 2434 LOAD(p, NFIFOENTRY_STYPE_ALTSOURCE | 2435 NFIFOENTRY_DEST_CLASS1 | 2436 NFIFOENTRY_DTYPE_ICV | 2437 NFIFOENTRY_LC1 | 2438 NFIFOENTRY_FC1 | 4, NFIFO_SZL, 0, 4, IMMED); 2439 MOVEB(p, MATH3, 0, ALTSOURCE, 0, 4, IMMED); 2440 } 2441 2442 return 0; 2443 } 2444 2445 static inline int 2446 pdcp_insert_uplane_no_int_op(struct program *p, 2447 bool swap __maybe_unused, 2448 struct alginfo *cipherdata, 2449 unsigned int dir, 2450 enum pdcp_sn_size sn_size) 2451 { 2452 int op; 2453 uint32_t sn_mask; 2454 2455 /* Insert Cipher Key */ 2456 KEY(p, KEY1, cipherdata->key_enc_flags, cipherdata->key, 2457 cipherdata->keylen, INLINE_KEY(cipherdata)); 2458 2459 if ((rta_sec_era >= RTA_SEC_ERA_8 && sn_size == PDCP_SN_SIZE_15) || 2460 (rta_sec_era >= RTA_SEC_ERA_10)) { 2461 PROTOCOL(p, dir, OP_PCLID_LTE_PDCP_USER, 2462 (uint16_t)cipherdata->algtype); 2463 return 0; 2464 } 2465 2466 if (sn_size == PDCP_SN_SIZE_15) { 2467 SEQLOAD(p, MATH0, 6, 2, 0); 2468 sn_mask = (swap == false) ? PDCP_U_PLANE_15BIT_SN_MASK : 2469 PDCP_U_PLANE_15BIT_SN_MASK_BE; 2470 } else { /* SN Size == PDCP_SN_SIZE_18 */ 2471 SEQLOAD(p, MATH0, 5, 3, 0); 2472 sn_mask = (swap == false) ? PDCP_U_PLANE_18BIT_SN_MASK : 2473 PDCP_U_PLANE_18BIT_SN_MASK_BE; 2474 } 2475 JUMP(p, 1, LOCAL_JUMP, ALL_TRUE, CALM); 2476 MATHB(p, MATH0, AND, sn_mask, MATH1, 8, IFB | IMMED2); 2477 2478 if (sn_size == PDCP_SN_SIZE_15) 2479 SEQSTORE(p, MATH0, 6, 2, 0); 2480 else /* SN Size == PDCP_SN_SIZE_18 */ 2481 SEQSTORE(p, MATH0, 5, 3, 0); 2482 2483 MATHB(p, MATH1, SHLD, MATH1, MATH1, 8, 0); 2484 MOVEB(p, DESCBUF, 8, MATH2, 0, 8, WAITCOMP | IMMED); 2485 MATHB(p, MATH1, OR, MATH2, MATH2, 8, 0); 2486 2487 MATHB(p, SEQINSZ, SUB, MATH3, VSEQINSZ, 4, 0); 2488 MATHB(p, SEQINSZ, SUB, MATH3, VSEQOUTSZ, 4, 0); 2489 2490 SEQFIFOSTORE(p, MSG, 0, 0, VLF); 2491 2492 op = dir == OP_TYPE_ENCAP_PROTOCOL ? DIR_ENC : DIR_DEC; 2493 switch (cipherdata->algtype) { 2494 case PDCP_CIPHER_TYPE_SNOW: 2495 MOVEB(p, MATH2, 0, CONTEXT1, 0, 8, WAITCOMP | IMMED); 2496 ALG_OPERATION(p, OP_ALG_ALGSEL_SNOW_F8, 2497 OP_ALG_AAI_F8, 2498 OP_ALG_AS_INITFINAL, 2499 ICV_CHECK_DISABLE, 2500 op); 2501 break; 2502 2503 case PDCP_CIPHER_TYPE_AES: 2504 MOVEB(p, MATH2, 0, CONTEXT1, 0x10, 0x10, WAITCOMP | IMMED); 2505 ALG_OPERATION(p, OP_ALG_ALGSEL_AES, 2506 OP_ALG_AAI_CTR, 2507 OP_ALG_AS_INITFINAL, 2508 ICV_CHECK_DISABLE, 2509 op); 2510 break; 2511 2512 case PDCP_CIPHER_TYPE_ZUC: 2513 if (rta_sec_era < RTA_SEC_ERA_5) { 2514 pr_err("Invalid era for selected algorithm\n"); 2515 return -ENOTSUP; 2516 } 2517 MOVEB(p, MATH2, 0, CONTEXT1, 0, 0x08, IMMED); 2518 MOVEB(p, MATH2, 0, CONTEXT1, 0x08, 0x08, WAITCOMP | IMMED); 2519 2520 ALG_OPERATION(p, OP_ALG_ALGSEL_ZUCE, 2521 OP_ALG_AAI_F8, 2522 OP_ALG_AS_INITFINAL, 2523 ICV_CHECK_DISABLE, 2524 op); 2525 break; 2526 2527 default: 2528 pr_err("%s: Invalid encrypt algorithm selected: %d\n", 2529 "pdcp_insert_uplane_15bit_op", cipherdata->algtype); 2530 return -EINVAL; 2531 } 2532 2533 SEQFIFOLOAD(p, MSG1, 0, VLF | LAST1 | FLUSH1); 2534 2535 return 0; 2536 } 2537 2538 /* 2539 * Function for inserting the snippet of code responsible for creating 2540 * the HFN override code via either DPOVRD or via the input frame. 2541 */ 2542 static inline int 2543 insert_hfn_ov_op(struct program *p, 2544 uint32_t shift, 2545 enum pdb_type_e pdb_type, 2546 unsigned char era_2_sw_hfn_ovrd) 2547 { 2548 uint32_t imm = PDCP_DPOVRD_HFN_OV_EN; 2549 uint16_t hfn_pdb_offset; 2550 LABEL(keyjump); 2551 REFERENCE(pkeyjump); 2552 2553 if (rta_sec_era == RTA_SEC_ERA_2 && !era_2_sw_hfn_ovrd) 2554 return 0; 2555 2556 switch (pdb_type) { 2557 case PDCP_PDB_TYPE_NO_PDB: 2558 /* 2559 * If there is no PDB, then HFN override mechanism does not 2560 * make any sense, thus in this case the function will 2561 * return the pointer to the current position in the 2562 * descriptor buffer 2563 */ 2564 return 0; 2565 2566 case PDCP_PDB_TYPE_REDUCED_PDB: 2567 hfn_pdb_offset = 4; 2568 break; 2569 2570 case PDCP_PDB_TYPE_FULL_PDB: 2571 hfn_pdb_offset = 8; 2572 break; 2573 2574 default: 2575 return -EINVAL; 2576 } 2577 2578 if (rta_sec_era > RTA_SEC_ERA_2) { 2579 MATHB(p, DPOVRD, AND, imm, NONE, 8, IFB | IMMED2); 2580 } else { 2581 SEQLOAD(p, MATH0, 4, 4, 0); 2582 JUMP(p, 1, LOCAL_JUMP, ALL_TRUE, CALM); 2583 MATHB(p, MATH0, AND, imm, NONE, 8, IFB | IMMED2); 2584 SEQSTORE(p, MATH0, 4, 4, 0); 2585 } 2586 2587 pkeyjump = JUMP(p, keyjump, LOCAL_JUMP, ALL_TRUE, MATH_Z); 2588 2589 if (rta_sec_era > RTA_SEC_ERA_2) 2590 MATHI(p, DPOVRD, LSHIFT, shift, MATH0, 4, IMMED2); 2591 else 2592 MATHB(p, MATH0, LSHIFT, shift, MATH0, 4, IMMED2); 2593 2594 MATHB(p, MATH0, SHLD, MATH0, MATH0, 8, 0); 2595 MOVE(p, MATH0, 0, DESCBUF, hfn_pdb_offset, 4, IMMED); 2596 2597 if (rta_sec_era >= RTA_SEC_ERA_8) 2598 /* 2599 * For ERA8, DPOVRD could be handled by the PROTOCOL command 2600 * itself. For now, this is not done. Thus, clear DPOVRD here 2601 * to alleviate any side-effects. 2602 */ 2603 MATHB(p, DPOVRD, AND, ZERO, DPOVRD, 4, STL); 2604 2605 SET_LABEL(p, keyjump); 2606 PATCH_JUMP(p, pkeyjump, keyjump); 2607 return 0; 2608 } 2609 2610 /* 2611 * PDCP Control PDB creation function 2612 */ 2613 static inline enum pdb_type_e 2614 cnstr_pdcp_c_plane_pdb(struct program *p, 2615 uint32_t hfn, 2616 enum pdcp_sn_size sn_size, 2617 unsigned char bearer, 2618 unsigned char direction, 2619 uint32_t hfn_threshold, 2620 struct alginfo *cipherdata, 2621 struct alginfo *authdata) 2622 { 2623 struct pdcp_pdb pdb; 2624 enum pdb_type_e 2625 pdb_mask[PDCP_CIPHER_TYPE_INVALID][PDCP_AUTH_TYPE_INVALID] = { 2626 { /* NULL */ 2627 PDCP_PDB_TYPE_NO_PDB, /* NULL */ 2628 PDCP_PDB_TYPE_FULL_PDB, /* SNOW f9 */ 2629 PDCP_PDB_TYPE_FULL_PDB, /* AES CMAC */ 2630 PDCP_PDB_TYPE_FULL_PDB /* ZUC-I */ 2631 }, 2632 { /* SNOW f8 */ 2633 PDCP_PDB_TYPE_FULL_PDB, /* NULL */ 2634 PDCP_PDB_TYPE_FULL_PDB, /* SNOW f9 */ 2635 PDCP_PDB_TYPE_REDUCED_PDB, /* AES CMAC */ 2636 PDCP_PDB_TYPE_REDUCED_PDB /* ZUC-I */ 2637 }, 2638 { /* AES CTR */ 2639 PDCP_PDB_TYPE_FULL_PDB, /* NULL */ 2640 PDCP_PDB_TYPE_REDUCED_PDB, /* SNOW f9 */ 2641 PDCP_PDB_TYPE_FULL_PDB, /* AES CMAC */ 2642 PDCP_PDB_TYPE_REDUCED_PDB /* ZUC-I */ 2643 }, 2644 { /* ZUC-E */ 2645 PDCP_PDB_TYPE_FULL_PDB, /* NULL */ 2646 PDCP_PDB_TYPE_REDUCED_PDB, /* SNOW f9 */ 2647 PDCP_PDB_TYPE_REDUCED_PDB, /* AES CMAC */ 2648 PDCP_PDB_TYPE_FULL_PDB /* ZUC-I */ 2649 }, 2650 }; 2651 2652 if (rta_sec_era >= RTA_SEC_ERA_8) { 2653 memset(&pdb, 0x00, sizeof(struct pdcp_pdb)); 2654 2655 /* To support 12-bit seq numbers, we use u-plane opt in pdb. 2656 * SEC supports 5-bit only with c-plane opt in pdb. 2657 */ 2658 if (sn_size == PDCP_SN_SIZE_12) { 2659 pdb.hfn_res = hfn << PDCP_U_PLANE_PDB_LONG_SN_HFN_SHIFT; 2660 pdb.bearer_dir_res = (uint32_t) 2661 ((bearer << PDCP_U_PLANE_PDB_BEARER_SHIFT) | 2662 (direction << PDCP_U_PLANE_PDB_DIR_SHIFT)); 2663 2664 pdb.hfn_thr_res = 2665 hfn_threshold << PDCP_U_PLANE_PDB_LONG_SN_HFN_THR_SHIFT; 2666 2667 } else { 2668 /* This means 5-bit c-plane. 2669 * Here we use c-plane opt in pdb 2670 */ 2671 2672 /* This is a HW issue. Bit 2 should be set to zero, 2673 * but it does not work this way. Override here. 2674 */ 2675 pdb.opt_res.rsvd = 0x00000002; 2676 2677 /* Copy relevant information from user to PDB */ 2678 pdb.hfn_res = hfn << PDCP_C_PLANE_PDB_HFN_SHIFT; 2679 pdb.bearer_dir_res = (uint32_t) 2680 ((bearer << PDCP_C_PLANE_PDB_BEARER_SHIFT) | 2681 (direction << PDCP_C_PLANE_PDB_DIR_SHIFT)); 2682 pdb.hfn_thr_res = 2683 hfn_threshold << PDCP_C_PLANE_PDB_HFN_THR_SHIFT; 2684 } 2685 2686 /* copy PDB in descriptor*/ 2687 __rta_out32(p, pdb.opt_res.opt); 2688 __rta_out32(p, pdb.hfn_res); 2689 __rta_out32(p, pdb.bearer_dir_res); 2690 __rta_out32(p, pdb.hfn_thr_res); 2691 2692 return PDCP_PDB_TYPE_FULL_PDB; 2693 } 2694 2695 switch (pdb_mask[cipherdata->algtype][authdata->algtype]) { 2696 case PDCP_PDB_TYPE_NO_PDB: 2697 break; 2698 2699 case PDCP_PDB_TYPE_REDUCED_PDB: 2700 __rta_out32(p, (hfn << PDCP_C_PLANE_PDB_HFN_SHIFT)); 2701 __rta_out32(p, 2702 (uint32_t)((bearer << 2703 PDCP_C_PLANE_PDB_BEARER_SHIFT) | 2704 (direction << 2705 PDCP_C_PLANE_PDB_DIR_SHIFT))); 2706 break; 2707 2708 case PDCP_PDB_TYPE_FULL_PDB: 2709 memset(&pdb, 0x00, sizeof(struct pdcp_pdb)); 2710 2711 /* This is a HW issue. Bit 2 should be set to zero, 2712 * but it does not work this way. Override here. 2713 */ 2714 pdb.opt_res.rsvd = 0x00000002; 2715 2716 /* Copy relevant information from user to PDB */ 2717 pdb.hfn_res = hfn << PDCP_C_PLANE_PDB_HFN_SHIFT; 2718 pdb.bearer_dir_res = (uint32_t) 2719 ((bearer << PDCP_C_PLANE_PDB_BEARER_SHIFT) | 2720 (direction << PDCP_C_PLANE_PDB_DIR_SHIFT)); 2721 pdb.hfn_thr_res = 2722 hfn_threshold << PDCP_C_PLANE_PDB_HFN_THR_SHIFT; 2723 2724 /* copy PDB in descriptor*/ 2725 __rta_out32(p, pdb.opt_res.opt); 2726 __rta_out32(p, pdb.hfn_res); 2727 __rta_out32(p, pdb.bearer_dir_res); 2728 __rta_out32(p, pdb.hfn_thr_res); 2729 2730 break; 2731 2732 default: 2733 return PDCP_PDB_TYPE_INVALID; 2734 } 2735 2736 return pdb_mask[cipherdata->algtype][authdata->algtype]; 2737 } 2738 2739 /* 2740 * PDCP UPlane PDB creation function 2741 */ 2742 static inline enum pdb_type_e 2743 cnstr_pdcp_u_plane_pdb(struct program *p, 2744 enum pdcp_sn_size sn_size, 2745 uint32_t hfn, unsigned short bearer, 2746 unsigned short direction, 2747 uint32_t hfn_threshold, 2748 struct alginfo *cipherdata, 2749 struct alginfo *authdata) 2750 { 2751 struct pdcp_pdb pdb; 2752 enum pdb_type_e pdb_type = PDCP_PDB_TYPE_FULL_PDB; 2753 enum pdb_type_e 2754 pdb_mask[PDCP_CIPHER_TYPE_INVALID][PDCP_AUTH_TYPE_INVALID] = { 2755 { /* NULL */ 2756 PDCP_PDB_TYPE_NO_PDB, /* NULL */ 2757 PDCP_PDB_TYPE_FULL_PDB, /* SNOW f9 */ 2758 PDCP_PDB_TYPE_FULL_PDB, /* AES CMAC */ 2759 PDCP_PDB_TYPE_FULL_PDB /* ZUC-I */ 2760 }, 2761 { /* SNOW f8 */ 2762 PDCP_PDB_TYPE_FULL_PDB, /* NULL */ 2763 PDCP_PDB_TYPE_FULL_PDB, /* SNOW f9 */ 2764 PDCP_PDB_TYPE_REDUCED_PDB, /* AES CMAC */ 2765 PDCP_PDB_TYPE_REDUCED_PDB /* ZUC-I */ 2766 }, 2767 { /* AES CTR */ 2768 PDCP_PDB_TYPE_FULL_PDB, /* NULL */ 2769 PDCP_PDB_TYPE_REDUCED_PDB, /* SNOW f9 */ 2770 PDCP_PDB_TYPE_FULL_PDB, /* AES CMAC */ 2771 PDCP_PDB_TYPE_REDUCED_PDB /* ZUC-I */ 2772 }, 2773 { /* ZUC-E */ 2774 PDCP_PDB_TYPE_FULL_PDB, /* NULL */ 2775 PDCP_PDB_TYPE_REDUCED_PDB, /* SNOW f9 */ 2776 PDCP_PDB_TYPE_REDUCED_PDB, /* AES CMAC */ 2777 PDCP_PDB_TYPE_FULL_PDB /* ZUC-I */ 2778 }, 2779 }; 2780 2781 /* Read options from user */ 2782 /* Depending on sequence number length, the HFN and HFN threshold 2783 * have different lengths. 2784 */ 2785 memset(&pdb, 0x00, sizeof(struct pdcp_pdb)); 2786 2787 switch (sn_size) { 2788 case PDCP_SN_SIZE_7: 2789 pdb.opt_res.opt |= PDCP_U_PLANE_PDB_OPT_SHORT_SN; 2790 pdb.hfn_res = hfn << PDCP_U_PLANE_PDB_SHORT_SN_HFN_SHIFT; 2791 pdb.hfn_thr_res = 2792 hfn_threshold<<PDCP_U_PLANE_PDB_SHORT_SN_HFN_THR_SHIFT; 2793 break; 2794 2795 case PDCP_SN_SIZE_12: 2796 pdb.opt_res.opt &= (uint32_t)(~PDCP_U_PLANE_PDB_OPT_SHORT_SN); 2797 pdb.hfn_res = hfn << PDCP_U_PLANE_PDB_LONG_SN_HFN_SHIFT; 2798 pdb.hfn_thr_res = 2799 hfn_threshold<<PDCP_U_PLANE_PDB_LONG_SN_HFN_THR_SHIFT; 2800 break; 2801 2802 case PDCP_SN_SIZE_15: 2803 pdb.opt_res.opt = (uint32_t)(PDCP_U_PLANE_PDB_OPT_15B_SN); 2804 pdb.hfn_res = hfn << PDCP_U_PLANE_PDB_15BIT_SN_HFN_SHIFT; 2805 pdb.hfn_thr_res = 2806 hfn_threshold<<PDCP_U_PLANE_PDB_15BIT_SN_HFN_THR_SHIFT; 2807 break; 2808 2809 case PDCP_SN_SIZE_18: 2810 pdb.opt_res.opt = (uint32_t)(PDCP_U_PLANE_PDB_OPT_18B_SN); 2811 pdb.hfn_res = hfn << PDCP_U_PLANE_PDB_18BIT_SN_HFN_SHIFT; 2812 pdb.hfn_thr_res = 2813 hfn_threshold<<PDCP_U_PLANE_PDB_18BIT_SN_HFN_THR_SHIFT; 2814 2815 if (rta_sec_era <= RTA_SEC_ERA_8) { 2816 if (cipherdata && authdata) 2817 pdb_type = pdb_mask[cipherdata->algtype] 2818 [authdata->algtype]; 2819 } 2820 break; 2821 2822 default: 2823 pr_err("Invalid Sequence Number Size setting in PDB\n"); 2824 return -EINVAL; 2825 } 2826 2827 pdb.bearer_dir_res = (uint32_t) 2828 ((bearer << PDCP_U_PLANE_PDB_BEARER_SHIFT) | 2829 (direction << PDCP_U_PLANE_PDB_DIR_SHIFT)); 2830 2831 switch (pdb_type) { 2832 case PDCP_PDB_TYPE_NO_PDB: 2833 break; 2834 2835 case PDCP_PDB_TYPE_REDUCED_PDB: 2836 __rta_out32(p, pdb.hfn_res); 2837 __rta_out32(p, pdb.bearer_dir_res); 2838 break; 2839 2840 case PDCP_PDB_TYPE_FULL_PDB: 2841 /* copy PDB in descriptor*/ 2842 __rta_out32(p, pdb.opt_res.opt); 2843 __rta_out32(p, pdb.hfn_res); 2844 __rta_out32(p, pdb.bearer_dir_res); 2845 __rta_out32(p, pdb.hfn_thr_res); 2846 2847 break; 2848 2849 default: 2850 return PDCP_PDB_TYPE_INVALID; 2851 } 2852 2853 return pdb_type; 2854 } 2855 /** 2856 * cnstr_shdsc_pdcp_c_plane_encap - Function for creating a PDCP Control Plane 2857 * encapsulation descriptor. 2858 * @descbuf: pointer to buffer for descriptor construction 2859 * @ps: if 36/40bit addressing is desired, this parameter must be true 2860 * @swap: must be true when core endianness doesn't match SEC endianness 2861 * @hfn: starting Hyper Frame Number to be used together with the SN from the 2862 * PDCP frames. 2863 * @sn_size: size of sequence numbers, only 5/12 bit sequence numbers are valid 2864 * @bearer: radio bearer ID 2865 * @direction: the direction of the PDCP frame (UL/DL) 2866 * @hfn_threshold: HFN value that once reached triggers a warning from SEC that 2867 * keys should be renegotiated at the earliest convenience. 2868 * @cipherdata: pointer to block cipher transform definitions 2869 * Valid algorithm values are those from cipher_type_pdcp enum. 2870 * @authdata: pointer to authentication transform definitions 2871 * Valid algorithm values are those from auth_type_pdcp enum. 2872 * @era_2_sw_hfn_ovrd: if software HFN override mechanism is desired for 2873 * this descriptor. Note: Can only be used for 2874 * SEC ERA 2. 2875 * Return: size of descriptor written in words or negative number on error. 2876 * Once the function returns, the value of this parameter can be used 2877 * for reclaiming the space that wasn't used for the descriptor. 2878 * 2879 * Note: descbuf must be large enough to contain a full 256 byte long 2880 * descriptor; after the function returns, by subtracting the actual number of 2881 * bytes used, the user can reuse the remaining buffer space for other purposes. 2882 */ 2883 static inline int 2884 cnstr_shdsc_pdcp_c_plane_encap(uint32_t *descbuf, 2885 bool ps, 2886 bool swap, 2887 uint32_t hfn, 2888 enum pdcp_sn_size sn_size, 2889 unsigned char bearer, 2890 unsigned char direction, 2891 uint32_t hfn_threshold, 2892 struct alginfo *cipherdata, 2893 struct alginfo *authdata, 2894 unsigned char era_2_sw_hfn_ovrd) 2895 { 2896 static int 2897 (*pdcp_cp_fp[PDCP_CIPHER_TYPE_INVALID][PDCP_AUTH_TYPE_INVALID]) 2898 (struct program*, bool swap, struct alginfo *, 2899 struct alginfo *, unsigned int, enum pdcp_sn_size, 2900 unsigned char __maybe_unused) = { 2901 { /* NULL */ 2902 pdcp_insert_cplane_null_op, /* NULL */ 2903 pdcp_insert_cplane_int_only_op, /* SNOW f9 */ 2904 pdcp_insert_cplane_int_only_op, /* AES CMAC */ 2905 pdcp_insert_cplane_int_only_op /* ZUC-I */ 2906 }, 2907 { /* SNOW f8 */ 2908 pdcp_insert_cplane_enc_only_op, /* NULL */ 2909 pdcp_insert_cplane_acc_op, /* SNOW f9 */ 2910 pdcp_insert_cplane_snow_aes_op, /* AES CMAC */ 2911 pdcp_insert_cplane_snow_zuc_op /* ZUC-I */ 2912 }, 2913 { /* AES CTR */ 2914 pdcp_insert_cplane_enc_only_op, /* NULL */ 2915 pdcp_insert_cplane_aes_snow_op, /* SNOW f9 */ 2916 pdcp_insert_cplane_acc_op, /* AES CMAC */ 2917 pdcp_insert_cplane_aes_zuc_op /* ZUC-I */ 2918 }, 2919 { /* ZUC-E */ 2920 pdcp_insert_cplane_enc_only_op, /* NULL */ 2921 pdcp_insert_cplane_zuc_snow_op, /* SNOW f9 */ 2922 pdcp_insert_cplane_zuc_aes_op, /* AES CMAC */ 2923 pdcp_insert_cplane_acc_op /* ZUC-I */ 2924 }, 2925 }; 2926 static enum rta_share_type 2927 desc_share[PDCP_CIPHER_TYPE_INVALID][PDCP_AUTH_TYPE_INVALID] = { 2928 { /* NULL */ 2929 SHR_WAIT, /* NULL */ 2930 SHR_ALWAYS, /* SNOW f9 */ 2931 SHR_ALWAYS, /* AES CMAC */ 2932 SHR_ALWAYS /* ZUC-I */ 2933 }, 2934 { /* SNOW f8 */ 2935 SHR_ALWAYS, /* NULL */ 2936 SHR_ALWAYS, /* SNOW f9 */ 2937 SHR_WAIT, /* AES CMAC */ 2938 SHR_WAIT /* ZUC-I */ 2939 }, 2940 { /* AES CTR */ 2941 SHR_ALWAYS, /* NULL */ 2942 SHR_ALWAYS, /* SNOW f9 */ 2943 SHR_ALWAYS, /* AES CMAC */ 2944 SHR_WAIT /* ZUC-I */ 2945 }, 2946 { /* ZUC-E */ 2947 SHR_ALWAYS, /* NULL */ 2948 SHR_WAIT, /* SNOW f9 */ 2949 SHR_WAIT, /* AES CMAC */ 2950 SHR_ALWAYS /* ZUC-I */ 2951 }, 2952 }; 2953 enum pdb_type_e pdb_type; 2954 struct program prg; 2955 struct program *p = &prg; 2956 int err; 2957 LABEL(pdb_end); 2958 2959 if (rta_sec_era != RTA_SEC_ERA_2 && era_2_sw_hfn_ovrd) { 2960 pr_err("Cannot select SW HFN override for other era than 2"); 2961 return -EINVAL; 2962 } 2963 2964 if (sn_size != PDCP_SN_SIZE_12 && sn_size != PDCP_SN_SIZE_5) { 2965 pr_err("C-plane supports only 5-bit and 12-bit sequence numbers\n"); 2966 return -EINVAL; 2967 } 2968 2969 PROGRAM_CNTXT_INIT(p, descbuf, 0); 2970 if (swap) 2971 PROGRAM_SET_BSWAP(p); 2972 if (ps) 2973 PROGRAM_SET_36BIT_ADDR(p); 2974 2975 SHR_HDR(p, desc_share[cipherdata->algtype][authdata->algtype], 0, 0); 2976 2977 pdb_type = cnstr_pdcp_c_plane_pdb(p, 2978 hfn, 2979 sn_size, 2980 bearer, 2981 direction, 2982 hfn_threshold, 2983 cipherdata, 2984 authdata); 2985 2986 SET_LABEL(p, pdb_end); 2987 2988 err = insert_hfn_ov_op(p, sn_size, pdb_type, 2989 era_2_sw_hfn_ovrd); 2990 if (err) 2991 return err; 2992 2993 err = pdcp_cp_fp[cipherdata->algtype][authdata->algtype](p, 2994 swap, 2995 cipherdata, 2996 authdata, 2997 OP_TYPE_ENCAP_PROTOCOL, 2998 sn_size, 2999 era_2_sw_hfn_ovrd); 3000 if (err) 3001 return err; 3002 3003 PATCH_HDR(p, 0, pdb_end); 3004 3005 return PROGRAM_FINALIZE(p); 3006 } 3007 3008 /** 3009 * cnstr_shdsc_pdcp_c_plane_decap - Function for creating a PDCP Control Plane 3010 * decapsulation descriptor. 3011 * @descbuf: pointer to buffer for descriptor construction 3012 * @ps: if 36/40bit addressing is desired, this parameter must be true 3013 * @swap: must be true when core endianness doesn't match SEC endianness 3014 * @hfn: starting Hyper Frame Number to be used together with the SN from the 3015 * PDCP frames. 3016 * @sn_size: size of sequence numbers, only 5/12 bit sequence numbers are valid 3017 * @bearer: radio bearer ID 3018 * @direction: the direction of the PDCP frame (UL/DL) 3019 * @hfn_threshold: HFN value that once reached triggers a warning from SEC that 3020 * keys should be renegotiated at the earliest convenience. 3021 * @cipherdata: pointer to block cipher transform definitions 3022 * Valid algorithm values are those from cipher_type_pdcp enum. 3023 * @authdata: pointer to authentication transform definitions 3024 * Valid algorithm values are those from auth_type_pdcp enum. 3025 * @era_2_sw_hfn_ovrd: if software HFN override mechanism is desired for 3026 * this descriptor. Note: Can only be used for 3027 * SEC ERA 2. 3028 * 3029 * Return: size of descriptor written in words or negative number on error. 3030 * Once the function returns, the value of this parameter can be used 3031 * for reclaiming the space that wasn't used for the descriptor. 3032 * 3033 * Note: descbuf must be large enough to contain a full 256 byte long 3034 * descriptor; after the function returns, by subtracting the actual number of 3035 * bytes used, the user can reuse the remaining buffer space for other purposes. 3036 */ 3037 static inline int 3038 cnstr_shdsc_pdcp_c_plane_decap(uint32_t *descbuf, 3039 bool ps, 3040 bool swap, 3041 uint32_t hfn, 3042 enum pdcp_sn_size sn_size, 3043 unsigned char bearer, 3044 unsigned char direction, 3045 uint32_t hfn_threshold, 3046 struct alginfo *cipherdata, 3047 struct alginfo *authdata, 3048 unsigned char era_2_sw_hfn_ovrd) 3049 { 3050 static int 3051 (*pdcp_cp_fp[PDCP_CIPHER_TYPE_INVALID][PDCP_AUTH_TYPE_INVALID]) 3052 (struct program*, bool swap, struct alginfo *, 3053 struct alginfo *, unsigned int, enum pdcp_sn_size, 3054 unsigned char) = { 3055 { /* NULL */ 3056 pdcp_insert_cplane_null_op, /* NULL */ 3057 pdcp_insert_cplane_int_only_op, /* SNOW f9 */ 3058 pdcp_insert_cplane_int_only_op, /* AES CMAC */ 3059 pdcp_insert_cplane_int_only_op /* ZUC-I */ 3060 }, 3061 { /* SNOW f8 */ 3062 pdcp_insert_cplane_enc_only_op, /* NULL */ 3063 pdcp_insert_cplane_acc_op, /* SNOW f9 */ 3064 pdcp_insert_cplane_snow_aes_op, /* AES CMAC */ 3065 pdcp_insert_cplane_snow_zuc_op /* ZUC-I */ 3066 }, 3067 { /* AES CTR */ 3068 pdcp_insert_cplane_enc_only_op, /* NULL */ 3069 pdcp_insert_cplane_aes_snow_op, /* SNOW f9 */ 3070 pdcp_insert_cplane_acc_op, /* AES CMAC */ 3071 pdcp_insert_cplane_aes_zuc_op /* ZUC-I */ 3072 }, 3073 { /* ZUC-E */ 3074 pdcp_insert_cplane_enc_only_op, /* NULL */ 3075 pdcp_insert_cplane_zuc_snow_op, /* SNOW f9 */ 3076 pdcp_insert_cplane_zuc_aes_op, /* AES CMAC */ 3077 pdcp_insert_cplane_acc_op /* ZUC-I */ 3078 }, 3079 }; 3080 static enum rta_share_type 3081 desc_share[PDCP_CIPHER_TYPE_INVALID][PDCP_AUTH_TYPE_INVALID] = { 3082 { /* NULL */ 3083 SHR_WAIT, /* NULL */ 3084 SHR_ALWAYS, /* SNOW f9 */ 3085 SHR_ALWAYS, /* AES CMAC */ 3086 SHR_ALWAYS /* ZUC-I */ 3087 }, 3088 { /* SNOW f8 */ 3089 SHR_ALWAYS, /* NULL */ 3090 SHR_ALWAYS, /* SNOW f9 */ 3091 SHR_WAIT, /* AES CMAC */ 3092 SHR_WAIT /* ZUC-I */ 3093 }, 3094 { /* AES CTR */ 3095 SHR_ALWAYS, /* NULL */ 3096 SHR_ALWAYS, /* SNOW f9 */ 3097 SHR_ALWAYS, /* AES CMAC */ 3098 SHR_WAIT /* ZUC-I */ 3099 }, 3100 { /* ZUC-E */ 3101 SHR_ALWAYS, /* NULL */ 3102 SHR_WAIT, /* SNOW f9 */ 3103 SHR_WAIT, /* AES CMAC */ 3104 SHR_ALWAYS /* ZUC-I */ 3105 }, 3106 }; 3107 enum pdb_type_e pdb_type; 3108 struct program prg; 3109 struct program *p = &prg; 3110 int err; 3111 LABEL(pdb_end); 3112 3113 if (rta_sec_era != RTA_SEC_ERA_2 && era_2_sw_hfn_ovrd) { 3114 pr_err("Cannot select SW HFN override for other era than 2"); 3115 return -EINVAL; 3116 } 3117 3118 if (sn_size != PDCP_SN_SIZE_12 && sn_size != PDCP_SN_SIZE_5) { 3119 pr_err("C-plane supports only 5-bit and 12-bit sequence numbers\n"); 3120 return -EINVAL; 3121 } 3122 3123 PROGRAM_CNTXT_INIT(p, descbuf, 0); 3124 if (swap) 3125 PROGRAM_SET_BSWAP(p); 3126 if (ps) 3127 PROGRAM_SET_36BIT_ADDR(p); 3128 3129 SHR_HDR(p, desc_share[cipherdata->algtype][authdata->algtype], 0, 0); 3130 3131 pdb_type = cnstr_pdcp_c_plane_pdb(p, 3132 hfn, 3133 sn_size, 3134 bearer, 3135 direction, 3136 hfn_threshold, 3137 cipherdata, 3138 authdata); 3139 3140 SET_LABEL(p, pdb_end); 3141 3142 err = insert_hfn_ov_op(p, sn_size, pdb_type, 3143 era_2_sw_hfn_ovrd); 3144 if (err) 3145 return err; 3146 3147 err = pdcp_cp_fp[cipherdata->algtype][authdata->algtype](p, 3148 swap, 3149 cipherdata, 3150 authdata, 3151 OP_TYPE_DECAP_PROTOCOL, 3152 sn_size, 3153 era_2_sw_hfn_ovrd); 3154 if (err) 3155 return err; 3156 3157 PATCH_HDR(p, 0, pdb_end); 3158 3159 return PROGRAM_FINALIZE(p); 3160 } 3161 3162 static int 3163 pdcp_insert_uplane_with_int_op(struct program *p, 3164 bool swap __maybe_unused, 3165 struct alginfo *cipherdata, 3166 struct alginfo *authdata, 3167 enum pdcp_sn_size sn_size, 3168 unsigned char era_2_sw_hfn_ovrd, 3169 unsigned int dir) 3170 { 3171 static int 3172 (*pdcp_cp_fp[PDCP_CIPHER_TYPE_INVALID][PDCP_AUTH_TYPE_INVALID]) 3173 (struct program*, bool swap, struct alginfo *, 3174 struct alginfo *, unsigned int, enum pdcp_sn_size, 3175 unsigned char __maybe_unused) = { 3176 { /* NULL */ 3177 pdcp_insert_cplane_null_op, /* NULL */ 3178 pdcp_insert_cplane_int_only_op, /* SNOW f9 */ 3179 pdcp_insert_cplane_int_only_op, /* AES CMAC */ 3180 pdcp_insert_cplane_int_only_op /* ZUC-I */ 3181 }, 3182 { /* SNOW f8 */ 3183 pdcp_insert_cplane_enc_only_op, /* NULL */ 3184 pdcp_insert_uplane_snow_snow_op, /* SNOW f9 */ 3185 pdcp_insert_cplane_snow_aes_op, /* AES CMAC */ 3186 pdcp_insert_cplane_snow_zuc_op /* ZUC-I */ 3187 }, 3188 { /* AES CTR */ 3189 pdcp_insert_cplane_enc_only_op, /* NULL */ 3190 pdcp_insert_cplane_aes_snow_op, /* SNOW f9 */ 3191 pdcp_insert_uplane_aes_aes_op, /* AES CMAC */ 3192 pdcp_insert_cplane_aes_zuc_op /* ZUC-I */ 3193 }, 3194 { /* ZUC-E */ 3195 pdcp_insert_cplane_enc_only_op, /* NULL */ 3196 pdcp_insert_cplane_zuc_snow_op, /* SNOW f9 */ 3197 pdcp_insert_cplane_zuc_aes_op, /* AES CMAC */ 3198 pdcp_insert_uplane_zuc_zuc_op /* ZUC-I */ 3199 }, 3200 }; 3201 int err; 3202 3203 err = pdcp_cp_fp[cipherdata->algtype][authdata->algtype](p, 3204 swap, 3205 cipherdata, 3206 authdata, 3207 dir, 3208 sn_size, 3209 era_2_sw_hfn_ovrd); 3210 if (err) 3211 return err; 3212 3213 return 0; 3214 } 3215 3216 3217 /** 3218 * cnstr_shdsc_pdcp_u_plane_encap - Function for creating a PDCP User Plane 3219 * encapsulation descriptor. 3220 * @descbuf: pointer to buffer for descriptor construction 3221 * @ps: if 36/40bit addressing is desired, this parameter must be true 3222 * @swap: must be true when core endianness doesn't match SEC endianness 3223 * @sn_size: selects Sequence Number Size: 7/12/15 bits 3224 * @hfn: starting Hyper Frame Number to be used together with the SN from the 3225 * PDCP frames. 3226 * @bearer: radio bearer ID 3227 * @direction: the direction of the PDCP frame (UL/DL) 3228 * @hfn_threshold: HFN value that once reached triggers a warning from SEC that 3229 * keys should be renegotiated at the earliest convenience. 3230 * @cipherdata: pointer to block cipher transform definitions 3231 * Valid algorithm values are those from cipher_type_pdcp enum. 3232 * @era_2_sw_hfn_ovrd: if software HFN override mechanism is desired for 3233 * this descriptor. Note: Can only be used for 3234 * SEC ERA 2. 3235 * 3236 * Return: size of descriptor written in words or negative number on error. 3237 * Once the function returns, the value of this parameter can be used 3238 * for reclaiming the space that wasn't used for the descriptor. 3239 * 3240 * Note: descbuf must be large enough to contain a full 256 byte long 3241 * descriptor; after the function returns, by subtracting the actual number of 3242 * bytes used, the user can reuse the remaining buffer space for other purposes. 3243 */ 3244 static inline int 3245 cnstr_shdsc_pdcp_u_plane_encap(uint32_t *descbuf, 3246 bool ps, 3247 bool swap, 3248 enum pdcp_sn_size sn_size, 3249 uint32_t hfn, 3250 unsigned short bearer, 3251 unsigned short direction, 3252 uint32_t hfn_threshold, 3253 struct alginfo *cipherdata, 3254 struct alginfo *authdata, 3255 unsigned char era_2_sw_hfn_ovrd) 3256 { 3257 struct program prg; 3258 struct program *p = &prg; 3259 int err; 3260 enum pdb_type_e pdb_type; 3261 static enum rta_share_type 3262 desc_share[PDCP_CIPHER_TYPE_INVALID][PDCP_AUTH_TYPE_INVALID] = { 3263 { /* NULL */ 3264 SHR_WAIT, /* NULL */ 3265 SHR_ALWAYS, /* SNOW f9 */ 3266 SHR_ALWAYS, /* AES CMAC */ 3267 SHR_ALWAYS /* ZUC-I */ 3268 }, 3269 { /* SNOW f8 */ 3270 SHR_ALWAYS, /* NULL */ 3271 SHR_ALWAYS, /* SNOW f9 */ 3272 SHR_WAIT, /* AES CMAC */ 3273 SHR_WAIT /* ZUC-I */ 3274 }, 3275 { /* AES CTR */ 3276 SHR_ALWAYS, /* NULL */ 3277 SHR_ALWAYS, /* SNOW f9 */ 3278 SHR_ALWAYS, /* AES CMAC */ 3279 SHR_WAIT /* ZUC-I */ 3280 }, 3281 { /* ZUC-E */ 3282 SHR_ALWAYS, /* NULL */ 3283 SHR_WAIT, /* SNOW f9 */ 3284 SHR_WAIT, /* AES CMAC */ 3285 SHR_WAIT /* ZUC-I */ 3286 }, 3287 }; 3288 LABEL(pdb_end); 3289 3290 if (rta_sec_era != RTA_SEC_ERA_2 && era_2_sw_hfn_ovrd) { 3291 pr_err("Cannot select SW HFN ovrd for other era than 2"); 3292 return -EINVAL; 3293 } 3294 3295 if (authdata && !authdata->algtype && rta_sec_era < RTA_SEC_ERA_8) { 3296 pr_err("Cannot use u-plane auth with era < 8"); 3297 return -EINVAL; 3298 } 3299 3300 PROGRAM_CNTXT_INIT(p, descbuf, 0); 3301 if (swap) 3302 PROGRAM_SET_BSWAP(p); 3303 if (ps) 3304 PROGRAM_SET_36BIT_ADDR(p); 3305 3306 if (authdata) 3307 SHR_HDR(p, desc_share[cipherdata->algtype][authdata->algtype], 0, 0); 3308 else 3309 SHR_HDR(p, SHR_ALWAYS, 0, 0); 3310 pdb_type = cnstr_pdcp_u_plane_pdb(p, sn_size, hfn, 3311 bearer, direction, hfn_threshold, 3312 cipherdata, authdata); 3313 if (pdb_type == PDCP_PDB_TYPE_INVALID) { 3314 pr_err("Error creating PDCP UPlane PDB\n"); 3315 return -EINVAL; 3316 } 3317 SET_LABEL(p, pdb_end); 3318 3319 err = insert_hfn_ov_op(p, sn_size, pdb_type, era_2_sw_hfn_ovrd); 3320 if (err) 3321 return err; 3322 3323 switch (sn_size) { 3324 case PDCP_SN_SIZE_7: 3325 case PDCP_SN_SIZE_12: 3326 switch (cipherdata->algtype) { 3327 case PDCP_CIPHER_TYPE_ZUC: 3328 if (rta_sec_era < RTA_SEC_ERA_5) { 3329 pr_err("Invalid era for selected algorithm\n"); 3330 return -ENOTSUP; 3331 } 3332 /* fallthrough */ 3333 case PDCP_CIPHER_TYPE_AES: 3334 case PDCP_CIPHER_TYPE_SNOW: 3335 case PDCP_CIPHER_TYPE_NULL: 3336 if (rta_sec_era == RTA_SEC_ERA_8 && 3337 authdata && authdata->algtype == 0){ 3338 err = pdcp_insert_uplane_with_int_op(p, swap, 3339 cipherdata, authdata, 3340 sn_size, era_2_sw_hfn_ovrd, 3341 OP_TYPE_ENCAP_PROTOCOL); 3342 if (err) 3343 return err; 3344 break; 3345 } 3346 3347 if (pdb_type != PDCP_PDB_TYPE_FULL_PDB) { 3348 pr_err("PDB type must be FULL for PROTO desc\n"); 3349 return -EINVAL; 3350 } 3351 3352 /* Insert auth key if requested */ 3353 if (authdata && authdata->algtype) { 3354 KEY(p, KEY2, authdata->key_enc_flags, 3355 (uint64_t)authdata->key, authdata->keylen, 3356 INLINE_KEY(authdata)); 3357 } 3358 /* Insert Cipher Key */ 3359 KEY(p, KEY1, cipherdata->key_enc_flags, 3360 (uint64_t)cipherdata->key, cipherdata->keylen, 3361 INLINE_KEY(cipherdata)); 3362 3363 if (authdata) 3364 PROTOCOL(p, OP_TYPE_ENCAP_PROTOCOL, 3365 OP_PCLID_LTE_PDCP_USER_RN, 3366 ((uint16_t)cipherdata->algtype << 8) | 3367 (uint16_t)authdata->algtype); 3368 else 3369 PROTOCOL(p, OP_TYPE_ENCAP_PROTOCOL, 3370 OP_PCLID_LTE_PDCP_USER, 3371 (uint16_t)cipherdata->algtype); 3372 break; 3373 default: 3374 pr_err("%s: Invalid encrypt algorithm selected: %d\n", 3375 "cnstr_pcl_shdsc_pdcp_u_plane_decap", 3376 cipherdata->algtype); 3377 return -EINVAL; 3378 } 3379 break; 3380 3381 case PDCP_SN_SIZE_15: 3382 case PDCP_SN_SIZE_18: 3383 if (authdata) { 3384 err = pdcp_insert_uplane_with_int_op(p, swap, 3385 cipherdata, authdata, 3386 sn_size, era_2_sw_hfn_ovrd, 3387 OP_TYPE_ENCAP_PROTOCOL); 3388 if (err) 3389 return err; 3390 3391 break; 3392 } 3393 3394 switch (cipherdata->algtype) { 3395 case PDCP_CIPHER_TYPE_NULL: 3396 insert_copy_frame_op(p, 3397 cipherdata, 3398 OP_TYPE_ENCAP_PROTOCOL); 3399 break; 3400 3401 default: 3402 err = pdcp_insert_uplane_no_int_op(p, swap, cipherdata, 3403 OP_TYPE_ENCAP_PROTOCOL, sn_size); 3404 if (err) 3405 return err; 3406 break; 3407 } 3408 break; 3409 3410 case PDCP_SN_SIZE_5: 3411 default: 3412 pr_err("Invalid SN size selected\n"); 3413 return -ENOTSUP; 3414 } 3415 3416 PATCH_HDR(p, 0, pdb_end); 3417 return PROGRAM_FINALIZE(p); 3418 } 3419 3420 /** 3421 * cnstr_shdsc_pdcp_u_plane_decap - Function for creating a PDCP User Plane 3422 * decapsulation descriptor. 3423 * @descbuf: pointer to buffer for descriptor construction 3424 * @ps: if 36/40bit addressing is desired, this parameter must be true 3425 * @swap: must be true when core endianness doesn't match SEC endianness 3426 * @sn_size: selects Sequence Number Size: 7/12/15 bits 3427 * @hfn: starting Hyper Frame Number to be used together with the SN from the 3428 * PDCP frames. 3429 * @bearer: radio bearer ID 3430 * @direction: the direction of the PDCP frame (UL/DL) 3431 * @hfn_threshold: HFN value that once reached triggers a warning from SEC that 3432 * keys should be renegotiated at the earliest convenience. 3433 * @cipherdata: pointer to block cipher transform definitions 3434 * Valid algorithm values are those from cipher_type_pdcp enum. 3435 * @era_2_sw_hfn_ovrd: if software HFN override mechanism is desired for 3436 * this descriptor. Note: Can only be used for 3437 * SEC ERA 2. 3438 * 3439 * Return: size of descriptor written in words or negative number on error. 3440 * Once the function returns, the value of this parameter can be used 3441 * for reclaiming the space that wasn't used for the descriptor. 3442 * 3443 * Note: descbuf must be large enough to contain a full 256 byte long 3444 * descriptor; after the function returns, by subtracting the actual number of 3445 * bytes used, the user can reuse the remaining buffer space for other purposes. 3446 */ 3447 static inline int 3448 cnstr_shdsc_pdcp_u_plane_decap(uint32_t *descbuf, 3449 bool ps, 3450 bool swap, 3451 enum pdcp_sn_size sn_size, 3452 uint32_t hfn, 3453 unsigned short bearer, 3454 unsigned short direction, 3455 uint32_t hfn_threshold, 3456 struct alginfo *cipherdata, 3457 struct alginfo *authdata, 3458 unsigned char era_2_sw_hfn_ovrd) 3459 { 3460 struct program prg; 3461 struct program *p = &prg; 3462 int err; 3463 enum pdb_type_e pdb_type; 3464 static enum rta_share_type 3465 desc_share[PDCP_CIPHER_TYPE_INVALID][PDCP_AUTH_TYPE_INVALID] = { 3466 { /* NULL */ 3467 SHR_WAIT, /* NULL */ 3468 SHR_ALWAYS, /* SNOW f9 */ 3469 SHR_ALWAYS, /* AES CMAC */ 3470 SHR_ALWAYS /* ZUC-I */ 3471 }, 3472 { /* SNOW f8 */ 3473 SHR_ALWAYS, /* NULL */ 3474 SHR_ALWAYS, /* SNOW f9 */ 3475 SHR_WAIT, /* AES CMAC */ 3476 SHR_WAIT /* ZUC-I */ 3477 }, 3478 { /* AES CTR */ 3479 SHR_ALWAYS, /* NULL */ 3480 SHR_ALWAYS, /* SNOW f9 */ 3481 SHR_ALWAYS, /* AES CMAC */ 3482 SHR_WAIT /* ZUC-I */ 3483 }, 3484 { /* ZUC-E */ 3485 SHR_ALWAYS, /* NULL */ 3486 SHR_WAIT, /* SNOW f9 */ 3487 SHR_WAIT, /* AES CMAC */ 3488 SHR_WAIT /* ZUC-I */ 3489 }, 3490 }; 3491 3492 LABEL(pdb_end); 3493 3494 if (rta_sec_era != RTA_SEC_ERA_2 && era_2_sw_hfn_ovrd) { 3495 pr_err("Cannot select SW HFN override for other era than 2"); 3496 return -EINVAL; 3497 } 3498 3499 if (authdata && !authdata->algtype && rta_sec_era < RTA_SEC_ERA_8) { 3500 pr_err("Cannot use u-plane auth with era < 8"); 3501 return -EINVAL; 3502 } 3503 3504 PROGRAM_CNTXT_INIT(p, descbuf, 0); 3505 if (swap) 3506 PROGRAM_SET_BSWAP(p); 3507 if (ps) 3508 PROGRAM_SET_36BIT_ADDR(p); 3509 if (authdata) 3510 SHR_HDR(p, desc_share[cipherdata->algtype][authdata->algtype], 0, 0); 3511 else 3512 SHR_HDR(p, SHR_ALWAYS, 0, 0); 3513 3514 pdb_type = cnstr_pdcp_u_plane_pdb(p, sn_size, hfn, bearer, 3515 direction, hfn_threshold, 3516 cipherdata, authdata); 3517 if (pdb_type == PDCP_PDB_TYPE_INVALID) { 3518 pr_err("Error creating PDCP UPlane PDB\n"); 3519 return -EINVAL; 3520 } 3521 SET_LABEL(p, pdb_end); 3522 3523 err = insert_hfn_ov_op(p, sn_size, pdb_type, era_2_sw_hfn_ovrd); 3524 if (err) 3525 return err; 3526 3527 switch (sn_size) { 3528 case PDCP_SN_SIZE_7: 3529 case PDCP_SN_SIZE_12: 3530 switch (cipherdata->algtype) { 3531 case PDCP_CIPHER_TYPE_ZUC: 3532 if (rta_sec_era < RTA_SEC_ERA_5) { 3533 pr_err("Invalid era for selected algorithm\n"); 3534 return -ENOTSUP; 3535 } 3536 /* fallthrough */ 3537 case PDCP_CIPHER_TYPE_AES: 3538 case PDCP_CIPHER_TYPE_SNOW: 3539 case PDCP_CIPHER_TYPE_NULL: 3540 if (pdb_type != PDCP_PDB_TYPE_FULL_PDB) { 3541 pr_err("PDB type must be FULL for PROTO desc\n"); 3542 return -EINVAL; 3543 } 3544 3545 /* Insert auth key if requested */ 3546 if (authdata && authdata->algtype) 3547 KEY(p, KEY2, authdata->key_enc_flags, 3548 (uint64_t)authdata->key, authdata->keylen, 3549 INLINE_KEY(authdata)); 3550 else if (authdata && authdata->algtype == 0) { 3551 err = pdcp_insert_uplane_with_int_op(p, swap, 3552 cipherdata, authdata, 3553 sn_size, era_2_sw_hfn_ovrd, 3554 OP_TYPE_DECAP_PROTOCOL); 3555 if (err) 3556 return err; 3557 break; 3558 } 3559 3560 /* Insert Cipher Key */ 3561 KEY(p, KEY1, cipherdata->key_enc_flags, 3562 cipherdata->key, cipherdata->keylen, 3563 INLINE_KEY(cipherdata)); 3564 if (authdata) 3565 PROTOCOL(p, OP_TYPE_DECAP_PROTOCOL, 3566 OP_PCLID_LTE_PDCP_USER_RN, 3567 ((uint16_t)cipherdata->algtype << 8) | 3568 (uint16_t)authdata->algtype); 3569 else 3570 PROTOCOL(p, OP_TYPE_DECAP_PROTOCOL, 3571 OP_PCLID_LTE_PDCP_USER, 3572 (uint16_t)cipherdata->algtype); 3573 break; 3574 default: 3575 pr_err("%s: Invalid encrypt algorithm selected: %d\n", 3576 "cnstr_pcl_shdsc_pdcp_u_plane_decap", 3577 cipherdata->algtype); 3578 return -EINVAL; 3579 } 3580 break; 3581 3582 case PDCP_SN_SIZE_15: 3583 case PDCP_SN_SIZE_18: 3584 if (authdata) { 3585 err = pdcp_insert_uplane_with_int_op(p, swap, 3586 cipherdata, authdata, 3587 sn_size, era_2_sw_hfn_ovrd, 3588 OP_TYPE_DECAP_PROTOCOL); 3589 if (err) 3590 return err; 3591 3592 break; 3593 } 3594 3595 switch (cipherdata->algtype) { 3596 case PDCP_CIPHER_TYPE_NULL: 3597 insert_copy_frame_op(p, 3598 cipherdata, 3599 OP_TYPE_DECAP_PROTOCOL); 3600 break; 3601 3602 default: 3603 err = pdcp_insert_uplane_no_int_op(p, swap, cipherdata, 3604 OP_TYPE_DECAP_PROTOCOL, sn_size); 3605 if (err) 3606 return err; 3607 break; 3608 } 3609 break; 3610 3611 case PDCP_SN_SIZE_5: 3612 default: 3613 pr_err("Invalid SN size selected\n"); 3614 return -ENOTSUP; 3615 } 3616 3617 PATCH_HDR(p, 0, pdb_end); 3618 return PROGRAM_FINALIZE(p); 3619 } 3620 3621 /** 3622 * cnstr_shdsc_pdcp_short_mac - Function for creating a PDCP Short MAC 3623 * descriptor. 3624 * @descbuf: pointer to buffer for descriptor construction 3625 * @ps: if 36/40bit addressing is desired, this parameter must be true 3626 * @swap: must be true when core endianness doesn't match SEC endianness 3627 * @authdata: pointer to authentication transform definitions 3628 * Valid algorithm values are those from auth_type_pdcp enum. 3629 * 3630 * Return: size of descriptor written in words or negative number on error. 3631 * Once the function returns, the value of this parameter can be used 3632 * for reclaiming the space that wasn't used for the descriptor. 3633 * 3634 * Note: descbuf must be large enough to contain a full 256 byte long 3635 * descriptor; after the function returns, by subtracting the actual number of 3636 * bytes used, the user can reuse the remaining buffer space for other purposes. 3637 */ 3638 static inline int 3639 cnstr_shdsc_pdcp_short_mac(uint32_t *descbuf, 3640 bool ps, 3641 bool swap, 3642 struct alginfo *authdata) 3643 { 3644 struct program prg; 3645 struct program *p = &prg; 3646 uint32_t iv[3] = {0, 0, 0}; 3647 LABEL(local_offset); 3648 REFERENCE(move_cmd_read_descbuf); 3649 REFERENCE(move_cmd_write_descbuf); 3650 3651 PROGRAM_CNTXT_INIT(p, descbuf, 0); 3652 if (swap) 3653 PROGRAM_SET_BSWAP(p); 3654 if (ps) 3655 PROGRAM_SET_36BIT_ADDR(p); 3656 3657 SHR_HDR(p, SHR_ALWAYS, 1, 0); 3658 3659 if (rta_sec_era > RTA_SEC_ERA_2) { 3660 MATHB(p, SEQINSZ, SUB, ZERO, VSEQINSZ, 4, 0); 3661 MATHB(p, SEQINSZ, SUB, ZERO, MATH1, 4, 0); 3662 } else { 3663 MATHB(p, SEQINSZ, ADD, ONE, MATH1, 4, 0); 3664 MATHB(p, MATH1, SUB, ONE, MATH1, 4, 0); 3665 MATHB(p, ZERO, ADD, MATH1, VSEQINSZ, 4, 0); 3666 MOVE(p, MATH1, 0, MATH0, 0, 8, IMMED); 3667 3668 /* 3669 * Since MOVELEN is available only starting with 3670 * SEC ERA 3, use poor man's MOVELEN: create a MOVE 3671 * command dynamically by writing the length from M1 by 3672 * OR-ing the command in the M1 register and MOVE the 3673 * result into the descriptor buffer. Care must be taken 3674 * wrt. the location of the command because of SEC 3675 * pipelining. The actual MOVEs are written at the end 3676 * of the descriptor due to calculations needed on the 3677 * offset in the descriptor for the MOVE command. 3678 */ 3679 move_cmd_read_descbuf = MOVE(p, DESCBUF, 0, MATH0, 0, 6, 3680 IMMED); 3681 move_cmd_write_descbuf = MOVE(p, MATH0, 0, DESCBUF, 0, 8, 3682 WAITCOMP | IMMED); 3683 } 3684 MATHB(p, ZERO, ADD, MATH1, VSEQOUTSZ, 4, 0); 3685 3686 switch (authdata->algtype) { 3687 case PDCP_AUTH_TYPE_NULL: 3688 SEQFIFOSTORE(p, MSG, 0, 0, VLF); 3689 if (rta_sec_era > RTA_SEC_ERA_2) { 3690 MOVE(p, AB1, 0, OFIFO, 0, MATH1, 0); 3691 } else { 3692 SET_LABEL(p, local_offset); 3693 3694 /* Shut off automatic Info FIFO entries */ 3695 LOAD(p, 0, DCTRL, LDOFF_DISABLE_AUTO_NFIFO, 0, IMMED); 3696 3697 /* Placeholder for MOVE command with length from M1 3698 * register 3699 */ 3700 MOVE(p, IFIFOAB1, 0, OFIFO, 0, 0, IMMED); 3701 3702 /* Enable automatic Info FIFO entries */ 3703 LOAD(p, 0, DCTRL, LDOFF_ENABLE_AUTO_NFIFO, 0, IMMED); 3704 } 3705 3706 LOAD(p, (uintptr_t)iv, MATH0, 0, 8, IMMED | COPY); 3707 SEQFIFOLOAD(p, MSG1, 0, VLF | LAST1 | LAST2 | FLUSH1); 3708 SEQSTORE(p, MATH0, 0, 4, 0); 3709 3710 break; 3711 3712 case PDCP_AUTH_TYPE_SNOW: 3713 iv[0] = 0xFFFFFFFF; 3714 iv[1] = swap ? swab32(0x04000000) : 0x04000000; 3715 iv[2] = swap ? swab32(0xF8000000) : 0xF8000000; 3716 3717 KEY(p, KEY2, authdata->key_enc_flags, authdata->key, 3718 authdata->keylen, INLINE_KEY(authdata)); 3719 LOAD(p, (uintptr_t)&iv, CONTEXT2, 0, 12, IMMED | COPY); 3720 ALG_OPERATION(p, OP_ALG_ALGSEL_SNOW_F9, 3721 OP_ALG_AAI_F9, 3722 OP_ALG_AS_INITFINAL, 3723 ICV_CHECK_DISABLE, 3724 DIR_ENC); 3725 SEQFIFOSTORE(p, MSG, 0, 0, VLF); 3726 3727 if (rta_sec_era > RTA_SEC_ERA_2) { 3728 MOVE(p, AB1, 0, OFIFO, 0, MATH1, 0); 3729 } else { 3730 SET_LABEL(p, local_offset); 3731 3732 3733 /* Shut off automatic Info FIFO entries */ 3734 LOAD(p, 0, DCTRL, LDOFF_DISABLE_AUTO_NFIFO, 0, IMMED); 3735 3736 /* Placeholder for MOVE command with length from M1 3737 * register 3738 */ 3739 MOVE(p, IFIFOAB1, 0, OFIFO, 0, 0, IMMED); 3740 3741 /* Enable automatic Info FIFO entries */ 3742 LOAD(p, 0, DCTRL, LDOFF_ENABLE_AUTO_NFIFO, 0, IMMED); 3743 } 3744 SEQFIFOLOAD(p, MSGINSNOOP, 0, VLF | LAST1 | LAST2 | FLUSH1); 3745 SEQSTORE(p, CONTEXT2, 0, 4, 0); 3746 3747 break; 3748 3749 case PDCP_AUTH_TYPE_AES: 3750 iv[0] = 0xFFFFFFFF; 3751 iv[1] = swap ? swab32(0xFC000000) : 0xFC000000; 3752 iv[2] = 0x00000000; /* unused */ 3753 3754 KEY(p, KEY1, authdata->key_enc_flags, authdata->key, 3755 authdata->keylen, INLINE_KEY(authdata)); 3756 LOAD(p, (uintptr_t)&iv, MATH0, 0, 8, IMMED | COPY); 3757 MOVE(p, MATH0, 0, IFIFOAB1, 0, 8, IMMED); 3758 ALG_OPERATION(p, OP_ALG_ALGSEL_AES, 3759 OP_ALG_AAI_CMAC, 3760 OP_ALG_AS_INITFINAL, 3761 ICV_CHECK_DISABLE, 3762 DIR_ENC); 3763 SEQFIFOSTORE(p, MSG, 0, 0, VLF); 3764 3765 if (rta_sec_era > RTA_SEC_ERA_2) { 3766 MOVE(p, AB2, 0, OFIFO, 0, MATH1, 0); 3767 } else { 3768 SET_LABEL(p, local_offset); 3769 3770 /* Shut off automatic Info FIFO entries */ 3771 LOAD(p, 0, DCTRL, LDOFF_DISABLE_AUTO_NFIFO, 0, IMMED); 3772 3773 /* Placeholder for MOVE command with length from M1 3774 * register 3775 */ 3776 MOVE(p, IFIFOAB2, 0, OFIFO, 0, 0, IMMED); 3777 3778 /* Enable automatic Info FIFO entries */ 3779 LOAD(p, 0, DCTRL, LDOFF_ENABLE_AUTO_NFIFO, 0, IMMED); 3780 } 3781 SEQFIFOLOAD(p, MSGINSNOOP, 0, VLF | LAST1 | LAST2 | FLUSH1); 3782 SEQSTORE(p, CONTEXT1, 0, 4, 0); 3783 3784 break; 3785 3786 case PDCP_AUTH_TYPE_ZUC: 3787 if (rta_sec_era < RTA_SEC_ERA_5) { 3788 pr_err("Invalid era for selected algorithm\n"); 3789 return -ENOTSUP; 3790 } 3791 iv[0] = 0xFFFFFFFF; 3792 iv[1] = swap ? swab32(0xFC000000) : 0xFC000000; 3793 iv[2] = 0x00000000; /* unused */ 3794 3795 KEY(p, KEY2, authdata->key_enc_flags, authdata->key, 3796 authdata->keylen, INLINE_KEY(authdata)); 3797 LOAD(p, (uintptr_t)&iv, CONTEXT2, 0, 12, IMMED | COPY); 3798 ALG_OPERATION(p, OP_ALG_ALGSEL_ZUCA, 3799 OP_ALG_AAI_F9, 3800 OP_ALG_AS_INITFINAL, 3801 ICV_CHECK_DISABLE, 3802 DIR_ENC); 3803 SEQFIFOSTORE(p, MSG, 0, 0, VLF); 3804 MOVE(p, AB1, 0, OFIFO, 0, MATH1, 0); 3805 SEQFIFOLOAD(p, MSGINSNOOP, 0, VLF | LAST1 | LAST2 | FLUSH1); 3806 SEQSTORE(p, CONTEXT2, 0, 4, 0); 3807 3808 break; 3809 3810 default: 3811 pr_err("%s: Invalid integrity algorithm selected: %d\n", 3812 "cnstr_shdsc_pdcp_short_mac", authdata->algtype); 3813 return -EINVAL; 3814 } 3815 3816 3817 if (rta_sec_era < RTA_SEC_ERA_3) { 3818 PATCH_MOVE(p, move_cmd_read_descbuf, local_offset); 3819 PATCH_MOVE(p, move_cmd_write_descbuf, local_offset); 3820 } 3821 3822 return PROGRAM_FINALIZE(p); 3823 } 3824 3825 #endif /* __DESC_PDCP_H__ */ 3826