1 /* SPDX-License-Identifier: BSD-3-Clause or GPL-2.0+ 2 * Copyright 2008-2013 Freescale Semiconductor, Inc. 3 * Copyright 2019-2023 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 #define REDUCED_PDB_DESCBUF_HFN_BEARER_DIR_OFFSET 4 274 #define FULL_PDB_DESCBUF_HFN_BEARER_DIR_OFFSET 8 275 276 /** 277 * rta_inline_pdcp_query() - Provide indications if a key can be passed as 278 * immediate data or shall be referenced in a 279 * shared descriptor. 280 * Return: 0 if data can be inlined or 1 if referenced. 281 */ 282 static inline int 283 rta_inline_pdcp_query(enum auth_type_pdcp auth_alg, 284 enum cipher_type_pdcp cipher_alg, 285 enum pdcp_sn_size sn_size, 286 int8_t hfn_ovd) 287 { 288 /** 289 * Shared Descriptors for some of the cases does not fit in the 290 * MAX_DESC_SIZE of the descriptor especially when non-protocol 291 * descriptors are formed as in 18bit cases and when HFN override 292 * is enabled as 2 extra words are added in the job descriptor. 293 * The cases which exceed are for RTA_SEC_ERA=8 and HFN override 294 * enabled and 18bit uplane and either of following Algo combinations. 295 * - SNOW-AES 296 * - AES-SNOW 297 * - SNOW-SNOW 298 * - ZUC-SNOW 299 * 300 * We cannot make inline for all cases, as this will impact performance 301 * due to extra memory accesses for the keys. 302 */ 303 if ((rta_sec_era == RTA_SEC_ERA_8) && hfn_ovd && 304 (sn_size == PDCP_SN_SIZE_18) && 305 ((cipher_alg == PDCP_CIPHER_TYPE_SNOW && 306 auth_alg == PDCP_AUTH_TYPE_AES) || 307 (cipher_alg == PDCP_CIPHER_TYPE_AES && 308 auth_alg == PDCP_AUTH_TYPE_SNOW) || 309 (cipher_alg == PDCP_CIPHER_TYPE_SNOW && 310 auth_alg == PDCP_AUTH_TYPE_SNOW) || 311 (cipher_alg == PDCP_CIPHER_TYPE_ZUC && 312 auth_alg == PDCP_AUTH_TYPE_SNOW))) { 313 314 return 1; 315 } 316 317 return 0; 318 } 319 320 /* 321 * Function for appending the portion of a PDCP Control Plane shared descriptor 322 * which performs NULL encryption and integrity (i.e. copies the input frame 323 * to the output frame, appending 32 bits of zeros at the end (MAC-I for 324 * NULL integrity). 325 */ 326 static inline int 327 pdcp_insert_cplane_null_op(struct program *p, 328 bool swap __maybe_unused, 329 struct alginfo *cipherdata __maybe_unused, 330 struct alginfo *authdata __maybe_unused, 331 unsigned int dir, 332 enum pdcp_sn_size sn_size __maybe_unused) 333 { 334 MATHB(p, SEQINSZ, ADD, ZERO, VSEQINSZ, 4, 0); 335 if (dir == OP_TYPE_ENCAP_PROTOCOL) 336 MATHB(p, SEQINSZ, ADD, PDCP_MAC_I_LEN, VSEQOUTSZ, 4, 337 IMMED2); 338 else 339 MATHB(p, SEQINSZ, SUB, PDCP_MAC_I_LEN, VSEQOUTSZ, 4, 340 IMMED2); 341 342 MATHB(p, VSEQINSZ, SUB, PDCP_NULL_MAX_FRAME_LEN, NONE, 4, 343 IMMED2); 344 JUMP(p, PDCP_MAX_FRAME_LEN_STATUS, HALT_STATUS, ALL_FALSE, MATH_N); 345 346 if (dir == OP_TYPE_ENCAP_PROTOCOL) 347 MATHB(p, VSEQINSZ, ADD, ZERO, MATH0, 4, 0); 348 else 349 MATHB(p, VSEQOUTSZ, ADD, ZERO, MATH0, 4, 0); 350 351 SEQFIFOSTORE(p, MSG, 0, 0, VLF); 352 SEQFIFOLOAD(p, MSG1, 0, VLF | LAST1 | FLUSH1); 353 354 MOVE(p, AB1, 0, OFIFO, 0, MATH0, 0); 355 356 if (dir == OP_TYPE_ENCAP_PROTOCOL) { 357 MATHB(p, MATH1, XOR, MATH1, MATH0, 8, 0); 358 MOVE(p, MATH0, 0, OFIFO, 0, 4, IMMED); 359 } 360 361 return 0; 362 } 363 364 static inline int 365 insert_copy_frame_op(struct program *p, 366 struct alginfo *cipherdata __maybe_unused, 367 unsigned int dir __maybe_unused) 368 { 369 MATHB(p, SEQINSZ, ADD, ZERO, VSEQINSZ, 4, 0); 370 MATHB(p, SEQINSZ, ADD, ZERO, VSEQOUTSZ, 4, 0); 371 372 MATHB(p, SEQINSZ, SUB, PDCP_NULL_MAX_FRAME_LEN, NONE, 4, 373 IFB | IMMED2); 374 JUMP(p, PDCP_MAX_FRAME_LEN_STATUS, HALT_STATUS, ALL_FALSE, MATH_N); 375 376 MATHB(p, VSEQINSZ, ADD, ZERO, MATH0, 4, 0); 377 378 SEQFIFOLOAD(p, MSG1, 0, VLF | LAST1 | FLUSH1); 379 380 MOVE(p, AB1, 0, OFIFO, 0, MATH0, 0); 381 382 SEQFIFOSTORE(p, MSG, 0, 0, VLF); 383 384 return 0; 385 } 386 387 static inline int 388 pdcp_insert_cplane_int_only_op(struct program *p, 389 bool swap __maybe_unused, 390 struct alginfo *cipherdata __maybe_unused, 391 struct alginfo *authdata, unsigned int dir, 392 enum pdcp_sn_size sn_size) 393 { 394 uint32_t offset = 0, length = 0, sn_mask = 0; 395 396 /* 12 bit SN is only supported for protocol offload case */ 397 if (sn_size == PDCP_SN_SIZE_12) { 398 KEY(p, KEY2, authdata->key_enc_flags, authdata->key, 399 authdata->keylen, INLINE_KEY(authdata)); 400 401 PROTOCOL(p, dir, OP_PCLID_LTE_PDCP_USER_RN, 402 (uint16_t)authdata->algtype); 403 return 0; 404 } 405 406 /* Non-proto is supported only for 5bit cplane and 18bit uplane */ 407 switch (sn_size) { 408 case PDCP_SN_SIZE_5: 409 offset = 7; 410 length = 1; 411 sn_mask = (swap == false) ? PDCP_C_PLANE_SN_MASK : 412 PDCP_C_PLANE_SN_MASK_BE; 413 break; 414 case PDCP_SN_SIZE_18: 415 offset = 5; 416 length = 3; 417 sn_mask = (swap == false) ? PDCP_U_PLANE_18BIT_SN_MASK : 418 PDCP_U_PLANE_18BIT_SN_MASK_BE; 419 break; 420 case PDCP_SN_SIZE_7: 421 case PDCP_SN_SIZE_12: 422 case PDCP_SN_SIZE_15: 423 pr_err("Invalid sn_size for %s\n", __func__); 424 return -ENOTSUP; 425 426 } 427 428 switch (authdata->algtype) { 429 case PDCP_AUTH_TYPE_SNOW: 430 /* Insert Auth Key */ 431 KEY(p, KEY2, authdata->key_enc_flags, authdata->key, 432 authdata->keylen, INLINE_KEY(authdata)); 433 SEQLOAD(p, MATH0, offset, length, 0); 434 JUMP(p, 1, LOCAL_JUMP, ALL_TRUE, CALM); 435 436 SEQINPTR(p, 0, length, RTO); 437 438 if (swap == false) { 439 MATHB(p, MATH0, AND, sn_mask, MATH1, 8, 440 IFB | IMMED2); 441 MATHB(p, MATH1, SHLD, MATH1, MATH1, 8, 0); 442 443 MOVEB(p, DESCBUF, 8, MATH2, 0, 8, WAITCOMP | IMMED); 444 445 MATHB(p, MATH2, AND, PDCP_BEARER_MASK, MATH2, 8, 446 IMMED2); 447 MOVEB(p, DESCBUF, 0x0C, MATH3, 0, 4, WAITCOMP | IMMED); 448 MATHB(p, MATH3, AND, PDCP_DIR_MASK, MATH3, 8, IMMED2); 449 MATHB(p, MATH1, OR, MATH2, MATH2, 8, 0); 450 MOVEB(p, MATH2, 0, CONTEXT2, 0, 0x0C, WAITCOMP | IMMED); 451 } else { 452 MATHB(p, MATH0, AND, sn_mask, MATH1, 8, 453 IFB | IMMED2); 454 MATHB(p, MATH1, SHLD, MATH1, MATH1, 8, 0); 455 456 MOVE(p, DESCBUF, 8, MATH2, 0, 8, WAITCOMP | IMMED); 457 MATHB(p, MATH2, AND, PDCP_BEARER_MASK_BE, MATH2, 8, 458 IMMED2); 459 460 MOVE(p, DESCBUF, 0x0C, MATH3, 0, 4, WAITCOMP | IMMED); 461 MATHB(p, MATH3, AND, PDCP_DIR_MASK_BE, MATH3, 8, 462 IMMED2); 463 MATHB(p, MATH1, OR, MATH2, MATH2, 8, 0); 464 MOVE(p, MATH2, 0, CONTEXT2, 0, 0x0C, WAITCOMP | IMMED); 465 } 466 467 if (dir == OP_TYPE_DECAP_PROTOCOL) { 468 MATHB(p, SEQINSZ, SUB, PDCP_MAC_I_LEN, MATH1, 4, 469 IMMED2); 470 } else { 471 MATHB(p, SEQINSZ, SUB, ZERO, MATH1, 4, 0); 472 } 473 474 MATHB(p, MATH1, SUB, ZERO, VSEQINSZ, 4, 0); 475 MATHB(p, MATH1, SUB, ZERO, VSEQOUTSZ, 4, 0); 476 477 SEQFIFOSTORE(p, MSG, 0, 0, VLF); 478 ALG_OPERATION(p, OP_ALG_ALGSEL_SNOW_F9, OP_ALG_AAI_F9, 479 OP_ALG_AS_INITFINAL, 480 dir == OP_TYPE_ENCAP_PROTOCOL ? 481 ICV_CHECK_DISABLE : ICV_CHECK_ENABLE, 482 DIR_ENC); 483 484 SEQFIFOLOAD(p, MSGINSNOOP, 0, 485 VLF | LAST1 | LAST2 | FLUSH1); 486 MOVE(p, AB1, 0, OFIFO, 0, MATH1, 0); 487 488 if (dir == OP_TYPE_DECAP_PROTOCOL) 489 SEQFIFOLOAD(p, ICV2, 4, LAST2); 490 else 491 SEQSTORE(p, CONTEXT2, 0, 4, 0); 492 493 break; 494 495 case PDCP_AUTH_TYPE_AES: 496 /* Insert Auth Key */ 497 KEY(p, KEY1, authdata->key_enc_flags, authdata->key, 498 authdata->keylen, INLINE_KEY(authdata)); 499 SEQLOAD(p, MATH0, offset, length, 0); 500 JUMP(p, 1, LOCAL_JUMP, ALL_TRUE, CALM); 501 SEQINPTR(p, 0, length, RTO); 502 503 if (swap == false) { 504 MATHB(p, MATH0, AND, sn_mask, MATH1, 8, 505 IFB | IMMED2); 506 MATHB(p, MATH1, SHLD, MATH1, MATH1, 8, 0); 507 508 MOVEB(p, DESCBUF, 8, MATH2, 0, 8, WAITCOMP | IMMED); 509 MATHB(p, MATH1, OR, MATH2, MATH2, 8, 0); 510 MOVEB(p, MATH2, 0, IFIFOAB1, 0, 8, IMMED); 511 } else { 512 MATHB(p, MATH0, AND, sn_mask, MATH1, 8, 513 IFB | IMMED2); 514 MATHB(p, MATH1, SHLD, MATH1, MATH1, 8, 0); 515 516 MOVE(p, DESCBUF, 8, MATH2, 0, 8, WAITCOMP | IMMED); 517 MATHB(p, MATH1, OR, MATH2, MATH2, 8, 0); 518 MOVE(p, MATH2, 0, IFIFOAB1, 0, 8, IMMED); 519 } 520 521 if (dir == OP_TYPE_DECAP_PROTOCOL) { 522 MATHB(p, SEQINSZ, SUB, PDCP_MAC_I_LEN, MATH1, 4, 523 IMMED2); 524 } else { 525 MATHB(p, SEQINSZ, SUB, ZERO, MATH1, 4, 0); 526 } 527 528 MATHB(p, MATH1, SUB, ZERO, VSEQINSZ, 4, 0); 529 MATHB(p, MATH1, SUB, ZERO, VSEQOUTSZ, 4, 0); 530 531 SEQFIFOSTORE(p, MSG, 0, 0, VLF); 532 ALG_OPERATION(p, OP_ALG_ALGSEL_AES, 533 OP_ALG_AAI_CMAC, 534 OP_ALG_AS_INITFINAL, 535 dir == OP_TYPE_ENCAP_PROTOCOL ? 536 ICV_CHECK_DISABLE : ICV_CHECK_ENABLE, 537 DIR_ENC); 538 539 MOVE(p, AB2, 0, OFIFO, 0, MATH1, 0); 540 SEQFIFOLOAD(p, MSGINSNOOP, 0, 541 VLF | LAST1 | LAST2 | FLUSH1); 542 543 if (dir == OP_TYPE_DECAP_PROTOCOL) 544 SEQFIFOLOAD(p, ICV1, 4, LAST1 | FLUSH1); 545 else 546 SEQSTORE(p, CONTEXT1, 0, 4, 0); 547 548 break; 549 550 case PDCP_AUTH_TYPE_ZUC: 551 /* Insert Auth Key */ 552 KEY(p, KEY2, authdata->key_enc_flags, authdata->key, 553 authdata->keylen, INLINE_KEY(authdata)); 554 SEQLOAD(p, MATH0, offset, length, 0); 555 JUMP(p, 1, LOCAL_JUMP, ALL_TRUE, CALM); 556 SEQINPTR(p, 0, length, RTO); 557 if (swap == false) { 558 MATHB(p, MATH0, AND, sn_mask, MATH1, 8, 559 IFB | IMMED2); 560 MATHB(p, MATH1, SHLD, MATH1, MATH1, 8, 0); 561 562 MOVEB(p, DESCBUF, 8, MATH2, 0, 8, WAITCOMP | IMMED); 563 MATHB(p, MATH1, OR, MATH2, MATH2, 8, 0); 564 MOVEB(p, MATH2, 0, CONTEXT2, 0, 8, IMMED); 565 566 } else { 567 MATHB(p, MATH0, AND, sn_mask, MATH1, 8, 568 IFB | IMMED2); 569 MATHB(p, MATH1, SHLD, MATH1, MATH1, 8, 0); 570 571 MOVE(p, DESCBUF, 8, MATH2, 0, 8, WAITCOMP | IMMED); 572 MATHB(p, MATH1, OR, MATH2, MATH2, 8, 0); 573 MOVE(p, MATH2, 0, CONTEXT2, 0, 8, IMMED); 574 } 575 if (dir == OP_TYPE_DECAP_PROTOCOL) 576 MATHB(p, SEQINSZ, SUB, PDCP_MAC_I_LEN, MATH1, 4, 577 IMMED2); 578 else 579 MATHB(p, SEQINSZ, SUB, ZERO, MATH1, 4, 0); 580 581 MATHB(p, MATH1, SUB, ZERO, VSEQINSZ, 4, 0); 582 MATHB(p, MATH1, SUB, ZERO, VSEQOUTSZ, 4, 0); 583 SEQFIFOSTORE(p, MSG, 0, 0, VLF); 584 ALG_OPERATION(p, OP_ALG_ALGSEL_ZUCA, 585 OP_ALG_AAI_F9, 586 OP_ALG_AS_INITFINAL, 587 dir == OP_TYPE_ENCAP_PROTOCOL ? 588 ICV_CHECK_DISABLE : ICV_CHECK_ENABLE, 589 DIR_ENC); 590 SEQFIFOLOAD(p, MSGINSNOOP, 0, VLF | LAST1 | LAST2 | FLUSH1); 591 MOVE(p, AB1, 0, OFIFO, 0, MATH1, 0); 592 593 if (dir == OP_TYPE_DECAP_PROTOCOL) 594 SEQFIFOLOAD(p, ICV2, 4, LAST2); 595 else 596 SEQSTORE(p, CONTEXT2, 0, 4, 0); 597 598 break; 599 600 default: 601 pr_err("%s: Invalid integrity algorithm selected: %d\n", 602 "pdcp_insert_cplane_int_only_op", authdata->algtype); 603 return -EINVAL; 604 } 605 606 return 0; 607 } 608 609 static inline int 610 pdcp_insert_cplane_enc_only_op(struct program *p, 611 bool swap __maybe_unused, 612 struct alginfo *cipherdata, 613 struct alginfo *authdata __maybe_unused, 614 unsigned int dir, 615 enum pdcp_sn_size sn_size) 616 { 617 uint32_t offset = 0, length = 0, sn_mask = 0; 618 /* Insert Cipher Key */ 619 KEY(p, KEY1, cipherdata->key_enc_flags, cipherdata->key, 620 cipherdata->keylen, INLINE_KEY(cipherdata)); 621 622 if ((sn_size != PDCP_SN_SIZE_18 && 623 !(rta_sec_era == RTA_SEC_ERA_8 && 624 authdata->algtype == 0)) 625 || (rta_sec_era == RTA_SEC_ERA_10)) { 626 if (sn_size == PDCP_SN_SIZE_5) 627 PROTOCOL(p, dir, OP_PCLID_LTE_PDCP_CTRL_MIXED, 628 (uint16_t)cipherdata->algtype << 8); 629 else 630 PROTOCOL(p, dir, OP_PCLID_LTE_PDCP_USER_RN, 631 (uint16_t)cipherdata->algtype << 8); 632 return 0; 633 } 634 /* Non-proto is supported only for 5bit cplane and 18bit uplane */ 635 switch (sn_size) { 636 case PDCP_SN_SIZE_5: 637 offset = 7; 638 length = 1; 639 sn_mask = (swap == false) ? PDCP_C_PLANE_SN_MASK : 640 PDCP_C_PLANE_SN_MASK_BE; 641 break; 642 case PDCP_SN_SIZE_18: 643 offset = 5; 644 length = 3; 645 sn_mask = (swap == false) ? PDCP_U_PLANE_18BIT_SN_MASK : 646 PDCP_U_PLANE_18BIT_SN_MASK_BE; 647 break; 648 case PDCP_SN_SIZE_12: 649 offset = 6; 650 length = 2; 651 sn_mask = (swap == false) ? PDCP_12BIT_SN_MASK : 652 PDCP_12BIT_SN_MASK_BE; 653 break; 654 case PDCP_SN_SIZE_7: 655 case PDCP_SN_SIZE_15: 656 pr_err("Invalid sn_size for %s\n", __func__); 657 return -ENOTSUP; 658 } 659 660 SEQLOAD(p, MATH0, offset, length, 0); 661 JUMP(p, 1, LOCAL_JUMP, ALL_TRUE, CALM); 662 MATHB(p, MATH0, AND, sn_mask, MATH1, 8, IFB | IMMED2); 663 SEQSTORE(p, MATH0, offset, length, 0); 664 MATHB(p, MATH1, SHLD, MATH1, MATH1, 8, 0); 665 MOVEB(p, DESCBUF, 8, MATH2, 0, 8, WAITCOMP | IMMED); 666 MATHB(p, MATH1, OR, MATH2, MATH2, 8, 0); 667 668 switch (cipherdata->algtype) { 669 case PDCP_CIPHER_TYPE_SNOW: 670 MOVEB(p, MATH2, 0, CONTEXT1, 0, 8, WAITCOMP | IMMED); 671 672 MATHB(p, SEQINSZ, SUB, ZERO, VSEQINSZ, 4, 0); 673 674 if (dir == OP_TYPE_ENCAP_PROTOCOL) 675 MATHB(p, SEQINSZ, ADD, PDCP_MAC_I_LEN, VSEQOUTSZ, 4, 676 IMMED2); 677 else 678 MATHB(p, SEQINSZ, SUB, PDCP_MAC_I_LEN, VSEQOUTSZ, 4, 679 IMMED2); 680 SEQFIFOSTORE(p, MSG, 0, 0, VLF | CONT); 681 ALG_OPERATION(p, OP_ALG_ALGSEL_SNOW_F8, 682 OP_ALG_AAI_F8, 683 OP_ALG_AS_INITFINAL, ICV_CHECK_DISABLE, 684 dir == OP_TYPE_ENCAP_PROTOCOL ? 685 DIR_ENC : DIR_DEC); 686 break; 687 688 case PDCP_CIPHER_TYPE_AES: 689 MOVEB(p, MATH2, 0, CONTEXT1, 0x10, 0x10, WAITCOMP | IMMED); 690 691 MATHB(p, SEQINSZ, SUB, ZERO, VSEQINSZ, 4, 0); 692 693 if (dir == OP_TYPE_ENCAP_PROTOCOL) 694 MATHB(p, SEQINSZ, ADD, PDCP_MAC_I_LEN, VSEQOUTSZ, 4, 695 IMMED2); 696 else 697 MATHB(p, SEQINSZ, SUB, PDCP_MAC_I_LEN, VSEQOUTSZ, 4, 698 IMMED2); 699 700 SEQFIFOSTORE(p, MSG, 0, 0, VLF | CONT); 701 ALG_OPERATION(p, OP_ALG_ALGSEL_AES, 702 OP_ALG_AAI_CTR, 703 OP_ALG_AS_INITFINAL, 704 ICV_CHECK_DISABLE, 705 dir == OP_TYPE_ENCAP_PROTOCOL ? 706 DIR_ENC : DIR_DEC); 707 break; 708 709 case PDCP_CIPHER_TYPE_ZUC: 710 MOVEB(p, MATH2, 0, CONTEXT1, 0, 0x08, IMMED); 711 MOVEB(p, MATH2, 0, CONTEXT1, 0x08, 0x08, WAITCOMP | IMMED); 712 MATHB(p, SEQINSZ, SUB, ZERO, VSEQINSZ, 4, 0); 713 if (dir == OP_TYPE_ENCAP_PROTOCOL) 714 MATHB(p, SEQINSZ, ADD, PDCP_MAC_I_LEN, VSEQOUTSZ, 4, 715 IMMED2); 716 else 717 MATHB(p, SEQINSZ, SUB, PDCP_MAC_I_LEN, VSEQOUTSZ, 4, 718 IMMED2); 719 720 SEQFIFOSTORE(p, MSG, 0, 0, VLF | CONT); 721 ALG_OPERATION(p, OP_ALG_ALGSEL_ZUCE, 722 OP_ALG_AAI_F8, 723 OP_ALG_AS_INITFINAL, 724 ICV_CHECK_DISABLE, 725 dir == OP_TYPE_ENCAP_PROTOCOL ? 726 DIR_ENC : DIR_DEC); 727 break; 728 729 default: 730 pr_err("%s: Invalid encrypt algorithm selected: %d\n", 731 "pdcp_insert_cplane_enc_only_op", cipherdata->algtype); 732 return -EINVAL; 733 } 734 735 if (dir == OP_TYPE_ENCAP_PROTOCOL) { 736 SEQFIFOLOAD(p, MSG1, 0, VLF); 737 FIFOLOAD(p, MSG1, PDCP_NULL_INT_MAC_I_VAL, 4, 738 LAST1 | FLUSH1 | IMMED); 739 } else { 740 SEQFIFOLOAD(p, MSG1, 0, VLF | LAST1 | FLUSH1); 741 MOVE(p, OFIFO, 0, MATH1, 4, PDCP_MAC_I_LEN, WAITCOMP | IMMED); 742 MATHB(p, MATH1, XOR, PDCP_NULL_INT_MAC_I_VAL, NONE, 4, IMMED2); 743 JUMP(p, PDCP_NULL_INT_ICV_CHECK_FAILED_STATUS, 744 HALT_STATUS, ALL_FALSE, MATH_Z); 745 } 746 747 return 0; 748 } 749 750 static inline int 751 pdcp_insert_uplane_snow_snow_op(struct program *p, 752 bool swap __maybe_unused, 753 struct alginfo *cipherdata, 754 struct alginfo *authdata, 755 unsigned int dir, 756 enum pdcp_sn_size sn_size) 757 { 758 uint32_t offset = 0, length = 0, sn_mask = 0; 759 760 KEY(p, KEY1, cipherdata->key_enc_flags, cipherdata->key, 761 cipherdata->keylen, INLINE_KEY(cipherdata)); 762 KEY(p, KEY2, authdata->key_enc_flags, authdata->key, authdata->keylen, 763 INLINE_KEY(authdata)); 764 765 if (sn_size != PDCP_SN_SIZE_18) { 766 int pclid; 767 768 if (sn_size == PDCP_SN_SIZE_5) 769 pclid = OP_PCLID_LTE_PDCP_CTRL_MIXED; 770 else 771 pclid = OP_PCLID_LTE_PDCP_USER_RN; 772 773 PROTOCOL(p, dir, pclid, 774 ((uint16_t)cipherdata->algtype << 8) | 775 (uint16_t)authdata->algtype); 776 777 return 0; 778 } 779 /* sn_size is 18 */ 780 offset = 5; 781 length = 3; 782 sn_mask = (swap == false) ? PDCP_U_PLANE_18BIT_SN_MASK : 783 PDCP_U_PLANE_18BIT_SN_MASK_BE; 784 785 if (dir == OP_TYPE_ENCAP_PROTOCOL) 786 MATHB(p, SEQINSZ, SUB, length, VSEQINSZ, 4, IMMED2); 787 788 SEQLOAD(p, MATH0, offset, length, 0); 789 JUMP(p, 1, LOCAL_JUMP, ALL_TRUE, CALM); 790 MOVEB(p, MATH0, offset, IFIFOAB2, 0, length, IMMED); 791 MATHB(p, MATH0, AND, sn_mask, MATH1, 8, IFB | IMMED2); 792 793 SEQSTORE(p, MATH0, offset, length, 0); 794 MATHB(p, MATH1, SHLD, MATH1, MATH1, 8, 0); 795 MOVEB(p, DESCBUF, 8, MATH2, 0, 8, WAITCOMP | IMMED); 796 MATHB(p, MATH1, OR, MATH2, MATH1, 8, 0); 797 MOVEB(p, MATH1, 0, CONTEXT1, 0, 8, IMMED); 798 MOVEB(p, MATH1, 0, CONTEXT2, 0, 4, WAITCOMP | IMMED); 799 if (swap == false) { 800 MATHB(p, MATH1, AND, upper_32_bits(PDCP_BEARER_MASK), 801 MATH2, 4, IMMED2); 802 MATHB(p, MATH1, AND, lower_32_bits(PDCP_DIR_MASK), 803 MATH3, 4, IMMED2); 804 } else { 805 MATHB(p, MATH1, AND, lower_32_bits(PDCP_BEARER_MASK_BE), 806 MATH2, 4, IMMED2); 807 MATHB(p, MATH1, AND, upper_32_bits(PDCP_DIR_MASK_BE), 808 MATH3, 4, IMMED2); 809 } 810 MATHB(p, MATH3, SHLD, MATH3, MATH3, 8, 0); 811 812 MOVEB(p, MATH2, 4, OFIFO, 0, 12, IMMED); 813 MOVE(p, OFIFO, 0, CONTEXT2, 4, 12, IMMED); 814 if (dir == OP_TYPE_ENCAP_PROTOCOL) { 815 MATHB(p, SEQINSZ, ADD, PDCP_MAC_I_LEN, VSEQOUTSZ, 4, IMMED2); 816 } else { 817 MATHI(p, SEQINSZ, SUB, PDCP_MAC_I_LEN, VSEQOUTSZ, 4, IMMED2); 818 MATHI(p, SEQINSZ, SUB, PDCP_MAC_I_LEN, VSEQINSZ, 4, IMMED2); 819 } 820 821 if (dir == OP_TYPE_ENCAP_PROTOCOL) 822 SEQFIFOSTORE(p, MSG, 0, 0, VLF); 823 else 824 SEQFIFOSTORE(p, MSG, 0, 0, VLF | CONT); 825 826 ALG_OPERATION(p, OP_ALG_ALGSEL_SNOW_F9, 827 OP_ALG_AAI_F9, 828 OP_ALG_AS_INITFINAL, 829 dir == OP_TYPE_ENCAP_PROTOCOL ? 830 ICV_CHECK_DISABLE : ICV_CHECK_ENABLE, 831 DIR_DEC); 832 ALG_OPERATION(p, OP_ALG_ALGSEL_SNOW_F8, 833 OP_ALG_AAI_F8, 834 OP_ALG_AS_INITFINAL, 835 ICV_CHECK_DISABLE, 836 dir == OP_TYPE_ENCAP_PROTOCOL ? DIR_ENC : DIR_DEC); 837 838 if (dir == OP_TYPE_ENCAP_PROTOCOL) { 839 SEQFIFOLOAD(p, MSGINSNOOP, 0, VLF | LAST2); 840 MOVE(p, CONTEXT2, 0, IFIFOAB1, 0, 4, LAST1 | FLUSH1 | IMMED); 841 } else { 842 SEQFIFOLOAD(p, MSGOUTSNOOP, 0, VLF | LAST2); 843 SEQFIFOLOAD(p, MSG1, 4, LAST1 | FLUSH1); 844 JUMP(p, 1, LOCAL_JUMP, ALL_TRUE, CLASS1 | NOP | NIFP); 845 846 LOAD(p, 0, DCTRL, 0, LDLEN_RST_CHA_OFIFO_PTR, IMMED); 847 848 MOVE(p, OFIFO, 0, MATH0, 0, 4, WAITCOMP | IMMED); 849 850 NFIFOADD(p, IFIFO, ICV2, 4, LAST2); 851 852 MOVE(p, MATH0, 0, IFIFO, 0, 4, WAITCOMP | IMMED); 853 } 854 855 return 0; 856 } 857 858 static inline int 859 pdcp_insert_uplane_zuc_zuc_op(struct program *p, 860 bool swap __maybe_unused, 861 struct alginfo *cipherdata, 862 struct alginfo *authdata, 863 unsigned int dir, 864 enum pdcp_sn_size sn_size) 865 { 866 uint32_t offset = 0, length = 0, sn_mask = 0; 867 868 LABEL(keyjump); 869 REFERENCE(pkeyjump); 870 871 pkeyjump = JUMP(p, keyjump, LOCAL_JUMP, ALL_TRUE, SHRD | SELF | BOTH); 872 KEY(p, KEY1, cipherdata->key_enc_flags, cipherdata->key, 873 cipherdata->keylen, INLINE_KEY(cipherdata)); 874 KEY(p, KEY2, authdata->key_enc_flags, authdata->key, authdata->keylen, 875 INLINE_KEY(authdata)); 876 877 SET_LABEL(p, keyjump); 878 PATCH_JUMP(p, pkeyjump, keyjump); 879 880 if (sn_size != PDCP_SN_SIZE_18) { 881 int pclid; 882 883 if (sn_size == PDCP_SN_SIZE_5) 884 pclid = OP_PCLID_LTE_PDCP_CTRL_MIXED; 885 else 886 pclid = OP_PCLID_LTE_PDCP_USER_RN; 887 888 PROTOCOL(p, dir, pclid, 889 ((uint16_t)cipherdata->algtype << 8) | 890 (uint16_t)authdata->algtype); 891 892 return 0; 893 } 894 /* sn_size is 18 */ 895 offset = 5; 896 length = 3; 897 sn_mask = (swap == false) ? PDCP_U_PLANE_18BIT_SN_MASK : 898 PDCP_U_PLANE_18BIT_SN_MASK_BE; 899 900 SEQLOAD(p, MATH0, offset, length, 0); 901 JUMP(p, 1, LOCAL_JUMP, ALL_TRUE, CALM); 902 MOVEB(p, MATH0, offset, IFIFOAB2, 0, length, IMMED); 903 MATHB(p, MATH0, AND, sn_mask, MATH1, 8, IFB | IMMED2); 904 MATHB(p, MATH1, SHLD, MATH1, MATH1, 8, 0); 905 906 MOVEB(p, DESCBUF, 8, MATH2, 0, 8, WAITCOMP | IMMED); 907 MATHB(p, MATH1, OR, MATH2, MATH2, 8, 0); 908 MOVEB(p, MATH2, 0, CONTEXT1, 0, 8, IMMED); 909 910 MOVEB(p, MATH2, 0, CONTEXT2, 0, 8, WAITCOMP | IMMED); 911 912 if (dir == OP_TYPE_ENCAP_PROTOCOL) 913 MATHB(p, SEQINSZ, ADD, PDCP_MAC_I_LEN, VSEQOUTSZ, 4, IMMED2); 914 else 915 MATHB(p, SEQINSZ, SUB, PDCP_MAC_I_LEN, VSEQOUTSZ, 4, IMMED2); 916 917 MATHB(p, SEQINSZ, SUB, ZERO, VSEQINSZ, 4, 0); 918 SEQSTORE(p, MATH0, offset, length, 0); 919 920 if (dir == OP_TYPE_ENCAP_PROTOCOL) { 921 SEQFIFOSTORE(p, MSG, 0, 0, VLF); 922 SEQFIFOLOAD(p, MSGINSNOOP, 0, VLF | LAST2); 923 } else { 924 SEQFIFOSTORE(p, MSG, 0, 0, VLF | CONT); 925 SEQFIFOLOAD(p, MSGOUTSNOOP, 0, VLF | LAST1 | FLUSH1); 926 } 927 928 ALG_OPERATION(p, OP_ALG_ALGSEL_ZUCA, 929 OP_ALG_AAI_F9, 930 OP_ALG_AS_INITFINAL, 931 dir == OP_TYPE_ENCAP_PROTOCOL ? 932 ICV_CHECK_DISABLE : ICV_CHECK_ENABLE, 933 DIR_ENC); 934 935 ALG_OPERATION(p, OP_ALG_ALGSEL_ZUCE, 936 OP_ALG_AAI_F8, 937 OP_ALG_AS_INITFINAL, 938 ICV_CHECK_DISABLE, 939 dir == OP_TYPE_ENCAP_PROTOCOL ? DIR_ENC : DIR_DEC); 940 941 if (dir == OP_TYPE_ENCAP_PROTOCOL) { 942 MOVE(p, CONTEXT2, 0, IFIFOAB1, 0, 4, LAST1 | FLUSH1 | IMMED); 943 } else { 944 /* Save ICV */ 945 MOVEB(p, OFIFO, 0, MATH0, 0, 4, IMMED); 946 947 LOAD(p, NFIFOENTRY_STYPE_ALTSOURCE | 948 NFIFOENTRY_DEST_CLASS2 | 949 NFIFOENTRY_DTYPE_ICV | 950 NFIFOENTRY_LC2 | 4, NFIFO_SZL, 0, 4, IMMED); 951 MOVEB(p, MATH0, 0, ALTSOURCE, 0, 4, WAITCOMP | IMMED); 952 } 953 954 /* Reset ZUCA mode and done interrupt */ 955 LOAD(p, CLRW_CLR_C2MODE, CLRW, 0, 4, IMMED); 956 LOAD(p, CIRQ_ZADI, ICTRL, 0, 4, IMMED); 957 958 return 0; 959 } 960 961 static inline int 962 pdcp_insert_uplane_aes_aes_op(struct program *p, 963 bool swap __maybe_unused, 964 struct alginfo *cipherdata, 965 struct alginfo *authdata, 966 unsigned int dir, 967 enum pdcp_sn_size sn_size) 968 { 969 uint32_t offset = 0, length = 0, sn_mask = 0; 970 971 if (sn_size != PDCP_SN_SIZE_18) { 972 /* Insert Auth Key */ 973 KEY(p, KEY2, authdata->key_enc_flags, authdata->key, 974 authdata->keylen, INLINE_KEY(authdata)); 975 976 /* Insert Cipher Key */ 977 KEY(p, KEY1, cipherdata->key_enc_flags, cipherdata->key, 978 cipherdata->keylen, INLINE_KEY(cipherdata)); 979 980 PROTOCOL(p, dir, OP_PCLID_LTE_PDCP_USER_RN, 981 ((uint16_t)cipherdata->algtype << 8) | 982 (uint16_t)authdata->algtype); 983 return 0; 984 } 985 986 /* Non-proto is supported only for 5bit cplane and 18bit uplane */ 987 switch (sn_size) { 988 case PDCP_SN_SIZE_18: 989 offset = 5; 990 length = 3; 991 sn_mask = (swap == false) ? PDCP_U_PLANE_18BIT_SN_MASK : 992 PDCP_U_PLANE_18BIT_SN_MASK_BE; 993 break; 994 995 default: 996 pr_err("Invalid sn_size for %s\n", __func__); 997 return -ENOTSUP; 998 } 999 1000 SEQLOAD(p, MATH0, offset, length, 0); 1001 JUMP(p, 1, LOCAL_JUMP, ALL_TRUE, CALM); 1002 MATHB(p, MATH0, AND, sn_mask, MATH1, 8, IFB | IMMED2); 1003 1004 MATHB(p, MATH1, SHLD, MATH1, MATH1, 8, 0); 1005 MOVEB(p, DESCBUF, 8, MATH2, 0, 0x08, WAITCOMP | IMMED); 1006 MATHB(p, MATH1, OR, MATH2, MATH2, 8, 0); 1007 SEQSTORE(p, MATH0, offset, length, 0); 1008 1009 if (dir == OP_TYPE_ENCAP_PROTOCOL) { 1010 KEY(p, KEY1, authdata->key_enc_flags, authdata->key, 1011 authdata->keylen, INLINE_KEY(authdata)); 1012 MOVEB(p, MATH2, 0, IFIFOAB1, 0, 0x08, IMMED); 1013 MOVEB(p, MATH0, offset, IFIFOAB1, 0, length, IMMED); 1014 1015 MATHB(p, SEQINSZ, SUB, ZERO, VSEQINSZ, 4, 0); 1016 MATHB(p, VSEQINSZ, ADD, PDCP_MAC_I_LEN, VSEQOUTSZ, 4, IMMED2); 1017 1018 ALG_OPERATION(p, OP_ALG_ALGSEL_AES, 1019 OP_ALG_AAI_CMAC, 1020 OP_ALG_AS_INITFINAL, 1021 ICV_CHECK_DISABLE, 1022 DIR_DEC); 1023 SEQFIFOLOAD(p, MSG1, 0, VLF | LAST1 | FLUSH1); 1024 MOVEB(p, CONTEXT1, 0, MATH3, 0, 4, WAITCOMP | IMMED); 1025 1026 /* conditional jump with calm added to ensure that the 1027 * previous processing has been completed 1028 */ 1029 JUMP(p, 1, LOCAL_JUMP, ALL_TRUE, CALM); 1030 1031 LOAD(p, CLRW_RESET_CLS1_CHA | 1032 CLRW_CLR_C1KEY | 1033 CLRW_CLR_C1CTX | 1034 CLRW_CLR_C1ICV | 1035 CLRW_CLR_C1DATAS | 1036 CLRW_CLR_C1MODE, 1037 CLRW, 0, 4, IMMED); 1038 1039 KEY(p, KEY1, cipherdata->key_enc_flags, cipherdata->key, 1040 cipherdata->keylen, INLINE_KEY(cipherdata)); 1041 1042 MOVEB(p, MATH2, 0, CONTEXT1, 16, 8, IMMED); 1043 SEQINPTR(p, 0, PDCP_NULL_MAX_FRAME_LEN, RTO); 1044 1045 ALG_OPERATION(p, OP_ALG_ALGSEL_AES, 1046 OP_ALG_AAI_CTR, 1047 OP_ALG_AS_INITFINAL, 1048 ICV_CHECK_DISABLE, 1049 DIR_ENC); 1050 1051 SEQFIFOSTORE(p, MSG, 0, 0, VLF); 1052 1053 SEQFIFOLOAD(p, SKIP, length, 0); 1054 1055 SEQFIFOLOAD(p, MSG1, 0, VLF); 1056 MOVEB(p, MATH3, 0, IFIFOAB1, 0, 4, LAST1 | FLUSH1 | IMMED); 1057 } else { 1058 MOVEB(p, MATH2, 0, CONTEXT1, 16, 8, IMMED); 1059 MOVEB(p, MATH2, 0, CONTEXT2, 0, 8, IMMED); 1060 1061 MATHB(p, SEQINSZ, SUB, ZERO, VSEQINSZ, 4, 0); 1062 MATHB(p, SEQINSZ, SUB, PDCP_MAC_I_LEN, VSEQOUTSZ, 4, IMMED2); 1063 1064 KEY(p, KEY1, cipherdata->key_enc_flags, cipherdata->key, 1065 cipherdata->keylen, INLINE_KEY(cipherdata)); 1066 1067 ALG_OPERATION(p, OP_ALG_ALGSEL_AES, 1068 OP_ALG_AAI_CTR, 1069 OP_ALG_AS_INITFINAL, 1070 ICV_CHECK_DISABLE, 1071 DIR_DEC); 1072 1073 SEQFIFOSTORE(p, MSG, 0, 0, VLF | CONT); 1074 SEQFIFOLOAD(p, MSG1, 0, VLF | LAST1 | FLUSH1); 1075 1076 MOVEB(p, OFIFO, 0, MATH3, 0, 4, IMMED); 1077 1078 /* conditional jump with calm added to ensure that the 1079 * previous processing has been completed 1080 */ 1081 JUMP(p, 1, LOCAL_JUMP, ALL_TRUE, CALM); 1082 1083 LOAD(p, CLRW_RESET_CLS1_CHA | 1084 CLRW_CLR_C1KEY | 1085 CLRW_CLR_C1CTX | 1086 CLRW_CLR_C1ICV | 1087 CLRW_CLR_C1DATAS | 1088 CLRW_CLR_C1MODE, 1089 CLRW, 0, 4, IMMED); 1090 1091 KEY(p, KEY1, authdata->key_enc_flags, authdata->key, 1092 authdata->keylen, INLINE_KEY(authdata)); 1093 1094 SEQINPTR(p, 0, 0, SOP); 1095 1096 ALG_OPERATION(p, OP_ALG_ALGSEL_AES, 1097 OP_ALG_AAI_CMAC, 1098 OP_ALG_AS_INITFINAL, 1099 ICV_CHECK_ENABLE, 1100 DIR_DEC); 1101 1102 MATHB(p, SEQINSZ, SUB, ZERO, VSEQINSZ, 4, 0); 1103 1104 MOVE(p, CONTEXT2, 0, IFIFOAB1, 0, 8, IMMED); 1105 1106 SEQFIFOLOAD(p, MSG1, 0, VLF | LAST1 | FLUSH1); 1107 1108 LOAD(p, NFIFOENTRY_STYPE_ALTSOURCE | 1109 NFIFOENTRY_DEST_CLASS1 | 1110 NFIFOENTRY_DTYPE_ICV | 1111 NFIFOENTRY_LC1 | 1112 NFIFOENTRY_FC1 | 4, NFIFO_SZL, 0, 4, IMMED); 1113 MOVEB(p, MATH3, 0, ALTSOURCE, 0, 4, IMMED); 1114 } 1115 1116 return 0; 1117 } 1118 1119 static inline int 1120 pdcp_insert_cplane_acc_op(struct program *p, 1121 bool swap __maybe_unused, 1122 struct alginfo *cipherdata, 1123 struct alginfo *authdata, 1124 unsigned int dir, 1125 enum pdcp_sn_size sn_size) 1126 { 1127 /* Insert Auth Key */ 1128 KEY(p, KEY2, authdata->key_enc_flags, authdata->key, authdata->keylen, 1129 INLINE_KEY(authdata)); 1130 1131 /* Insert Cipher Key */ 1132 KEY(p, KEY1, cipherdata->key_enc_flags, cipherdata->key, 1133 cipherdata->keylen, INLINE_KEY(cipherdata)); 1134 1135 if (sn_size == PDCP_SN_SIZE_5) 1136 PROTOCOL(p, dir, OP_PCLID_LTE_PDCP_CTRL, 1137 (uint16_t)cipherdata->algtype); 1138 else 1139 PROTOCOL(p, dir, OP_PCLID_LTE_PDCP_USER_RN, 1140 ((uint16_t)cipherdata->algtype << 8) | 1141 (uint16_t)authdata->algtype); 1142 1143 return 0; 1144 } 1145 1146 static inline int 1147 pdcp_insert_cplane_snow_aes_op(struct program *p, 1148 bool swap __maybe_unused, 1149 struct alginfo *cipherdata, 1150 struct alginfo *authdata, 1151 unsigned int dir, 1152 enum pdcp_sn_size sn_size) 1153 { 1154 uint32_t offset = 0, length = 0, sn_mask = 0; 1155 1156 LABEL(back_to_sd_offset); 1157 LABEL(end_desc); 1158 LABEL(local_offset); 1159 LABEL(jump_to_beginning); 1160 REFERENCE(seqin_ptr_read); 1161 REFERENCE(seqin_ptr_write); 1162 REFERENCE(seq_out_read); 1163 REFERENCE(jump_back_to_sd_cmd); 1164 1165 if ((sn_size != PDCP_SN_SIZE_18) || 1166 (rta_sec_era == RTA_SEC_ERA_10)) { 1167 KEY(p, KEY1, cipherdata->key_enc_flags, cipherdata->key, 1168 cipherdata->keylen, INLINE_KEY(cipherdata)); 1169 KEY(p, KEY2, authdata->key_enc_flags, authdata->key, 1170 authdata->keylen, INLINE_KEY(authdata)); 1171 1172 if (sn_size == PDCP_SN_SIZE_5) 1173 PROTOCOL(p, dir, OP_PCLID_LTE_PDCP_CTRL_MIXED, 1174 ((uint16_t)cipherdata->algtype << 8) | 1175 (uint16_t)authdata->algtype); 1176 else 1177 PROTOCOL(p, dir, OP_PCLID_LTE_PDCP_USER_RN, 1178 ((uint16_t)cipherdata->algtype << 8) | 1179 (uint16_t)authdata->algtype); 1180 1181 return 0; 1182 } 1183 /* sn_size is 18 */ 1184 offset = 5; 1185 length = 3; 1186 sn_mask = (swap == false) ? PDCP_U_PLANE_18BIT_SN_MASK : 1187 PDCP_U_PLANE_18BIT_SN_MASK_BE; 1188 1189 SEQLOAD(p, MATH0, offset, length, 0); 1190 JUMP(p, 1, LOCAL_JUMP, ALL_TRUE, CALM); 1191 MATHB(p, MATH0, AND, sn_mask, MATH1, 8, IFB | IMMED2); 1192 MATHB(p, MATH1, SHLD, MATH1, MATH1, 8, 0); 1193 MOVEB(p, DESCBUF, 4, MATH2, 0, 0x08, WAITCOMP | IMMED); 1194 MATHB(p, MATH1, OR, MATH2, MATH2, 8, 0); 1195 SEQSTORE(p, MATH0, offset, length, 0); 1196 if (dir == OP_TYPE_ENCAP_PROTOCOL) { 1197 SEQINPTR(p, 0, length, RTO); 1198 1199 KEY(p, KEY1, authdata->key_enc_flags, authdata->key, 1200 authdata->keylen, INLINE_KEY(authdata)); 1201 MOVEB(p, MATH2, 0, IFIFOAB1, 0, 0x08, IMMED); 1202 1203 MATHB(p, SEQINSZ, SUB, ZERO, VSEQINSZ, 4, 0); 1204 MATHB(p, SEQINSZ, SUB, ZERO, MATH1, 4, 0); 1205 MATHB(p, VSEQINSZ, ADD, PDCP_MAC_I_LEN - 1, VSEQOUTSZ, 1206 4, IMMED2); 1207 1208 /* 1209 * Placeholder for filling the length in 1210 * SEQIN PTR RTO below 1211 */ 1212 seqin_ptr_read = MOVE(p, DESCBUF, 0, MATH1, 0, 6, IMMED); 1213 seqin_ptr_write = MOVE(p, MATH1, 0, DESCBUF, 0, 8, 1214 WAITCOMP | IMMED); 1215 ALG_OPERATION(p, OP_ALG_ALGSEL_AES, 1216 OP_ALG_AAI_CMAC, 1217 OP_ALG_AS_INITFINAL, 1218 ICV_CHECK_DISABLE, 1219 DIR_DEC); 1220 SEQFIFOLOAD(p, MSG1, 0, VLF | LAST1 | FLUSH1); 1221 MOVEB(p, CONTEXT1, 0, MATH3, 0, 4, WAITCOMP | IMMED); 1222 1223 /* conditional jump with calm added to ensure that the 1224 * previous processing has been completed 1225 */ 1226 JUMP(p, 1, LOCAL_JUMP, ALL_TRUE, CALM); 1227 1228 LOAD(p, CLRW_RESET_CLS1_CHA | 1229 CLRW_CLR_C1KEY | 1230 CLRW_CLR_C1CTX | 1231 CLRW_CLR_C1ICV | 1232 CLRW_CLR_C1DATAS | 1233 CLRW_CLR_C1MODE, 1234 CLRW, 0, 4, IMMED); 1235 1236 KEY(p, KEY1, cipherdata->key_enc_flags, cipherdata->key, 1237 cipherdata->keylen, INLINE_KEY(cipherdata)); 1238 SET_LABEL(p, local_offset); 1239 MOVEB(p, MATH2, 0, CONTEXT1, 0, 8, IMMED); 1240 SEQINPTR(p, 0, 0, RTO); 1241 1242 MATHB(p, SEQINSZ, SUB, length, VSEQINSZ, 4, IMMED2); 1243 ALG_OPERATION(p, OP_ALG_ALGSEL_SNOW_F8, 1244 OP_ALG_AAI_F8, 1245 OP_ALG_AS_INITFINAL, 1246 ICV_CHECK_DISABLE, 1247 DIR_ENC); 1248 SEQFIFOSTORE(p, MSG, 0, 0, VLF); 1249 1250 SEQFIFOLOAD(p, SKIP, length, 0); 1251 1252 SEQFIFOLOAD(p, MSG1, 0, VLF); 1253 MOVEB(p, MATH3, 0, IFIFOAB1, 0, 4, LAST1 | FLUSH1 | IMMED); 1254 PATCH_MOVE(p, seqin_ptr_read, local_offset); 1255 PATCH_MOVE(p, seqin_ptr_write, local_offset); 1256 } else { 1257 MOVEB(p, MATH2, 0, CONTEXT1, 0, 8, IMMED); 1258 1259 MOVE(p, CONTEXT1, 0, CONTEXT2, 0, 8, IMMED); 1260 1261 MATHB(p, SEQINSZ, SUB, ZERO, VSEQINSZ, 4, 0); 1262 1263 MATHI(p, SEQINSZ, SUB, PDCP_MAC_I_LEN, VSEQOUTSZ, 4, IMMED2); 1264 /* 1265 * TODO: To be changed when proper support is added in RTA (can't load a 1266 * command that is also written by RTA (or patch it for that matter). 1267 * Change when proper RTA support is added. 1268 */ 1269 if (p->ps) 1270 WORD(p, 0x168B0004); 1271 else 1272 WORD(p, 0x16880404); 1273 1274 jump_back_to_sd_cmd = JUMP(p, 0, LOCAL_JUMP, ALL_TRUE, 0); 1275 /* 1276 * Placeholder for command reading the SEQ OUT command in 1277 * JD. Done for rereading the decrypted data and performing 1278 * the integrity check 1279 */ 1280 /* 1281 * TODO: RTA currently doesn't support patching of length of a MOVE command 1282 * Thus, it is inserted as a raw word, as per PS setting. 1283 */ 1284 if (p->ps) 1285 seq_out_read = MOVE(p, DESCBUF, 0, MATH1, 0, 20, 1286 WAITCOMP | IMMED); 1287 else 1288 seq_out_read = MOVE(p, DESCBUF, 0, MATH1, 0, 16, 1289 WAITCOMP | IMMED); 1290 1291 MATHB(p, MATH1, XOR, CMD_SEQ_IN_PTR ^ CMD_SEQ_OUT_PTR, MATH1, 4, 1292 IMMED2); 1293 /* Placeholder for overwriting the SEQ IN with SEQ OUT */ 1294 /* 1295 * TODO: RTA currently doesn't support patching of length of a MOVE command 1296 * Thus, it is inserted as a raw word, as per PS setting. 1297 */ 1298 if (p->ps) 1299 MOVE(p, MATH1, 0, DESCBUF, 0, 24, IMMED); 1300 else 1301 MOVE(p, MATH1, 0, DESCBUF, 0, 20, IMMED); 1302 1303 KEY(p, KEY1, cipherdata->key_enc_flags, cipherdata->key, 1304 cipherdata->keylen, INLINE_KEY(cipherdata)); 1305 1306 MOVE(p, CONTEXT1, 0, CONTEXT2, 0, 8, IMMED); 1307 1308 ALG_OPERATION(p, OP_ALG_ALGSEL_SNOW_F8, 1309 OP_ALG_AAI_F8, 1310 OP_ALG_AS_INITFINAL, 1311 ICV_CHECK_DISABLE, 1312 DIR_DEC); 1313 SEQFIFOSTORE(p, MSG, 0, 0, VLF | CONT); 1314 SEQFIFOLOAD(p, MSG1, 0, VLF | LAST1 | FLUSH1); 1315 1316 MOVE(p, OFIFO, 0, MATH3, 0, 4, IMMED); 1317 1318 LOAD(p, CLRW_RESET_CLS1_CHA | 1319 CLRW_CLR_C1KEY | 1320 CLRW_CLR_C1CTX | 1321 CLRW_CLR_C1ICV | 1322 CLRW_CLR_C1DATAS | 1323 CLRW_CLR_C1MODE, 1324 CLRW, 0, 4, IMMED); 1325 1326 KEY(p, KEY1, authdata->key_enc_flags, authdata->key, 1327 authdata->keylen, INLINE_KEY(authdata)); 1328 /* 1329 * Placeholder for jump in SD for executing the new SEQ IN PTR 1330 * command (which is actually the old SEQ OUT PTR command 1331 * copied over from JD. 1332 */ 1333 SET_LABEL(p, jump_to_beginning); 1334 JUMP(p, 1 - jump_to_beginning, LOCAL_JUMP, ALL_TRUE, 0); 1335 SET_LABEL(p, back_to_sd_offset); 1336 ALG_OPERATION(p, OP_ALG_ALGSEL_AES, 1337 OP_ALG_AAI_CMAC, 1338 OP_ALG_AS_INITFINAL, 1339 ICV_CHECK_ENABLE, 1340 DIR_DEC); 1341 1342 /* Read the # of bytes written in the output buffer + 1 (HDR) */ 1343 MATHI(p, VSEQOUTSZ, ADD, length, VSEQINSZ, 4, IMMED2); 1344 1345 MOVE(p, CONTEXT2, 0, IFIFOAB1, 0, 8, IMMED); 1346 1347 SEQFIFOLOAD(p, MSG1, 0, VLF | LAST1 | FLUSH1); 1348 1349 LOAD(p, NFIFOENTRY_STYPE_ALTSOURCE | 1350 NFIFOENTRY_DEST_CLASS1 | 1351 NFIFOENTRY_DTYPE_ICV | 1352 NFIFOENTRY_LC1 | 1353 NFIFOENTRY_FC1 | 4, NFIFO_SZL, 0, 4, IMMED); 1354 MOVE(p, MATH3, 0, ALTSOURCE, 0, 4, IMMED); 1355 1356 1357 SET_LABEL(p, end_desc); 1358 1359 if (!p->ps) { 1360 PATCH_MOVE(p, seq_out_read, end_desc + 1); 1361 PATCH_JUMP(p, jump_back_to_sd_cmd, 1362 back_to_sd_offset + jump_back_to_sd_cmd - 5); 1363 } else { 1364 PATCH_MOVE(p, seq_out_read, end_desc + 2); 1365 PATCH_JUMP(p, jump_back_to_sd_cmd, 1366 back_to_sd_offset + jump_back_to_sd_cmd - 5); 1367 } 1368 } 1369 1370 return 0; 1371 } 1372 1373 static inline int 1374 pdcp_insert_cplane_aes_snow_op(struct program *p, 1375 bool swap __maybe_unused, 1376 struct alginfo *cipherdata, 1377 struct alginfo *authdata, 1378 unsigned int dir, 1379 enum pdcp_sn_size sn_size) 1380 { 1381 uint32_t offset = 0, length = 0, sn_mask = 0; 1382 1383 KEY(p, KEY1, cipherdata->key_enc_flags, cipherdata->key, 1384 cipherdata->keylen, INLINE_KEY(cipherdata)); 1385 KEY(p, KEY2, authdata->key_enc_flags, authdata->key, authdata->keylen, 1386 INLINE_KEY(authdata)); 1387 1388 if ((sn_size != PDCP_SN_SIZE_18) || 1389 (rta_sec_era == RTA_SEC_ERA_10)) { 1390 int pclid; 1391 1392 if (sn_size == PDCP_SN_SIZE_5) 1393 pclid = OP_PCLID_LTE_PDCP_CTRL_MIXED; 1394 else 1395 pclid = OP_PCLID_LTE_PDCP_USER_RN; 1396 1397 PROTOCOL(p, dir, pclid, 1398 ((uint16_t)cipherdata->algtype << 8) | 1399 (uint16_t)authdata->algtype); 1400 1401 return 0; 1402 } 1403 /* sn_size is 18 */ 1404 offset = 5; 1405 length = 3; 1406 sn_mask = (swap == false) ? PDCP_U_PLANE_18BIT_SN_MASK : 1407 PDCP_U_PLANE_18BIT_SN_MASK_BE; 1408 1409 if (dir == OP_TYPE_ENCAP_PROTOCOL) 1410 MATHB(p, SEQINSZ, SUB, length, VSEQINSZ, 4, IMMED2); 1411 1412 SEQLOAD(p, MATH0, offset, length, 0); 1413 JUMP(p, 1, LOCAL_JUMP, ALL_TRUE, CALM); 1414 MOVEB(p, MATH0, offset, IFIFOAB2, 0, length, IMMED); 1415 MATHB(p, MATH0, AND, sn_mask, MATH1, 8, IFB | IMMED2); 1416 1417 SEQSTORE(p, MATH0, offset, length, 0); 1418 MATHB(p, MATH1, SHLD, MATH1, MATH1, 8, 0); 1419 MOVEB(p, DESCBUF, 4, MATH2, 0, 8, WAITCOMP | IMMED); 1420 MATHB(p, MATH1, OR, MATH2, MATH1, 8, 0); 1421 MOVEB(p, MATH1, 0, CONTEXT1, 16, 8, IMMED); 1422 MOVEB(p, MATH1, 0, CONTEXT2, 0, 4, IMMED); 1423 if (swap == false) { 1424 MATHB(p, MATH1, AND, upper_32_bits(PDCP_BEARER_MASK), MATH2, 4, 1425 IMMED2); 1426 MATHB(p, MATH1, AND, lower_32_bits(PDCP_DIR_MASK), MATH3, 4, 1427 IMMED2); 1428 } else { 1429 MATHB(p, MATH1, AND, lower_32_bits(PDCP_BEARER_MASK_BE), MATH2, 1430 4, IMMED2); 1431 MATHB(p, MATH1, AND, upper_32_bits(PDCP_DIR_MASK_BE), MATH3, 1432 4, IMMED2); 1433 } 1434 MATHB(p, MATH3, SHLD, MATH3, MATH3, 8, 0); 1435 MOVEB(p, MATH2, 4, OFIFO, 0, 12, IMMED); 1436 MOVE(p, OFIFO, 0, CONTEXT2, 4, 12, IMMED); 1437 if (dir == OP_TYPE_ENCAP_PROTOCOL) { 1438 MATHB(p, SEQINSZ, ADD, PDCP_MAC_I_LEN, VSEQOUTSZ, 4, IMMED2); 1439 } else { 1440 MATHB(p, SEQINSZ, SUB, PDCP_MAC_I_LEN, MATH1, 4, IMMED2); 1441 1442 MATHB(p, ZERO, ADD, MATH1, VSEQOUTSZ, 4, 0); 1443 MATHB(p, ZERO, ADD, MATH1, VSEQINSZ, 4, 0); 1444 } 1445 1446 if (dir == OP_TYPE_ENCAP_PROTOCOL) 1447 SEQFIFOSTORE(p, MSG, 0, 0, VLF); 1448 else 1449 SEQFIFOSTORE(p, MSG, 0, 0, VLF | CONT); 1450 1451 ALG_OPERATION(p, OP_ALG_ALGSEL_SNOW_F9, 1452 OP_ALG_AAI_F9, 1453 OP_ALG_AS_INITFINAL, 1454 dir == OP_TYPE_ENCAP_PROTOCOL ? 1455 ICV_CHECK_DISABLE : ICV_CHECK_ENABLE, 1456 DIR_DEC); 1457 ALG_OPERATION(p, OP_ALG_ALGSEL_AES, 1458 OP_ALG_AAI_CTR, 1459 OP_ALG_AS_INITFINAL, 1460 ICV_CHECK_DISABLE, 1461 dir == OP_TYPE_ENCAP_PROTOCOL ? DIR_ENC : DIR_DEC); 1462 1463 if (dir == OP_TYPE_ENCAP_PROTOCOL) { 1464 SEQFIFOLOAD(p, MSGINSNOOP, 0, VLF | LAST2); 1465 MOVE(p, CONTEXT2, 0, IFIFOAB1, 0, 4, LAST1 | FLUSH1 | IMMED); 1466 } else { 1467 SEQFIFOLOAD(p, MSGOUTSNOOP, 0, VLF | LAST2); 1468 SEQFIFOLOAD(p, MSG1, 4, LAST1 | FLUSH1); 1469 JUMP(p, 1, LOCAL_JUMP, ALL_TRUE, CLASS1 | NOP | NIFP); 1470 1471 LOAD(p, 0, DCTRL, 0, LDLEN_RST_CHA_OFIFO_PTR, IMMED); 1472 1473 MOVE(p, OFIFO, 0, MATH0, 0, 4, WAITCOMP | IMMED); 1474 1475 NFIFOADD(p, IFIFO, ICV2, 4, LAST2); 1476 1477 MOVE(p, MATH0, 0, IFIFO, 0, 4, WAITCOMP | IMMED); 1478 } 1479 1480 return 0; 1481 } 1482 1483 static inline int 1484 pdcp_insert_cplane_snow_zuc_op(struct program *p, 1485 bool swap __maybe_unused, 1486 struct alginfo *cipherdata, 1487 struct alginfo *authdata, 1488 unsigned int dir, 1489 enum pdcp_sn_size sn_size) 1490 { 1491 uint32_t offset = 0, length = 0, sn_mask = 0; 1492 1493 LABEL(keyjump); 1494 REFERENCE(pkeyjump); 1495 1496 if ((sn_size != PDCP_SN_SIZE_18) || 1497 (rta_sec_era == RTA_SEC_ERA_10)) { 1498 int pclid; 1499 KEY(p, KEY1, cipherdata->key_enc_flags, cipherdata->key, 1500 cipherdata->keylen, INLINE_KEY(cipherdata)); 1501 KEY(p, KEY2, authdata->key_enc_flags, authdata->key, authdata->keylen, 1502 INLINE_KEY(authdata)); 1503 1504 if (sn_size == PDCP_SN_SIZE_5) 1505 pclid = OP_PCLID_LTE_PDCP_CTRL_MIXED; 1506 else 1507 pclid = OP_PCLID_LTE_PDCP_USER_RN; 1508 1509 PROTOCOL(p, dir, pclid, 1510 ((uint16_t)cipherdata->algtype << 8) | 1511 (uint16_t)authdata->algtype); 1512 return 0; 1513 } 1514 /* sn_size is 18 */ 1515 offset = 5; 1516 length = 3; 1517 sn_mask = (swap == false) ? PDCP_U_PLANE_18BIT_SN_MASK : 1518 PDCP_U_PLANE_18BIT_SN_MASK_BE; 1519 1520 pkeyjump = JUMP(p, keyjump, LOCAL_JUMP, ALL_TRUE, SHRD | SELF | BOTH); 1521 KEY(p, KEY1, cipherdata->key_enc_flags, cipherdata->key, 1522 cipherdata->keylen, INLINE_KEY(cipherdata)); 1523 KEY(p, KEY2, authdata->key_enc_flags, authdata->key, authdata->keylen, 1524 INLINE_KEY(authdata)); 1525 1526 SET_LABEL(p, keyjump); 1527 SEQLOAD(p, MATH0, offset, length, 0); 1528 JUMP(p, 1, LOCAL_JUMP, ALL_TRUE, CALM); 1529 MOVEB(p, MATH0, offset, IFIFOAB2, 0, length, IMMED); 1530 MATHB(p, MATH0, AND, sn_mask, MATH1, 8, IFB | IMMED2); 1531 1532 MATHB(p, MATH1, SHLD, MATH1, MATH1, 8, 0); 1533 MOVEB(p, DESCBUF, 4, MATH2, 0, 8, WAITCOMP | IMMED); 1534 MATHB(p, MATH1, OR, MATH2, MATH2, 8, 0); 1535 MOVEB(p, MATH2, 0, CONTEXT1, 0, 8, IMMED); 1536 MOVEB(p, MATH2, 0, CONTEXT2, 0, 8, WAITCOMP | IMMED); 1537 1538 if (dir == OP_TYPE_ENCAP_PROTOCOL) 1539 MATHB(p, SEQINSZ, ADD, PDCP_MAC_I_LEN, VSEQOUTSZ, 4, IMMED2); 1540 else 1541 MATHB(p, SEQINSZ, SUB, PDCP_MAC_I_LEN, VSEQOUTSZ, 4, IMMED2); 1542 1543 MATHB(p, SEQINSZ, SUB, ZERO, VSEQINSZ, 4, 0); 1544 SEQSTORE(p, MATH0, offset, length, 0); 1545 1546 if (dir == OP_TYPE_ENCAP_PROTOCOL) { 1547 SEQFIFOSTORE(p, MSG, 0, 0, VLF); 1548 SEQFIFOLOAD(p, MSGINSNOOP, 0, VLF | LAST2); 1549 } else { 1550 SEQFIFOSTORE(p, MSG, 0, 0, VLF | CONT); 1551 SEQFIFOLOAD(p, MSGOUTSNOOP, 0, VLF | LAST1 | FLUSH1); 1552 } 1553 1554 ALG_OPERATION(p, OP_ALG_ALGSEL_ZUCA, 1555 OP_ALG_AAI_F9, 1556 OP_ALG_AS_INITFINAL, 1557 dir == OP_TYPE_ENCAP_PROTOCOL ? 1558 ICV_CHECK_DISABLE : ICV_CHECK_ENABLE, 1559 DIR_ENC); 1560 1561 ALG_OPERATION(p, OP_ALG_ALGSEL_SNOW_F8, 1562 OP_ALG_AAI_F8, 1563 OP_ALG_AS_INITFINAL, 1564 ICV_CHECK_DISABLE, 1565 dir == OP_TYPE_ENCAP_PROTOCOL ? DIR_ENC : DIR_DEC); 1566 if (dir == OP_TYPE_ENCAP_PROTOCOL) { 1567 MOVE(p, CONTEXT2, 0, IFIFOAB1, 0, 4, LAST1 | FLUSH1 | IMMED); 1568 } else { 1569 /* Save ICV */ 1570 MOVE(p, OFIFO, 0, MATH0, 0, 4, IMMED); 1571 LOAD(p, NFIFOENTRY_STYPE_ALTSOURCE | 1572 NFIFOENTRY_DEST_CLASS2 | 1573 NFIFOENTRY_DTYPE_ICV | 1574 NFIFOENTRY_LC2 | 4, NFIFO_SZL, 0, 4, IMMED); 1575 MOVE(p, MATH0, 0, ALTSOURCE, 0, 4, WAITCOMP | IMMED); 1576 } 1577 1578 /* Reset ZUCA mode and done interrupt */ 1579 LOAD(p, CLRW_CLR_C2MODE, CLRW, 0, 4, IMMED); 1580 LOAD(p, CIRQ_ZADI, ICTRL, 0, 4, IMMED); 1581 1582 PATCH_JUMP(p, pkeyjump, keyjump); 1583 return 0; 1584 } 1585 1586 static inline int 1587 pdcp_insert_cplane_aes_zuc_op(struct program *p, 1588 bool swap __maybe_unused, 1589 struct alginfo *cipherdata, 1590 struct alginfo *authdata, 1591 unsigned int dir, 1592 enum pdcp_sn_size sn_size) 1593 { 1594 uint32_t offset = 0, length = 0, sn_mask = 0; 1595 LABEL(keyjump); 1596 REFERENCE(pkeyjump); 1597 1598 if ((sn_size != PDCP_SN_SIZE_18) || 1599 (rta_sec_era == RTA_SEC_ERA_10)) { 1600 int pclid; 1601 KEY(p, KEY1, cipherdata->key_enc_flags, cipherdata->key, 1602 cipherdata->keylen, INLINE_KEY(cipherdata)); 1603 KEY(p, KEY2, authdata->key_enc_flags, authdata->key, authdata->keylen, 1604 INLINE_KEY(authdata)); 1605 1606 if (sn_size == PDCP_SN_SIZE_5) 1607 pclid = OP_PCLID_LTE_PDCP_CTRL_MIXED; 1608 else 1609 pclid = OP_PCLID_LTE_PDCP_USER_RN; 1610 1611 PROTOCOL(p, dir, pclid, 1612 ((uint16_t)cipherdata->algtype << 8) | 1613 (uint16_t)authdata->algtype); 1614 1615 return 0; 1616 } 1617 /* sn_size is 18 */ 1618 offset = 5; 1619 length = 3; 1620 sn_mask = (swap == false) ? PDCP_U_PLANE_18BIT_SN_MASK : 1621 PDCP_U_PLANE_18BIT_SN_MASK_BE; 1622 1623 pkeyjump = JUMP(p, keyjump, LOCAL_JUMP, ALL_TRUE, SHRD | SELF | BOTH); 1624 KEY(p, KEY1, cipherdata->key_enc_flags, cipherdata->key, 1625 cipherdata->keylen, INLINE_KEY(cipherdata)); 1626 KEY(p, KEY2, authdata->key_enc_flags, authdata->key, authdata->keylen, 1627 INLINE_KEY(authdata)); 1628 1629 SET_LABEL(p, keyjump); 1630 1631 SEQLOAD(p, MATH0, offset, length, 0); 1632 JUMP(p, 1, LOCAL_JUMP, ALL_TRUE, CALM); 1633 MOVEB(p, MATH0, offset, IFIFOAB2, 0, length, IMMED); 1634 MATHB(p, MATH0, AND, sn_mask, MATH1, 8, IFB | IMMED2); 1635 1636 MATHB(p, MATH1, SHLD, MATH1, MATH1, 8, 0); 1637 MOVEB(p, DESCBUF, 4, MATH2, 0, 8, WAITCOMP | IMMED); 1638 MATHB(p, MATH1, OR, MATH2, MATH2, 8, 0); 1639 MOVEB(p, MATH2, 0, CONTEXT1, 16, 8, IMMED); 1640 MOVEB(p, MATH2, 0, CONTEXT2, 0, 8, WAITCOMP | IMMED); 1641 1642 if (dir == OP_TYPE_ENCAP_PROTOCOL) 1643 MATHB(p, SEQINSZ, ADD, PDCP_MAC_I_LEN, VSEQOUTSZ, 4, IMMED2); 1644 else 1645 MATHB(p, SEQINSZ, SUB, PDCP_MAC_I_LEN, VSEQOUTSZ, 4, IMMED2); 1646 1647 MATHB(p, SEQINSZ, SUB, ZERO, VSEQINSZ, 4, 0); 1648 SEQSTORE(p, MATH0, offset, length, 0); 1649 1650 if (dir == OP_TYPE_ENCAP_PROTOCOL) { 1651 SEQFIFOSTORE(p, MSG, 0, 0, VLF); 1652 SEQFIFOLOAD(p, MSGINSNOOP, 0, VLF | LAST2); 1653 } else { 1654 SEQFIFOSTORE(p, MSG, 0, 0, VLF | CONT); 1655 SEQFIFOLOAD(p, MSGOUTSNOOP, 0, VLF | LAST1 | FLUSH1); 1656 } 1657 1658 ALG_OPERATION(p, OP_ALG_ALGSEL_ZUCA, 1659 OP_ALG_AAI_F9, 1660 OP_ALG_AS_INITFINAL, 1661 dir == OP_TYPE_ENCAP_PROTOCOL ? 1662 ICV_CHECK_DISABLE : ICV_CHECK_ENABLE, 1663 DIR_ENC); 1664 1665 ALG_OPERATION(p, OP_ALG_ALGSEL_AES, 1666 OP_ALG_AAI_CTR, 1667 OP_ALG_AS_INITFINAL, 1668 ICV_CHECK_DISABLE, 1669 dir == OP_TYPE_ENCAP_PROTOCOL ? DIR_ENC : DIR_DEC); 1670 1671 if (dir == OP_TYPE_ENCAP_PROTOCOL) { 1672 MOVE(p, CONTEXT2, 0, IFIFOAB1, 0, 4, LAST1 | FLUSH1 | IMMED); 1673 } else { 1674 /* Save ICV */ 1675 MOVE(p, OFIFO, 0, MATH0, 0, 4, IMMED); 1676 1677 LOAD(p, NFIFOENTRY_STYPE_ALTSOURCE | 1678 NFIFOENTRY_DEST_CLASS2 | 1679 NFIFOENTRY_DTYPE_ICV | 1680 NFIFOENTRY_LC2 | 4, NFIFO_SZL, 0, 4, IMMED); 1681 MOVE(p, MATH0, 0, ALTSOURCE, 0, 4, WAITCOMP | IMMED); 1682 } 1683 1684 /* Reset ZUCA mode and done interrupt */ 1685 LOAD(p, CLRW_CLR_C2MODE, CLRW, 0, 4, IMMED); 1686 LOAD(p, CIRQ_ZADI, ICTRL, 0, 4, IMMED); 1687 1688 PATCH_JUMP(p, pkeyjump, keyjump); 1689 1690 return 0; 1691 } 1692 1693 static inline int 1694 pdcp_insert_cplane_zuc_snow_op(struct program *p, 1695 bool swap __maybe_unused, 1696 struct alginfo *cipherdata, 1697 struct alginfo *authdata, 1698 unsigned int dir, 1699 enum pdcp_sn_size sn_size) 1700 { 1701 uint32_t offset = 0, length = 0, sn_mask = 0; 1702 LABEL(keyjump); 1703 REFERENCE(pkeyjump); 1704 1705 if ((sn_size != PDCP_SN_SIZE_18) || 1706 (rta_sec_era == RTA_SEC_ERA_10)) { 1707 int pclid; 1708 KEY(p, KEY1, cipherdata->key_enc_flags, cipherdata->key, 1709 cipherdata->keylen, INLINE_KEY(cipherdata)); 1710 KEY(p, KEY2, authdata->key_enc_flags, authdata->key, authdata->keylen, 1711 INLINE_KEY(authdata)); 1712 1713 if (sn_size == PDCP_SN_SIZE_5) 1714 pclid = OP_PCLID_LTE_PDCP_CTRL_MIXED; 1715 else 1716 pclid = OP_PCLID_LTE_PDCP_USER_RN; 1717 1718 PROTOCOL(p, dir, pclid, 1719 ((uint16_t)cipherdata->algtype << 8) | 1720 (uint16_t)authdata->algtype); 1721 1722 return 0; 1723 } 1724 /* sn_size is 18 */ 1725 offset = 5; 1726 length = 3; 1727 sn_mask = (swap == false) ? PDCP_U_PLANE_18BIT_SN_MASK : 1728 PDCP_U_PLANE_18BIT_SN_MASK_BE; 1729 1730 pkeyjump = JUMP(p, keyjump, LOCAL_JUMP, ALL_TRUE, SHRD | SELF | BOTH); 1731 KEY(p, KEY1, cipherdata->key_enc_flags, cipherdata->key, 1732 cipherdata->keylen, INLINE_KEY(cipherdata)); 1733 KEY(p, KEY2, authdata->key_enc_flags, authdata->key, authdata->keylen, 1734 INLINE_KEY(authdata)); 1735 1736 SET_LABEL(p, keyjump); 1737 SEQLOAD(p, MATH0, offset, length, 0); 1738 JUMP(p, 1, LOCAL_JUMP, ALL_TRUE, CALM); 1739 MOVEB(p, MATH0, offset, IFIFOAB2, 0, length, IMMED); 1740 MATHB(p, MATH0, AND, sn_mask, MATH1, 8, IFB | IMMED2); 1741 1742 MATHB(p, MATH1, SHLD, MATH1, MATH1, 8, 0); 1743 MOVEB(p, DESCBUF, 4, MATH2, 0, 8, WAITCOMP | IMMED); 1744 MATHB(p, MATH1, OR, MATH2, MATH1, 8, 0); 1745 MOVEB(p, MATH1, 0, CONTEXT1, 0, 8, IMMED); 1746 MOVEB(p, MATH1, 0, CONTEXT2, 0, 4, IMMED); 1747 if (swap == false) { 1748 MATHB(p, MATH1, AND, upper_32_bits(PDCP_BEARER_MASK), MATH2, 1749 4, IMMED2); 1750 MATHB(p, MATH1, AND, lower_32_bits(PDCP_DIR_MASK), MATH3, 1751 4, IMMED2); 1752 } else { 1753 MATHB(p, MATH1, AND, lower_32_bits(PDCP_BEARER_MASK_BE), MATH2, 1754 4, IMMED2); 1755 MATHB(p, MATH1, AND, upper_32_bits(PDCP_DIR_MASK_BE), MATH3, 1756 4, IMMED2); 1757 } 1758 MATHB(p, MATH3, SHLD, MATH3, MATH3, 8, 0); 1759 MOVEB(p, MATH2, 4, OFIFO, 0, 12, IMMED); 1760 MOVE(p, OFIFO, 0, CONTEXT2, 4, 12, IMMED); 1761 1762 if (dir == OP_TYPE_ENCAP_PROTOCOL) { 1763 MATHB(p, SEQINSZ, ADD, PDCP_MAC_I_LEN, VSEQOUTSZ, 4, IMMED2); 1764 MATHB(p, SEQINSZ, SUB, ZERO, VSEQINSZ, 4, 0); 1765 } else { 1766 MATHB(p, SEQINSZ, SUB, PDCP_MAC_I_LEN, VSEQOUTSZ, 4, IMMED2); 1767 MATHB(p, VSEQOUTSZ, SUB, ZERO, VSEQINSZ, 4, 0); 1768 } 1769 1770 SEQSTORE(p, MATH0, offset, length, 0); 1771 1772 if (dir == OP_TYPE_ENCAP_PROTOCOL) { 1773 SEQFIFOSTORE(p, MSG, 0, 0, VLF); 1774 SEQFIFOLOAD(p, MSGINSNOOP, 0, VLF | LAST2); 1775 } else { 1776 SEQFIFOSTORE(p, MSG, 0, 0, VLF | CONT); 1777 SEQFIFOLOAD(p, MSGOUTSNOOP, 0, VLF | LAST2); 1778 } 1779 1780 ALG_OPERATION(p, OP_ALG_ALGSEL_SNOW_F9, 1781 OP_ALG_AAI_F9, 1782 OP_ALG_AS_INITFINAL, 1783 dir == OP_TYPE_ENCAP_PROTOCOL ? 1784 ICV_CHECK_DISABLE : ICV_CHECK_ENABLE, 1785 DIR_DEC); 1786 1787 ALG_OPERATION(p, OP_ALG_ALGSEL_ZUCE, 1788 OP_ALG_AAI_F8, 1789 OP_ALG_AS_INITFINAL, 1790 ICV_CHECK_DISABLE, 1791 dir == OP_TYPE_ENCAP_PROTOCOL ? DIR_ENC : DIR_DEC); 1792 1793 if (dir == OP_TYPE_ENCAP_PROTOCOL) { 1794 MOVE(p, CONTEXT2, 0, IFIFOAB1, 0, 4, LAST1 | FLUSH1 | IMMED); 1795 } else { 1796 SEQFIFOLOAD(p, MSG1, 4, LAST1 | FLUSH1); 1797 JUMP(p, 1, LOCAL_JUMP, ALL_TRUE, CLASS1 | NOP | NIFP); 1798 1799 /* 1800 * For SEC ERA 6, there's a problem with the OFIFO 1801 * pointer, and thus it needs to be reset here before 1802 * moving to M0. 1803 */ 1804 LOAD(p, 0, DCTRL, 0, LDLEN_RST_CHA_OFIFO_PTR, IMMED); 1805 1806 /* Put ICV to M0 before sending it to C2 for comparison. */ 1807 MOVEB(p, OFIFO, 0, MATH0, 0, 4, WAITCOMP | IMMED); 1808 1809 LOAD(p, NFIFOENTRY_STYPE_ALTSOURCE | 1810 NFIFOENTRY_DEST_CLASS2 | 1811 NFIFOENTRY_DTYPE_ICV | 1812 NFIFOENTRY_LC2 | 4, NFIFO_SZL, 0, 4, IMMED); 1813 MOVEB(p, MATH0, 0, ALTSOURCE, 0, 4, IMMED); 1814 } 1815 1816 PATCH_JUMP(p, pkeyjump, keyjump); 1817 return 0; 1818 } 1819 1820 static inline int 1821 pdcp_insert_cplane_zuc_aes_op(struct program *p, 1822 bool swap __maybe_unused, 1823 struct alginfo *cipherdata, 1824 struct alginfo *authdata, 1825 unsigned int dir, 1826 enum pdcp_sn_size sn_size) 1827 { 1828 uint32_t offset = 0, length = 0, sn_mask = 0; 1829 1830 if ((sn_size != PDCP_SN_SIZE_18) || 1831 (rta_sec_era == RTA_SEC_ERA_10)) { 1832 int pclid; 1833 1834 KEY(p, KEY1, cipherdata->key_enc_flags, cipherdata->key, 1835 cipherdata->keylen, INLINE_KEY(cipherdata)); 1836 KEY(p, KEY2, authdata->key_enc_flags, authdata->key, 1837 authdata->keylen, INLINE_KEY(authdata)); 1838 1839 if (sn_size == PDCP_SN_SIZE_5) 1840 pclid = OP_PCLID_LTE_PDCP_CTRL_MIXED; 1841 else 1842 pclid = OP_PCLID_LTE_PDCP_USER_RN; 1843 1844 PROTOCOL(p, dir, pclid, 1845 ((uint16_t)cipherdata->algtype << 8) | 1846 (uint16_t)authdata->algtype); 1847 return 0; 1848 } 1849 1850 /* sn_size is 18 */ 1851 offset = 5; 1852 length = 3; 1853 sn_mask = (swap == false) ? PDCP_U_PLANE_18BIT_SN_MASK : 1854 PDCP_U_PLANE_18BIT_SN_MASK_BE; 1855 1856 SEQLOAD(p, MATH0, offset, length, 0); 1857 JUMP(p, 1, LOCAL_JUMP, ALL_TRUE, CALM); 1858 MATHB(p, MATH0, AND, sn_mask, MATH1, 8, IFB | IMMED2); 1859 1860 MATHB(p, MATH1, SHLD, MATH1, MATH1, 8, 0); 1861 MOVEB(p, DESCBUF, 4, MATH2, 0, 0x08, WAITCOMP | IMMED); 1862 MATHB(p, MATH1, OR, MATH2, MATH2, 8, 0); 1863 SEQSTORE(p, MATH0, offset, length, 0); 1864 if (dir == OP_TYPE_ENCAP_PROTOCOL) { 1865 KEY(p, KEY1, authdata->key_enc_flags, authdata->key, 1866 authdata->keylen, INLINE_KEY(authdata)); 1867 MOVEB(p, MATH2, 0, IFIFOAB1, 0, 0x08, IMMED); 1868 MOVEB(p, MATH0, offset, IFIFOAB1, 0, length, IMMED); 1869 1870 MATHB(p, SEQINSZ, SUB, ZERO, VSEQINSZ, 4, 0); 1871 MATHB(p, VSEQINSZ, ADD, PDCP_MAC_I_LEN, VSEQOUTSZ, 4, IMMED2); 1872 1873 ALG_OPERATION(p, OP_ALG_ALGSEL_AES, 1874 OP_ALG_AAI_CMAC, 1875 OP_ALG_AS_INITFINAL, 1876 ICV_CHECK_DISABLE, 1877 DIR_DEC); 1878 SEQFIFOLOAD(p, MSG1, 0, VLF | LAST1 | FLUSH1); 1879 MOVEB(p, CONTEXT1, 0, MATH3, 0, 4, WAITCOMP | IMMED); 1880 LOAD(p, CLRW_RESET_CLS1_CHA | 1881 CLRW_CLR_C1KEY | 1882 CLRW_CLR_C1CTX | 1883 CLRW_CLR_C1ICV | 1884 CLRW_CLR_C1DATAS | 1885 CLRW_CLR_C1MODE, 1886 CLRW, 0, 4, IMMED); 1887 1888 KEY(p, KEY1, cipherdata->key_enc_flags, cipherdata->key, 1889 cipherdata->keylen, INLINE_KEY(cipherdata)); 1890 1891 MOVEB(p, MATH2, 0, CONTEXT1, 0, 8, IMMED); 1892 SEQINPTR(p, 0, PDCP_NULL_MAX_FRAME_LEN, RTO); 1893 1894 ALG_OPERATION(p, OP_ALG_ALGSEL_ZUCE, 1895 OP_ALG_AAI_F8, 1896 OP_ALG_AS_INITFINAL, 1897 ICV_CHECK_DISABLE, 1898 DIR_ENC); 1899 SEQFIFOSTORE(p, MSG, 0, 0, VLF); 1900 1901 SEQFIFOLOAD(p, SKIP, length, 0); 1902 1903 SEQFIFOLOAD(p, MSG1, 0, VLF); 1904 MOVEB(p, MATH3, 0, IFIFOAB1, 0, 4, LAST1 | FLUSH1 | IMMED); 1905 } else { 1906 MOVEB(p, MATH2, 0, CONTEXT1, 0, 8, IMMED); 1907 1908 MOVE(p, CONTEXT1, 0, CONTEXT2, 0, 8, IMMED); 1909 1910 MATHB(p, SEQINSZ, SUB, ZERO, VSEQINSZ, 4, 0); 1911 1912 MATHB(p, SEQINSZ, SUB, PDCP_MAC_I_LEN, VSEQOUTSZ, 4, IMMED2); 1913 1914 KEY(p, KEY1, cipherdata->key_enc_flags, cipherdata->key, 1915 cipherdata->keylen, INLINE_KEY(cipherdata)); 1916 1917 MOVE(p, CONTEXT1, 0, CONTEXT2, 0, 8, IMMED); 1918 1919 ALG_OPERATION(p, OP_ALG_ALGSEL_ZUCE, 1920 OP_ALG_AAI_F8, 1921 OP_ALG_AS_INITFINAL, 1922 ICV_CHECK_DISABLE, 1923 DIR_DEC); 1924 SEQFIFOSTORE(p, MSG, 0, 0, VLF | CONT); 1925 SEQFIFOLOAD(p, MSG1, 0, VLF | LAST1 | FLUSH1); 1926 1927 MOVEB(p, OFIFO, 0, MATH3, 0, 4, IMMED); 1928 1929 /* conditional jump with calm added to ensure that the 1930 * previous processing has been completed 1931 */ 1932 JUMP(p, 1, LOCAL_JUMP, ALL_TRUE, CALM); 1933 1934 LOAD(p, CLRW_RESET_CLS1_CHA | 1935 CLRW_CLR_C1KEY | 1936 CLRW_CLR_C1CTX | 1937 CLRW_CLR_C1ICV | 1938 CLRW_CLR_C1DATAS | 1939 CLRW_CLR_C1MODE, 1940 CLRW, 0, 4, IMMED); 1941 1942 KEY(p, KEY1, authdata->key_enc_flags, authdata->key, 1943 authdata->keylen, INLINE_KEY(authdata)); 1944 1945 SEQINPTR(p, 0, 0, SOP); 1946 1947 ALG_OPERATION(p, OP_ALG_ALGSEL_AES, 1948 OP_ALG_AAI_CMAC, 1949 OP_ALG_AS_INITFINAL, 1950 ICV_CHECK_ENABLE, 1951 DIR_DEC); 1952 1953 MATHB(p, SEQINSZ, SUB, ZERO, VSEQINSZ, 4, 0); 1954 1955 MOVE(p, CONTEXT2, 0, IFIFOAB1, 0, 8, IMMED); 1956 1957 SEQFIFOLOAD(p, MSG1, 0, VLF | LAST1 | FLUSH1); 1958 1959 LOAD(p, NFIFOENTRY_STYPE_ALTSOURCE | 1960 NFIFOENTRY_DEST_CLASS1 | 1961 NFIFOENTRY_DTYPE_ICV | 1962 NFIFOENTRY_LC1 | 1963 NFIFOENTRY_FC1 | 4, NFIFO_SZL, 0, 4, IMMED); 1964 MOVEB(p, MATH3, 0, ALTSOURCE, 0, 4, IMMED); 1965 } 1966 1967 return 0; 1968 } 1969 1970 static inline int 1971 pdcp_insert_uplane_no_int_op(struct program *p, 1972 bool swap __maybe_unused, 1973 struct alginfo *cipherdata, 1974 unsigned int dir, 1975 enum pdcp_sn_size sn_size) 1976 { 1977 int op; 1978 uint32_t sn_mask; 1979 1980 /* Insert Cipher Key */ 1981 KEY(p, KEY1, cipherdata->key_enc_flags, cipherdata->key, 1982 cipherdata->keylen, INLINE_KEY(cipherdata)); 1983 1984 if ((sn_size == PDCP_SN_SIZE_15) || 1985 (rta_sec_era >= RTA_SEC_ERA_10)) { 1986 PROTOCOL(p, dir, OP_PCLID_LTE_PDCP_USER, 1987 (uint16_t)cipherdata->algtype); 1988 return 0; 1989 } 1990 1991 if (sn_size == PDCP_SN_SIZE_15) { 1992 SEQLOAD(p, MATH0, 6, 2, 0); 1993 sn_mask = (swap == false) ? PDCP_U_PLANE_15BIT_SN_MASK : 1994 PDCP_U_PLANE_15BIT_SN_MASK_BE; 1995 } else { /* SN Size == PDCP_SN_SIZE_18 */ 1996 SEQLOAD(p, MATH0, 5, 3, 0); 1997 sn_mask = (swap == false) ? PDCP_U_PLANE_18BIT_SN_MASK : 1998 PDCP_U_PLANE_18BIT_SN_MASK_BE; 1999 } 2000 JUMP(p, 1, LOCAL_JUMP, ALL_TRUE, CALM); 2001 MATHB(p, MATH0, AND, sn_mask, MATH1, 8, IFB | IMMED2); 2002 2003 if (sn_size == PDCP_SN_SIZE_15) 2004 SEQSTORE(p, MATH0, 6, 2, 0); 2005 else /* SN Size == PDCP_SN_SIZE_18 */ 2006 SEQSTORE(p, MATH0, 5, 3, 0); 2007 2008 MATHB(p, MATH1, SHLD, MATH1, MATH1, 8, 0); 2009 MOVEB(p, DESCBUF, 8, MATH2, 0, 8, WAITCOMP | IMMED); 2010 MATHB(p, MATH1, OR, MATH2, MATH2, 8, 0); 2011 2012 MATHB(p, SEQINSZ, SUB, MATH3, VSEQINSZ, 4, 0); 2013 MATHB(p, SEQINSZ, SUB, MATH3, VSEQOUTSZ, 4, 0); 2014 2015 SEQFIFOSTORE(p, MSG, 0, 0, VLF); 2016 2017 op = dir == OP_TYPE_ENCAP_PROTOCOL ? DIR_ENC : DIR_DEC; 2018 switch (cipherdata->algtype) { 2019 case PDCP_CIPHER_TYPE_SNOW: 2020 MOVEB(p, MATH2, 0, CONTEXT1, 0, 8, WAITCOMP | IMMED); 2021 ALG_OPERATION(p, OP_ALG_ALGSEL_SNOW_F8, 2022 OP_ALG_AAI_F8, 2023 OP_ALG_AS_INITFINAL, 2024 ICV_CHECK_DISABLE, 2025 op); 2026 break; 2027 2028 case PDCP_CIPHER_TYPE_AES: 2029 MOVEB(p, MATH2, 0, CONTEXT1, 0x10, 0x10, WAITCOMP | IMMED); 2030 ALG_OPERATION(p, OP_ALG_ALGSEL_AES, 2031 OP_ALG_AAI_CTR, 2032 OP_ALG_AS_INITFINAL, 2033 ICV_CHECK_DISABLE, 2034 op); 2035 break; 2036 2037 case PDCP_CIPHER_TYPE_ZUC: 2038 MOVEB(p, MATH2, 0, CONTEXT1, 0, 0x08, IMMED); 2039 MOVEB(p, MATH2, 0, CONTEXT1, 0x08, 0x08, WAITCOMP | IMMED); 2040 2041 ALG_OPERATION(p, OP_ALG_ALGSEL_ZUCE, 2042 OP_ALG_AAI_F8, 2043 OP_ALG_AS_INITFINAL, 2044 ICV_CHECK_DISABLE, 2045 op); 2046 break; 2047 2048 default: 2049 pr_err("%s: Invalid encrypt algorithm selected: %d\n", 2050 "pdcp_insert_uplane_15bit_op", cipherdata->algtype); 2051 return -EINVAL; 2052 } 2053 2054 SEQFIFOLOAD(p, MSG1, 0, VLF | LAST1 | FLUSH1); 2055 2056 return 0; 2057 } 2058 2059 /* 2060 * Function for inserting the snippet of code responsible for creating 2061 * the HFN override code via either DPOVRD or via the input frame. 2062 */ 2063 static inline int 2064 insert_hfn_ov_op(struct program *p, 2065 uint32_t shift, 2066 enum pdb_type_e pdb_type, 2067 bool clear_dpovrd_at_end) 2068 { 2069 uint32_t imm = PDCP_DPOVRD_HFN_OV_EN; 2070 uint16_t hfn_pdb_offset; 2071 LABEL(keyjump); 2072 REFERENCE(pkeyjump); 2073 2074 switch (pdb_type) { 2075 case PDCP_PDB_TYPE_NO_PDB: 2076 /* 2077 * If there is no PDB, then HFN override mechanism does not 2078 * make any sense, thus in this case the function will 2079 * return the pointer to the current position in the 2080 * descriptor buffer 2081 */ 2082 return 0; 2083 2084 case PDCP_PDB_TYPE_REDUCED_PDB: 2085 hfn_pdb_offset = REDUCED_PDB_DESCBUF_HFN_BEARER_DIR_OFFSET; 2086 break; 2087 2088 case PDCP_PDB_TYPE_FULL_PDB: 2089 hfn_pdb_offset = FULL_PDB_DESCBUF_HFN_BEARER_DIR_OFFSET; 2090 break; 2091 2092 default: 2093 return -EINVAL; 2094 } 2095 2096 MATHB(p, DPOVRD, AND, imm, NONE, 8, IFB | IMMED2); 2097 2098 pkeyjump = JUMP(p, keyjump, LOCAL_JUMP, ALL_TRUE, MATH_Z); 2099 2100 MATHI(p, DPOVRD, LSHIFT, shift, MATH0, 4, IMMED2); 2101 2102 MATHB(p, MATH0, SHLD, MATH0, MATH0, 8, 0); 2103 MOVE(p, MATH0, 0, DESCBUF, hfn_pdb_offset, 4, IMMED); 2104 2105 if (clear_dpovrd_at_end) { 2106 /* 2107 * For ERA8, DPOVRD could be handled by the PROTOCOL command 2108 * itself. For now, this is not done. Thus, clear DPOVRD here 2109 * to alleviate any side-effects. 2110 */ 2111 MATHB(p, DPOVRD, AND, ZERO, DPOVRD, 4, STL); 2112 } 2113 2114 SET_LABEL(p, keyjump); 2115 PATCH_JUMP(p, pkeyjump, keyjump); 2116 return 0; 2117 } 2118 2119 /* 2120 * PDCP Control PDB creation function 2121 */ 2122 static inline enum pdb_type_e 2123 cnstr_pdcp_c_plane_pdb(struct program *p, 2124 uint32_t hfn, 2125 enum pdcp_sn_size sn_size, 2126 unsigned char bearer, 2127 unsigned char direction, 2128 uint32_t hfn_threshold) 2129 { 2130 struct pdcp_pdb pdb; 2131 2132 memset(&pdb, 0x00, sizeof(struct pdcp_pdb)); 2133 2134 /* To support 12-bit seq numbers, we use u-plane opt in pdb. 2135 * SEC supports 5-bit only with c-plane opt in pdb. 2136 */ 2137 if (sn_size == PDCP_SN_SIZE_12) { 2138 pdb.hfn_res = hfn << PDCP_U_PLANE_PDB_LONG_SN_HFN_SHIFT; 2139 pdb.bearer_dir_res = (uint32_t) 2140 ((bearer << PDCP_U_PLANE_PDB_BEARER_SHIFT) | 2141 (direction << PDCP_U_PLANE_PDB_DIR_SHIFT)); 2142 2143 pdb.hfn_thr_res = 2144 hfn_threshold << PDCP_U_PLANE_PDB_LONG_SN_HFN_THR_SHIFT; 2145 2146 } else { 2147 /* This means 5-bit c-plane. 2148 * Here we use c-plane opt in pdb 2149 */ 2150 2151 /* This is a HW issue. Bit 2 should be set to zero, 2152 * but it does not work this way. Override here. 2153 */ 2154 pdb.opt_res.rsvd = 0x00000002; 2155 2156 /* Copy relevant information from user to PDB */ 2157 pdb.hfn_res = hfn << PDCP_C_PLANE_PDB_HFN_SHIFT; 2158 pdb.bearer_dir_res = (uint32_t) 2159 ((bearer << PDCP_C_PLANE_PDB_BEARER_SHIFT) | 2160 (direction << PDCP_C_PLANE_PDB_DIR_SHIFT)); 2161 pdb.hfn_thr_res = 2162 hfn_threshold << PDCP_C_PLANE_PDB_HFN_THR_SHIFT; 2163 } 2164 2165 /* copy PDB in descriptor*/ 2166 __rta_out32(p, pdb.opt_res.opt); 2167 __rta_out32(p, pdb.hfn_res); 2168 __rta_out32(p, pdb.bearer_dir_res); 2169 __rta_out32(p, pdb.hfn_thr_res); 2170 2171 return PDCP_PDB_TYPE_FULL_PDB; 2172 } 2173 2174 /* 2175 * PDCP UPlane PDB creation function 2176 */ 2177 static inline enum pdb_type_e 2178 cnstr_pdcp_u_plane_pdb(struct program *p, 2179 enum pdcp_sn_size sn_size, 2180 uint32_t hfn, unsigned short bearer, 2181 unsigned short direction, 2182 uint32_t hfn_threshold, 2183 struct alginfo *cipherdata, 2184 struct alginfo *authdata) 2185 { 2186 struct pdcp_pdb pdb; 2187 enum pdb_type_e pdb_type = PDCP_PDB_TYPE_FULL_PDB; 2188 enum pdb_type_e 2189 pdb_mask[PDCP_CIPHER_TYPE_INVALID][PDCP_AUTH_TYPE_INVALID] = { 2190 { /* NULL */ 2191 PDCP_PDB_TYPE_NO_PDB, /* NULL */ 2192 PDCP_PDB_TYPE_FULL_PDB, /* SNOW f9 */ 2193 PDCP_PDB_TYPE_FULL_PDB, /* AES CMAC */ 2194 PDCP_PDB_TYPE_FULL_PDB /* ZUC-I */ 2195 }, 2196 { /* SNOW f8 */ 2197 PDCP_PDB_TYPE_FULL_PDB, /* NULL */ 2198 PDCP_PDB_TYPE_FULL_PDB, /* SNOW f9 */ 2199 PDCP_PDB_TYPE_REDUCED_PDB, /* AES CMAC */ 2200 PDCP_PDB_TYPE_REDUCED_PDB /* ZUC-I */ 2201 }, 2202 { /* AES CTR */ 2203 PDCP_PDB_TYPE_FULL_PDB, /* NULL */ 2204 PDCP_PDB_TYPE_REDUCED_PDB, /* SNOW f9 */ 2205 PDCP_PDB_TYPE_FULL_PDB, /* AES CMAC */ 2206 PDCP_PDB_TYPE_REDUCED_PDB /* ZUC-I */ 2207 }, 2208 { /* ZUC-E */ 2209 PDCP_PDB_TYPE_FULL_PDB, /* NULL */ 2210 PDCP_PDB_TYPE_REDUCED_PDB, /* SNOW f9 */ 2211 PDCP_PDB_TYPE_REDUCED_PDB, /* AES CMAC */ 2212 PDCP_PDB_TYPE_FULL_PDB /* ZUC-I */ 2213 }, 2214 }; 2215 2216 /* Read options from user */ 2217 /* Depending on sequence number length, the HFN and HFN threshold 2218 * have different lengths. 2219 */ 2220 memset(&pdb, 0x00, sizeof(struct pdcp_pdb)); 2221 2222 switch (sn_size) { 2223 case PDCP_SN_SIZE_7: 2224 pdb.opt_res.opt |= PDCP_U_PLANE_PDB_OPT_SHORT_SN; 2225 pdb.hfn_res = hfn << PDCP_U_PLANE_PDB_SHORT_SN_HFN_SHIFT; 2226 pdb.hfn_thr_res = 2227 hfn_threshold<<PDCP_U_PLANE_PDB_SHORT_SN_HFN_THR_SHIFT; 2228 break; 2229 2230 case PDCP_SN_SIZE_12: 2231 pdb.opt_res.opt &= (uint32_t)(~PDCP_U_PLANE_PDB_OPT_SHORT_SN); 2232 pdb.hfn_res = hfn << PDCP_U_PLANE_PDB_LONG_SN_HFN_SHIFT; 2233 pdb.hfn_thr_res = 2234 hfn_threshold<<PDCP_U_PLANE_PDB_LONG_SN_HFN_THR_SHIFT; 2235 break; 2236 2237 case PDCP_SN_SIZE_15: 2238 pdb.opt_res.opt = (uint32_t)(PDCP_U_PLANE_PDB_OPT_15B_SN); 2239 pdb.hfn_res = hfn << PDCP_U_PLANE_PDB_15BIT_SN_HFN_SHIFT; 2240 pdb.hfn_thr_res = 2241 hfn_threshold<<PDCP_U_PLANE_PDB_15BIT_SN_HFN_THR_SHIFT; 2242 break; 2243 2244 case PDCP_SN_SIZE_18: 2245 pdb.opt_res.opt = (uint32_t)(PDCP_U_PLANE_PDB_OPT_18B_SN); 2246 pdb.hfn_res = hfn << PDCP_U_PLANE_PDB_18BIT_SN_HFN_SHIFT; 2247 pdb.hfn_thr_res = 2248 hfn_threshold<<PDCP_U_PLANE_PDB_18BIT_SN_HFN_THR_SHIFT; 2249 2250 if (rta_sec_era == RTA_SEC_ERA_8) { 2251 if (cipherdata && authdata) 2252 pdb_type = pdb_mask[cipherdata->algtype] 2253 [authdata->algtype]; 2254 } 2255 break; 2256 2257 default: 2258 pr_err("Invalid Sequence Number Size setting in PDB\n"); 2259 return -EINVAL; 2260 } 2261 2262 pdb.bearer_dir_res = (uint32_t) 2263 ((bearer << PDCP_U_PLANE_PDB_BEARER_SHIFT) | 2264 (direction << PDCP_U_PLANE_PDB_DIR_SHIFT)); 2265 2266 switch (pdb_type) { 2267 case PDCP_PDB_TYPE_NO_PDB: 2268 break; 2269 2270 case PDCP_PDB_TYPE_REDUCED_PDB: 2271 __rta_out32(p, pdb.hfn_res); 2272 __rta_out32(p, pdb.bearer_dir_res); 2273 break; 2274 2275 case PDCP_PDB_TYPE_FULL_PDB: 2276 /* copy PDB in descriptor*/ 2277 __rta_out32(p, pdb.opt_res.opt); 2278 __rta_out32(p, pdb.hfn_res); 2279 __rta_out32(p, pdb.bearer_dir_res); 2280 __rta_out32(p, pdb.hfn_thr_res); 2281 2282 break; 2283 2284 default: 2285 return PDCP_PDB_TYPE_INVALID; 2286 } 2287 2288 return pdb_type; 2289 } 2290 2291 /** 2292 * cnstr_shdsc_pdcp_c_plane_encap - Function for creating a PDCP Control Plane 2293 * encapsulation descriptor. 2294 * @descbuf: pointer to buffer for descriptor construction 2295 * @ps: if 36/40bit addressing is desired, this parameter must be true 2296 * @swap: must be true when core endianness doesn't match SEC endianness 2297 * @hfn: starting Hyper Frame Number to be used together with the SN from the 2298 * PDCP frames. 2299 * @sn_size: size of sequence numbers, only 5/12 bit sequence numbers are valid 2300 * @bearer: radio bearer ID 2301 * @direction: the direction of the PDCP frame (UL/DL) 2302 * @hfn_threshold: HFN value that once reached triggers a warning from SEC that 2303 * keys should be renegotiated at the earliest convenience. 2304 * @cipherdata: pointer to block cipher transform definitions 2305 * Valid algorithm values are those from cipher_type_pdcp enum. 2306 * @authdata: pointer to authentication transform definitions 2307 * Valid algorithm values are those from auth_type_pdcp enum. 2308 * Return: size of descriptor written in words or negative number on error. 2309 * Once the function returns, the value of this parameter can be used 2310 * for reclaiming the space that wasn't used for the descriptor. 2311 * 2312 * Note: descbuf must be large enough to contain a full 256 byte long 2313 * descriptor; after the function returns, by subtracting the actual number of 2314 * bytes used, the user can reuse the remaining buffer space for other purposes. 2315 */ 2316 static inline int 2317 cnstr_shdsc_pdcp_c_plane_encap(uint32_t *descbuf, 2318 bool ps, 2319 bool swap, 2320 uint32_t hfn, 2321 enum pdcp_sn_size sn_size, 2322 unsigned char bearer, 2323 unsigned char direction, 2324 uint32_t hfn_threshold, 2325 struct alginfo *cipherdata, 2326 struct alginfo *authdata) 2327 { 2328 static int 2329 (*pdcp_cp_fp[PDCP_CIPHER_TYPE_INVALID][PDCP_AUTH_TYPE_INVALID]) 2330 (struct program*, bool swap, struct alginfo *, 2331 struct alginfo *, unsigned int dir, enum pdcp_sn_size) = { 2332 { /* NULL */ 2333 pdcp_insert_cplane_null_op, /* NULL */ 2334 pdcp_insert_cplane_int_only_op, /* SNOW f9 */ 2335 pdcp_insert_cplane_int_only_op, /* AES CMAC */ 2336 pdcp_insert_cplane_int_only_op /* ZUC-I */ 2337 }, 2338 { /* SNOW f8 */ 2339 pdcp_insert_cplane_enc_only_op, /* NULL */ 2340 pdcp_insert_cplane_acc_op, /* SNOW f9 */ 2341 pdcp_insert_cplane_snow_aes_op, /* AES CMAC */ 2342 pdcp_insert_cplane_snow_zuc_op /* ZUC-I */ 2343 }, 2344 { /* AES CTR */ 2345 pdcp_insert_cplane_enc_only_op, /* NULL */ 2346 pdcp_insert_cplane_aes_snow_op, /* SNOW f9 */ 2347 pdcp_insert_cplane_acc_op, /* AES CMAC */ 2348 pdcp_insert_cplane_aes_zuc_op /* ZUC-I */ 2349 }, 2350 { /* ZUC-E */ 2351 pdcp_insert_cplane_enc_only_op, /* NULL */ 2352 pdcp_insert_cplane_zuc_snow_op, /* SNOW f9 */ 2353 pdcp_insert_cplane_zuc_aes_op, /* AES CMAC */ 2354 pdcp_insert_cplane_acc_op /* ZUC-I */ 2355 }, 2356 }; 2357 static enum rta_share_type 2358 desc_share[PDCP_CIPHER_TYPE_INVALID][PDCP_AUTH_TYPE_INVALID] = { 2359 { /* NULL */ 2360 SHR_WAIT, /* NULL */ 2361 SHR_WAIT, /* SNOW f9 */ 2362 SHR_ALWAYS, /* AES CMAC */ 2363 SHR_WAIT /* ZUC-I */ 2364 }, 2365 { /* SNOW f8 */ 2366 SHR_WAIT, /* NULL */ 2367 SHR_WAIT, /* SNOW f9 */ 2368 SHR_WAIT, /* AES CMAC */ 2369 SHR_WAIT /* ZUC-I */ 2370 }, 2371 { /* AES CTR */ 2372 SHR_WAIT, /* NULL */ 2373 SHR_WAIT, /* SNOW f9 */ 2374 SHR_ALWAYS, /* AES CMAC */ 2375 SHR_WAIT /* ZUC-I */ 2376 }, 2377 { /* ZUC-E */ 2378 SHR_WAIT, /* NULL */ 2379 SHR_WAIT, /* SNOW f9 */ 2380 SHR_WAIT, /* AES CMAC */ 2381 SHR_WAIT /* ZUC-I */ 2382 }, 2383 }; 2384 enum pdb_type_e pdb_type; 2385 struct program prg; 2386 struct program *p = &prg; 2387 int err; 2388 LABEL(pdb_end); 2389 2390 if (sn_size != PDCP_SN_SIZE_12 && sn_size != PDCP_SN_SIZE_5) { 2391 pr_err("C-plane supports only 5-bit and 12-bit sequence numbers\n"); 2392 return -EINVAL; 2393 } 2394 2395 PROGRAM_CNTXT_INIT(p, descbuf, 0); 2396 if (swap) 2397 PROGRAM_SET_BSWAP(p); 2398 if (ps) 2399 PROGRAM_SET_36BIT_ADDR(p); 2400 2401 SHR_HDR(p, desc_share[cipherdata->algtype][authdata->algtype], 0, 0); 2402 2403 pdb_type = cnstr_pdcp_c_plane_pdb(p, 2404 hfn, 2405 sn_size, 2406 bearer, 2407 direction, 2408 hfn_threshold); 2409 2410 SET_LABEL(p, pdb_end); 2411 2412 err = insert_hfn_ov_op(p, sn_size, pdb_type, true); 2413 if (err) 2414 return err; 2415 2416 err = pdcp_cp_fp[cipherdata->algtype][authdata->algtype](p, 2417 swap, 2418 cipherdata, 2419 authdata, 2420 OP_TYPE_ENCAP_PROTOCOL, 2421 sn_size); 2422 if (err) 2423 return err; 2424 2425 PATCH_HDR(p, 0, pdb_end); 2426 2427 return PROGRAM_FINALIZE(p); 2428 } 2429 2430 /** 2431 * cnstr_shdsc_pdcp_c_plane_decap - Function for creating a PDCP Control Plane 2432 * decapsulation descriptor. 2433 * @descbuf: pointer to buffer for descriptor construction 2434 * @ps: if 36/40bit addressing is desired, this parameter must be true 2435 * @swap: must be true when core endianness doesn't match SEC endianness 2436 * @hfn: starting Hyper Frame Number to be used together with the SN from the 2437 * PDCP frames. 2438 * @sn_size: size of sequence numbers, only 5/12 bit sequence numbers are valid 2439 * @bearer: radio bearer ID 2440 * @direction: the direction of the PDCP frame (UL/DL) 2441 * @hfn_threshold: HFN value that once reached triggers a warning from SEC that 2442 * keys should be renegotiated at the earliest convenience. 2443 * @cipherdata: pointer to block cipher transform definitions 2444 * Valid algorithm values are those from cipher_type_pdcp enum. 2445 * @authdata: pointer to authentication transform definitions 2446 * Valid algorithm values are those from auth_type_pdcp enum. 2447 * 2448 * Return: size of descriptor written in words or negative number on error. 2449 * Once the function returns, the value of this parameter can be used 2450 * for reclaiming the space that wasn't used for the descriptor. 2451 * 2452 * Note: descbuf must be large enough to contain a full 256 byte long 2453 * descriptor; after the function returns, by subtracting the actual number of 2454 * bytes used, the user can reuse the remaining buffer space for other purposes. 2455 */ 2456 static inline int 2457 cnstr_shdsc_pdcp_c_plane_decap(uint32_t *descbuf, 2458 bool ps, 2459 bool swap, 2460 uint32_t hfn, 2461 enum pdcp_sn_size sn_size, 2462 unsigned char bearer, 2463 unsigned char direction, 2464 uint32_t hfn_threshold, 2465 struct alginfo *cipherdata, 2466 struct alginfo *authdata) 2467 { 2468 static int 2469 (*pdcp_cp_fp[PDCP_CIPHER_TYPE_INVALID][PDCP_AUTH_TYPE_INVALID]) 2470 (struct program*, bool swap, struct alginfo *, 2471 struct alginfo *, unsigned int dir, enum pdcp_sn_size) = { 2472 { /* NULL */ 2473 pdcp_insert_cplane_null_op, /* NULL */ 2474 pdcp_insert_cplane_int_only_op, /* SNOW f9 */ 2475 pdcp_insert_cplane_int_only_op, /* AES CMAC */ 2476 pdcp_insert_cplane_int_only_op /* ZUC-I */ 2477 }, 2478 { /* SNOW f8 */ 2479 pdcp_insert_cplane_enc_only_op, /* NULL */ 2480 pdcp_insert_cplane_acc_op, /* SNOW f9 */ 2481 pdcp_insert_cplane_snow_aes_op, /* AES CMAC */ 2482 pdcp_insert_cplane_snow_zuc_op /* ZUC-I */ 2483 }, 2484 { /* AES CTR */ 2485 pdcp_insert_cplane_enc_only_op, /* NULL */ 2486 pdcp_insert_cplane_aes_snow_op, /* SNOW f9 */ 2487 pdcp_insert_cplane_acc_op, /* AES CMAC */ 2488 pdcp_insert_cplane_aes_zuc_op /* ZUC-I */ 2489 }, 2490 { /* ZUC-E */ 2491 pdcp_insert_cplane_enc_only_op, /* NULL */ 2492 pdcp_insert_cplane_zuc_snow_op, /* SNOW f9 */ 2493 pdcp_insert_cplane_zuc_aes_op, /* AES CMAC */ 2494 pdcp_insert_cplane_acc_op /* ZUC-I */ 2495 }, 2496 }; 2497 static enum rta_share_type 2498 desc_share[PDCP_CIPHER_TYPE_INVALID][PDCP_AUTH_TYPE_INVALID] = { 2499 { /* NULL */ 2500 SHR_WAIT, /* NULL */ 2501 SHR_WAIT, /* SNOW f9 */ 2502 SHR_ALWAYS, /* AES CMAC */ 2503 SHR_WAIT /* ZUC-I */ 2504 }, 2505 { /* SNOW f8 */ 2506 SHR_WAIT, /* NULL */ 2507 SHR_WAIT, /* SNOW f9 */ 2508 SHR_WAIT, /* AES CMAC */ 2509 SHR_WAIT /* ZUC-I */ 2510 }, 2511 { /* AES CTR */ 2512 SHR_WAIT, /* NULL */ 2513 SHR_WAIT, /* SNOW f9 */ 2514 SHR_ALWAYS, /* AES CMAC */ 2515 SHR_WAIT /* ZUC-I */ 2516 }, 2517 { /* ZUC-E */ 2518 SHR_WAIT, /* NULL */ 2519 SHR_WAIT, /* SNOW f9 */ 2520 SHR_WAIT, /* AES CMAC */ 2521 SHR_WAIT /* ZUC-I */ 2522 }, 2523 }; 2524 enum pdb_type_e pdb_type; 2525 struct program prg; 2526 struct program *p = &prg; 2527 int err; 2528 LABEL(pdb_end); 2529 2530 if (sn_size != PDCP_SN_SIZE_12 && sn_size != PDCP_SN_SIZE_5) { 2531 pr_err("C-plane supports only 5-bit and 12-bit sequence numbers\n"); 2532 return -EINVAL; 2533 } 2534 2535 PROGRAM_CNTXT_INIT(p, descbuf, 0); 2536 if (swap) 2537 PROGRAM_SET_BSWAP(p); 2538 if (ps) 2539 PROGRAM_SET_36BIT_ADDR(p); 2540 2541 SHR_HDR(p, desc_share[cipherdata->algtype][authdata->algtype], 0, 0); 2542 2543 pdb_type = cnstr_pdcp_c_plane_pdb(p, 2544 hfn, 2545 sn_size, 2546 bearer, 2547 direction, 2548 hfn_threshold); 2549 2550 SET_LABEL(p, pdb_end); 2551 2552 err = insert_hfn_ov_op(p, sn_size, pdb_type, true); 2553 if (err) 2554 return err; 2555 2556 err = pdcp_cp_fp[cipherdata->algtype][authdata->algtype](p, 2557 swap, 2558 cipherdata, 2559 authdata, 2560 OP_TYPE_DECAP_PROTOCOL, 2561 sn_size); 2562 if (err) 2563 return err; 2564 2565 PATCH_HDR(p, 0, pdb_end); 2566 2567 return PROGRAM_FINALIZE(p); 2568 } 2569 2570 static int 2571 pdcp_insert_uplane_with_int_op(struct program *p, 2572 bool swap __maybe_unused, 2573 struct alginfo *cipherdata, 2574 struct alginfo *authdata, 2575 enum pdcp_sn_size sn_size, 2576 unsigned int dir) 2577 { 2578 static int 2579 (*pdcp_cp_fp[PDCP_CIPHER_TYPE_INVALID][PDCP_AUTH_TYPE_INVALID]) 2580 (struct program*, bool swap, struct alginfo *, 2581 struct alginfo *, unsigned int dir, enum pdcp_sn_size) = { 2582 { /* NULL */ 2583 pdcp_insert_cplane_null_op, /* NULL */ 2584 pdcp_insert_cplane_int_only_op, /* SNOW f9 */ 2585 pdcp_insert_cplane_int_only_op, /* AES CMAC */ 2586 pdcp_insert_cplane_int_only_op /* ZUC-I */ 2587 }, 2588 { /* SNOW f8 */ 2589 pdcp_insert_cplane_enc_only_op, /* NULL */ 2590 pdcp_insert_uplane_snow_snow_op, /* SNOW f9 */ 2591 pdcp_insert_cplane_snow_aes_op, /* AES CMAC */ 2592 pdcp_insert_cplane_snow_zuc_op /* ZUC-I */ 2593 }, 2594 { /* AES CTR */ 2595 pdcp_insert_cplane_enc_only_op, /* NULL */ 2596 pdcp_insert_cplane_aes_snow_op, /* SNOW f9 */ 2597 pdcp_insert_uplane_aes_aes_op, /* AES CMAC */ 2598 pdcp_insert_cplane_aes_zuc_op /* ZUC-I */ 2599 }, 2600 { /* ZUC-E */ 2601 pdcp_insert_cplane_enc_only_op, /* NULL */ 2602 pdcp_insert_cplane_zuc_snow_op, /* SNOW f9 */ 2603 pdcp_insert_cplane_zuc_aes_op, /* AES CMAC */ 2604 pdcp_insert_uplane_zuc_zuc_op /* ZUC-I */ 2605 }, 2606 }; 2607 int err; 2608 2609 err = pdcp_cp_fp[cipherdata->algtype][authdata->algtype](p, 2610 swap, 2611 cipherdata, 2612 authdata, 2613 dir, 2614 sn_size); 2615 if (err) 2616 return err; 2617 2618 return 0; 2619 } 2620 2621 2622 /** 2623 * cnstr_shdsc_pdcp_u_plane_encap - Function for creating a PDCP User Plane 2624 * encapsulation descriptor. 2625 * @descbuf: pointer to buffer for descriptor construction 2626 * @ps: if 36/40bit addressing is desired, this parameter must be true 2627 * @swap: must be true when core endianness doesn't match SEC endianness 2628 * @sn_size: selects Sequence Number Size: 7/12/15 bits 2629 * @hfn: starting Hyper Frame Number to be used together with the SN from the 2630 * PDCP frames. 2631 * @bearer: radio bearer ID 2632 * @direction: the direction of the PDCP frame (UL/DL) 2633 * @hfn_threshold: HFN value that once reached triggers a warning from SEC that 2634 * keys should be renegotiated at the earliest convenience. 2635 * @cipherdata: pointer to block cipher transform definitions 2636 * Valid algorithm values are those from cipher_type_pdcp enum. 2637 * 2638 * Return: size of descriptor written in words or negative number on error. 2639 * Once the function returns, the value of this parameter can be used 2640 * for reclaiming the space that wasn't used for the descriptor. 2641 * 2642 * Note: descbuf must be large enough to contain a full 256 byte long 2643 * descriptor; after the function returns, by subtracting the actual number of 2644 * bytes used, the user can reuse the remaining buffer space for other purposes. 2645 */ 2646 static inline int 2647 cnstr_shdsc_pdcp_u_plane_encap(uint32_t *descbuf, 2648 bool ps, 2649 bool swap, 2650 enum pdcp_sn_size sn_size, 2651 uint32_t hfn, 2652 unsigned short bearer, 2653 unsigned short direction, 2654 uint32_t hfn_threshold, 2655 struct alginfo *cipherdata, 2656 struct alginfo *authdata) 2657 { 2658 struct program prg; 2659 struct program *p = &prg; 2660 int err; 2661 enum pdb_type_e pdb_type; 2662 static enum rta_share_type 2663 desc_share[PDCP_CIPHER_TYPE_INVALID][PDCP_AUTH_TYPE_INVALID] = { 2664 { /* NULL */ 2665 SHR_WAIT, /* NULL */ 2666 SHR_WAIT, /* SNOW f9 */ 2667 SHR_ALWAYS, /* AES CMAC */ 2668 SHR_WAIT /* ZUC-I */ 2669 }, 2670 { /* SNOW f8 */ 2671 SHR_WAIT, /* NULL */ 2672 SHR_WAIT, /* SNOW f9 */ 2673 SHR_WAIT, /* AES CMAC */ 2674 SHR_WAIT /* ZUC-I */ 2675 }, 2676 { /* AES CTR */ 2677 SHR_WAIT, /* NULL */ 2678 SHR_WAIT, /* SNOW f9 */ 2679 SHR_ALWAYS, /* AES CMAC */ 2680 SHR_WAIT /* ZUC-I */ 2681 }, 2682 { /* ZUC-E */ 2683 SHR_WAIT, /* NULL */ 2684 SHR_WAIT, /* SNOW f9 */ 2685 SHR_WAIT, /* AES CMAC */ 2686 SHR_WAIT /* ZUC-I */ 2687 }, 2688 }; 2689 LABEL(pdb_end); 2690 2691 PROGRAM_CNTXT_INIT(p, descbuf, 0); 2692 if (swap) 2693 PROGRAM_SET_BSWAP(p); 2694 if (ps) 2695 PROGRAM_SET_36BIT_ADDR(p); 2696 2697 if (authdata) 2698 SHR_HDR(p, desc_share[cipherdata->algtype][authdata->algtype], 0, 0); 2699 else 2700 SHR_HDR(p, SHR_WAIT, 0, 0); 2701 pdb_type = cnstr_pdcp_u_plane_pdb(p, sn_size, hfn, 2702 bearer, direction, hfn_threshold, 2703 cipherdata, authdata); 2704 if (pdb_type == PDCP_PDB_TYPE_INVALID) { 2705 pr_err("Error creating PDCP UPlane PDB\n"); 2706 return -EINVAL; 2707 } 2708 SET_LABEL(p, pdb_end); 2709 2710 err = insert_hfn_ov_op(p, sn_size, pdb_type, true); 2711 if (err) 2712 return err; 2713 2714 switch (sn_size) { 2715 case PDCP_SN_SIZE_7: 2716 case PDCP_SN_SIZE_12: 2717 switch (cipherdata->algtype) { 2718 case PDCP_CIPHER_TYPE_ZUC: 2719 /* fallthrough */ 2720 case PDCP_CIPHER_TYPE_AES: 2721 case PDCP_CIPHER_TYPE_SNOW: 2722 case PDCP_CIPHER_TYPE_NULL: 2723 if (rta_sec_era == RTA_SEC_ERA_8 && 2724 authdata && authdata->algtype == 0){ 2725 err = pdcp_insert_uplane_with_int_op(p, swap, 2726 cipherdata, authdata, 2727 sn_size, 2728 OP_TYPE_ENCAP_PROTOCOL); 2729 if (err) 2730 return err; 2731 break; 2732 } 2733 2734 if (pdb_type != PDCP_PDB_TYPE_FULL_PDB) { 2735 pr_err("PDB type must be FULL for PROTO desc\n"); 2736 return -EINVAL; 2737 } 2738 2739 /* Insert auth key if requested */ 2740 if (authdata && authdata->algtype) { 2741 KEY(p, KEY2, authdata->key_enc_flags, 2742 (uint64_t)authdata->key, authdata->keylen, 2743 INLINE_KEY(authdata)); 2744 } 2745 /* Insert Cipher Key */ 2746 KEY(p, KEY1, cipherdata->key_enc_flags, 2747 (uint64_t)cipherdata->key, cipherdata->keylen, 2748 INLINE_KEY(cipherdata)); 2749 2750 if (authdata) 2751 PROTOCOL(p, OP_TYPE_ENCAP_PROTOCOL, 2752 OP_PCLID_LTE_PDCP_USER_RN, 2753 ((uint16_t)cipherdata->algtype << 8) | 2754 (uint16_t)authdata->algtype); 2755 else 2756 PROTOCOL(p, OP_TYPE_ENCAP_PROTOCOL, 2757 OP_PCLID_LTE_PDCP_USER, 2758 (uint16_t)cipherdata->algtype); 2759 break; 2760 default: 2761 pr_err("%s: Invalid encrypt algorithm selected: %d\n", 2762 "cnstr_pcl_shdsc_pdcp_u_plane_decap", 2763 cipherdata->algtype); 2764 return -EINVAL; 2765 } 2766 break; 2767 2768 case PDCP_SN_SIZE_15: 2769 case PDCP_SN_SIZE_18: 2770 if (authdata) { 2771 err = pdcp_insert_uplane_with_int_op(p, swap, 2772 cipherdata, authdata, 2773 sn_size, 2774 OP_TYPE_ENCAP_PROTOCOL); 2775 if (err) 2776 return err; 2777 2778 break; 2779 } 2780 2781 switch (cipherdata->algtype) { 2782 case PDCP_CIPHER_TYPE_NULL: 2783 insert_copy_frame_op(p, 2784 cipherdata, 2785 OP_TYPE_ENCAP_PROTOCOL); 2786 break; 2787 2788 default: 2789 err = pdcp_insert_uplane_no_int_op(p, swap, cipherdata, 2790 OP_TYPE_ENCAP_PROTOCOL, sn_size); 2791 if (err) 2792 return err; 2793 break; 2794 } 2795 break; 2796 2797 case PDCP_SN_SIZE_5: 2798 default: 2799 pr_err("Invalid SN size selected\n"); 2800 return -ENOTSUP; 2801 } 2802 2803 PATCH_HDR(p, 0, pdb_end); 2804 return PROGRAM_FINALIZE(p); 2805 } 2806 2807 /** 2808 * cnstr_shdsc_pdcp_u_plane_decap - Function for creating a PDCP User Plane 2809 * decapsulation descriptor. 2810 * @descbuf: pointer to buffer for descriptor construction 2811 * @ps: if 36/40bit addressing is desired, this parameter must be true 2812 * @swap: must be true when core endianness doesn't match SEC endianness 2813 * @sn_size: selects Sequence Number Size: 7/12/15 bits 2814 * @hfn: starting Hyper Frame Number to be used together with the SN from the 2815 * PDCP frames. 2816 * @bearer: radio bearer ID 2817 * @direction: the direction of the PDCP frame (UL/DL) 2818 * @hfn_threshold: HFN value that once reached triggers a warning from SEC that 2819 * keys should be renegotiated at the earliest convenience. 2820 * @cipherdata: pointer to block cipher transform definitions 2821 * Valid algorithm values are those from cipher_type_pdcp enum. 2822 * 2823 * Return: size of descriptor written in words or negative number on error. 2824 * Once the function returns, the value of this parameter can be used 2825 * for reclaiming the space that wasn't used for the descriptor. 2826 * 2827 * Note: descbuf must be large enough to contain a full 256 byte long 2828 * descriptor; after the function returns, by subtracting the actual number of 2829 * bytes used, the user can reuse the remaining buffer space for other purposes. 2830 */ 2831 static inline int 2832 cnstr_shdsc_pdcp_u_plane_decap(uint32_t *descbuf, 2833 bool ps, 2834 bool swap, 2835 enum pdcp_sn_size sn_size, 2836 uint32_t hfn, 2837 unsigned short bearer, 2838 unsigned short direction, 2839 uint32_t hfn_threshold, 2840 struct alginfo *cipherdata, 2841 struct alginfo *authdata) 2842 { 2843 struct program prg; 2844 struct program *p = &prg; 2845 int err; 2846 enum pdb_type_e pdb_type; 2847 static enum rta_share_type 2848 desc_share[PDCP_CIPHER_TYPE_INVALID][PDCP_AUTH_TYPE_INVALID] = { 2849 { /* NULL */ 2850 SHR_WAIT, /* NULL */ 2851 SHR_WAIT, /* SNOW f9 */ 2852 SHR_ALWAYS, /* AES CMAC */ 2853 SHR_WAIT /* ZUC-I */ 2854 }, 2855 { /* SNOW f8 */ 2856 SHR_WAIT, /* NULL */ 2857 SHR_WAIT, /* SNOW f9 */ 2858 SHR_WAIT, /* AES CMAC */ 2859 SHR_WAIT /* ZUC-I */ 2860 }, 2861 { /* AES CTR */ 2862 SHR_WAIT, /* NULL */ 2863 SHR_WAIT, /* SNOW f9 */ 2864 SHR_ALWAYS, /* AES CMAC */ 2865 SHR_WAIT /* ZUC-I */ 2866 }, 2867 { /* ZUC-E */ 2868 SHR_WAIT, /* NULL */ 2869 SHR_WAIT, /* SNOW f9 */ 2870 SHR_WAIT, /* AES CMAC */ 2871 SHR_WAIT /* ZUC-I */ 2872 }, 2873 }; 2874 2875 LABEL(pdb_end); 2876 2877 PROGRAM_CNTXT_INIT(p, descbuf, 0); 2878 if (swap) 2879 PROGRAM_SET_BSWAP(p); 2880 if (ps) 2881 PROGRAM_SET_36BIT_ADDR(p); 2882 if (authdata) 2883 SHR_HDR(p, desc_share[cipherdata->algtype][authdata->algtype], 0, 0); 2884 else 2885 SHR_HDR(p, SHR_WAIT, 0, 0); 2886 2887 pdb_type = cnstr_pdcp_u_plane_pdb(p, sn_size, hfn, bearer, 2888 direction, hfn_threshold, 2889 cipherdata, authdata); 2890 if (pdb_type == PDCP_PDB_TYPE_INVALID) { 2891 pr_err("Error creating PDCP UPlane PDB\n"); 2892 return -EINVAL; 2893 } 2894 SET_LABEL(p, pdb_end); 2895 2896 err = insert_hfn_ov_op(p, sn_size, pdb_type, true); 2897 if (err) 2898 return err; 2899 2900 switch (sn_size) { 2901 case PDCP_SN_SIZE_7: 2902 case PDCP_SN_SIZE_12: 2903 switch (cipherdata->algtype) { 2904 case PDCP_CIPHER_TYPE_ZUC: 2905 /* fallthrough */ 2906 case PDCP_CIPHER_TYPE_AES: 2907 case PDCP_CIPHER_TYPE_SNOW: 2908 case PDCP_CIPHER_TYPE_NULL: 2909 if (pdb_type != PDCP_PDB_TYPE_FULL_PDB) { 2910 pr_err("PDB type must be FULL for PROTO desc\n"); 2911 return -EINVAL; 2912 } 2913 2914 /* Insert auth key if requested */ 2915 if (authdata && authdata->algtype) 2916 KEY(p, KEY2, authdata->key_enc_flags, 2917 (uint64_t)authdata->key, authdata->keylen, 2918 INLINE_KEY(authdata)); 2919 else if (authdata && authdata->algtype == 0) { 2920 err = pdcp_insert_uplane_with_int_op(p, swap, 2921 cipherdata, authdata, 2922 sn_size, 2923 OP_TYPE_DECAP_PROTOCOL); 2924 if (err) 2925 return err; 2926 break; 2927 } 2928 2929 /* Insert Cipher Key */ 2930 KEY(p, KEY1, cipherdata->key_enc_flags, 2931 cipherdata->key, cipherdata->keylen, 2932 INLINE_KEY(cipherdata)); 2933 if (authdata) 2934 PROTOCOL(p, OP_TYPE_DECAP_PROTOCOL, 2935 OP_PCLID_LTE_PDCP_USER_RN, 2936 ((uint16_t)cipherdata->algtype << 8) | 2937 (uint16_t)authdata->algtype); 2938 else 2939 PROTOCOL(p, OP_TYPE_DECAP_PROTOCOL, 2940 OP_PCLID_LTE_PDCP_USER, 2941 (uint16_t)cipherdata->algtype); 2942 break; 2943 default: 2944 pr_err("%s: Invalid encrypt algorithm selected: %d\n", 2945 "cnstr_pcl_shdsc_pdcp_u_plane_decap", 2946 cipherdata->algtype); 2947 return -EINVAL; 2948 } 2949 break; 2950 2951 case PDCP_SN_SIZE_15: 2952 case PDCP_SN_SIZE_18: 2953 if (authdata) { 2954 err = pdcp_insert_uplane_with_int_op(p, swap, 2955 cipherdata, authdata, 2956 sn_size, 2957 OP_TYPE_DECAP_PROTOCOL); 2958 if (err) 2959 return err; 2960 2961 break; 2962 } 2963 2964 switch (cipherdata->algtype) { 2965 case PDCP_CIPHER_TYPE_NULL: 2966 insert_copy_frame_op(p, 2967 cipherdata, 2968 OP_TYPE_DECAP_PROTOCOL); 2969 break; 2970 2971 default: 2972 err = pdcp_insert_uplane_no_int_op(p, swap, cipherdata, 2973 OP_TYPE_DECAP_PROTOCOL, sn_size); 2974 if (err) 2975 return err; 2976 break; 2977 } 2978 break; 2979 2980 case PDCP_SN_SIZE_5: 2981 default: 2982 pr_err("Invalid SN size selected\n"); 2983 return -ENOTSUP; 2984 } 2985 2986 PATCH_HDR(p, 0, pdb_end); 2987 return PROGRAM_FINALIZE(p); 2988 } 2989 2990 /** 2991 * cnstr_shdsc_pdcp_short_mac - Function for creating a PDCP Short MAC 2992 * descriptor. 2993 * @descbuf: pointer to buffer for descriptor construction 2994 * @ps: if 36/40bit addressing is desired, this parameter must be true 2995 * @swap: must be true when core endianness doesn't match SEC endianness 2996 * @authdata: pointer to authentication transform definitions 2997 * Valid algorithm values are those from auth_type_pdcp enum. 2998 * 2999 * Return: size of descriptor written in words or negative number on error. 3000 * Once the function returns, the value of this parameter can be used 3001 * for reclaiming the space that wasn't used for the descriptor. 3002 * 3003 * Note: descbuf must be large enough to contain a full 256 byte long 3004 * descriptor; after the function returns, by subtracting the actual number of 3005 * bytes used, the user can reuse the remaining buffer space for other purposes. 3006 */ 3007 static inline int 3008 cnstr_shdsc_pdcp_short_mac(uint32_t *descbuf, 3009 bool ps, 3010 bool swap, 3011 struct alginfo *authdata) 3012 { 3013 struct program prg; 3014 struct program *p = &prg; 3015 uint32_t iv[3] = {0, 0, 0}; 3016 3017 PROGRAM_CNTXT_INIT(p, descbuf, 0); 3018 if (swap) 3019 PROGRAM_SET_BSWAP(p); 3020 if (ps) 3021 PROGRAM_SET_36BIT_ADDR(p); 3022 3023 SHR_HDR(p, SHR_ALWAYS, 1, 0); 3024 3025 MATHB(p, SEQINSZ, SUB, ZERO, VSEQINSZ, 4, 0); 3026 MATHB(p, SEQINSZ, SUB, ZERO, MATH1, 4, 0); 3027 3028 MATHB(p, ZERO, ADD, MATH1, VSEQOUTSZ, 4, 0); 3029 3030 switch (authdata->algtype) { 3031 case PDCP_AUTH_TYPE_NULL: 3032 SEQFIFOSTORE(p, MSG, 0, 0, VLF); 3033 MOVE(p, AB1, 0, OFIFO, 0, MATH1, 0); 3034 3035 LOAD(p, (uintptr_t)iv, MATH0, 0, 8, IMMED | COPY); 3036 SEQFIFOLOAD(p, MSG1, 0, VLF | LAST1 | LAST2 | FLUSH1); 3037 SEQSTORE(p, MATH0, 0, 4, 0); 3038 3039 break; 3040 3041 case PDCP_AUTH_TYPE_SNOW: 3042 /* IV calculation based on 3GPP specs. 36331, section:5.3.7.4 */ 3043 iv[0] = 0xFFFFFFFF; 3044 iv[1] = swab32(0x04000000); 3045 iv[2] = swab32(0xF8000000); 3046 3047 KEY(p, KEY2, authdata->key_enc_flags, authdata->key, 3048 authdata->keylen, INLINE_KEY(authdata)); 3049 LOAD(p, (uintptr_t)&iv, CONTEXT2, 0, 12, IMMED | COPY); 3050 ALG_OPERATION(p, OP_ALG_ALGSEL_SNOW_F9, 3051 OP_ALG_AAI_F9, 3052 OP_ALG_AS_INITFINAL, 3053 ICV_CHECK_DISABLE, 3054 DIR_ENC); 3055 SEQFIFOSTORE(p, MSG, 0, 0, VLF); 3056 3057 MOVE(p, AB1, 0, OFIFO, 0, MATH1, 0); 3058 3059 SEQFIFOLOAD(p, MSGINSNOOP, 0, VLF | LAST1 | LAST2 | FLUSH1); 3060 SEQSTORE(p, CONTEXT2, 0, 4, 0); 3061 3062 break; 3063 3064 case PDCP_AUTH_TYPE_AES: 3065 iv[0] = 0xFFFFFFFF; 3066 iv[1] = swap ? swab32(0xFC000000) : 0xFC000000; 3067 iv[2] = 0x00000000; /* unused */ 3068 3069 KEY(p, KEY1, authdata->key_enc_flags, authdata->key, 3070 authdata->keylen, INLINE_KEY(authdata)); 3071 LOAD(p, (uintptr_t)&iv, MATH0, 0, 8, IMMED | COPY); 3072 MOVE(p, MATH0, 0, IFIFOAB1, 0, 8, IMMED); 3073 ALG_OPERATION(p, OP_ALG_ALGSEL_AES, 3074 OP_ALG_AAI_CMAC, 3075 OP_ALG_AS_INITFINAL, 3076 ICV_CHECK_DISABLE, 3077 DIR_ENC); 3078 SEQFIFOSTORE(p, MSG, 0, 0, VLF); 3079 3080 MOVE(p, AB2, 0, OFIFO, 0, MATH1, 0); 3081 3082 SEQFIFOLOAD(p, MSGINSNOOP, 0, VLF | LAST1 | LAST2 | FLUSH1); 3083 SEQSTORE(p, CONTEXT1, 0, 4, 0); 3084 3085 break; 3086 3087 case PDCP_AUTH_TYPE_ZUC: 3088 iv[0] = 0xFFFFFFFF; 3089 iv[1] = swab32(0xFC000000); 3090 iv[2] = 0x00000000; /* unused */ 3091 3092 KEY(p, KEY2, authdata->key_enc_flags, authdata->key, 3093 authdata->keylen, INLINE_KEY(authdata)); 3094 LOAD(p, (uintptr_t)&iv, CONTEXT2, 0, 12, IMMED | COPY); 3095 ALG_OPERATION(p, OP_ALG_ALGSEL_ZUCA, 3096 OP_ALG_AAI_F9, 3097 OP_ALG_AS_INITFINAL, 3098 ICV_CHECK_DISABLE, 3099 DIR_ENC); 3100 SEQFIFOSTORE(p, MSG, 0, 0, VLF); 3101 MOVE(p, AB1, 0, OFIFO, 0, MATH1, 0); 3102 SEQFIFOLOAD(p, MSGINSNOOP, 0, VLF | LAST1 | LAST2 | FLUSH1); 3103 SEQSTORE(p, CONTEXT2, 0, 4, 0); 3104 3105 break; 3106 3107 default: 3108 pr_err("%s: Invalid integrity algorithm selected: %d\n", 3109 "cnstr_shdsc_pdcp_short_mac", authdata->algtype); 3110 return -EINVAL; 3111 } 3112 3113 return PROGRAM_FINALIZE(p); 3114 } 3115 3116 #endif /* __DESC_PDCP_H__ */ 3117