1 /* SPDX-License-Identifier: (BSD-3-Clause OR GPL-2.0) 2 * 3 * Copyright 2008-2016 Freescale Semiconductor Inc. 4 * Copyright 2016,2019-2021 NXP 5 * 6 */ 7 8 #ifndef __DESC_ALGO_H__ 9 #define __DESC_ALGO_H__ 10 11 #include "rta.h" 12 #include "common.h" 13 14 /** 15 * DOC: Algorithms - Shared Descriptor Constructors 16 * 17 * Shared descriptors for algorithms (i.e. not for protocols). 18 */ 19 20 /** 21 * cnstr_shdsc_zuce - ZUC Enc (EEA2) as a shared descriptor 22 * @descbuf: pointer to descriptor-under-construction buffer 23 * @ps: if 36/40bit addressing is desired, this parameter must be true 24 * @swap: must be true when core endianness doesn't match SEC endianness 25 * @cipherdata: pointer to block cipher transform definitions 26 * @dir: Cipher direction (DIR_ENC/DIR_DEC) 27 * 28 * Return: size of descriptor written in words or negative number on error 29 */ 30 static inline int 31 cnstr_shdsc_zuce(uint32_t *descbuf, bool ps, bool swap, 32 struct alginfo *cipherdata, uint8_t dir) 33 { 34 struct program prg; 35 struct program *p = &prg; 36 37 PROGRAM_CNTXT_INIT(p, descbuf, 0); 38 if (swap) 39 PROGRAM_SET_BSWAP(p); 40 41 if (ps) 42 PROGRAM_SET_36BIT_ADDR(p); 43 SHR_HDR(p, SHR_ALWAYS, 1, 0); 44 45 KEY(p, KEY1, cipherdata->key_enc_flags, cipherdata->key, 46 cipherdata->keylen, INLINE_KEY(cipherdata)); 47 48 SEQLOAD(p, CONTEXT1, 0, 16, 0); 49 50 MATHB(p, SEQINSZ, SUB, MATH2, VSEQINSZ, 4, 0); 51 MATHB(p, SEQINSZ, SUB, MATH2, VSEQOUTSZ, 4, 0); 52 ALG_OPERATION(p, OP_ALG_ALGSEL_ZUCE, OP_ALG_AAI_F8, 53 OP_ALG_AS_INITFINAL, 0, dir); 54 SEQFIFOLOAD(p, MSG1, 0, VLF | LAST1); 55 SEQFIFOSTORE(p, MSG, 0, 0, VLF); 56 57 return PROGRAM_FINALIZE(p); 58 } 59 60 /** 61 * cnstr_shdsc_zuca - ZUC Auth (EIA2) as a shared descriptor 62 * @descbuf: pointer to descriptor-under-construction buffer 63 * @ps: if 36/40bit addressing is desired, this parameter must be true 64 * @swap: must be true when core endianness doesn't match SEC endianness 65 * @authdata: pointer to authentication transform definitions 66 * @chk_icv: Whether to compare and verify ICV (true/false) 67 * @authlen: size of digest 68 * 69 * The IV prepended before hmac payload must be 8 bytes consisting 70 * of COUNT||BEAERER||DIR. The COUNT is of 32-bits, bearer is of 5 bits and 71 * direction is of 1 bit - totalling to 38 bits. 72 * 73 * Return: size of descriptor written in words or negative number on error 74 */ 75 static inline int 76 cnstr_shdsc_zuca(uint32_t *descbuf, bool ps, bool swap, 77 struct alginfo *authdata, uint8_t chk_icv, 78 uint32_t authlen) 79 { 80 struct program prg; 81 struct program *p = &prg; 82 int dir = chk_icv ? DIR_DEC : DIR_ENC; 83 84 PROGRAM_CNTXT_INIT(p, descbuf, 0); 85 if (swap) 86 PROGRAM_SET_BSWAP(p); 87 88 if (ps) 89 PROGRAM_SET_36BIT_ADDR(p); 90 SHR_HDR(p, SHR_ALWAYS, 1, 0); 91 92 KEY(p, KEY2, authdata->key_enc_flags, authdata->key, 93 authdata->keylen, INLINE_KEY(authdata)); 94 95 SEQLOAD(p, CONTEXT2, 0, 8, 0); 96 97 if (chk_icv == ICV_CHECK_ENABLE) 98 MATHB(p, SEQINSZ, SUB, authlen, VSEQINSZ, 4, IMMED2); 99 else 100 MATHB(p, SEQINSZ, SUB, ZERO, VSEQINSZ, 4, 0); 101 102 ALG_OPERATION(p, OP_ALG_ALGSEL_ZUCA, OP_ALG_AAI_F9, 103 OP_ALG_AS_INITFINAL, chk_icv, dir); 104 105 SEQFIFOLOAD(p, MSG2, 0, VLF | CLASS2 | LAST2); 106 107 if (chk_icv == ICV_CHECK_ENABLE) 108 SEQFIFOLOAD(p, ICV2, authlen, LAST2); 109 else 110 /* Save lower half of MAC out into a 32-bit sequence */ 111 SEQSTORE(p, CONTEXT2, 0, authlen, 0); 112 113 return PROGRAM_FINALIZE(p); 114 } 115 116 117 /** 118 * cnstr_shdsc_snow_f8 - SNOW/f8 (UEA2) as a shared descriptor 119 * @descbuf: pointer to descriptor-under-construction buffer 120 * @ps: if 36/40bit addressing is desired, this parameter must be true 121 * @swap: must be true when core endianness doesn't match SEC endianness 122 * @cipherdata: pointer to block cipher transform definitions 123 * @dir: Cipher direction (DIR_ENC/DIR_DEC) 124 * 125 * Return: size of descriptor written in words or negative number on error 126 */ 127 static inline int 128 cnstr_shdsc_snow_f8(uint32_t *descbuf, bool ps, bool swap, 129 struct alginfo *cipherdata, uint8_t dir) 130 { 131 struct program prg; 132 struct program *p = &prg; 133 134 PROGRAM_CNTXT_INIT(p, descbuf, 0); 135 if (swap) 136 PROGRAM_SET_BSWAP(p); 137 138 if (ps) 139 PROGRAM_SET_36BIT_ADDR(p); 140 SHR_HDR(p, SHR_ALWAYS, 1, 0); 141 142 KEY(p, KEY1, cipherdata->key_enc_flags, cipherdata->key, 143 cipherdata->keylen, INLINE_KEY(cipherdata)); 144 145 SEQLOAD(p, CONTEXT1, 0, 16, 0); 146 147 MATHB(p, SEQINSZ, SUB, MATH2, VSEQINSZ, 4, 0); 148 MATHB(p, SEQINSZ, SUB, MATH2, VSEQOUTSZ, 4, 0); 149 ALG_OPERATION(p, OP_ALG_ALGSEL_SNOW_F8, OP_ALG_AAI_F8, 150 OP_ALG_AS_INITFINAL, 0, dir); 151 SEQFIFOLOAD(p, MSG1, 0, VLF | LAST1); 152 SEQFIFOSTORE(p, MSG, 0, 0, VLF); 153 154 return PROGRAM_FINALIZE(p); 155 } 156 157 /** 158 * conv_to_zuc_eia_iv - ZUCA IV 16-byte to 8-byte convert 159 * function for 3G. 160 * @iv: 16 bytes of original IV data. 161 * 162 * From the original IV, we extract 32-bits of COUNT, 163 * 5-bits of bearer and 1-bit of direction. 164 * Refer to CAAM refman for ZUCA IV format. Then these values are 165 * appended as COUNT||BEARER||DIR continuously to make a 38-bit block. 166 * This 38-bit block is copied left justified into 8-byte array used as 167 * converted IV. 168 * 169 * Return: 8-bytes of IV data as understood by SEC HW 170 */ 171 172 static inline uint8_t *conv_to_zuc_eia_iv(uint8_t *iv) 173 { 174 uint8_t dir = (iv[14] & 0x80) ? 4 : 0; 175 176 iv[12] = iv[4] | dir; 177 iv[13] = 0; 178 iv[14] = 0; 179 iv[15] = 0; 180 181 iv[8] = iv[0]; 182 iv[9] = iv[1]; 183 iv[10] = iv[2]; 184 iv[11] = iv[3]; 185 186 return (iv + 8); 187 } 188 189 /** 190 * conv_to_snow_f9_iv - SNOW/f9 (UIA2) IV 16 byte to 12 byte convert 191 * function for 3G. 192 * @iv: 16 byte original IV data 193 * 194 * Return: 12 byte IV data as understood by SEC HW 195 */ 196 197 static inline uint8_t *conv_to_snow_f9_iv(uint8_t *iv) 198 { 199 uint8_t temp = (iv[8] == iv[0]) ? 0 : 4; 200 201 iv[12] = iv[4]; 202 iv[13] = iv[5]; 203 iv[14] = iv[6]; 204 iv[15] = iv[7]; 205 206 iv[8] = temp; 207 iv[9] = 0x00; 208 iv[10] = 0x00; 209 iv[11] = 0x00; 210 211 iv[4] = iv[0]; 212 iv[5] = iv[1]; 213 iv[6] = iv[2]; 214 iv[7] = iv[3]; 215 216 return (iv + 4); 217 } 218 219 /** 220 * cnstr_shdsc_snow_f9 - SNOW/f9 (UIA2) as a shared descriptor 221 * @descbuf: pointer to descriptor-under-construction buffer 222 * @ps: if 36/40bit addressing is desired, this parameter must be true 223 * @swap: must be true when core endianness doesn't match SEC endianness 224 * @authdata: pointer to authentication transform definitions 225 * @chk_icv: check or generate ICV value 226 * @authlen: size of digest 227 * 228 * Return: size of descriptor written in words or negative number on error 229 */ 230 static inline int 231 cnstr_shdsc_snow_f9(uint32_t *descbuf, bool ps, bool swap, 232 struct alginfo *authdata, uint8_t chk_icv, 233 uint32_t authlen) 234 { 235 struct program prg; 236 struct program *p = &prg; 237 int dir = chk_icv ? DIR_DEC : DIR_ENC; 238 239 PROGRAM_CNTXT_INIT(p, descbuf, 0); 240 if (swap) 241 PROGRAM_SET_BSWAP(p); 242 243 if (ps) 244 PROGRAM_SET_36BIT_ADDR(p); 245 246 SHR_HDR(p, SHR_ALWAYS, 1, 0); 247 248 KEY(p, KEY2, authdata->key_enc_flags, authdata->key, 249 authdata->keylen, INLINE_KEY(authdata)); 250 251 SEQLOAD(p, CONTEXT2, 0, 12, 0); 252 253 if (chk_icv == ICV_CHECK_ENABLE) 254 MATHB(p, SEQINSZ, SUB, authlen, VSEQINSZ, 4, IMMED2); 255 else 256 MATHB(p, SEQINSZ, SUB, ZERO, VSEQINSZ, 4, 0); 257 258 ALG_OPERATION(p, OP_ALG_ALGSEL_SNOW_F9, OP_ALG_AAI_F9, 259 OP_ALG_AS_INITFINAL, chk_icv, dir); 260 261 SEQFIFOLOAD(p, MSG2, 0, VLF | CLASS2 | LAST2); 262 263 if (chk_icv == ICV_CHECK_ENABLE) 264 SEQFIFOLOAD(p, ICV2, authlen, LAST2); 265 else 266 /* Save lower half of MAC out into a 32-bit sequence */ 267 SEQSTORE(p, CONTEXT2, 0, authlen, 0); 268 269 return PROGRAM_FINALIZE(p); 270 } 271 272 /** 273 * cnstr_shdsc_blkcipher - block cipher transformation 274 * @descbuf: pointer to descriptor-under-construction buffer 275 * @ps: if 36/40bit addressing is desired, this parameter must be true 276 * @swap: must be true when core endianness doesn't match SEC endianness 277 * @share: sharing type of shared descriptor 278 * @cipherdata: pointer to block cipher transform definitions 279 * Valid algorithm values one of OP_ALG_ALGSEL_* {DES, 3DES, AES} 280 * Valid modes for: 281 * AES: OP_ALG_AAI_* {CBC, CTR} 282 * DES, 3DES: OP_ALG_AAI_CBC 283 * @iv: IV data; if NULL, "ivlen" bytes from the input frame will be read as IV 284 * @ivlen: IV length 285 * @dir: DIR_ENC/DIR_DEC 286 * 287 * Return: size of descriptor written in words or negative number on error 288 */ 289 static inline int 290 cnstr_shdsc_blkcipher(uint32_t *descbuf, bool ps, bool swap, 291 enum rta_share_type share, 292 struct alginfo *cipherdata, 293 uint32_t ivlen, uint8_t dir) 294 { 295 struct program prg; 296 struct program *p = &prg; 297 uint32_t iv_off = 0, counter; 298 const bool need_dk = (dir == DIR_DEC) && 299 (cipherdata->algtype == OP_ALG_ALGSEL_AES) && 300 (cipherdata->algmode == OP_ALG_AAI_CBC); 301 LABEL(keyjmp); 302 LABEL(skipdk); 303 REFERENCE(pkeyjmp); 304 REFERENCE(pskipdk); 305 306 PROGRAM_CNTXT_INIT(p, descbuf, 0); 307 if (swap) 308 PROGRAM_SET_BSWAP(p); 309 if (ps) 310 PROGRAM_SET_36BIT_ADDR(p); 311 SHR_HDR(p, share, 1, SC); 312 313 pkeyjmp = JUMP(p, keyjmp, LOCAL_JUMP, ALL_TRUE, SHRD); 314 /* Insert Key */ 315 KEY(p, KEY1, cipherdata->key_enc_flags, cipherdata->key, 316 cipherdata->keylen, INLINE_KEY(cipherdata)); 317 318 if (need_dk) { 319 ALG_OPERATION(p, cipherdata->algtype, cipherdata->algmode, 320 OP_ALG_AS_INITFINAL, ICV_CHECK_DISABLE, dir); 321 322 pskipdk = JUMP(p, skipdk, LOCAL_JUMP, ALL_TRUE, 0); 323 } 324 SET_LABEL(p, keyjmp); 325 326 if (need_dk) { 327 ALG_OPERATION(p, OP_ALG_ALGSEL_AES, cipherdata->algmode | 328 OP_ALG_AAI_DK, OP_ALG_AS_INITFINAL, 329 ICV_CHECK_DISABLE, dir); 330 SET_LABEL(p, skipdk); 331 } else { 332 ALG_OPERATION(p, cipherdata->algtype, cipherdata->algmode, 333 OP_ALG_AS_INITFINAL, ICV_CHECK_DISABLE, dir); 334 } 335 336 if (cipherdata->algmode == OP_ALG_AAI_CTR) 337 iv_off = 16; 338 339 /* IV is present first before the actual message */ 340 SEQLOAD(p, CONTEXT1, iv_off, ivlen, 0); 341 342 /* If IV len is less than 16 bytes, set 'counter' as 1 */ 343 if (cipherdata->algmode == OP_ALG_AAI_CTR && ivlen < 16) { 344 counter = 1; 345 if (!swap) 346 counter = swab32(1); 347 348 LOAD(p, counter, CONTEXT1, (iv_off + ivlen), 16 - ivlen, IMMED); 349 } 350 351 MATHB(p, SEQINSZ, SUB, MATH2, VSEQINSZ, 4, 0); 352 MATHB(p, SEQINSZ, SUB, MATH2, VSEQOUTSZ, 4, 0); 353 354 /* Insert sequence load/store with VLF */ 355 SEQFIFOLOAD(p, MSG1, 0, VLF | LAST1); 356 SEQFIFOSTORE(p, MSG, 0, 0, VLF); 357 358 PATCH_JUMP(p, pkeyjmp, keyjmp); 359 if (need_dk) 360 PATCH_JUMP(p, pskipdk, skipdk); 361 362 return PROGRAM_FINALIZE(p); 363 } 364 365 /** 366 * cnstr_shdsc_hmac - HMAC shared 367 * @descbuf: pointer to descriptor-under-construction buffer 368 * @ps: if 36/40bit addressing is desired, this parameter must be true 369 * @swap: must be true when core endianness doesn't match SEC endianness 370 * @share: sharing type of shared descriptor 371 * @authdata: pointer to authentication transform definitions; 372 * message digest algorithm: OP_ALG_ALGSEL_MD5/ SHA1-512. 373 * @do_icv: 0 if ICV checking is not desired, any other value if ICV checking 374 * is needed for all the packets processed by this shared descriptor 375 * @trunc_len: Length of the truncated ICV to be written in the output buffer, 0 376 * if no truncation is needed 377 * 378 * Note: There's no support for keys longer than the block size of the 379 * underlying hash function, according to the selected algorithm. 380 * 381 * Return: size of descriptor written in words or negative number on error 382 */ 383 static inline int 384 cnstr_shdsc_hmac(uint32_t *descbuf, bool ps, bool swap, 385 enum rta_share_type share, 386 struct alginfo *authdata, uint8_t do_icv, 387 uint8_t trunc_len) 388 { 389 struct program prg; 390 struct program *p = &prg; 391 uint8_t storelen, opicv, dir; 392 LABEL(keyjmp); 393 LABEL(jmpprecomp); 394 REFERENCE(pkeyjmp); 395 REFERENCE(pjmpprecomp); 396 397 /* Compute fixed-size store based on alg selection */ 398 switch (authdata->algtype) { 399 case OP_ALG_ALGSEL_MD5: 400 storelen = 16; 401 break; 402 case OP_ALG_ALGSEL_SHA1: 403 storelen = 20; 404 break; 405 case OP_ALG_ALGSEL_SHA224: 406 storelen = 28; 407 break; 408 case OP_ALG_ALGSEL_SHA256: 409 storelen = 32; 410 break; 411 case OP_ALG_ALGSEL_SHA384: 412 storelen = 48; 413 break; 414 case OP_ALG_ALGSEL_SHA512: 415 storelen = 64; 416 break; 417 default: 418 return -EINVAL; 419 } 420 421 trunc_len = trunc_len && (trunc_len < storelen) ? trunc_len : storelen; 422 423 opicv = do_icv ? ICV_CHECK_ENABLE : ICV_CHECK_DISABLE; 424 dir = do_icv ? DIR_DEC : DIR_ENC; 425 426 PROGRAM_CNTXT_INIT(p, descbuf, 0); 427 if (swap) 428 PROGRAM_SET_BSWAP(p); 429 if (ps) 430 PROGRAM_SET_36BIT_ADDR(p); 431 SHR_HDR(p, share, 1, SC); 432 433 pkeyjmp = JUMP(p, keyjmp, LOCAL_JUMP, ALL_TRUE, SHRD); 434 KEY(p, KEY2, authdata->key_enc_flags, authdata->key, authdata->keylen, 435 INLINE_KEY(authdata)); 436 437 /* Do operation */ 438 ALG_OPERATION(p, authdata->algtype, OP_ALG_AAI_HMAC, 439 OP_ALG_AS_INITFINAL, opicv, dir); 440 441 pjmpprecomp = JUMP(p, jmpprecomp, LOCAL_JUMP, ALL_TRUE, 0); 442 SET_LABEL(p, keyjmp); 443 444 ALG_OPERATION(p, authdata->algtype, OP_ALG_AAI_HMAC_PRECOMP, 445 OP_ALG_AS_INITFINAL, opicv, dir); 446 447 SET_LABEL(p, jmpprecomp); 448 449 /* compute sequences */ 450 if (opicv == ICV_CHECK_ENABLE) 451 MATHB(p, SEQINSZ, SUB, trunc_len, VSEQINSZ, 4, IMMED2); 452 else 453 MATHB(p, SEQINSZ, SUB, MATH2, VSEQINSZ, 4, 0); 454 455 /* Do load (variable length) */ 456 SEQFIFOLOAD(p, MSG2, 0, VLF | LAST2); 457 458 if (opicv == ICV_CHECK_ENABLE) 459 SEQFIFOLOAD(p, ICV2, trunc_len, LAST2); 460 else 461 SEQSTORE(p, CONTEXT2, 0, trunc_len, 0); 462 463 PATCH_JUMP(p, pkeyjmp, keyjmp); 464 PATCH_JUMP(p, pjmpprecomp, jmpprecomp); 465 466 return PROGRAM_FINALIZE(p); 467 } 468 469 /** 470 * cnstr_shdsc_hash - HASH shared 471 * @descbuf: pointer to descriptor-under-construction buffer 472 * @ps: if 36/40bit addressing is desired, this parameter must be true 473 * @swap: must be true when core endianness doesn't match SEC endianness 474 * @share: sharing type of shared descriptor 475 * @authdata: pointer to authentication transform definitions; 476 * message digest algorithm: OP_ALG_ALGSEL_MD5/ SHA1-512. 477 * @do_icv: 0 if ICV checking is not desired, any other value if ICV checking 478 * is needed for all the packets processed by this shared descriptor 479 * @trunc_len: Length of the truncated ICV to be written in the output buffer, 0 480 * if no truncation is needed 481 * 482 * Note: There's no support for keys longer than the block size of the 483 * underlying hash function, according to the selected algorithm. 484 * 485 * Return: size of descriptor written in words or negative number on error 486 */ 487 static inline int 488 cnstr_shdsc_hash(uint32_t *descbuf, bool ps, bool swap, 489 enum rta_share_type share, 490 struct alginfo *authdata, uint8_t do_icv, 491 uint8_t trunc_len) 492 { 493 struct program prg; 494 struct program *p = &prg; 495 uint8_t storelen, opicv, dir; 496 497 /* Compute fixed-size store based on alg selection */ 498 switch (authdata->algtype) { 499 case OP_ALG_ALGSEL_MD5: 500 storelen = 16; 501 break; 502 case OP_ALG_ALGSEL_SHA1: 503 storelen = 20; 504 break; 505 case OP_ALG_ALGSEL_SHA224: 506 storelen = 28; 507 break; 508 case OP_ALG_ALGSEL_SHA256: 509 storelen = 32; 510 break; 511 case OP_ALG_ALGSEL_SHA384: 512 storelen = 48; 513 break; 514 case OP_ALG_ALGSEL_SHA512: 515 storelen = 64; 516 break; 517 default: 518 return -EINVAL; 519 } 520 521 trunc_len = trunc_len && (trunc_len < storelen) ? trunc_len : storelen; 522 523 opicv = do_icv ? ICV_CHECK_ENABLE : ICV_CHECK_DISABLE; 524 dir = do_icv ? DIR_DEC : DIR_ENC; 525 526 PROGRAM_CNTXT_INIT(p, descbuf, 0); 527 if (swap) 528 PROGRAM_SET_BSWAP(p); 529 if (ps) 530 PROGRAM_SET_36BIT_ADDR(p); 531 SHR_HDR(p, share, 1, SC); 532 533 /* Do operation */ 534 /* compute sequences */ 535 if (opicv == ICV_CHECK_ENABLE) 536 MATHB(p, SEQINSZ, SUB, trunc_len, VSEQINSZ, 4, IMMED2); 537 else 538 MATHB(p, SEQINSZ, SUB, MATH2, VSEQINSZ, 4, 0); 539 540 ALG_OPERATION(p, authdata->algtype, 541 OP_ALG_AAI_HASH, 542 OP_ALG_AS_INITFINAL, opicv, dir); 543 SEQFIFOLOAD(p, MSG2, 0, VLF | LAST2); 544 545 if (opicv == ICV_CHECK_ENABLE) 546 SEQFIFOLOAD(p, ICV2, trunc_len, LAST2); 547 else 548 SEQSTORE(p, CONTEXT2, 0, trunc_len, 0); 549 550 return PROGRAM_FINALIZE(p); 551 } 552 553 /** 554 * cnstr_shdsc_kasumi_f8 - KASUMI F8 (Confidentiality) as a shared descriptor 555 * (ETSI "Document 1: f8 and f9 specification") 556 * @descbuf: pointer to descriptor-under-construction buffer 557 * @ps: if 36/40bit addressing is desired, this parameter must be true 558 * @swap: must be true when core endianness doesn't match SEC endianness 559 * @cipherdata: pointer to block cipher transform definitions 560 * @dir: cipher direction (DIR_ENC/DIR_DEC) 561 * @count: count value (32 bits) 562 * @bearer: bearer ID (5 bits) 563 * @direction: direction (1 bit) 564 * 565 * Return: size of descriptor written in words or negative number on error 566 */ 567 static inline int 568 cnstr_shdsc_kasumi_f8(uint32_t *descbuf, bool ps, bool swap, 569 struct alginfo *cipherdata, uint8_t dir) 570 { 571 struct program prg; 572 struct program *p = &prg; 573 574 PROGRAM_CNTXT_INIT(p, descbuf, 0); 575 if (swap) 576 PROGRAM_SET_BSWAP(p); 577 if (ps) 578 PROGRAM_SET_36BIT_ADDR(p); 579 SHR_HDR(p, SHR_ALWAYS, 1, 0); 580 581 KEY(p, KEY1, cipherdata->key_enc_flags, cipherdata->key, 582 cipherdata->keylen, INLINE_KEY(cipherdata)); 583 SEQLOAD(p, CONTEXT1, 0, 8, 0); 584 MATHB(p, SEQINSZ, SUB, MATH2, VSEQINSZ, 4, 0); 585 MATHB(p, SEQINSZ, SUB, MATH2, VSEQOUTSZ, 4, 0); 586 ALG_OPERATION(p, OP_ALG_ALGSEL_KASUMI, OP_ALG_AAI_F8, 587 OP_ALG_AS_INITFINAL, 0, dir); 588 SEQFIFOLOAD(p, MSG1, 0, VLF | LAST1); 589 SEQFIFOSTORE(p, MSG, 0, 0, VLF); 590 591 return PROGRAM_FINALIZE(p); 592 } 593 594 /** 595 * cnstr_shdsc_kasumi_f9 - KASUMI F9 (Integrity) as a shared descriptor 596 * (ETSI "Document 1: f8 and f9 specification") 597 * @descbuf: pointer to descriptor-under-construction buffer 598 * @ps: if 36/40bit addressing is desired, this parameter must be true 599 * @swap: must be true when core endianness doesn't match SEC endianness 600 * @authdata: pointer to authentication transform definitions 601 * @chk_icv: check or generate ICV value 602 * @authlen: size of digest 603 * 604 * Return: size of descriptor written in words or negative number on error 605 */ 606 static inline int 607 cnstr_shdsc_kasumi_f9(uint32_t *descbuf, bool ps, bool swap, 608 struct alginfo *authdata, uint8_t chk_icv, 609 uint32_t authlen) 610 { 611 struct program prg; 612 struct program *p = &prg; 613 int dir = chk_icv ? DIR_DEC : DIR_ENC; 614 615 PROGRAM_CNTXT_INIT(p, descbuf, 0); 616 if (swap) 617 PROGRAM_SET_BSWAP(p); 618 619 if (ps) 620 PROGRAM_SET_36BIT_ADDR(p); 621 622 SHR_HDR(p, SHR_ALWAYS, 1, 0); 623 624 KEY(p, KEY2, authdata->key_enc_flags, authdata->key, 625 authdata->keylen, INLINE_KEY(authdata)); 626 627 SEQLOAD(p, CONTEXT2, 0, 12, 0); 628 629 if (chk_icv == ICV_CHECK_ENABLE) 630 MATHB(p, SEQINSZ, SUB, authlen, VSEQINSZ, 4, IMMED2); 631 else 632 MATHB(p, SEQINSZ, SUB, ZERO, VSEQINSZ, 4, 0); 633 634 ALG_OPERATION(p, OP_ALG_ALGSEL_KASUMI, OP_ALG_AAI_F9, 635 OP_ALG_AS_INITFINAL, chk_icv, dir); 636 637 SEQFIFOLOAD(p, MSG2, 0, VLF | CLASS2 | LAST2); 638 639 if (chk_icv == ICV_CHECK_ENABLE) 640 SEQFIFOLOAD(p, ICV2, authlen, LAST2); 641 else 642 /* Save lower half of MAC out into a 32-bit sequence */ 643 SEQSTORE(p, CONTEXT2, 0, authlen, 0); 644 645 return PROGRAM_FINALIZE(p); 646 } 647 648 /** 649 * cnstr_shdsc_crc - CRC32 Accelerator (IEEE 802 CRC32 protocol mode) 650 * @descbuf: pointer to descriptor-under-construction buffer 651 * @swap: must be true when core endianness doesn't match SEC endianness 652 * 653 * Return: size of descriptor written in words or negative number on error 654 */ 655 static inline int 656 cnstr_shdsc_crc(uint32_t *descbuf, bool swap) 657 { 658 struct program prg; 659 struct program *p = &prg; 660 661 PROGRAM_CNTXT_INIT(p, descbuf, 0); 662 if (swap) 663 PROGRAM_SET_BSWAP(p); 664 665 SHR_HDR(p, SHR_ALWAYS, 1, 0); 666 667 MATHB(p, SEQINSZ, SUB, MATH2, VSEQINSZ, 4, 0); 668 ALG_OPERATION(p, OP_ALG_ALGSEL_CRC, 669 OP_ALG_AAI_802 | OP_ALG_AAI_DOC, 670 OP_ALG_AS_FINALIZE, 0, DIR_ENC); 671 SEQFIFOLOAD(p, MSG2, 0, VLF | LAST2); 672 SEQSTORE(p, CONTEXT2, 0, 4, 0); 673 674 return PROGRAM_FINALIZE(p); 675 } 676 677 /** 678 * cnstr_shdsc_gcm_encap - AES-GCM encap as a shared descriptor 679 * @descbuf: pointer to descriptor-under-construction buffer 680 * @ps: if 36/40bit addressing is desired, this parameter must be true 681 * @swap: must be true when core endianness doesn't match SEC endianness 682 * @share: sharing type of shared descriptor 683 * @cipherdata: pointer to block cipher transform definitions 684 * Valid algorithm values - OP_ALG_ALGSEL_AES ANDed with 685 * OP_ALG_AAI_GCM. 686 * @ivlen: Initialization vector length 687 * @icvsize: integrity check value (ICV) size (truncated or full) 688 * 689 * Return: size of descriptor written in words or negative number on error 690 */ 691 static inline int 692 cnstr_shdsc_gcm_encap(uint32_t *descbuf, bool ps, bool swap, 693 enum rta_share_type share, 694 struct alginfo *cipherdata, 695 uint32_t ivlen, uint32_t icvsize) 696 { 697 struct program prg; 698 struct program *p = &prg; 699 700 LABEL(keyjmp); 701 LABEL(zeroassocjump2); 702 LABEL(zeroassocjump1); 703 LABEL(zeropayloadjump); 704 REFERENCE(pkeyjmp); 705 REFERENCE(pzeroassocjump2); 706 REFERENCE(pzeroassocjump1); 707 REFERENCE(pzeropayloadjump); 708 709 PROGRAM_CNTXT_INIT(p, descbuf, 0); 710 711 if (swap) 712 PROGRAM_SET_BSWAP(p); 713 if (ps) 714 PROGRAM_SET_36BIT_ADDR(p); 715 716 SHR_HDR(p, share, 1, SC); 717 718 pkeyjmp = JUMP(p, keyjmp, LOCAL_JUMP, ALL_TRUE, SELF | SHRD); 719 /* Insert Key */ 720 KEY(p, KEY1, cipherdata->key_enc_flags, cipherdata->key, 721 cipherdata->keylen, INLINE_KEY(cipherdata)); 722 723 SET_LABEL(p, keyjmp); 724 725 /* class 1 operation */ 726 ALG_OPERATION(p, cipherdata->algtype, cipherdata->algmode, 727 OP_ALG_AS_INITFINAL, ICV_CHECK_DISABLE, DIR_ENC); 728 729 MATHB(p, DPOVRD, AND, 0x7fffffff, MATH3, 4, IMMED2); 730 731 /* if assoclen + cryptlen is ZERO, skip to ICV write */ 732 MATHB(p, SEQINSZ, SUB, ivlen, VSEQOUTSZ, 4, IMMED2); 733 pzeroassocjump2 = JUMP(p, zeroassocjump2, LOCAL_JUMP, ALL_TRUE, MATH_Z); 734 735 SEQFIFOLOAD(p, IV1, ivlen, FLUSH1); 736 737 /* if assoclen is ZERO, skip reading the assoc data */ 738 MATHB(p, ZERO, ADD, MATH3, VSEQINSZ, 4, 0); 739 pzeroassocjump1 = JUMP(p, zeroassocjump1, LOCAL_JUMP, ALL_TRUE, MATH_Z); 740 741 /* cryptlen = seqinlen - assoclen */ 742 MATHB(p, SEQINSZ, SUB, MATH3, VSEQOUTSZ, 4, 0); 743 744 /* if cryptlen is ZERO jump to zero-payload commands */ 745 pzeropayloadjump = JUMP(p, zeropayloadjump, LOCAL_JUMP, ALL_TRUE, 746 MATH_Z); 747 748 /* read assoc data */ 749 SEQFIFOLOAD(p, AAD1, 0, CLASS1 | VLF | FLUSH1); 750 SET_LABEL(p, zeroassocjump1); 751 752 MATHB(p, SEQINSZ, SUB, MATH0, VSEQINSZ, 4, 0); 753 754 /* write encrypted data */ 755 SEQFIFOSTORE(p, MSG, 0, 0, VLF); 756 757 /* read payload data */ 758 SEQFIFOLOAD(p, MSG1, 0, CLASS1 | VLF | LAST1); 759 760 /* jump the zero-payload commands */ 761 JUMP(p, 4, LOCAL_JUMP, ALL_TRUE, 0); 762 763 /* zero-payload commands */ 764 SET_LABEL(p, zeropayloadjump); 765 766 /* read assoc data */ 767 SEQFIFOLOAD(p, AAD1, 0, CLASS1 | VLF | LAST1); 768 769 JUMP(p, 2, LOCAL_JUMP, ALL_TRUE, 0); 770 771 /* There is no input data */ 772 SET_LABEL(p, zeroassocjump2); 773 774 SEQFIFOLOAD(p, IV1, ivlen, FLUSH1 | LAST1); 775 776 /* write ICV */ 777 SEQSTORE(p, CONTEXT1, 0, icvsize, 0); 778 779 PATCH_JUMP(p, pkeyjmp, keyjmp); 780 PATCH_JUMP(p, pzeroassocjump2, zeroassocjump2); 781 PATCH_JUMP(p, pzeroassocjump1, zeroassocjump1); 782 PATCH_JUMP(p, pzeropayloadjump, zeropayloadjump); 783 784 return PROGRAM_FINALIZE(p); 785 } 786 787 /** 788 * cnstr_shdsc_gcm_decap - AES-GCM decap as a shared descriptor 789 * @descbuf: pointer to descriptor-under-construction buffer 790 * @ps: if 36/40bit addressing is desired, this parameter must be true 791 * @swap: must be true when core endianness doesn't match SEC endianness 792 * @share: sharing type of shared descriptor 793 * @cipherdata: pointer to block cipher transform definitions 794 * Valid algorithm values - OP_ALG_ALGSEL_AES ANDed with 795 * OP_ALG_AAI_GCM. 796 * @icvsize: integrity check value (ICV) size (truncated or full) 797 * 798 * Return: size of descriptor written in words or negative number on error 799 */ 800 static inline int 801 cnstr_shdsc_gcm_decap(uint32_t *descbuf, bool ps, bool swap, 802 enum rta_share_type share, 803 struct alginfo *cipherdata, 804 uint32_t ivlen, uint32_t icvsize) 805 { 806 struct program prg; 807 struct program *p = &prg; 808 809 LABEL(keyjmp); 810 LABEL(zeroassocjump1); 811 LABEL(zeropayloadjump); 812 REFERENCE(pkeyjmp); 813 REFERENCE(pzeroassocjump1); 814 REFERENCE(pzeropayloadjump); 815 816 PROGRAM_CNTXT_INIT(p, descbuf, 0); 817 818 if (swap) 819 PROGRAM_SET_BSWAP(p); 820 if (ps) 821 PROGRAM_SET_36BIT_ADDR(p); 822 823 SHR_HDR(p, share, 1, SC); 824 825 pkeyjmp = JUMP(p, keyjmp, LOCAL_JUMP, ALL_TRUE, SELF | SHRD); 826 /* Insert Key */ 827 KEY(p, KEY1, cipherdata->key_enc_flags, cipherdata->key, 828 cipherdata->keylen, INLINE_KEY(cipherdata)); 829 830 SET_LABEL(p, keyjmp); 831 832 /* class 1 operation */ 833 ALG_OPERATION(p, cipherdata->algtype, cipherdata->algmode, 834 OP_ALG_AS_INITFINAL, ICV_CHECK_ENABLE, DIR_DEC); 835 836 MATHB(p, DPOVRD, AND, 0x7fffffff, MATH3, 4, IMMED2); 837 SEQFIFOLOAD(p, IV1, ivlen, FLUSH1); 838 839 /* if assoclen is ZERO, skip reading the assoc data */ 840 MATHB(p, ZERO, ADD, MATH3, VSEQINSZ, 4, 0); 841 pzeroassocjump1 = JUMP(p, zeroassocjump1, LOCAL_JUMP, ALL_TRUE, MATH_Z); 842 843 /* read assoc data */ 844 SEQFIFOLOAD(p, AAD1, 0, CLASS1 | VLF | FLUSH1); 845 846 SET_LABEL(p, zeroassocjump1); 847 848 /* cryptlen = seqoutlen - assoclen */ 849 MATHB(p, SEQOUTSZ, SUB, MATH0, VSEQINSZ, 4, 0); 850 851 /* jump to zero-payload command if cryptlen is zero */ 852 pzeropayloadjump = JUMP(p, zeropayloadjump, LOCAL_JUMP, ALL_TRUE, 853 MATH_Z); 854 855 MATHB(p, SEQOUTSZ, SUB, MATH0, VSEQOUTSZ, 4, 0); 856 857 /* store encrypted data */ 858 SEQFIFOSTORE(p, MSG, 0, 0, VLF); 859 860 /* read payload data */ 861 SEQFIFOLOAD(p, MSG1, 0, CLASS1 | VLF | FLUSH1); 862 863 /* zero-payload command */ 864 SET_LABEL(p, zeropayloadjump); 865 866 /* read ICV */ 867 SEQFIFOLOAD(p, ICV1, icvsize, CLASS1 | LAST1); 868 869 PATCH_JUMP(p, pkeyjmp, keyjmp); 870 PATCH_JUMP(p, pzeroassocjump1, zeroassocjump1); 871 PATCH_JUMP(p, pzeropayloadjump, zeropayloadjump); 872 873 return PROGRAM_FINALIZE(p); 874 } 875 876 /** 877 * cnstr_shdsc_aes_mac - AES_XCBC_MAC, CMAC cases 878 * @descbuf: pointer to descriptor-under-construction buffer 879 * @ps: if 36/40bit addressing is desired, this parameter must be true 880 * @swap: must be true when core endianness doesn't match SEC endianness 881 * @share: sharing type of shared descriptor 882 * @authdata: pointer to authentication transform definitions; 883 * message digest algorithm: OP_ALG_ALGSEL_AES. 884 * @do_icv: 0 if ICV checking is not desired, any other value if ICV checking 885 * is needed for all the packets processed by this shared descriptor 886 * @trunc_len: Length of the truncated ICV to be written in the output buffer, 887 * 0 if no truncation is needed 888 * 889 * Note: There's no support for keys longer than the block size of the 890 * underlying hash function, according to the selected algorithm. 891 * 892 * Return: size of descriptor written in words or negative number on error 893 */ 894 static inline int 895 cnstr_shdsc_aes_mac(uint32_t *descbuf, bool ps, bool swap, 896 enum rta_share_type share, 897 struct alginfo *authdata, uint8_t do_icv, 898 uint8_t trunc_len) 899 { 900 struct program prg; 901 struct program *p = &prg; 902 uint8_t opicv, dir; 903 904 opicv = do_icv ? ICV_CHECK_ENABLE : ICV_CHECK_DISABLE; 905 dir = do_icv ? DIR_DEC : DIR_ENC; 906 907 PROGRAM_CNTXT_INIT(p, descbuf, 0); 908 if (swap) 909 PROGRAM_SET_BSWAP(p); 910 if (ps) 911 PROGRAM_SET_36BIT_ADDR(p); 912 SHR_HDR(p, share, 1, SC); 913 914 KEY(p, KEY2, authdata->key_enc_flags, authdata->key, authdata->keylen, 915 INLINE_KEY(authdata)); 916 917 /* compute sequences */ 918 if (opicv == ICV_CHECK_ENABLE) 919 MATHB(p, SEQINSZ, SUB, trunc_len, VSEQINSZ, 4, IMMED2); 920 else 921 MATHB(p, SEQINSZ, SUB, MATH2, VSEQINSZ, 4, 0); 922 923 /* Do operation */ 924 ALG_OPERATION_NP(p, authdata->algtype, authdata->algmode, 925 OP_ALG_AS_INITFINAL, opicv, dir); 926 927 /* Do load (variable length) */ 928 SEQFIFOLOAD(p, MSG2, 0, VLF | LAST2); 929 930 if (opicv == ICV_CHECK_ENABLE) { 931 LOAD(p, trunc_len, ICV2SZ, 0, 4, IMMED); 932 SEQFIFOLOAD(p, ICV2, trunc_len, LAST2); 933 } else 934 SEQSTORE(p, CONTEXT2, 0, trunc_len, 0); 935 936 return PROGRAM_FINALIZE(p); 937 } 938 939 #endif /* __DESC_ALGO_H__ */ 940