From patchwork Thu Oct 13 14:53:43 2016 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Gary R Hook X-Patchwork-Id: 9375417 X-Patchwork-Delegate: herbert@gondor.apana.org.au Return-Path: Received: from mail.wl.linuxfoundation.org (pdx-wl-mail.web.codeaurora.org [172.30.200.125]) by pdx-korg-patchwork.web.codeaurora.org (Postfix) with ESMTP id 07B606075E for ; Thu, 13 Oct 2016 16:34:35 +0000 (UTC) Received: from mail.wl.linuxfoundation.org (localhost [127.0.0.1]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id EA3B42A16A for ; Thu, 13 Oct 2016 16:34:34 +0000 (UTC) Received: by mail.wl.linuxfoundation.org (Postfix, from userid 486) id DE7EE2A16C; Thu, 13 Oct 2016 16:34:34 +0000 (UTC) X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on pdx-wl-mail.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-6.8 required=2.0 tests=BAYES_00,DKIM_SIGNED, RCVD_IN_DNSWL_HI,T_DKIM_INVALID autolearn=ham version=3.3.1 Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id DE2682A16B for ; Thu, 13 Oct 2016 16:34:32 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1756852AbcJMQ2q (ORCPT ); Thu, 13 Oct 2016 12:28:46 -0400 Received: from mail-by2nam01on0052.outbound.protection.outlook.com ([104.47.34.52]:60960 "EHLO NAM01-BY2-obe.outbound.protection.outlook.com" rhost-flags-OK-OK-OK-FAIL) by vger.kernel.org with ESMTP id S1756462AbcJMQ2R (ORCPT ); Thu, 13 Oct 2016 12:28:17 -0400 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=amdcloud.onmicrosoft.com; s=selector1-amd-com; h=From:Date:Subject:Message-ID:Content-Type:MIME-Version; bh=isp4oLqvNCaB3GzyXi0dly7gSs1DB4S8mGUrfFDb5T4=; b=UT7fDVjPlFGd2mudzWO7oC99EhvWOHH6gpmHsfB7oPGXlTxXNqaFpTpK4BAXhshVWcG3H3p+XSbI0cQqINPS6CDoiXaQ1S/xsMi16CPGU+yPJiRc6XRPDJKeKeZBpVIBolkkA406ivNP/BeevKWgQMv7oI5XeJ78Pb7Gh2rGk8s= Authentication-Results: spf=none (sender IP is ) smtp.mailfrom=Gary.Hook@amd.com; Received: from [10.236.19.42] (165.204.77.1) by MWHPR12MB1405.namprd12.prod.outlook.com (10.169.206.16) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA384_P384) id 15.1.649.16; Thu, 13 Oct 2016 14:53:49 +0000 Subject: [PATCH 6/6] crypto: ccp - Enable 3DES function on v5 CCPs From: Gary R Hook To: CC: , , Date: Thu, 13 Oct 2016 09:53:43 -0500 Message-ID: <20161013145343.19759.84415.stgit@taos> In-Reply-To: <20161013144542.19759.6924.stgit@taos> References: <20161013144542.19759.6924.stgit@taos> User-Agent: StGit/0.17.1-dirty MIME-Version: 1.0 X-Originating-IP: [165.204.77.1] X-ClientProxiedBy: CY1PR08CA0015.namprd08.prod.outlook.com (10.163.94.153) To MWHPR12MB1405.namprd12.prod.outlook.com (10.169.206.16) X-MS-Office365-Filtering-Correlation-Id: e77cb05e-4013-4c6d-a255-08d3f378be24 X-Microsoft-Exchange-Diagnostics: 1; MWHPR12MB1405; 2:jLqy7+PPPwTJDXEXf823xdEvEgNIAN5PwQivzV7FA1ZmwSfK+2hCEA/vBbKLKNgRdHxvwvqkMzM8prtg3YdnQjN1iOguRt0FP78kFP7dgn/By+WQc5d8FLg+Jn0DBYcTNTTVA1s/QH4SgoD8gzul7LKQabsK1y+ZVWdFjXsHydUHJPCs13cMAX2PxZgXpEmw5CVuwnf3UXEIaTht97giMg==; 3:EX1qhX5vGBTlKmQvwF+cO9SrbMPTq/0VP86Ll0E2xyQZ9OU2RumK1LPerrqZC3Bur4JalAJD1jlYcCyxhiI6jjieCqtaUTw5nm5JPcFs28LuwW+dLUWGZ2qjqApBHPJyDCIfnfqPYwYYEqjNShVNcQ==; 25:6g5tc+iVlZ78Ta03PlZHN46DdHdducNjTidMxpMRHFXVv/1fSY/aqWBxxoheCF8RNd+pausgdVNEt76u35icbdjH7irX8ljFmn3jsekzoxAYZl4D3r8n3P5P5Ogmg0PaQOQHyJ98hv/6XmrcydVhQIMEn+5BMoADCGw+KJsJEHqi+iLVeADnmhdTyeWh0zBJBAmqLQXwYUb3vs0J+bzWeQ1Km4wrYIXG+B59JZGgfhs+t6F+FN3KdspbYTkjFdC1gEz2guV9xZv8jiT0LPF2VJwO3jPjXcO++qMdX8t0/nOWyP799nexVuVCGuDSOpGSsiaJuJ+ej0O0HD1rhDds7F3AGJ4zdK5MP7FkHtg44EifBjNpqp4wvdZawrk2zhX1puW3o+joYTcToXczRhB3smoQP2gIPW26bHpz+LnJZ4Y9MCyv8VLGoBGSo7Cq4APM X-Microsoft-Antispam: UriScan:;BCL:0;PCL:0;RULEID:;SRVR:MWHPR12MB1405; X-Microsoft-Exchange-Diagnostics: 1; MWHPR12MB1405; 31:+MEqwWAVKUCH6chShKvl88pnV9HnaXBsJHOlIVi3xDL19cZ5p6KWhtv7IOV/7HyhNazzeJcXw3sSYGbiKV2EJCAVQtj4Qnj2bya9T22tMcIPMB2cesme7wRj2cWvVhevm0hlC2x6xIOjONNJhFZJXfAxKLnwfctPCu3XrOq9MrVnjT1/C3QnEgs62qC22o/xX0rSskVYrGEYoWkgoAf9C3tNmGBKV+j/Wm8hnnCy+c5jqTNieFshw8bpr1+yV2tisPoGKl+sCQLjrSpYAv7Lrw==; 20:ycKjlHv16FkKQT5hGWtBDKLh7VOMITqEZ7T3LwOPWfdNtOsUc+eawwZUf3zsVVDAEVPkx5mfs49PXTMD/F8HrbfZkm5ZSz5GsTRafrsqUg/G9QHg3/ivpCZ1JxtySc5xw9v1lUxr8wddIjRPee92Y8E5FUi9il18COtb9XIYRnwuD3yvSIhYSWY63CgQkZzPEkKuTHg4451t7vxt+Nooc265EUrLCVY+HDbjDv/TsTiJbPvRn/c9OLNS+Z+ka7m+01bdOJrK0DMcb7TvqTRI7zvdcUpjCtqjFkSG1ICgAz4gexyBBtLqEVMzXartCkTOkh1PvIVKDUhDR2acYcsO5tQk8vjq989+7zPUCia986mbvQBfYl9X+hM4Ap7xK5E8kHp4d069lAz9/ahlBC80Zphsi3EiMNBVchx0920itoZ/yU98f7gxv/BfKS2jgtY2sVCBWRqIN1tKpaBcdNpU0O9fP2o2RtcfdDsE56wbRal1mGyLgFEgj+6hhm+gg7xZ X-Microsoft-Antispam-PRVS: X-Exchange-Antispam-Report-Test: UriScan:(767451399110); X-Exchange-Antispam-Report-CFA-Test: BCL:0; PCL:0; RULEID:(6040176)(601004)(2401047)(5005006)(8121501046)(10201501046)(3002001)(6055026); SRVR:MWHPR12MB1405; BCL:0; PCL:0; RULEID:; SRVR:MWHPR12MB1405; X-Microsoft-Exchange-Diagnostics: 1; MWHPR12MB1405; 4:EFLFZn4554zuJQa28G2jFwTV5PpBT2L+tGkT4bieNEBLlrDavvophy458I2eaMOiq9WVMGs6uH3hV9Hftn0nCJbpTycfzbdGKZNFFvw2BwQpZ5Qddae0MG974rj5TPjwn+jjDj79r2qzsPNu+4uhzm/WayE+bo0jb9uD/rtILmIMpmSFF5TP9fZofYHSXgqI+gT4+e84szVNu/kWzLiTmeguLerzno39wvf+i9ZJhXD4eNqGcLZ8pFfXKZTFkti1i8ycMSWw52N6mRn2EtX3WbyYkaD8G4KCVkLoyMIVqVZVwXgmzg+ACM817sTFiGPTTNbGO93SVCzDZdk26O8aL47EKeCxZ1mRJfBCWK0Ritcbw8h7KqKNPY2BWf9HwYQyq0qcwNHz2zePtebrEutY5Fwj/kYCbaD57E9vHOD49yOjZuybwr7xXOILEsVwWNIFYTNFAgjj5Zw2iuFxRWpAgw== X-Forefront-PRVS: 0094E3478A X-Forefront-Antispam-Report: SFV:NSPM; SFS:(10009020)(4630300001)(6009001)(6049001)(7916002)(199003)(189002)(9686002)(83506001)(7846002)(50466002)(105586002)(3846002)(305945005)(97736004)(4326007)(81156014)(33646002)(86362001)(7736002)(230700001)(97746001)(103116003)(23676002)(8676002)(1076002)(189998001)(101416001)(47776003)(4001350100001)(33716001)(66066001)(2906002)(586003)(68736007)(6116002)(19580405001)(54356999)(76176999)(50986999)(6666003)(77096005)(2950100002)(6916009)(81166006)(2351001)(5660300001)(229853001)(106356001)(42186005)(110136003)(92566002)(19580395003)(2004002); DIR:OUT; SFP:1101; SCL:1; SRVR:MWHPR12MB1405; H:[10.236.19.42]; FPR:; SPF:None; PTR:InfoNoRecords; A:1; MX:1; LANG:en; Received-SPF: None (protection.outlook.com: amd.com does not designate permitted sender hosts) X-Microsoft-Exchange-Diagnostics: =?utf-8?B?MTtNV0hQUjEyTUIxNDA1OzIzOlEwMmlIaUJKdWlVZ3VHUTVLcUEwNEJURE1l?= =?utf-8?B?Q2dFZDFuWUJ4TExlcXRtTW4yMkd1eS9ZQ2VCWENkcGlnVHcrRkJvSytvd3g1?= =?utf-8?B?WHY5SHF0cnhicGZzUmpLSW1vemZ0KzUvbklHa0xLNHNFcUZqSnZ3UGFpVEhU?= =?utf-8?B?dmlNd0JUTmZTQk9FWHowOFZMeWhlY2hjSitidWVCQVc5eE16RUZrSW1MVXE2?= =?utf-8?B?a1Nxa3ByWlM1cHNBemE3OC9sQVlOWkZvQld5SS8reGlwOHdSU1JOSWZPdkRK?= =?utf-8?B?czVuU1p5OCtIbnF5TElqUGdOd2NyK01aVXJ6SUZBc1psRngwZlgvVXFpK0RV?= =?utf-8?B?ejNucXUzZVJGWmlDL2RhVlJqaGhadUhDMWs4Qm5rWFdUb3lXb3hVeFJLbkt0?= =?utf-8?B?SEc2cEhyOEpSYlpYN2pGRi9BTDNKMmx6VjBRd05BVjBkMXlXL1NOSno0ZTRl?= =?utf-8?B?eDZVRG1ucFdBVjdHRTRoKzFSaUlZV0FxNTJMR0hPNFdGOEVJeXRTelZkdVg5?= =?utf-8?B?Y0cwdGVjUEJBNUpxQTgwaEg4dGpoWm02MkI5Z2JsNTRNdVI5dFJnSnJjVUxX?= =?utf-8?B?Rm1aMFNXUVNneGdhcVp5SjgzM0VYVlFGakxhWkFMb0hmL2dPT204OGl6aHNQ?= =?utf-8?B?bGtzL0wzamdDWWFuYnpON1FTbjQ1eEdmRzAzMllGTElZdStndDNGb1U1TTFS?= =?utf-8?B?NDQ3YWh1N3Z3UUY1SUl6aVpBalp5dVR3T1BTc28xVjYrNnhxbXZjSzZ1Mlpz?= =?utf-8?B?dGFIMmdWNi9NRnRzRkpVYldtaUFQR1hMQXJxWDBWNEVXUWhpbHk1U2hZUjJw?= =?utf-8?B?ZzZHRnlPL3VtdzZoVzdQVHVFQldyRWlqNlVpZVhhaWdZRktQSTV2Smh1RFpn?= =?utf-8?B?YTk3cjRyT3lVSXY3VlJESXVhU0FIU2c0aHpmd2Y3Tm5iaW1id1hHajduQkx5?= =?utf-8?B?V1JUUVlodVlVTkhDOVZNVFJpZEUwdG9OVTZJV1RPazhIb2Rjek96N0Y2eC9y?= =?utf-8?B?emp2M0xlVmxoUGxmUEJZYzdiYVQ2N2tXYThFdllYVDVvbzRpRnppWDNXQUVF?= =?utf-8?B?dFVMcy8rRDlRZGdERmxpdklaZU13NnVKdTg2Unk3QUx4Szhzc1NUUGR6S2pB?= =?utf-8?B?Y09kNUoyQXhWQ1dFUWFWSmM0YzMrUXJTVGs3WXRMWDBVNG9wNlFZTTc4bHNY?= =?utf-8?B?dmEzSldPS09GMWNDZU0rWmxWVjZpRmNMeHRsVHhBWFFSNGVLUk1Ka3I2cDM0?= =?utf-8?B?emFmN3YxNmErZlZuclBKbFdQa2VJc1ZoREFuNDdZYnpIdUtEL1IyOTJGSWFz?= =?utf-8?B?ZFdnbmIyTkdzeElTM1YxaVk2cHJDbE9Yd1hUN0hxc3dkZGdQbkF0ZGFMbll6?= =?utf-8?B?a0FMWmlIekhHa29ybkt6b3lwQzJOL2dOMS9YM0JCUXVhZEN5SHErL1BXSzB2?= =?utf-8?B?dXdqRjJoMVZEd1V0ZHlnS2ZHNUJGOXZDT3FyU3dyUThna3diQkEyRDI1Tm9K?= =?utf-8?B?cE9QWEJINkY3Z2srdGJEMm1kN3E5TUYrZlcwQU5iK1RORDBLNThJNHVqWU5G?= =?utf-8?B?dVlJVGF5cmt2Z0hDUHl0VDlVdVJnTmR4Y0UyWjJhOWxUQVM0NVJ1K2ozUnRs?= =?utf-8?B?cW5Eeld5a0Q3ampPd3F5dGR5NjkzU2dxN2duSGZULzJJdzM3cXh1c1N0TExk?= =?utf-8?B?czcvVFFYcG42QkEzbCtXQW93dDZFa3BHd1lVWWxKRHJVT0pqalMySFBSbmhu?= =?utf-8?B?MjB3bWYyRDF3SDNhN0xsZz09?= X-Microsoft-Exchange-Diagnostics: 1; MWHPR12MB1405; 6:hzjO3qr9wQKF0EXC5R3EtcAE8buz8q+W5sYB0Yz6oKMs5wnIDUnTwuwLjCBHxTFVTOxe5QM1mjl3t6JIUfXwemJ4nkdPIbr8BjGBu3aJSQAcRIkACrNBIIGipwnH61+R6FbO3f+ImvGSBBl3vHB3JV3onZixWNOA9aLSQaN6dzigDTh32wnqTyeBuqH1Za3nmgOs0C/fTKO826S6P6ZY6SHuN7F1c3dpuXG6A8wmVIJaC4F7IHTn+AMu2FTodP054jnYfsgjrdS/CG1V6RdfQkv9Cyg/xjkV8ZGQ05XFnjYsPoV5Q4Qb1mvAUwZ+vLBXdVlVG6h+v7N2qkYqVK51ZWNv6/9u1egskZpwUcQGQxM=; 5:gaU5i7TyJ+yYuD+DpMfyaxOivUDJfFAl8i9cqex9ewGjJ1XFw9EDlPRafTIflgvZnfWCeJF2vkq2VWnt/mKl7kLRBKYYL7B8i+rPBigYzmeEKO/1I7EAp6LrkQcpYN2wq66Y8zGAqhcv8qS2XKAEiE1wIjuVLk41TYVy/DYXZQg=; 24:s/lfvutABv8XZeiQlK98CgwgG+2Ky4j6F8eXjLSaIhJaOeash1byV1euGnyKjYwE+72/0q1AdCkdWC2Pv0pDx1Hi/d3c0Vkg0o8WGDDJegQ= SpamDiagnosticOutput: 1:99 SpamDiagnosticMetadata: NSPM X-Microsoft-Exchange-Diagnostics: 1; MWHPR12MB1405; 7:1vJZQgQXNrNFHdaCNfg8Ko2WjqsyK0Gq3HDeDGDZBJVArP6xXKwbjHVQLs6JOMjwJQ2kUojFuZ3rBTSqs3Qpa1X9QHwGKNyYLkkpPt/QG/VfXlgG0smrbKULniBnbgHpYBnCfN87vBcMrpFERD4G3QVQLhXYGm/Ltfa+4M3n38Hh5SUyW19M+ZqwEJrwGVeyn9qDLo5AwsPuKZbL38V7qK9kRT59zXW19vH4rB3bM0y6DTQvDe+rizwl/BKuAnuVCRwDIUn39G2AwMbaZxSxb/Ty/9+ByjTTGl6F08QzwrAThQR/ivGPyQebQxcuVB5GYorPHBnqfNYcLZ2+YKWtUBeLG111uKSjboX7+ZjltJ0=; 20:PI0Jp7TuNPmmhKrVYP7cwmuhSPMJQ/jICZ8Emts7rkN3IcFcVvMGCcC1VLPpDih6vW7+BIy7YIgIjSVHAUgL2ymSGIvp+cXBr4vxpoA5pgK8gnR3/atvtrN47oa/jkSElPzmhwKEa01I+yvm86O6tA9rWB60a0MlVK0kHeW/U1cpT+5jg0ecpRQFD3G13vuI75qIiTMplel74fsQsBX79eEoUVJbK7tcjOO/LAgmRotGwIh2ZrgWjd5P5EKy6um6 X-OriginatorOrg: amd.com X-MS-Exchange-CrossTenant-OriginalArrivalTime: 13 Oct 2016 14:53:49.7445 (UTC) X-MS-Exchange-CrossTenant-FromEntityHeader: Hosted X-MS-Exchange-Transport-CrossTenantHeadersStamped: MWHPR12MB1405 Sender: linux-crypto-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-crypto@vger.kernel.org X-Virus-Scanned: ClamAV using ClamSMTP Wire up support for Triple DES in ECB mode. Signed-off-by: Gary R Hook --- drivers/crypto/ccp/Makefile | 1 drivers/crypto/ccp/ccp-crypto-des3.c | 254 ++++++++++++++++++++++++++++++++++ drivers/crypto/ccp/ccp-crypto-main.c | 10 + drivers/crypto/ccp/ccp-crypto.h | 25 +++ drivers/crypto/ccp/ccp-dev-v3.c | 1 drivers/crypto/ccp/ccp-dev-v5.c | 65 ++++++++- drivers/crypto/ccp/ccp-dev.h | 18 ++ drivers/crypto/ccp/ccp-ops.c | 201 +++++++++++++++++++++++++++ drivers/crypto/ccp/ccp-pci.c | 2 include/linux/ccp.h | 57 +++++++- 10 files changed, 624 insertions(+), 10 deletions(-) create mode 100644 drivers/crypto/ccp/ccp-crypto-des3.c -- To unsubscribe from this list: send the line "unsubscribe linux-crypto" in the body of a message to majordomo@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html diff --git a/drivers/crypto/ccp/Makefile b/drivers/crypto/ccp/Makefile index fd77225..563594a 100644 --- a/drivers/crypto/ccp/Makefile +++ b/drivers/crypto/ccp/Makefile @@ -14,4 +14,5 @@ ccp-crypto-objs := ccp-crypto-main.o \ ccp-crypto-aes-xts.o \ ccp-crypto-rsa.o \ ccp-crypto-aes-galois.o \ + ccp-crypto-des3.o \ ccp-crypto-sha.o diff --git a/drivers/crypto/ccp/ccp-crypto-des3.c b/drivers/crypto/ccp/ccp-crypto-des3.c new file mode 100644 index 0000000..5af7347 --- /dev/null +++ b/drivers/crypto/ccp/ccp-crypto-des3.c @@ -0,0 +1,254 @@ +/* + * AMD Cryptographic Coprocessor (CCP) DES3 crypto API support + * + * Copyright (C) 2016 Advanced Micro Devices, Inc. + * + * Author: Gary R Hook + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + */ + +#include +#include +#include +#include +#include +#include +#include +#include + +#include "ccp-crypto.h" + +static int ccp_des3_complete(struct crypto_async_request *async_req, int ret) +{ + struct ablkcipher_request *req = ablkcipher_request_cast(async_req); + struct ccp_ctx *ctx = crypto_tfm_ctx(req->base.tfm); + struct ccp_des3_req_ctx *rctx = ablkcipher_request_ctx(req); + + if (ret) + return ret; + + if (ctx->u.des3.mode != CCP_DES3_MODE_ECB) + memcpy(req->info, rctx->iv, DES3_EDE_BLOCK_SIZE); + + return 0; +} + +static int ccp_des3_setkey(struct crypto_ablkcipher *tfm, const u8 *key, + unsigned int key_len) +{ + struct ccp_ctx *ctx = crypto_tfm_ctx(crypto_ablkcipher_tfm(tfm)); + struct ccp_crypto_ablkcipher_alg *alg = + ccp_crypto_ablkcipher_alg(crypto_ablkcipher_tfm(tfm)); + u32 *flags = &tfm->base.crt_flags; + + + /* From des_generic.c: + * + * RFC2451: + * If the first two or last two independent 64-bit keys are + * equal (k1 == k2 or k2 == k3), then the DES3 operation is simply the + * same as DES. Implementers MUST reject keys that exhibit this + * property. + */ + const u32 *K = (const u32 *)key; + + if (unlikely(!((K[0] ^ K[2]) | (K[1] ^ K[3])) || + !((K[2] ^ K[4]) | (K[3] ^ K[5]))) && + (*flags & CRYPTO_TFM_REQ_WEAK_KEY)) { + *flags |= CRYPTO_TFM_RES_WEAK_KEY; + return -EINVAL; + } + + /* It's not clear that there is any support for a keysize of 112. + * If needed, the caller should make K1 == K3 + */ + ctx->u.des3.type = CCP_DES3_TYPE_168; + ctx->u.des3.mode = alg->mode; + ctx->u.des3.key_len = key_len; + + memcpy(ctx->u.des3.key, key, key_len); + sg_init_one(&ctx->u.des3.key_sg, ctx->u.des3.key, key_len); + + return 0; +} + +static int ccp_des3_crypt(struct ablkcipher_request *req, bool encrypt) +{ + struct ccp_ctx *ctx = crypto_tfm_ctx(req->base.tfm); + struct ccp_des3_req_ctx *rctx = ablkcipher_request_ctx(req); + struct scatterlist *iv_sg = NULL; + unsigned int iv_len = 0; + int ret; + + if (!ctx->u.des3.key_len) + return -EINVAL; + + if (((ctx->u.des3.mode == CCP_DES3_MODE_ECB) || + (ctx->u.des3.mode == CCP_DES3_MODE_CBC)) && + (req->nbytes & (DES3_EDE_BLOCK_SIZE - 1))) + return -EINVAL; + + if (ctx->u.des3.mode != CCP_DES3_MODE_ECB) { + if (!req->info) + return -EINVAL; + + memcpy(rctx->iv, req->info, DES3_EDE_BLOCK_SIZE); + iv_sg = &rctx->iv_sg; + iv_len = DES3_EDE_BLOCK_SIZE; + sg_init_one(iv_sg, rctx->iv, iv_len); + } + + memset(&rctx->cmd, 0, sizeof(rctx->cmd)); + INIT_LIST_HEAD(&rctx->cmd.entry); + rctx->cmd.engine = CCP_ENGINE_DES3; + rctx->cmd.u.des3.type = ctx->u.des3.type; + rctx->cmd.u.des3.mode = ctx->u.des3.mode; + rctx->cmd.u.des3.action = (encrypt) + ? CCP_DES3_ACTION_ENCRYPT + : CCP_DES3_ACTION_DECRYPT; + rctx->cmd.u.des3.key = &ctx->u.des3.key_sg; + rctx->cmd.u.des3.key_len = ctx->u.des3.key_len; + rctx->cmd.u.des3.iv = iv_sg; + rctx->cmd.u.des3.iv_len = iv_len; + rctx->cmd.u.des3.src = req->src; + rctx->cmd.u.des3.src_len = req->nbytes; + rctx->cmd.u.des3.dst = req->dst; + + ret = ccp_crypto_enqueue_request(&req->base, &rctx->cmd); + + return ret; +} + +static int ccp_des3_encrypt(struct ablkcipher_request *req) +{ + return ccp_des3_crypt(req, true); +} + +static int ccp_des3_decrypt(struct ablkcipher_request *req) +{ + return ccp_des3_crypt(req, false); +} + +static int ccp_des3_cra_init(struct crypto_tfm *tfm) +{ + struct ccp_ctx *ctx = crypto_tfm_ctx(tfm); + + ctx->complete = ccp_des3_complete; + ctx->u.des3.key_len = 0; + + tfm->crt_ablkcipher.reqsize = sizeof(struct ccp_des3_req_ctx); + + return 0; +} + +static void ccp_des3_cra_exit(struct crypto_tfm *tfm) +{ +} + +static struct crypto_alg ccp_des3_defaults = { + .cra_flags = CRYPTO_ALG_TYPE_ABLKCIPHER | + CRYPTO_ALG_ASYNC | + CRYPTO_ALG_KERN_DRIVER_ONLY | + CRYPTO_ALG_NEED_FALLBACK, + .cra_blocksize = DES3_EDE_BLOCK_SIZE, + .cra_ctxsize = sizeof(struct ccp_ctx), + .cra_priority = CCP_CRA_PRIORITY, + .cra_type = &crypto_ablkcipher_type, + .cra_init = ccp_des3_cra_init, + .cra_exit = ccp_des3_cra_exit, + .cra_module = THIS_MODULE, + .cra_ablkcipher = { + .setkey = ccp_des3_setkey, + .encrypt = ccp_des3_encrypt, + .decrypt = ccp_des3_decrypt, + .min_keysize = DES3_EDE_KEY_SIZE, + .max_keysize = DES3_EDE_KEY_SIZE, + }, +}; + +struct ccp_des3_def { + enum ccp_des3_mode mode; + unsigned int version; + const char *name; + const char *driver_name; + unsigned int blocksize; + unsigned int ivsize; + struct crypto_alg *alg_defaults; +}; + +static struct ccp_des3_def des3_algs[] = { + { + .mode = CCP_DES3_MODE_ECB, + .version = CCP_VERSION(5, 0), + .name = "ecb(des3_ede)", + .driver_name = "ecb-des3-ccp", + .blocksize = DES3_EDE_BLOCK_SIZE, + .ivsize = 0, + .alg_defaults = &ccp_des3_defaults, + }, + { + .mode = CCP_DES3_MODE_CBC, + .version = CCP_VERSION(5, 0), + .name = "cbc(des3_ede)", + .driver_name = "cbc-des3-ccp", + .blocksize = DES3_EDE_BLOCK_SIZE, + .ivsize = DES3_EDE_BLOCK_SIZE, + .alg_defaults = &ccp_des3_defaults, + }, +}; + +static int ccp_register_des3_alg(struct list_head *head, + const struct ccp_des3_def *def) +{ + struct ccp_crypto_ablkcipher_alg *ccp_alg; + struct crypto_alg *alg; + int ret; + + ccp_alg = kzalloc(sizeof(*ccp_alg), GFP_KERNEL); + if (!ccp_alg) + return -ENOMEM; + + INIT_LIST_HEAD(&ccp_alg->entry); + + ccp_alg->mode = def->mode; + + /* Copy the defaults and override as necessary */ + alg = &ccp_alg->alg; + *alg = *def->alg_defaults; + snprintf(alg->cra_name, CRYPTO_MAX_ALG_NAME, "%s", def->name); + snprintf(alg->cra_driver_name, CRYPTO_MAX_ALG_NAME, "%s", + def->driver_name); + alg->cra_blocksize = def->blocksize; + alg->cra_ablkcipher.ivsize = def->ivsize; + + ret = crypto_register_alg(alg); + if (ret) { + pr_err("%s ablkcipher algorithm registration error (%d)\n", + alg->cra_name, ret); + kfree(ccp_alg); + return ret; + } + + list_add(&ccp_alg->entry, head); + + return 0; +} + +int ccp_register_des3_algs(struct list_head *head) +{ + int i, ret; + unsigned int ccpversion = ccp_version(); + + for (i = 0; i < ARRAY_SIZE(des3_algs); i++) { + if (des3_algs[i].version > ccpversion) + continue; + ret = ccp_register_des3_alg(head, &des3_algs[i]); + if (ret) + return ret; + } + + return 0; +} diff --git a/drivers/crypto/ccp/ccp-crypto-main.c b/drivers/crypto/ccp/ccp-crypto-main.c index 103a7b3..4b35329 100644 --- a/drivers/crypto/ccp/ccp-crypto-main.c +++ b/drivers/crypto/ccp/ccp-crypto-main.c @@ -37,6 +37,10 @@ static unsigned int rsa_disable; module_param(rsa_disable, uint, 0444); MODULE_PARM_DESC(rsa_disable, "Disable use of RSA - any non-zero value"); +static unsigned int des3_disable; +module_param(des3_disable, uint, 0444); +MODULE_PARM_DESC(des3_disable, "Disable use of 3DES - any non-zero value"); + /* List heads for the supported algorithms */ static LIST_HEAD(hash_algs); static LIST_HEAD(cipher_algs); @@ -346,6 +350,12 @@ static int ccp_register_algs(void) return ret; } + if (!des3_disable) { + ret = ccp_register_des3_algs(&cipher_algs); + if (ret) + return ret; + } + if (!sha_disable) { ret = ccp_register_sha_algs(&hash_algs); if (ret) diff --git a/drivers/crypto/ccp/ccp-crypto.h b/drivers/crypto/ccp/ccp-crypto.h index b2918f6..7b7f3b2 100644 --- a/drivers/crypto/ccp/ccp-crypto.h +++ b/drivers/crypto/ccp/ccp-crypto.h @@ -26,6 +26,8 @@ #include #include +#define CCP_LOG_LEVEL KERN_INFO + #define CCP_CRA_PRIORITY 300 struct ccp_crypto_ablkcipher_alg { @@ -151,7 +153,26 @@ struct ccp_aes_cmac_exp_ctx { u8 buf[AES_BLOCK_SIZE]; }; -/* SHA-related defines +/***** 3DES related defines *****/ +struct ccp_des3_ctx { + enum ccp_engine engine; + enum ccp_des3_type type; + enum ccp_des3_mode mode; + + struct scatterlist key_sg; + unsigned int key_len; + u8 key[AES_MAX_KEY_SIZE]; +}; + +struct ccp_des3_req_ctx { + struct scatterlist iv_sg; + u8 iv[AES_BLOCK_SIZE]; + + struct ccp_cmd cmd; +}; + +/* + * SHA-related defines * These values must be large enough to accommodate any variant */ #define MAX_SHA_CONTEXT_SIZE SHA512_DIGEST_SIZE @@ -236,6 +257,7 @@ struct ccp_ctx { struct ccp_aes_ctx aes; struct ccp_rsa_ctx rsa; struct ccp_sha_ctx sha; + struct ccp_des3_ctx des3; } u; }; @@ -251,5 +273,6 @@ int ccp_register_aes_aeads(struct list_head *head); int ccp_register_sha_algs(struct list_head *head); int ccp_register_rsa_algs(void); void ccp_unregister_rsa_algs(void); +int ccp_register_des3_algs(struct list_head *head); #endif diff --git a/drivers/crypto/ccp/ccp-dev-v3.c b/drivers/crypto/ccp/ccp-dev-v3.c index 75a0978..fccca16 100644 --- a/drivers/crypto/ccp/ccp-dev-v3.c +++ b/drivers/crypto/ccp/ccp-dev-v3.c @@ -595,6 +595,7 @@ static irqreturn_t ccp_irq_handler(int irq, void *data) static const struct ccp_actions ccp3_actions = { .aes = ccp_perform_aes, .xts_aes = ccp_perform_xts_aes, + .des3 = NULL, .sha = ccp_perform_sha, .rsa = ccp_perform_rsa, .passthru = ccp_perform_passthru, diff --git a/drivers/crypto/ccp/ccp-dev-v5.c b/drivers/crypto/ccp/ccp-dev-v5.c index dcae391..85387dc 100644 --- a/drivers/crypto/ccp/ccp-dev-v5.c +++ b/drivers/crypto/ccp/ccp-dev-v5.c @@ -101,6 +101,12 @@ union ccp_function { u16 type:2; } aes_xts; struct { + u16 size:7; + u16 encrypt:1; + u16 mode:5; + u16 type:2; + } des3; + struct { u16 rsvd1:10; u16 type:4; u16 rsvd2:1; @@ -132,6 +138,10 @@ union ccp_function { #define CCP_AES_TYPE(p) ((p)->aes.type) #define CCP_XTS_SIZE(p) ((p)->aes_xts.size) #define CCP_XTS_ENCRYPT(p) ((p)->aes_xts.encrypt) +#define CCP_DES3_SIZE(p) ((p)->des3.size) +#define CCP_DES3_ENCRYPT(p) ((p)->des3.encrypt) +#define CCP_DES3_MODE(p) ((p)->des3.mode) +#define CCP_DES3_TYPE(p) ((p)->des3.type) #define CCP_SHA_TYPE(p) ((p)->sha.type) #define CCP_RSA_SIZE(p) ((p)->rsa.size) #define CCP_PT_BYTESWAP(p) ((p)->pt.byteswap) @@ -242,13 +252,16 @@ static int ccp5_do_cmd(struct ccp5_desc *desc, /* Wait for the job to complete */ ret = wait_event_interruptible(cmd_q->int_queue, cmd_q->int_rcvd); - if (ret || cmd_q->cmd_error) { + if (cmd_q->cmd_error) { + /* + * Log the error and flush the queue by + * moving the head pointer + */ if (cmd_q->cmd_error) ccp_log_error(cmd_q->ccp, cmd_q->cmd_error); - /* A version 5 device doesn't use Job IDs... */ - if (!ret) - ret = -EIO; + iowrite32(tail, cmd_q->reg_head_lo); + ret = -EIO; } cmd_q->int_rcvd = 0; } @@ -381,6 +394,47 @@ static int ccp5_perform_sha(struct ccp_op *op) return ccp5_do_cmd(&desc, op->cmd_q); } +static int ccp5_perform_des3(struct ccp_op *op) +{ + struct ccp5_desc desc; + union ccp_function function; + u32 key_addr = op->sb_key * LSB_ITEM_SIZE; + + /* Zero out all the fields of the command desc */ + memset(&desc, 0, sizeof(struct ccp5_desc)); + + CCP5_CMD_ENGINE(&desc) = CCP_ENGINE_DES3; + + CCP5_CMD_SOC(&desc) = op->soc; + CCP5_CMD_IOC(&desc) = 1; + CCP5_CMD_INIT(&desc) = op->init; + CCP5_CMD_EOM(&desc) = op->eom; + CCP5_CMD_PROT(&desc) = 0; + + function.raw = 0; + CCP_DES3_ENCRYPT(&function) = op->u.des3.action; + CCP_DES3_MODE(&function) = op->u.des3.mode; + CCP_DES3_TYPE(&function) = op->u.des3.type; + CCP5_CMD_FUNCTION(&desc) = cpu_to_le32(function.raw); + + CCP5_CMD_LEN(&desc) = cpu_to_le32(op->src.u.dma.length); + + CCP5_CMD_SRC_LO(&desc) = cpu_to_le32(ccp_addr_lo(&op->src.u.dma)); + CCP5_CMD_SRC_HI(&desc) = cpu_to_le32(ccp_addr_hi(&op->src.u.dma)); + CCP5_CMD_SRC_MEM(&desc) = cpu_to_le32(CCP_MEMTYPE_SYSTEM); + + CCP5_CMD_DST_LO(&desc) = cpu_to_le32(ccp_addr_lo(&op->dst.u.dma)); + CCP5_CMD_DST_HI(&desc) = cpu_to_le32(ccp_addr_hi(&op->dst.u.dma)); + CCP5_CMD_DST_MEM(&desc) = cpu_to_le32(CCP_MEMTYPE_SYSTEM); + + CCP5_CMD_KEY_LO(&desc) = cpu_to_le32(lower_32_bits(key_addr)); + CCP5_CMD_KEY_HI(&desc) = 0; + CCP5_CMD_KEY_MEM(&desc) = cpu_to_le32(CCP_MEMTYPE_SB); + CCP5_CMD_LSB_ID(&desc) = cpu_to_le32(op->sb_ctx); + + return ccp5_do_cmd(&desc, op->cmd_q); +} + static int ccp5_perform_rsa(struct ccp_op *op) { struct ccp5_desc desc; @@ -428,6 +482,7 @@ static int ccp5_perform_passthru(struct ccp_op *op) struct ccp_dma_info *saddr = &op->src.u.dma; struct ccp_dma_info *daddr = &op->dst.u.dma; + memset(&desc, 0, Q_DESC_SIZE); CCP5_CMD_ENGINE(&desc) = CCP_ENGINE_PASSTHRU; @@ -722,6 +777,7 @@ static int ccp5_init(struct ccp_device *ccp) dev_dbg(dev, "queue #%u available\n", i); } + if (ccp->cmd_q_count == 0) { dev_notice(dev, "no command queues available\n"); ret = -EIO; @@ -991,6 +1047,7 @@ static const struct ccp_actions ccp5_actions = { .aes = ccp5_perform_aes, .xts_aes = ccp5_perform_xts_aes, .sha = ccp5_perform_sha, + .des3 = ccp5_perform_des3, .rsa = ccp5_perform_rsa, .passthru = ccp5_perform_passthru, .ecc = ccp5_perform_ecc, diff --git a/drivers/crypto/ccp/ccp-dev.h b/drivers/crypto/ccp/ccp-dev.h index a2214ac..12a92d5 100644 --- a/drivers/crypto/ccp/ccp-dev.h +++ b/drivers/crypto/ccp/ccp-dev.h @@ -27,6 +27,10 @@ #include #include +#ifndef CCP_LOG_LEVEL +#define CCP_LOG_LEVEL KERN_INFO +#endif + #define MAX_CCP_NAME_LEN 16 #define MAX_DMAPOOL_NAME_LEN 32 @@ -190,6 +194,9 @@ #define CCP_XTS_AES_KEY_SB_COUNT 1 #define CCP_XTS_AES_CTX_SB_COUNT 1 +#define CCP_DES3_KEY_SB_COUNT 1 +#define CCP_DES3_CTX_SB_COUNT 1 + #define CCP_SHA_SB_COUNT 1 #define CCP_RSA_MAX_WIDTH 4096 @@ -475,6 +482,12 @@ struct ccp_xts_aes_op { enum ccp_xts_aes_unit_size unit_size; }; +struct ccp_des3_op { + enum ccp_des3_type type; + enum ccp_des3_mode mode; + enum ccp_des3_action action; +}; + struct ccp_sha_op { enum ccp_sha_type type; u64 msg_bits; @@ -512,6 +525,7 @@ struct ccp_op { union { struct ccp_aes_op aes; struct ccp_xts_aes_op xts; + struct ccp_des3_op des3; struct ccp_sha_op sha; struct ccp_rsa_op rsa; struct ccp_passthru_op passthru; @@ -620,13 +634,13 @@ void ccp_dmaengine_unregister(struct ccp_device *ccp); struct ccp_actions { int (*aes)(struct ccp_op *); int (*xts_aes)(struct ccp_op *); + int (*des3)(struct ccp_op *); int (*sha)(struct ccp_op *); int (*rsa)(struct ccp_op *); int (*passthru)(struct ccp_op *); int (*ecc)(struct ccp_op *); u32 (*sballoc)(struct ccp_cmd_queue *, unsigned int); - void (*sbfree)(struct ccp_cmd_queue *, unsigned int, - unsigned int); + void (*sbfree)(struct ccp_cmd_queue *, unsigned int, unsigned int); unsigned int (*get_free_slots)(struct ccp_cmd_queue *); int (*init)(struct ccp_device *); void (*destroy)(struct ccp_device *); diff --git a/drivers/crypto/ccp/ccp-ops.c b/drivers/crypto/ccp/ccp-ops.c index de28867..f9543f7 100644 --- a/drivers/crypto/ccp/ccp-ops.c +++ b/drivers/crypto/ccp/ccp-ops.c @@ -16,6 +16,7 @@ #include #include #include +#include #include #include @@ -882,8 +883,7 @@ static int ccp_run_aes_cmd(struct ccp_cmd_queue *cmd_q, struct ccp_cmd *cmd) return -EINVAL; if (((aes->mode == CCP_AES_MODE_ECB) || - (aes->mode == CCP_AES_MODE_CBC) || - (aes->mode == CCP_AES_MODE_CFB)) && + (aes->mode == CCP_AES_MODE_CBC)) && (aes->src_len & (AES_BLOCK_SIZE - 1))) return -EINVAL; @@ -1194,6 +1194,200 @@ e_key: return ret; } +static int ccp_run_des3_cmd(struct ccp_cmd_queue *cmd_q, struct ccp_cmd *cmd) +{ + struct ccp_des3_engine *des3 = &cmd->u.des3; + + struct ccp_dm_workarea key, ctx; + struct ccp_data src, dst; + struct ccp_op op; + unsigned int dm_offset; + unsigned int len_singlekey; + bool in_place = false; + int ret; + + /* Error checks */ + if (!cmd_q->ccp->vdata->perform->des3) + return -EINVAL; + + if (des3->key_len != DES3_EDE_KEY_SIZE) + return -EINVAL; + + if (((des3->mode == CCP_DES3_MODE_ECB) || + (des3->mode == CCP_DES3_MODE_CBC)) && + (des3->src_len & (DES3_EDE_BLOCK_SIZE - 1))) + return -EINVAL; + + if (!des3->key || !des3->src || !des3->dst) + return -EINVAL; + + if (des3->mode != CCP_DES3_MODE_ECB) { + if (des3->iv_len != DES3_EDE_BLOCK_SIZE) + return -EINVAL; + + if (!des3->iv) + return -EINVAL; + } + + ret = -EIO; + /* Zero out all the fields of the command desc */ + memset(&op, 0, sizeof(op)); + + /* Set up the Function field */ + op.cmd_q = cmd_q; + op.jobid = CCP_NEW_JOBID(cmd_q->ccp); + op.sb_key = cmd_q->sb_key; + + op.init = (des3->mode == CCP_DES3_MODE_ECB) ? 0 : 1; + op.u.des3.type = des3->type; + op.u.des3.mode = des3->mode; + op.u.des3.action = des3->action; + + /* + * All supported key sizes fit in a single (32-byte) KSB entry and + * (like AES) must be in little endian format. Use the 256-bit byte + * swap passthru option to convert from big endian to little endian. + */ + ret = ccp_init_dm_workarea(&key, cmd_q, + CCP_DES3_KEY_SB_COUNT * CCP_SB_BYTES, + DMA_TO_DEVICE); + if (ret) + return ret; + + /* + * The contents of the key triplet are in the reverse order of what + * is required by the engine. Copy the 3 pieces individually to put + * them where they belong. + */ + dm_offset = CCP_SB_BYTES - des3->key_len; /* Basic offset */ + + len_singlekey = des3->key_len / 3; + ccp_set_dm_area(&key, dm_offset + 2 * len_singlekey, + des3->key, 0, len_singlekey); + ccp_set_dm_area(&key, dm_offset + len_singlekey, + des3->key, len_singlekey, len_singlekey); + ccp_set_dm_area(&key, dm_offset, + des3->key, 2 * len_singlekey, len_singlekey); + + /* Copy the key to the SB */ + ret = ccp_copy_to_sb(cmd_q, &key, op.jobid, op.sb_key, + CCP_PASSTHRU_BYTESWAP_256BIT); + if (ret) { + cmd->engine_error = cmd_q->cmd_error; + goto e_key; + } + + /* + * The DES3 context fits in a single (32-byte) KSB entry and + * must be in little endian format. Use the 256-bit byte swap + * passthru option to convert from big endian to little endian. + */ + if (des3->mode != CCP_DES3_MODE_ECB) { + u32 load_mode; + + op.sb_ctx = cmd_q->sb_ctx; + + ret = ccp_init_dm_workarea(&ctx, cmd_q, + CCP_DES3_CTX_SB_COUNT * CCP_SB_BYTES, + DMA_BIDIRECTIONAL); + if (ret) + goto e_key; + + /* Load the context into the LSB */ + dm_offset = CCP_SB_BYTES - des3->iv_len; + ccp_set_dm_area(&ctx, dm_offset, des3->iv, 0, des3->iv_len); + + if (cmd_q->ccp->vdata->version == CCP_VERSION(3, 0)) + load_mode = CCP_PASSTHRU_BYTESWAP_NOOP; + else + load_mode = CCP_PASSTHRU_BYTESWAP_256BIT; + ret = ccp_copy_to_sb(cmd_q, &ctx, op.jobid, op.sb_ctx, + load_mode); + if (ret) { + cmd->engine_error = cmd_q->cmd_error; + goto e_ctx; + } + } + + /* + * Prepare the input and output data workareas. For in-place + * operations we need to set the dma direction to BIDIRECTIONAL + * and copy the src workarea to the dst workarea. + */ + if (sg_virt(des3->src) == sg_virt(des3->dst)) + in_place = true; + + ret = ccp_init_data(&src, cmd_q, des3->src, des3->src_len, + DES3_EDE_BLOCK_SIZE, + in_place ? DMA_BIDIRECTIONAL : DMA_TO_DEVICE); + if (ret) + goto e_ctx; + + if (in_place) + dst = src; + else { + ret = ccp_init_data(&dst, cmd_q, des3->dst, des3->src_len, + DES3_EDE_BLOCK_SIZE, DMA_FROM_DEVICE); + if (ret) + goto e_src; + } + + /* Send data to the CCP DES3 engine */ + while (src.sg_wa.bytes_left) { + ccp_prepare_data(&src, &dst, &op, DES3_EDE_BLOCK_SIZE, true); + if (!src.sg_wa.bytes_left) { + op.eom = 1; + + /* Since we don't retrieve the context in ECB mode + * we have to wait for the operation to complete + * on the last piece of data + */ + op.soc = 0; + } + + ret = cmd_q->ccp->vdata->perform->des3(&op); + if (ret) { + cmd->engine_error = cmd_q->cmd_error; + goto e_dst; + } + + ccp_process_data(&src, &dst, &op); + } + + if (des3->mode != CCP_DES3_MODE_ECB) { + /* Retrieve the context and make BE */ + ret = ccp_copy_from_sb(cmd_q, &ctx, op.jobid, op.sb_ctx, + CCP_PASSTHRU_BYTESWAP_256BIT); + if (ret) { + cmd->engine_error = cmd_q->cmd_error; + goto e_dst; + } + + /* ...but we only need the last DES3_EDE_BLOCK_SIZE bytes */ + if (cmd_q->ccp->vdata->version == CCP_VERSION(3, 0)) + dm_offset = CCP_SB_BYTES - des3->iv_len; + else + dm_offset = 0; + ccp_get_dm_area(&ctx, dm_offset, des3->iv, 0, + DES3_EDE_BLOCK_SIZE); + } +e_dst: + if (!in_place) + ccp_free_data(&dst, cmd_q); + +e_src: + ccp_free_data(&src, cmd_q); + +e_ctx: + if (des3->mode != CCP_DES3_MODE_ECB) + ccp_dm_free(&ctx); + +e_key: + ccp_dm_free(&key); + + return ret; +} + static int ccp_run_sha_cmd(struct ccp_cmd_queue *cmd_q, struct ccp_cmd *cmd) { struct ccp_sha_engine *sha = &cmd->u.sha; @@ -2190,6 +2384,9 @@ int ccp_run_cmd(struct ccp_cmd_queue *cmd_q, struct ccp_cmd *cmd) case CCP_ENGINE_XTS_AES_128: ret = ccp_run_xts_aes_cmd(cmd_q, cmd); break; + case CCP_ENGINE_DES3: + ret = ccp_run_des3_cmd(cmd_q, cmd); + break; case CCP_ENGINE_SHA: ret = ccp_run_sha_cmd(cmd_q, cmd); break; diff --git a/drivers/crypto/ccp/ccp-pci.c b/drivers/crypto/ccp/ccp-pci.c index 28a9996..e9bdf6f 100644 --- a/drivers/crypto/ccp/ccp-pci.c +++ b/drivers/crypto/ccp/ccp-pci.c @@ -230,9 +230,11 @@ static int ccp_pci_probe(struct pci_dev *pdev, const struct pci_device_id *id) dev_set_drvdata(dev, ccp); + /* Instance-specific required setup */ if (ccp->vdata->setup) ccp->vdata->setup(ccp); + /* Initialize the CCP device */ ret = ccp->vdata->perform->init(ccp); if (ret) goto e_iomap; diff --git a/include/linux/ccp.h b/include/linux/ccp.h index f90f8ba..e7acc37 100644 --- a/include/linux/ccp.h +++ b/include/linux/ccp.h @@ -303,6 +303,60 @@ struct ccp_sha_engine { * final sha cmd */ }; +/***** 3DES engine *****/ +enum ccp_des3_mode { + CCP_DES3_MODE_ECB = 0, + CCP_DES3_MODE_CBC, + CCP_DES3_MODE_CFB, + CCP_DES3_MODE__LAST, +}; + +enum ccp_des3_type { + CCP_DES3_TYPE_168 = 1, + CCP_DES3_TYPE__LAST, + }; + +enum ccp_des3_action { + CCP_DES3_ACTION_DECRYPT = 0, + CCP_DES3_ACTION_ENCRYPT, + CCP_DES3_ACTION__LAST, +}; + +/** + * struct ccp_des3_engine - CCP SHA operation + * @type: Type of 3DES operation + * @mode: cipher mode + * @action: 3DES operation (decrypt/encrypt) + * @key: key to be used for this 3DES operation + * @key_len: length of key (in bytes) + * @iv: IV to be used for this AES operation + * @iv_len: length in bytes of iv + * @src: input data to be used for this operation + * @src_len: length of input data used for this operation (in bytes) + * @dst: output data produced by this operation + * + * Variables required to be set when calling ccp_enqueue_cmd(): + * - type, mode, action, key, key_len, src, dst, src_len + * - iv, iv_len for any mode other than ECB + * + * The iv variable is used as both input and output. On completion of the + * 3DES operation the new IV overwrites the old IV. + */ +struct ccp_des3_engine { + enum ccp_des3_type type; + enum ccp_des3_mode mode; + enum ccp_des3_action action; + + struct scatterlist *key; + u32 key_len; /* In bytes */ + + struct scatterlist *iv; + u32 iv_len; /* In bytes */ + + struct scatterlist *src, *dst; + u64 src_len; /* In bytes */ +}; + /** * ccp_rsa_type - mode of RSA operation * @@ -583,7 +637,7 @@ struct ccp_ecc_engine { enum ccp_engine { CCP_ENGINE_AES = 0, CCP_ENGINE_XTS_AES_128, - CCP_ENGINE_RSVD1, + CCP_ENGINE_DES3, CCP_ENGINE_SHA, CCP_ENGINE_RSA, CCP_ENGINE_PASSTHRU, @@ -631,6 +685,7 @@ struct ccp_cmd { union { struct ccp_aes_engine aes; struct ccp_xts_aes_engine xts; + struct ccp_des3_engine des3; struct ccp_sha_engine sha; struct ccp_rsa_engine rsa; struct ccp_passthru_engine passthru;