Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Introduce config option of 128-bit key only in AES calculation #7451

Merged
merged 31 commits into from
Jun 15, 2023
Merged
Show file tree
Hide file tree
Changes from 21 commits
Commits
Show all changes
31 commits
Select commit Hold shift + click to select a range
732ca32
AES: add macro of MBEDTLS_AES_ONLY_128_BIT_KEY_LENGTH
Apr 14, 2023
0f06618
AES: skip 192bit and 256bit key in selftest if 128bit_only enabled
Apr 20, 2023
b1c626b
AES: adjust AES RAM usage according to config options
Apr 14, 2023
a870467
Add checks if MBEDTLS_AES_ONLY_128_BIT_KEY_LENGTH enabled
Apr 20, 2023
3eb50e7
all.sh: add test for AES_ONLY_128_BIT_KEY_LENGTH
Apr 14, 2023
ecb6a02
Add AES 128-bit key dependency for tests data
Apr 19, 2023
d98ae2f
Add AES 128-bit key dependency in test_suite_psa_crypto.data
Apr 21, 2023
a9808ce
Add AES 128-bit key dependency in test_suite_ssl.data
Apr 21, 2023
3f41744
generate_psa_tests.py: add extra dependencies based on key bit
Apr 21, 2023
3d4d146
mbedtls_config.h: fix issue in grammar
May 5, 2023
4a7fdff
mbedtls_config.h: paraphrase code size saving in comment
May 5, 2023
8b9877b
aes.h: add comment for round key buffer in aes context
May 5, 2023
1ed226f
Auto-enable CTR_DRBG_USE_128_BIT_KEY with AES_ONLY_128_BIT_KEY_LENGTH
May 5, 2023
374c3ae
all.sh: add test for AES-128bit only without MBEDTLS_CTR_DRBG_C
May 5, 2023
d9bf370
add ChangeLog entry
May 5, 2023
e2bc158
aesce.c: add macro of MBEDTLS_AES_ONLY_128_BIT_KEY_LENGTH
May 8, 2023
5dd429c
generate_psa_tests.py: fix typo
May 10, 2023
ab4fb0d
aes.h: rewrite comment for aes round key buf
May 10, 2023
a30c72f
rewrite ChangeLog
May 10, 2023
d2ae432
mbedtls_config.h: rewrite comment for AES_ONLY_128_BIT_KEY_LENGTH
May 10, 2023
7265bab
mbedtls_config.h: remove empty * line before closing */ line
May 10, 2023
463351d
ChangeLog: remove issue number as this is a new feature
May 10, 2023
62c9991
aes selftest: remove non-128-bit data if aes_128bit_only enabled
May 11, 2023
59c2dfa
aes selftest: determine selftest loop limit in runtime
May 11, 2023
dd56add
cmac selftest: add macro for non-128-bit data/test
May 11, 2023
d329c69
gcm selftest: remove non-128-bit data if aes_128bit_only enabled
May 11, 2023
93533b5
gcm.c: do not set length for some arrays in selftest
May 11, 2023
d896fcb
nist_kw.c: remove non-128-bit data if aes_128bit_only enabled
May 11, 2023
012b6bb
all.sh: test AES built-in implementation in AES-128-bit key only
May 11, 2023
4292441
all.sh: use clang for one test of AES_ONLY_128_BIT_KEY_LENGTH
Jun 14, 2023
55ef22c
mbedtls_config.h: add description for CTR_DRBG about AES-128 only
Jun 15, 2023
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions ChangeLog.d/add-aes-128bit-only.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
Features
* Add support to restrict AES to 128-bit keys in order to save code size.
A new configuration option, MBEDTLS_AES_ONLY_128_BIT_KEY_LENGTH, can be
used to enable this feature.
Fixes #7376.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

(minor) I don't think we need this last line. (1) it's not really a fix, and (2) it looks from other ChangeLog entries that we don't include the issue number for things that we raise

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We normally include the issue number for a bug fix, whether discovered internally or externally. This is an indication to users who have existing code and who know that this particular bug affects them. We don't include the issue number for a new feature.

