-
Notifications
You must be signed in to change notification settings - Fork 51
Refactor benchmark example to reduce stack usage #116
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
a4d7dbf
to
76b3bc7
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.
I checked what I could at my knowledge level:
- missed options that have no implementation
- resources not being released
I found no issue of that sort.
I have one usability related suggestion.
benchmark/main.cpp
Outdated
else | ||
#if defined(MBEDTLS_RSA_C) && \ | ||
defined(MBEDTLS_PEM_PARSE_C) && defined(MBEDTLS_PK_PARSE_C) | ||
if( todo->rsa ) |
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 program may benefit from printing warnings if the user requests a given test via CLI but it is compiled out. Currently it skips it silently.
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.
@k-stachowiak Perhaps, but this PR is only to refactor the code into different test functions, to reduce stack size
Changes look fine to me, but just as a note for future pull requests - it would be nice to split it into two commits - first, moving the code around without changes, and second - introducing these changes. |
This PR needs rebasing, as |
Rewrite after a rebase with many conflicts
76b3bc7
to
a198d9b
Compare
There were too many conflicts, so I have rewritten the PR. |
1. update copyright year. 2. Enable ecdsa. 3. Change `hlen` parameter in the ecdsa test to byte size, as this is what the API expects. 4. Remove unused variables.
Add the platform context to the test functions, as these are the functions handling the cryptographic modules.
@AndrzejKurek I have rewritten the PR, as there were too many conflicts in rebase. Please re-review. @k-stachowiak could you please specify where there are resources not being freed? If you found some memory leaks, I think it would be a good idea to open a separate issue, as I didn't really modify code, except the ecdsa code that didn't work on my HW accelerator. |
Have the test functions return error code, to avoid resource leak of the platform context, and for cleaner exit.
@@ -145,7 +145,7 @@ | |||
/* | |||
* Uncomment this line to enable ECDSA benchmark. | |||
*/ | |||
//#define ENABLE_ECDSA | |||
#define ENABLE_ECDSA |
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.
Should this be enabled? It is more than just reducing stack size, its a functional change.
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.
The reason it was disabled was because ECDSA caused stack overflow.
Now, it can be returned.
I think we can remove the whole ENABLE_ECDSA
part, once this will be tested on numerous targets
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 change breaks the example for the ARM Compiler on K64F! We should have tested that before merging. It's especially obvious to test because it's what the CI tests!
cc: @mazimkhan
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 tested it on K64F and on NRF52840.
If CI is still broken, we can return this change.
@@ -819,7 +777,7 @@ static int benchmark( int argc, char *argv[], mbedtls_platform_context* ctx ) | |||
mbedtls_snprintf( title, sizeof( title ), "ECDSA-%s", | |||
curve_info->name ); | |||
TIME_PUBLIC( title, "sign", | |||
ret = mbedtls_ecdsa_write_signature( &ecdsa, MBEDTLS_MD_SHA256, buf, curve_info->bit_size, | |||
ret = mbedtls_ecdsa_write_signature( &ecdsa, MBEDTLS_MD_SHA256, buf, ( curve_info->bit_size + 7 ) / 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.
Was the previous buffer size simply inaccurate, or we don't have so much space? If this amount only plays a role in checking whether the buffer is big enough, why don't we pass the real buffer 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.
The parameter is hlen
not buffer length. So, sizeof(buf) is inaccurate.
The previous buffer size was sent as bits, not bytes, but the API expects length in bytes.
SInce this is a benchmark application, it didn't verify with expected result, and the SW implementation succeeded. I noticed this issue, when a HW accelerator expects only specific standard lengths, so it returned an error
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.
Besides the malloc_buf allocation that's not freed, and probably should be raised as a bug, this PR is ok.
@AndrzejKurek Thanks for the review. I did consider adding a free to the malloc_buf allocation, but since it's not defined on Mbed OS(at least no the targets I checked), and it's a functional change, I didn't add 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.
This PR is mostly a straight forward split of the previous long benchmark function to reduce stack usage. And I am happy with these changes. However, I pointed out several other (mostly preexisting issues) that would be good to fix, but I do not think they are a blocker because they do were already there.
Also pointed out a simple style issue, but this is not a blocker either...
int i; | ||
todo_list todo; | ||
#if defined(MBEDTLS_MEMORY_BUFFER_ALLOC_C) | ||
unsigned char malloc_buf[HEAP_SIZE] = { 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.
I do not think this is going to work. This line will allocate a 64KB array on the stack that will then be managed by Mbed TLS. However, the default stack size in Mbed OS is 4KB and it almost certainly cause problems. I suggest removing the use of MBEDTLS_MEMORY_BUFFER_ALLOC_C
from this example. The embedded platforms that this example is targeting cannot cope with these huge allocations. If you still want to make it work, you can probably look up the appropriate symbols in the linker files and pass it real pointers to the heap. Even then, this might cause trouble if other parts of the system use the real malloc/calloc...
for( i = 1; i < argc; i++ ) | ||
{ | ||
if( strcmp( argv[i], "md4" ) == 0 ) | ||
todo.md4 = 1; |
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 todo
struct is a trace of the origin of this example, that is, the benchmark application in mbedtls/programs/benchmark.c
. That application was meant for command line usage, so it made sense to provide an interface to enable/disable parts of the benchmark. However, this app is meant for an embedded platform and (as far as I remember) these values have never been changed (proof of that is that we used ENABLE_ECDSA instead of flicking the appropriate todo bit). I think this feature is entirely redundant and causes clutter. I suggest removing the todo
struct and all its associated code.
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 agree it's redundant and not needed. Opened #170 to track it,
Side note: ENABLE_ECDSA
was used to reduce stack size. Flipping the todo bit would keep the code compiled and keep the stack usage.
#endif | ||
memset( buf, 0xAA, sizeof( buf ) ); | ||
|
||
if( test_md( &todo, ctx ) != 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.
style: Please add
before )
.
return ( 0 ); | ||
} | ||
|
||
static int test_rng( const todo_list * todo, mbedtls_platform_context* ctx ) |
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 like the idea of this function returning an error code. However, as far as I can tell, this is currently not properly set in all cases (same situation with all the other test_*()
). It would be great to properly set the value, specially if there are more platforms with hardware acceleration support.
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 don't understand what you mean. Do you mean to set a ret
variable and set its value according to the crypto functions? I agree it should be done, but I think it should be part of a different PR, as this PR is only refactoring the function calls to separate functions, to reduce stack 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.
Yep, thats what I mean.
Agreed, preexisting and different issue
memset( tmp, 0xBB, sizeof( tmp ) ); | ||
|
||
#if defined(MBEDTLS_MD4_C) | ||
if( todo.md4 ) | ||
if( todo->md4 ) | ||
TIME_AND_TSC( "MD4", mbedtls_md4( buf, BUFSIZE, tmp ) ); |
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 dont think the return code in any of these is being checked.
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.
Correct, but this is pre-existing behavior. Opened #172 to track this
|
||
if( mbedtls_ctr_drbg_seed( &ctr_drbg, myrand, NULL, NULL, 0 ) != 0 ) | ||
return(1); | ||
mbedtls_ctr_drbg_set_prediction_resistance( &ctr_drbg, MBEDTLS_CTR_DRBG_PR_ON ); | ||
TIME_AND_TSC( "CTR_DRBG (PR)", | ||
if( mbedtls_ctr_drbg_random( &ctr_drbg, buf, BUFSIZE ) != 0 ) | ||
return(1) ); | ||
return(1) ); |
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 the return value in all these is lost...
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.
why? this return is part of the CODE
being set in the TIME_AND_TSC
macro
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.
It is returning 1 in all cases, so if it fails, the user would not know the cause. That is what I mean by "lost"
@andresag01 Thank you for your comments. |
@RonEld: I agree. As I mentioned in my review comments, I do not think these are blockers because they are preexisting issues. |
My comment only stated, what I was checking for, including unreleased resources. Let me confirm, that I have found no issues of that kind. |
@k-stachowiak Thanks for confirming. |
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.
@RonEld: As discussed, most of my comments are related to preexisting issues and are best addressed in another PR. There is just one or two style issues, but that is not a blocker, so I am approving this PR.
their module
Tested on K64F and NRF52840_DK