Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

crypto: qce - Add support for AEAD algorithms

Introduce support to enable following algorithms in Qualcomm Crypto Engine.

- authenc(hmac(sha1),cbc(des))
- authenc(hmac(sha1),cbc(des3_ede))
- authenc(hmac(sha256),cbc(des))
- authenc(hmac(sha256),cbc(des3_ede))
- authenc(hmac(sha256),cbc(aes))
- ccm(aes)
- rfc4309(ccm(aes))

Signed-off-by: Thara Gopinath <thara.gopinath@linaro.org>
Signed-off-by: Herbert Xu <herbert@gondor.apana.org.au>

authored by

Thara Gopinath and committed by
Herbert Xu
9363efb4 7ba9cd4e

+874
+15
drivers/crypto/Kconfig
··· 627 627 select CRYPTO_SHA1 628 628 select CRYPTO_SHA256 629 629 630 + config CRYPTO_DEV_QCE_AEAD 631 + bool 632 + depends on CRYPTO_DEV_QCE 633 + select CRYPTO_AUTHENC 634 + select CRYPTO_LIB_DES 635 + 630 636 choice 631 637 prompt "Algorithms enabled for QCE acceleration" 632 638 default CRYPTO_DEV_QCE_ENABLE_ALL ··· 653 647 bool "All supported algorithms" 654 648 select CRYPTO_DEV_QCE_SKCIPHER 655 649 select CRYPTO_DEV_QCE_SHA 650 + select CRYPTO_DEV_QCE_AEAD 656 651 help 657 652 Enable all supported algorithms: 658 653 - AES (CBC, CTR, ECB, XTS) ··· 679 672 - SHA1, HMAC-SHA1 680 673 - SHA256, HMAC-SHA256 681 674 675 + config CRYPTO_DEV_QCE_ENABLE_AEAD 676 + bool "AEAD algorithms only" 677 + select CRYPTO_DEV_QCE_AEAD 678 + help 679 + Enable AEAD algorithms only: 680 + - authenc() 681 + - ccm(aes) 682 + - rfc4309(ccm(aes)) 682 683 endchoice 683 684 684 685 config CRYPTO_DEV_QCE_SW_MAX_LEN
+1
drivers/crypto/qce/Makefile
··· 6 6 7 7 qcrypto-$(CONFIG_CRYPTO_DEV_QCE_SHA) += sha.o 8 8 qcrypto-$(CONFIG_CRYPTO_DEV_QCE_SKCIPHER) += skcipher.o 9 + qcrypto-$(CONFIG_CRYPTO_DEV_QCE_AEAD) += aead.o
+799
drivers/crypto/qce/aead.c
··· 1 + // SPDX-License-Identifier: GPL-2.0-only 2 + 3 + /* 4 + * Copyright (C) 2021, Linaro Limited. All rights reserved. 5 + */ 6 + #include <linux/dma-mapping.h> 7 + #include <linux/interrupt.h> 8 + #include <crypto/gcm.h> 9 + #include <crypto/authenc.h> 10 + #include <crypto/internal/aead.h> 11 + #include <crypto/internal/des.h> 12 + #include <crypto/sha1.h> 13 + #include <crypto/sha2.h> 14 + #include <crypto/scatterwalk.h> 15 + #include "aead.h" 16 + 17 + #define CCM_NONCE_ADATA_SHIFT 6 18 + #define CCM_NONCE_AUTHSIZE_SHIFT 3 19 + #define MAX_CCM_ADATA_HEADER_LEN 6 20 + 21 + static LIST_HEAD(aead_algs); 22 + 23 + static void qce_aead_done(void *data) 24 + { 25 + struct crypto_async_request *async_req = data; 26 + struct aead_request *req = aead_request_cast(async_req); 27 + struct qce_aead_reqctx *rctx = aead_request_ctx(req); 28 + struct qce_aead_ctx *ctx = crypto_tfm_ctx(async_req->tfm); 29 + struct qce_alg_template *tmpl = to_aead_tmpl(crypto_aead_reqtfm(req)); 30 + struct qce_device *qce = tmpl->qce; 31 + struct qce_result_dump *result_buf = qce->dma.result_buf; 32 + enum dma_data_direction dir_src, dir_dst; 33 + bool diff_dst; 34 + int error; 35 + u32 status; 36 + unsigned int totallen; 37 + unsigned char tag[SHA256_DIGEST_SIZE] = {0}; 38 + int ret = 0; 39 + 40 + diff_dst = (req->src != req->dst) ? true : false; 41 + dir_src = diff_dst ? DMA_TO_DEVICE : DMA_BIDIRECTIONAL; 42 + dir_dst = diff_dst ? DMA_FROM_DEVICE : DMA_BIDIRECTIONAL; 43 + 44 + error = qce_dma_terminate_all(&qce->dma); 45 + if (error) 46 + dev_dbg(qce->dev, "aead dma termination error (%d)\n", 47 + error); 48 + if (diff_dst) 49 + dma_unmap_sg(qce->dev, rctx->src_sg, rctx->src_nents, dir_src); 50 + 51 + dma_unmap_sg(qce->dev, rctx->dst_sg, rctx->dst_nents, dir_dst); 52 + 53 + if (IS_CCM(rctx->flags)) { 54 + if (req->assoclen) { 55 + sg_free_table(&rctx->src_tbl); 56 + if (diff_dst) 57 + sg_free_table(&rctx->dst_tbl); 58 + } else { 59 + if (!(IS_DECRYPT(rctx->flags) && !diff_dst)) 60 + sg_free_table(&rctx->dst_tbl); 61 + } 62 + } else { 63 + sg_free_table(&rctx->dst_tbl); 64 + } 65 + 66 + error = qce_check_status(qce, &status); 67 + if (error < 0 && (error != -EBADMSG)) 68 + dev_err(qce->dev, "aead operation error (%x)\n", status); 69 + 70 + if (IS_ENCRYPT(rctx->flags)) { 71 + totallen = req->cryptlen + req->assoclen; 72 + if (IS_CCM(rctx->flags)) 73 + scatterwalk_map_and_copy(rctx->ccmresult_buf, req->dst, 74 + totallen, ctx->authsize, 1); 75 + else 76 + scatterwalk_map_and_copy(result_buf->auth_iv, req->dst, 77 + totallen, ctx->authsize, 1); 78 + 79 + } else if (!IS_CCM(rctx->flags)) { 80 + totallen = req->cryptlen + req->assoclen - ctx->authsize; 81 + scatterwalk_map_and_copy(tag, req->src, totallen, ctx->authsize, 0); 82 + ret = memcmp(result_buf->auth_iv, tag, ctx->authsize); 83 + if (ret) { 84 + pr_err("Bad message error\n"); 85 + error = -EBADMSG; 86 + } 87 + } 88 + 89 + qce->async_req_done(qce, error); 90 + } 91 + 92 + static struct scatterlist * 93 + qce_aead_prepare_result_buf(struct sg_table *tbl, struct aead_request *req) 94 + { 95 + struct qce_aead_reqctx *rctx = aead_request_ctx(req); 96 + struct qce_alg_template *tmpl = to_aead_tmpl(crypto_aead_reqtfm(req)); 97 + struct qce_device *qce = tmpl->qce; 98 + 99 + sg_init_one(&rctx->result_sg, qce->dma.result_buf, QCE_RESULT_BUF_SZ); 100 + return qce_sgtable_add(tbl, &rctx->result_sg, QCE_RESULT_BUF_SZ); 101 + } 102 + 103 + static struct scatterlist * 104 + qce_aead_prepare_ccm_result_buf(struct sg_table *tbl, struct aead_request *req) 105 + { 106 + struct qce_aead_reqctx *rctx = aead_request_ctx(req); 107 + 108 + sg_init_one(&rctx->result_sg, rctx->ccmresult_buf, QCE_BAM_BURST_SIZE); 109 + return qce_sgtable_add(tbl, &rctx->result_sg, QCE_BAM_BURST_SIZE); 110 + } 111 + 112 + static struct scatterlist * 113 + qce_aead_prepare_dst_buf(struct aead_request *req) 114 + { 115 + struct qce_aead_reqctx *rctx = aead_request_ctx(req); 116 + struct qce_alg_template *tmpl = to_aead_tmpl(crypto_aead_reqtfm(req)); 117 + struct qce_device *qce = tmpl->qce; 118 + struct scatterlist *sg, *msg_sg, __sg[2]; 119 + gfp_t gfp; 120 + unsigned int assoclen = req->assoclen; 121 + unsigned int totallen; 122 + int ret; 123 + 124 + totallen = rctx->cryptlen + assoclen; 125 + rctx->dst_nents = sg_nents_for_len(req->dst, totallen); 126 + if (rctx->dst_nents < 0) { 127 + dev_err(qce->dev, "Invalid numbers of dst SG.\n"); 128 + return ERR_PTR(-EINVAL); 129 + } 130 + if (IS_CCM(rctx->flags)) 131 + rctx->dst_nents += 2; 132 + else 133 + rctx->dst_nents += 1; 134 + 135 + gfp = (req->base.flags & CRYPTO_TFM_REQ_MAY_SLEEP) ? 136 + GFP_KERNEL : GFP_ATOMIC; 137 + ret = sg_alloc_table(&rctx->dst_tbl, rctx->dst_nents, gfp); 138 + if (ret) 139 + return ERR_PTR(ret); 140 + 141 + if (IS_CCM(rctx->flags) && assoclen) { 142 + /* Get the dst buffer */ 143 + msg_sg = scatterwalk_ffwd(__sg, req->dst, assoclen); 144 + 145 + sg = qce_sgtable_add(&rctx->dst_tbl, &rctx->adata_sg, 146 + rctx->assoclen); 147 + if (IS_ERR(sg)) { 148 + ret = PTR_ERR(sg); 149 + goto dst_tbl_free; 150 + } 151 + /* dst buffer */ 152 + sg = qce_sgtable_add(&rctx->dst_tbl, msg_sg, rctx->cryptlen); 153 + if (IS_ERR(sg)) { 154 + ret = PTR_ERR(sg); 155 + goto dst_tbl_free; 156 + } 157 + totallen = rctx->cryptlen + rctx->assoclen; 158 + } else { 159 + if (totallen) { 160 + sg = qce_sgtable_add(&rctx->dst_tbl, req->dst, totallen); 161 + if (IS_ERR(sg)) 162 + goto dst_tbl_free; 163 + } 164 + } 165 + if (IS_CCM(rctx->flags)) 166 + sg = qce_aead_prepare_ccm_result_buf(&rctx->dst_tbl, req); 167 + else 168 + sg = qce_aead_prepare_result_buf(&rctx->dst_tbl, req); 169 + 170 + if (IS_ERR(sg)) 171 + goto dst_tbl_free; 172 + 173 + sg_mark_end(sg); 174 + rctx->dst_sg = rctx->dst_tbl.sgl; 175 + rctx->dst_nents = sg_nents_for_len(rctx->dst_sg, totallen) + 1; 176 + 177 + return sg; 178 + 179 + dst_tbl_free: 180 + sg_free_table(&rctx->dst_tbl); 181 + return sg; 182 + } 183 + 184 + static int 185 + qce_aead_ccm_prepare_buf_assoclen(struct aead_request *req) 186 + { 187 + struct scatterlist *sg, *msg_sg, __sg[2]; 188 + struct crypto_aead *tfm = crypto_aead_reqtfm(req); 189 + struct qce_aead_reqctx *rctx = aead_request_ctx(req); 190 + struct qce_aead_ctx *ctx = crypto_aead_ctx(tfm); 191 + unsigned int assoclen = rctx->assoclen; 192 + unsigned int adata_header_len, cryptlen, totallen; 193 + gfp_t gfp; 194 + bool diff_dst; 195 + int ret; 196 + 197 + if (IS_DECRYPT(rctx->flags)) 198 + cryptlen = rctx->cryptlen + ctx->authsize; 199 + else 200 + cryptlen = rctx->cryptlen; 201 + totallen = cryptlen + req->assoclen; 202 + 203 + /* Get the msg */ 204 + msg_sg = scatterwalk_ffwd(__sg, req->src, req->assoclen); 205 + 206 + rctx->adata = kzalloc((ALIGN(assoclen, 16) + MAX_CCM_ADATA_HEADER_LEN) * 207 + sizeof(unsigned char), GFP_ATOMIC); 208 + if (!rctx->adata) 209 + return -ENOMEM; 210 + 211 + /* 212 + * Format associated data (RFC3610 and NIST 800-38C) 213 + * Even though specification allows for AAD to be up to 2^64 - 1 bytes, 214 + * the assoclen field in aead_request is unsigned int and thus limits 215 + * the AAD to be up to 2^32 - 1 bytes. So we handle only two scenarios 216 + * while forming the header for AAD. 217 + */ 218 + if (assoclen < 0xff00) { 219 + adata_header_len = 2; 220 + *(__be16 *)rctx->adata = cpu_to_be16(assoclen); 221 + } else { 222 + adata_header_len = 6; 223 + *(__be16 *)rctx->adata = cpu_to_be16(0xfffe); 224 + *(__be32 *)(rctx->adata + 2) = cpu_to_be32(assoclen); 225 + } 226 + 227 + /* Copy the associated data */ 228 + if (sg_copy_to_buffer(req->src, sg_nents_for_len(req->src, assoclen), 229 + rctx->adata + adata_header_len, 230 + assoclen) != assoclen) 231 + return -EINVAL; 232 + 233 + /* Pad associated data to block size */ 234 + rctx->assoclen = ALIGN(assoclen + adata_header_len, 16); 235 + 236 + diff_dst = (req->src != req->dst) ? true : false; 237 + 238 + if (diff_dst) 239 + rctx->src_nents = sg_nents_for_len(req->src, totallen) + 1; 240 + else 241 + rctx->src_nents = sg_nents_for_len(req->src, totallen) + 2; 242 + 243 + gfp = (req->base.flags & CRYPTO_TFM_REQ_MAY_SLEEP) ? GFP_KERNEL : GFP_ATOMIC; 244 + ret = sg_alloc_table(&rctx->src_tbl, rctx->src_nents, gfp); 245 + if (ret) 246 + return ret; 247 + 248 + /* Associated Data */ 249 + sg_init_one(&rctx->adata_sg, rctx->adata, rctx->assoclen); 250 + sg = qce_sgtable_add(&rctx->src_tbl, &rctx->adata_sg, 251 + rctx->assoclen); 252 + if (IS_ERR(sg)) { 253 + ret = PTR_ERR(sg); 254 + goto err_free; 255 + } 256 + /* src msg */ 257 + sg = qce_sgtable_add(&rctx->src_tbl, msg_sg, cryptlen); 258 + if (IS_ERR(sg)) { 259 + ret = PTR_ERR(sg); 260 + goto err_free; 261 + } 262 + if (!diff_dst) { 263 + /* 264 + * For decrypt, when src and dst buffers are same, there is already space 265 + * in the buffer for padded 0's which is output in lieu of 266 + * the MAC that is input. So skip the below. 267 + */ 268 + if (!IS_DECRYPT(rctx->flags)) { 269 + sg = qce_aead_prepare_ccm_result_buf(&rctx->src_tbl, req); 270 + if (IS_ERR(sg)) { 271 + ret = PTR_ERR(sg); 272 + goto err_free; 273 + } 274 + } 275 + } 276 + sg_mark_end(sg); 277 + rctx->src_sg = rctx->src_tbl.sgl; 278 + totallen = cryptlen + rctx->assoclen; 279 + rctx->src_nents = sg_nents_for_len(rctx->src_sg, totallen); 280 + 281 + if (diff_dst) { 282 + sg = qce_aead_prepare_dst_buf(req); 283 + if (IS_ERR(sg)) 284 + goto err_free; 285 + } else { 286 + if (IS_ENCRYPT(rctx->flags)) 287 + rctx->dst_nents = rctx->src_nents + 1; 288 + else 289 + rctx->dst_nents = rctx->src_nents; 290 + rctx->dst_sg = rctx->src_sg; 291 + } 292 + 293 + return 0; 294 + err_free: 295 + sg_free_table(&rctx->src_tbl); 296 + return ret; 297 + } 298 + 299 + static int qce_aead_prepare_buf(struct aead_request *req) 300 + { 301 + struct qce_aead_reqctx *rctx = aead_request_ctx(req); 302 + struct qce_alg_template *tmpl = to_aead_tmpl(crypto_aead_reqtfm(req)); 303 + struct qce_device *qce = tmpl->qce; 304 + struct scatterlist *sg; 305 + bool diff_dst = (req->src != req->dst) ? true : false; 306 + unsigned int totallen; 307 + 308 + totallen = rctx->cryptlen + rctx->assoclen; 309 + 310 + sg = qce_aead_prepare_dst_buf(req); 311 + if (IS_ERR(sg)) 312 + return PTR_ERR(sg); 313 + if (diff_dst) { 314 + rctx->src_nents = sg_nents_for_len(req->src, totallen); 315 + if (rctx->src_nents < 0) { 316 + dev_err(qce->dev, "Invalid numbers of src SG.\n"); 317 + return -EINVAL; 318 + } 319 + rctx->src_sg = req->src; 320 + } else { 321 + rctx->src_nents = rctx->dst_nents - 1; 322 + rctx->src_sg = rctx->dst_sg; 323 + } 324 + return 0; 325 + } 326 + 327 + static int qce_aead_ccm_prepare_buf(struct aead_request *req) 328 + { 329 + struct qce_aead_reqctx *rctx = aead_request_ctx(req); 330 + struct crypto_aead *tfm = crypto_aead_reqtfm(req); 331 + struct qce_aead_ctx *ctx = crypto_aead_ctx(tfm); 332 + struct scatterlist *sg; 333 + bool diff_dst = (req->src != req->dst) ? true : false; 334 + unsigned int cryptlen; 335 + 336 + if (rctx->assoclen) 337 + return qce_aead_ccm_prepare_buf_assoclen(req); 338 + 339 + if (IS_ENCRYPT(rctx->flags)) 340 + return qce_aead_prepare_buf(req); 341 + 342 + cryptlen = rctx->cryptlen + ctx->authsize; 343 + if (diff_dst) { 344 + rctx->src_nents = sg_nents_for_len(req->src, cryptlen); 345 + rctx->src_sg = req->src; 346 + sg = qce_aead_prepare_dst_buf(req); 347 + if (IS_ERR(sg)) 348 + return PTR_ERR(sg); 349 + } else { 350 + rctx->src_nents = sg_nents_for_len(req->src, cryptlen); 351 + rctx->src_sg = req->src; 352 + rctx->dst_nents = rctx->src_nents; 353 + rctx->dst_sg = rctx->src_sg; 354 + } 355 + 356 + return 0; 357 + } 358 + 359 + static int qce_aead_create_ccm_nonce(struct qce_aead_reqctx *rctx, struct qce_aead_ctx *ctx) 360 + { 361 + unsigned int msglen_size, ivsize; 362 + u8 msg_len[4]; 363 + int i; 364 + 365 + if (!rctx || !rctx->iv) 366 + return -EINVAL; 367 + 368 + msglen_size = rctx->iv[0] + 1; 369 + 370 + /* Verify that msg len size is valid */ 371 + if (msglen_size < 2 || msglen_size > 8) 372 + return -EINVAL; 373 + 374 + ivsize = rctx->ivsize; 375 + 376 + /* 377 + * Clear the msglen bytes in IV. 378 + * Else the h/w engine and nonce will use any stray value pending there. 379 + */ 380 + if (!IS_CCM_RFC4309(rctx->flags)) { 381 + for (i = 0; i < msglen_size; i++) 382 + rctx->iv[ivsize - i - 1] = 0; 383 + } 384 + 385 + /* 386 + * The crypto framework encodes cryptlen as unsigned int. Thus, even though 387 + * spec allows for upto 8 bytes to encode msg_len only 4 bytes are needed. 388 + */ 389 + if (msglen_size > 4) 390 + msglen_size = 4; 391 + 392 + memcpy(&msg_len[0], &rctx->cryptlen, 4); 393 + 394 + memcpy(&rctx->ccm_nonce[0], rctx->iv, rctx->ivsize); 395 + if (rctx->assoclen) 396 + rctx->ccm_nonce[0] |= 1 << CCM_NONCE_ADATA_SHIFT; 397 + rctx->ccm_nonce[0] |= ((ctx->authsize - 2) / 2) << 398 + CCM_NONCE_AUTHSIZE_SHIFT; 399 + for (i = 0; i < msglen_size; i++) 400 + rctx->ccm_nonce[QCE_MAX_NONCE - i - 1] = msg_len[i]; 401 + 402 + return 0; 403 + } 404 + 405 + static int 406 + qce_aead_async_req_handle(struct crypto_async_request *async_req) 407 + { 408 + struct aead_request *req = aead_request_cast(async_req); 409 + struct qce_aead_reqctx *rctx = aead_request_ctx(req); 410 + struct crypto_aead *tfm = crypto_aead_reqtfm(req); 411 + struct qce_aead_ctx *ctx = crypto_tfm_ctx(async_req->tfm); 412 + struct qce_alg_template *tmpl = to_aead_tmpl(crypto_aead_reqtfm(req)); 413 + struct qce_device *qce = tmpl->qce; 414 + enum dma_data_direction dir_src, dir_dst; 415 + bool diff_dst; 416 + int dst_nents, src_nents, ret; 417 + 418 + if (IS_CCM_RFC4309(rctx->flags)) { 419 + memset(rctx->ccm_rfc4309_iv, 0, QCE_MAX_IV_SIZE); 420 + rctx->ccm_rfc4309_iv[0] = 3; 421 + memcpy(&rctx->ccm_rfc4309_iv[1], ctx->ccm4309_salt, QCE_CCM4309_SALT_SIZE); 422 + memcpy(&rctx->ccm_rfc4309_iv[4], req->iv, 8); 423 + rctx->iv = rctx->ccm_rfc4309_iv; 424 + rctx->ivsize = AES_BLOCK_SIZE; 425 + } else { 426 + rctx->iv = req->iv; 427 + rctx->ivsize = crypto_aead_ivsize(tfm); 428 + } 429 + if (IS_CCM_RFC4309(rctx->flags)) 430 + rctx->assoclen = req->assoclen - 8; 431 + else 432 + rctx->assoclen = req->assoclen; 433 + 434 + diff_dst = (req->src != req->dst) ? true : false; 435 + dir_src = diff_dst ? DMA_TO_DEVICE : DMA_BIDIRECTIONAL; 436 + dir_dst = diff_dst ? DMA_FROM_DEVICE : DMA_BIDIRECTIONAL; 437 + 438 + if (IS_CCM(rctx->flags)) { 439 + ret = qce_aead_create_ccm_nonce(rctx, ctx); 440 + if (ret) 441 + return ret; 442 + } 443 + if (IS_CCM(rctx->flags)) 444 + ret = qce_aead_ccm_prepare_buf(req); 445 + else 446 + ret = qce_aead_prepare_buf(req); 447 + 448 + if (ret) 449 + return ret; 450 + dst_nents = dma_map_sg(qce->dev, rctx->dst_sg, rctx->dst_nents, dir_dst); 451 + if (dst_nents < 0) 452 + goto error_free; 453 + 454 + if (diff_dst) { 455 + src_nents = dma_map_sg(qce->dev, rctx->src_sg, rctx->src_nents, dir_src); 456 + if (src_nents < 0) 457 + goto error_unmap_dst; 458 + } else { 459 + if (IS_CCM(rctx->flags) && IS_DECRYPT(rctx->flags)) 460 + src_nents = dst_nents; 461 + else 462 + src_nents = dst_nents - 1; 463 + } 464 + 465 + ret = qce_dma_prep_sgs(&qce->dma, rctx->src_sg, src_nents, rctx->dst_sg, dst_nents, 466 + qce_aead_done, async_req); 467 + if (ret) 468 + goto error_unmap_src; 469 + 470 + qce_dma_issue_pending(&qce->dma); 471 + 472 + ret = qce_start(async_req, tmpl->crypto_alg_type); 473 + if (ret) 474 + goto error_terminate; 475 + 476 + return 0; 477 + 478 + error_terminate: 479 + qce_dma_terminate_all(&qce->dma); 480 + error_unmap_src: 481 + if (diff_dst) 482 + dma_unmap_sg(qce->dev, req->src, rctx->src_nents, dir_src); 483 + error_unmap_dst: 484 + dma_unmap_sg(qce->dev, rctx->dst_sg, rctx->dst_nents, dir_dst); 485 + error_free: 486 + if (IS_CCM(rctx->flags) && rctx->assoclen) { 487 + sg_free_table(&rctx->src_tbl); 488 + if (diff_dst) 489 + sg_free_table(&rctx->dst_tbl); 490 + } else { 491 + sg_free_table(&rctx->dst_tbl); 492 + } 493 + return ret; 494 + } 495 + 496 + static int qce_aead_crypt(struct aead_request *req, int encrypt) 497 + { 498 + struct crypto_aead *tfm = crypto_aead_reqtfm(req); 499 + struct qce_aead_reqctx *rctx = aead_request_ctx(req); 500 + struct qce_aead_ctx *ctx = crypto_aead_ctx(tfm); 501 + struct qce_alg_template *tmpl = to_aead_tmpl(tfm); 502 + unsigned int blocksize = crypto_aead_blocksize(tfm); 503 + 504 + rctx->flags = tmpl->alg_flags; 505 + rctx->flags |= encrypt ? QCE_ENCRYPT : QCE_DECRYPT; 506 + 507 + if (encrypt) 508 + rctx->cryptlen = req->cryptlen; 509 + else 510 + rctx->cryptlen = req->cryptlen - ctx->authsize; 511 + 512 + /* CE does not handle 0 length messages */ 513 + if (!rctx->cryptlen) { 514 + if (!(IS_CCM(rctx->flags) && IS_DECRYPT(rctx->flags))) 515 + return -EINVAL; 516 + } 517 + 518 + /* 519 + * CBC algorithms require message lengths to be 520 + * multiples of block size. 521 + */ 522 + if (IS_CBC(rctx->flags) && !IS_ALIGNED(rctx->cryptlen, blocksize)) 523 + return -EINVAL; 524 + 525 + /* RFC4309 supported AAD size 16 bytes/20 bytes */ 526 + if (IS_CCM_RFC4309(rctx->flags)) 527 + if (crypto_ipsec_check_assoclen(req->assoclen)) 528 + return -EINVAL; 529 + 530 + return tmpl->qce->async_req_enqueue(tmpl->qce, &req->base); 531 + } 532 + 533 + static int qce_aead_encrypt(struct aead_request *req) 534 + { 535 + return qce_aead_crypt(req, 1); 536 + } 537 + 538 + static int qce_aead_decrypt(struct aead_request *req) 539 + { 540 + return qce_aead_crypt(req, 0); 541 + } 542 + 543 + static int qce_aead_ccm_setkey(struct crypto_aead *tfm, const u8 *key, 544 + unsigned int keylen) 545 + { 546 + struct qce_aead_ctx *ctx = crypto_aead_ctx(tfm); 547 + unsigned long flags = to_aead_tmpl(tfm)->alg_flags; 548 + 549 + if (IS_CCM_RFC4309(flags)) { 550 + if (keylen < QCE_CCM4309_SALT_SIZE) 551 + return -EINVAL; 552 + keylen -= QCE_CCM4309_SALT_SIZE; 553 + memcpy(ctx->ccm4309_salt, key + keylen, QCE_CCM4309_SALT_SIZE); 554 + } 555 + 556 + if (keylen != AES_KEYSIZE_128 && keylen != AES_KEYSIZE_256) 557 + return -EINVAL; 558 + 559 + ctx->enc_keylen = keylen; 560 + ctx->auth_keylen = keylen; 561 + 562 + memcpy(ctx->enc_key, key, keylen); 563 + memcpy(ctx->auth_key, key, keylen); 564 + 565 + return 0; 566 + } 567 + 568 + static int qce_aead_setkey(struct crypto_aead *tfm, const u8 *key, unsigned int keylen) 569 + { 570 + struct qce_aead_ctx *ctx = crypto_aead_ctx(tfm); 571 + struct crypto_authenc_keys authenc_keys; 572 + unsigned long flags = to_aead_tmpl(tfm)->alg_flags; 573 + u32 _key[6]; 574 + int err; 575 + 576 + err = crypto_authenc_extractkeys(&authenc_keys, key, keylen); 577 + if (err) 578 + return err; 579 + 580 + if (authenc_keys.enckeylen > QCE_MAX_KEY_SIZE || 581 + authenc_keys.authkeylen > QCE_MAX_KEY_SIZE) 582 + return -EINVAL; 583 + 584 + if (IS_DES(flags)) { 585 + err = verify_aead_des_key(tfm, authenc_keys.enckey, authenc_keys.enckeylen); 586 + if (err) 587 + return err; 588 + } else if (IS_3DES(flags)) { 589 + err = verify_aead_des3_key(tfm, authenc_keys.enckey, authenc_keys.enckeylen); 590 + if (err) 591 + return err; 592 + /* 593 + * The crypto engine does not support any two keys 594 + * being the same for triple des algorithms. The 595 + * verify_skcipher_des3_key does not check for all the 596 + * below conditions. Return -EINVAL in case any two keys 597 + * are the same. Revisit to see if a fallback cipher 598 + * is needed to handle this condition. 599 + */ 600 + memcpy(_key, authenc_keys.enckey, DES3_EDE_KEY_SIZE); 601 + if (!((_key[0] ^ _key[2]) | (_key[1] ^ _key[3])) || 602 + !((_key[2] ^ _key[4]) | (_key[3] ^ _key[5])) || 603 + !((_key[0] ^ _key[4]) | (_key[1] ^ _key[5]))) 604 + return -EINVAL; 605 + } else if (IS_AES(flags)) { 606 + /* No random key sizes */ 607 + if (authenc_keys.enckeylen != AES_KEYSIZE_128 && 608 + authenc_keys.enckeylen != AES_KEYSIZE_256) 609 + return -EINVAL; 610 + } 611 + 612 + ctx->enc_keylen = authenc_keys.enckeylen; 613 + ctx->auth_keylen = authenc_keys.authkeylen; 614 + 615 + memcpy(ctx->enc_key, authenc_keys.enckey, authenc_keys.enckeylen); 616 + 617 + memset(ctx->auth_key, 0, sizeof(ctx->auth_key)); 618 + memcpy(ctx->auth_key, authenc_keys.authkey, authenc_keys.authkeylen); 619 + 620 + return 0; 621 + } 622 + 623 + static int qce_aead_setauthsize(struct crypto_aead *tfm, unsigned int authsize) 624 + { 625 + struct qce_aead_ctx *ctx = crypto_aead_ctx(tfm); 626 + unsigned long flags = to_aead_tmpl(tfm)->alg_flags; 627 + 628 + if (IS_CCM(flags)) { 629 + if (authsize < 4 || authsize > 16 || authsize % 2) 630 + return -EINVAL; 631 + if (IS_CCM_RFC4309(flags) && (authsize < 8 || authsize % 4)) 632 + return -EINVAL; 633 + } 634 + ctx->authsize = authsize; 635 + return 0; 636 + } 637 + 638 + static int qce_aead_init(struct crypto_aead *tfm) 639 + { 640 + crypto_aead_set_reqsize(tfm, sizeof(struct qce_aead_reqctx)); 641 + return 0; 642 + } 643 + 644 + struct qce_aead_def { 645 + unsigned long flags; 646 + const char *name; 647 + const char *drv_name; 648 + unsigned int blocksize; 649 + unsigned int chunksize; 650 + unsigned int ivsize; 651 + unsigned int maxauthsize; 652 + }; 653 + 654 + static const struct qce_aead_def aead_def[] = { 655 + { 656 + .flags = QCE_ALG_DES | QCE_MODE_CBC | QCE_HASH_SHA1_HMAC, 657 + .name = "authenc(hmac(sha1),cbc(des))", 658 + .drv_name = "authenc-hmac-sha1-cbc-des-qce", 659 + .blocksize = DES_BLOCK_SIZE, 660 + .ivsize = DES_BLOCK_SIZE, 661 + .maxauthsize = SHA1_DIGEST_SIZE, 662 + }, 663 + { 664 + .flags = QCE_ALG_3DES | QCE_MODE_CBC | QCE_HASH_SHA1_HMAC, 665 + .name = "authenc(hmac(sha1),cbc(des3_ede))", 666 + .drv_name = "authenc-hmac-sha1-cbc-3des-qce", 667 + .blocksize = DES3_EDE_BLOCK_SIZE, 668 + .ivsize = DES3_EDE_BLOCK_SIZE, 669 + .maxauthsize = SHA1_DIGEST_SIZE, 670 + }, 671 + { 672 + .flags = QCE_ALG_DES | QCE_MODE_CBC | QCE_HASH_SHA256_HMAC, 673 + .name = "authenc(hmac(sha256),cbc(des))", 674 + .drv_name = "authenc-hmac-sha256-cbc-des-qce", 675 + .blocksize = DES_BLOCK_SIZE, 676 + .ivsize = DES_BLOCK_SIZE, 677 + .maxauthsize = SHA256_DIGEST_SIZE, 678 + }, 679 + { 680 + .flags = QCE_ALG_3DES | QCE_MODE_CBC | QCE_HASH_SHA256_HMAC, 681 + .name = "authenc(hmac(sha256),cbc(des3_ede))", 682 + .drv_name = "authenc-hmac-sha256-cbc-3des-qce", 683 + .blocksize = DES3_EDE_BLOCK_SIZE, 684 + .ivsize = DES3_EDE_BLOCK_SIZE, 685 + .maxauthsize = SHA256_DIGEST_SIZE, 686 + }, 687 + { 688 + .flags = QCE_ALG_AES | QCE_MODE_CBC | QCE_HASH_SHA256_HMAC, 689 + .name = "authenc(hmac(sha256),cbc(aes))", 690 + .drv_name = "authenc-hmac-sha256-cbc-aes-qce", 691 + .blocksize = AES_BLOCK_SIZE, 692 + .ivsize = AES_BLOCK_SIZE, 693 + .maxauthsize = SHA256_DIGEST_SIZE, 694 + }, 695 + { 696 + .flags = QCE_ALG_AES | QCE_MODE_CCM, 697 + .name = "ccm(aes)", 698 + .drv_name = "ccm-aes-qce", 699 + .blocksize = 1, 700 + .ivsize = AES_BLOCK_SIZE, 701 + .maxauthsize = AES_BLOCK_SIZE, 702 + }, 703 + { 704 + .flags = QCE_ALG_AES | QCE_MODE_CCM | QCE_MODE_CCM_RFC4309, 705 + .name = "rfc4309(ccm(aes))", 706 + .drv_name = "rfc4309-ccm-aes-qce", 707 + .blocksize = 1, 708 + .ivsize = 8, 709 + .maxauthsize = AES_BLOCK_SIZE, 710 + }, 711 + }; 712 + 713 + static int qce_aead_register_one(const struct qce_aead_def *def, struct qce_device *qce) 714 + { 715 + struct qce_alg_template *tmpl; 716 + struct aead_alg *alg; 717 + int ret; 718 + 719 + tmpl = kzalloc(sizeof(*tmpl), GFP_KERNEL); 720 + if (!tmpl) 721 + return -ENOMEM; 722 + 723 + alg = &tmpl->alg.aead; 724 + 725 + snprintf(alg->base.cra_name, CRYPTO_MAX_ALG_NAME, "%s", def->name); 726 + snprintf(alg->base.cra_driver_name, CRYPTO_MAX_ALG_NAME, "%s", 727 + def->drv_name); 728 + 729 + alg->base.cra_blocksize = def->blocksize; 730 + alg->chunksize = def->chunksize; 731 + alg->ivsize = def->ivsize; 732 + alg->maxauthsize = def->maxauthsize; 733 + if (IS_CCM(def->flags)) 734 + alg->setkey = qce_aead_ccm_setkey; 735 + else 736 + alg->setkey = qce_aead_setkey; 737 + alg->setauthsize = qce_aead_setauthsize; 738 + alg->encrypt = qce_aead_encrypt; 739 + alg->decrypt = qce_aead_decrypt; 740 + alg->init = qce_aead_init; 741 + 742 + alg->base.cra_priority = 300; 743 + alg->base.cra_flags = CRYPTO_ALG_ASYNC | 744 + CRYPTO_ALG_ALLOCATES_MEMORY | 745 + CRYPTO_ALG_KERN_DRIVER_ONLY; 746 + alg->base.cra_ctxsize = sizeof(struct qce_aead_ctx); 747 + alg->base.cra_alignmask = 0; 748 + alg->base.cra_module = THIS_MODULE; 749 + 750 + INIT_LIST_HEAD(&tmpl->entry); 751 + tmpl->crypto_alg_type = CRYPTO_ALG_TYPE_AEAD; 752 + tmpl->alg_flags = def->flags; 753 + tmpl->qce = qce; 754 + 755 + ret = crypto_register_aead(alg); 756 + if (ret) { 757 + kfree(tmpl); 758 + dev_err(qce->dev, "%s registration failed\n", alg->base.cra_name); 759 + return ret; 760 + } 761 + 762 + list_add_tail(&tmpl->entry, &aead_algs); 763 + dev_dbg(qce->dev, "%s is registered\n", alg->base.cra_name); 764 + return 0; 765 + } 766 + 767 + static void qce_aead_unregister(struct qce_device *qce) 768 + { 769 + struct qce_alg_template *tmpl, *n; 770 + 771 + list_for_each_entry_safe(tmpl, n, &aead_algs, entry) { 772 + crypto_unregister_aead(&tmpl->alg.aead); 773 + list_del(&tmpl->entry); 774 + kfree(tmpl); 775 + } 776 + } 777 + 778 + static int qce_aead_register(struct qce_device *qce) 779 + { 780 + int ret, i; 781 + 782 + for (i = 0; i < ARRAY_SIZE(aead_def); i++) { 783 + ret = qce_aead_register_one(&aead_def[i], qce); 784 + if (ret) 785 + goto err; 786 + } 787 + 788 + return 0; 789 + err: 790 + qce_aead_unregister(qce); 791 + return ret; 792 + } 793 + 794 + const struct qce_algo_ops aead_ops = { 795 + .type = CRYPTO_ALG_TYPE_AEAD, 796 + .register_algs = qce_aead_register, 797 + .unregister_algs = qce_aead_unregister, 798 + .async_req_handle = qce_aead_async_req_handle, 799 + };
+53
drivers/crypto/qce/aead.h
··· 1 + /* SPDX-License-Identifier: GPL-2.0-only */ 2 + /* 3 + * Copyright (c) 2021, Linaro Limited. All rights reserved. 4 + */ 5 + 6 + #ifndef _AEAD_H_ 7 + #define _AEAD_H_ 8 + 9 + #include "common.h" 10 + #include "core.h" 11 + 12 + #define QCE_MAX_KEY_SIZE 64 13 + #define QCE_CCM4309_SALT_SIZE 3 14 + 15 + struct qce_aead_ctx { 16 + u8 enc_key[QCE_MAX_KEY_SIZE]; 17 + u8 auth_key[QCE_MAX_KEY_SIZE]; 18 + u8 ccm4309_salt[QCE_CCM4309_SALT_SIZE]; 19 + unsigned int enc_keylen; 20 + unsigned int auth_keylen; 21 + unsigned int authsize; 22 + }; 23 + 24 + struct qce_aead_reqctx { 25 + unsigned long flags; 26 + u8 *iv; 27 + unsigned int ivsize; 28 + int src_nents; 29 + int dst_nents; 30 + struct scatterlist result_sg; 31 + struct scatterlist adata_sg; 32 + struct sg_table dst_tbl; 33 + struct sg_table src_tbl; 34 + struct scatterlist *dst_sg; 35 + struct scatterlist *src_sg; 36 + unsigned int cryptlen; 37 + unsigned int assoclen; 38 + unsigned char *adata; 39 + u8 ccm_nonce[QCE_MAX_NONCE]; 40 + u8 ccmresult_buf[QCE_BAM_BURST_SIZE]; 41 + u8 ccm_rfc4309_iv[QCE_MAX_IV_SIZE]; 42 + }; 43 + 44 + static inline struct qce_alg_template *to_aead_tmpl(struct crypto_aead *tfm) 45 + { 46 + struct aead_alg *alg = crypto_aead_alg(tfm); 47 + 48 + return container_of(alg, struct qce_alg_template, alg.aead); 49 + } 50 + 51 + extern const struct qce_algo_ops aead_ops; 52 + 53 + #endif /* _AEAD_H_ */
+2
drivers/crypto/qce/common.h
··· 11 11 #include <crypto/aes.h> 12 12 #include <crypto/hash.h> 13 13 #include <crypto/internal/skcipher.h> 14 + #include <crypto/internal/aead.h> 14 15 15 16 /* xts du size */ 16 17 #define QCE_SECTOR_SIZE 512 ··· 89 88 union { 90 89 struct skcipher_alg skcipher; 91 90 struct ahash_alg ahash; 91 + struct aead_alg aead; 92 92 } alg; 93 93 struct qce_device *qce; 94 94 const u8 *hash_zero;
+4
drivers/crypto/qce/core.c
··· 17 17 #include "core.h" 18 18 #include "cipher.h" 19 19 #include "sha.h" 20 + #include "aead.h" 20 21 21 22 #define QCE_MAJOR_VERSION5 0x05 22 23 #define QCE_QUEUE_LENGTH 1 ··· 28 27 #endif 29 28 #ifdef CONFIG_CRYPTO_DEV_QCE_SHA 30 29 &ahash_ops, 30 + #endif 31 + #ifdef CONFIG_CRYPTO_DEV_QCE_AEAD 32 + &aead_ops, 31 33 #endif 32 34 }; 33 35