From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1753072AbdEJNIT (ORCPT ); Wed, 10 May 2017 09:08:19 -0400 Received: from mail-bn3nam01on0075.outbound.protection.outlook.com ([104.47.33.75]:13152 "EHLO NAM01-BN3-obe.outbound.protection.outlook.com" rhost-flags-OK-OK-OK-FAIL) by vger.kernel.org with ESMTP id S1752520AbdEJNHi (ORCPT ); Wed, 10 May 2017 09:07:38 -0400 Authentication-Results: gondor.apana.org.au; dkim=none (message not signed) header.d=none;gondor.apana.org.au; dmarc=none action=none header.from=cavium.com; From: Srikanth Jampala To: herbert@gondor.apana.org.au Cc: davem@davemloft.net, linux-kernel@vger.kernel.org, linux-crypto@vger.kernel.org, George.Cherian@cavium.com, Nidadavolu.Murthy@cavium.com, Sreerama.Gadam@cavium.com, Ram.Kumar@cavium.com, Jampala.Srikanth@cavium.com Subject: [PATCH v1 3/3] crypto: cavium - Register the CNN55XX supported crypto algorithms. Date: Wed, 10 May 2017 18:36:40 +0530 Message-Id: <20170510130640.5838-4-Jampala.Srikanth@cavium.com> X-Mailer: git-send-email 2.9.3 In-Reply-To: <20170510130640.5838-1-Jampala.Srikanth@cavium.com> References: <20170510130640.5838-1-Jampala.Srikanth@cavium.com> MIME-Version: 1.0 Content-Type: text/plain X-Originating-IP: [14.140.2.178] X-ClientProxiedBy: BMXPR01CA0025.INDPRD01.PROD.OUTLOOK.COM (10.174.214.11) To CY4PR07MB3592.namprd07.prod.outlook.com (10.171.253.19) X-MS-PublicTrafficType: Email X-MS-Office365-Filtering-Correlation-Id: 581fb41b-c5db-4839-0321-08d497a57f82 X-Microsoft-Antispam: UriScan:;BCL:0;PCL:0;RULEID:(22001)(201703131423075)(201703031133081);SRVR:CY4PR07MB3592; X-Microsoft-Exchange-Diagnostics: 1;CY4PR07MB3592;3:X0PMuyarupJ28Cp28mf7vXv5TsMplCzgkpc/dyiCxSgqggX2CPxsyI5lQPxarhz0PYka/UDKQUrQuquETd7srEl17I3JZ3p0IYp+uLJzlyTX9VQnJDBZF5ZpVz3CA6eqmnVa84NHZeYBUOY7RHhogiRJfSDsLs9SHfls+HO3tUwQUNp8rYrrknT7r9Qkp1FzyFWAEspwNWi1iFQBvP6iiby2rqWQCV0yY0ev9RUfljUA5r2tMAu5s89FLbcO3kH7PSuiy5O3oYf+GLi0LvdqayBpUnwPvYM207v/doNuRUSvfHmb9nf5CGXEHsVuKlMb60+jMQUz3Jcjxhvt0KNquQ==;25:4G6ZLguFkZePmMuGKwDAqWDJvyBN9GaCWmBgD2PvaUFektk82n3Ze6SU7LZDI/M6euX1HogPs/+L9Wd1eK9SNo445E+gOLtbHs/NaQx1BJ4iDEa59PXleuma03ExxTjikfxQCpWgGQ1NPVxJMh/TmPG34GQZ5cGpcazzLMeWUT5o2JTkuyZyRqtBMjGjjxGkCNGBAthk0+lNpkShv2/bifRXcK1Ao3f8aBOfIjuoxJrFzIpFNfg5Cdb9EWtw/G43RpJfwlz/VkSrlg677oCwn6Ft9Mv7nJfubUV8ZhE/5BK6+InI1fveeihVfAh62kWNuHwRhaNz/cfNE/q9jgZB88/ljpwtt2YGIsEcl2vMJNYpeWuEB3+bLC7QOfMGDSZmA1x2WAdoa2XjAHCDUTbI/XCnM5sJG8HconmkdYmWptMZYvSYRzPtD14svE7zjcMOfbG8GKcanojdfCSOKQyq8cwP6e+D0IU2zeMY5D0YiRM= X-Microsoft-Exchange-Diagnostics: 1;CY4PR07MB3592;31:DnbP9gZiO+7odE9MMmF0505RMsi8fRr7AED68mLX6HXbwq7FCt+/si/38bh/7KLIwgaEq2AfZDq9M1agxzoxO4o8zxydvDbA5sCnRYlm6HYQVfJRk+v+B1JmY5nOMqNIpgSqka4lj4lcgFNfm7bs88J+S0B+j4a381brKmuaw1AclHXa/8pbz3YmlOYXxwwQgTn89rPdtQCTCuMZHOBv6Z+a6RdyNNQkuHyBEdT21Xo=;20:FZK1w33fTjbmyX+ayJEXtaJQITRF9a029HnpVT25ia3li1OpQlD5I2dThJPaTApkBoA/xvtY+XXaX3gx+6yT4/7v85Io+34Cf2/01IWwnwNezyCx+tAcfOjif6Oilv4w8Z+85sJuWQ5yJ391NMgfI9qMtuUiGVskLlqSe07xb2VG4Ifr+yOdXFHJ/QeraYWiiz+eeXAroSVKwF097SrfaW4rlWiHIqii+OH7HdNIIj2xKomwjEkHDW8flTTsDbgenY7V3QVDRekwDMEWDTUpE3Umm/EUYxsvGRCcoD7YpiCb8+Sdfo7yfVebBL+Y2yok5MGIeOHvM8SVT4rAzKrkDyHkkgLkvOgnJWK8lc4qY3oyCBG++sysEkp9B2c6ItU8CggD3e6j6ge+HgmG5CG+gGHdd/8MRYPqDRNAvssRQE8y6R2qiUVuRoS3gGdGU8kGpMis4Vn5Te1nO3S/YJ6cSqmYy5a49qIFtSOMyLSREx8+FoofIQOLCZKL+xV0Lfe9 X-Microsoft-Antispam-PRVS: X-Exchange-Antispam-Report-Test: UriScan:; X-Exchange-Antispam-Report-CFA-Test: BCL:0;PCL:0;RULEID:(6040450)(601004)(2401047)(8121501046)(5005006)(10201501046)(3002001)(93006095)(93001095)(6041248)(20161123564025)(201703131423075)(201702281528075)(201703061421075)(201703061406153)(20161123558100)(20161123562025)(20161123555025)(20161123560025)(6072148);SRVR:CY4PR07MB3592;BCL:0;PCL:0;RULEID:;SRVR:CY4PR07MB3592; X-Microsoft-Exchange-Diagnostics: 1;CY4PR07MB3592;4:xFbPM9QMQPG3lOAaA5nItkGZHnMt9u18B0QuwYuBxZtdxuWWkWh2AreJCO5dI/i6B4LyyLiQ5STtDs4NKnXjXD5XqK+rjU9vzNxfx9fkjVNvU54P9WuQmivXyEKfnXGSfZTvB7MpOVoCBfhCZdNMwGoJ0eqUdU/RToBrV2qNLn0JxH2yIEZf0V+8FyrtcVBixdxqGuv/R2StsspNZrCgTk79lHtlH8coVXS+Rw1ooNdgLJoldHrjwQV6kkwrPyVLsqqwriHUNBhsa4CyYwX9cq7bJ0dBgmc6A6M7dvn7F6OAMBz15m761bkNp1WUlCZKMLIVIdbdXTW7n808Lb49e7034g//9+ceY/9jOTADEofW6thJYDcZV8GgklqK85WdtPpeRStbBLaTSLzihClztDCE67MCYge9s8DGKJW/MwEtjDD4pMfbl2JBgUZKKJ0iBFLCyZdM3UjBmUEP0RTJuKygVUuM6ph9NNUMOiPtigVn79ZrgFsWUUpIhN994ymdjteMviqIC0Xm41pbirZBiqBiYmJbQAJgBEr+5UTozjs0GTqgOiwOoTmuDqhbPMZpyD8cxeafsKp1A3DO3ESc4Rw6m+w5YAzY0+XxaqlKHXTnsA1jnHv30giZVfGD/hcHiwMsFrgUSIdfP8XCDQV/S7XCIPphZAcWqrgl/o14E5R6+tV0JkSmyvReWbVSJlP0pIYcZQkMN46c3fwZzOtIJx+4TTftVoDzCUzF+Ww4mMN1XKPhgyCdhNmDILxmUtzp/+47ui9TO4yalUxp1RYh836p+Buc+MTTiwZimVq7Zcw= X-Forefront-PRVS: 03030B9493 X-Forefront-Antispam-Report: SFV:NSPM;SFS:(10009020)(4630300001)(6009001)(6069001)(39450400003)(39400400002)(39850400002)(39840400002)(39410400002)(5660300001)(6666003)(7736002)(189998001)(76176999)(305945005)(5009440100003)(50986999)(4326008)(2351001)(2361001)(2906002)(72206003)(42186005)(25786009)(48376002)(50466002)(5003940100001)(478600001)(6116002)(3846002)(1076002)(107886003)(110136004)(6506006)(53936002)(38730400002)(6512007)(66066001)(47776003)(2950100002)(8676002)(81166006)(6916009)(50226002)(36756003)(86362001)(6486002)(110426004);DIR:OUT;SFP:1101;SCL:1;SRVR:CY4PR07MB3592;H:localhost.localdomain.in.caveonetworks.com;FPR:;SPF:None;MLV:nov;PTR:InfoNoRecords;LANG:en; X-Microsoft-Exchange-Diagnostics: =?us-ascii?Q?1;CY4PR07MB3592;23:Oiqz7cO7LkVvEc3Db+S2YmYVRsExtM2ywV40POYAq?= =?us-ascii?Q?/iaArOK41TxY6K9PRyYChpkUWaRvJnmqlyAKGuXhBDFmujUcGCdVv+tG6Bbp?= =?us-ascii?Q?B3ye55Ma7RgwjvGj5UBVjlge1o4IuAztLvwgHH8Gstfdq8arKNikb/ApV+nu?= =?us-ascii?Q?dV618UJzO7LsqPn5HX6xNleJiWepl65geBdhz/fGWgpgTFtk9BmD23CqDnMj?= =?us-ascii?Q?DOyepQIbstBXiDFViBXUjOjzKzwouCS8OoIdLs/nvZpi3MgIlx8HzPyNABN7?= =?us-ascii?Q?31P3WecPN8HfGWfCgjsVBcUmFY7cBegvlwUlYvMxi0osWwOeRRgPht3tdNoe?= =?us-ascii?Q?7tbLK68Be+eG/VPQltANWhd19dQK0tsAsnwmWWQf9wVoSgu7P8UvKLRvsMSS?= =?us-ascii?Q?/xgYvbc9mPttcKPEpi3mfVXsfpywi+rQRCd3YMaxkhkzz42Ll+g9QXUhBsC2?= =?us-ascii?Q?vdhcFoLfyOFHL2VQx7cnqA1oXq2DP9ow0l1gIbh3aGn+ZM45gTAAEg5dE2oq?= =?us-ascii?Q?oa8MLf8tNqmC0M+pYeTMJiz4CWsWjoHJh+hE5kxva2ft4FohwgjvEEI3cKhd?= =?us-ascii?Q?8kiE2tHV8Pbmw1J9jlgXCxThvBdTj3x2KxziTpQBfkTvJnHXOHdnkwqF2D65?= =?us-ascii?Q?xoNlyTY/sMXozbT2onND0YvKAkHzAu/GNuvSDIFS28tyJV2DTaZTPSdPBnmm?= =?us-ascii?Q?ogzO8CUcX/YE0R/UfAFjhQn9BItoeE/sXWnHUgQm5MJYKMcAgjRpjCFeakvi?= =?us-ascii?Q?J/4EDLXpIIxt7766BUJAIsemUmRZnB1BMjsx/216EoQ9u1Ze1fXvd6jVhW7c?= =?us-ascii?Q?J/yoBVDeKunaPgNLMYnTP6Qrp+jdMpKPXYX1BTEPDPZedgM8n5FQ7Qv6Q3TV?= =?us-ascii?Q?BENHyBCIxnm2dx/xMXVOUdFmYWUNEpE/Vqqtd4HQfHfahz3/DDQLMn/g/1I9?= =?us-ascii?Q?LfN3RDK8zF4yw9WscKiq3k70zLHPiDq4jjH46zLPnQMviHBvFbNP8xF99AH/?= =?us-ascii?Q?K/5z8z/O50y7FpIUorIVvZbbdgURukPgQH7UCz2WKwvbSo0C52m5en3fgBEK?= =?us-ascii?Q?wgsK0wi3GIO0OT59JHRn4ME6wFr+MClN5TXNC+ZILI2sZEZZ35uhVSuEY0qP?= =?us-ascii?Q?JGjp/wjUgPFlH5Qj21mkTLBBIrTQnmRHEFhGvgeK9dUXl1qDGBikQofAM4UA?= =?us-ascii?Q?tnvPnLvp5EtJtg=3D?= X-Microsoft-Exchange-Diagnostics: 1;CY4PR07MB3592;6:Cax3j32ctC5vOyZUx2TJxgUWaDPtB4dng/kVk9aPA4R75BEYzJv85hQrs2lpPRHZohFAYnUE1vQwiBMacfBEl5kE7da3m1vYQZyV/bEthlEnLrpaO/GlDuz4YLxJHNIrVKPe+Zr224yvFBd22KlPXRuiwGrs/Fe5wyiC1fYJ7Xsf6aEZkXDysgUixeekttSDpwWCQ3SvOmXnYvG9e1IBrO+6ItUxJD8+Xs/6vaxhqSD3sOL6NerooIvy8aOWY3yH1yePqmNw8hsCzF1NkSgPc2EfBYhz1z4zzov6PmR0VMixE7xVJS1nWJYcAtF/bRYosfDWHAVvebUG/wGzUvoOe4lENRhJeTadmo3gjp5GMbYeepm/flzKDlo8XvMpFX1f3nHFuBWs5vP80ZnNkIZlJJ2p9HUryGqASN6Jmku139gg4USV3LbLkCDreYXRHJDu2ApLEtrX5hS+5Z+rfCkgjO/ca0yAZqIgCf+nQSCT9AxMQ1RFIn+e8utVuKlSAchWXGYrxV8W4zEiGci81YPCxA==;5:M4M12uiNqrWYqj+fepGdmIfD0b71HrK7cI5wixO0Rhpn2o30/NRtTTtEMlZx7zHzybccXvYyYLYMmYqhBs9mTVUFo2Nr1Rhh/P/ESRlpkawmiOlpHfrjh9rtPWOW3/RjYfxQs+4+sjqCA+A3PgA+aw==;24:IqJG/Q+gPX9VvScq2MKtUTrRqNjG1JRzKP/hByYCAgW/s38kOgisgNovZaPJoewa1nYHzhrj31fQVbEEaFitCnhI0V5Tt5OHW8R7wWXjcps= SpamDiagnosticOutput: 1:99 SpamDiagnosticMetadata: NSPM X-Microsoft-Exchange-Diagnostics: 1;CY4PR07MB3592;7:xBexgw9fBAdASnkWG2hAIyzNALLSqg2P1xET0EvN7vqreSsyHKChBgC6y4tTOK6oGZ7z3OrMWZptsQQrr07maQV9zkbMC6I3eRpxdHeM3hC1/OcRbTt+bAHHUKbUQcRdy47sH0MSzIzsojlruSAqEpnkxm97t9Aqunnfan418bxx228aBkMu+vQ/54dC7JGcUz1ZUFlDBGX48FlbFO9D6hq6FJWJ91jpyQZSYT5sEkGbzMPJlGWRLMdrQ7xsXdeufC4yIn7+sRiLCL4PfxsJSe7a1FVADguURij0SjRtWQ7HjS/nbDUadFsGQG50cd04mnQZJUKlHXWKeHGhhNrhlg== X-OriginatorOrg: cavium.com X-MS-Exchange-CrossTenant-OriginalArrivalTime: 10 May 2017 13:07:19.9285 (UTC) X-MS-Exchange-CrossTenant-FromEntityHeader: Hosted X-MS-Exchange-Transport-CrossTenantHeadersStamped: CY4PR07MB3592 Sender: linux-kernel-owner@vger.kernel.org List-ID: X-Mailing-List: linux-kernel@vger.kernel.org Register the Symmetric crypto algorithms supported by CNN55XX driver with crypto subsystem. The following Symmetric crypto algorithms are supported, - aes with cbc, ecb, cfb, xts, ctr and cts modes - des3_ede with cbc and ecb modes Signed-off-by: Srikanth Jampala --- drivers/crypto/cavium/nitrox/Makefile | 3 +- drivers/crypto/cavium/nitrox/nitrox_algs.c | 584 +++++++++++++++++++++++++++ drivers/crypto/cavium/nitrox/nitrox_common.h | 7 + drivers/crypto/cavium/nitrox/nitrox_lib.c | 38 ++ drivers/crypto/cavium/nitrox/nitrox_main.c | 40 ++ 5 files changed, 671 insertions(+), 1 deletion(-) create mode 100644 drivers/crypto/cavium/nitrox/nitrox_algs.c diff --git a/drivers/crypto/cavium/nitrox/Makefile b/drivers/crypto/cavium/nitrox/Makefile index ef457f6..5af2e43 100644 --- a/drivers/crypto/cavium/nitrox/Makefile +++ b/drivers/crypto/cavium/nitrox/Makefile @@ -4,4 +4,5 @@ n5pf-objs := nitrox_main.o \ nitrox_isr.o \ nitrox_lib.o \ nitrox_hal.o \ - nitrox_reqmgr.o + nitrox_reqmgr.o \ + nitrox_algs.o diff --git a/drivers/crypto/cavium/nitrox/nitrox_algs.c b/drivers/crypto/cavium/nitrox/nitrox_algs.c new file mode 100644 index 0000000..aa9df1c --- /dev/null +++ b/drivers/crypto/cavium/nitrox/nitrox_algs.c @@ -0,0 +1,584 @@ +#include +#include +#include +#include + +#include +#include +#include +#include +#include + +#include "nitrox_dev.h" +#include "nitrox_common.h" +#include "nitrox_req.h" + +struct nitrox_cipher { + const char *name; + enum flexi_cipher value; +}; + +/** + * supported cipher list + */ +static const struct nitrox_cipher flexi_cipher_table[] = { + { "null", CIPHER_NULL }, + { "cbc(des3_ede)", CIPHER_3DES_CBC }, + { "ecb(des3_ede)", CIPHER_3DES_ECB }, + { "cbc(aes)", CIPHER_AES_CBC }, + { "ecb(aes)", CIPHER_AES_ECB }, + { "cfb(aes)", CIPHER_AES_CFB }, + { "rfc3686(ctr(aes))", CIPHER_AES_CTR }, + { "xts(aes)", CIPHER_AES_XTS }, + { "cts(cbc(aes))", CIPHER_AES_CBC_CTS }, + { NULL, CIPHER_INVALID } +}; + +static enum flexi_cipher flexi_cipher_type(const char *name) +{ + const struct nitrox_cipher *cipher = flexi_cipher_table; + + while (cipher->name) { + if (!strcmp(cipher->name, name)) + break; + cipher++; + } + return cipher->value; +} + +static int flexi_aes_keylen(int keylen) +{ + int aes_keylen; + + switch (keylen) { + case AES_KEYSIZE_128: + aes_keylen = 1; + break; + case AES_KEYSIZE_192: + aes_keylen = 2; + break; + case AES_KEYSIZE_256: + aes_keylen = 3; + break; + default: + aes_keylen = -EINVAL; + break; + } + return aes_keylen; +} + +static inline void create_io_list(struct scatterlist *src, + struct io_sglist *io) +{ + struct scatterlist *sg; + int cnt, sgcount, i; + + cnt = io->cnt; + sgcount = sg_nents(src); + + for_each_sg(src, sg, sgcount, i) { + if (!sg->length) + continue; + io->bufs[cnt].addr = sg_virt(sg); + io->bufs[cnt].len = sg->length; + cnt++; + } + io->cnt = cnt; +} + +static int nitrox_ablkcipher_init(struct crypto_tfm *tfm) +{ + struct nitrox_crypto_instance *inst = crypto_tfm_ctx(tfm); + void *ctx; + + tfm->crt_ablkcipher.reqsize = sizeof(struct nitrox_crypto_request); + /* get the first device */ + inst->ndev = nitrox_get_first_device(); + if (!inst->ndev) + return -ENODEV; + + /* allocate crypto context */ + ctx = crypto_alloc_context(inst->ndev); + if (!ctx) { + nitrox_put_device(inst->ndev); + return -ENOMEM; + } + inst->u.ctx_handle = (uintptr_t)ctx; + + return 0; +} + +static void nitrox_ablkcipher_exit(struct crypto_tfm *tfm) +{ + struct nitrox_crypto_instance *inst = crypto_tfm_ctx(tfm); + + /* free the crypto context */ + if (inst->u.ctx_handle) + crypto_free_context((void *)inst->u.ctx_handle); + + nitrox_put_device(inst->ndev); + + inst->u.ctx_handle = 0; + inst->ndev = NULL; +} + +static inline int nitrox_ablkcipher_setkey(struct crypto_ablkcipher *cipher, + int aes_keylen, const u8 *key, + unsigned int keylen) +{ + struct crypto_tfm *tfm = crypto_ablkcipher_tfm(cipher); + struct nitrox_crypto_instance *inst = crypto_tfm_ctx(tfm); + struct flexi_crypto_context *fctx; + enum flexi_cipher cipher_type; + const char *name; + + name = crypto_tfm_alg_name(tfm); + cipher_type = flexi_cipher_type(name); + if (cipher_type == CIPHER_INVALID) { + pr_err("unsupported cipher: %s\n", name); + return -EINVAL; + } + + /* fill crypto context */ + fctx = inst->u.fctx; + fctx->flags = 0; + fctx->w0.cipher_type = cipher_type; + fctx->w0.aes_keylen = aes_keylen; + fctx->w0.iv_source = IV_FROM_DPTR; + fctx->flags = cpu_to_be64(*(u64 *)&fctx->w0); + /* copy the key to context */ + memcpy(fctx->crypto.u.key, key, keylen); + + return 0; +} + +static int nitrox_aes_setkey(struct crypto_ablkcipher *cipher, const u8 *key, + unsigned int keylen) +{ + int aes_keylen; + + aes_keylen = flexi_aes_keylen(keylen); + if (aes_keylen < 0) { + crypto_ablkcipher_set_flags(cipher, CRYPTO_TFM_RES_BAD_KEY_LEN); + return -EINVAL; + } + return nitrox_ablkcipher_setkey(cipher, aes_keylen, key, keylen); +} + +static void nitrox_ablkcipher_alg_callback(int status, void *arg) +{ + struct nitrox_crypto_request *nkreq = arg; + struct ablkcipher_request *areq = nkreq->abreq; + struct crypto_ablkcipher *cipher = crypto_ablkcipher_reqtfm(areq); + int ivsize = crypto_ablkcipher_ivsize(cipher); + struct crypto_request *creq = &nkreq->creq; + + /* copy the iv back */ + memcpy(areq->info, creq->out->bufs[0].addr, ivsize); + + kfree(creq->in->bufs[0].addr); + kfree(creq->in); + kfree(creq->out->bufs[0].addr); + kfree(creq->out); + + if (status) { + pr_err_ratelimited("request failed status 0x%0x\n", status); + status = -EINVAL; + } + + areq->base.complete(&areq->base, status); +} + +static inline int create_crypt_input_list(struct ablkcipher_request *areq, + struct crypto_request *creq) +{ + struct crypto_ablkcipher *cipher = crypto_ablkcipher_reqtfm(areq); + int ivsize = crypto_ablkcipher_ivsize(cipher); + struct io_sglist *in; + size_t sz; + gfp_t gfp; + + /* one extra entry for IV */ + sz = sizeof(*in) + + (1 + sg_nents(areq->src)) * sizeof(struct nitrox_buffer); + + gfp = (areq->base.flags & CRYPTO_TFM_REQ_MAY_SLEEP) ? + GFP_KERNEL : GFP_ATOMIC; + + in = kzalloc(sz, gfp); + if (!in) + return -ENOMEM; + + in->bufs[0].addr = kmalloc(ivsize, gfp); + if (!in->bufs[0].addr) { + kfree(in); + return -ENOMEM; + } + creq->in = in; + /* copy iv */ + memcpy(in->bufs[0].addr, areq->info, ivsize); + in->bufs[0].len = ivsize; + in->cnt++; + + create_io_list(areq->src, in); + return 0; +} + +static inline int create_crypt_output_list(struct ablkcipher_request *areq, + struct crypto_request *creq) +{ + struct crypto_ablkcipher *cipher = crypto_ablkcipher_reqtfm(areq); + int ivsize = crypto_ablkcipher_ivsize(cipher); + struct io_sglist *out; + size_t sz; + gfp_t gfp; + + /* one extra entry for IV */ + sz = sizeof(*out) + + (1 + sg_nents(areq->dst)) * sizeof(struct nitrox_buffer); + + gfp = (areq->base.flags & CRYPTO_TFM_REQ_MAY_SLEEP) ? + GFP_KERNEL : GFP_ATOMIC; + + out = kzalloc(sz, gfp); + if (!out) + return -ENOMEM; + + /* place for iv */ + out->bufs[0].addr = kzalloc(ivsize, gfp); + if (!out->bufs[0].addr) { + kfree(out); + return -ENOMEM; + } + creq->out = out; + out->bufs[0].len = ivsize; + out->cnt++; + + create_io_list(areq->dst, out); + return 0; +} + +static int nitrox_ablkcipher_crypt(struct ablkcipher_request *areq, bool enc) +{ + struct crypto_ablkcipher *cipher = crypto_ablkcipher_reqtfm(areq); + struct crypto_tfm *tfm = crypto_ablkcipher_tfm(cipher); + struct nitrox_crypto_instance *inst = crypto_tfm_ctx(tfm); + struct nitrox_crypto_request *nkreq = ablkcipher_request_ctx(areq); + int ivsize = crypto_ablkcipher_ivsize(cipher); + struct crypto_request *creq; + int ret; + + creq = &nkreq->creq; + /* fill the request */ + creq->ctrl.value = 0; + creq->opcode = FLEXI_CRYPTO_ENCRYPT_HMAC; + creq->ctrl.s.arg = (enc ? ENCRYPT : DECRYPT); + /* param0: length of the data to be encrypted */ + creq->gph.param0 = cpu_to_be16(areq->nbytes); + creq->gph.param1 = 0; + /* param2: encryption data offset */ + creq->gph.param2 = cpu_to_be16(ivsize); + creq->gph.param3 = 0; + + creq->ctx_handle = inst->u.ctx_handle; + creq->ctrl.s.ctxl = sizeof(struct flexi_crypto_context); + + ret = create_crypt_input_list(areq, creq); + if (ret) + return ret; + + ret = create_crypt_output_list(areq, creq); + if (ret) { + kfree(creq->in); + return ret; + } + + nkreq->inst = inst; + nkreq->abreq = areq; + creq->callback = nitrox_ablkcipher_alg_callback; + creq->cb_arg = nkreq; + creq->flags = areq->base.flags; + + /* send the crypto request */ + ret = nitrox_se_request(inst->ndev, creq); + if (ret) + return ret; + + return -EINPROGRESS; +} + +static int nitrox_aes_encrypt(struct ablkcipher_request *areq) +{ + return nitrox_ablkcipher_crypt(areq, true); +} + +static int nitrox_aes_decrypt(struct ablkcipher_request *areq) +{ + return nitrox_ablkcipher_crypt(areq, false); +} + +static int nitrox_3des_setkey(struct crypto_ablkcipher *cipher, const u8 *key, + unsigned int keylen) +{ + if (keylen != DES3_EDE_KEY_SIZE) { + crypto_ablkcipher_set_flags(cipher, CRYPTO_TFM_RES_BAD_KEY_LEN); + return -EINVAL; + } + + return nitrox_ablkcipher_setkey(cipher, 0, key, keylen); +} + +static int nitrox_3des_encrypt(struct ablkcipher_request *areq) +{ + return nitrox_ablkcipher_crypt(areq, true); +} + +static int nitrox_3des_decrypt(struct ablkcipher_request *areq) +{ + return nitrox_ablkcipher_crypt(areq, false); +} + +static int nitrox_aes_xts_setkey(struct crypto_ablkcipher *cipher, + const u8 *key, unsigned int keylen) +{ + struct crypto_tfm *tfm = crypto_ablkcipher_tfm(cipher); + struct nitrox_crypto_instance *inst = crypto_tfm_ctx(tfm); + struct flexi_crypto_context *fctx; + int aes_keylen, ret; + + ret = xts_check_key(tfm, key, keylen); + if (ret) + return ret; + + keylen /= 2; + + aes_keylen = flexi_aes_keylen(keylen); + if (aes_keylen < 0) { + crypto_ablkcipher_set_flags(cipher, CRYPTO_TFM_RES_BAD_KEY_LEN); + return -EINVAL; + } + + fctx = inst->u.fctx; + /* copy KEY2 */ + memcpy(fctx->auth.u.key2, (key + keylen), keylen); + + return nitrox_ablkcipher_setkey(cipher, aes_keylen, key, keylen); +} + +static int nitrox_aes_ctr_rfc3686_setkey(struct crypto_ablkcipher *cipher, + const u8 *key, unsigned int keylen) +{ + struct crypto_tfm *tfm = crypto_ablkcipher_tfm(cipher); + struct nitrox_crypto_instance *inst = crypto_tfm_ctx(tfm); + struct flexi_crypto_context *fctx; + int aes_keylen; + + if (keylen < CTR_RFC3686_NONCE_SIZE) + return -EINVAL; + + fctx = inst->u.fctx; + + memcpy(fctx->crypto.iv, key + (keylen - CTR_RFC3686_NONCE_SIZE), + CTR_RFC3686_NONCE_SIZE); + + keylen -= CTR_RFC3686_NONCE_SIZE; + + aes_keylen = flexi_aes_keylen(keylen); + if (aes_keylen < 0) { + crypto_ablkcipher_set_flags(cipher, CRYPTO_TFM_RES_BAD_KEY_LEN); + return -EINVAL; + } + return nitrox_ablkcipher_setkey(cipher, aes_keylen, key, keylen); +} + +static struct crypto_alg nitrox_algs[] = { { + .cra_name = "cbc(aes)", + .cra_driver_name = "n5_cbc(aes)", + .cra_priority = 4001, + .cra_flags = CRYPTO_ALG_TYPE_ABLKCIPHER | CRYPTO_ALG_ASYNC, + .cra_blocksize = AES_BLOCK_SIZE, + .cra_ctxsize = sizeof(struct nitrox_crypto_instance), + .cra_alignmask = 0, + .cra_type = &crypto_ablkcipher_type, + .cra_module = THIS_MODULE, + .cra_init = nitrox_ablkcipher_init, + .cra_exit = nitrox_ablkcipher_exit, + .cra_u = { + .ablkcipher = { + .setkey = nitrox_aes_setkey, + .decrypt = nitrox_aes_decrypt, + .encrypt = nitrox_aes_encrypt, + .min_keysize = AES_MIN_KEY_SIZE, + .max_keysize = AES_MAX_KEY_SIZE, + .ivsize = AES_BLOCK_SIZE, + }, + }, +}, { + .cra_name = "ecb(aes)", + .cra_driver_name = "n5_ecb(aes)", + .cra_priority = 4001, + .cra_flags = CRYPTO_ALG_TYPE_ABLKCIPHER | CRYPTO_ALG_ASYNC, + .cra_blocksize = AES_BLOCK_SIZE, + .cra_ctxsize = sizeof(struct nitrox_crypto_instance), + .cra_alignmask = 0, + .cra_type = &crypto_ablkcipher_type, + .cra_module = THIS_MODULE, + .cra_init = nitrox_ablkcipher_init, + .cra_exit = nitrox_ablkcipher_exit, + .cra_u = { + .ablkcipher = { + .setkey = nitrox_aes_setkey, + .decrypt = nitrox_aes_decrypt, + .encrypt = nitrox_aes_encrypt, + .min_keysize = AES_MIN_KEY_SIZE, + .max_keysize = AES_MAX_KEY_SIZE, + .ivsize = AES_BLOCK_SIZE, + }, + }, +}, { + .cra_name = "cfb(aes)", + .cra_driver_name = "n5_cfb(aes)", + .cra_priority = 4001, + .cra_flags = CRYPTO_ALG_TYPE_ABLKCIPHER | CRYPTO_ALG_ASYNC, + .cra_blocksize = AES_BLOCK_SIZE, + .cra_ctxsize = sizeof(struct nitrox_crypto_instance), + .cra_alignmask = 0, + .cra_type = &crypto_ablkcipher_type, + .cra_module = THIS_MODULE, + .cra_init = nitrox_ablkcipher_init, + .cra_exit = nitrox_ablkcipher_exit, + .cra_u = { + .ablkcipher = { + .setkey = nitrox_aes_setkey, + .decrypt = nitrox_aes_decrypt, + .encrypt = nitrox_aes_encrypt, + .min_keysize = AES_MIN_KEY_SIZE, + .max_keysize = AES_MAX_KEY_SIZE, + .ivsize = AES_BLOCK_SIZE, + }, + }, +}, { + .cra_name = "cbc(des3_ede)", + .cra_driver_name = "n5_cbc(des3_ede)", + .cra_priority = 4001, + .cra_flags = CRYPTO_ALG_TYPE_ABLKCIPHER | CRYPTO_ALG_ASYNC, + .cra_blocksize = DES3_EDE_BLOCK_SIZE, + .cra_ctxsize = sizeof(struct nitrox_crypto_instance), + .cra_alignmask = 0, + .cra_type = &crypto_ablkcipher_type, + .cra_module = THIS_MODULE, + .cra_init = nitrox_ablkcipher_init, + .cra_exit = nitrox_ablkcipher_exit, + .cra_u = { + .ablkcipher = { + .setkey = nitrox_3des_setkey, + .decrypt = nitrox_3des_decrypt, + .encrypt = nitrox_3des_encrypt, + .min_keysize = DES3_EDE_KEY_SIZE, + .max_keysize = DES3_EDE_KEY_SIZE, + .ivsize = DES3_EDE_BLOCK_SIZE, + }, + }, +}, { + .cra_name = "ecb(des3_ede)", + .cra_driver_name = "n5_ecb(des3_ede)", + .cra_priority = 4001, + .cra_flags = CRYPTO_ALG_TYPE_ABLKCIPHER | CRYPTO_ALG_ASYNC, + .cra_blocksize = DES3_EDE_BLOCK_SIZE, + .cra_ctxsize = sizeof(struct nitrox_crypto_instance), + .cra_alignmask = 0, + .cra_type = &crypto_ablkcipher_type, + .cra_module = THIS_MODULE, + .cra_init = nitrox_ablkcipher_init, + .cra_exit = nitrox_ablkcipher_exit, + .cra_u = { + .ablkcipher = { + .setkey = nitrox_3des_setkey, + .decrypt = nitrox_3des_decrypt, + .encrypt = nitrox_3des_encrypt, + .min_keysize = DES3_EDE_KEY_SIZE, + .max_keysize = DES3_EDE_KEY_SIZE, + .ivsize = DES3_EDE_BLOCK_SIZE, + }, + }, +}, { + .cra_name = "xts(aes)", + .cra_driver_name = "n5_xts(aes)", + .cra_priority = 4001, + .cra_flags = CRYPTO_ALG_TYPE_ABLKCIPHER | CRYPTO_ALG_ASYNC, + .cra_blocksize = AES_BLOCK_SIZE, + .cra_ctxsize = sizeof(struct nitrox_crypto_instance), + .cra_alignmask = 0, + .cra_type = &crypto_ablkcipher_type, + .cra_module = THIS_MODULE, + .cra_init = nitrox_ablkcipher_init, + .cra_exit = nitrox_ablkcipher_exit, + .cra_u = { + .ablkcipher = { + .setkey = nitrox_aes_xts_setkey, + .decrypt = nitrox_aes_decrypt, + .encrypt = nitrox_aes_encrypt, + .min_keysize = 2 * AES_MIN_KEY_SIZE, + .max_keysize = 2 * AES_MAX_KEY_SIZE, + .ivsize = AES_BLOCK_SIZE, + }, + }, +}, { + .cra_name = "rfc3686(ctr(aes))", + .cra_driver_name = "n5_rfc3686(ctr(aes))", + .cra_priority = 4001, + .cra_flags = CRYPTO_ALG_TYPE_ABLKCIPHER | CRYPTO_ALG_ASYNC, + .cra_blocksize = 1, + .cra_ctxsize = sizeof(struct nitrox_crypto_instance), + .cra_alignmask = 0, + .cra_type = &crypto_ablkcipher_type, + .cra_module = THIS_MODULE, + .cra_init = nitrox_ablkcipher_init, + .cra_exit = nitrox_ablkcipher_exit, + .cra_u = { + .ablkcipher = { + .setkey = nitrox_aes_ctr_rfc3686_setkey, + .decrypt = nitrox_aes_decrypt, + .encrypt = nitrox_aes_encrypt, + .min_keysize = AES_MIN_KEY_SIZE + + CTR_RFC3686_NONCE_SIZE, + .max_keysize = AES_MAX_KEY_SIZE + + CTR_RFC3686_NONCE_SIZE, + .ivsize = CTR_RFC3686_IV_SIZE, + }, + }, +}, { + .cra_name = "cts(cbc(aes))", + .cra_driver_name = "n5_cts(cbc(aes))", + .cra_priority = 4001, + .cra_flags = CRYPTO_ALG_TYPE_ABLKCIPHER | CRYPTO_ALG_ASYNC, + .cra_blocksize = AES_BLOCK_SIZE, + .cra_ctxsize = sizeof(struct nitrox_crypto_instance), + .cra_alignmask = 0, + .cra_type = &crypto_ablkcipher_type, + .cra_module = THIS_MODULE, + .cra_init = nitrox_ablkcipher_init, + .cra_exit = nitrox_ablkcipher_exit, + .cra_u = { + .ablkcipher = { + .setkey = nitrox_aes_setkey, + .decrypt = nitrox_aes_decrypt, + .encrypt = nitrox_aes_encrypt, + .min_keysize = AES_MIN_KEY_SIZE, + .max_keysize = AES_MAX_KEY_SIZE, + .ivsize = AES_BLOCK_SIZE, + }, + }, +} + +}; + +int nitrox_crypto_register(void) +{ + return crypto_register_algs(nitrox_algs, ARRAY_SIZE(nitrox_algs)); +} + +void nitrox_crypto_unregister(void) +{ + crypto_unregister_algs(nitrox_algs, ARRAY_SIZE(nitrox_algs)); +} diff --git a/drivers/crypto/cavium/nitrox/nitrox_common.h b/drivers/crypto/cavium/nitrox/nitrox_common.h index f79be7d..206a6d4 100644 --- a/drivers/crypto/cavium/nitrox/nitrox_common.h +++ b/drivers/crypto/cavium/nitrox/nitrox_common.h @@ -4,6 +4,13 @@ #include "nitrox_dev.h" #include "nitrox_req.h" +int nitrox_crypto_register(void); +void nitrox_crypto_unregister(void); +void *crypto_alloc_context(struct nitrox_device *ndev); +void crypto_free_context(void *ctx); +struct nitrox_device *nitrox_get_first_device(void); +void nitrox_put_device(struct nitrox_device *ndev); + void nitrox_pf_cleanup_isr(struct nitrox_device *ndev); int nitrox_pf_init_isr(struct nitrox_device *ndev); diff --git a/drivers/crypto/cavium/nitrox/nitrox_lib.c b/drivers/crypto/cavium/nitrox/nitrox_lib.c index ab77c21..637509f 100644 --- a/drivers/crypto/cavium/nitrox/nitrox_lib.c +++ b/drivers/crypto/cavium/nitrox/nitrox_lib.c @@ -135,6 +135,44 @@ static void destroy_crypto_dma_pool(struct nitrox_device *ndev) ndev->ctx_pool = NULL; } +/* + * crypto_alloc_context - Allocate crypto context from pool + * @ndev: NITROX Device + */ +void *crypto_alloc_context(struct nitrox_device *ndev) +{ + struct ctx_hdr *ctx; + void *vaddr; + dma_addr_t dma; + + vaddr = dma_pool_alloc(ndev->ctx_pool, (GFP_ATOMIC | __GFP_ZERO), &dma); + if (!vaddr) + return NULL; + + /* fill meta data */ + ctx = vaddr; + ctx->pool = ndev->ctx_pool; + ctx->dma = dma; + ctx->ctx_dma = dma + sizeof(struct ctx_hdr); + + return ((u8 *)vaddr + sizeof(struct ctx_hdr)); +} + +/** + * crypto_free_context - Free crypto context to pool + * @ctx: context to free + */ +void crypto_free_context(void *ctx) +{ + struct ctx_hdr *ctxp; + + if (!ctx) + return; + + ctxp = (struct ctx_hdr *)((u8 *)ctx - sizeof(struct ctx_hdr)); + dma_pool_free(ctxp->pool, ctxp, ctxp->dma); +} + /** * nitrox_common_sw_init - allocate software resources. * @ndev: NITROX device diff --git a/drivers/crypto/cavium/nitrox/nitrox_main.c b/drivers/crypto/cavium/nitrox/nitrox_main.c index 432a21b..f37b788 100644 --- a/drivers/crypto/cavium/nitrox/nitrox_main.c +++ b/drivers/crypto/cavium/nitrox/nitrox_main.c @@ -178,6 +178,35 @@ static void nitrox_remove_from_devlist(struct nitrox_device *ndev) mutex_unlock(&devlist_lock); } +struct nitrox_device *nitrox_get_first_device(void) +{ + struct nitrox_device *ndev = NULL; + + mutex_lock(&devlist_lock); + list_for_each_entry(ndev, &ndevlist, list) { + if (nitrox_ready(ndev)) + break; + } + mutex_unlock(&devlist_lock); + if (!ndev) + return NULL; + + atomic_inc(&ndev->refcnt); + /* barrier to sync with other cpus */ + smp_mb__after_atomic(); + return ndev; +} + +void nitrox_put_device(struct nitrox_device *ndev) +{ + if (!ndev) + return; + + atomic_dec(&ndev->refcnt); + /* barrier to sync with other cpus */ + smp_mb__after_atomic(); +} + static int nitrox_reset_device(struct pci_dev *pdev) { int pos = 0; @@ -527,8 +556,18 @@ static int nitrox_probe(struct pci_dev *pdev, const struct pci_device_id *id) set_bit(NITROX_READY, &ndev->status); /* barrier to sync with other cpus */ smp_mb__after_atomic(); + + err = nitrox_crypto_register(); + if (err) + goto crypto_fail; + return 0; +crypto_fail: + nitrox_debugfs_exit(ndev); + clear_bit(NITROX_READY, &ndev->status); + /* barrier to sync with other cpus */ + smp_mb__after_atomic(); pf_hw_fail: nitrox_pf_sw_cleanup(ndev); ioremap_err: @@ -564,6 +603,7 @@ static void nitrox_remove(struct pci_dev *pdev) smp_mb__after_atomic(); nitrox_remove_from_devlist(ndev); + nitrox_crypto_unregister(); nitrox_debugfs_exit(ndev); nitrox_pf_sw_cleanup(ndev); -- 2.9.3