From patchwork Tue Jun 5 13:49:47 2018 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Linus Walleij X-Patchwork-Id: 137739 Delivered-To: patch@linaro.org Received: by 2002:a2e:970d:0:0:0:0:0 with SMTP id r13-v6csp986079lji; Tue, 5 Jun 2018 06:50:38 -0700 (PDT) X-Google-Smtp-Source: ADUXVKJMGQDQuwT+um5JN8D757KmdPw4hVnhk7owx7G99n/ct5ivWwb88RWBHCKdW2nz+o7/sb0p X-Received: by 2002:a62:1656:: with SMTP id 83-v6mr25635493pfw.61.1528206637859; Tue, 05 Jun 2018 06:50:37 -0700 (PDT) ARC-Seal: i=1; a=rsa-sha256; t=1528206637; cv=none; d=google.com; s=arc-20160816; b=pr7tHwDqyit61j7C0NIxhi05229//VJd+I8ajpuFj85yaFmSPSWiTIlUsep+x8Z1nG Nasmq9rzeNHwt4g5iwCgtb3JPvv/DniU3JnmpHBK4L2n4g4UWKDeQkU1Gx8GclQLx77M astdj9KkDY9SUfk96oWSiwYRjk1Ix13bQRu/QS6hEOtDmy9tDqWXZTG2B4pOhHEeCqG3 BzFB4KpcH3IdjepfaxdiCQYGi7bKrxVe0g6mz4oGRB94nwtrOBWZVNrZQZh4j/WCPiI7 KPit53zvk2+yfAMFnVHa35xwpVAhRZcsdsrLEcrA9rGYrqffwSXR73WXUTc0R8uUr8D0 E7Og== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=list-id:precedence:sender:references:in-reply-to:message-id:date :subject:cc:to:from:dkim-signature:arc-authentication-results; bh=D6YbNO6YBqKM4Fb7yN5okUZ/2TOZtySAcL4Qfb/3wks=; b=BQM9Nbgym2NaZV6qQeT5ZAoPPqahqfX7ftQzNIw5zpvNWOgOsuHUmIv9b+me9r+Nju cblEvXy4roKbJN4lTrqd8RvpVMpsev+dLTZiRs3sod55f7uczWDMup0HSLjq02hSxPlP zdxpfWtWdCY+A4EKKtiIm2pE46CBXDPqta8CJ+3h3+BQkdhiZSQ3JptKWqO70zUfk+lJ KpFMblHDExAsZVNFnx9Jimin5sn9XJZHrYGwVysoFQ19IlFDJn2LLnlKNSAXAYwINE2t WMnLXhKSQYIlS67N0wbolNahTxXpQPq2CaKy5Yz+QAs4A2GlWJg+zZ+Js5kGuUtPdAQv 27hw== ARC-Authentication-Results: i=1; mx.google.com; dkim=pass header.i=@linaro.org header.s=google header.b=e+2A41rH; spf=pass (google.com: best guess record for domain of linux-crypto-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) smtp.mailfrom=linux-crypto-owner@vger.kernel.org; dmarc=pass (p=NONE sp=NONE dis=NONE) header.from=linaro.org Return-Path: Received: from vger.kernel.org (vger.kernel.org. [209.132.180.67]) by mx.google.com with ESMTP id j78-v6si24186154pfe.187.2018.06.05.06.50.37; Tue, 05 Jun 2018 06:50:37 -0700 (PDT) Received-SPF: pass (google.com: best guess record for domain of linux-crypto-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) client-ip=209.132.180.67; Authentication-Results: mx.google.com; dkim=pass header.i=@linaro.org header.s=google header.b=e+2A41rH; spf=pass (google.com: best guess record for domain of linux-crypto-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) smtp.mailfrom=linux-crypto-owner@vger.kernel.org; dmarc=pass (p=NONE sp=NONE dis=NONE) header.from=linaro.org Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1751945AbeFENug (ORCPT + 1 other); Tue, 5 Jun 2018 09:50:36 -0400 Received: from mail-lf0-f65.google.com ([209.85.215.65]:37986 "EHLO mail-lf0-f65.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1751948AbeFENuf (ORCPT ); Tue, 5 Jun 2018 09:50:35 -0400 Received: by mail-lf0-f65.google.com with SMTP id i83-v6so3711230lfh.5 for ; Tue, 05 Jun 2018 06:50:35 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=linaro.org; s=google; h=from:to:cc:subject:date:message-id:in-reply-to:references; bh=D6YbNO6YBqKM4Fb7yN5okUZ/2TOZtySAcL4Qfb/3wks=; b=e+2A41rHl0l2ZLdhF3/MquRYXDCirfZknYN289DvPUvDjgEW+joQX9XPJDyzzEDlIM jvuI2DWy3G3wFbtiUxLzzwwltO9lOVjPyjt6mXJ6UoFMFS9T3TtMHSmeHFimP103hf6y 1k154i1ob8l424EaeMA6gwmmk9uh/LMsn/WyE= X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references; bh=D6YbNO6YBqKM4Fb7yN5okUZ/2TOZtySAcL4Qfb/3wks=; b=Ziw2Y3eXn+p7NL6gy9bJoQU7weu3/drV+EEK9T4kUeO0065G5wAKnfH2790xkvk4oJ FN+m3sZc7W4aT9rVrpZl3GcbInUpqTyc7uC1r13a7+DBfM39yUFHfvRmMlz/o0AqX13R Hgk+2jtau9mVvrIIAOZeBYrnDf1iZCCUEdUF6SQkVMuKY3c/9SFznJ5VCT6qnF/RbAFu pFkix8RdHOlmRTgp9my+Xo8VaNnoFrAotLK57VjO+FYcIoTUDjQ5jU06QKhK4WZaU+9g ZDJIcq3Rbopk3XNt2uL05rpxSnBg1A9ZfZESaHmfd8G54f3RctF+prIfVVZyG8oKWuy6 Woxg== X-Gm-Message-State: APt69E1gtFYPypE4n/m57kUJ7mOA/c8jxZs6nAxcJGLdiPbz4iU7xJjC sPnQ/YlD2BIvkn4x8FakCr1290TKQFM= X-Received: by 2002:a2e:9c08:: with SMTP id s8-v6mr600489lji.97.1528206634080; Tue, 05 Jun 2018 06:50:34 -0700 (PDT) Received: from genomnajs.ideon.se ([85.235.10.227]) by smtp.gmail.com with ESMTPSA id x72-v6sm5201092lfi.52.2018.06.05.06.50.32 (version=TLS1_2 cipher=ECDHE-RSA-CHACHA20-POLY1305 bits=256/256); Tue, 05 Jun 2018 06:50:32 -0700 (PDT) From: Linus Walleij To: linux-crypto@vger.kernel.org, Herbert Xu , Tudor Ambarus Cc: Linus Walleij Subject: [PATCH 6/9] crypto: atmel-ecc: Marshal the command while sending Date: Tue, 5 Jun 2018 15:49:47 +0200 Message-Id: <20180605134950.6605-6-linus.walleij@linaro.org> X-Mailer: git-send-email 2.17.0 In-Reply-To: <20180605134950.6605-1-linus.walleij@linaro.org> References: <20180605134950.6605-1-linus.walleij@linaro.org> Sender: linux-crypto-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-crypto@vger.kernel.org Instead of casting the struct for the command into (u8 *) which is problematic in many ways, and instead of calculating the CRC sum in a separate function, marshal, checksum and send the command in one single function. Instead of providing the length of the whole command in defines, it makes more sense to provide the length of the data buffer used with the command. This avoids the hazzle to try to keep the command structure in the device endianness, we fix up the endianness when marshalling the command instead. Signed-off-by: Linus Walleij --- drivers/crypto/atmel-ecc.c | 71 ++++++++++++++++++-------------------- drivers/crypto/atmel-ecc.h | 13 +++---- 2 files changed, 40 insertions(+), 44 deletions(-) -- 2.17.0 diff --git a/drivers/crypto/atmel-ecc.c b/drivers/crypto/atmel-ecc.c index d89b69d228ac..603e29bdcb97 100644 --- a/drivers/crypto/atmel-ecc.c +++ b/drivers/crypto/atmel-ecc.c @@ -113,29 +113,6 @@ struct atmel_ecc_work_data { struct atmel_ecc_cmd cmd; }; -static u16 atmel_ecc_crc16(u16 crc, const u8 *buffer, size_t len) -{ - return cpu_to_le16(bitrev16(crc16(crc, buffer, len))); -} - -/** - * atmel_ecc_checksum() - Generate 16-bit CRC as required by ATMEL ECC. - * CRC16 verification of the count, opcode, param1, param2 and data bytes. - * The checksum is saved in little-endian format in the least significant - * two bytes of the command. CRC polynomial is 0x8005 and the initial register - * value should be zero. - * - * @cmd : structure used for communicating with the device. - */ -static void atmel_ecc_checksum(struct atmel_ecc_cmd *cmd) -{ - u8 *data = &cmd->count; - size_t len = cmd->count - CRC_SIZE; - u16 *crc16 = (u16 *)(data + len); - - *crc16 = atmel_ecc_crc16(0, data, len); -} - static void atmel_ecc_init_read_config_word(struct atmel_ecc_cmd *cmd, u16 config_word) { @@ -143,10 +120,7 @@ static void atmel_ecc_init_read_config_word(struct atmel_ecc_cmd *cmd, cmd->opcode = OPCODE_READ; cmd->param1 = CONFIG_ZONE; cmd->param2 = config_word; - cmd->count = READ_COUNT; - - atmel_ecc_checksum(cmd); - + cmd->datasz = READ_DATASZ; cmd->msecs = MAX_EXEC_TIME_READ; cmd->rxsize = READ_RSP_SIZE; } @@ -154,14 +128,11 @@ static void atmel_ecc_init_read_config_word(struct atmel_ecc_cmd *cmd, static void atmel_ecc_init_genkey_cmd(struct atmel_ecc_cmd *cmd, u16 keyid) { cmd->word_addr = COMMAND; - cmd->count = GENKEY_COUNT; + cmd->datasz = GENKEY_DATASZ; cmd->opcode = OPCODE_GENKEY; cmd->param1 = GENKEY_MODE_PRIVATE; /* a random private key will be generated and stored in slot keyID */ - cmd->param2 = cpu_to_le16(keyid); - - atmel_ecc_checksum(cmd); - + cmd->param2 = keyid; cmd->msecs = MAX_EXEC_TIME_GENKEY; cmd->rxsize = GENKEY_RSP_SIZE; } @@ -172,11 +143,11 @@ static int atmel_ecc_init_ecdh_cmd(struct atmel_ecc_cmd *cmd, size_t copied; cmd->word_addr = COMMAND; - cmd->count = ECDH_COUNT; + cmd->datasz = ECDH_DATASZ; cmd->opcode = OPCODE_ECDH; cmd->param1 = ECDH_PREFIX_MODE; /* private key slot */ - cmd->param2 = cpu_to_le16(DATA_SLOT_2); + cmd->param2 = DATA_SLOT_2; /* * The device only supports NIST P256 ECC keys. The public key size will @@ -186,9 +157,6 @@ static int atmel_ecc_init_ecdh_cmd(struct atmel_ecc_cmd *cmd, copied = sg_copy_to_buffer(pubkey, 1, cmd->data, ATMEL_ECC_PUBKEY_SIZE); if (copied != ATMEL_ECC_PUBKEY_SIZE) return -EINVAL; - - atmel_ecc_checksum(cmd); - cmd->msecs = MAX_EXEC_TIME_ECDH; cmd->rxsize = ECDH_RSP_SIZE; @@ -302,7 +270,11 @@ static int atmel_ecc_send_receive(struct i2c_client *client, struct atmel_ecc_cmd *cmd) { struct atmel_ecc_i2c_client_priv *i2c_priv = i2c_get_clientdata(client); + u8 buf[MAX_CMD_SIZE]; + u16 cmdcrc; + u8 cmdlen; int ret; + int i; mutex_lock(&i2c_priv->lock); @@ -312,8 +284,31 @@ static int atmel_ecc_send_receive(struct i2c_client *client, goto err; } + /* Marshal the command */ + cmdlen = 6 + cmd->datasz + CRC_SIZE; + buf[0] = cmd->word_addr; + /* This excludes the word address, includes CRC */ + buf[1] = cmdlen - 1; + buf[2] = cmd->opcode; + buf[3] = cmd->param1; + /* Enforce little-endian byte order */ + buf[4] = cmd->param2 & 0xff; + buf[5] = (cmd->param2 >> 8); + /* Copy over the data array */ + for (i = 0; i < cmd->datasz; i++) + buf[6+i] = cmd->data[i]; + /* + * CRC sum the command, do not include word addr or CRC. The + * bit order in the CRC16 algorithm inside the chip is reversed, + * so we need to swizzle the bits with bitrev16(). + */ + cmdcrc = bitrev16(crc16(0x0000, buf+1, cmdlen - 1 - CRC_SIZE)); + /* Enforce little-endian byte order */ + buf[6+i] = (cmdcrc & 0xff); + buf[6+i+1] = (cmdcrc >> 8); + /* send the command */ - ret = i2c_master_send(client, (u8 *)cmd, cmd->count + WORD_ADDR_SIZE); + ret = i2c_master_send(client, buf, cmdlen); if (ret < 0) { dev_err(&client->dev, "command send failed\n"); goto err; diff --git a/drivers/crypto/atmel-ecc.h b/drivers/crypto/atmel-ecc.h index 6d586a3e443d..2a378bccc213 100644 --- a/drivers/crypto/atmel-ecc.h +++ b/drivers/crypto/atmel-ecc.h @@ -41,29 +41,30 @@ CMD_OVERHEAD_SIZE) #define READ_RSP_SIZE (4 + CMD_OVERHEAD_SIZE) #define MAX_RSP_SIZE GENKEY_RSP_SIZE +#define MAX_CMD_SIZE (9 + MAX_RSP_SIZE) /** * atmel_ecc_cmd - structure used for communicating with the device. * @word_addr: indicates the function of the packet sent to the device. This * byte should have a value of COMMAND for normal operation. - * @count : number of bytes to be transferred to (or from) the device. * @opcode : the command code. * @param1 : the first parameter; always present. * @param2 : the second parameter; always present. + * @datasz : size of the data field * @data : optional remaining input data. Includes a 2-byte CRC. * @rxsize : size of the data received from i2c client. * @msecs : command execution time in milliseconds */ struct atmel_ecc_cmd { u8 word_addr; - u8 count; u8 opcode; u8 param1; u16 param2; + u8 datasz; u8 data[MAX_RSP_SIZE]; u8 msecs; u16 rxsize; -} __packed; +}; /* Status/Error codes */ #define STATUS_SIZE 0x04 @@ -136,14 +137,14 @@ static const struct { #define OPCODE_READ 0x02 /* Definitions for the READ Command */ -#define READ_COUNT 7 +#define READ_DATASZ 0 /* Definitions for the GenKey Command */ -#define GENKEY_COUNT 7 +#define GENKEY_DATASZ 0 #define GENKEY_MODE_PRIVATE 0x04 /* Definitions for the ECDH Command */ -#define ECDH_COUNT 71 +#define ECDH_DATASZ 64 #define ECDH_PREFIX_MODE 0x00 #endif /* __ATMEL_ECC_H__ */