Skip to content

Port aes cc310 driver #10907

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

Merged
merged 4 commits into from
Aug 23, 2019
Merged

Port aes cc310 driver #10907

merged 4 commits into from
Aug 23, 2019

Conversation

RonEld
Copy link
Contributor

@RonEld RonEld commented Jun 27, 2019

Description

Add support for CC310 AES driver,
returning MBEDTLS_ERR_PLATFORM_FEATURE_UNSUPPORTED for key size
other than 128 bits, and for AES modes not supported by the driver.
Use MBEDTLS_CTR_DRBG_USE_128_BIT_KEY.
Benchmark information, built with GCC_ARM:

 AES-CBC-128              :      15023 KB/s
  AES-CBC-192              :  Feature unsupported
  AES-CBC-256              :  Feature unsupported
  AES-CTR-128              :      15017 KB/s
  AES-CTR-192              :  Feature unsupported
  AES-CTR-256              :  Feature unsupported
  AES-GCM-128              :        232 KB/s
  AES-GCM-192              :  Feature unsupported
  AES-GCM-256              :  Feature unsupported
  AES-CMAC-128             :        531 KB/s
  AES-CMAC-192             :  Feature unsupported
  AES-CMAC-256             :  Feature unsupported

Tested also with the Mbed TLS On Target Tests on NRF52840_DK

Pull request type

[ ] Fix
[ ] Refactor
[x] Target update
[ ] Functionality change
[ ] Docs update
[ ] Test update
[ ] Breaking change

Reviewers

@ARMmbed/mbed-os-crypto

Release Notes

This is a target update, adding hw accelerated AES, however, it can also be considered as a breaking change, as it removes support for AES other than 128 bit keys.

@40Grit
Copy link

40Grit commented Jun 27, 2019

Please show effect on resource usage. Flash/ram

@trowbridgec @AGlass0fMilk

@RonEld
Copy link
Contributor Author

RonEld commented Jun 27, 2019

Using the generated map file, I see the following changes:
RAM: no change
ROM: with the Cryptocell AES driver, 2432 bytes smaller than the sw AES implementation

@RonEld
Copy link
Contributor Author

RonEld commented Jun 27, 2019

benchmark performance with the sw driver:

  AES-CBC-128              :        509 KB/s
  AES-CBC-192              :        439 KB/s
  AES-CBC-256              :        386 KB/s
  AES-CTR-128              :        513 KB/s
  AES-CTR-192              :        442 KB/s
  AES-CTR-256              :        388 KB/s
  AES-GCM-128              :        214 KB/s
  AES-GCM-192              :        200 KB/s
  AES-GCM-256              :        189 KB/s
  AES-CMAC-128             :        440 KB/s
  AES-CMAC-192             :        386 KB/s
  AES-CMAC-256             :        344 KB/s
  AES-CMAC-PRF-128         :        439 KB/s

@40Grit
Copy link

40Grit commented Jun 27, 2019

@maclobdell

@ciarmcom ciarmcom requested review from a team June 27, 2019 11:00
@ciarmcom
Copy link
Member

@RonEld, thank you for your changes.
@ARMmbed/mbed-os-crypto @ARMmbed/mbed-os-maintainers please review.

Add support for CC310 AES driver,
returning `MBEDTLS_ERR_PLATFORM_FEATURE_UNSUPPORTED` for key size
other than 128 bits, and for AES modes not supported by the driver.
Use `MBEDTLS_CTR_DRBG_USE_128_BIT_KEY`.
@RonEld
Copy link
Contributor Author

RonEld commented Jun 27, 2019

I amended the three files with the correct copyright year and updated the Arm brand name

}
#if defined(MBEDTLS_CIPHER_MODE_XTS)

void mbedtls_aes_xts_init( mbedtls_aes_xts_context *ctx ){}
Copy link
Contributor

Choose a reason for hiding this comment

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

If we don't define these, if someone attempts to use them, they'll get build failures. If we implement them doing nothing, that's a small waste of code space, but also could hide the unsupported nature until run-time. Maybe worth adding #error AES XTS is not supported with CC310 AES within this #if defined(MBEDTLS_CIPHER_MODE_XTS), instead of making empty functions.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Personally, I also prefer catching issues as soon as possible, e.g. at build time. However. this is according to our design, and in this specific case it may cause CI issues, when trying to set different configurations on different platforms

Copy link
Contributor

Choose a reason for hiding this comment

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

OK for now in this PR.

That's a problem in our CI, IMO. We shouldn't count it as a failure, nor attempt such an an invalid configuration, when a certain platform's ALT implementation can't do certain block modes.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Yes, this is why I added the FEATURE UNSUPPORTED PR

Copy link
Contributor

