From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from phobos.denx.de (phobos.denx.de [85.214.62.61]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by smtp.lore.kernel.org (Postfix) with ESMTPS id E9C28C4451B for ; Mon, 20 Jul 2026 04:34:29 +0000 (UTC) Received: from h2850616.stratoserver.net (localhost [IPv6:::1]) by phobos.denx.de (Postfix) with ESMTP id 8D0CF84A0F; Mon, 20 Jul 2026 06:33:28 +0200 (CEST) Authentication-Results: phobos.denx.de; dmarc=pass (p=none dis=none) header.from=gmail.com Authentication-Results: phobos.denx.de; spf=pass smtp.mailfrom=u-boot-bounces@lists.denx.de Authentication-Results: phobos.denx.de; dkim=pass (2048-bit key; unprotected) header.d=gmail.com header.i=@gmail.com header.b="b2O/1k/T"; dkim-atps=neutral Received: by phobos.denx.de (Postfix, from userid 109) id 7569B80517; Mon, 20 Jul 2026 06:14:31 +0200 (CEST) Received: from mail-ot1-x330.google.com (mail-ot1-x330.google.com [IPv6:2607:f8b0:4864:20::330]) (using TLSv1.3 with cipher TLS_AES_128_GCM_SHA256 (128/128 bits)) (No client certificate requested) by phobos.denx.de (Postfix) with ESMTPS id 19EA880433 for ; Mon, 20 Jul 2026 06:14:29 +0200 (CEST) Authentication-Results: phobos.denx.de; dmarc=pass (p=none dis=none) header.from=gmail.com Authentication-Results: phobos.denx.de; spf=pass smtp.mailfrom=james.hilliard1@gmail.com Received: by mail-ot1-x330.google.com with SMTP id 46e09a7af769-7eb5a9f02e8so4572328a34.0 for ; Sun, 19 Jul 2026 21:14:29 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20251104; t=1784520868; x=1785125668; darn=lists.denx.de; h=cc:to:in-reply-to:references:message-id:content-transfer-encoding :content-type:mime-version:subject:date:from:from:to:cc:subject:date :message-id:reply-to:content-type; bh=90F51Koe7yFjcx9Q5OaPQdkwZWssxkYpZdxGtD2uZkA=; b=b2O/1k/T1sn1b61jjW90xHoRkpx5ibDu3DlauFWMGVJKan02Ab7elSnKhoHQJEW6jW NDnEoSR8f1mY5LeAesKfxAvh65fVm5GfXUa0CynhuANClnI9JBEINOQ9nwsuZHKhH+sj R1j4kJXCLrvEOnaKy/FqrvG0moeKRS9zm0al4xYBsdDqD8fH3vcX7xrt4N6ykY/5jRBb tYrWoSg+LtSiLgMjswCbcIDP8HkOzxbPlhdiannf7yUYaErgH6GsRJG0YxAtFNNZD7lp HoQH2OX8e7d9vKukFNyYj9uNwFywQ1/HS8JjSKIdu/2ZTRHv/d5ZKKaGLtETNruI7LXm bxMA== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20251104; t=1784520868; x=1785125668; h=cc:to:in-reply-to:references:message-id:content-transfer-encoding :content-type:mime-version:subject:date:from:x-gm-gg :x-gm-message-state:from:to:cc:subject:date:message-id:reply-to :content-type; bh=90F51Koe7yFjcx9Q5OaPQdkwZWssxkYpZdxGtD2uZkA=; b=J7dfMVb0xQiZh8LlSVpbnEN1EmukpjdSs7npn+MjIKdpTeDNn5Xk7hNlOjANG1dc71 5db4MFkyha5rE9dSduvxXzZ5bnUxXdiuKC7EK5RXZubSOrz4Wlme/NmTeZvoCrrTj2nB 0BaSHG6xIYR7rv5r+1IbOTFsYnLOKF94Jtfps/l5bWkVpJoMhhw8vjg4vJQWM3EpOi3k VkIuYqTL4U42N+Y1clyu49r+CQCb7XO2wv5IXdb/2XrGhJYAnseKIKydOzePKtk9LaX0 UTAZyzq702pDAoQjA56bBkOaeDzYFWaQ+t8oSzhq5nWOKXNO5Jp3uKEIMxo3I4sjkSd6 Qz+A== X-Forwarded-Encrypted: i=1; AHgh+RqVor0InnJ9ZmuwMqILUfB5ZFMim5YKdFNUlcSB1S7GbuMVwVtEviXr2IEFQLa4eUIE96hu1/Q=@lists.denx.de X-Gm-Message-State: AOJu0YxWjkYMlnfM7eDIYTImd9ZZGZWn9guZfXjJ8aoaBTxPfml7Phkm o/YUq2GEHQe2MMItEjguvTiPQo8S0SwcXM4EXl/rI1TxCBH1K4dtQura X-Gm-Gg: AfdE7cnEY3paE8He/RP89hsa+zCKSMEBBSmOhtXH4sfGbl/M9wXbanNPwcMIWAMSWcm Gc+dQHHtZxs/dSIVrcIO0UnaWuKgGwxLsbPFzgxC4vpHbtiEGnyMI2wh2Lt/Xhy58PqA5KIs/a3 ZCKtL+Rbr+2hyBUi3E8zcrydzcF1a3NX1U2U21hNA7/axptdjzblnbZbaBS5/F4FxnoAEz3BRF+ tLKLOOJlZtYNbBeGx8Ze27UvxJwnZkJJG9yvHtIY514W4quGIZumEv9qYJacLMauzemM+kyXn57 qXilEtqsTndLNefZgKdf7bE0j7OnrgDFHBI6xJ/rSfQqU8B5qvlyalIsXtDIZFhKonezqODyU4K zIwjaVepn2S/gppaoPfjDK0BjaGly4HNtyLLzmH9ENjnoTcdZN89XdF2tpzpkig9TaI66UdvCdQ 31KK8xQ3P0dcrGB61d0GGXUgTUwczTUpYnnu1hh9hJXDwaE0SY7jbtLOVJ0BPMuFTo27xjNWnca r0k1h2h5OnGEkJJWX/kkQD4b1fdUpYYANh79KCtQUrvCOKL3EQzfQ== X-Received: by 2002:a05:6830:4988:b0:7e9:c481:ff8a with SMTP id 46e09a7af769-7ed9aa38532mr7041434a34.11.1784520867554; Sun, 19 Jul 2026 21:14:27 -0700 (PDT) Received: from [127.0.1.1] (174-29-11-8.hlrn.qwest.net. [174.29.11.8]) by smtp.gmail.com with ESMTPSA id 46e09a7af769-7edaf94a737sm7159191a34.15.2026.07.19.21.14.23 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Sun, 19 Jul 2026 21:14:25 -0700 (PDT) From: James Hilliard Date: Sun, 19 Jul 2026 22:13:50 -0600 Subject: [PATCH v5 06/14] crypto: aes: fix software key-size handling MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: 7bit Message-Id: <20260719-submit-ce-series-v2-v5-6-3c41f66d4522@gmail.com> References: <20260719-submit-ce-series-v2-v5-0-3c41f66d4522@gmail.com> In-Reply-To: <20260719-submit-ce-series-v2-v5-0-3c41f66d4522@gmail.com> To: Svyatoslav Ryhel , Ion Agorria , u-boot@lists.denx.de, Aspeed BMC SW team , Joel Stanley Cc: Chen-Yu Tsai , Samuel Holland , Tom Rini , Simon Glass , James Hilliard , Thierry Reding , Quentin Schulz , Quentin Schulz , Marek Vasut , Marek Vasut , Rasmus Villemoes , Rasmus Villemoes , Aristo Chen , Anton Ivanov , Daniel Golle , Francois Berder , Peng Fan , Neil Armstrong , Randolph Sapp , Jonas Karlman , Wolfgang Wallner , Alexey Charkov , Ilias Apalodimas , Heiko Schocher , "Kory Maincent (TI.com)" , Anshul Dalal , Johan Jonker , Francesco Valla , Heinrich Schuchardt , Michael Walle , Andre Przywara , Lukasz Majewski , Richard Genoud , Michael Trimarchi , E Shattow , Enric Balletbo i Serra , Mattijs Korpershoek , Lucas Dietrich , David Lechner , Julien Stephan , Kuan-Wei Chiu , Bastien Curutchet , Raymond Mao , Ryan Chen , Chia-Wei Wang , "Lucien.Jheng" , Mateusz Furdyna , Dinesh Maniyam , Heiko Stuebner , Vincent Jardin X-Mailer: b4 0.15.2 X-Mailman-Approved-At: Mon, 20 Jul 2026 06:33:25 +0200 X-BeenThere: u-boot@lists.denx.de X-Mailman-Version: 2.1.39 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" X-Virus-Scanned: clamav-milter 0.103.8 at phobos.denx.de X-Virus-Status: Clean The AES uclass API expresses key sizes in bits, while the common software AES primitives take key lengths in bytes. The software provider passes the uclass value through unchanged, so AES-192 and AES-256 select the AES-128 round count and key schedule shape. Key expansion also copies the bit count as a byte count for every key size. Validate the uclass key size, convert it to bytes once and retain that byte length for the software operations. Correct the primitive API documentation and add NIST ECB and CBC vectors for AES-128, AES-192 and AES-256. Signed-off-by: James Hilliard --- Changes v3 -> v4: - New patch --- drivers/crypto/aes/aes-sw.c | 43 +++++++++++++----- include/uboot_aes.h | 20 ++++----- test/dm/aes.c | 107 ++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 148 insertions(+), 22 deletions(-) diff --git a/drivers/crypto/aes/aes-sw.c b/drivers/crypto/aes/aes-sw.c index a65200fb79b..6bad343ea7d 100644 --- a/drivers/crypto/aes/aes-sw.c +++ b/drivers/crypto/aes/aes-sw.c @@ -12,13 +12,23 @@ struct sw_aes_priv { u8 key_slots[SW_KEY_SLOTS][AES256_KEY_LENGTH]; u8 key_schedule[AES256_EXPAND_KEY_LENGTH]; u8 selected_slot; - u32 selected_key_size; + u8 selected_key_len; bool key_expanded; }; +static int sw_aes_key_len(u32 key_size) +{ + if (key_size == AES128_KEY_LENGTH * 8 || + key_size == AES192_KEY_LENGTH * 8 || + key_size == AES256_KEY_LENGTH * 8) + return key_size / 8; + + return -EINVAL; +} + static int prepare_aes(struct sw_aes_priv *priv) { - if (!priv->selected_key_size) { + if (!priv->selected_key_len) { log_debug("%s: AES key size not set, setup a slot first\n", __func__); return 1; } @@ -28,7 +38,8 @@ static int prepare_aes(struct sw_aes_priv *priv) priv->key_expanded = 1; - aes_expand_key(priv->key_slots[priv->selected_slot], priv->selected_key_size, + aes_expand_key(priv->key_slots[priv->selected_slot], + priv->selected_key_len, priv->key_schedule); return 0; @@ -42,12 +53,16 @@ static int sw_aes_ops_available_key_slots(struct udevice *dev) static int sw_aes_ops_select_key_slot(struct udevice *dev, u32 key_size, u8 slot) { struct sw_aes_priv *priv = dev_get_priv(dev); + int key_len; if (slot >= SW_KEY_SLOTS) - return 1; + return -EINVAL; + key_len = sw_aes_key_len(key_size); + if (key_len < 0) + return key_len; priv->selected_slot = slot; - priv->selected_key_size = key_size; + priv->selected_key_len = key_len; priv->key_expanded = 0; return 0; @@ -57,14 +72,18 @@ static int sw_aes_ops_set_key_for_key_slot(struct udevice *dev, u32 key_size, u8 *key, u8 slot) { struct sw_aes_priv *priv = dev_get_priv(dev); + int key_len; if (slot >= SW_KEY_SLOTS) - return 1; + return -EINVAL; + key_len = sw_aes_key_len(key_size); + if (key_len < 0) + return key_len; - memcpy(priv->key_slots[slot], key, key_size / 8); + memcpy(priv->key_slots[slot], key, key_len); if (priv->selected_slot == slot) - priv->selected_key_size = key_size; + priv->selected_key_len = key_len; priv->key_expanded = 0; @@ -82,7 +101,7 @@ static int sw_aes_ops_aes_ecb_encrypt(struct udevice *dev, u8 *src, u8 *dst, return ret; while (num_aes_blocks > 0) { - aes_encrypt(priv->selected_key_size, src, priv->key_schedule, dst); + aes_encrypt(priv->selected_key_len, src, priv->key_schedule, dst); num_aes_blocks -= 1; src += AES_BLOCK_LENGTH; dst += AES_BLOCK_LENGTH; @@ -102,7 +121,7 @@ static int sw_aes_ops_aes_ecb_decrypt(struct udevice *dev, u8 *src, u8 *dst, return ret; while (num_aes_blocks > 0) { - aes_decrypt(priv->selected_key_size, src, priv->key_schedule, dst); + aes_decrypt(priv->selected_key_len, src, priv->key_schedule, dst); num_aes_blocks -= 1; src += AES_BLOCK_LENGTH; dst += AES_BLOCK_LENGTH; @@ -121,7 +140,7 @@ static int sw_aes_ops_aes_cbc_encrypt(struct udevice *dev, u8 *iv, u8 *src, if (ret) return ret; - aes_cbc_encrypt_blocks(priv->selected_key_size, priv->key_schedule, iv, + aes_cbc_encrypt_blocks(priv->selected_key_len, priv->key_schedule, iv, src, dst, num_aes_blocks); return 0; @@ -137,7 +156,7 @@ static int sw_aes_ops_aes_cbc_decrypt(struct udevice *dev, u8 *iv, u8 *src, if (ret) return ret; - aes_cbc_decrypt_blocks(priv->selected_key_size, priv->key_schedule, + aes_cbc_decrypt_blocks(priv->selected_key_len, priv->key_schedule, iv, src, dst, num_aes_blocks); return 0; diff --git a/include/uboot_aes.h b/include/uboot_aes.h index 592b7dbee43..65a9b382843 100644 --- a/include/uboot_aes.h +++ b/include/uboot_aes.h @@ -47,30 +47,30 @@ enum { * operations. * * @key Key - * @key_size Size of the key (in bits) + * @key_len Size of the key in bytes * @expkey Buffer to place expanded key, AES_EXPAND_KEY_LENGTH */ -void aes_expand_key(u8 *key, u32 key_size, u8 *expkey); +void aes_expand_key(u8 *key, u32 key_len, u8 *expkey); /** * aes_encrypt() - Encrypt single block of data with AES 128 * - * @key_size Size of the aes key (in bits) + * @key_len Size of the AES key in bytes * @in Input data * @expkey Expanded key to use for encryption (from aes_expand_key()) * @out Output data */ -void aes_encrypt(u32 key_size, u8 *in, u8 *expkey, u8 *out); +void aes_encrypt(u32 key_len, u8 *in, u8 *expkey, u8 *out); /** * aes_decrypt() - Decrypt single block of data with AES 128 * - * @key_size Size of the aes key (in bits) + * @key_len Size of the AES key in bytes * @in Input data * @expkey Expanded key to use for decryption (from aes_expand_key()) * @out Output data */ -void aes_decrypt(u32 key_size, u8 *in, u8 *expkey, u8 *out); +void aes_decrypt(u32 key_len, u8 *in, u8 *expkey, u8 *out); /** * Apply chain data to the destination using EOR @@ -86,27 +86,27 @@ void aes_apply_cbc_chain_data(u8 *cbc_chain_data, u8 *src, u8 *dst); /** * aes_cbc_encrypt_blocks() - Encrypt multiple blocks of data with AES CBC. * - * @key_size Size of the aes key (in bits) + * @key_len Size of the AES key in bytes * @key_exp Expanded key to use * @iv Initialization vector * @src Source data to encrypt * @dst Destination buffer * @num_aes_blocks Number of AES blocks to encrypt */ -void aes_cbc_encrypt_blocks(u32 key_size, u8 *key_exp, u8 *iv, u8 *src, u8 *dst, +void aes_cbc_encrypt_blocks(u32 key_len, u8 *key_exp, u8 *iv, u8 *src, u8 *dst, u32 num_aes_blocks); /** * Decrypt multiple blocks of data with AES CBC. * - * @key_size Size of the aes key (in bits) + * @key_len Size of the AES key in bytes * @key_exp Expanded key to use * @iv Initialization vector * @src Source data to decrypt * @dst Destination buffer * @num_aes_blocks Number of AES blocks to decrypt */ -void aes_cbc_decrypt_blocks(u32 key_size, u8 *key_exp, u8 *iv, u8 *src, u8 *dst, +void aes_cbc_decrypt_blocks(u32 key_len, u8 *key_exp, u8 *iv, u8 *src, u8 *dst, u32 num_aes_blocks); /* An AES block filled with zeros */ diff --git a/test/dm/aes.c b/test/dm/aes.c index 702e4db2b35..9c85fb1dac9 100644 --- a/test/dm/aes.c +++ b/test/dm/aes.c @@ -55,3 +55,110 @@ static int dm_test_aes(struct unit_test_state *uts) } DM_TEST(dm_test_aes, UTF_SCAN_FDT); + +struct aes_test_vector { + u32 key_size; + u8 key[AES256_KEY_LENGTH]; + u8 ecb[AES_BLOCK_LENGTH]; + u8 cbc[AES_BLOCK_LENGTH]; +}; + +static const u8 aes_test_plaintext[AES_BLOCK_LENGTH] = { + 0x6b, 0xc1, 0xbe, 0xe2, 0x2e, 0x40, 0x9f, 0x96, + 0xe9, 0x3d, 0x7e, 0x11, 0x73, 0x93, 0x17, 0x2a, +}; + +static const u8 aes_test_iv[AES_BLOCK_LENGTH] = { + 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, + 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, +}; + +static const struct aes_test_vector aes_test_vectors[] = { + { + .key_size = 128, + .key = { + 0x2b, 0x7e, 0x15, 0x16, 0x28, 0xae, 0xd2, 0xa6, + 0xab, 0xf7, 0x15, 0x88, 0x09, 0xcf, 0x4f, 0x3c, + }, + .ecb = { + 0x3a, 0xd7, 0x7b, 0xb4, 0x0d, 0x7a, 0x36, 0x60, + 0xa8, 0x9e, 0xca, 0xf3, 0x24, 0x66, 0xef, 0x97, + }, + .cbc = { + 0x76, 0x49, 0xab, 0xac, 0x81, 0x19, 0xb2, 0x46, + 0xce, 0xe9, 0x8e, 0x9b, 0x12, 0xe9, 0x19, 0x7d, + }, + }, { + .key_size = 192, + .key = { + 0x8e, 0x73, 0xb0, 0xf7, 0xda, 0x0e, 0x64, 0x52, + 0xc8, 0x10, 0xf3, 0x2b, 0x80, 0x90, 0x79, 0xe5, + 0x62, 0xf8, 0xea, 0xd2, 0x52, 0x2c, 0x6b, 0x7b, + }, + .ecb = { + 0xbd, 0x33, 0x4f, 0x1d, 0x6e, 0x45, 0xf2, 0x5f, + 0xf7, 0x12, 0xa2, 0x14, 0x57, 0x1f, 0xa5, 0xcc, + }, + .cbc = { + 0x4f, 0x02, 0x1d, 0xb2, 0x43, 0xbc, 0x63, 0x3d, + 0x71, 0x78, 0x18, 0x3a, 0x9f, 0xa0, 0x71, 0xe8, + }, + }, { + .key_size = 256, + .key = { + 0x60, 0x3d, 0xeb, 0x10, 0x15, 0xca, 0x71, 0xbe, + 0x2b, 0x73, 0xae, 0xf0, 0x85, 0x7d, 0x77, 0x81, + 0x1f, 0x35, 0x2c, 0x07, 0x3b, 0x61, 0x08, 0xd7, + 0x2d, 0x98, 0x10, 0xa3, 0x09, 0x14, 0xdf, 0xf4, + }, + .ecb = { + 0xf3, 0xee, 0xd1, 0xbd, 0xb5, 0xd2, 0xa0, 0x3c, + 0x06, 0x4b, 0x5a, 0x7e, 0x3d, 0xb1, 0x81, 0xf8, + }, + .cbc = { + 0xf5, 0x8c, 0x4c, 0x04, 0xd6, 0xe5, 0xf1, 0xba, + 0x77, 0x9e, 0xab, 0xfb, 0x5f, 0x7b, 0xfb, 0xd6, + }, + }, +}; + +static int dm_test_aes_key_sizes(struct unit_test_state *uts) +{ + struct udevice *dev; + u8 key[AES256_KEY_LENGTH]; + u8 input[AES_BLOCK_LENGTH]; + u8 iv[AES_BLOCK_LENGTH]; + u8 buf[AES_BLOCK_LENGTH]; + int i, ret; + + ut_assertok(uclass_first_device_err(UCLASS_AES, &dev)); + + for (i = 0; i < ARRAY_SIZE(aes_test_vectors); i++) { + const struct aes_test_vector *vector = &aes_test_vectors[i]; + + memcpy(key, vector->key, vector->key_size / 8); + memcpy(input, aes_test_plaintext, sizeof(input)); + memcpy(iv, aes_test_iv, sizeof(iv)); + ut_assertok(dm_aes_select_key_slot(dev, vector->key_size, 0)); + ret = dm_aes_set_key_for_key_slot(dev, vector->key_size, key, 0); + ut_assertok(ret); + + ut_assertok(dm_aes_ecb_encrypt(dev, input, buf, 1)); + ut_asserteq_mem(vector->ecb, buf, sizeof(buf)); + ut_assertok(dm_aes_ecb_decrypt(dev, buf, buf, 1)); + ut_asserteq_mem(aes_test_plaintext, buf, sizeof(buf)); + + ut_assertok(dm_aes_cbc_encrypt(dev, iv, input, buf, 1)); + ut_asserteq_mem(vector->cbc, buf, sizeof(buf)); + ut_assertok(dm_aes_cbc_decrypt(dev, iv, buf, buf, 1)); + ut_asserteq_mem(aes_test_plaintext, buf, sizeof(buf)); + } + + ut_asserteq(-EINVAL, dm_aes_select_key_slot(dev, 64, 0)); + ret = dm_aes_set_key_for_key_slot(dev, 64, key, 0); + ut_asserteq(-EINVAL, ret); + + return 0; +} + +DM_TEST(dm_test_aes_key_sizes, UTF_SCAN_FDT); -- 2.53.0