-
Notifications
You must be signed in to change notification settings - Fork 3k
NUC472/M487: Refine code with mbed TLS crypto alternatives #4925
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
Conversation
|
||
|
||
static void __nvt_aes_crypt( mbedtls_aes_context *ctx, | ||
const unsigned char input[16], | ||
unsigned char output[16], int dataSize) | ||
const unsigned char input[16], |
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 missed this in the previous Review.
This function also seems not thread safe. au8OutputData
and au8InputData
are defined out of this function, as static variables, which could be overwritten every cryptographic call
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.
Hi @ccli8 Thank you for this PR, the code is now a lot more readable. |
@yanesca Thoughts? |
@theotherjimmy I didn't loose track of this PR, I am just tied down with other tasks. I will review this and the underlying two other PRs as soon as I can! |
@yanesca The pings are just to make sure you don't lose track of it. Feel free to get to it when it's best for you. |
@theotherjimmy Ah ok, thank you! |
My current estimate is that I can start looking at this by the end of next week. |
@yanesca Bump for review |
@tommikas The jenkins CI did not report the status for this PR |
So it seems. I restarted the build. It should update once it's done. |
I am terribly sorry, but a lot has changed since my last comment and I haven't had the time to look at this yet. I don't have any estimate when that will be, but I am going to review this PR as soon as I can. |
ARM Internal Ref: IOTSSL-1718 |
I tried the simple stress test that I added in issue #5079 and I got the following error:
Could you please take a look at this failure? |
@andresag01 NUC472/M480 AES H/W just supports 4 channels, but #5079 requires 12. That's the cause. Is the fix necessary? If yes, we need to merge in AES S/W ( Bump @cyliangtw |
@andresag01 I would try your suggestion. |
@andresag01 To pass test code in #5079, I fix AES alter. bugs. Please check commits b9a3298 and a63c9e2. |
@ccli8: Many thanks for considering my comments. I will take a look at the changes as soon as I can. |
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.
@ccli8: Thank you for your contribution. I have given a first pass to the changes related to hardware acceleration and left several comments and questions.
{ | ||
if( i >=0 && i < (int)sizeof(channel_flag) ) | ||
channel_flag[i] = 0x00; | ||
unsigned int* piv; |
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 would prefer using uint32_t
#endif | ||
uint32_t iv[4]; | ||
unsigned char prv_iv[16]; | ||
uint32_t buf[8]; |
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.
Could you add a comment describing what this buffer is used for?
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.
@andresag01 I add comment in 2a8875b.
/* We support multiple contexts with context save & restore and so needs just one | ||
* H/W channel. Always use H/W channel #0. */ | ||
ctx->channel = 0; | ||
memset(ctx->iv, 0, sizeof (ctx->iv)); |
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 seems slightly redundant given that you have already set the whole ctx
to 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.
@andresag01 This code is refined in 2d7a33e.
* H/W channel. Always use H/W channel #0. */ | ||
ctx->channel = 0; | ||
memset(ctx->iv, 0, sizeof (ctx->iv)); | ||
|
||
/* Unlock protected registers */ | ||
SYS_UnlockReg(); | ||
CLK_EnableModuleClock(CRPT_MODULE); |
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.
Is it possible for a user to actually switch the crypto module off?
int i =-1; | ||
|
||
|
||
mbedtls_trace("=== %s \r\n", __FUNCTION__); | ||
memset( ctx, 0, sizeof( mbedtls_aes_context ) ); |
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.
What happens if the input pointer is NULL?
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.
@andresag01 This follows mbed-os/features/mbedtls/src/aes.c
by assuming upper layer won't pass NULL context pointer.
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
#include "config.h" | ||
#else | ||
#include MBEDTLS_CONFIG_FILE | ||
#endif |
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.
Same comment as above regarding config.h
|
||
#if defined(MBEDTLS_SHA512_C) | ||
#if defined(MBEDTLS_SHA512_ALT) | ||
|
||
#include "mbedtls/sha512.h" | ||
|
||
#if defined(_MSC_VER) || defined(__WATCOMC__) |
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 think this is just for windows, so not needed in mbed OS
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.
@andresag01 Same as above.
@@ -56,8 +50,10 @@ | |||
#endif /* MBEDTLS_SELF_TEST */ |
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 do not think there is a self test in this file
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.
@andresag01 Same as above.
#else | ||
#include MBEDTLS_CONFIG_FILE | ||
#endif | ||
|
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.
Same comment as above regarding config.h
#else | ||
#include MBEDTLS_CONFIG_FILE | ||
#endif | ||
|
||
#if defined(MBEDTLS_SHA1_C) || defined(MBEDTLS_SHA256_C) || defined(MBEDTLS_SHA512_C) | ||
#if defined(MBEDTLS_SHA1_ALT) || defined(MBEDTLS_SHA256_ALT) || defined(MBEDTLS_SHA512_ALT) |
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 woudl suggest splitting this file into 1 file per module as with the software ones...
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.
@andresag01 SHA1/SHA256/SHA512 share the same SHA H/W, so these code are placed together.
@andresag01 I update AES first. I would update DES and SHA later. |
@andresag01 Besides AES just now, I add updates for DES and SHA. Please check them. |
channel_flag[i] = 0x00; | ||
uint32_t buff_ = (uint32_t) buff; | ||
|
||
return (((buff_ & 0x03) == 0) && ((buff_ & 0x20000000) == 0x20000000)); |
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 am not sure this check corresponds to the conditions that you have stated in the comment above. For example consider the value 0x30000000
that is word aligned and will also satisfy the check (buff_ & 0x20000000) == 0x20000000
even though is not in the 0x2xxxxxxx
range. Perhaps I misunderstood the constraints, but I believe something like this will satisfy:
ptr % 4 == 0 && (ptr & 0xF0000000) == 0x20000000
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.
@andresag01 Yes, you are right. I fixed it in 3119935.
int i =-1; | ||
|
||
|
||
mbedtls_trace("=== %s \r\n", __FUNCTION__); | ||
memset( ctx, 0, sizeof( mbedtls_aes_context ) ); |
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
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 have reviewed the changes once again and left more comments and questions.
As a general note, I still do not understand why are there two copies of the following files:
- aes_alt.c
- aes_alt.h
- des_alt.h
- des_alt.c
- etc
I compared some of these and except for aes_alt.c they seem to have exactly the same content. Also, the differences between the two aes_alt.c files is only these lines:
< #include "M480.h"
---
> #include "NUC472_442.h"
193,196c193,196
< ctx->iv[0] = CRPT->AES_FDBCK[0];
< ctx->iv[1] = CRPT->AES_FDBCK[1];
< ctx->iv[2] = CRPT->AES_FDBCK[2];
< ctx->iv[3] = CRPT->AES_FDBCK[3];
---
> ctx->iv[0] = CRPT->AES_FDBCK0;
> ctx->iv[1] = CRPT->AES_FDBCK1;
> ctx->iv[2] = CRPT->AES_FDBCK2;
> ctx->iv[3] = CRPT->AES_FDBCK3;
I do not think that differences justify the code duplication. Please take a look at the acceleration code for other targets to get an idea of what I mean.
memset( ctx, 0, sizeof( mbedtls_aes_context ) ); | ||
|
||
ctx->swapType = AES_IN_OUT_SWAP; |
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.
Question, what does AES_IN_OUT_SWAP
represent?
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.
AES_IN_OUT_SWAP
represents input/output data in little-endian. The code was refined in
ed39056.
ctx->channel = i; | ||
ctx->iv = au32MyAESIV; | ||
|
||
|
||
/* Unlock protected registers */ | ||
SYS_UnlockReg(); | ||
CLK_EnableModuleClock(CRPT_MODULE); |
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.
Question: Is it possible for a user to actually switch the crypto module off when not in use? Is it necessary at all to do that in order to save power, etc?
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.
In this commit 3aff492, crypto module clock is disabled when it is not in use.
ctx->buf[i] = (*(key+i*4) << 24) | | ||
(*(key+1+i*4) << 16) | | ||
(*(key+2+i*4) << 8) | | ||
(*(key+3+i*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.
@ccli8: Perhaps I am missing something, but I do not think that commit bd0960a modifies these lines of code.
* 2) Located in 0x2xxxxxxx region | ||
*/ | ||
MBED_ALIGN(4) uint8_t au8OutputData[MAX_DMA_CHAIN_SIZE]; | ||
MBED_ALIGN(4) uint8_t au8InputData[MAX_DMA_CHAIN_SIZE]; |
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.
Could you please take a look at this code again? I am not entirely sure it will work reliably given the constraints in the memory range for the DMA.
At the moment, these two buffers are being allocated in the stack. However, the thread stack is actually allocated in heap memory when a new thread is spawned. I looked at the linker script for one of the target NUC472 (XRAM_SUPPORTED) and found that:
RAM_EXTERN (rwx) : ORIGIN = 0x60000000, LENGTH = 0x00100000
...
.heap (NOLOAD):
{
__end__ = .;
end = __end__;
*(.heap*);
. += (ORIGIN(RAM_EXTERN) + LENGTH(RAM_EXTERN) - .);
__HeapLimit = .;
} > RAM_EXTERN
Given the origin for RAM_EXTERN, it looks like these buffers will not be in 0x20000000 and the check below would be triggered for this target. However, it would work on NUC (XRAM_UNSUPPORTED). Given the constraints, I think you probably need to allocate these buffers in .bss instead, but I am not as familiar with the nuvoton linker scripts. Please feel free to consider alternatives...
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.
@andresag01 Yes, it was a potential bug. In 20b696d, DMA buffer is now allocated at bss to guarantee it is located at 0x20000.000 region.
ctx->encDec = 0; | ||
__nvt_aes_crypt(ctx, input, output, blockChainLen); | ||
memcpy( iv, temp, 16 ); | ||
} |
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.
As far as I can see, this code is using three copies of the same value, just in different format:
iv
: the input parameter to the function in LEctx->iv
: same asiv
but BEtemp
: same asiv
Because of this, I thinktemp
is unnecessary, but please feel free to point out any flaws in my reasoning.
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.
@andresag01 Same as above.
} | ||
|
||
/* Last incomplete block */ | ||
size_t last_block_len = length; |
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.
Is last_block_len
really necessary?
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.
@andresag01 I refined it in 2fd1226.
uint32_t opMode; /* AES_MODE_ECB/CBC/CFB */ | ||
uint32_t swapType; /* Input/Output data endianness */ | ||
uint32_t iv[4]; /* IV for next block cipher */ | ||
uint32_t buf[8]; /* Cipher key */ |
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 think this buffer holds the BE representation of the AES keys. Perhaps we should just call the buffer key
instead of buf
...
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.
@andresag01 I renamed buf
to keys
in 2fd1226.
uint32_t keySize; /* Key size: AES_KEY_SIZE_128/192/256 */ | ||
uint32_t encDec; /* 0: decrypt, 1: encrypt */ | ||
uint32_t opMode; /* AES_MODE_ECB/CBC/CFB */ | ||
uint32_t swapType; /* Input/Output data endianness */ |
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.
swapType
seems to only ever hold one value, namely:
ctx->swapType = AES_IN_OUT_SWAP;
Is it necessary to keep this variable around?
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.
@andresag01 I removed it in ed39056.
while (rmn) { | ||
|
||
// Must be a multiple of 64-bit block size | ||
#define MAXSIZE_DMABUF (8 * 5) |
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.
Where does this limit come from?
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.
@andresag01 It was roughly estimated to make a trade-off between memory footprint and performance. I commented it in 2fd1226.
|
||
#if defined(MBEDTLS_SHA1_C) | ||
#if defined(MBEDTLS_SHA1_ALT) | ||
|
||
#include "mbedtls/sha1.h" | ||
|
||
#include <string.h> | ||
#if defined(MBEDTLS_SELF_TEST) |
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.
@ccli8: Could you please help me understand why is there a software fallback for SHA1 at all? I mean, it seems that there is an accelerator available. Is it because for some reason it is not possible to switch the accelerator context so that operations can be interleaved?
P.S. The same comment does for SHA256 and SHA512
@andresag01 At present, our port, like serial, i2c, spi, etc. separate code by chip family. NUC472 and M487 belong to different chip families, so there are two copies of them. In the future, we may consider merging them together when there are too many branches and it is difficult to maintain them. |
…tion completion in DES alter. This is to be consistent with PRNG/AES.
…MAC_CTL in SHA alter.
As destination/source contexts are the same, we return immediately.
@0xc0170 I've done with rebase. Please check it. |
/morph build |
Build : SUCCESSBuild number : 809 Triggering tests/morph test |
Exporter Build : FAILUREBuild number : 458 |
Node went offline, restarting /morph export-build |
Exporter Build : SUCCESSBuild number : 459 |
Test : SUCCESSBuild number : 646 |
Description
This PR refines code with mbed TLS crypto alternatives on code review in previous PR. It includes the following modifications:
Related PRs
#4832
#4608
@0xc0170 @RonEld