Choose a reason for hiding this comment

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

OK


}

int mbedtls_aes_setkey_dec( mbedtls_aes_context *ctx, const unsigned char *key,
Copy link
Contributor

Choose a reason for hiding this comment

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

This looks identical to mbedtls_aes_setkey_enc() other than one flag. Could we implement these functions by returning the result of a new function return mbedtls_aes_setkey(SASI_AES_DECRYPT)? It should save a bit of flash space, and be more readable.

return( MBEDTLS_ERR_AES_BAD_INPUT_DATA );

return( CC_aes_cipher( ctx, mode, SASI_AES_MODE_ECB, 16, NULL, 0, input, output ) );

Copy link
Contributor

Choose a reason for hiding this comment

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

Style: Sometimes there is a newline here after return before }, and sometimes not. Be consistent at least. We prefer the no newline in this location style.


if ( *nc_off )
{
/* handle corner case where we are resuming a previous encryption,
Copy link
Contributor

Choose a reason for hiding this comment

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

Does CC_aes_cipher not handle this corner case itself?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

no. CC CTR implementation only supports where *nc_off is zero

Copy link
Contributor

Choose a reason for hiding this comment

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

What happens if it isn't? Incorrect computation? How do users of the CC API cope with this limitation ordinarily?

Copy link
Contributor Author

@RonEld RonEld Jul 1, 2019

Choose a reason for hiding this comment

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

yes, incorrect computation. Users of CC, that are interested in *nc_off != 0 will need to do the same thing

if( ( ( length % SASI_AES_BLOCK_SIZE_IN_BYTES ) != 0 ) && ret == 0 )
{
/* in case the length is not aligned, generate stream block for resuming
* increase nonce_block to the correct value*/
Copy link
Contributor

Choose a reason for hiding this comment

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

Could we fail with hardware unsupported or invalid parameter when alignment is not correct?

If not, maybe it's smaller in code size to copy the block to an aligned location, perform the hardware operation, and then copy back.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

It's bad wording. It's not a matter of memory alignment. It's a matter of length which is a multiple of AES block size (16). This functionality generates the stream block for resuming on next call( if there is), for generating the first block on next block ( since *nc_off is not zero in this case)

Copy link
Contributor Author

Choose a reason for hiding this comment

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

I think that returning unsupported feature in this case will result in a major functionality decrease, on the expense of minor flash set back, IMHO

Copy link
Contributor

Choose a reason for hiding this comment

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

What's the use case exactly? Why this is a major functionality decrease? Don't users usually use AES with a length that's a multiple of the block length?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

not for CTR.
CTR is streaming mode, which you can send any length of data, and pause the streaming in the middle, resume the streaming from same location, or any other arbitrary location

Copy link
Contributor

Choose a reason for hiding this comment

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

Seems odd that CC only lets you do CTR in multiples of the block length. Is that really the case? Doesn't that sort of defeat the purpose of streaming?

Choose a reason for hiding this comment

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

@Patater CTR mode is a stream cipher based on top of a block operation. From the user's perspective, partial inputs can have any byte length (even any bit length in theory). But under the hood, the operation involving the key works on 128 bits at a time (for a cipher with 128-bit blocks). If a call completes with a total input size that isn't a multiple of the block size, something in the stack has to remember the partial state. The hardware can't do this by itself (it would need to store the state of all ongoing calls). Either the hardware stores the partial state in an opaque form that the driver just keeps in memory, or the hardware works on 128 bits at a time and it's up to the driver to compensate. Usually, it's the latter: if the “hardware” is doing it, it means that some software layer deeper down is doing it.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

@Patater In addition to what was mentioned by @gilles-peskine-arm CC supports any byte length as input, but it doesn't support byte offset.
As you can see from previous call to CC driver(line 284), the full length ( after reducing nc_off ), no matter what the length is. However, if the length is not a multiple of 16, then we need to calculate stream_block for next API call.

1. Make common function for setting key, which receives
the direction as parameter.
2. Remove rediundant extra lines.
@RonEld
Copy link
Contributor Author

RonEld commented Jul 1, 2019

@Patater I addressed your issues.
I modified the code according to the comments I agree with, and waiting for your feedback on other comments.

@bulislaw
Copy link
Member

bulislaw commented Jul 2, 2019

it can also be considered as a breaking change, as it removes support for AES other than 128 bit keys.

I don't exactly know how it used to work, but I don't want us to break people use cases. I'd much rather add it as an option for now and make it as default for 6.

@RonEld
Copy link
Contributor Author

RonEld commented Jul 2, 2019

I don't exactly know how it used to work, but I don't want us to break people use cases. I'd much rather add it as an option for now and make it as default for 6.

Previously, AES 192 and AES 256 were supported by SW implementation. With this PR, a request for these key size modes( and some addition aes modes such as XTS and OFB ) will return an unsupported error.
The idea was to make it for the next major release, unless it is required for current minor release, in which case we should make it optional, by removing MBEDTLS_AES_ALT from mbedtls_device.h and users that want this feature will need to add this definition in mbed_app.json

Have the alternative aes undefined by default,
in order not to break backwards compatability.
`MBEDTLS_CTR_DRBG_USE_128_BIT_KEY` remains defined for better usability.
@RonEld
Copy link
Contributor Author

RonEld commented Jul 8, 2019

I made the alternative aes optional. I will make a separate PR, updating the readme file

@SeppoTakalo
Copy link
Contributor

@ARMmbed/mbed-os-crypto Please leave your review conclusions, + or -, Can this move forward, or does this require more work?

if( ( ( length % SASI_AES_BLOCK_SIZE_IN_BYTES ) != 0 ) && ret == 0 )
{
/* in case the length is not aligned, generate stream block for resuming
* increase nonce_block to the correct value*/
Copy link
Contributor

Choose a reason for hiding this comment

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

Seems odd that CC only lets you do CTR in multiples of the block length. Is that really the case? Doesn't that sort of defeat the purpose of streaming?

}
#if defined(MBEDTLS_CIPHER_MODE_XTS)

void mbedtls_aes_xts_init( mbedtls_aes_xts_context *ctx ){}
Copy link
Contributor

Choose a reason for hiding this comment

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

OK

static int CC_aes_setkey( mbedtls_aes_context *ctx, const unsigned char *key,
unsigned int keybits, SaSiAesEncryptMode_t cipher_flag )
{

Copy link
Contributor

Choose a reason for hiding this comment

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

Remove extra newline

}

return ( 0 );

Copy link
Contributor

Choose a reason for hiding this comment

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

Remove extra newline


}
int mbedtls_aes_setkey_enc( mbedtls_aes_context *ctx, const unsigned char *key,
unsigned int keybits )
Copy link
Contributor

