diff options
Diffstat (limited to 'drivers/crypto/ccree/cc_cipher.c')
-rw-r--r-- | drivers/crypto/ccree/cc_cipher.c | 170 |
1 files changed, 91 insertions, 79 deletions
diff --git a/drivers/crypto/ccree/cc_cipher.c b/drivers/crypto/ccree/cc_cipher.c index d2810c183b73..7623b29911af 100644 --- a/drivers/crypto/ccree/cc_cipher.c +++ b/drivers/crypto/ccree/cc_cipher.c @@ -19,8 +19,6 @@ #define template_skcipher template_u.skcipher -#define CC_MIN_AES_XTS_SIZE 0x10 -#define CC_MAX_AES_XTS_SIZE 0x2000 struct cc_cipher_handle { struct list_head alg_list; }; @@ -98,8 +96,7 @@ static int validate_data_size(struct cc_cipher_ctx *ctx_p, case S_DIN_to_AES: switch (ctx_p->cipher_mode) { case DRV_CIPHER_XTS: - if (size >= CC_MIN_AES_XTS_SIZE && - size <= CC_MAX_AES_XTS_SIZE && + if (size >= AES_BLOCK_SIZE && IS_ALIGNED(size, AES_BLOCK_SIZE)) return 0; break; @@ -593,34 +590,82 @@ static void cc_setup_cipher_data(struct crypto_tfm *tfm, } } +/* + * Update a CTR-AES 128 bit counter + */ +static void cc_update_ctr(u8 *ctr, unsigned int increment) +{ + if (IS_ENABLED(CONFIG_HAVE_EFFICIENT_UNALIGNED_ACCESS) || + IS_ALIGNED((unsigned long)ctr, 8)) { + + __be64 *high_be = (__be64 *)ctr; + __be64 *low_be = high_be + 1; + u64 orig_low = __be64_to_cpu(*low_be); + u64 new_low = orig_low + (u64)increment; + + *low_be = __cpu_to_be64(new_low); + + if (new_low < orig_low) + *high_be = __cpu_to_be64(__be64_to_cpu(*high_be) + 1); + } else { + u8 *pos = (ctr + AES_BLOCK_SIZE); + u8 val; + unsigned int size; + + for (; increment; increment--) + for (size = AES_BLOCK_SIZE; size; size--) { + val = *--pos + 1; + *pos = val; + if (val) + break; + } + } +} + static void cc_cipher_complete(struct device *dev, void *cc_req, int err) { struct skcipher_request *req = (struct skcipher_request *)cc_req; struct scatterlist *dst = req->dst; struct scatterlist *src = req->src; struct cipher_req_ctx *req_ctx = skcipher_request_ctx(req); - struct crypto_skcipher *tfm = crypto_skcipher_reqtfm(req); - unsigned int ivsize = crypto_skcipher_ivsize(tfm); + struct crypto_skcipher *sk_tfm = crypto_skcipher_reqtfm(req); + struct crypto_tfm *tfm = crypto_skcipher_tfm(sk_tfm); + struct cc_cipher_ctx *ctx_p = crypto_tfm_ctx(tfm); + unsigned int ivsize = crypto_skcipher_ivsize(sk_tfm); + unsigned int len; - cc_unmap_cipher_request(dev, req_ctx, ivsize, src, dst); - kzfree(req_ctx->iv); + switch (ctx_p->cipher_mode) { + case DRV_CIPHER_CBC: + /* + * The crypto API expects us to set the req->iv to the last + * ciphertext block. For encrypt, simply copy from the result. + * For decrypt, we must copy from a saved buffer since this + * could be an in-place decryption operation and the src is + * lost by this point. + */ + if (req_ctx->gen_ctx.op_type == DRV_CRYPTO_DIRECTION_DECRYPT) { + memcpy(req->iv, req_ctx->backup_info, ivsize); + kzfree(req_ctx->backup_info); + } else if (!err) { + len = req->cryptlen - ivsize; + scatterwalk_map_and_copy(req->iv, req->dst, len, + ivsize, 0); + } + break; - /* - * The crypto API expects us to set the req->iv to the last - * ciphertext block. For encrypt, simply copy from the result. - * For decrypt, we must copy from a saved buffer since this - * could be an in-place decryption operation and the src is - * lost by this point. - */ - if (req_ctx->gen_ctx.op_type == DRV_CRYPTO_DIRECTION_DECRYPT) { - memcpy(req->iv, req_ctx->backup_info, ivsize); - kzfree(req_ctx->backup_info); - } else if (!err) { - scatterwalk_map_and_copy(req->iv, req->dst, - (req->cryptlen - ivsize), - ivsize, 0); + case DRV_CIPHER_CTR: + /* Compute the counter of the last block */ + len = ALIGN(req->cryptlen, AES_BLOCK_SIZE) / AES_BLOCK_SIZE; + cc_update_ctr((u8 *)req->iv, len); + break; + + default: + break; } + cc_unmap_cipher_request(dev, req_ctx, ivsize, src, dst); + kzfree(req_ctx->iv); + skcipher_request_complete(req, err); } @@ -639,7 +684,7 @@ static int cc_cipher_process(struct skcipher_request *req, struct device *dev = drvdata_to_dev(ctx_p->drvdata); struct cc_hw_desc desc[MAX_ABLKCIPHER_SEQ_LEN]; struct cc_crypto_req cc_req = {}; - int rc, cts_restore_flag = 0; + int rc; unsigned int seq_len = 0; gfp_t flags = cc_gfp_flags(&req->base); @@ -671,23 +716,10 @@ static int cc_cipher_process(struct skcipher_request *req, goto exit_process; } - /*For CTS in case of data size aligned to 16 use CBC mode*/ - if (((nbytes % AES_BLOCK_SIZE) == 0) && - ctx_p->cipher_mode == DRV_CIPHER_CBC_CTS) { - ctx_p->cipher_mode = DRV_CIPHER_CBC; - cts_restore_flag = 1; - } - /* Setup request structure */ cc_req.user_cb = (void *)cc_cipher_complete; cc_req.user_arg = (void *)req; -#ifdef ENABLE_CYCLE_COUNT - cc_req.op_type = (direction == DRV_CRYPTO_DIRECTION_DECRYPT) ? - STAT_OP_TYPE_DECODE : STAT_OP_TYPE_ENCODE; - -#endif - /* Setup request context */ req_ctx->gen_ctx.op_type = direction; @@ -708,14 +740,6 @@ static int cc_cipher_process(struct skcipher_request *req, cc_setup_cipher_data(tfm, req_ctx, dst, src, nbytes, req, desc, &seq_len); - /* do we need to generate IV? */ - if (req_ctx->is_giv) { - cc_req.ivgen_dma_addr[0] = req_ctx->gen_ctx.iv_dma_addr; - cc_req.ivgen_dma_addr_len = 1; - /* set the IV size (8/16 B long)*/ - cc_req.ivgen_size = ivsize; - } - /* STAT_PHASE_3: Lock HW and push sequence */ rc = cc_send_request(ctx_p->drvdata, &cc_req, desc, seq_len, @@ -728,9 +752,6 @@ static int cc_cipher_process(struct skcipher_request *req, } exit_process: - if (cts_restore_flag) - ctx_p->cipher_mode = DRV_CIPHER_CBC_CTS; - if (rc != -EINPROGRESS && rc != -EBUSY) { kzfree(req_ctx->backup_info); kzfree(req_ctx->iv); @@ -743,8 +764,7 @@ static int cc_cipher_encrypt(struct skcipher_request *req) { struct cipher_req_ctx *req_ctx = skcipher_request_ctx(req); - req_ctx->is_giv = false; - req_ctx->backup_info = NULL; + memset(req_ctx, 0, sizeof(*req_ctx)); return cc_cipher_process(req, DRV_CRYPTO_DIRECTION_ENCRYPT); } @@ -752,21 +772,28 @@ static int cc_cipher_encrypt(struct skcipher_request *req) static int cc_cipher_decrypt(struct skcipher_request *req) { struct crypto_skcipher *sk_tfm = crypto_skcipher_reqtfm(req); + struct crypto_tfm *tfm = crypto_skcipher_tfm(sk_tfm); + struct cc_cipher_ctx *ctx_p = crypto_tfm_ctx(tfm); struct cipher_req_ctx *req_ctx = skcipher_request_ctx(req); unsigned int ivsize = crypto_skcipher_ivsize(sk_tfm); gfp_t flags = cc_gfp_flags(&req->base); + unsigned int len; - /* - * Allocate and save the last IV sized bytes of the source, which will - * be lost in case of in-place decryption and might be needed for CTS. - */ - req_ctx->backup_info = kmalloc(ivsize, flags); - if (!req_ctx->backup_info) - return -ENOMEM; + memset(req_ctx, 0, sizeof(*req_ctx)); + + if (ctx_p->cipher_mode == DRV_CIPHER_CBC) { + + /* Allocate and save the last IV sized bytes of the source, + * which will be lost in case of in-place decryption. + */ + req_ctx->backup_info = kzalloc(ivsize, flags); + if (!req_ctx->backup_info) + return -ENOMEM; - scatterwalk_map_and_copy(req_ctx->backup_info, req->src, - (req->cryptlen - ivsize), ivsize, 0); - req_ctx->is_giv = false; + len = req->cryptlen - ivsize; + scatterwalk_map_and_copy(req_ctx->backup_info, req->src, len, + ivsize, 0); + } return cc_cipher_process(req, DRV_CRYPTO_DIRECTION_DECRYPT); } @@ -927,7 +954,6 @@ static const struct cc_alg_template skcipher_algs[] = { .name = "ecb(paes)", .driver_name = "ecb-paes-ccree", .blocksize = AES_BLOCK_SIZE, - .type = CRYPTO_ALG_TYPE_ABLKCIPHER, .template_skcipher = { .setkey = cc_cipher_sethkey, .encrypt = cc_cipher_encrypt, @@ -944,7 +970,6 @@ static const struct cc_alg_template skcipher_algs[] = { .name = "cbc(paes)", .driver_name = "cbc-paes-ccree", .blocksize = AES_BLOCK_SIZE, - .type = CRYPTO_ALG_TYPE_ABLKCIPHER, .template_skcipher = { .setkey = cc_cipher_sethkey, .encrypt = cc_cipher_encrypt, @@ -961,7 +986,6 @@ static const struct cc_alg_template skcipher_algs[] = { .name = "ofb(paes)", .driver_name = "ofb-paes-ccree", .blocksize = AES_BLOCK_SIZE, - .type = CRYPTO_ALG_TYPE_ABLKCIPHER, .template_skcipher = { .setkey = cc_cipher_sethkey, .encrypt = cc_cipher_encrypt, @@ -975,10 +999,9 @@ static const struct cc_alg_template skcipher_algs[] = { .min_hw_rev = CC_HW_REV_712, }, { - .name = "cts1(cbc(paes))", - .driver_name = "cts1-cbc-paes-ccree", + .name = "cts(cbc(paes))", + .driver_name = "cts-cbc-paes-ccree", .blocksize = AES_BLOCK_SIZE, - .type = CRYPTO_ALG_TYPE_ABLKCIPHER, .template_skcipher = { .setkey = cc_cipher_sethkey, .encrypt = cc_cipher_encrypt, @@ -995,7 +1018,6 @@ static const struct cc_alg_template skcipher_algs[] = { .name = "ctr(paes)", .driver_name = "ctr-paes-ccree", .blocksize = 1, - .type = CRYPTO_ALG_TYPE_ABLKCIPHER, .template_skcipher = { .setkey = cc_cipher_sethkey, .encrypt = cc_cipher_encrypt, @@ -1162,7 +1184,6 @@ static const struct cc_alg_template skcipher_algs[] = { .name = "ecb(aes)", .driver_name = "ecb-aes-ccree", .blocksize = AES_BLOCK_SIZE, - .type = CRYPTO_ALG_TYPE_ABLKCIPHER, .template_skcipher = { .setkey = cc_cipher_setkey, .encrypt = cc_cipher_encrypt, @@ -1179,7 +1200,6 @@ static const struct cc_alg_template skcipher_algs[] = { .name = "cbc(aes)", .driver_name = "cbc-aes-ccree", .blocksize = AES_BLOCK_SIZE, - .type = CRYPTO_ALG_TYPE_ABLKCIPHER, .template_skcipher = { .setkey = cc_cipher_setkey, .encrypt = cc_cipher_encrypt, @@ -1196,7 +1216,6 @@ static const struct cc_alg_template skcipher_algs[] = { .name = "ofb(aes)", .driver_name = "ofb-aes-ccree", .blocksize = AES_BLOCK_SIZE, - .type = CRYPTO_ALG_TYPE_ABLKCIPHER, .template_skcipher = { .setkey = cc_cipher_setkey, .encrypt = cc_cipher_encrypt, @@ -1210,10 +1229,9 @@ static const struct cc_alg_template skcipher_algs[] = { .min_hw_rev = CC_HW_REV_630, }, { - .name = "cts1(cbc(aes))", - .driver_name = "cts1-cbc-aes-ccree", + .name = "cts(cbc(aes))", + .driver_name = "cts-cbc-aes-ccree", .blocksize = AES_BLOCK_SIZE, - .type = CRYPTO_ALG_TYPE_ABLKCIPHER, .template_skcipher = { .setkey = cc_cipher_setkey, .encrypt = cc_cipher_encrypt, @@ -1230,7 +1248,6 @@ static const struct cc_alg_template skcipher_algs[] = { .name = "ctr(aes)", .driver_name = "ctr-aes-ccree", .blocksize = 1, - .type = CRYPTO_ALG_TYPE_ABLKCIPHER, .template_skcipher = { .setkey = cc_cipher_setkey, .encrypt = cc_cipher_encrypt, @@ -1247,7 +1264,6 @@ static const struct cc_alg_template skcipher_algs[] = { .name = "cbc(des3_ede)", .driver_name = "cbc-3des-ccree", .blocksize = DES3_EDE_BLOCK_SIZE, - .type = CRYPTO_ALG_TYPE_ABLKCIPHER, .template_skcipher = { .setkey = cc_cipher_setkey, .encrypt = cc_cipher_encrypt, @@ -1264,7 +1280,6 @@ static const struct cc_alg_template skcipher_algs[] = { .name = "ecb(des3_ede)", .driver_name = "ecb-3des-ccree", .blocksize = DES3_EDE_BLOCK_SIZE, - .type = CRYPTO_ALG_TYPE_ABLKCIPHER, .template_skcipher = { .setkey = cc_cipher_setkey, .encrypt = cc_cipher_encrypt, @@ -1281,7 +1296,6 @@ static const struct cc_alg_template skcipher_algs[] = { .name = "cbc(des)", .driver_name = "cbc-des-ccree", .blocksize = DES_BLOCK_SIZE, - .type = CRYPTO_ALG_TYPE_ABLKCIPHER, .template_skcipher = { .setkey = cc_cipher_setkey, .encrypt = cc_cipher_encrypt, @@ -1298,7 +1312,6 @@ static const struct cc_alg_template skcipher_algs[] = { .name = "ecb(des)", .driver_name = "ecb-des-ccree", .blocksize = DES_BLOCK_SIZE, - .type = CRYPTO_ALG_TYPE_ABLKCIPHER, .template_skcipher = { .setkey = cc_cipher_setkey, .encrypt = cc_cipher_encrypt, @@ -1338,8 +1351,7 @@ static struct cc_crypto_alg *cc_create_alg(const struct cc_alg_template *tmpl, alg->base.cra_init = cc_cipher_init; alg->base.cra_exit = cc_cipher_exit; - alg->base.cra_flags = CRYPTO_ALG_ASYNC | CRYPTO_ALG_KERN_DRIVER_ONLY | - CRYPTO_ALG_TYPE_SKCIPHER; + alg->base.cra_flags = CRYPTO_ALG_ASYNC | CRYPTO_ALG_KERN_DRIVER_ONLY; t_alg->cipher_mode = tmpl->cipher_mode; t_alg->flow_mode = tmpl->flow_mode; |