Path: blob/master/drivers/crypto/cavium/cpt/cptvf_algs.c
26285 views
// SPDX-License-Identifier: GPL-2.0-only12/*3* Copyright (C) 2016 Cavium, Inc.4*/56#include <crypto/aes.h>7#include <crypto/algapi.h>8#include <crypto/authenc.h>9#include <crypto/internal/des.h>10#include <crypto/xts.h>11#include <linux/crypto.h>12#include <linux/err.h>13#include <linux/list.h>14#include <linux/scatterlist.h>1516#include "cptvf.h"17#include "cptvf_algs.h"1819struct cpt_device_handle {20void *cdev[MAX_DEVICES];21u32 dev_count;22};2324static struct cpt_device_handle dev_handle;2526static void cvm_callback(u32 status, void *arg)27{28struct crypto_async_request *req = (struct crypto_async_request *)arg;2930crypto_request_complete(req, !status);31}3233static inline void update_input_iv(struct cpt_request_info *req_info,34u8 *iv, u32 enc_iv_len,35u32 *argcnt)36{37/* Setting the iv information */38req_info->in[*argcnt].vptr = (void *)iv;39req_info->in[*argcnt].size = enc_iv_len;40req_info->req.dlen += enc_iv_len;4142++(*argcnt);43}4445static inline void update_output_iv(struct cpt_request_info *req_info,46u8 *iv, u32 enc_iv_len,47u32 *argcnt)48{49/* Setting the iv information */50req_info->out[*argcnt].vptr = (void *)iv;51req_info->out[*argcnt].size = enc_iv_len;52req_info->rlen += enc_iv_len;5354++(*argcnt);55}5657static inline void update_input_data(struct cpt_request_info *req_info,58struct scatterlist *inp_sg,59u32 nbytes, u32 *argcnt)60{61req_info->req.dlen += nbytes;6263while (nbytes) {64u32 len = min(nbytes, inp_sg->length);65u8 *ptr = sg_virt(inp_sg);6667req_info->in[*argcnt].vptr = (void *)ptr;68req_info->in[*argcnt].size = len;69nbytes -= len;7071++(*argcnt);72++inp_sg;73}74}7576static inline void update_output_data(struct cpt_request_info *req_info,77struct scatterlist *outp_sg,78u32 nbytes, u32 *argcnt)79{80req_info->rlen += nbytes;8182while (nbytes) {83u32 len = min(nbytes, outp_sg->length);84u8 *ptr = sg_virt(outp_sg);8586req_info->out[*argcnt].vptr = (void *)ptr;87req_info->out[*argcnt].size = len;88nbytes -= len;89++(*argcnt);90++outp_sg;91}92}9394static inline u32 create_ctx_hdr(struct skcipher_request *req, u32 enc,95u32 *argcnt)96{97struct crypto_skcipher *tfm = crypto_skcipher_reqtfm(req);98struct cvm_enc_ctx *ctx = crypto_skcipher_ctx(tfm);99struct cvm_req_ctx *rctx = skcipher_request_ctx_dma(req);100struct fc_context *fctx = &rctx->fctx;101u32 enc_iv_len = crypto_skcipher_ivsize(tfm);102struct cpt_request_info *req_info = &rctx->cpt_req;103__be64 *ctrl_flags = NULL;104__be64 *offset_control;105106req_info->ctrl.s.grp = 0;107req_info->ctrl.s.dma_mode = DMA_GATHER_SCATTER;108req_info->ctrl.s.se_req = SE_CORE_REQ;109110req_info->req.opcode.s.major = MAJOR_OP_FC |111DMA_MODE_FLAG(DMA_GATHER_SCATTER);112if (enc)113req_info->req.opcode.s.minor = 2;114else115req_info->req.opcode.s.minor = 3;116117req_info->req.param1 = req->cryptlen; /* Encryption Data length */118req_info->req.param2 = 0; /*Auth data length */119120fctx->enc.enc_ctrl.e.enc_cipher = ctx->cipher_type;121fctx->enc.enc_ctrl.e.aes_key = ctx->key_type;122fctx->enc.enc_ctrl.e.iv_source = FROM_DPTR;123124if (ctx->cipher_type == AES_XTS)125memcpy(fctx->enc.encr_key, ctx->enc_key, ctx->key_len * 2);126else127memcpy(fctx->enc.encr_key, ctx->enc_key, ctx->key_len);128ctrl_flags = (__be64 *)&fctx->enc.enc_ctrl.flags;129*ctrl_flags = cpu_to_be64(fctx->enc.enc_ctrl.flags);130131offset_control = (__be64 *)&rctx->control_word;132*offset_control = cpu_to_be64(((u64)(enc_iv_len) << 16));133/* Storing Packet Data Information in offset134* Control Word First 8 bytes135*/136req_info->in[*argcnt].vptr = (u8 *)offset_control;137req_info->in[*argcnt].size = CONTROL_WORD_LEN;138req_info->req.dlen += CONTROL_WORD_LEN;139++(*argcnt);140141req_info->in[*argcnt].vptr = (u8 *)fctx;142req_info->in[*argcnt].size = sizeof(struct fc_context);143req_info->req.dlen += sizeof(struct fc_context);144145++(*argcnt);146147return 0;148}149150static inline u32 create_input_list(struct skcipher_request *req, u32 enc,151u32 enc_iv_len)152{153struct cvm_req_ctx *rctx = skcipher_request_ctx_dma(req);154struct cpt_request_info *req_info = &rctx->cpt_req;155u32 argcnt = 0;156157create_ctx_hdr(req, enc, &argcnt);158update_input_iv(req_info, req->iv, enc_iv_len, &argcnt);159update_input_data(req_info, req->src, req->cryptlen, &argcnt);160req_info->incnt = argcnt;161162return 0;163}164165static inline void store_cb_info(struct skcipher_request *req,166struct cpt_request_info *req_info)167{168req_info->callback = (void *)cvm_callback;169req_info->callback_arg = (void *)&req->base;170}171172static inline void create_output_list(struct skcipher_request *req,173u32 enc_iv_len)174{175struct cvm_req_ctx *rctx = skcipher_request_ctx_dma(req);176struct cpt_request_info *req_info = &rctx->cpt_req;177u32 argcnt = 0;178179/* OUTPUT Buffer Processing180* AES encryption/decryption output would be181* received in the following format182*183* ------IV--------|------ENCRYPTED/DECRYPTED DATA-----|184* [ 16 Bytes/ [ Request Enc/Dec/ DATA Len AES CBC ]185*/186/* Reading IV information */187update_output_iv(req_info, req->iv, enc_iv_len, &argcnt);188update_output_data(req_info, req->dst, req->cryptlen, &argcnt);189req_info->outcnt = argcnt;190}191192static inline int cvm_enc_dec(struct skcipher_request *req, u32 enc)193{194struct crypto_skcipher *tfm = crypto_skcipher_reqtfm(req);195struct cvm_req_ctx *rctx = skcipher_request_ctx_dma(req);196u32 enc_iv_len = crypto_skcipher_ivsize(tfm);197struct fc_context *fctx = &rctx->fctx;198struct cpt_request_info *req_info = &rctx->cpt_req;199void *cdev = NULL;200int status;201202memset(req_info, 0, sizeof(struct cpt_request_info));203req_info->may_sleep = (req->base.flags & CRYPTO_TFM_REQ_MAY_SLEEP) != 0;204memset(fctx, 0, sizeof(struct fc_context));205create_input_list(req, enc, enc_iv_len);206create_output_list(req, enc_iv_len);207store_cb_info(req, req_info);208cdev = dev_handle.cdev[smp_processor_id()];209status = cptvf_do_request(cdev, req_info);210/* We perform an asynchronous send and once211* the request is completed the driver would212* intimate through registered call back functions213*/214215if (status)216return status;217else218return -EINPROGRESS;219}220221static int cvm_encrypt(struct skcipher_request *req)222{223return cvm_enc_dec(req, true);224}225226static int cvm_decrypt(struct skcipher_request *req)227{228return cvm_enc_dec(req, false);229}230231static int cvm_xts_setkey(struct crypto_skcipher *cipher, const u8 *key,232u32 keylen)233{234struct cvm_enc_ctx *ctx = crypto_skcipher_ctx(cipher);235int err;236const u8 *key1 = key;237const u8 *key2 = key + (keylen / 2);238239err = xts_verify_key(cipher, key, keylen);240if (err)241return err;242ctx->key_len = keylen;243memcpy(ctx->enc_key, key1, keylen / 2);244memcpy(ctx->enc_key + KEY2_OFFSET, key2, keylen / 2);245ctx->cipher_type = AES_XTS;246switch (ctx->key_len) {247case 32:248ctx->key_type = AES_128_BIT;249break;250case 64:251ctx->key_type = AES_256_BIT;252break;253default:254return -EINVAL;255}256257return 0;258}259260static int cvm_validate_keylen(struct cvm_enc_ctx *ctx, u32 keylen)261{262if ((keylen == 16) || (keylen == 24) || (keylen == 32)) {263ctx->key_len = keylen;264switch (ctx->key_len) {265case 16:266ctx->key_type = AES_128_BIT;267break;268case 24:269ctx->key_type = AES_192_BIT;270break;271case 32:272ctx->key_type = AES_256_BIT;273break;274default:275return -EINVAL;276}277278if (ctx->cipher_type == DES3_CBC)279ctx->key_type = 0;280281return 0;282}283284return -EINVAL;285}286287static int cvm_setkey(struct crypto_skcipher *cipher, const u8 *key,288u32 keylen, u8 cipher_type)289{290struct cvm_enc_ctx *ctx = crypto_skcipher_ctx(cipher);291292ctx->cipher_type = cipher_type;293if (!cvm_validate_keylen(ctx, keylen)) {294memcpy(ctx->enc_key, key, keylen);295return 0;296} else {297return -EINVAL;298}299}300301static int cvm_cbc_aes_setkey(struct crypto_skcipher *cipher, const u8 *key,302u32 keylen)303{304return cvm_setkey(cipher, key, keylen, AES_CBC);305}306307static int cvm_ecb_aes_setkey(struct crypto_skcipher *cipher, const u8 *key,308u32 keylen)309{310return cvm_setkey(cipher, key, keylen, AES_ECB);311}312313static int cvm_cbc_des3_setkey(struct crypto_skcipher *cipher, const u8 *key,314u32 keylen)315{316return verify_skcipher_des3_key(cipher, key) ?:317cvm_setkey(cipher, key, keylen, DES3_CBC);318}319320static int cvm_ecb_des3_setkey(struct crypto_skcipher *cipher, const u8 *key,321u32 keylen)322{323return verify_skcipher_des3_key(cipher, key) ?:324cvm_setkey(cipher, key, keylen, DES3_ECB);325}326327static int cvm_enc_dec_init(struct crypto_skcipher *tfm)328{329crypto_skcipher_set_reqsize_dma(tfm, sizeof(struct cvm_req_ctx));330331return 0;332}333334static struct skcipher_alg algs[] = { {335.base.cra_flags = CRYPTO_ALG_ASYNC |336CRYPTO_ALG_ALLOCATES_MEMORY,337.base.cra_blocksize = AES_BLOCK_SIZE,338.base.cra_ctxsize = sizeof(struct cvm_enc_ctx),339.base.cra_alignmask = 7,340.base.cra_priority = 4001,341.base.cra_name = "xts(aes)",342.base.cra_driver_name = "cavium-xts-aes",343.base.cra_module = THIS_MODULE,344345.ivsize = AES_BLOCK_SIZE,346.min_keysize = 2 * AES_MIN_KEY_SIZE,347.max_keysize = 2 * AES_MAX_KEY_SIZE,348.setkey = cvm_xts_setkey,349.encrypt = cvm_encrypt,350.decrypt = cvm_decrypt,351.init = cvm_enc_dec_init,352}, {353.base.cra_flags = CRYPTO_ALG_ASYNC |354CRYPTO_ALG_ALLOCATES_MEMORY,355.base.cra_blocksize = AES_BLOCK_SIZE,356.base.cra_ctxsize = sizeof(struct cvm_enc_ctx),357.base.cra_alignmask = 7,358.base.cra_priority = 4001,359.base.cra_name = "cbc(aes)",360.base.cra_driver_name = "cavium-cbc-aes",361.base.cra_module = THIS_MODULE,362363.ivsize = AES_BLOCK_SIZE,364.min_keysize = AES_MIN_KEY_SIZE,365.max_keysize = AES_MAX_KEY_SIZE,366.setkey = cvm_cbc_aes_setkey,367.encrypt = cvm_encrypt,368.decrypt = cvm_decrypt,369.init = cvm_enc_dec_init,370}, {371.base.cra_flags = CRYPTO_ALG_ASYNC |372CRYPTO_ALG_ALLOCATES_MEMORY,373.base.cra_blocksize = AES_BLOCK_SIZE,374.base.cra_ctxsize = sizeof(struct cvm_enc_ctx),375.base.cra_alignmask = 7,376.base.cra_priority = 4001,377.base.cra_name = "ecb(aes)",378.base.cra_driver_name = "cavium-ecb-aes",379.base.cra_module = THIS_MODULE,380381.min_keysize = AES_MIN_KEY_SIZE,382.max_keysize = AES_MAX_KEY_SIZE,383.setkey = cvm_ecb_aes_setkey,384.encrypt = cvm_encrypt,385.decrypt = cvm_decrypt,386.init = cvm_enc_dec_init,387}, {388.base.cra_flags = CRYPTO_ALG_ASYNC |389CRYPTO_ALG_ALLOCATES_MEMORY,390.base.cra_blocksize = DES3_EDE_BLOCK_SIZE,391.base.cra_ctxsize = sizeof(struct cvm_des3_ctx),392.base.cra_alignmask = 7,393.base.cra_priority = 4001,394.base.cra_name = "cbc(des3_ede)",395.base.cra_driver_name = "cavium-cbc-des3_ede",396.base.cra_module = THIS_MODULE,397398.min_keysize = DES3_EDE_KEY_SIZE,399.max_keysize = DES3_EDE_KEY_SIZE,400.ivsize = DES_BLOCK_SIZE,401.setkey = cvm_cbc_des3_setkey,402.encrypt = cvm_encrypt,403.decrypt = cvm_decrypt,404.init = cvm_enc_dec_init,405}, {406.base.cra_flags = CRYPTO_ALG_ASYNC |407CRYPTO_ALG_ALLOCATES_MEMORY,408.base.cra_blocksize = DES3_EDE_BLOCK_SIZE,409.base.cra_ctxsize = sizeof(struct cvm_des3_ctx),410.base.cra_alignmask = 7,411.base.cra_priority = 4001,412.base.cra_name = "ecb(des3_ede)",413.base.cra_driver_name = "cavium-ecb-des3_ede",414.base.cra_module = THIS_MODULE,415416.min_keysize = DES3_EDE_KEY_SIZE,417.max_keysize = DES3_EDE_KEY_SIZE,418.ivsize = DES_BLOCK_SIZE,419.setkey = cvm_ecb_des3_setkey,420.encrypt = cvm_encrypt,421.decrypt = cvm_decrypt,422.init = cvm_enc_dec_init,423} };424425static inline int cav_register_algs(void)426{427return crypto_register_skciphers(algs, ARRAY_SIZE(algs));428}429430static inline void cav_unregister_algs(void)431{432crypto_unregister_skciphers(algs, ARRAY_SIZE(algs));433}434435int cvm_crypto_init(struct cpt_vf *cptvf)436{437struct pci_dev *pdev = cptvf->pdev;438u32 dev_count;439440dev_count = dev_handle.dev_count;441dev_handle.cdev[dev_count] = cptvf;442dev_handle.dev_count++;443444if (dev_count == 3) {445if (cav_register_algs()) {446dev_err(&pdev->dev, "Error in registering crypto algorithms\n");447return -EINVAL;448}449}450451return 0;452}453454void cvm_crypto_exit(void)455{456u32 dev_count;457458dev_count = --dev_handle.dev_count;459if (!dev_count)460cav_unregister_algs();461}462463464