From patchwork Thu Jun 28 13:07:26 2018 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Linus Walleij X-Patchwork-Id: 140444 Delivered-To: patch@linaro.org Received: by 2002:a2e:9754:0:0:0:0:0 with SMTP id f20-v6csp2166511ljj; Thu, 28 Jun 2018 06:08:23 -0700 (PDT) X-Google-Smtp-Source: AAOMgpcnRNnZjyQRTl4T2Blkhe5i6bXX01NIPB+blvP+MGG0mqYGi1g8Mx6MREfl6sfvnBV7ySrU X-Received: by 2002:a65:498c:: with SMTP id r12-v6mr157504pgs.112.1530191302878; Thu, 28 Jun 2018 06:08:22 -0700 (PDT) ARC-Seal: i=1; a=rsa-sha256; t=1530191302; cv=none; d=google.com; s=arc-20160816; b=F3Jlk9jKn7NXAcH4y23MVesUH74Oy059Urt/DI2enxVcpGHA2F3KJPTC6Kli7XrU9o YsUDNodoeP6YaLwkeGFGap8q/yXh4vKfm2LbyJXrCAmGC4C07eu3ph8sP3NWMgyL2sia CQ3f5UqwME+TAZad4q9o+UyrQnKFIeIiNRvMrc4/7OvoRE+D6+9To313Xv0Nr/yUoYVt W+GLQZAm2B/NMPCRs3C074REfb+qIq04erVukVIL0+eGjqvumqA5fkgjFxAsszikRhgc C0WnuIkfIRMqlW+mpr4zoVfqn+Nr5z6qOPaJs5dbVlscId0GVkJ+D+VSAR+Xb7ajtlsy UWzg== 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=znQp7iv1eckxnsCUtLYnt+wbxxbUmE18px2GlzrAhgM=; b=QWxeg01NAqcjZl8A4urmx8qz8XwXzY9I1gthD2JjhKkdygfp1W9YRCsqeKgFDjudbv XzMRoL2xBqwXv06Eed9/LILzSyX08W4PdpimJhqZNplcb5baNHGs3afgV/bAs1sU4iBW IhDIhQrAjIeb/8KacyUAVZuME0GQvXsWvO0OhgibcGSrUOFNxg1njphjJKp9LFJuIoXN zM6qlBwqLMWSFwCL/mwDltPg6xrfUbgTZ/VwDhNSUFI7jUvjPCGYdINtR6n/PU8qkyiA wznXXHEMVs0eRYBtpW98G8dhoPikEKwVPyhTd0pKaPaP0UjcvfKAMswwJbzn1bkKbScb kJIA== ARC-Authentication-Results: i=1; mx.google.com; dkim=pass header.i=@linaro.org header.s=google header.b=fkPtPNWt; 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 p88-v6si6621399pfj.294.2018.06.28.06.08.22; Thu, 28 Jun 2018 06:08:22 -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=fkPtPNWt; 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 S965269AbeF1NHy (ORCPT + 1 other); Thu, 28 Jun 2018 09:07:54 -0400 Received: from mail-lj1-f195.google.com ([209.85.208.195]:41978 "EHLO mail-lj1-f195.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S965644AbeF1NHr (ORCPT ); Thu, 28 Jun 2018 09:07:47 -0400 Received: by mail-lj1-f195.google.com with SMTP id a17-v6so1345809ljd.8 for ; Thu, 28 Jun 2018 06:07:46 -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=znQp7iv1eckxnsCUtLYnt+wbxxbUmE18px2GlzrAhgM=; b=fkPtPNWtcgAtbTJeGqIUMbBnimeyZ1pZIuJ9NpKnNHBa3md56OvfvliIAuoji90ViQ Ze0npT5qj8kk8py3ZiWoyI+WBrHLEZTzfi85UAK7MedpqVDlNUuu682IwgwBZ3ISx5sm dyfcEm5Nbe3cTwRSyqwcoyX+VBGBERaBchycs= 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=znQp7iv1eckxnsCUtLYnt+wbxxbUmE18px2GlzrAhgM=; b=nrjfeskGg58+BzrItaXIzHmhQX957I8o5ZH/+6h7PNm9A8qDcloOu0uKnlhySPSgF7 OH4bhPrQ5HqHQqvyRKoLm27x+B8F2X4F23WPtn967Hom+oK3W26bxEGHMwEkktKdwNtv 0m0j1AD0QeMlpeELpU5Mx5oeVSVlTlqmmnYaRPl9kUrdJi+BjE9J+rQwpBv+/C5Sntp/ Fs0UCcVgGP5XJMQ+l/dbtmrTne+dPVnXVdKXtW11UNXdA7HVnASJbheQcHAA1LWv+0rH 8QuAFyeKsoBCCdZ2gbMYF4ysnwWqBT8iCoILHhn0F8DaIgcL1q+qoCzeFPdrPCfVt++C 8H7w== X-Gm-Message-State: APt69E2lt1vTQu2ONbcrfym+rDMCsChvnoD19JIEwm2PNLxuC5GACYci JLJeZ0H6BUcGwd36FEHov11wPTCqTsU= X-Received: by 2002:a2e:18b:: with SMTP id f11-v6mr7056951lji.83.1530191265439; Thu, 28 Jun 2018 06:07:45 -0700 (PDT) Received: from genomnajs.ideon.se ([85.235.10.227]) by smtp.gmail.com with ESMTPSA id d24-v6sm1314649lfl.53.2018.06.28.06.07.44 (version=TLS1_2 cipher=ECDHE-RSA-CHACHA20-POLY1305 bits=256/256); Thu, 28 Jun 2018 06:07:44 -0700 (PDT) From: Linus Walleij To: linux-crypto@vger.kernel.org, Herbert Xu , Tudor Ambarus Cc: Linus Walleij Subject: [PATCH 6/9 v2] crypto: atmel-ecc: Marshal the command while sending Date: Thu, 28 Jun 2018 15:07:26 +0200 Message-Id: <20180628130729.17589-6-linus.walleij@linaro.org> X-Mailer: git-send-email 2.17.0 In-Reply-To: <20180628130729.17589-1-linus.walleij@linaro.org> References: <20180628130729.17589-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 --- ChangeLog v1->v2: - Rebase on other changes. --- drivers/crypto/atmel-ecc.c | 72 ++++++++++++++++++-------------------- drivers/crypto/atmel-ecc.h | 13 +++---- 2 files changed, 41 insertions(+), 44 deletions(-) -- 2.17.0 diff --git a/drivers/crypto/atmel-ecc.c b/drivers/crypto/atmel-ecc.c index 2ec570d06a27..f3322fae454e 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,7 +284,31 @@ static int atmel_ecc_send_receive(struct i2c_client *client, goto err; } - ret = i2c_master_send(client, (u8 *)cmd, cmd->count + WORD_ADDR_SIZE); + /* 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, 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 d941c4f3d28f..4458585ab588 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 @@ -120,14 +121,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__ */