From patchwork Fri Nov 4 16:04:51 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: 9412777 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 F22386022E for ; Fri, 4 Nov 2016 16:05:02 +0000 (UTC) Received: from mail.wl.linuxfoundation.org (localhost [127.0.0.1]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id E02612B189 for ; Fri, 4 Nov 2016 16:05:02 +0000 (UTC) Received: by mail.wl.linuxfoundation.org (Postfix, from userid 486) id D29CC2B1BC; Fri, 4 Nov 2016 16:05:02 +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 879122B189 for ; Fri, 4 Nov 2016 16:05:01 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S964843AbcKDQFA (ORCPT ); Fri, 4 Nov 2016 12:05:00 -0400 Received: from mail-by2nam01on0085.outbound.protection.outlook.com ([104.47.34.85]:50648 "EHLO NAM01-BY2-obe.outbound.protection.outlook.com" rhost-flags-OK-OK-OK-FAIL) by vger.kernel.org with ESMTP id S932299AbcKDQE7 (ORCPT ); Fri, 4 Nov 2016 12:04:59 -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=Gn9fkXarPG774S7w0U5qUKbnCdRz70WAZWHFgSIqKus=; b=HN7rQoRzRCXMsakmr1qmCrF+XWKybVkJqsTID+ib5ZxfkDpp4tzvDbYsbOe7IMDu+EW3jCE9jySDBP0y6PmyaJsUGdoinRjx6pDVZ1dzYz9OuaqnQS/gpO9XNZj9U0tPNHT4Cq44YyAatU2OzyNnjL+0JMsFAwSm9/1me4IydTo= Authentication-Results: spf=none (sender IP is ) smtp.mailfrom=Gary.Hook@amd.com; Received: from [10.236.19.42] (165.204.77.1) by DM5PR12MB1402.namprd12.prod.outlook.com (10.168.238.141) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA384_P384) id 15.1.693.12; Fri, 4 Nov 2016 16:04:57 +0000 Subject: [PATCH V2 8/9] crypto: ccp - Enable support for AES GCM on v5 CCPs From: Gary R Hook To: CC: , , Date: Fri, 4 Nov 2016 11:04:51 -0500 Message-ID: <20161104160451.18155.26354.stgit@taos> In-Reply-To: <20161104160140.18155.75618.stgit@taos> References: <20161104160140.18155.75618.stgit@taos> User-Agent: StGit/0.17.1-dirty MIME-Version: 1.0 X-Originating-IP: [165.204.77.1] X-ClientProxiedBy: BLUPR08CA0040.namprd08.prod.outlook.com (10.141.200.20) To DM5PR12MB1402.namprd12.prod.outlook.com (10.168.238.141) X-MS-Office365-Filtering-Correlation-Id: ea7ff790-c41d-4299-d01f-08d404cc52f8 X-Microsoft-Exchange-Diagnostics: 1; DM5PR12MB1402; 2:voEfkRr18V4emW5nVsRtj2Al4TjK+3rsoVrNJ5L0vxRVHbzMDEOEEWWGUqCko385ApL+kAUPCc7RdRsNd7wd86tWelMHgcDGIwrVFDEp0TeNz2qjFLHMUPd98nI+91gniDRIzyAI9tH6m272K9PZMT5+8kpduBSS4vk9VZytyYvWPqlqx2Rhz8SKe9K8HP4BnPsFw3HwNhscORQlQCDTpg==; 3:gn0ao1kJIvqjKS74h9U/59GExVW3hLqDNC4nLaNpJsW+2l8nADH7eG7hd4/sWkwdh37KSTr8rct2rnUddAAuiZThhyYd/0apujnQxFWAgbBI3MXE0B8JvtYyxEqrO+mW7qZXD/z0KWxx5eXkG7STtg== X-Microsoft-Antispam: UriScan:;BCL:0;PCL:0;RULEID:;SRVR:DM5PR12MB1402; X-Microsoft-Exchange-Diagnostics: 1; DM5PR12MB1402; 25:qx9x8m/KS2vUtpOAqnk2bv+DzlXwUEacn3/IWROn6W9XOsZ+OA0y2pFCq07+wTTEQs56nYhW98U741Rj0+ucBrM7HHzOQ964PwElegrVNeiN43cRx/IVyED+6OYHeMSwI18kVVu7B+JeDXkYFs11jmFn6BKn3RmD9O3a1uoqD82/N/JgsSanqJEf6um5/AudlReiq7k9Bt1KbN/Nznp9vct/PblSLl/G6eepsvjJH0VEBQLoXuyM6xKa3kyxHgLCpp0xgd/nbO2mHiovAvx0vP32AnBBGP2vQZggpobui0R9zRm9+GSmnIia8zbRA/7iNXCrNZyjQ13ltXoNd+l94yYsE48lXIQjJ0Y3/4oFixnCs5YBPONuvdBGCWtyl7lQ89wafYD0sJF8d2kbRW8b/zFE0fZZXWjMNdlvvvmlOdlay0kIcAHpd2upBdv9i26IqOmWlAYcbz/udDlT2uPCND0YyS0HgFuQ5su/k1H0mZYQdRu1UiZ4jTM/7OAYQHX6tv27PCyxfSU97vRxagshFDPpZe4FiylBsh24zKj7Mag+6r8Y770OUBadEOi7tJw7yH4cruMm8Z9cN5WwqJm7WpBeQBvY21ZTLhyW7DKkIrAGZYsBK9cE++z+bxQ7dxpDXJ7zpjX86s7tly2cErBNSsnTFZfj6GwuWk+YGVH0ne1MAIAZG088FNZJArRNo5mSXlFftuBpbWsBOmruXtW6yA== X-Microsoft-Exchange-Diagnostics: 1; DM5PR12MB1402; 31:UNha/KQJp+h6RwrIYJFwAuNefURMf50MxNZDOFCIBDFcbwFaKG8Rjq7ccSkMuEihAN97bGygTXXDCqEGW/jlQD44b4cwKLS0MCIaP2G1s+Y7VfvHiAeV7GjCzvbRUkwd5oj6FBu3wI6PpqjDWZ7tXc1oxvl2giWssXyx1JfFawRKRt33us7s1zkFHJlsTjvMRoUjgwoQ1n7s0huvHsPwJDF7xk6wRRSOq7c5Bxxk8L89SiH8o1fgEjyIbXqahmJi; 20:nG571yKX1Y2Vn4/JLlN3HoQBY3Ncwkbl1Yivwz3g8ItMmXgq9mXf2MY66fDvMIl/vnh/mL8aznVxlO05gfcQcllsOnvUQlfJm/TxaldH3pjRAlW6+wUEpcMYToes5hPwXhvJNANE8L/3wntkB0mCwoQkDuRwHdazzbbPAxlhrVCYshBYb6dzc9q/D7lxnUbzurkBIaMyhoCv8PBjdEE9eOosHYLp3IRRuw0Orblz9BkIKCMd4GwiKOAGmrAF7IyDR7u4l8YsEHeynSAH6g0FXB3WodpZ2Mmylv7kCAlswvRuQYIoz6Bxv3sKT/nJz68nxssuVfNYnwC1f73rZwJZNmHuB+1VnHm6NRmO5xjoMLZfUwdzQmqsUXxqG2EvdIVx1z9Lpe6ZusEFNr55bVGapBiAkM288+VHV2I8aKVMVEyylaaxagNpa+TY0AcSdYD2xxrI4pKd/RnQRUtJip9zH9WilNaXhhWXUueYu/WunZ6L2fizQwWQ73zf8R97FoFO 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)(8121501046)(5005006)(10201501046)(3002001)(6055026); SRVR:DM5PR12MB1402; BCL:0; PCL:0; RULEID:; SRVR:DM5PR12MB1402; X-Microsoft-Exchange-Diagnostics: 1; DM5PR12MB1402; 4:CbAXBAUFCMbLTcxulHvoPG49FSp6s5eHwY7PyIuWp8gy4Cz7Ue9oYJ5/1UZRDRm3nbdSOZMUVANapU77++OmLWjdVOvBZW8VBoDUje5M0gJ7H2rnOUDBPuHUsJ8akhZnn0ktmNT6dvWkpBNq4jr2GEQVkbv4kT/S5BeJ8DlNUpktTb9K1AyT6XbTcK+l+jF97u24Yynrm+DqmIc1QsDRDquLYXfVQp+Q8rBEM3acCOFqyE04LyWYAUA/QPDn0RuNHxsX6ho5tIEwB6Cc0/J6ZtXFKQV5r8rPQfOjX6Hf+z9JZZhXwfY9yoJPLA1ZlULr/7/NDegcLtkLxfMeczUGmHuoKmOmIS8Sbwlr69exIDV5EvprhQcrc/EqYhcyP6JubU+SBU87BksxYhqWDyiUI7gaqtXa/SEhZ/gCA8G864izAQUSD3T4nCMmBTaZ0RanVAu1JbhVZ1RC2Piqy5Qyxg== X-Forefront-PRVS: 01165471DB X-Forefront-Antispam-Report: SFV:NSPM; SFS:(10009020)(4630300001)(6049001)(6009001)(7916002)(199003)(189002)(81156014)(97736004)(6116002)(77096005)(86362001)(6666003)(4001350100001)(97746001)(586003)(92566002)(8676002)(54356999)(68736007)(33646002)(66066001)(76176999)(3846002)(50986999)(50466002)(81166006)(101416001)(19580395003)(2906002)(1076002)(7846002)(106356001)(6916009)(7736002)(229853001)(189998001)(305945005)(103116003)(42186005)(105586002)(33716001)(83506001)(9686002)(110136003)(2950100002)(2351001)(23676002)(47776003)(5660300001)(230700001)(4326007)(19580405001)(2004002)(217873001); DIR:OUT; SFP:1101; SCL:1; SRVR:DM5PR12MB1402; 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?MTtETTVQUjEyTUIxNDAyOzIzOjVmeXJlRS9zY1hUTFQxQ3k1a3lkWFBqcGo0?= =?utf-8?B?bjZNdWRWejBYMG16emFEVmgxcUFDR1lZV25PbktpUWJndE5hWHFOa0JvSjd6?= =?utf-8?B?THRUYk5yRzRDaDJ1aFM4Z0NueCtxNElrc3VNeGt3MndUcGtzUDhIU2JLQ01Q?= =?utf-8?B?NkRsWEVNR1VRVldTVnBQdnFpc0ZhKzBxbFlZYjdteFduTTBSMnNBUVFLVXVt?= =?utf-8?B?c2FhMTViUTdPZHl1anR0UGpoVW1TQ3JvMFlHbTFxaUFXZzZLaHFCaWZHWW1X?= =?utf-8?B?YmFQcEc2Nk5sUERPNk5xTkkvQ3JMeW1yQVFvOHo1NHNUaitydUhtQjFvK0h4?= =?utf-8?B?b2dEd3hqNDdzKzZ3K3pmNzEwUEhUelRndmM2a1M4bi9nVFI1ZVJHZW1COGVx?= =?utf-8?B?U0oyOG1IejFEWmhCN0Z1Um0vUEdiV2xHQlF2QnZEeUYveXJPTlZjclNjQkhW?= =?utf-8?B?ZTF4bVZHbUwvTzRGdk1YTWo2T1Ira3RMSklQMktZSUM4czdBT25kcko4eUpI?= =?utf-8?B?cGRGdXZrZ3JVdHdzeGtvVWdDWlk5K0FUdlVEdDEyQmFBTGhpSm1VNWZTWUlK?= =?utf-8?B?TTFwcm5SVkFmL1BZL21SeVhGUHByRG8rdFNjVUQxeDhOVFlnYkw4Tks0NkhC?= =?utf-8?B?b2hLRFNueHIyL1ZycW1MYUc3SGQ4MkhGbGp5dUI3YjNlWjRCVXpXTzZYM3pK?= =?utf-8?B?NU1SUnEycjczeEZURjVrSnYzL0gxbWN6a3d2WjJ0d0hlYWppUndsN1BVRmpJ?= =?utf-8?B?NW5sT1ZzWnpPa3psOGl2bGQ2N3BxT0poSkUxdUM4U01sbzRieEJ6OWczMVlu?= =?utf-8?B?Z3BERjI5OHd2OTNVRUt5QVFRYzZJb3FEZ0N5UVBIdWxFS252YzZkSWQ2aHFm?= =?utf-8?B?bFplNmtGM01hVkZlbTdycHE5TTN1a1FkczczS1ArektBOVM3WUpWVGdIWG5v?= =?utf-8?B?Q2d5Mm9OMUhqbXptb0xiL0dud0hoVmg1dFhGUWloNUppZGVKYUNPSml6N3BT?= =?utf-8?B?Q2RIMWlLREcwL3FOdXRtQ1lRblNZRHBXb0lWdE1paDF4UkoybU0wajlqSk9Y?= =?utf-8?B?VC9CeXo0MUdmM2Y2MWtSajVRRnBEYnd4b2dEZWI0ZzNzbW1KZ2JValRKZ0o2?= =?utf-8?B?bGZzaXZ0Mnh2RXk1TGp3cFJ3ZXhORFZEQlRnbmx0YzFWYUo5QmR0S2VMcGhv?= =?utf-8?B?TUZiOVZKVFlDQ21QK0YrQ29DN3hMOUQxaFRiSkxXT2xac2J0Q3UrY25OMjdC?= =?utf-8?B?ODlta3pwRWoxcVN3L1M1SE5Xb2hKUFNFc21PQnBvMnFyaWRuNElJM1hjSU9x?= =?utf-8?B?L0NkNENyM0s0QURwWmJsL3A3TVJFU1FyY1h3VU5OREJJdGdPSVlyUEZsV1Qz?= =?utf-8?B?TjRraHhBYkltY2cvWjU1a3BpbWlaQ3c0YktZeGg0MkEyRkxsenJ4dEtFQk5M?= =?utf-8?B?Z2FrYXgyWHk1NjJFclZEaUJNOElEb0UrejNBcS9WbFNIZ2NvMGpjemxJN0lE?= =?utf-8?B?RU42TTVKOW8wUXh0L2tGa2VodEc5T3RabklLQjM2UzlnSEZ5THZsd0NBQk8r?= =?utf-8?B?Sld0KzVOcmZQeGl4YVBKV3V6d3RtY1RjM3VMMHR3UUFJQmpHWmYrSWFMQVJp?= =?utf-8?B?V3pIcTM3VnE0YWt6ejkrRThtSDJkeUFkdStXeEZrYkpzUWJPNXVPdWFWczY3?= =?utf-8?B?bHZMMENVQStzRjd3K3Z2RmF3SlBCRVBjaE9wNzFhMG9ZRDJzL3hJaGNrNnZ3?= =?utf-8?Q?rtxB2XV0M3m1ydUrsB/rlpyjwDehOE92esBE0=3D?= X-Microsoft-Exchange-Diagnostics: 1; DM5PR12MB1402; 6:XRZ/lEwT1a43qfS2EeBCQK3YE6W5iobq1UeZNA/v7Q54e2DHbfCeyRSF95uPBpFN5BZlPJiXmQoJktaO+tsFci4NXqtWKlovC0V63xW2rJoib5NRBRh6x0z8oJejbGybvo8NU6peE23Zr0zbA6G/j7LdBT25r60VOcTb9VMx98n6Gy5sl70qTkmBNcPyOpWYZtIaonJZoUONAfCaNgOKw5e1A7W1kPBesjb3Q+s5+AzHsOX/4fAY+nekCWlTkxCnsBnjgJgbIbCdRDJdb1+PHq7NOa4WnSWrnIAqlEAmKMB0OUPy6B/10K2zVXQcfYsfXWgCaDdS4IrQ8D8lqh/KYg==; 5:UezKbpGa+6bwHoESqCN+wSgLlgca1PhR8vlR0RpuCVqkTISzakro4N6upJcekpf5tn0Wha4Bw0JdcIt+bD4YDQuD3oh4X8Y0Dtaeob2FW1leVeuXL+RcZ0OISOFMow9VE7WNT+SAebgg/w65DXgHQ5i5Ipt2fgr1nk+gSqTFSqA=; 24:peJF9jooYdtsu53PePLlDo9Q6t4zVpeyKkdOj6h1FwG3vFvgDDph7vN5oEF0g32ztQYo7PiLBaLP3SsGSGkkxQzdny8YhS2oUavkzJihEqk= SpamDiagnosticOutput: 1:99 SpamDiagnosticMetadata: NSPM X-Microsoft-Exchange-Diagnostics: 1; DM5PR12MB1402; 7:g2/EboNDkqaajXmkv9W6VzG/uMr4pZkToZyosoMlD39jwmwwnX8uP/8VYEtAVdC/7T3aQLRImln4s4XyMhIMBulOqh2loG9aZnrFkPlCCwD6OVt+CHKZDtE0vb61tWzCQYcDscZy3eGNQn+ka5JOwyA8fad8CEcAp91zxNB56eX1mVVSoqWhnpuFpKbLScdAClbvlCyTflqnf4LmXREZm9gU2wvAHs8Mv4kzmSHJy4b1XD61uDqAHd20lWJSVV8YxGjYhEdMOnZ5DY6QchdAq1IV+SjFKpRN6Gk2s0AnDujtiyzlLhE0OQG6GwJF1MVAac7FINs/sUD484IuljYP7crzz2MkrD1kQdD3PjK1CYQ=; 20:hoRZIVzyBd0EiryOFWa3E1OKJCqvBG9oj0OgMbDgLufDmKb+hTMtMBQPQVgCbc9QNgOQxkCtlQZyOidq0MeZe/jjWT8bnUeDqDA2gmxW7L+bVNUuGoFTxO3qQLxIkt7Fx4og5eGvPPEIqEDR8x6pjVtm0843Et7FghETIfJrGnrou7gqE5bklAYzvfaJZ01LmYW0hN7cUXDaMixcJSnTnTjAA6xrr/n3Rgwgt8ft34hcqn18HXsHT+D3Hcf8Ogs5 X-OriginatorOrg: amd.com X-MS-Exchange-CrossTenant-OriginalArrivalTime: 04 Nov 2016 16:04:57.2505 (UTC) X-MS-Exchange-CrossTenant-FromEntityHeader: Hosted X-MS-Exchange-Transport-CrossTenantHeadersStamped: DM5PR12MB1402 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 A version 5 device provides the primitive commands required for AES GCM. This patch adds support for en/decryption. Signed-off-by: Gary R Hook --- drivers/crypto/ccp/Makefile | 1 drivers/crypto/ccp/ccp-crypto-aes-galois.c | 257 ++++++++++++++++++++++++++++ drivers/crypto/ccp/ccp-crypto-main.c | 12 + drivers/crypto/ccp/ccp-crypto.h | 14 ++ drivers/crypto/ccp/ccp-dev-v5.c | 2 drivers/crypto/ccp/ccp-dev.h | 1 drivers/crypto/ccp/ccp-ops.c | 252 +++++++++++++++++++++++++++ include/linux/ccp.h | 9 + 8 files changed, 548 insertions(+) create mode 100644 drivers/crypto/ccp/ccp-crypto-aes-galois.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 23f89b7..fd77225 100644 --- a/drivers/crypto/ccp/Makefile +++ b/drivers/crypto/ccp/Makefile @@ -13,4 +13,5 @@ ccp-crypto-objs := ccp-crypto-main.o \ ccp-crypto-aes-cmac.o \ ccp-crypto-aes-xts.o \ ccp-crypto-rsa.o \ + ccp-crypto-aes-galois.o \ ccp-crypto-sha.o diff --git a/drivers/crypto/ccp/ccp-crypto-aes-galois.c b/drivers/crypto/ccp/ccp-crypto-aes-galois.c new file mode 100644 index 0000000..8bc18c9 --- /dev/null +++ b/drivers/crypto/ccp/ccp-crypto-aes-galois.c @@ -0,0 +1,257 @@ +/* + * AMD Cryptographic Coprocessor (CCP) AES GCM 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 +#include +#include + +#include "ccp-crypto.h" + +#define AES_GCM_IVSIZE 12 + +static int ccp_aes_gcm_complete(struct crypto_async_request *async_req, int ret) +{ + return ret; +} + +static int ccp_aes_gcm_setkey(struct crypto_aead *tfm, const u8 *key, + unsigned int key_len) +{ + struct ccp_ctx *ctx = crypto_aead_ctx(tfm); + + switch (key_len) { + case AES_KEYSIZE_128: + ctx->u.aes.type = CCP_AES_TYPE_128; + break; + case AES_KEYSIZE_192: + ctx->u.aes.type = CCP_AES_TYPE_192; + break; + case AES_KEYSIZE_256: + ctx->u.aes.type = CCP_AES_TYPE_256; + break; + default: + crypto_aead_set_flags(tfm, CRYPTO_TFM_RES_BAD_KEY_LEN); + return -EINVAL; + } + + ctx->u.aes.mode = CCP_AES_MODE_GCM; + ctx->u.aes.key_len = key_len; + + memcpy(ctx->u.aes.key, key, key_len); + sg_init_one(&ctx->u.aes.key_sg, ctx->u.aes.key, key_len); + + return 0; +} + +static int ccp_aes_gcm_setauthsize(struct crypto_aead *tfm, + unsigned int authsize) +{ + return 0; +} + +static int ccp_aes_gcm_crypt(struct aead_request *req, bool encrypt) +{ + struct crypto_aead *tfm = crypto_aead_reqtfm(req); + struct ccp_ctx *ctx = crypto_aead_ctx(tfm); + struct ccp_aes_req_ctx *rctx = aead_request_ctx(req); + struct scatterlist *iv_sg = NULL; + unsigned int iv_len = 0; + int i; + int ret = 0; + + if (!ctx->u.aes.key_len) + return -EINVAL; + + if (ctx->u.aes.mode != CCP_AES_MODE_GCM) + return -EINVAL; + + if (!req->iv) + return -EINVAL; + + /* + * 5 parts: + * plaintext/ciphertext input + * AAD + * key + * IV + * Destination+tag buffer + */ + + /* According to the way AES GCM has been implemented here, + * per RFC 4106 it seems, the provided IV is fixed at 12 bytes, + * occupies the beginning of the IV array. Write a 32-bit + * integer after that (bytes 13-16) with a value of "1". + */ + memcpy(rctx->iv, req->iv, AES_GCM_IVSIZE); + for (i = 0; i < 3; i++) + rctx->iv[i + AES_GCM_IVSIZE] = 0; + rctx->iv[AES_BLOCK_SIZE - 1] = 1; + + /* Set up a scatterlist for the IV */ + iv_sg = &rctx->iv_sg; + iv_len = AES_BLOCK_SIZE; + sg_init_one(iv_sg, rctx->iv, iv_len); + + /* The AAD + plaintext are concatenated in the src buffer */ + memset(&rctx->cmd, 0, sizeof(rctx->cmd)); + INIT_LIST_HEAD(&rctx->cmd.entry); + rctx->cmd.engine = CCP_ENGINE_AES; + rctx->cmd.u.aes.type = ctx->u.aes.type; + rctx->cmd.u.aes.mode = ctx->u.aes.mode; + rctx->cmd.u.aes.action = + (encrypt) ? CCP_AES_ACTION_ENCRYPT : CCP_AES_ACTION_DECRYPT; + rctx->cmd.u.aes.key = &ctx->u.aes.key_sg; + rctx->cmd.u.aes.key_len = ctx->u.aes.key_len; + rctx->cmd.u.aes.iv = iv_sg; + rctx->cmd.u.aes.iv_len = iv_len; + rctx->cmd.u.aes.src = req->src; + rctx->cmd.u.aes.src_len = req->cryptlen; + rctx->cmd.u.aes.aad_len = req->assoclen; + + /* The cipher text + the tag are in the dst buffer */ + rctx->cmd.u.aes.dst = req->dst; + + ret = ccp_crypto_enqueue_request(&req->base, &rctx->cmd); + + return ret; +} + +static int ccp_aes_gcm_encrypt(struct aead_request *req) +{ + return ccp_aes_gcm_crypt(req, true); +} + +static int ccp_aes_gcm_decrypt(struct aead_request *req) +{ + return ccp_aes_gcm_crypt(req, false); +} + +static int ccp_aes_gcm_cra_init(struct crypto_aead *tfm) +{ + struct ccp_ctx *ctx = crypto_aead_ctx(tfm); + + ctx->complete = ccp_aes_gcm_complete; + ctx->u.aes.key_len = 0; + + crypto_aead_set_reqsize(tfm, sizeof(struct ccp_aes_req_ctx)); + + return 0; +} + +static void ccp_aes_gcm_cra_exit(struct crypto_tfm *tfm) +{ +} + +static struct aead_alg ccp_aes_gcm_defaults = { + .setkey = ccp_aes_gcm_setkey, + .setauthsize = ccp_aes_gcm_setauthsize, + .encrypt = ccp_aes_gcm_encrypt, + .decrypt = ccp_aes_gcm_decrypt, + .init = ccp_aes_gcm_cra_init, + .ivsize = AES_GCM_IVSIZE, + .maxauthsize = AES_BLOCK_SIZE, + .base = { + .cra_flags = CRYPTO_ALG_TYPE_ABLKCIPHER | + CRYPTO_ALG_ASYNC | + CRYPTO_ALG_KERN_DRIVER_ONLY | + CRYPTO_ALG_NEED_FALLBACK, + .cra_blocksize = AES_BLOCK_SIZE, + .cra_ctxsize = sizeof(struct ccp_ctx), + .cra_priority = CCP_CRA_PRIORITY, + .cra_type = &crypto_ablkcipher_type, + .cra_exit = ccp_aes_gcm_cra_exit, + .cra_module = THIS_MODULE, + }, +}; + +struct ccp_aes_aead_def { + enum ccp_aes_mode mode; + unsigned int version; + const char *name; + const char *driver_name; + unsigned int blocksize; + unsigned int ivsize; + struct aead_alg *alg_defaults; +}; + +static struct ccp_aes_aead_def aes_aead_algs[] = { + { + .mode = CCP_AES_MODE_GHASH, + .version = CCP_VERSION(5, 0), + .name = "gcm(aes)", + .driver_name = "gcm-aes-ccp", + .blocksize = 1, + .ivsize = AES_BLOCK_SIZE, + .alg_defaults = &ccp_aes_gcm_defaults, + }, +}; + +static int ccp_register_aes_aead(struct list_head *head, + const struct ccp_aes_aead_def *def) +{ + struct ccp_crypto_aead *ccp_aead; + struct aead_alg *alg; + int ret; + + ccp_aead = kzalloc(sizeof(*ccp_aead), GFP_KERNEL); + if (!ccp_aead) + return -ENOMEM; + + INIT_LIST_HEAD(&ccp_aead->entry); + + ccp_aead->mode = def->mode; + + /* Copy the defaults and override as necessary */ + alg = &ccp_aead->alg; + *alg = *def->alg_defaults; + snprintf(alg->base.cra_name, CRYPTO_MAX_ALG_NAME, "%s", def->name); + snprintf(alg->base.cra_driver_name, CRYPTO_MAX_ALG_NAME, "%s", + def->driver_name); + alg->base.cra_blocksize = def->blocksize; + alg->base.cra_ablkcipher.ivsize = def->ivsize; + + ret = crypto_register_aead(alg); + if (ret) { + pr_err("%s ablkcipher algorithm registration error (%d)\n", + alg->base.cra_name, ret); + kfree(ccp_aead); + return ret; + } + + list_add(&ccp_aead->entry, head); + + return 0; +} + +int ccp_register_aes_aeads(struct list_head *head) +{ + int i, ret; + unsigned int ccpversion = ccp_version(); + + for (i = 0; i < ARRAY_SIZE(aes_aead_algs); i++) { + if (aes_aead_algs[i].version > ccpversion) + continue; + ret = ccp_register_aes_aead(head, &aes_aead_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 38d4466..e68012a 100644 --- a/drivers/crypto/ccp/ccp-crypto-main.c +++ b/drivers/crypto/ccp/ccp-crypto-main.c @@ -42,6 +42,7 @@ static LIST_HEAD(hash_algs); static LIST_HEAD(cipher_algs); static LIST_HEAD(akcipher_algs); +static LIST_HEAD(aead_algs); /* For any tfm, requests for that tfm must be returned on the order * received. With multiple queues available, the CCP can process more @@ -341,6 +342,10 @@ static int ccp_register_algs(void) ret = ccp_register_aes_xts_algs(&cipher_algs); if (ret) return ret; + + ret = ccp_register_aes_aeads(&aead_algs); + if (ret) + return ret; } if (!sha_disable) { @@ -363,6 +368,7 @@ static void ccp_unregister_algs(void) struct ccp_crypto_ahash_alg *ahash_alg, *ahash_tmp; struct ccp_crypto_ablkcipher_alg *ablk_alg, *ablk_tmp; struct ccp_crypto_akcipher_alg *ak_alg, *ak_tmp; + struct ccp_crypto_aead *aead_alg, *aead_tmp; list_for_each_entry_safe(ahash_alg, ahash_tmp, &hash_algs, entry) { crypto_unregister_ahash(&ahash_alg->alg); @@ -381,6 +387,12 @@ static void ccp_unregister_algs(void) list_del(&ak_alg->entry); kfree(ak_alg); } + + list_for_each_entry_safe(aead_alg, aead_tmp, &aead_algs, entry) { + crypto_unregister_aead(&aead_alg->alg); + list_del(&aead_alg->entry); + kfree(aead_alg); + } } static int ccp_crypto_init(void) diff --git a/drivers/crypto/ccp/ccp-crypto.h b/drivers/crypto/ccp/ccp-crypto.h index 76d8b63..cc5044c 100644 --- a/drivers/crypto/ccp/ccp-crypto.h +++ b/drivers/crypto/ccp/ccp-crypto.h @@ -19,6 +19,8 @@ #include #include #include +#include +#include #include #include #include @@ -35,6 +37,14 @@ struct ccp_crypto_ablkcipher_alg { struct crypto_alg alg; }; +struct ccp_crypto_aead { + struct list_head entry; + + u32 mode; + + struct aead_alg alg; +}; + struct ccp_crypto_ahash_alg { struct list_head entry; @@ -103,6 +113,9 @@ struct ccp_aes_req_ctx { struct scatterlist iv_sg; u8 iv[AES_BLOCK_SIZE]; + struct scatterlist tag_sg; + u8 tag[AES_BLOCK_SIZE]; + /* Fields used for RFC3686 requests */ u8 *rfc3686_info; u8 rfc3686_iv[AES_BLOCK_SIZE]; @@ -244,6 +257,7 @@ struct scatterlist *ccp_crypto_sg_table_add(struct sg_table *table, int ccp_register_aes_algs(struct list_head *head); int ccp_register_aes_cmac_algs(struct list_head *head); int ccp_register_aes_xts_algs(struct list_head *head); +int ccp_register_aes_aeads(struct list_head *head); int ccp_register_sha_algs(struct list_head *head); int ccp_register_rsa_algs(struct list_head *head); diff --git a/drivers/crypto/ccp/ccp-dev-v5.c b/drivers/crypto/ccp/ccp-dev-v5.c index b31be75..f386fca 100644 --- a/drivers/crypto/ccp/ccp-dev-v5.c +++ b/drivers/crypto/ccp/ccp-dev-v5.c @@ -289,6 +289,8 @@ static int ccp5_perform_aes(struct ccp_op *op) CCP_AES_TYPE(&function) = op->u.aes.type; if (op->u.aes.mode == CCP_AES_MODE_CFB) CCP_AES_SIZE(&function) = 0x7f; + if ((op->u.aes.mode == CCP_AES_MODE_GCTR) && op->eom) + CCP_AES_SIZE(&function) = op->u.aes.size; CCP5_CMD_FUNCTION(&desc) = function.raw; diff --git a/drivers/crypto/ccp/ccp-dev.h b/drivers/crypto/ccp/ccp-dev.h index f2e9bcb..1424f69 100644 --- a/drivers/crypto/ccp/ccp-dev.h +++ b/drivers/crypto/ccp/ccp-dev.h @@ -467,6 +467,7 @@ struct ccp_aes_op { enum ccp_aes_type type; enum ccp_aes_mode mode; enum ccp_aes_action action; + unsigned int size; }; struct ccp_xts_aes_op { diff --git a/drivers/crypto/ccp/ccp-ops.c b/drivers/crypto/ccp/ccp-ops.c index f7398e9..98f7983 100644 --- a/drivers/crypto/ccp/ccp-ops.c +++ b/drivers/crypto/ccp/ccp-ops.c @@ -600,6 +600,255 @@ static int ccp_run_aes_cmac_cmd(struct ccp_cmd_queue *cmd_q, return ret; } +static int ccp_run_aes_gcm_cmd(struct ccp_cmd_queue *cmd_q, + struct ccp_cmd *cmd) +{ + struct ccp_aes_engine *aes = &cmd->u.aes; + struct ccp_dm_workarea key, ctx, final_wa, tag; + struct ccp_data src, dst; + struct ccp_data aad; + struct ccp_op op; + + unsigned long long *final; + unsigned int dm_offset; + unsigned int ilen; + bool in_place = true; /* Default value */ + int ret; + + struct scatterlist *p_inp, sg_inp[2]; + struct scatterlist *p_tag, sg_tag[2]; + struct scatterlist *p_outp, sg_outp[2]; + struct scatterlist *p_aad; + + if (!aes->iv) + return -EINVAL; + + if (!((aes->key_len == AES_KEYSIZE_128) || + (aes->key_len == AES_KEYSIZE_192) || + (aes->key_len == AES_KEYSIZE_256))) + return -EINVAL; + + if (!aes->key) /* Gotta have a key SGL */ + return -EINVAL; + + /* First, decompose the source buffer into AAD & PT, + * and the destination buffer into AAD, CT & tag, or + * the input into CT & tag. + * It is expected that the input and output SGs will + * be valid, even if the AAD and input lengths are 0. + */ + p_aad = aes->src; + p_inp = scatterwalk_ffwd(sg_inp, aes->src, aes->aad_len); + p_outp = scatterwalk_ffwd(sg_outp, aes->dst, aes->aad_len); + if (aes->action == CCP_AES_ACTION_ENCRYPT) { + ilen = aes->src_len; + p_tag = scatterwalk_ffwd(sg_tag, p_outp, ilen); + } else { + /* Input length for decryption includes tag */ + ilen = aes->src_len - AES_BLOCK_SIZE; + p_tag = scatterwalk_ffwd(sg_tag, p_inp, ilen); + } + + memset(&op, 0, sizeof(op)); + op.cmd_q = cmd_q; + op.jobid = CCP_NEW_JOBID(cmd_q->ccp); + op.sb_key = cmd_q->sb_key; /* Pre-allocated */ + op.sb_ctx = cmd_q->sb_ctx; /* Pre-allocated */ + op.init = 1; + op.u.aes.type = aes->type; + + /* Copy the key to the LSB */ + ret = ccp_init_dm_workarea(&key, cmd_q, + CCP_AES_CTX_SB_COUNT * CCP_SB_BYTES, + DMA_TO_DEVICE); + if (ret) + return ret; + + dm_offset = CCP_SB_BYTES - aes->key_len; + ccp_set_dm_area(&key, dm_offset, aes->key, 0, aes->key_len); + 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; + } + + /* Copy the context (IV) to the LSB. + * There is an assumption here that the IV is 96 bits in length, plus + * a nonce of 32 bits. If no IV is present, use a zeroed buffer. + */ + ret = ccp_init_dm_workarea(&ctx, cmd_q, + CCP_AES_CTX_SB_COUNT * CCP_SB_BYTES, + DMA_BIDIRECTIONAL); + if (ret) + goto e_key; + + dm_offset = CCP_AES_CTX_SB_COUNT * CCP_SB_BYTES - aes->iv_len; + ccp_set_dm_area(&ctx, dm_offset, aes->iv, 0, aes->iv_len); + + ret = ccp_copy_to_sb(cmd_q, &ctx, op.jobid, op.sb_ctx, + CCP_PASSTHRU_BYTESWAP_256BIT); + if (ret) { + cmd->engine_error = cmd_q->cmd_error; + goto e_ctx; + } + + op.init = 1; + if (aes->aad_len > 0) { + /* Step 1: Run a GHASH over the Additional Authenticated Data */ + ret = ccp_init_data(&aad, cmd_q, p_aad, aes->aad_len, + AES_BLOCK_SIZE, + DMA_TO_DEVICE); + if (ret) + goto e_ctx; + + op.u.aes.mode = CCP_AES_MODE_GHASH; + op.u.aes.action = CCP_AES_GHASHAAD; + + while (aad.sg_wa.bytes_left) { + ccp_prepare_data(&aad, NULL, &op, AES_BLOCK_SIZE, true); + + ret = cmd_q->ccp->vdata->perform->aes(&op); + if (ret) { + cmd->engine_error = cmd_q->cmd_error; + goto e_aad; + } + + ccp_process_data(&aad, NULL, &op); + op.init = 0; + } + } + + op.u.aes.mode = CCP_AES_MODE_GCTR; + op.u.aes.action = aes->action; + + if (ilen > 0) { + /* Step 2: Run a GCTR over the plaintext */ + in_place = (sg_virt(p_inp) == sg_virt(p_outp)) ? true : false; + + ret = ccp_init_data(&src, cmd_q, p_inp, ilen, + AES_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, p_outp, ilen, + AES_BLOCK_SIZE, DMA_FROM_DEVICE); + if (ret) + goto e_src; + } + + op.soc = 0; + op.eom = 0; + op.init = 1; + while (src.sg_wa.bytes_left) { + ccp_prepare_data(&src, &dst, &op, AES_BLOCK_SIZE, true); + if (!src.sg_wa.bytes_left) { + unsigned int nbytes = aes->src_len + % AES_BLOCK_SIZE; + + if (nbytes) { + op.eom = 1; + op.u.aes.size = (nbytes * 8) - 1; + } + } + + ret = cmd_q->ccp->vdata->perform->aes(&op); + if (ret) { + cmd->engine_error = cmd_q->cmd_error; + goto e_dst; + } + + ccp_process_data(&src, &dst, &op); + op.init = 0; + } + } + + /* Step 3: Update the IV portion of the context with the original IV */ + 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; + } + + ccp_set_dm_area(&ctx, dm_offset, aes->iv, 0, aes->iv_len); + + ret = ccp_copy_to_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; + } + + /* Step 4: Concatenate the lengths of the AAD and source, and + * hash that 16 byte buffer. + */ + ret = ccp_init_dm_workarea(&final_wa, cmd_q, AES_BLOCK_SIZE, + DMA_BIDIRECTIONAL); + if (ret) + goto e_dst; + final = (unsigned long long *) final_wa.address; + final[0] = cpu_to_be64(aes->aad_len * 8); + final[1] = cpu_to_be64(ilen * 8); + + op.u.aes.mode = CCP_AES_MODE_GHASH; + op.u.aes.action = CCP_AES_GHASHFINAL; + op.src.type = CCP_MEMTYPE_SYSTEM; + op.src.u.dma.address = final_wa.dma.address; + op.src.u.dma.length = AES_BLOCK_SIZE; + op.dst.type = CCP_MEMTYPE_SYSTEM; + op.dst.u.dma.address = final_wa.dma.address; + op.dst.u.dma.length = AES_BLOCK_SIZE; + op.eom = 1; + op.u.aes.size = 0; + ret = cmd_q->ccp->vdata->perform->aes(&op); + if (ret) + goto e_dst; + + if (aes->action == CCP_AES_ACTION_ENCRYPT) { + /* Put the ciphered tag after the ciphertext. */ + ccp_get_dm_area(&final_wa, 0, p_tag, 0, AES_BLOCK_SIZE); + } else { + /* Does this ciphered tag match the input? */ + ret = ccp_init_dm_workarea(&tag, cmd_q, AES_BLOCK_SIZE, + DMA_BIDIRECTIONAL); + if (ret) + goto e_tag; + ccp_set_dm_area(&tag, 0, p_tag, 0, AES_BLOCK_SIZE); + + ret = memcmp(tag.address, final_wa.address, AES_BLOCK_SIZE); + ccp_dm_free(&tag); + } + +e_tag: + ccp_dm_free(&final_wa); + +e_dst: + if (aes->src_len && !in_place) + ccp_free_data(&dst, cmd_q); + +e_src: + if (aes->src_len) + ccp_free_data(&src, cmd_q); + +e_aad: + if (aes->aad_len) + ccp_free_data(&aad, cmd_q); + +e_ctx: + ccp_dm_free(&ctx); + +e_key: + ccp_dm_free(&key); + + return ret; +} + static int ccp_run_aes_cmd(struct ccp_cmd_queue *cmd_q, struct ccp_cmd *cmd) { struct ccp_aes_engine *aes = &cmd->u.aes; @@ -613,6 +862,9 @@ static int ccp_run_aes_cmd(struct ccp_cmd_queue *cmd_q, struct ccp_cmd *cmd) if (aes->mode == CCP_AES_MODE_CMAC) return ccp_run_aes_cmac_cmd(cmd_q, cmd); + if (aes->mode == CCP_AES_MODE_GCM) + return ccp_run_aes_gcm_cmd(cmd_q, cmd); + if (!((aes->key_len == AES_KEYSIZE_128) || (aes->key_len == AES_KEYSIZE_192) || (aes->key_len == AES_KEYSIZE_256))) diff --git a/include/linux/ccp.h b/include/linux/ccp.h index dd90670..423561a 100644 --- a/include/linux/ccp.h +++ b/include/linux/ccp.h @@ -122,6 +122,10 @@ enum ccp_aes_mode { CCP_AES_MODE_CFB, CCP_AES_MODE_CTR, CCP_AES_MODE_CMAC, + CCP_AES_MODE_GHASH, + CCP_AES_MODE_GCTR, + CCP_AES_MODE_GCM, + CCP_AES_MODE_GMAC, CCP_AES_MODE__LAST, }; @@ -136,6 +140,9 @@ enum ccp_aes_action { CCP_AES_ACTION_ENCRYPT, CCP_AES_ACTION__LAST, }; +/* Overloaded field */ +#define CCP_AES_GHASHAAD CCP_AES_ACTION_DECRYPT +#define CCP_AES_GHASHFINAL CCP_AES_ACTION_ENCRYPT /** * struct ccp_aes_engine - CCP AES operation @@ -180,6 +187,8 @@ struct ccp_aes_engine { struct scatterlist *cmac_key; /* K1/K2 cmac key required for * final cmac cmd */ u32 cmac_key_len; /* In bytes */ + + u32 aad_len; /* In bytes */ }; /***** XTS-AES engine *****/