5 changes: 5 additions & 0 deletions include/mbedtls/aes.h
Original file line number Diff line number Diff line change
Expand Up @@ -76,6 +76,10 @@ typedef struct mbedtls_aes_context {
int MBEDTLS_PRIVATE(nr); /*!< The number of rounds. */
size_t MBEDTLS_PRIVATE(rk_offset); /*!< The offset in array elements to AES
round keys in the buffer. */
#if defined(MBEDTLS_AES_ONLY_128_BIT_KEY_LENGTH) && !defined(MBEDTLS_PADLOCK_C)
uint32_t MBEDTLS_PRIVATE(buf)[44]; /*!< Aligned data buffer to hold
10 round keys for 128-bit case. */
#else
uint32_t MBEDTLS_PRIVATE(buf)[68]; /*!< Unaligned data buffer. This buffer can
hold 32 extra Bytes, which can be used for
one of the following purposes:
Expand All @@ -84,6 +88,7 @@ typedef struct mbedtls_aes_context {
<li>Simplifying key expansion in the 256-bit
case by generating an extra round key.
</li></ul> */
#endif /* MBEDTLS_AES_ONLY_128_BIT_KEY_LENGTH && !MBEDTLS_PADLOCK_C */
}
mbedtls_aes_context;

Expand Down
8 changes: 8 additions & 0 deletions include/mbedtls/build_info.h
Original file line number Diff line number Diff line change
Expand Up @@ -80,6 +80,14 @@
#include MBEDTLS_USER_CONFIG_FILE
#endif

/* Auto-enable MBEDTLS_CTR_DRBG_USE_128_BIT_KEY if
* MBEDTLS_AES_ONLY_128_BIT_KEY_LENGTH and MBEDTLS_CTR_DRBG_C defined
* to ensure a 128-bit key size in CTR_DRBG.
*/
#if defined(MBEDTLS_AES_ONLY_128_BIT_KEY_LENGTH) && defined(MBEDTLS_CTR_DRBG_C)
#define MBEDTLS_CTR_DRBG_USE_128_BIT_KEY
#endif

/* Auto-enable MBEDTLS_MD_C if needed by a module that didn't require it
* in a previous release, to ensure backwards compatibility.
*/
Expand Down
19 changes: 17 additions & 2 deletions include/mbedtls/mbedtls_config.h
Original file line number Diff line number Diff line change
Expand Up @@ -496,7 +496,6 @@
* performance if ROM access is slower than RAM access.
*
* This option is independent of \c MBEDTLS_AES_FEWER_TABLES.
*
*/
//#define MBEDTLS_AES_ROM_TABLES

Expand All @@ -518,10 +517,26 @@
* depends on the system and memory details.
*
* This option is independent of \c MBEDTLS_AES_ROM_TABLES.
*
*/
//#define MBEDTLS_AES_FEWER_TABLES

/**
* \def MBEDTLS_AES_ONLY_128_BIT_KEY_LENGTH
*
* Use only 128-bit keys in AES operations to save ROM.
*
* Uncomment this macro to remove support for AES operations that use 192-
* or 256-bit keys.
*
* Uncommenting this macro reduces the size of AES code by ~300 bytes
* on v8-M/Thumb2.
tom-cosgrove-arm marked this conversation as resolved.
Show resolved Hide resolved
*
* Module: library/aes.c
*
* Requires: MBEDTLS_AES_C
*/
//#define MBEDTLS_AES_ONLY_128_BIT_KEY_LENGTH

/**
* \def MBEDTLS_CAMELLIA_SMALL_MEMORY
*
Expand Down
32 changes: 32 additions & 0 deletions library/aes.c
Original file line number Diff line number Diff line change
Expand Up @@ -563,8 +563,10 @@ int mbedtls_aes_setkey_enc(mbedtls_aes_context *ctx, const unsigned char *key,

switch (keybits) {
case 128: ctx->nr = 10; break;
#if !defined(MBEDTLS_AES_ONLY_128_BIT_KEY_LENGTH)
case 192: ctx->nr = 12; break;
case 256: ctx->nr = 14; break;
#endif /* !MBEDTLS_AES_ONLY_128_BIT_KEY_LENGTH */
default: return MBEDTLS_ERR_AES_INVALID_KEY_LENGTH;
}

