diff --git a/drivers/crypto/qce/aead.c b/drivers/crypto/qce/aead.c index 8831adb7b0f56..37265bd141609 100644 --- a/drivers/crypto/qce/aead.c +++ b/drivers/crypto/qce/aead.c @@ -9,8 +9,6 @@ #include #include #include -#include -#include #include #include #include "aead.h" @@ -500,7 +498,8 @@ static int qce_aead_crypt(struct aead_request *req, int encrypt) struct qce_aead_reqctx *rctx = aead_request_ctx_dma(req); struct qce_aead_ctx *ctx = crypto_aead_ctx(tfm); struct qce_alg_template *tmpl = to_aead_tmpl(tfm); - unsigned int blocksize = crypto_aead_blocksize(tfm); + unsigned int blocksize = crypto_aead_blocksize(tfm), authsize; + struct scatterlist __sg[2], *msg_sg; rctx->flags = tmpl->alg_flags; rctx->flags |= encrypt ? QCE_ENCRYPT : QCE_DECRYPT; @@ -516,6 +515,35 @@ static int qce_aead_crypt(struct aead_request *req, int encrypt) ctx->need_fallback = true; } + /* + * CCM uses AES-CTR internally and the CE stalls on a partial final + * block, so a payload that is not a multiple of the block size has to + * be handled by the fallback. + */ + if (IS_CCM(rctx->flags) && !IS_ALIGNED(rctx->cryptlen, AES_BLOCK_SIZE)) + ctx->need_fallback = true; + + /* + * The CE reliably processes CCM only when the message payload is a + * single contiguous buffer. The associated data is linearized into a + * bounce buffer before being handed to the engine, but a fragmented + * payload makes the engine stall waiting for input, so route those + * requests to the fallback. + */ + if (IS_CCM(rctx->flags) && rctx->cryptlen) { + authsize = ctx->authsize; + + msg_sg = scatterwalk_ffwd(__sg, req->src, req->assoclen); + if (sg_nents_for_len(msg_sg, rctx->cryptlen + + (encrypt ? 0 : authsize)) > 1) + ctx->need_fallback = true; + + msg_sg = scatterwalk_ffwd(__sg, req->dst, req->assoclen); + if (sg_nents_for_len(msg_sg, rctx->cryptlen + + (encrypt ? authsize : 0)) > 1) + ctx->need_fallback = true; + } + /* If fallback is needed, schedule and exit */ if (ctx->need_fallback) { /* Reset need_fallback in case the same ctx is used for another transaction */ @@ -592,7 +620,6 @@ static int qce_aead_setkey(struct crypto_aead *tfm, const u8 *key, unsigned int struct qce_aead_ctx *ctx = crypto_aead_ctx(tfm); struct crypto_authenc_keys authenc_keys; unsigned long flags = to_aead_tmpl(tfm)->alg_flags; - u32 _key[6]; int err; err = crypto_authenc_extractkeys(&authenc_keys, key, keylen); @@ -603,26 +630,7 @@ static int qce_aead_setkey(struct crypto_aead *tfm, const u8 *key, unsigned int authenc_keys.authkeylen > QCE_MAX_KEY_SIZE) return -EINVAL; - if (IS_DES(flags)) { - err = verify_aead_des_key(tfm, authenc_keys.enckey, authenc_keys.enckeylen); - if (err) - return err; - } else if (IS_3DES(flags)) { - err = verify_aead_des3_key(tfm, authenc_keys.enckey, authenc_keys.enckeylen); - if (err) - return err; - /* - * The crypto engine does not support any two keys - * being the same for triple des algorithms. The - * verify_skcipher_des3_key does not check for all the - * below conditions. Schedule fallback in this case. - */ - memcpy(_key, authenc_keys.enckey, DES3_EDE_KEY_SIZE); - if (!((_key[0] ^ _key[2]) | (_key[1] ^ _key[3])) || - !((_key[2] ^ _key[4]) | (_key[3] ^ _key[5])) || - !((_key[0] ^ _key[4]) | (_key[1] ^ _key[5]))) - ctx->need_fallback = true; - } else if (IS_AES(flags)) { + if (IS_AES(flags)) { /* No random key sizes */ if (authenc_keys.enckeylen != AES_KEYSIZE_128 && authenc_keys.enckeylen != AES_KEYSIZE_192 && @@ -693,38 +701,6 @@ struct qce_aead_def { }; static const struct qce_aead_def aead_def[] = { - { - .flags = QCE_ALG_DES | QCE_MODE_CBC | QCE_HASH_SHA1_HMAC, - .name = "authenc(hmac(sha1),cbc(des))", - .drv_name = "authenc-hmac-sha1-cbc-des-qce", - .blocksize = DES_BLOCK_SIZE, - .ivsize = DES_BLOCK_SIZE, - .maxauthsize = SHA1_DIGEST_SIZE, - }, - { - .flags = QCE_ALG_3DES | QCE_MODE_CBC | QCE_HASH_SHA1_HMAC, - .name = "authenc(hmac(sha1),cbc(des3_ede))", - .drv_name = "authenc-hmac-sha1-cbc-3des-qce", - .blocksize = DES3_EDE_BLOCK_SIZE, - .ivsize = DES3_EDE_BLOCK_SIZE, - .maxauthsize = SHA1_DIGEST_SIZE, - }, - { - .flags = QCE_ALG_DES | QCE_MODE_CBC | QCE_HASH_SHA256_HMAC, - .name = "authenc(hmac(sha256),cbc(des))", - .drv_name = "authenc-hmac-sha256-cbc-des-qce", - .blocksize = DES_BLOCK_SIZE, - .ivsize = DES_BLOCK_SIZE, - .maxauthsize = SHA256_DIGEST_SIZE, - }, - { - .flags = QCE_ALG_3DES | QCE_MODE_CBC | QCE_HASH_SHA256_HMAC, - .name = "authenc(hmac(sha256),cbc(des3_ede))", - .drv_name = "authenc-hmac-sha256-cbc-3des-qce", - .blocksize = DES3_EDE_BLOCK_SIZE, - .ivsize = DES3_EDE_BLOCK_SIZE, - .maxauthsize = SHA256_DIGEST_SIZE, - }, { .flags = QCE_ALG_AES | QCE_MODE_CBC | QCE_HASH_SHA256_HMAC, .name = "authenc(hmac(sha256),cbc(aes))", diff --git a/drivers/crypto/qce/cipher.h b/drivers/crypto/qce/cipher.h index 850f257d00f3a..daea07551118d 100644 --- a/drivers/crypto/qce/cipher.h +++ b/drivers/crypto/qce/cipher.h @@ -14,6 +14,7 @@ struct qce_cipher_ctx { u8 enc_key[QCE_MAX_KEY_SIZE]; unsigned int enc_keylen; + bool use_fallback; struct crypto_skcipher *fallback; }; diff --git a/drivers/crypto/qce/common.c b/drivers/crypto/qce/common.c index 37bb6f03244d3..5930933412e94 100644 --- a/drivers/crypto/qce/common.c +++ b/drivers/crypto/qce/common.c @@ -8,7 +8,6 @@ #include #include #include -#include #include #include "cipher.h" @@ -119,18 +118,16 @@ static u32 qce_auth_cfg(unsigned long flags, u32 key_size, u32 auth_size) cfg |= AUTH_KEY_SZ_AES256 << AUTH_KEY_SIZE_SHIFT; } - if (IS_SHA1(flags) || IS_SHA1_HMAC(flags)) - cfg |= AUTH_SIZE_SHA1 << AUTH_SIZE_SHIFT; - else if (IS_SHA256(flags) || IS_SHA256_HMAC(flags)) + if (IS_SHA256(flags) || IS_SHA256_HMAC(flags)) cfg |= AUTH_SIZE_SHA256 << AUTH_SIZE_SHIFT; else if (IS_CMAC(flags)) cfg |= AUTH_SIZE_ENUM_16_BYTES << AUTH_SIZE_SHIFT; else if (IS_CCM(flags)) cfg |= (auth_size - 1) << AUTH_SIZE_SHIFT; - if (IS_SHA1(flags) || IS_SHA256(flags)) + if (IS_SHA256(flags)) cfg |= AUTH_MODE_HASH << AUTH_MODE_SHIFT; - else if (IS_SHA1_HMAC(flags) || IS_SHA256_HMAC(flags)) + else if (IS_SHA256_HMAC(flags)) cfg |= AUTH_MODE_HMAC << AUTH_MODE_SHIFT; else if (IS_CCM(flags)) cfg |= AUTH_MODE_CCM << AUTH_MODE_SHIFT; @@ -195,7 +192,7 @@ static int qce_setup_regs_ahash(struct crypto_async_request *async_req) else qce_cpu_to_be32p_array(auth, rctx->digest, digestsize); - iv_words = (IS_SHA1(rctx->flags) || IS_SHA1_HMAC(rctx->flags)) ? 5 : 8; + iv_words = 8; qce_write_array(qce, REG_AUTH_IV0, (u32 *)auth, iv_words); if (rctx->first_blk) @@ -245,19 +242,8 @@ static u32 qce_encr_cfg(unsigned long flags, u32 aes_key_size) if (IS_AES(flags)) cfg |= ENCR_ALG_AES << ENCR_ALG_SHIFT; - else if (IS_DES(flags) || IS_3DES(flags)) - cfg |= ENCR_ALG_DES << ENCR_ALG_SHIFT; - - if (IS_DES(flags)) - cfg |= ENCR_KEY_SZ_DES << ENCR_KEY_SZ_SHIFT; - - if (IS_3DES(flags)) - cfg |= ENCR_KEY_SZ_3DES << ENCR_KEY_SZ_SHIFT; switch (flags & QCE_MODE_MASK) { - case QCE_MODE_ECB: - cfg |= ENCR_MODE_ECB << ENCR_MODE_SHIFT; - break; case QCE_MODE_CBC: cfg |= ENCR_MODE_CBC << ENCR_MODE_SHIFT; break; @@ -342,13 +328,7 @@ static int qce_setup_regs_skcipher(struct crypto_async_request *async_req) encr_cfg = qce_encr_cfg(flags, keylen); - if (IS_DES(flags)) { - enciv_words = 2; - enckey_words = 2; - } else if (IS_3DES(flags)) { - enciv_words = 2; - enckey_words = 6; - } else if (IS_AES(flags)) { + if (IS_AES(flags)) { if (IS_XTS(flags)) qce_xtskey(qce, ctx->enc_key, ctx->enc_keylen, rctx->cryptlen); @@ -359,14 +339,12 @@ static int qce_setup_regs_skcipher(struct crypto_async_request *async_req) qce_write_array(qce, REG_ENCR_KEY0, (u32 *)enckey, enckey_words); - if (!IS_ECB(flags)) { - if (IS_XTS(flags)) - qce_xts_swapiv(enciv, rctx->iv, ivsize); - else - qce_cpu_to_be32p_array(enciv, rctx->iv, ivsize); + if (IS_XTS(flags)) + qce_xts_swapiv(enciv, rctx->iv, ivsize); + else + qce_cpu_to_be32p_array(enciv, rctx->iv, ivsize); - qce_write_array(qce, REG_CNTR0_IV0, (u32 *)enciv, enciv_words); - } + qce_write_array(qce, REG_CNTR0_IV0, (u32 *)enciv, enciv_words); if (IS_ENCRYPT(flags)) encr_cfg |= BIT(ENCODE_SHIFT); @@ -393,10 +371,6 @@ static int qce_setup_regs_skcipher(struct crypto_async_request *async_req) #endif #ifdef CONFIG_CRYPTO_DEV_QCE_AEAD -static const u32 std_iv_sha1[SHA256_DIGEST_SIZE / sizeof(u32)] = { - SHA1_H0, SHA1_H1, SHA1_H2, SHA1_H3, SHA1_H4, 0, 0, 0 -}; - static const u32 std_iv_sha256[SHA256_DIGEST_SIZE / sizeof(u32)] = { SHA256_H0, SHA256_H1, SHA256_H2, SHA256_H3, SHA256_H4, SHA256_H5, SHA256_H6, SHA256_H7 @@ -473,13 +447,8 @@ static int qce_setup_regs_aead(struct crypto_async_request *async_req) /* Write initial authentication IV only for HMAC algorithms */ if (IS_SHA_HMAC(rctx->flags)) { /* Write default authentication iv */ - if (IS_SHA1_HMAC(rctx->flags)) { - auth_ivsize = SHA1_DIGEST_SIZE; - memcpy(authiv, std_iv_sha1, auth_ivsize); - } else if (IS_SHA256_HMAC(rctx->flags)) { - auth_ivsize = SHA256_DIGEST_SIZE; - memcpy(authiv, std_iv_sha256, auth_ivsize); - } + auth_ivsize = SHA256_DIGEST_SIZE; + memcpy(authiv, std_iv_sha256, auth_ivsize); authiv_words = auth_ivsize / sizeof(u32); qce_write_array(qce, REG_AUTH_IV0, (u32 *)authiv, authiv_words); } else if (IS_CCM(rctx->flags)) { diff --git a/drivers/crypto/qce/common.h b/drivers/crypto/qce/common.h index 02e63ad9f2455..9cd2e6ed8bbb0 100644 --- a/drivers/crypto/qce/common.h +++ b/drivers/crypto/qce/common.h @@ -22,7 +22,7 @@ /* IV length in bytes */ #define QCE_AES_IV_LENGTH AES_BLOCK_SIZE -/* max of AES_BLOCK_SIZE, DES3_EDE_BLOCK_SIZE */ +/* max of AES_BLOCK_SIZE */ #define QCE_MAX_IV_SIZE AES_BLOCK_SIZE /* maximum nonce bytes */ @@ -33,14 +33,10 @@ #define QCE_MAX_ALIGN_SIZE 64 /* cipher algorithms */ -#define QCE_ALG_DES BIT(0) -#define QCE_ALG_3DES BIT(1) #define QCE_ALG_AES BIT(2) /* hash and hmac algorithms */ -#define QCE_HASH_SHA1 BIT(3) #define QCE_HASH_SHA256 BIT(4) -#define QCE_HASH_SHA1_HMAC BIT(5) #define QCE_HASH_SHA256_HMAC BIT(6) #define QCE_HASH_AES_CMAC BIT(7) @@ -58,21 +54,15 @@ #define QCE_ENCRYPT BIT(30) #define QCE_DECRYPT BIT(31) -#define IS_DES(flags) (flags & QCE_ALG_DES) -#define IS_3DES(flags) (flags & QCE_ALG_3DES) #define IS_AES(flags) (flags & QCE_ALG_AES) -#define IS_SHA1(flags) (flags & QCE_HASH_SHA1) #define IS_SHA256(flags) (flags & QCE_HASH_SHA256) -#define IS_SHA1_HMAC(flags) (flags & QCE_HASH_SHA1_HMAC) #define IS_SHA256_HMAC(flags) (flags & QCE_HASH_SHA256_HMAC) #define IS_CMAC(flags) (flags & QCE_HASH_AES_CMAC) -#define IS_SHA(flags) (IS_SHA1(flags) || IS_SHA256(flags)) -#define IS_SHA_HMAC(flags) \ - (IS_SHA1_HMAC(flags) || IS_SHA256_HMAC(flags)) +#define IS_SHA(flags) IS_SHA256(flags) +#define IS_SHA_HMAC(flags) IS_SHA256_HMAC(flags) #define IS_CBC(mode) (mode & QCE_MODE_CBC) -#define IS_ECB(mode) (mode & QCE_MODE_ECB) #define IS_CTR(mode) (mode & QCE_MODE_CTR) #define IS_XTS(mode) (mode & QCE_MODE_XTS) #define IS_CCM(mode) (mode & QCE_MODE_CCM) diff --git a/drivers/crypto/qce/regs-v5.h b/drivers/crypto/qce/regs-v5.h index d59ed27989062..431a7db1a4e72 100644 --- a/drivers/crypto/qce/regs-v5.h +++ b/drivers/crypto/qce/regs-v5.h @@ -203,7 +203,6 @@ #define AUTH_SIZE_SHIFT 9 #define AUTH_SIZE_MASK GENMASK(13, 9) -#define AUTH_SIZE_SHA1 0 #define AUTH_SIZE_SHA256 1 #define AUTH_SIZE_ENUM_1_BYTES 0 #define AUTH_SIZE_ENUM_2_BYTES 1 @@ -284,15 +283,12 @@ #define ENCR_KEY_SZ_SHIFT 3 #define ENCR_KEY_SZ_MASK GENMASK(5, 3) -#define ENCR_KEY_SZ_DES 0 -#define ENCR_KEY_SZ_3DES 1 #define ENCR_KEY_SZ_AES128 0 #define ENCR_KEY_SZ_AES256 2 #define ENCR_ALG_SHIFT 0 #define ENCR_ALG_MASK GENMASK(2, 0) #define ENCR_ALG_NONE 0 -#define ENCR_ALG_DES 1 #define ENCR_ALG_AES 2 #define ENCR_ALG_KASUMI 4 #define ENCR_ALG_SNOW_3G 5 diff --git a/drivers/crypto/qce/sha.c b/drivers/crypto/qce/sha.c index 508b4c18d2119..44659bf0dc891 100644 --- a/drivers/crypto/qce/sha.c +++ b/drivers/crypto/qce/sha.c @@ -25,10 +25,6 @@ struct qce_sha_saved_state { static LIST_HEAD(ahash_algs); -static const u32 std_iv_sha1[SHA256_DIGEST_SIZE / sizeof(u32)] = { - SHA1_H0, SHA1_H1, SHA1_H2, SHA1_H3, SHA1_H4, 0, 0, 0 -}; - static const u32 std_iv_sha256[SHA256_DIGEST_SIZE / sizeof(u32)] = { SHA256_H0, SHA256_H1, SHA256_H2, SHA256_H3, SHA256_H4, SHA256_H5, SHA256_H6, SHA256_H7 @@ -274,6 +270,36 @@ static int qce_ahash_update(struct ahash_request *req) return qce->async_req_enqueue(tmpl->qce, &req->base); } +/* + * BAM DMA cannot handle zero-length transfers. For plain hashes the result of + * an empty message is a known constant (hash_zero), for keyed HMAC it depends + * on the key, so compute it with the software fallback. + */ +static int qce_ahash_hmac_zero(struct ahash_request *req) +{ + struct crypto_ahash *tfm = crypto_ahash_reqtfm(req); + struct qce_sha_ctx *ctx = crypto_tfm_ctx(crypto_ahash_tfm(tfm)); + struct ahash_request *subreq; + struct crypto_wait wait; + struct scatterlist sg; + int ret; + + subreq = ahash_request_alloc(ctx->fallback, GFP_ATOMIC); + if (!subreq) + return -ENOMEM; + + crypto_init_wait(&wait); + ahash_request_set_callback(subreq, CRYPTO_TFM_REQ_MAY_BACKLOG, + crypto_req_done, &wait); + sg_init_one(&sg, NULL, 0); + ahash_request_set_crypt(subreq, &sg, req->result, 0); + + ret = crypto_wait_req(crypto_ahash_digest(subreq), &wait); + + ahash_request_free(subreq); + return ret; +} + static int qce_ahash_final(struct ahash_request *req) { struct qce_sha_reqctx *rctx = ahash_request_ctx_dma(req); @@ -284,6 +310,8 @@ static int qce_ahash_final(struct ahash_request *req) if (tmpl->hash_zero) memcpy(req->result, tmpl->hash_zero, tmpl->alg.ahash.halg.digestsize); + else if (IS_SHA_HMAC(rctx->flags)) + return qce_ahash_hmac_zero(req); return 0; } @@ -321,6 +349,8 @@ static int qce_ahash_digest(struct ahash_request *req) if (tmpl->hash_zero) memcpy(req->result, tmpl->hash_zero, tmpl->alg.ahash.halg.digestsize); + else if (IS_SHA_HMAC(rctx->flags)) + return qce_ahash_hmac_zero(req); return 0; } @@ -344,14 +374,23 @@ static int qce_ahash_hmac_setkey(struct crypto_ahash *tfm, const u8 *key, blocksize = crypto_tfm_alg_blocksize(crypto_ahash_tfm(tfm)); memset(ctx->authkey, 0, sizeof(ctx->authkey)); + /* + * Keep the software fallback keyed in sync - it is used for empty + * messages, which the DMA engine cannot process. + */ + crypto_ahash_clear_flags(ctx->fallback, CRYPTO_TFM_REQ_MASK); + crypto_ahash_set_flags(ctx->fallback, + crypto_ahash_get_flags(tfm) & CRYPTO_TFM_REQ_MASK); + ret = crypto_ahash_setkey(ctx->fallback, key, keylen); + if (ret) + return ret; + if (keylen <= blocksize) { memcpy(ctx->authkey, key, keylen); return 0; } - if (digestsize == SHA1_DIGEST_SIZE) - alg_name = "sha1-qce"; - else if (digestsize == SHA256_DIGEST_SIZE) + if (digestsize == SHA256_DIGEST_SIZE) alg_name = "sha256-qce"; else return -EINVAL; @@ -401,6 +440,36 @@ static int qce_ahash_cra_init(struct crypto_tfm *tfm) return 0; } +static int qce_ahash_hmac_cra_init(struct crypto_tfm *tfm) +{ + struct qce_sha_ctx *ctx = crypto_tfm_ctx(tfm); + struct crypto_ahash *fallback; + int ret; + + ret = qce_ahash_cra_init(tfm); + if (ret) + return ret; + + /* + * The fallback is used to compute HMACs of empty messages, which the + * DMA engine cannot process. + */ + fallback = crypto_alloc_ahash(crypto_tfm_alg_name(tfm), 0, + CRYPTO_ALG_NEED_FALLBACK); + if (IS_ERR(fallback)) + return PTR_ERR(fallback); + + ctx->fallback = fallback; + return 0; +} + +static void qce_ahash_hmac_cra_exit(struct crypto_tfm *tfm) +{ + struct qce_sha_ctx *ctx = crypto_tfm_ctx(tfm); + + crypto_free_ahash(ctx->fallback); +} + struct qce_ahash_def { unsigned long flags; const char *name; @@ -412,15 +481,6 @@ struct qce_ahash_def { }; static const struct qce_ahash_def ahash_def[] = { - { - .flags = QCE_HASH_SHA1, - .name = "sha1", - .drv_name = "sha1-qce", - .digestsize = SHA1_DIGEST_SIZE, - .blocksize = SHA1_BLOCK_SIZE, - .statesize = sizeof(struct qce_sha_saved_state), - .std_iv = std_iv_sha1, - }, { .flags = QCE_HASH_SHA256, .name = "sha256", @@ -430,15 +490,6 @@ static const struct qce_ahash_def ahash_def[] = { .statesize = sizeof(struct qce_sha_saved_state), .std_iv = std_iv_sha256, }, - { - .flags = QCE_HASH_SHA1_HMAC, - .name = "hmac(sha1)", - .drv_name = "hmac-sha1-qce", - .digestsize = SHA1_DIGEST_SIZE, - .blocksize = SHA1_BLOCK_SIZE, - .statesize = sizeof(struct qce_sha_saved_state), - .std_iv = std_iv_sha1, - }, { .flags = QCE_HASH_SHA256_HMAC, .name = "hmac(sha256)", @@ -476,9 +527,7 @@ static int qce_ahash_register_one(const struct qce_ahash_def *def, alg->halg.digestsize = def->digestsize; alg->halg.statesize = def->statesize; - if (IS_SHA1(def->flags)) - tmpl->hash_zero = sha1_zero_message_hash; - else if (IS_SHA256(def->flags)) + if (IS_SHA256(def->flags)) tmpl->hash_zero = sha256_zero_message_hash; base = &alg->halg.base; @@ -488,7 +537,14 @@ static int qce_ahash_register_one(const struct qce_ahash_def *def, base->cra_ctxsize = sizeof(struct qce_sha_ctx); base->cra_alignmask = 0; base->cra_module = THIS_MODULE; - base->cra_init = qce_ahash_cra_init; + + if (IS_SHA_HMAC(def->flags)) { + base->cra_flags |= CRYPTO_ALG_NEED_FALLBACK; + base->cra_init = qce_ahash_hmac_cra_init; + base->cra_exit = qce_ahash_hmac_cra_exit; + } else { + base->cra_init = qce_ahash_cra_init; + } strscpy(base->cra_name, def->name); strscpy(base->cra_driver_name, def->drv_name); diff --git a/drivers/crypto/qce/sha.h b/drivers/crypto/qce/sha.h index a22695361f165..2fa173ff2b2ec 100644 --- a/drivers/crypto/qce/sha.h +++ b/drivers/crypto/qce/sha.h @@ -7,7 +7,6 @@ #define _SHA_H_ #include -#include #include #include "common.h" @@ -18,6 +17,7 @@ struct qce_sha_ctx { u8 authkey[QCE_SHA_MAX_BLOCKSIZE]; + struct crypto_ahash *fallback; }; /** diff --git a/drivers/crypto/qce/skcipher.c b/drivers/crypto/qce/skcipher.c index 78fe3c3611cfe..286028b39f8fd 100644 --- a/drivers/crypto/qce/skcipher.c +++ b/drivers/crypto/qce/skcipher.c @@ -11,8 +11,8 @@ #include #include #include -#include #include +#include #include "cipher.h" @@ -34,6 +34,7 @@ static void qce_skcipher_done(void *data) struct qce_device *qce = tmpl->qce; struct qce_result_dump *result_buf = qce->dma.result_buf; enum dma_data_direction dir_src, dir_dst; + unsigned int blocks; u32 status; int error; bool diff_dst; @@ -57,7 +58,21 @@ static void qce_skcipher_done(void *data) if (error < 0) dev_dbg(qce->dev, "skcipher operation error (%x)\n", status); - memcpy(rctx->iv, result_buf->encr_cntr_iv, rctx->ivsize); + if (IS_CTR(rctx->flags)) { + /* + * QCE hardware does not increment the counter for a partial + * final block. Increment it in software so that iv_out + * reflects the correct next counter value expected by the CTR + * mode. + */ + blocks = DIV_ROUND_UP(rctx->cryptlen, AES_BLOCK_SIZE); + + while (blocks--) + crypto_inc(rctx->iv, rctx->ivsize); + } else { + memcpy(rctx->iv, result_buf->encr_cntr_iv, rctx->ivsize); + } + qce->async_req_done(tmpl->qce, error); } @@ -180,14 +195,17 @@ static int qce_skcipher_setkey(struct crypto_skcipher *ablk, const u8 *key, if (!key || !keylen) return -EINVAL; - /* - * AES XTS key1 = key2 not supported by crypto engine. - * Revisit to request a fallback cipher in this case. - */ if (IS_XTS(flags)) { + ret = xts_verify_key(ablk, key, keylen); + if (ret) + return ret; __keylen = keylen >> 1; - if (!memcmp(key, key + __keylen, __keylen)) - return -ENOKEY; + /* + * QCE does not support key1 == key2 for XTS. + * Use fallback cipher in this case. + */ + ctx->use_fallback = !crypto_memneq(key, key + __keylen, + __keylen); } else { __keylen = keylen; } @@ -209,51 +227,6 @@ static int qce_skcipher_setkey(struct crypto_skcipher *ablk, const u8 *key, return ret; } -static int qce_des_setkey(struct crypto_skcipher *ablk, const u8 *key, - unsigned int keylen) -{ - struct qce_cipher_ctx *ctx = crypto_skcipher_ctx(ablk); - int err; - - err = verify_skcipher_des_key(ablk, key); - if (err) - return err; - - ctx->enc_keylen = keylen; - memcpy(ctx->enc_key, key, keylen); - return 0; -} - -static int qce_des3_setkey(struct crypto_skcipher *ablk, const u8 *key, - unsigned int keylen) -{ - struct qce_cipher_ctx *ctx = crypto_skcipher_ctx(ablk); - u32 _key[6]; - int err; - - err = verify_skcipher_des3_key(ablk, key); - if (err) - return err; - - /* - * The crypto engine does not support any two keys - * being the same for triple des algorithms. The - * verify_skcipher_des3_key does not check for all the - * below conditions. Return -ENOKEY in case any two keys - * are the same. Revisit to see if a fallback cipher - * is needed to handle this condition. - */ - memcpy(_key, key, DES3_EDE_KEY_SIZE); - if (!((_key[0] ^ _key[2]) | (_key[1] ^ _key[3])) || - !((_key[2] ^ _key[4]) | (_key[3] ^ _key[5])) || - !((_key[0] ^ _key[4]) | (_key[1] ^ _key[5]))) - return -ENOKEY; - - ctx->enc_keylen = keylen; - memcpy(ctx->enc_key, key, keylen); - return 0; -} - static int qce_skcipher_crypt(struct skcipher_request *req, int encrypt) { struct crypto_skcipher *tfm = crypto_skcipher_reqtfm(req); @@ -269,14 +242,18 @@ static int qce_skcipher_crypt(struct skcipher_request *req, int encrypt) keylen = IS_XTS(rctx->flags) ? ctx->enc_keylen >> 1 : ctx->enc_keylen; /* CE does not handle 0 length messages */ - if (!req->cryptlen) + if (!req->cryptlen) { + /* XTS requires at least one full block of data */ + if (IS_XTS(rctx->flags)) + return -EINVAL; return 0; + } /* * ECB and CBC algorithms require message lengths to be * multiples of block size. */ - if (IS_ECB(rctx->flags) || IS_CBC(rctx->flags)) + if (IS_CBC(rctx->flags)) if (!IS_ALIGNED(req->cryptlen, blocksize)) return -EINVAL; @@ -287,12 +264,17 @@ static int qce_skcipher_crypt(struct skcipher_request *req, int encrypt) * AES-XTS request with len > QCE_SECTOR_SIZE and * is not a multiple of it.(Revisit this condition to check if it is * needed in all versions of CE) + * AES-CTR with a partial final block (the CE stalls waiting for a full + * block of input). + * AES-XTS with key1 == key2 (not supported by the CE). */ if (IS_AES(rctx->flags) && ((keylen != AES_KEYSIZE_128 && keylen != AES_KEYSIZE_256) || + (IS_CTR(rctx->flags) && !IS_ALIGNED(req->cryptlen, AES_BLOCK_SIZE)) || (IS_XTS(rctx->flags) && ((req->cryptlen <= aes_sw_max_len) || (req->cryptlen > QCE_SECTOR_SIZE && - req->cryptlen % QCE_SECTOR_SIZE))))) { + req->cryptlen % QCE_SECTOR_SIZE))) || + (IS_XTS(rctx->flags) && ctx->use_fallback))) { skcipher_request_set_tfm(&rctx->fallback_req, ctx->fallback); skcipher_request_set_callback(&rctx->fallback_req, req->base.flags, @@ -359,15 +341,6 @@ struct qce_skcipher_def { }; static const struct qce_skcipher_def skcipher_def[] = { - { - .flags = QCE_ALG_AES | QCE_MODE_ECB, - .name = "ecb(aes)", - .drv_name = "ecb-aes-qce", - .blocksize = AES_BLOCK_SIZE, - .ivsize = 0, - .min_keysize = AES_MIN_KEY_SIZE, - .max_keysize = AES_MAX_KEY_SIZE, - }, { .flags = QCE_ALG_AES | QCE_MODE_CBC, .name = "cbc(aes)", @@ -396,42 +369,6 @@ static const struct qce_skcipher_def skcipher_def[] = { .min_keysize = AES_MIN_KEY_SIZE * 2, .max_keysize = AES_MAX_KEY_SIZE * 2, }, - { - .flags = QCE_ALG_DES | QCE_MODE_ECB, - .name = "ecb(des)", - .drv_name = "ecb-des-qce", - .blocksize = DES_BLOCK_SIZE, - .ivsize = 0, - .min_keysize = DES_KEY_SIZE, - .max_keysize = DES_KEY_SIZE, - }, - { - .flags = QCE_ALG_DES | QCE_MODE_CBC, - .name = "cbc(des)", - .drv_name = "cbc-des-qce", - .blocksize = DES_BLOCK_SIZE, - .ivsize = DES_BLOCK_SIZE, - .min_keysize = DES_KEY_SIZE, - .max_keysize = DES_KEY_SIZE, - }, - { - .flags = QCE_ALG_3DES | QCE_MODE_ECB, - .name = "ecb(des3_ede)", - .drv_name = "ecb-3des-qce", - .blocksize = DES3_EDE_BLOCK_SIZE, - .ivsize = 0, - .min_keysize = DES3_EDE_KEY_SIZE, - .max_keysize = DES3_EDE_KEY_SIZE, - }, - { - .flags = QCE_ALG_3DES | QCE_MODE_CBC, - .name = "cbc(des3_ede)", - .drv_name = "cbc-3des-qce", - .blocksize = DES3_EDE_BLOCK_SIZE, - .ivsize = DES3_EDE_BLOCK_SIZE, - .min_keysize = DES3_EDE_KEY_SIZE, - .max_keysize = DES3_EDE_KEY_SIZE, - }, }; static int qce_skcipher_register_one(const struct qce_skcipher_def *def, @@ -455,9 +392,7 @@ static int qce_skcipher_register_one(const struct qce_skcipher_def *def, alg->ivsize = def->ivsize; alg->min_keysize = def->min_keysize; alg->max_keysize = def->max_keysize; - alg->setkey = IS_3DES(def->flags) ? qce_des3_setkey : - IS_DES(def->flags) ? qce_des_setkey : - qce_skcipher_setkey; + alg->setkey = qce_skcipher_setkey; alg->encrypt = qce_skcipher_encrypt; alg->decrypt = qce_skcipher_decrypt;