Choose a reason for hiding this comment

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

Align arguments

int mbedtls_aes_crypt_ecb( mbedtls_aes_context *ctx,
int mode,
const unsigned char input[16],
unsigned char output[16] )
Copy link
Contributor

Choose a reason for hiding this comment

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

Align arguments

@@ -22,6 +22,8 @@
#define __MBEDTLS_DEVICE__

#define MBEDTLS_PLATFORM_SETUP_TEARDOWN_ALT
//#define MBEDTLS_AES_ALT
#define MBEDTLS_CTR_DRBG_USE_128_BIT_KEY
Copy link
Contributor

Choose a reason for hiding this comment

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

I don't think we want to degrade the security of devices by default. Consider wrapping this setting in a ifdef, with a comment explaining why it's needed.

#if defined(MBEDTLS_AES_ALT)
#define MBEDTLS_CTR_DRBG_USE_128_BIT_KEY
#endif

Choose a reason for hiding this comment

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

AES-128 is acceptable as default security as long as there are less than about one quintillion devices (128-bit security, divide by two for the birthday bound) under ideal conditions (if there are side channels, it can be another matter, but more bits often doesn't help anyway). AES-256 gives a better security margin, but there's no reason to require it.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

I agree, we don't want to degrade security, and perhaps as long as AES_ALT is not defined we shouldn't , however I decide to add it in order to have as less configurability as possible, for readability reasons. In addition, as mentioned by Gilles, the degrade doesn't have much effect.

1. Remove redundant extra lines.
2. Have the function parameters aligned.
3. Remove redundant white spaces.
@RonEld
Copy link
Contributor Author

RonEld commented Aug 11, 2019

@Patater @gilles-peskine-arm I have fixes some style issues.
Please review.
I haven't changed according to #10907 (comment) as I don't think it's needed.

@mbed-ci
Copy link

mbed-ci commented Aug 20, 2019

Test run: FAILED

Summary: 2 of 11 test jobs failed
Build number : 1
Build artifacts

Failed test jobs:

  • jenkins-ci/mbed-os-ci_cloud-client-test
  • jenkins-ci/mbed-os-ci_exporter

@0xc0170
Copy link
Contributor

0xc0170 commented Aug 20, 2019

CI restarted

@0xc0170
Copy link
Contributor

0xc0170 commented Aug 23, 2019

Restarted CI (the last run did not complete neither reported here).

@mbed-ci
Copy link

mbed-ci commented Aug 23, 2019

Test run: SUCCESS

Summary: 11 of 11 test jobs passed
Build number : 2
Build artifacts

@0xc0170 0xc0170 merged commit b9a6251 into ARMmbed:master Aug 23, 2019
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

9 participants