Expand Down Expand Up @@ -610,6 +612,7 @@ int mbedtls_aes_setkey_enc(mbedtls_aes_context *ctx, const unsigned char *key,
}
break;

#if !defined(MBEDTLS_AES_ONLY_128_BIT_KEY_LENGTH)
case 12:

for (i = 0; i < 8; i++, RK += 6) {
Expand Down Expand Up @@ -651,6 +654,7 @@ int mbedtls_aes_setkey_enc(mbedtls_aes_context *ctx, const unsigned char *key,
RK[15] = RK[7] ^ RK[14];
}
break;
#endif /* !MBEDTLS_AES_ONLY_128_BIT_KEY_LENGTH */
}

return 0;
Expand Down Expand Up @@ -1811,6 +1815,13 @@ int mbedtls_aes_self_test(int verbose)
(mode == MBEDTLS_AES_DECRYPT) ? "dec" : "enc");
}

#if defined(MBEDTLS_AES_ONLY_128_BIT_KEY_LENGTH)
if (keybits > 128) {
mbedtls_printf("skipped\n");
continue;
}
#endif /* MBEDTLS_AES_ONLY_128_BIT_KEY_LENGTH */

tom-cosgrove-arm marked this conversation as resolved.
Show resolved Hide resolved
memset(buf, 0, 16);

if (mode == MBEDTLS_AES_DECRYPT) {
Expand Down Expand Up @@ -1868,6 +1879,13 @@ int mbedtls_aes_self_test(int verbose)
(mode == MBEDTLS_AES_DECRYPT) ? "dec" : "enc");
}

#if defined(MBEDTLS_AES_ONLY_128_BIT_KEY_LENGTH)
if (keybits > 128) {
mbedtls_printf("skipped\n");
continue;
}
#endif /* MBEDTLS_AES_ONLY_128_BIT_KEY_LENGTH */

memset(iv, 0, 16);
memset(prv, 0, 16);
memset(buf, 0, 16);
Expand Down Expand Up @@ -1937,6 +1955,13 @@ int mbedtls_aes_self_test(int verbose)
(mode == MBEDTLS_AES_DECRYPT) ? "dec" : "enc");
}

#if defined(MBEDTLS_AES_ONLY_128_BIT_KEY_LENGTH)
if (keybits > 128) {
mbedtls_printf("skipped\n");
continue;
}
#endif /* MBEDTLS_AES_ONLY_128_BIT_KEY_LENGTH */

memcpy(iv, aes_test_cfb128_iv, 16);
memcpy(key, aes_test_cfb128_key[u], keybits / 8);

Expand Down Expand Up @@ -1996,6 +2021,13 @@ int mbedtls_aes_self_test(int verbose)
(mode == MBEDTLS_AES_DECRYPT) ? "dec" : "enc");
}

#if defined(MBEDTLS_AES_ONLY_128_BIT_KEY_LENGTH)
if (keybits > 128) {
mbedtls_printf("skipped\n");
continue;
}
#endif /* MBEDTLS_AES_ONLY_128_BIT_KEY_LENGTH */

memcpy(iv, aes_test_ofb_iv, 16);
memcpy(key, aes_test_ofb_key[u], keybits / 8);

Expand Down
2 changes: 2 additions & 0 deletions library/aesce.c
Original file line number Diff line number Diff line change
Expand Up @@ -251,6 +251,7 @@ static void aesce_setkey_enc(unsigned char *rk,
/* Do not write overflow words.*/
continue;
}
#if !defined(MBEDTLS_AES_ONLY_128_BIT_KEY_LENGTH)
switch (key_bit_length) {
case 128:
break;
Expand All @@ -265,6 +266,7 @@ static void aesce_setkey_enc(unsigned char *rk,
rko[7] = rko[6] ^ rki[7];
break;
}
#endif /* !MBEDTLS_AES_ONLY_128_BIT_KEY_LENGTH */
}
}

