From patchwork Mon Apr 2 06:15:03 2018 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Siva Durga Prasad Paladugu X-Patchwork-Id: 894100 X-Patchwork-Delegate: monstr@monstr.eu Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Authentication-Results: ozlabs.org; spf=none (mailfrom) smtp.mailfrom=lists.denx.de (client-ip=81.169.180.215; helo=lists.denx.de; envelope-from=u-boot-bounces@lists.denx.de; receiver=) Authentication-Results: ozlabs.org; dmarc=none (p=none dis=none) header.from=xilinx.com Authentication-Results: ozlabs.org; dkim=fail reason="signature verification failed" (1024-bit key; unprotected) header.d=xilinx.onmicrosoft.com header.i=@xilinx.onmicrosoft.com header.b="gEmuu6lG"; dkim-atps=neutral Received: from lists.denx.de (dione.denx.de [81.169.180.215]) by ozlabs.org (Postfix) with ESMTP id 40F24P6b5lz9s0w for ; Mon, 2 Apr 2018 16:14:29 +1000 (AEST) Received: by lists.denx.de (Postfix, from userid 105) id 750C2C21E8A; Mon, 2 Apr 2018 06:14:25 +0000 (UTC) X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on lists.denx.de X-Spam-Level: X-Spam-Status: No, score=0.0 required=5.0 tests=BAD_ENC_HEADER, RCVD_IN_DNSWL_BLOCKED, SPF_HELO_PASS, T_DKIM_INVALID autolearn=unavailable autolearn_force=no version=3.4.0 Received: from lists.denx.de (localhost [IPv6:::1]) by lists.denx.de (Postfix) with ESMTP id ABC5FC21DEC; Mon, 2 Apr 2018 06:14:21 +0000 (UTC) Received: by lists.denx.de (Postfix, from userid 105) id 50BE9C21E0B; Mon, 2 Apr 2018 06:14:20 +0000 (UTC) Received: from NAM01-SN1-obe.outbound.protection.outlook.com (mail-sn1nam01on0064.outbound.protection.outlook.com [104.47.32.64]) by lists.denx.de (Postfix) with ESMTPS id 7B80BC21DEC for ; Mon, 2 Apr 2018 06:14:19 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=xilinx.onmicrosoft.com; s=selector1-xilinx-com; h=From:Date:Subject:Message-ID:Content-Type:MIME-Version; bh=MXi3OjTxAGlSdXYq+xr1WfKWj0+73EBycudPJre28qE=; b=gEmuu6lGE+AYKSA7yjozJv4lht7Qv7ELbAGuDiY0ZBom8v9weiofrN4u/GHHg+LjJbtKym1o8vms2oZV2h9XW46CMGg/TZAhL0TvDIFx8RtrRLfSGJNbyMt5oUb8KoPF+LlcMCnOtWf1gbybsSm1U/Ysz25CNYbXbYFHHjvsibY= Received: from SN4PR0201CA0038.namprd02.prod.outlook.com (10.162.76.24) by BN6PR02MB2260.namprd02.prod.outlook.com (10.168.253.142) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.20.631.10; Mon, 2 Apr 2018 06:14:16 +0000 Received: from BL2NAM02FT054.eop-nam02.prod.protection.outlook.com (2a01:111:f400:7e46::202) by SN4PR0201CA0038.outlook.office365.com (2603:10b6:803:2e::24) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA384) id 15.20.631.10 via Frontend Transport; Mon, 2 Apr 2018 06:14:15 +0000 Authentication-Results: spf=pass (sender IP is 149.199.60.100) smtp.mailfrom=xilinx.com; lists.denx.de; dkim=none (message not signed) header.d=none;lists.denx.de; dmarc=bestguesspass action=none header.from=xilinx.com; Received-SPF: Pass (protection.outlook.com: domain of xilinx.com designates 149.199.60.100 as permitted sender) receiver=protection.outlook.com; client-ip=149.199.60.100; helo=xsj-pvapsmtpgw02; Received: from xsj-pvapsmtpgw02 (149.199.60.100) by BL2NAM02FT054.mail.protection.outlook.com (10.152.77.107) with Microsoft SMTP Server (version=TLS1_0, cipher=TLS_RSA_WITH_AES_256_CBC_SHA) id 15.20.631.7 via Frontend Transport; Mon, 2 Apr 2018 06:14:14 +0000 Received: from unknown-38-66.xilinx.com ([149.199.38.66]:48096 helo=xsj-pvapsmtp01) by xsj-pvapsmtpgw02 with esmtp (Exim 4.63) (envelope-from ) id 1f2sjO-0007n0-8m for u-boot@lists.denx.de; Sun, 01 Apr 2018 23:14:14 -0700 Received: from [127.0.0.1] (helo=localhost) by xsj-pvapsmtp01 with smtp (Exim 4.63) (envelope-from ) id 1f2sjJ-0004Oj-5N for u-boot@lists.denx.de; Sun, 01 Apr 2018 23:14:09 -0700 Received: from xsj-pvapsmtp01 (smtp.xilinx.com [149.199.38.66]) by xsj-smtp-dlp2.xlnx.xilinx.com (8.13.8/8.13.1) with ESMTP id w326E3MO018716; Sun, 1 Apr 2018 23:14:03 -0700 Received: from [172.23.37.99] (helo=xhdsivadur40.xilinx.com) by xsj-pvapsmtp01 with esmtp (Exim 4.63) (envelope-from ) id 1f2sjC-0004Mn-Mt; Sun, 01 Apr 2018 23:14:03 -0700 From: Siva Durga Prasad Paladugu To: Date: Mon, 2 Apr 2018 11:45:03 +0530 Message-ID: <1522649704-11696-1-git-send-email-sivadur@xilinx.com> X-Mailer: git-send-email 2.7.4 X-RCIS-Action: ALLOW X-TM-AS-Product-Ver: IMSS-7.1.0.1224-8.2.0.1013-23620.005 X-TM-AS-User-Approved-Sender: Yes;Yes X-EOPAttributedMessage: 0 X-MS-Office365-Filtering-HT: Tenant X-Forefront-Antispam-Report: CIP:149.199.60.100; IPV:NLI; CTRY:US; EFV:NLI; SFV:NSPM; SFS:(10009020)(346002)(376002)(39860400002)(39380400002)(396003)(2970300002)(438002)(199004)(189003)(575784001)(50226002)(107886003)(36386004)(81156014)(36756003)(476003)(63266004)(51416003)(7696005)(486005)(486005)(47776003)(8936002)(81166006)(8676002)(8746002)(59450400001)(2616005)(126002)(9786002)(5890100001)(316002)(426003)(48376002)(106466001)(2351001)(54906003)(5660300001)(26005)(106002)(478600001)(186003)(305945005)(4326008)(2906002)(6916009)(336012)(356003)(50466002)(77096007)(107986001)(217873001)(5001870100001); DIR:OUT; SFP:1101; SCL:1; SRVR:BN6PR02MB2260; H:xsj-pvapsmtpgw02; FPR:; SPF:Pass; LANG:en; PTR:xapps1.xilinx.com,unknown-60-100.xilinx.com; A:1; MX:3; X-Microsoft-Exchange-Diagnostics: 1; BL2NAM02FT054; 1:hbfbU55P4ZE652iJ9D9wvv9n4dyYIgiRq+gM+2+gSkoqZCk06yoeZXq9ke4LKZntZ0pqp4mW7+vyVJfw2HLatSHNM8TxFVYnr1itgZ61PHqIuh1ScAewDSqEh8hlF8jA MIME-Version: 1.0 X-MS-PublicTrafficType: Email X-MS-Office365-Filtering-Correlation-Id: 24515637-3166-4cd6-d800-08d59860f5d7 X-Microsoft-Antispam: UriScan:; BCL:0; PCL:0; RULEID:(7020095)(4652020)(5600026)(4604075)(4608076)(4534165)(4627221)(201703031133081)(201702281549075)(2017052603328)(7153060); SRVR:BN6PR02MB2260; X-Microsoft-Exchange-Diagnostics: 1; BN6PR02MB2260; 3:74dHFhF56qAIhIQH6wHn6gpbZREXJIEB3z91yE3DiXy9Nbz9oYyiaNIyPew1346rvGk0er4umujleqn5BB+XoXkOPQarXb+ZSisvvzqMhlvaqbSunzTcBiDtOnD6BTXprK6koXeHDnNFBj45GADGtSBBkK8oX9/ScgbL9dISodSGRGRH3lIh/C7Moszysn8fBM594y3z8E+/6bJtn2lIH+bf0WsGizOS7baZ0GSLIPbbCf0TStDsOkeQDAXTAyajXeVJSXXl+rpg/JDgh52uCqGN2KMO9tfEJ/eRp48aAB60ME7KI0Ur8U5rBcBvIje+p+2M8FQaBcSKlUdnIyr8nVYeBpZ07TYtEmIqrtIYkcQ=; 25:p7w4gtemf2haA9QnNImMLkFfzW1gWROITUtZnISHv+yVxXZVAF02aNkWQiXp4/WzUqenMXYzlOaIRucCZ2ePdkIlBCMMNeTeKk4wrfPgYbpwBPJ9pZ9Gditm44Xbjpe32CLA3A12exONlewrdS4BHLsRqceVDRbRlU6ypn3c+wmtzUkRITeNzPzmeGs4BczdiL7ZfzErMHSNuQKw0IvU2L56ZfWv00QK/5KKmGaHTOn3NFMPTNtFFpGtd9/dzQh8ZWNErjfwL0uR95J66c1bPguBH0Zu2TU45OpOr3FfA0E0RvgbWsrWXiNInzuTptYs5YNKAk3WPF3Ek3BTY3uEnA== X-MS-TrafficTypeDiagnostic: BN6PR02MB2260: X-Microsoft-Exchange-Diagnostics: 1; BN6PR02MB2260; 31:YntQ0x+Hy2mjbFmzPG+AEubX2+ZlMa7H1LxagaMdszKmq6rmtif3dsAXZKSx4KTY5WbqRIO/OyZDHHHJ8Sla9YrGI6ATGhXjUoPN+DvOVmrI3gKOmQpQDSq+jASUxbf9CCjIPMwl6Sz9MV0Ihn5lS5nGVjylO4Hq/iRUKNDITzpo3FwjIVnnLMduL1YMduvJUzHlroMBkhaKK2nuKuePXYAPtiGvO2mARoM3RBS9hno=; 20:QMqAF1VlBgrvbjvH6GdSq/glT6G7WniJFEx83hY5PiwmT/eKhNruki93qSIdTNn3WyGYR0RThblbjPr0Xpu45uiEIS0PhymbXCQ/3Utwr5fvdC3DopTSfuIoC3actAgbFXnUbZ2jF+4RRz69H9GV3ZdP3F7Nfl8W1sJgEQRh2W1iJmg447BdCn6TKBLTDlkLLc1MOpVFrLixNC3ZJzIWkYr9mbbkECpqrH1XTQHanOmcCiTeN9WluCou4q1uANblAiqNVjI2J7Sn58/pen6Ly5zMo+4aC7aYWSxHzG1p88O8SVixSL/TqIzNgnbhtMGOAnDK/PZac1sLHBs9RYeWsjTHu//rxujz669lWGmeY7w2oojsoUg468XPTEqwlpaTM80nctuYA8qehFutLbARYXb1RhNpC/SutuW2i0k37H36pcBN+dY4vSh+4eiR0lltfY8jV+E49QEQjAQTG7mDu7VPKcs+XuAz3cOVRj5C+LCH4N088JtXatceyfMs3qq0 X-Auto-Response-Suppress: DR, RN, NRN, OOF, AutoReply X-Microsoft-Antispam-PRVS: X-Exchange-Antispam-Report-Test: UriScan:(192813158149592); X-Exchange-Antispam-Report-CFA-Test: BCL:0; PCL:0; RULEID:(8211001083)(6040522)(2401047)(8121501046)(5005006)(3002001)(93006095)(93004095)(10201501046)(3231221)(944501327)(52105095)(6055026)(6041310)(20161123558120)(20161123562045)(20161123564045)(20161123560045)(201703131423095)(201702281528075)(20161123555045)(201703061421075)(201703061406153)(6072148)(201708071742011); SRVR:BN6PR02MB2260; BCL:0; PCL:0; RULEID:; SRVR:BN6PR02MB2260; X-Microsoft-Exchange-Diagnostics: 1; BN6PR02MB2260; 4:PCYCbTvHlTT7JY2Nj/fdih0puoLV94K6qsfAreDdCZQOhEo8t9AdQlxDut7ZmNCTmyhfnoW85VhGVR5bICqtBuSNvfEujto+FCzAFj8fMJ2+46kZNHCyU/ackYCcVpUgvhxCemtYq4b3JdWDCB5aH5J0VnMuUurJGDt2XQ+pW7Sqgm2m1eQdMnGssxsWOyYrm6csHNM0oqYA1cWtS8LElrUPSjID2xA5h6aJuKeGF7wnxpWRWnsEYPmEb7mt1Vrjb2BirJR52qNvOnUpGuRWgP4O3lZ3KhzeoE269o5nN23EF1GlWj6JINsFbIUzRrbN X-Forefront-PRVS: 0630013541 X-Microsoft-Exchange-Diagnostics: =?us-ascii?Q?1; BN6PR02MB2260; 23:YhRKyd8FfItaY7pDnwoE+cPEymBayFKCF7PKRBn7H?= gRD50ZJoSQ70zEfhX/su214oowq59ENQnvrJKW9iaVdPgn71j+/204sS5C4T1dR7ogOpw+mBHsT/8e9SmIBPEr/6Q5W+lCE5fubpguqnT5R1HGno71T58gmHyt/aYIgSK3hU3y0pSq+/ul54bpTwe9okjWpFBl2ynm6CFNXgrvKKX/obDO4yMP7AlSix6QHvXCZZSPyQbedY0+sLmHKwLbFEx9hoovjS1f3O8hkxJMXtfTJU78KGqOMObGp60Dz4JE5XWDh6inPgSBvUQ2nt4luodtY3cY9ITM5ri7hPCTgUAyXbdItv3dsP0Idk4FbRfutE2ucmnWOoGAR6Um9tM6XDOto6pJgR6A1TMi7kRJIQfFHiUvvYfkwL/I3Unk5yPXNH2KXzzwCFCTx81/WSD3JgRdQrkEe8YP01caMNUrPTnri6hq9Iiwv+iblY9sv8S/UIn9ME9aTokM5K+WEv7RNWEJmCaNd9p/AcibcOOeUfr9o8QehhgxvsUbKzUGgmj6N1jFw8PQHz8BnplXXqrFtPr6kHXfi4k76qAcL3XHi/Jp1Y0PVfjOVh8SFjHUb0sqsmmvXrnyWojA+U6NsHuYTTiHK9SFpHof3u6GGYoA816X5kstHD4lAgHmDNo5nTZKVB3yJxPDmPAS9mIftKBQq15MSyfG9Hyrvh3W7BlHp3739/aA6PfLKGi/+PWQw8CnXUZ0pAb1W8BAxzIc2kb3MIobVf7aDkF0bmTvxmqXyKkYK2lQqaQSdXgPkWsVzHLvwE/n41mbOyYTowqcHAlQs7+dW0Hf9ZHPDyHDHt/1h4lEWjS431M4K3XscwuQQw6YidYv39kopo9H/6x/wK0Y+zWK0UX9nV3YzApD6nO89IiKq89wqNDRrrllTa8u2qVc6my+TcCze7JGCoZgYbDps7clnHAadQV/jtEf7D3/x+HwE/26sbpswWrentR8wyksJLHfZxhG1YIElMTxMB7WemNOWEGAKXedYzybZQgLY6qB0Mo0FEoriGoq4ibf3MWlUCm0wcTKQ9RaJwQODRmCOpurntRPDw5HlgJez/v/+gfYdwh/QOWbXA+uzQ3l73uMT5oCl1xav6eSKKJIHPlj+eYJPa3S/nNns2uGJTYRS3NJXmuqO0Py0tDSmfcs3wx8hOUJUXeaioy+j6IhEOUJ3 X-Microsoft-Antispam-Message-Info: s91t6iq0ebQxeUgRAGrjAlbJotimq4MmQgLa/M+bfYOxoFQoYQ4fyvQYcCnCoj2Ty4dXrgk7PMKilFCb5IPlvEDm7iIXa+j9W5vmBgqIRYYzuncELTVdwKWsXSQTIiTM8KKDkmWVDTL9Zsqa7F5AS4MqM6fCIaPC/a5uGYJAx0kqrPoeE5jo8uyez5oYCxW4 X-Microsoft-Exchange-Diagnostics: 1; BN6PR02MB2260; 6:bAEQHrCXzysHVuEugbVhOLphkPSTzM1HZlvKSupqxAMaFUC8AJG9A6jhQ4Webd6vuqxoT8W4K5PkitH/F4w31tAq/gPVLbYoBJXo5vM39xwYCEdbSFkmJ1PuDPI4jbDfanbkcDjIW6X9ERPKcvP/V9S/G0484tcVqirA5Qi8MuDpIB2oVe2fxZZjSjWw6jmVwXGKfzRSQVRkkw+hqMjywnW2gNAhv4oZJIccE3CeksElkaXgfw/0l7wgzmxjXF/OjvEFjuDXhHuxnsR5xdWB5WGUOKf+YvaaKm8g4MP0cnikk4QqxhBiW5AFKB3w60GcrHPqlJsg/LjWa+/ytu+1e+ML7OFZ5Q2S9iJGRjeTkJBMy2s2r11+3Gwt0/QBh8xqFhpdZu5Nin84dgrbV280T2QdVEm7JJt9/1jq2RApxAtoXDpaoGGfFB+MOqkInBP/9QhGtuorycMTMuzVWnKozA==; 5:/Af7hVXF9eh5akk0mrdA+ucRNZcvjHggcuncuRvCV8VAkFHvnG6bnniBROwy1rnFojYZ79MR60x8+e/YOkMivRKRzEirO6lfgZpllX/26KSwGXzyc1YjFGPHcm9R69kEqpKaJDn5EAxF+LAYJ5HkEqzptyOSCCKKaUq0QGIr9uQ=; 24:dcyvNW4XXTB0XcHJ/2zohWWqkVwRmsKmmvZl83MPz+G8bJQVErdIVsZby5kh4lcmO0D0x/IzS+JDnjolowH1Qjj9eetSBjeaDtxLmPNC6+o= SpamDiagnosticOutput: 1:99 SpamDiagnosticMetadata: NSPM X-Microsoft-Exchange-Diagnostics: 1; BN6PR02MB2260; 7:qqNIkpV5cf7esFvGGeTtjCW16zEJNq7kow40MfTxrfH3STtrpIoWpyTgxlMfVLpDAK6Fam3M1r8uqwVN2bCaBE+/RJejUmEC+R/FfEW2+fKS876ip4aQvbXxftj2I44nZO0UZG4U35+7tsk5WWyVAWF9mprSTIdowgzHZCEnC22EzMLUxsSJwhqFzowGK0/+lO8dQpY3GL1WkEe7hY7QeB94Chm42GL9CNKAP5lnJwKddDCQ3mnFxvEgpvLRP96w X-OriginatorOrg: xilinx.com X-MS-Exchange-CrossTenant-OriginalArrivalTime: 02 Apr 2018 06:14:14.9138 (UTC) X-MS-Exchange-CrossTenant-Network-Message-Id: 24515637-3166-4cd6-d800-08d59860f5d7 X-MS-Exchange-CrossTenant-Id: 657af505-d5df-48d0-8300-c31994686c5c X-MS-Exchange-CrossTenant-OriginalAttributedTenantConnectingIp: TenantId=657af505-d5df-48d0-8300-c31994686c5c; Ip=[149.199.60.100]; Helo=[xsj-pvapsmtpgw02] X-MS-Exchange-CrossTenant-FromEntityHeader: HybridOnPrem X-MS-Exchange-Transport-CrossTenantHeadersStamped: BN6PR02MB2260 Cc: michal.simek@xilinx.com, Siva Durga Prasad Paladugu Subject: [U-Boot] [RFC PATCH 1/2] fpga: xilinx: zynq: Add support to decrypt images X-BeenThere: u-boot@lists.denx.de X-Mailman-Version: 2.1.18 Precedence: list List-Id: U-Boot discussion List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: u-boot-bounces@lists.denx.de Sender: "U-Boot" This patch adds support to decrypt an encrypted bitstream or image. This zynq aes command can either load decrypted image back to DDR or it can load an encrypted bitsream to PL directly by decrypting it. The image has to be encrypted using xilinx bootgen tool and to get only the encrypted image from tool use -split option while invoking bootgen. Signed-off-by: Siva Durga Prasad Paladugu --- arch/arm/Kconfig | 1 + board/xilinx/zynq/Kconfig | 14 ++++ drivers/fpga/zynqpl.c | 158 ++++++++++++++++++++++++++++++++++++++++++++++ include/zynqpl.h | 5 ++ 4 files changed, 178 insertions(+) create mode 100644 board/xilinx/zynq/Kconfig -- 2.7.4 This email and any attachments are intended for the sole use of the named recipient(s) and contain(s) confidential information that may be proprietary, privileged or copyrighted under applicable law. If you are not the intended recipient, do not read, copy, or forward this email message or any attachments. Delete this email message and any attachments immediately. diff --git a/arch/arm/Kconfig b/arch/arm/Kconfig index 068ea1e..e0cd1d8 100644 --- a/arch/arm/Kconfig +++ b/arch/arm/Kconfig @@ -1360,6 +1360,7 @@ source "board/toradex/colibri_pxa270/Kconfig" source "board/vscom/baltos/Kconfig" source "board/woodburn/Kconfig" source "board/work-microwave/work_92105/Kconfig" +source "board/xilinx/zynq/Kconfig" source "board/xilinx/zynqmp/Kconfig" source "board/zipitz2/Kconfig" diff --git a/board/xilinx/zynq/Kconfig b/board/xilinx/zynq/Kconfig new file mode 100644 index 0000000..f8f8a7f --- /dev/null +++ b/board/xilinx/zynq/Kconfig @@ -0,0 +1,14 @@ +# Copyright (c) 2018, Xilinx, Inc. +# +# SPDX-License-Identifier: GPL-2.0 + +if ARCH_ZYNQ + +config CMD_ZYNQ_AES + bool "Zynq AES" + default y + help + Decrypts the encrypted image present in source address + and places the decrypted image at destination address. + +endif diff --git a/drivers/fpga/zynqpl.c b/drivers/fpga/zynqpl.c index db9bd12..fcffc2d 100644 --- a/drivers/fpga/zynqpl.c +++ b/drivers/fpga/zynqpl.c @@ -18,6 +18,7 @@ #define DEVCFG_CTRL_PCFG_PROG_B 0x40000000 #define DEVCFG_CTRL_PCFG_AES_EFUSE_MASK 0x00001000 +#define DEVCFG_CTRL_PCAP_RATE_EN_MASK 0x02000000 #define DEVCFG_ISR_FATAL_ERROR_MASK 0x00740040 #define DEVCFG_ISR_ERROR_FLAGS_MASK 0x00340840 #define DEVCFG_ISR_RX_FIFO_OV 0x00040000 @@ -498,3 +499,160 @@ struct xilinx_fpga_op zynq_op = { .loadfs = zynq_loadfs, #endif }; + +#ifdef CONFIG_CMD_ZYNQ_AES +/* + * Load the encrypted image from src addr and decrypt the image and + * place it back the decrypted image into dstaddr. + */ +int zynq_decrypt_load(u32 srcaddr, u32 srclen, u32 dstaddr, u32 dstlen, + u8 bstype) +{ + u32 isr_status, ts; + + if ((srcaddr < SZ_1M) || (dstaddr < SZ_1M)) { + printf("%s: src and dst addr should be > 1M\n", + __func__); + return FPGA_FAIL; + } + + if (zynq_dma_xfer_init(bstype)) { + printf("%s: zynq_dma_xfer_init FAIL\n", __func__); + return FPGA_FAIL; + } + + writel((readl(&devcfg_base->ctrl) | DEVCFG_CTRL_PCAP_RATE_EN_MASK), + &devcfg_base->ctrl); + + debug("%s: Source = 0x%08X\n", __func__, (u32)srcaddr); + debug("%s: Size = %zu\n", __func__, srclen); + + /* flush(clean & invalidate) d-cache range buf */ + flush_dcache_range((u32)srcaddr, (u32)srcaddr + + roundup(srclen << 2, ARCH_DMA_MINALIGN)); + /* + * Flush destination address range only if image is not + * bitstream. + */ + if (bstype == BIT_NONE) + flush_dcache_range((u32)dstaddr, (u32)dstaddr + + roundup(dstlen << 2, ARCH_DMA_MINALIGN)); + + if (zynq_dma_transfer(srcaddr | 1, srclen, dstaddr | 1, dstlen)) + return FPGA_FAIL; + + if (bstype == BIT_FULL) { + isr_status = readl(&devcfg_base->int_sts); + /* Check FPGA configuration completion */ + ts = get_timer(0); + while (!(isr_status & DEVCFG_ISR_PCFG_DONE)) { + if (get_timer(ts) > CONFIG_SYS_FPGA_WAIT) { + printf("%s: Timeout wait for FPGA to config\n", + __func__); + return FPGA_FAIL; + } + isr_status = readl(&devcfg_base->int_sts); + } + + printf("%s: FPGA config done\n", __func__); + + if (bstype != BIT_PARTIAL) + zynq_slcr_devcfg_enable(); + } + + return FPGA_SUCCESS; +} + +static int do_zynq_decrypt_image(cmd_tbl_t *cmdtp, int flag, int argc, + char * const argv[]) +{ + char *endp; + u32 srcaddr; + u32 srclen; + u32 dstaddr; + u32 dstlen; + u8 imgtype = BIT_NONE; + int status; + u8 i = 1; + + if (argc < 4 && argc > 5) + goto usage; + + if (argc == 4) { + if (!strcmp("load", argv[i])) + imgtype = BIT_FULL; + else if (!strcmp("loadp", argv[i])) + imgtype = BIT_PARTIAL; + else + goto usage; + i++; + } + + srcaddr = simple_strtoul(argv[i], &endp, 16); + if (*argv[i++] == 0 || *endp != 0) + goto usage; + srclen = simple_strtoul(argv[i], &endp, 16); + if (*argv[i++] == 0 || *endp != 0) + goto usage; + if (argc == 4) { + dstaddr = 0xFFFFFFFF; + dstlen = srclen; + } else { + dstaddr = simple_strtoul(argv[i], &endp, 16); + if (*argv[i++] == 0 || *endp != 0) + goto usage; + dstlen = simple_strtoul(argv[i], &endp, 16); + if (*argv[i++] == 0 || *endp != 0) + goto usage; + } + + /* + * If the image is not bitstream but destination address is + * 0xFFFFFFFF + */ + if (imgtype == BIT_NONE && dstaddr == 0xFFFFFFFF) { + printf("ERR:use zynqaes load/loadp encrypted bitstream\n"); + goto usage; + } + + /* + * Roundup source and destination lengths to + * word size + */ + if (srclen % 4) + srclen = roundup(srclen, 4); + if (dstlen % 4) + dstlen = roundup(dstlen, 4); + + status = zynq_decrypt_load(srcaddr, srclen >> 2, dstaddr, dstlen >> 2, + imgtype); + if (status != 0) + return -1; + + return 0; + +usage: + return CMD_RET_USAGE; +} + +#ifdef CONFIG_SYS_LONGHELP +static char zynqaes_help_text[] = +"zynqaes [operation type] -\n" +"Decrypts the encrypted image present in source address\n" +"and places the decrypted image at destination address\n" +"zynqaes operations:\n" +" zynqaes \n" +" zynqaes load \n" +" zynqaes loadp \n" +"if operation type is load or loadp, it loads the encrypted\n" +"full or partial bitstream on to PL respectively. If no valid\n" +"operation type specified then it loads decrypted image back\n" +"to memory and it doesn't support loading PL bistsream\n"; +#endif + +U_BOOT_CMD( + zynqaes, 5, 0, do_zynq_decrypt_image, + "Zynq AES decryption ", zynqaes_help_text + ); + +#endif diff --git a/include/zynqpl.h b/include/zynqpl.h index 5a34a17..0dd4cf9 100644 --- a/include/zynqpl.h +++ b/include/zynqpl.h @@ -12,6 +12,11 @@ #include +#ifdef CONFIG_CMD_ZYNQ_AES +int zynq_decrypt_load(u32 srcaddr, u32 dstaddr, u32 srclen, u32 dstlen, + u8 bstype); +#endif + #if defined(CONFIG_FPGA_ZYNQPL) extern struct xilinx_fpga_op zynq_op; # define FPGA_ZYNQPL_OPS &zynq_op From patchwork Mon Apr 2 06:15:04 2018 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Siva Durga Prasad Paladugu X-Patchwork-Id: 894101 X-Patchwork-Delegate: monstr@monstr.eu Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Authentication-Results: ozlabs.org; spf=none (mailfrom) smtp.mailfrom=lists.denx.de (client-ip=81.169.180.215; helo=lists.denx.de; envelope-from=u-boot-bounces@lists.denx.de; receiver=) Authentication-Results: ozlabs.org; dmarc=none (p=none dis=none) header.from=xilinx.com Authentication-Results: ozlabs.org; dkim=fail reason="signature verification failed" (1024-bit key; unprotected) header.d=xilinx.onmicrosoft.com header.i=@xilinx.onmicrosoft.com header.b="BuCB1ehJ"; dkim-atps=neutral Received: from lists.denx.de (dione.denx.de [81.169.180.215]) by ozlabs.org (Postfix) with ESMTP id 40F25V2SZPz9s0w for ; Mon, 2 Apr 2018 16:15:26 +1000 (AEST) Received: by lists.denx.de (Postfix, from userid 105) id C52C5C21EFD; Mon, 2 Apr 2018 06:14:54 +0000 (UTC) X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on lists.denx.de X-Spam-Level: X-Spam-Status: No, score=0.0 required=5.0 tests=BAD_ENC_HEADER, RCVD_IN_DNSWL_BLOCKED, SPF_HELO_PASS, T_DKIM_INVALID autolearn=unavailable autolearn_force=no version=3.4.0 Received: from lists.denx.de (localhost [IPv6:::1]) by lists.denx.de (Postfix) with ESMTP id 7A7E6C21ED6; Mon, 2 Apr 2018 06:14:32 +0000 (UTC) Received: by lists.denx.de (Postfix, from userid 105) id 026BAC21EE0; Mon, 2 Apr 2018 06:14:28 +0000 (UTC) Received: from NAM02-SN1-obe.outbound.protection.outlook.com (mail-sn1nam02on0084.outbound.protection.outlook.com [104.47.36.84]) by lists.denx.de (Postfix) with ESMTPS id 9E329C21EBE for ; Mon, 2 Apr 2018 06:14:22 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=xilinx.onmicrosoft.com; s=selector1-xilinx-com; h=From:Date:Subject:Message-ID:Content-Type:MIME-Version; bh=ERAb+mtsosDufyslbhLfSFBLBxnbQkcffNFnR3IjQlY=; b=BuCB1ehJbttSbRWOUkveYuX/wvaiYenN0M6yVqfvnIM4vm1b8coMDzrmS0a3hq00aIRgbyJ/71zGMRh5XHnpQui6nYTyDcPCe9FfAk3wYgXwGSBKghN/DpzrSjcJMJcyOT77jFmN6pDyPl1PxJHncOrRhyH8dIRd9hbhY1hvwrU= Received: from BY2PR02CA0095.namprd02.prod.outlook.com (2a01:111:e400:5261::21) by DM2PR02MB1305.namprd02.prod.outlook.com (2a01:111:e400:50c8::16) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA384_P256) id 15.20.609.10; Mon, 2 Apr 2018 06:14:18 +0000 Received: from BL2NAM02FT022.eop-nam02.prod.protection.outlook.com (2a01:111:f400:7e46::203) by BY2PR02CA0095.outlook.office365.com (2a01:111:e400:5261::21) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA384) id 15.20.631.10 via Frontend Transport; Mon, 2 Apr 2018 06:14:17 +0000 Authentication-Results: spf=temperror (sender IP is 149.199.60.100) smtp.mailfrom=xilinx.com; lists.denx.de; dkim=none (message not signed) header.d=none;lists.denx.de; dmarc=temperror action=none header.from=xilinx.com; Received-SPF: TempError (protection.outlook.com: error in processing during lookup of xilinx.com: DNS Timeout) Received: from xsj-pvapsmtpgw02 (149.199.60.100) by BL2NAM02FT022.mail.protection.outlook.com (10.152.77.153) with Microsoft SMTP Server (version=TLS1_0, cipher=TLS_RSA_WITH_AES_256_CBC_SHA) id 15.20.631.7 via Frontend Transport; Mon, 2 Apr 2018 06:14:14 +0000 Received: from unknown-38-66.xilinx.com ([149.199.38.66]:48099 helo=xsj-pvapsmtp01) by xsj-pvapsmtpgw02 with esmtp (Exim 4.63) (envelope-from ) id 1f2sjO-0007n1-9v for u-boot@lists.denx.de; Sun, 01 Apr 2018 23:14:14 -0700 Received: from [127.0.0.1] (helo=localhost) by xsj-pvapsmtp01 with smtp (Exim 4.63) (envelope-from ) id 1f2sjJ-0004Oj-6v for u-boot@lists.denx.de; Sun, 01 Apr 2018 23:14:09 -0700 Received: from xsj-pvapsmtp01 (mailman.xilinx.com [149.199.38.66]) by xsj-smtp-dlp1.xlnx.xilinx.com (8.13.8/8.13.1) with ESMTP id w326E5EK017247; Sun, 1 Apr 2018 23:14:05 -0700 Received: from [172.23.37.99] (helo=xhdsivadur40.xilinx.com) by xsj-pvapsmtp01 with esmtp (Exim 4.63) (envelope-from ) id 1f2sjE-0004Mn-9b; Sun, 01 Apr 2018 23:14:04 -0700 From: Siva Durga Prasad Paladugu To: Date: Mon, 2 Apr 2018 11:45:04 +0530 Message-ID: <1522649704-11696-2-git-send-email-sivadur@xilinx.com> X-Mailer: git-send-email 2.7.4 In-Reply-To: <1522649704-11696-1-git-send-email-sivadur@xilinx.com> References: <1522649704-11696-1-git-send-email-sivadur@xilinx.com> X-RCIS-Action: ALLOW X-TM-AS-Product-Ver: IMSS-7.1.0.1224-8.2.0.1013-23620.005 X-TM-AS-User-Approved-Sender: Yes;Yes X-EOPAttributedMessage: 0 X-MS-Office365-Filtering-HT: Tenant X-Forefront-Antispam-Report: CIP:149.199.60.100; IPV:NLI; CTRY:US; EFV:NLI; SFV:NSPM; SFS:(10009020)(346002)(396003)(39860400002)(376002)(39380400002)(2980300002)(189003)(199004)(336012)(36756003)(2351001)(6916009)(106466001)(48376002)(47776003)(50466002)(5890100001)(63266004)(2616005)(446003)(63350400001)(11346002)(5660300001)(4326008)(63370400001)(426003)(486005)(476003)(8746002)(305945005)(8936002)(59450400001)(50226002)(81156014)(486005)(8676002)(356003)(81166006)(9786002)(7696005)(51416003)(126002)(107886003)(76176011)(36386004)(186003)(77096007)(26005)(54906003)(575784001)(2906002)(316002)(478600001)(107986001)(217873001)(5001870100001); DIR:OUT; SFP:1101; SCL:1; SRVR:DM2PR02MB1305; H:xsj-pvapsmtpgw02; FPR:; SPF:TempError; PTR:xapps1.xilinx.com,unknown-60-100.xilinx.com; MX:1; A:3; LANG:en; X-Microsoft-Exchange-Diagnostics: 1; BL2NAM02FT022; 1:mBQYsiL1/I8iY341hrIJINhUGLnWVUkrbBEQo+n5uc/8QSnRP/Vwx7p/na2l29HQOxM6QmGSTpYl7iNDUkSUqFcJD5ocWGtB18btxSRv3TDoNXUochgVwDKRyJR2knwA MIME-Version: 1.0 X-MS-PublicTrafficType: Email X-MS-Office365-Filtering-Correlation-Id: d21954ba-6ae7-487f-c818-08d59860f5eb X-Microsoft-Antispam: UriScan:; BCL:0; PCL:0; RULEID:(7020095)(4652020)(5600026)(4604075)(4534165)(4627221)(201703031133081)(201702281549075)(2017052603328)(7153060); SRVR:DM2PR02MB1305; X-Microsoft-Exchange-Diagnostics: 1; DM2PR02MB1305; 3:K9PX9cSlMt9kOY937mMJ5yNw85b/d1FV+SmU/fsfv892MAIK/b86TtrFxl8xHD9kkxFTVqyApLIGvnOdXMEPvCYTJzG5yYQL++8aghgMiuRgZ4ReEIbGQ0ono2ziRz8QKOQeF9EGTDMFxfakNyx7LEfssADezpIHUQM+siU2d7JHmqirxtO6QyIeXloUowOajEC0uG9wPzGghuapMSQkCbjKcnSz8HMJmwhUY9gdAPiYsrSrtG/3vN+W3r6GhF4TNZw2xSRxIWhDLupPa86Jfl69GvHPdy78AohQDIHMSIixRmyT5YEf7NRkpFTmr0c7F2wYKioT4Y5FjatZQqFLXNpXwOAot6/Fz5EkHJrWr1Y=; 25:yojoOCR+2X8aJtq026eAymyNvHRRPIVibbCWu9GYV8TCAvA1uiRy8ttxdR8mrEdtt8tPAleQa1CF0jHT+ppjoniLVX2Jz3b68JqeKTFLv8XpuMxRB1xzN+mwH/NlyPbHBAR4DF8e6nKsUXeAWpKoZliDCrgR5+wL7hbP/VPbgVFT/eHoMaJBXn+M49Zvc5p5k0OiAktlkjm23ZHYdD9Fbh70a1GPbMyv/n1eCjTpfL0MXsLdiOHS/GoEB4XY4ZGY2Okf7C1e5C/2jJwOEt+JdAzm+QZGD3j0HMEaYDdvqg0px3znQ2+r2KMqvVzZzsXkhv8h4zI8fyIp2F/RRojy8Q== X-MS-TrafficTypeDiagnostic: DM2PR02MB1305: X-Microsoft-Exchange-Diagnostics: 1; DM2PR02MB1305; 31:t4+S3sq+j4Pyoqf6uPdXmvFgjAlM7qU043zomgqBpfCjiHbMz8Kn+FPwSFca3X1kTQj5hU+2Zniy3rLbIp9ZSFQmv+Ckuclu2p9BcLZht6wCbiGQeXlJ1oEY7K8XTPlOV30paW4MDp0sHeZVANuHvVf3PAUpnzQxaqLh9rX0sVERrZinpZ0W+x7SxH3LUHWxxVqZ9vlCKciBGpsqYF2+mtS5vJwoei68ObGrxyKdXzY=; 20:wBsy3AtkVxyDSCswcUGp0IUxzKOy1SZOm3c6Lku35QMD74SAxvo7alYu4O0VHatJTq2EzNQLePvRwC29Z1fHfgKicTXdeLsbZt8BitYgd28d5tiEzNclAfeBFjItsMKy/3eDYVZ/3Z+h8SvaRHY9j+eu+Qe8KutXyLCtRRJqJF1a9AMRNr6+bHEOeoeggjfh3FdU4XLd++2CbrbxlKtaK4SCIWCZazsh5QJlQbSovrMW2iUQZ5GrzjnD1Ey8G7d8HIFe2UVldxEZ6AQj3LZ49EXY5pUXaVvEh7aqqUQAbMRDG6yaYuBoDNAEYPa8WmP/iFKlzbAK4K203qw4GKSuGUFdk6ucqheLlqICGq6Y5GIsYhM5d01EeLde0FU8cJYETjqwvxkIZ5WfW3+nX+OFstOjDsK3RXhcCA+V4ecdRTqQdSR5nRGBTNRShMk+zcdr+uqrv9bnwaOCXkImevItYVsJybX9v/U5/Dzgqommuh1hkeAa1Fkd3byVkeVG/Eq0 X-Auto-Response-Suppress: DR, RN, NRN, OOF, AutoReply X-Microsoft-Antispam-PRVS: X-Exchange-Antispam-Report-Test: UriScan:(192813158149592); X-Exchange-Antispam-Report-CFA-Test: BCL:0; PCL:0; RULEID:(8211001083)(6040522)(2401047)(5005006)(8121501046)(10201501046)(3002001)(93006095)(93001095)(3231221)(944501327)(52105095)(6055026)(6041310)(201703131423095)(201702281528075)(20161123555045)(201703061421075)(201703061406153)(20161123560045)(20161123564045)(20161123558120)(20161123562045)(6072148)(201708071742011); SRVR:DM2PR02MB1305; BCL:0; PCL:0; RULEID:; SRVR:DM2PR02MB1305; X-Microsoft-Exchange-Diagnostics: 1; DM2PR02MB1305; 4:7KkJJNYi3oMxFH6cJPn9h4kwktVSd4BPN7yIIJ38BTV7CtnwSJujCZ/YuOGwSBKDamywi6TxPDwTy9PqLxM/ukuJz9ROc8nMPADoulqL8BDiwAG7J60sGj9D38UdPeX6bbiUzL0tH3KdNJGqBcjT858ki/S47fobjY+RA/T1pi84mJZlEq2n9tXQiT2D4Ip/L70XbwYH3iicHSeKdQxL1pkpK8zr4cBkk413A3PdFjOSjH3fe6yhMt4VkBHj7wdTW8ZcNMhTUphZ7ELud3QIKElUUBh5vIo0HmoOCdZ7fOQSncfXVlTWDMeSpJ48M9vA X-Forefront-PRVS: 0630013541 X-Microsoft-Exchange-Diagnostics: =?us-ascii?Q?1; DM2PR02MB1305; 23:c5uCOmKK3r1xq2zuT9qXo/P9pX8jF5+yHSgDXTduT?= 9fHUx2qokPp3GxKOS7AM16m1NfCCCy19U/g2diE1UT+BfErw+xJ6D4UpEx0UlBt4cb9j/TOXsWntDVk9NmnIatcT9qOLwDVdnfcVKDSzakNBMGmAl6CPV0vaaxclNGb0AtNj9swVt5/ytLcSrDS/AFhbirstZH420H2ceF4Cx0rFkduu2DpTjdcS0XecQLyaosRfPAxGl5L6bzGHxegVW7wSNqmsdnBBgMiycCAIP5iet6pDLZNtjyFR4Nhj1+Ik85ju5hPAcbGXJQPYgNFF4b5pmXySZWqzBiJbXoG9ecwLaQ8JggWVvAwA8Wew0NlanfZ+k7Jwspj+ubIF4ApymjUkaZyjF8uxN7LEXOQuTNWXwoAjifJmmz4FjDPAKIvDCsZQ4JSxUdH/2YpzHtLqMb5uGE+IKgWLUsNF8X6kXSF3Ua+2/5/t/OeyC4zaKrPREJIf8LcDS2ZSSE1DuwSPSGSQikYFu4SwbzgdxPJe+kiHqLtkIeuhtTGASr9BWpUJZfQewHP+KhF4yMLCMT+FpSz9CsuJDfCxeSkmWcI47hQejZNjN2yPmHHGoclAOnx4IkT5ymDxg8jgEsUXmNFkA6wUmisjmh4LDwhljsmTlxQ467BP49brM7QD2jDasb4qzZp9TV/KBt3FFE/cUTAXUxrIm8QSiRmgQ6WnGZY2R9nSKlVaWl07no3n1N8e1nviWb7Xbgxr4L93acBbtZHYbw0rfyL2myMfXSwGsOlEyfYILqnAaw8uncMymr51BYz7+sNpeRJR6nkFbjizf9Gnv1EsIuRne0b5/2I8FAtpVZZ1ke9oaWLv7ArxdkfPWdzCwit6PQpkE1bzdBqjch791fArKcgpt+0mULfhMNevk1UgpUeWLQMoel/KcJHWiwz2dKjV/JuyzxE/9zjerHkg4lawARku5zAeB9zUIX2Ewh3rgAalyUpZmJOqiVgneKkPNcO1uIpuH12iwBdaJUA3LlksG7I3uEaflgUT/PA17Uc2XIepVldAQAlgVaZB6V0eU4StdIQS7xete4Vdnlz3n+9+FJlSmnmWcxbfe9lR7kiO8SffbbPUJb5n72WbQIvQs5KI1mj7vQI4zty1b84W4129nvfshlhJprbxJ31Ee3zmmFQuBHqLNyPEWZuNkfOlTTwgVtUCV/DAdltVFkmajPwfTicr+LvzqixAOEBj3U0glamMb7TMsrxR0lvnH5xOennIN+1ryussgZogEtKK6cH17IitrO2oYAKD6KrUCHFlQ== X-Microsoft-Antispam-Message-Info: IryASVLMycDAKTmNBWbvFs+3UoiJOxNKWzfNX1ZIdohyfq1INVi6vQCkTDYGEnfJa0kDM9ebZpX4TPxET9PeetDjNfgD9W9yPzlMvW6tELv9voeUXi3CJwOcOFlfucmCFTr3UNtwrXepRmYnJ2b2CLd5EcilT52YRS/cLQgQjiL31YNrUNEv8XQXmv9XoI4k X-Microsoft-Exchange-Diagnostics: 1; DM2PR02MB1305; 6:zwRKhCzpGfyrh6iJhdIn5s8+5DV4YhKMzkUEdKKnaOyx7J2OBNs3STvjjXWGZyX2faah0NJ/AN2rCSmK2KMwlvBppqoDXwGmIksSBTBAMY+nqMxKXzBpFNjkzd0+uGVGq5OlIooTSZ8Mzy8rfcdhGFCAOYnfoumZwsNtsLNHK9J8rVTHi4UNfZV/AQfNCl67OB2+XokY1hn1Eb1JoosDzlluGk2spuerWXXX8M1RNrQ0Yovx6KoQzjj2eCFU8HlTe4EYyMCKp1kcD/mkvTuhIoQfldQcuCbFoiUCflS8IlfBfT+Z4nMkObGqRxeFfLWmAKT6VZl3g+nrinfIxlZnOa5XCZLysb9fMQI9PzDtHnkzhBBKbZtG/Al+52vZAtZ4Msq6FB2Fk8dapMLvBc5F1CQMPbLOtw3ESUpOde/WgcLJt3Hx/2PrOJGmPvZMDiyXd6eQsdhxfwCRnLepLnW8Sg==; 5:ZMJGHOUo+KZPLOUq9Z/Wqgr7xK4mPcRI074+HdJnxJ+7S/fslFOcd7SHUDGqHW7e60eyQClw/JQxtrdfdLXvfAotv5rE8AUtQqQT2FHzUXEZxMLPSnXy1w3E826e98jsJiKd3pt8tVd63jjBq0kDE3qa0B3HHnqlWYG/gpDbf74=; 24:/S7OKov9CAjNc3AauBzpup8dqoN27zjJ6SD7fKyKldhkiS8KDDKbbmiZHxYY81mON2yGbfm6uT7qqNy219B1n7JRH1Qdx2T2WfoMMXUux7A= SpamDiagnosticOutput: 1:99 SpamDiagnosticMetadata: NSPM X-Microsoft-Exchange-Diagnostics: 1; DM2PR02MB1305; 7:RzVC0Ar0Ukpgm2brJiPlxzb1KS5pYXqJ+FQhOb8UfrL6yG6tGPfQcoGqlloXdgqQ+J7nfxbRvVqNMN4EN8kdP91iuuWiRBsDCfYOK48N5ZpTqkMF9QNW/0zF6UpT8wq5LYe5hixZC5sQsBdlw1HI7Xg1w8SYIeZ2t5KmqWDauYD1XMlpb7wW5RKENGuWMw9TAKp9h0GE+bKT2JxTY1n1vrV3zkvYd2PVZnm+e4tDmyVFOBkayLz02Fi0iG/jzhzv X-OriginatorOrg: xilinx.com X-MS-Exchange-CrossTenant-OriginalArrivalTime: 02 Apr 2018 06:14:14.8883 (UTC) X-MS-Exchange-CrossTenant-Network-Message-Id: d21954ba-6ae7-487f-c818-08d59860f5eb X-MS-Exchange-CrossTenant-Id: 657af505-d5df-48d0-8300-c31994686c5c X-MS-Exchange-CrossTenant-OriginalAttributedTenantConnectingIp: TenantId=657af505-d5df-48d0-8300-c31994686c5c; Ip=[149.199.60.100]; Helo=[xsj-pvapsmtpgw02] X-MS-Exchange-CrossTenant-FromEntityHeader: HybridOnPrem X-MS-Exchange-Transport-CrossTenantHeadersStamped: DM2PR02MB1305 Cc: michal.simek@xilinx.com, Siva Durga Prasad Paladugu Subject: [U-Boot] [RFC PATCH 2/2] zynq: Add support for loading secure images X-BeenThere: u-boot@lists.denx.de X-Mailman-Version: 2.1.18 Precedence: list List-Id: U-Boot discussion List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: u-boot-bounces@lists.denx.de Sender: "U-Boot" This patch adds support to load secure images secure image is an image which is authenticated or encrypted or both autheticated and encrypted image in xilinx boot image(BOOT.BIN) format. The secure image has to be created using xilinx bootgen tool. Signed-off-by: Siva Durga Prasad Paladugu --- board/xilinx/zynq/Kconfig | 12 + board/xilinx/zynq/Makefile | 4 + board/xilinx/zynq/cmds.c | 602 +++++++++++++++++++++++++++++++++++++++++++ include/u-boot/rsa-mod-exp.h | 4 + lib/rsa/rsa-mod-exp.c | 51 ++++ 5 files changed, 673 insertions(+) create mode 100644 board/xilinx/zynq/cmds.c -- 2.7.4 This email and any attachments are intended for the sole use of the named recipient(s) and contain(s) confidential information that may be proprietary, privileged or copyrighted under applicable law. If you are not the intended recipient, do not read, copy, or forward this email message or any attachments. Delete this email message and any attachments immediately. diff --git a/board/xilinx/zynq/Kconfig b/board/xilinx/zynq/Kconfig index f8f8a7f..54d71dc 100644 --- a/board/xilinx/zynq/Kconfig +++ b/board/xilinx/zynq/Kconfig @@ -11,4 +11,16 @@ config CMD_ZYNQ_AES Decrypts the encrypted image present in source address and places the decrypted image at destination address. +config CMD_ZYNQ + bool "Enable ZynqMP specific commands" + default y + depends on CMD_ZYNQ_AES + help + Enable Zynq specific commands like "zynq rsa" + which is used for zynq secure image verification. + The secure image is a xilinx specific BOOT.BIN with + either authentication or encryption or both encryption + and authentication feature enabled while generating + BOOT.BIN using Xilinx bootgen tool. + endif diff --git a/board/xilinx/zynq/Makefile b/board/xilinx/zynq/Makefile index 7de0212..07a5bc5 100644 --- a/board/xilinx/zynq/Makefile +++ b/board/xilinx/zynq/Makefile @@ -20,6 +20,10 @@ $(warning Put custom ps7_init_gpl.c/h to board/xilinx/zynq/custom_hw_platform/)) endif endif +ifndef CONFIG_SPL_BUILD +obj-$(CONFIG_CMD_ZYNQ) += cmds.o +endif + obj-$(CONFIG_SPL_BUILD) += $(init-objs) # Suppress "warning: function declaration isn't a prototype" diff --git a/board/xilinx/zynq/cmds.c b/board/xilinx/zynq/cmds.c new file mode 100644 index 0000000..9365557 --- /dev/null +++ b/board/xilinx/zynq/cmds.c @@ -0,0 +1,602 @@ +/* + * Copyright (C) 2018 Xilinx, Inc. + * + * SPDX-License-Identifier: GPL-2.0+ + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +DECLARE_GLOBAL_DATA_PTR; + +#define ZYNQ_IMAGE_PHDR_OFFSET 0x09C +#define ZYNQ_IMAGE_FSBL_LEN_OFFSET 0x040 + +#define ZYNQ_PART_HDR_CHKSUM_WORD_COUNT 0x0F +#define ZYNQ_PART_HDR_WORD_COUNT 0x10 + +#define ZYNQ_EFUSE_RSA_ENABLE_MASK 0x400 + +#define ZYNQ_ATTRIBUTE_PL_IMAGE_MASK 0x20 +#define ZYNQ_ATTRIBUTE_CHECKSUM_TYPE_MASK 0x7000 +#define ZYNQ_ATTRIBUTE_RSA_PRESENT_MASK 0x8000 +#define ZYNQ_ATTRIBUTE_RSA_PART_OWNER_MASK 0x30000 + +#define ZYNQ_MAX_PARTITION_NUMBER 0xE + +#define ZYNQ_RSA_MODULAR_SIZE 256 +#define ZYNQ_RSA_MODULAR_EXT_SIZE 256 +#define ZYNQ_RSA_EXPO_SIZE 64 +#define ZYNQ_RSA_SPK_SIGNATURE_SIZE 256 +#define ZYNQ_RSA_PARTITION_SIGNATURE_SIZE 256 +#define ZYNQ_RSA_SIGNATURE_SIZE 0x6C0 +#define ZYNQ_RSA_HEADER_SIZE 4 +#define ZYNQ_RSA_MAGIC_WORD_SIZE 60 +#define ZYNQ_RSA_PART_OWNER_UBOOT 1 +#define ZYNQ_RSA_ALIGN_PPK_START 64 + +#define WORD_LENGTH_SHIFT 2 +#define ZYNQ_MAXIMUM_IMAGE_WORD_LEN 0x40000000 + +#define MD5_CHECKSUM_SIZE 16 + +static u8 *ppkmodular; +static u8 *ppkmodularex; +static u32 ppkexp; + +struct partition_hdr { + u32 imagewordlen; /* 0x0 */ + u32 datawordlen; /* 0x4 */ + u32 partitionwordlen; /* 0x8 */ + u32 loadaddr; /* 0xC */ + u32 execaddr; /* 0x10 */ + u32 partitionstart; /* 0x14 */ + u32 partitionattr; /* 0x18 */ + u32 sectioncount; /* 0x1C */ + u32 checksumoffset; /* 0x20 */ + u32 pads1[1]; + u32 acoffset; /* 0x28 */ + u32 pads2[4]; + u32 checksum; /* 0x3C */ +}; + +struct zynq_rsa_public_key { + uint len; /* Length of modulus[] in number of u32 */ + u32 n0inv; /* -1 / modulus[0] mod 2^32 */ + u32 *modulus; /* modulus as little endian array */ + u32 *rr; /* R^2 as little endian array */ +}; + +struct partition_hdr part_hdr[ZYNQ_MAX_PARTITION_NUMBER]; + +struct headerarray { + u32 fields[16]; +}; + +struct zynq_rsa_public_key public_key; + +static u32 fsbl_len; + +/* + * Check whether the given partition is last partition or not + */ +static int zynq_islastpartition(struct headerarray *head) +{ + int index; + + debug("%s\n", __func__); + if (head->fields[ZYNQ_PART_HDR_CHKSUM_WORD_COUNT] != 0xFFFFFFFF) + return -1; + + for (index = 0; index < ZYNQ_PART_HDR_WORD_COUNT - 1; index++) { + if (head->fields[index] != 0x0) + return -1; + } + + return 0; +} + +/* + * Get the partition count from the partition header + */ +static int zynq_get_part_count(struct partition_hdr *part_hdr_info) +{ + u32 count = 0; + struct headerarray *hap; + + debug("%s\n", __func__); + + for (count = 0; count < ZYNQ_MAX_PARTITION_NUMBER; count++) { + hap = (struct headerarray *)&part_hdr_info[count]; + if (zynq_islastpartition(hap) != -1) + break; + } + + return count; +} + +/* + * Get the partition info of all the partitions available. + */ +static int zynq_get_partition_info(u32 image_base_addr) +{ + u32 parthdroffset; + + fsbl_len = *((u32 *)(image_base_addr + ZYNQ_IMAGE_FSBL_LEN_OFFSET)); + + parthdroffset = *((u32 *)(image_base_addr + ZYNQ_IMAGE_PHDR_OFFSET)); + + parthdroffset += image_base_addr; + + memcpy(&part_hdr[0], (u32 *)parthdroffset, + (sizeof(struct partition_hdr) * ZYNQ_MAX_PARTITION_NUMBER)); + + return 0; +} + +/* + * Check whether the partition header is valid or not + */ +static int zynq_validate_hdr(struct partition_hdr *header) +{ + struct headerarray *hap; + u32 index; + u32 checksum; + + debug("%s\n", __func__); + + hap = (struct headerarray *)header; + + for (index = 0; index < ZYNQ_PART_HDR_WORD_COUNT; index++) { + if (hap->fields[index] != 0x0) + break; + } + if (index == ZYNQ_PART_HDR_WORD_COUNT) + return -1; + + checksum = 0; + for (index = 0; index < ZYNQ_PART_HDR_CHKSUM_WORD_COUNT; index++) + checksum += hap->fields[index]; + + checksum ^= 0xFFFFFFFF; + + if (hap->fields[ZYNQ_PART_HDR_CHKSUM_WORD_COUNT] != checksum) { + printf("Error: Checksum 0x%8.8x != 0x%8.8x\r\n", + checksum, hap->fields[ZYNQ_PART_HDR_CHKSUM_WORD_COUNT]); + return -1; + } + + if (header->imagewordlen > ZYNQ_MAXIMUM_IMAGE_WORD_LEN) { + printf("INVALID_PARTITION_LENGTH\r\n"); + return -1; + } + + return 0; +} + +/* + * Validate the partition by calculationg the md5 checksum for the + * partition and compare with checksum present in checksum offset of + * partition + */ +static int zynq_validate_partition(u32 start_addr, u32 len, u32 chksum_off) +{ + u8 checksum[MD5_CHECKSUM_SIZE]; + u8 calchecksum[MD5_CHECKSUM_SIZE]; + + memcpy(&checksum[0], (u32 *)chksum_off, MD5_CHECKSUM_SIZE); + + md5_wd((u8 *)start_addr, len, &calchecksum[0], 0x10000); + + if ((memcmp(checksum, calchecksum, MD5_CHECKSUM_SIZE)) != 0) { + printf("Error: Partition DataChecksum \r\n"); + return -1; + } + return 0; +} + +/* + * Extract the primary public key components from already autheticated FSBL + */ +static void zynq_extract_ppk(void) +{ + u32 padsize; + u8 *ppkptr; + + debug("%s\n", __func__); + + ppkptr = (u8 *)(fsbl_len + 0xFFFC0000); + padsize = ((u32)ppkptr % ZYNQ_RSA_ALIGN_PPK_START); + if (padsize != 0) + ppkptr += (ZYNQ_RSA_ALIGN_PPK_START - padsize); + + ppkptr += ZYNQ_RSA_HEADER_SIZE; + + ppkptr += ZYNQ_RSA_MAGIC_WORD_SIZE; + + ppkmodular = (u8 *)ppkptr; + ppkptr += ZYNQ_RSA_MODULAR_SIZE; + ppkmodularex = (u8 *)ppkptr; + ppkptr += ZYNQ_RSA_MODULAR_EXT_SIZE; + ppkexp = *(u32 *)ppkptr; +} + +/* + * Calculate the inverse(-1 / modulus[0] mod 2^32 ) for the PPK + */ +static u32 zynq_calc_inv(void) +{ + u32 modulus = public_key.modulus[0]; + u32 tmp = BIT(1); + u32 inverse; + + inverse = modulus & BIT(0); + + while (tmp) { + inverse *= 2 - modulus * inverse; + tmp *= tmp; + } + + return -inverse; +} + +/* + * Recreate the signature by padding the bytes and verify with hash value + */ +static int zynq_pad_and_check(u8 *signature, u8 *hash) +{ + u8 padding[] = {0x30, 0x31, 0x30, 0x0D, 0x06, 0x09, 0x60, 0x86, 0x48, + 0x01, 0x65, 0x03, 0x04, 0x02, 0x01, 0x05, 0x00, 0x04, + 0x20 }; + u8 *pad_ptr = signature + 256; + u32 pad = 256 - 3 - 19 - 32; + u32 ii; + + /* Re-Create PKCS#1v1.5 Padding */ + if (*--pad_ptr != 0x00 || *--pad_ptr != 0x01) + return -1; + + for (ii = 0; ii < pad; ii++) { + if (*--pad_ptr != 0xFF) + return -1; + } + + if (*--pad_ptr != 0x00) + return -1; + + for (ii = 0; ii < sizeof(padding); ii++) { + if (*--pad_ptr != padding[ii]) + return -1; + } + + for (ii = 0; ii < 32; ii++) { + if (*--pad_ptr != hash[ii]) + return -1; + } + return 0; +} + +/* + * Verify and extract the hash value from signature using the public key + * and compare it with calculated hash value. + */ +static int zynq_rsa_verify_key(const struct zynq_rsa_public_key *key, + const u8 *sig, const u32 sig_len, const u8 *hash) +{ + int status; + + if ((!key) || (!sig) || (!hash)) + return -1; + + if (sig_len != (key->len * sizeof(u32))) { + printf("Signature is of incorrect length %d\n", sig_len); + return -1; + } + + /* Sanity check for stack size */ + if (sig_len > ZYNQ_RSA_SPK_SIGNATURE_SIZE) { + printf("Signature length %u exceeds maximum %d\n", sig_len, + ZYNQ_RSA_SPK_SIGNATURE_SIZE); + return -1; + } + + u32 buf[sig_len / sizeof(u32)]; + + memcpy(buf, sig, sig_len); + + status = zynq_pow_mod((u32 *)key, buf); + if (status == -1) + return status; + + status = zynq_pad_and_check((u8 *)buf, (u8 *)hash); + if (status == -1) + return status; + return 0; +} + +/* + * Authenticate the partition + */ +static int zynq_authenticate_part(u8 *buffer, u32 size) +{ + u8 hash_signature[32]; + u8 *spk_modular; + u8 *spk_modular_ex; + u8 *signature_ptr; + u32 status; + + debug("%s\n", __func__); + + signature_ptr = (u8 *)(buffer + size - ZYNQ_RSA_SIGNATURE_SIZE); + + signature_ptr += ZYNQ_RSA_HEADER_SIZE; + + signature_ptr += ZYNQ_RSA_MAGIC_WORD_SIZE; + + ppkmodular = (u8 *)signature_ptr; + signature_ptr += ZYNQ_RSA_MODULAR_SIZE; + ppkmodularex = signature_ptr; + signature_ptr += ZYNQ_RSA_MODULAR_EXT_SIZE; + signature_ptr += ZYNQ_RSA_EXPO_SIZE; + + sha256_csum_wd((const unsigned char *)signature_ptr, + (ZYNQ_RSA_MODULAR_EXT_SIZE + ZYNQ_RSA_EXPO_SIZE + + ZYNQ_RSA_MODULAR_SIZE), + (unsigned char *)hash_signature, 0x1000); + + spk_modular = (u8 *)signature_ptr; + signature_ptr += ZYNQ_RSA_MODULAR_SIZE; + spk_modular_ex = (u8 *)signature_ptr; + signature_ptr += ZYNQ_RSA_MODULAR_EXT_SIZE; + signature_ptr += ZYNQ_RSA_EXPO_SIZE; + + public_key.len = ZYNQ_RSA_MODULAR_SIZE / sizeof(u32); + public_key.modulus = (u32 *)ppkmodular; + public_key.rr = (u32 *)ppkmodularex; + public_key.n0inv = zynq_calc_inv(); + + status = zynq_rsa_verify_key(&public_key, signature_ptr, + ZYNQ_RSA_SPK_SIGNATURE_SIZE, + hash_signature); + + if (status) + return status; + + signature_ptr += ZYNQ_RSA_SPK_SIGNATURE_SIZE; + + sha256_csum_wd((const unsigned char *)buffer, + (size - ZYNQ_RSA_PARTITION_SIGNATURE_SIZE), + (unsigned char *)hash_signature, 0x1000); + + public_key.len = ZYNQ_RSA_MODULAR_SIZE / sizeof(u32); + public_key.modulus = (u32 *)spk_modular; + public_key.rr = (u32 *)spk_modular_ex; + public_key.n0inv = zynq_calc_inv(); + + status = zynq_rsa_verify_key(&public_key, (u8 *)signature_ptr, + ZYNQ_RSA_PARTITION_SIGNATURE_SIZE, + (u8 *)hash_signature); + + if (status) + return status; + + return 0; +} + +/* + * Parses the partition header and verfies the authenticated and + * encrypted image. + */ +static int zynq_verify_image(u32 src_ptr) +{ + u32 silicon_ver; + u32 image_base_addr; + u32 status; + u32 partition_num; + u32 efuseval; + u32 srcaddr; + u32 size; + struct partition_hdr *hdr_ptr; + u32 part_data_len; + u32 part_img_len; + u32 part_attr; + u32 part_load_addr; + u32 part_dst_addr; + u32 part_chksum_offset; + u32 part_start_addr; + u32 part_total_size; + u32 partitioncount; + u8 encrypt_part_flag; + u8 part_chksum_flag; + u8 signed_part_flag; + + image_base_addr = src_ptr; + + silicon_ver = zynq_get_silicon_version(); + + /* RSA not supported in silicon versions 1.0 and 2.0 */ + if (silicon_ver == 0 || silicon_ver == 1) + return -1; + + status = zynq_get_partition_info(image_base_addr); + if (status == -1) { + printf("Get Partition Info Failed\n"); + return status; + } + + /* Extract ppk if efuse was blown Otherwise return error */ + efuseval = readl(&efuse_base->status); + if (efuseval & ZYNQ_EFUSE_RSA_ENABLE_MASK) + zynq_extract_ppk(); + else + return -1; + + partitioncount = zynq_get_part_count(&part_hdr[0]); + + if ((partitioncount <= 2) || + (partitioncount > ZYNQ_MAX_PARTITION_NUMBER)) + return -1; + + partition_num = 0; + + while (partition_num < partitioncount) { + if (((part_hdr[partition_num].partitionattr & + ZYNQ_ATTRIBUTE_RSA_PART_OWNER_MASK) >> 16) != + ZYNQ_RSA_PART_OWNER_UBOOT) { + printf("UBOOT is not Owner for partition %d\r\n", + partition_num); + } else { + hdr_ptr = &part_hdr[partition_num]; + status = zynq_validate_hdr(hdr_ptr); + if (status == -1) + return status; + + part_data_len = hdr_ptr->datawordlen; + part_img_len = hdr_ptr->imagewordlen; + part_attr = hdr_ptr->partitionattr; + part_load_addr = hdr_ptr->loadaddr; + part_chksum_offset = hdr_ptr->checksumoffset; + part_start_addr = hdr_ptr->partitionstart; + part_total_size = hdr_ptr->partitionwordlen; + + if (part_data_len != part_img_len) { + debug("Encrypted\r\n"); + encrypt_part_flag = 1; + } else { + encrypt_part_flag = 0; + } + + if (part_attr & ZYNQ_ATTRIBUTE_CHECKSUM_TYPE_MASK) + part_chksum_flag = 1; + else + part_chksum_flag = 0; + + if (part_attr & ZYNQ_ATTRIBUTE_RSA_PRESENT_MASK) { + debug("RSA Signed\r\n"); + signed_part_flag = 1; + } else { + signed_part_flag = 0; + } + + srcaddr = image_base_addr + + (part_start_addr << WORD_LENGTH_SHIFT); + + if (part_attr & ZYNQ_ATTRIBUTE_RSA_PRESENT_MASK) { + signed_part_flag = 1; + size = part_total_size << WORD_LENGTH_SHIFT; + } else { + signed_part_flag = 0; + size = part_img_len; + } + + if ((part_load_addr < gd->bd->bi_dram[0].start) && + ((part_load_addr + part_data_len) > + (gd->bd->bi_dram[0].start + + gd->bd->bi_dram[0].size))) { + printf("INVALID_LOAD_ADDRESS_FAIL\r\n"); + return -1; + } + + if (part_attr & ZYNQ_ATTRIBUTE_PL_IMAGE_MASK) + part_load_addr = srcaddr; + else + memcpy((u32 *)part_load_addr, (u32 *)srcaddr, + size); + + if (!signed_part_flag && !part_chksum_flag) { + printf("Partition not signed & no chksum\n"); + continue; + } + + if (part_chksum_flag) { + part_chksum_offset = image_base_addr + + (part_chksum_offset << + WORD_LENGTH_SHIFT); + status = zynq_validate_partition(part_load_addr, + (part_total_size << + WORD_LENGTH_SHIFT), + part_chksum_offset); + if (status != 0) { + printf("PART_CHKSUM_FAIL\r\n"); + return -1; + } + debug("Partition Validation Done\r\n"); + } + + if (signed_part_flag == 1) { + status = zynq_authenticate_part( + (u8 *)part_load_addr, + size); + if (status != 0) { + printf("AUTHENTICATION_FAIL\r\n"); + return -1; + } + debug("Authentication Done\r\n"); + } + + if (encrypt_part_flag) { + debug("DECRYPTION \r\n"); + + part_dst_addr = part_load_addr; + + if (part_attr & ZYNQ_ATTRIBUTE_PL_IMAGE_MASK) + part_dst_addr = 0xFFFFFFFF; + + status = zynq_decrypt_load(part_load_addr, + part_img_len, + part_dst_addr, + part_data_len, + BIT_NONE); + if (status != 0) { + printf("DECRYPTION_FAIL\r\n"); + return -1; + } + } + } + partition_num++; + } + + return 0; +} + +static int do_zynq(cmd_tbl_t *cmdtp, int flag, int argc, + char * const argv[]) +{ + u32 src_ptr; + int ret; + char *endp; + + if (argc < 2 || strncmp(argv[1], "rsa", 3)) + goto usage; + + src_ptr = simple_strtoul(argv[2], &endp, 16); + if (*argv[2] == 0 || *endp != 0) + goto usage; + + ret = zynq_verify_image(src_ptr); + if (!ret) + return 0; + +usage: + return CMD_RET_USAGE; +} + +#ifdef CONFIG_SYS_LONGHELP +static char zynq_help_text[] = + "rsa - Verifies the authenticated and encrypted\n" + " zynq images\n"; +#endif + +U_BOOT_CMD( + zynq, 3, 0, do_zynq, + "Zynq specific commands RSA verfication ", zynq_help_text +); diff --git a/include/u-boot/rsa-mod-exp.h b/include/u-boot/rsa-mod-exp.h index 45a031b..61068d2 100644 --- a/include/u-boot/rsa-mod-exp.h +++ b/include/u-boot/rsa-mod-exp.h @@ -43,6 +43,10 @@ int rsa_mod_exp_sw(const uint8_t *sig, uint32_t sig_len, int rsa_mod_exp(struct udevice *dev, const uint8_t *sig, uint32_t sig_len, struct key_prop *node, uint8_t *out); +#if defined(CONFIG_CMD_ZYNQ) +int zynq_pow_mod(u32 *keyptr, u32 *inout); +#endif + /** * struct struct mod_exp_ops - Driver model for RSA Modular Exponentiation * operations diff --git a/lib/rsa/rsa-mod-exp.c b/lib/rsa/rsa-mod-exp.c index 9d78aa1..adaf433 100644 --- a/lib/rsa/rsa-mod-exp.c +++ b/lib/rsa/rsa-mod-exp.c @@ -301,3 +301,54 @@ int rsa_mod_exp_sw(const uint8_t *sig, uint32_t sig_len, return 0; } + +#if defined(CONFIG_CMD_ZYNQ) +/** + * zynq_pow_mod() - in-place public exponentiation + * + * @keyptr: RSA key + * @inout: Big-endian word array containing value and result + * + * FIXME: Use pow_mod() instead of zynq_pow_mod() + * pow_mod calculation required for zynq is bit different from + * pw_mod above here, hence defined zynq specific routine. + */ +int zynq_pow_mod(u32 *keyptr, u32 *inout) +{ + u32 *result, *ptr; + uint i; + struct rsa_public_key *key; + + key = (struct rsa_public_key *)keyptr; + + /* Sanity check for stack size - key->len is in 32-bit words */ + if (key->len > RSA_MAX_KEY_BITS / 32) { + debug("RSA key words %u exceeds maximum %d\n", key->len, + RSA_MAX_KEY_BITS / 32); + return -EINVAL; + } + + u32 val[key->len], acc[key->len], tmp[key->len]; + + result = tmp; /* Re-use location. */ + + for (i = 0, ptr = inout; i < key->len; i++, ptr++) + val[i] = *(ptr); + + montgomery_mul(key, acc, val, key->rr); /* axx = a * RR / R mod M */ + for (i = 0; i < 16; i += 2) { + montgomery_mul(key, tmp, acc, acc); /* tmp = acc^2 / R mod M */ + montgomery_mul(key, acc, tmp, tmp); /* acc = tmp^2 / R mod M */ + } + montgomery_mul(key, result, acc, val); /* result = XX * a / R mod M */ + + /* Make sure result < mod; result is at most 1x mod too large. */ + if (greater_equal_modulus(key, result)) + subtract_modulus(key, result); + + for (i = 0, ptr = inout; i < key->len; i++, ptr++) + *ptr = result[i]; + + return 0; +} +#endif