-
Notifications
You must be signed in to change notification settings - Fork 2.6k
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
Refactor AES context to be shallow-copyable #5896
Refactor AES context to be shallow-copyable #5896
Conversation
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Looks mostly good, just a couple of minor points.
library/aes.c
Outdated
else | ||
#endif | ||
ctx->rk = RK = ctx->buf; | ||
ctx->rk_offset = 0; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This line is not indented correctly. The indentation should reflect the fact that ctx->rk_offset = 0;
is not executed if aes_padlock_ace
is nonzero (whereas the assignment to RK
is unconditional).
When we have an interaction between preprocessor nesting and instruction nesting, I prefer to arrange for the indentation to be correct if you hide the disabled preprocessor directives. For if/else, with our brace style, this can be done by putting the “either else or sole code path” line in braces:
#if defined(MBEDTLS_PADLOCK_C) && defined(MBEDTLS_PADLOCK_ALIGN16)
if( aes_padlock_ace == -1 )
aes_padlock_ace = mbedtls_padlock_has_support( MBEDTLS_PADLOCK_ACE );
if( aes_padlock_ace )
ctx->rk_offset = MBEDTLS_PADLOCK_ALIGN16( ctx->buf ) - ctx->buf;
else
#endif
{
ctx->rk_offset = 0;
}
RK = ctx->buf + ctx->rk_offset;
But in fact I would find this code more readable as
ctx->rk_offset = 0;
#if defined(MBEDTLS_PADLOCK_C) && defined(MBEDTLS_PADLOCK_ALIGN16)
if( aes_padlock_ace == -1 )
aes_padlock_ace = mbedtls_padlock_has_support( MBEDTLS_PADLOCK_ACE );
if( aes_padlock_ace )
ctx->rk_offset = MBEDTLS_PADLOCK_ALIGN16( ctx->buf ) - ctx->buf;
#endif
RK = ctx->buf + ctx->rk_offset;
Same thing in setkey_dec
.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks for the information on indentation in this case, I've updated to use the latter formatting.
include/mbedtls/aes.h
Outdated
@@ -80,7 +80,7 @@ extern "C" { | |||
typedef struct mbedtls_aes_context | |||
{ | |||
int MBEDTLS_PRIVATE(nr); /*!< The number of rounds. */ | |||
uint32_t *MBEDTLS_PRIVATE(rk); /*!< AES round keys. */ | |||
size_t MBEDTLS_PRIVATE(rk_offset); /*!< Buffer offset for AES round keys. */ |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Please document the unit. Both bytes and array elements (which is uint32_t
) are plausible. Turns out the offset is a number of array elements.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'm not sure if I follow the logic here - isn't this just a 16-byte alignment offset kept along an unaligned buffer, so bytes?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
No, rk_offset
is the difference between two uint32_t *
s. I agree the name MBEDTLS_PADLOCK_ALIGN16
doesn't make it clear, but it includes a cast to uint32_t *
.
See
library/padlock.h:#define MBEDTLS_PADLOCK_ALIGN16(x) (uint32_t *) (16 + ((int32_t) (x) & ~15))
library/aes.c:ctx->rk_offset = MBEDTLS_PADLOCK_ALIGN16( ctx->buf ) - ctx->buf;
and
library/aes.c:RK = ctx->buf + ctx->rk_offset;
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
OK, but even though this is a difference between two uint32_t's, this contains an address offset aligned to 16 bytes, and the result of MBEDTLS_PADLOCK_ALIGN16( buf ) - buf
can be at most 16.
For uint32_t
elements, this means that it's at most an offset of half of an element, not the number of elements. ctx->rk_offset
is not used when accesing a specific index of RK, where I would interpret it as an offset of given array elements.
Again - what am I missing here?
Edit: Sorry, mixed up the sizes here. It can be up to 16 bytes, while the elements have 4 bytes, so if it was to be used as a number of array elements, it should rather be divided by 4.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Err, yes, (char *)MBEDTLS_PADLOCK_ALIGN16( buf ) - (char *)buf
will be 0, 4, 8 or 12 bytes, but MBEDTLS_PADLOCK_ALIGN16( buf ) - buf
will be 0, 1, 2 or 3.
this is a difference between two uint32_t's
It's actually the difference between two uint32_t *
s.
If buf
(i.e. &buf[0]
) is at (vaddr_t)1000
(decimal), &buf[1]
is at 1004
, &buf[2]
is at 1008
and &buf[3]
is at 1012
, MBEDTLS_PADLOCK_ALIGN16(buf)
will give us (uint32_t *)1008
, which will give us 2
- the third one in the list) when we subtract buf
from it
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
All clear, I failed at pointer-land arithmetics :) Sorry for taking so long to realize!
tests/suites/test_suite_aes.function
Outdated
// Encrypt with copied context and decrypt | ||
TEST_ASSERT( mbedtls_aes_crypt_ecb( &ctx2, MBEDTLS_AES_ENCRYPT, | ||
src_str->x, output2 ) == 0 ); | ||
TEST_ASSERT( mbedtls_aes_setkey_dec( &ctx2, key_str->x, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We're testing the sequence {setkey_enc; move; crypt}, and the sequence {init; move; setkey_enc}, but not the sequence {setkey_dec; move; crypt}. Since the problematic code is present in both setkey_enc and setkey_dec, we should test both, i.e. move the context after setkey_dec.
The sequence {init; move; setkey} is not particularly risky since setkey is unlikely to have a flaw where it would depend on previous content: that bug would be likely to hit on a freshly initialized context too. We can test it just in case, but I don't think it's required.
On code inspection, I believe that VIA padlock support (which was the reason for the offset due to its alignment constraint) is preserved. However we do not have the hardware to test it. I sent a message to the mailing list to let people know and ask for someone to test it if they can. |
d052322
to
c2b2da8
Compare
Please address review comments with subsequent commits (one commit for each unrelated change), not by rewriting old commits. |
c2b2da8
to
ae8a99f
Compare
The latest commits are missing a signoff line.
|
ae8a99f
to
56666c5
Compare
Replace RK pointer in AES context with a buffer offset, to allow shallow copying. Fixes Mbed-TLS#2147. Signed-off-by: Werner Lewis <werner.lewis@arm.com>
Signed-off-by: Werner Lewis <werner.lewis@arm.com>
Signed-off-by: Werner Lewis <werner.lewis@arm.com>
Signed-off-by: Werner Lewis <werner.lewis@arm.com>
56666c5
to
ec0193d
Compare
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
LGTM.
Re-iterating previous comment about adding new commits to address review comments, rather than re-writing and force pushing.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Looks good apart from the one minor comment that I'm not sure about.
Since we normally backport bug fixes, should we backport this one? |
Answer: no backport, as it would break the ABI on LTS, which we try hard not to break (except for security fixes) |
Hmm, a thought about this PR: the whole point is to make the structure shallow-copyable, so instead of having an embedded pointer into |
Looking at the use case and steps to reproduce - |
Yes, this could lead to a change in alignment, which would cause failures with |
Actually, all you need to do is check that This means that a non-shallow-copied (OG) ctx will still use Padlock acceleration, and a (lucky) aligned shallow-copied ctx will use Padlock, but an unlucky not-aligned shallow-copied ctx will at least work. That seems reasonable - you can copy the context, but it might be slow on the (rare, these days) VIA Padlock system. |
Signed-off-by: Werner Lewis <werner.lewis@arm.com>
c1999d5
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
LGTM - thanks for fixing so quickly
CI failures are all ABI, as expected |
Description
Replaces use of a round key pointer in
mbedtls_aes_context
with a buffer offset, so that the structure is shallow-copyable. This retains support for alignment requirements with PadLock, removal ofrk
results in an ABI change. A test is added to confirm a shallow-copy of the structure is valid. Fixes #2147.Status
READY
Requires Backporting
NO
Todos
Steps to test or reproduce
Initialise an
mbedtls_aes_context
structure, set encryption keys and then encrypt plaintext. Shallow-copy and then zero the original context, and then repeat encryption of the same plaintext using the copied context. The two ciphertexts should match, but will not prior to this change.A similar test has been added in this PR.