Expand Down
10 changes: 10 additions & 0 deletions library/aesni.c
Original file line number Diff line number Diff line change
Expand Up @@ -273,6 +273,7 @@ static void aesni_setkey_enc_128(unsigned char *rk_bytes,
/*
* Key expansion, 192-bit case
*/
#if !defined(MBEDTLS_AES_ONLY_128_BIT_KEY_LENGTH)
static void aesni_set_rk_192(__m128i *state0, __m128i *state1, __m128i xword,
unsigned char *rk)
{
Expand Down Expand Up @@ -327,10 +328,12 @@ static void aesni_setkey_enc_192(unsigned char *rk,
aesni_set_rk_192(&state0, &state1, _mm_aeskeygenassist_si128(state1, 0x40), rk + 24 * 7);
aesni_set_rk_192(&state0, &state1, _mm_aeskeygenassist_si128(state1, 0x80), rk + 24 * 8);
}
#endif /* !MBEDTLS_AES_ONLY_128_BIT_KEY_LENGTH */

/*
* Key expansion, 256-bit case
*/
#if !defined(MBEDTLS_AES_ONLY_128_BIT_KEY_LENGTH)
static void aesni_set_rk_256(__m128i state0, __m128i state1, __m128i xword,
__m128i *rk0, __m128i *rk1)
{
Expand Down Expand Up @@ -387,6 +390,7 @@ static void aesni_setkey_enc_256(unsigned char *rk_bytes,
aesni_set_rk_256(rk[10], rk[11], _mm_aeskeygenassist_si128(rk[11], 0x20), &rk[12], &rk[13]);
aesni_set_rk_256(rk[12], rk[13], _mm_aeskeygenassist_si128(rk[13], 0x40), &rk[14], &rk[15]);
}
#endif /* !MBEDTLS_AES_ONLY_128_BIT_KEY_LENGTH */

#else /* MBEDTLS_AESNI_HAVE_CODE == 1 */

Expand Down Expand Up @@ -656,6 +660,7 @@ static void aesni_setkey_enc_128(unsigned char *rk,
/*
* Key expansion, 192-bit case
*/
#if !defined(MBEDTLS_AES_ONLY_128_BIT_KEY_LENGTH)
static void aesni_setkey_enc_192(unsigned char *rk,
const unsigned char *key)
{
Expand Down Expand Up @@ -709,10 +714,12 @@ static void aesni_setkey_enc_192(unsigned char *rk,
: "r" (rk), "r" (key)
: "memory", "cc", "0");
}
#endif /* !MBEDTLS_AES_ONLY_128_BIT_KEY_LENGTH */

/*
* Key expansion, 256-bit case
*/
#if !defined(MBEDTLS_AES_ONLY_128_BIT_KEY_LENGTH)
static void aesni_setkey_enc_256(unsigned char *rk,
const unsigned char *key)
{
Expand Down Expand Up @@ -775,6 +782,7 @@ static void aesni_setkey_enc_256(unsigned char *rk,
: "r" (rk), "r" (key)
: "memory", "cc", "0");
}
#endif /* !MBEDTLS_AES_ONLY_128_BIT_KEY_LENGTH */

#endif /* MBEDTLS_AESNI_HAVE_CODE */

Expand All @@ -787,8 +795,10 @@ int mbedtls_aesni_setkey_enc(unsigned char *rk,
{
switch (bits) {
case 128: aesni_setkey_enc_128(rk, key); break;
#if !defined(MBEDTLS_AES_ONLY_128_BIT_KEY_LENGTH)
case 192: aesni_setkey_enc_192(rk, key); break;
case 256: aesni_setkey_enc_256(rk, key); break;
#endif /* !MBEDTLS_AES_ONLY_128_BIT_KEY_LENGTH */
default: return MBEDTLS_ERR_AES_INVALID_KEY_LENGTH;
}

Expand Down
14 changes: 14 additions & 0 deletions library/cmac.c
Original file line number Diff line number Diff line change
Expand Up @@ -760,6 +760,13 @@ static int cmac_test_subkeys(int verbose,
mbedtls_printf(" %s CMAC subkey #%d: ", testname, i + 1);
}

#if defined(MBEDTLS_AES_ONLY_128_BIT_KEY_LENGTH)
if (keybits > 128) {
mbedtls_printf("skipped\n");
continue;
}
#endif /* MBEDTLS_AES_ONLY_128_BIT_KEY_LENGTH */

mbedtls_cipher_init(&ctx);

if ((ret = mbedtls_cipher_setup(&ctx, cipher_info)) != 0) {
Expand Down Expand Up @@ -855,6 +862,13 @@ static int cmac_test_wth_cipher(int verbose,
mbedtls_printf(" %s CMAC #%d: ", testname, i + 1);
}

#if defined(MBEDTLS_AES_ONLY_128_BIT_KEY_LENGTH)
if (keybits > 128) {
mbedtls_printf("skipped\n");
continue;
}
#endif /* MBEDTLS_AES_ONLY_128_BIT_KEY_LENGTH */

if ((ret = mbedtls_cipher_cmac(cipher_info, key, keybits, messages,
message_lengths[i], output)) != 0) {
/* When CMAC is implemented by an alternative implementation, or
Expand Down
11 changes: 9 additions & 2 deletions library/gcm.c
Original file line number Diff line number Diff line change
Expand Up @@ -888,13 +888,20 @@ int mbedtls_gcm_self_test(int verbose)
int key_len = 128 + 64 * j;

for (i = 0; i < MAX_TESTS; i++) {
mbedtls_gcm_init(&ctx);

if (verbose != 0) {
mbedtls_printf(" AES-GCM-%3d #%d (%s): ",
key_len, i, "enc");
}

#if defined(MBEDTLS_AES_ONLY_128_BIT_KEY_LENGTH)
if (key_len > 128) {
mbedtls_printf("skipped\n");
continue;
}
#endif /* MBEDTLS_AES_ONLY_128_BIT_KEY_LENGTH */

mbedtls_gcm_init(&ctx);

ret = mbedtls_gcm_setkey(&ctx, cipher,
key_test_data[key_index_test_data[i]],
key_len);
Expand Down
13 changes: 13 additions & 0 deletions library/nist_kw.c
Original file line number Diff line number Diff line change
Expand Up @@ -567,6 +567,13 @@ int mbedtls_nist_kw_self_test(int verbose)
mbedtls_printf(" KW-AES-%u ", (unsigned int) key_len[i] * 8);
}

#if defined(MBEDTLS_AES_ONLY_128_BIT_KEY_LENGTH)
if (key_len[i] > 16) {
mbedtls_printf("skipped\n");
continue;
}
#endif /* MBEDTLS_AES_ONLY_128_BIT_KEY_LENGTH */

ret = mbedtls_nist_kw_setkey(&ctx, MBEDTLS_CIPHER_ID_AES,
kw_key[i], key_len[i] * 8, 1);
if (ret != 0) {
Expand Down Expand Up @@ -622,6 +629,12 @@ int mbedtls_nist_kw_self_test(int verbose)
if (verbose != 0) {
mbedtls_printf(" KWP-AES-%u ", (unsigned int) key_len[i] * 8);
}
#if defined(MBEDTLS_AES_ONLY_128_BIT_KEY_LENGTH)
if (key_len[i] > 16) {
mbedtls_printf("skipped\n");
continue;
}
#endif /* MBEDTLS_AES_ONLY_128_BIT_KEY_LENGTH */

ret = mbedtls_nist_kw_setkey(&ctx, MBEDTLS_CIPHER_ID_AES, kwp_key[i],
key_len[i] * 8, 1);
Expand Down
1 change: 1 addition & 0 deletions scripts/config.py
Original file line number Diff line number Diff line change
Expand Up @@ -189,6 +189,7 @@ def realfull_adapter(_name, active, section):
# * Options that remove features.
EXCLUDE_FROM_FULL = frozenset([
#pylint: disable=line-too-long
'MBEDTLS_AES_ONLY_128_BIT_KEY_LENGTH', # interacts with CTR_DRBG_128_BIT_KEY
'MBEDTLS_CTR_DRBG_USE_128_BIT_KEY', # interacts with ENTROPY_FORCE_SHA256
'MBEDTLS_DEPRECATED_REMOVED', # conflicts with deprecated options
'MBEDTLS_DEPRECATED_WARNING', # conflicts with deprecated options
Expand Down
23 changes: 23 additions & 0 deletions tests/scripts/all.sh
Original file line number Diff line number Diff line change
Expand Up @@ -3448,6 +3448,29 @@ component_test_malloc_0_null () {
tests/ssl-opt.sh -e 'proxy'
}

component_test_aes_only_128_bit_keys () {
msg "build: default config with AES_ONLY_128_BIT_KEY_LENGTH enabled"
scripts/config.py set MBEDTLS_AES_ONLY_128_BIT_KEY_LENGTH
scripts/config.py unset MBEDTLS_PADLOCK_C

make CC=gcc CFLAGS='-Werror -Wall -Wextra'

msg "test: AES_ONLY_128_BIT_KEY_LENGTH"
make test
}

component_test_no_ctr_drbg_aes_only_128_bit_keys () {
msg "build: default config with AES_ONLY_128_BIT_KEY_LENGTH enabled and MBEDTLS_CTR_DRBG_C disabled"
scripts/config.py set MBEDTLS_AES_ONLY_128_BIT_KEY_LENGTH
scripts/config.py unset MBEDTLS_CTR_DRBG_C
scripts/config.py unset MBEDTLS_PADLOCK_C

make CC=gcc CFLAGS='-Werror -Wall -Wextra'

msg "test: AES_ONLY_128_BIT_KEY_LENGTH without MBEDTLS_CTR_DRBG_C"
make test
}

component_test_aes_fewer_tables () {
msg "build: default config with AES_FEWER_TABLES enabled"
scripts/config.py set MBEDTLS_AES_FEWER_TABLES
Expand Down
19 changes: 19 additions & 0 deletions tests/scripts/generate_psa_tests.py
Original file line number Diff line number Diff line change
Expand Up @@ -77,6 +77,24 @@ def automatic_dependencies(*expressions: str) -> List[str]:
used.difference_update(SYMBOLS_WITHOUT_DEPENDENCY)
return sorted(psa_want_symbol(name) for name in used)

# Define set of regular expressions and dependencies to optionally append
# extra dependencies for test case.
AES_128BIT_ONLY_DEP_REGEX = r'AES\s(192|256)'
AES_128BIT_ONLY_DEP = ["!MBEDTLS_AES_ONLY_128_BIT_KEY_LENGTH"]

DEPENDENCY_FROM_KEY = {
AES_128BIT_ONLY_DEP_REGEX: AES_128BIT_ONLY_DEP
}#type: Dict[str, List[str]]
def generate_key_dependencies(description: str) -> List[str]:
"""Return additional dependencies based on pairs of REGEX and dependencies.
"""
deps = []
for regex, dep in DEPENDENCY_FROM_KEY.items():
if re.search(regex, description):
deps += dep

return deps

# A temporary hack: at the time of writing, not all dependency symbols
# are implemented yet. Skip test cases for which the dependency symbols are
# not available. Once all dependency symbols are available, this hack must
Expand Down Expand Up @@ -574,6 +592,7 @@ def make_test_case(self, key: StorageTestData) -> test_case.TestCase:
key.alg.string, key.alg2.string,
)
dependencies = finish_family_dependencies(dependencies, key.bits)
dependencies += generate_key_dependencies(key.description)
tc.set_dependencies(dependencies)
tc.set_function('key_storage_' + verb)
if self.forward:
Expand Down
Loading