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

NUCLEO_F439ZI/mbedtls: add SHA256 hw_acceleration #4159

Merged
merged 9 commits into from
Jun 28, 2017
167 changes: 167 additions & 0 deletions TESTS/mbedtls/multi/main.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,167 @@
/*
* Copyright (c) 2013-2016, ARM Limited, All Rights Reserved
* SPDX-License-Identifier: Apache-2.0
*
* Licensed under the Apache License, Version 2.0 (the "License"); you may
* not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#include <stdio.h>
#include <string.h>
#include "mbed.h"
#include "greentea-client/test_env.h"
#include "unity/unity.h"
#include "utest/utest.h"

#include "mbedtls/sha256.h"


using namespace utest::v1;

#if defined(MBEDTLS_SHA256_C)
/* Tests several call to mbedtls_sha256_update function that are not modulo 64 bytes */
void test_case_sha256_split() {
const unsigned char test_buf[] = {"abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopqabcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopqabcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq"};
// sha256_output_values for 3*abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq
const unsigned char test_sum[] =
{ 0x50, 0xEA, 0x82, 0x5D, 0x96, 0x84, 0xF4, 0x22,
0x9C, 0xA2, 0x9F, 0x1F, 0xEC, 0x51, 0x15, 0x93,
0xE2, 0x81, 0xE4, 0x6A, 0x14, 0x0D, 0x81, 0xE0,
0x00, 0x5F, 0x8F, 0x68, 0x86, 0x69, 0xA0, 0x6C};
unsigned char outsum[32];
int i;

mbedtls_sha256_context ctx;
printf("test sha256\n");
mbedtls_sha256_init( &ctx );
mbedtls_sha256_starts( &ctx, 0);
#if 0
printf("test not splitted\n");
mbedtls_sha256_update( &ctx, test_buf, 168 );
#else
printf("test splitted into 3 pieces\n");
mbedtls_sha256_update( &ctx, test_buf, 2 );
mbedtls_sha256_update( &ctx, test_buf+2, 66 );
mbedtls_sha256_update( &ctx, test_buf+68, 100 );
#endif

mbedtls_sha256_finish( &ctx, outsum );
mbedtls_sha256_free( &ctx );

printf("\nreceived result : ");
for (i=0;i<32;i++) { printf("%02X",outsum[i]);}
printf("\nawaited result : 50EA825D9684F4229CA29F1FEC511593E281E46A140D81E0005F8F688669A06C\n"); // for abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq

printf("\nend of test sha256\n");
TEST_ASSERT_EQUAL_UINT8_ARRAY(outsum, test_sum,32);
}

/* Tests that treating 2 sha256 objects in // does not impact the result */
void test_case_sha256_multi() {
const unsigned char test_buf[] = {"abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopqabcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopqabcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq"};
const unsigned char test_buf2[] = {"abcdefghijklmnopqrstuvwxyz012345678901234567890123456789"};

// sha256_output_values for abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq
const unsigned char test_sum1[] =
{ 0x24, 0x8D, 0x6A, 0x61, 0xD2, 0x06, 0x38, 0xB8,
0xE5, 0xC0, 0x26, 0x93, 0x0C, 0x3E, 0x60, 0x39,
0xA3, 0x3C, 0xE4, 0x59, 0x64, 0xFF, 0x21, 0x67,
0xF6, 0xEC, 0xED, 0xD4, 0x19, 0xDB, 0x06, 0xC1 };
// sha256_output_values for 3*abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq
const unsigned char test_sum2[] =
{ 0x50, 0xEA, 0x82, 0x5D, 0x96, 0x84, 0xF4, 0x22,
0x9C, 0xA2, 0x9F, 0x1F, 0xEC, 0x51, 0x15, 0x93,
0xE2, 0x81, 0xE4, 0x6A, 0x14, 0x0D, 0x81, 0xE0,
0x00, 0x5F, 0x8F, 0x68, 0x86, 0x69, 0xA0, 0x6C};
// sha256_output_values for abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopqabcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopqabcdefghijklmnopqrstuvwxyz012345678901234567890123456789
const unsigned char test_sum3[] =
{ 0x6D, 0x5D, 0xDB, 0x5F, 0x4A, 0x94, 0xAB, 0x7E,
0x5C, 0xF7, 0x9A, 0xD8, 0x3F, 0x58, 0xD3, 0x97,
0xFE, 0x79, 0xFB, 0x0D, 0x79, 0xB2, 0x0D, 0x22,
0xFF, 0x95, 0x9F, 0x04, 0xA2, 0xE4, 0x6C, 0x68};
unsigned char outsum1[32], outsum2[32], outsum3[32];
int i;

mbedtls_sha256_context ctx1;
mbedtls_sha256_context ctx2;
mbedtls_sha256_context ctx3;
printf("test sha256_multi\n");
//Init both contexts
mbedtls_sha256_init( &ctx1);
mbedtls_sha256_init( &ctx2);
mbedtls_sha256_init( &ctx3);
//Start both contexts
mbedtls_sha256_starts( &ctx1, 0);
mbedtls_sha256_starts( &ctx2, 0);

printf("upd ctx1\n");
mbedtls_sha256_update( &ctx1, test_buf, 56 );
printf("upd ctx2\n");
mbedtls_sha256_update( &ctx2, test_buf, 66 );
printf("finish ctx1\n");
mbedtls_sha256_finish( &ctx1, outsum1 );
printf("upd ctx2\n");
mbedtls_sha256_update( &ctx2, test_buf+66, 46 );
printf("clone ctx2 in ctx3\n");
mbedtls_sha256_clone(&ctx3, (const mbedtls_sha256_context *)&ctx2);
printf("free ctx1\n");
mbedtls_sha256_free( &ctx1 );
printf("upd ctx2\n");
mbedtls_sha256_update( &ctx2, test_buf+112, 56 );
printf("upd ctx3 with different values than ctx2\n");
mbedtls_sha256_update( &ctx3, test_buf2, 56 );
printf("finish ctx2\n");
mbedtls_sha256_finish( &ctx2, outsum2 );
printf("finish ctx3\n");
mbedtls_sha256_finish( &ctx3, outsum3 );
printf("free ctx2\n");
mbedtls_sha256_free( &ctx2 );
printf("free ctx3\n");
mbedtls_sha256_free( &ctx3 );

printf("\nreceived result ctx1 : ");
for (i=0;i<32;i++) { printf("%02X",outsum1[i]);}
printf("\nawaited result : 248D6A61D20638B8E5C026930C3E6039A33CE45964FF216F6ECEDD19DB06C1\n"); // for abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq
printf("\nreceived result ctx2 : ");
for (i=0;i<32;i++) { printf("%02X",outsum2[i]);}
printf("\nawaited result : 50EA825D9684F4229CA29F1FEC511593E281E46A140D81E0005F8F688669A06C\n"); // for 3*abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq
printf("\nreceived result ctx3 : ");
for (i=0;i<32;i++) { printf("%02X",outsum3[i]);}
printf("\nawaited result : 6D5DDB5F4A94AB7E5CF79AD83F58D397FE79FB0D79B20D22FF959F04A2E46C68\n"); // for 2*abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq+3*0123456789
printf("\nend of test sha256\n");
TEST_ASSERT_EQUAL_UINT8_ARRAY(outsum1, test_sum1,32);
TEST_ASSERT_EQUAL_UINT8_ARRAY(outsum2, test_sum2,32);
TEST_ASSERT_EQUAL_UINT8_ARRAY(outsum3, test_sum3,32);
}
#endif //MBEDTLS_SHA256_C

utest::v1::status_t greentea_failure_handler(const Case *const source, const failure_t reason) {
greentea_case_failure_abort_handler(source, reason);
return STATUS_CONTINUE;
}

Case cases[] = {
#if defined(MBEDTLS_SHA256_C)
Case("Crypto: sha256_split", test_case_sha256_split, greentea_failure_handler),
Case("Crypto: sha256_multi", test_case_sha256_multi, greentea_failure_handler),
#endif
};

utest::v1::status_t greentea_test_setup(const size_t number_of_cases) {
GREENTEA_SETUP(10, "default_auto");
return greentea_test_setup_handler(number_of_cases);
}

Specification specification(greentea_test_setup, cases, greentea_test_teardown_handler);

int main() {
Harness::run(specification);
}
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,9 @@
#define MBEDTLS_DEVICE_H

#define MBEDTLS_AES_ALT

#define MBEDTLS_SHA256_ALT

#define MBEDTLS_SHA1_ALT

#endif /* MBEDTLS_DEVICE_H */
217 changes: 217 additions & 0 deletions features/mbedtls/targets/TARGET_STM/sha256_alt.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,217 @@
/*
* sha256_alt.c for SHA256 HASH
*******************************************************************************
* Copyright (c) 2017, STMicroelectronics
* SPDX-License-Identifier: Apache-2.0
*
* Licensed under the Apache License, Version 2.0 (the "License"); you may
* not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
*/
#include "mbedtls/sha256.h"

#if defined(MBEDTLS_SHA256_ALT)
#include "mbedtls/platform.h"

/* Implementation that should never be optimized out by the compiler */
static void mbedtls_zeroize( void *v, size_t n ) {
volatile unsigned char *p = v; while( n-- ) *p++ = 0;
}

static int st_sha256_restore_hw_context(mbedtls_sha256_context *ctx)
{
uint32_t i;
uint32_t tickstart;
/* allow multi-instance of HASH use: save context for HASH HW module CR */
/* Check that there is no HASH activity on going */
tickstart = HAL_GetTick();
while ((HASH->SR & (HASH_FLAG_BUSY | HASH_FLAG_DMAS)) != 0) {
if ((HAL_GetTick() - tickstart) > ST_SHA256_TIMEOUT) {
return 0; // timeout: HASH processor is busy
}
}
HASH->STR = ctx->ctx_save_str;
HASH->CR = (ctx->ctx_save_cr | HASH_CR_INIT);
for (i=0;i<38;i++) {
HASH->CSR[i] = ctx->ctx_save_csr[i];
}
return 1;
}

static int st_sha256_save_hw_context(mbedtls_sha256_context *ctx)
{
uint32_t i;
uint32_t tickstart;
/* Check that there is no HASH activity on going */
tickstart = HAL_GetTick();
while ((HASH->SR & (HASH_FLAG_BUSY | HASH_FLAG_DMAS)) != 0) {
if ((HAL_GetTick() - tickstart) > ST_SHA256_TIMEOUT) {
return 0; // timeout: HASH processor is busy
}
}
/* allow multi-instance of HASH use: restore context for HASH HW module CR */
ctx->ctx_save_cr = HASH->CR;
ctx->ctx_save_str = HASH->STR;
for (i=0;i<38;i++) {
ctx->ctx_save_csr[i] = HASH->CSR[i];
}
return 1;
}

void mbedtls_sha256_init( mbedtls_sha256_context *ctx )
{
mbedtls_zeroize( ctx, sizeof( mbedtls_sha256_context ) );

/* Enable HASH clock */
__HAL_RCC_HASH_CLK_ENABLE();

Choose a reason for hiding this comment

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

Is this the right place to power on the hardware? See my comment about reset in mbedtls_sha256_free.

Copy link
Member Author

Choose a reason for hiding this comment

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

Powering the hw will have no effect if already done.

}

void mbedtls_sha256_free( mbedtls_sha256_context *ctx )
{
if( ctx == NULL )
return;
mbedtls_zeroize( ctx, sizeof( mbedtls_sha256_context ) );
}

void mbedtls_sha256_clone( mbedtls_sha256_context *dst,
const mbedtls_sha256_context *src )
{
*dst = *src;

Choose a reason for hiding this comment

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

I'm not sure this is correct, but again it might be because I am not familiar with the hardware. After calling the clone function, a user of the crypto library can alternate calls to the two contexts. If the context data is copied, in particular if the clones have the same contents in all the HASH_HandleTypeDef fields, won't they be sharing some resources?

Copy link
Member Author

Choose a reason for hiding this comment

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

see previous comment

}

void mbedtls_sha256_starts( mbedtls_sha256_context *ctx, int is224 )
{
/* HASH IP initialization */
if (HAL_HASH_DeInit(&ctx->hhash_sha256) == HAL_ERROR) {
// error found to be returned
return;
}

ctx->is224 = is224;
/* HASH Configuration */
ctx->hhash_sha256.Init.DataType = HASH_DATATYPE_8B;
if (HAL_HASH_Init(&ctx->hhash_sha256) == HAL_ERROR) {
// error found to be returned
return;
}
if (st_sha256_save_hw_context(ctx) != 1) {
return; // return HASH_BUSY timeout Error here
}
}

void mbedtls_sha256_process( mbedtls_sha256_context *ctx, const unsigned char data[ST_SHA256_BLOCK_SIZE] )
{
if (st_sha256_restore_hw_context(ctx) != 1) {
return; // Return HASH_BUSY timout error here
}
if (ctx->is224 == 0) {
if (HAL_HASHEx_SHA256_Accumulate(&ctx->hhash_sha256, (uint8_t *) data, ST_SHA256_BLOCK_SIZE) != 0) {
return; // Return error code
}
} else {
if (HAL_HASHEx_SHA224_Accumulate(&ctx->hhash_sha256, (uint8_t *) data, ST_SHA256_BLOCK_SIZE) != 0) {
return; // Return error code
}
}

if (st_sha256_save_hw_context(ctx) != 1) {
return; // return HASH_BUSY timeout Error here
}
}

void mbedtls_sha256_update( mbedtls_sha256_context *ctx, const unsigned char *input, size_t ilen )
{
size_t currentlen = ilen;
if (st_sha256_restore_hw_context(ctx) != 1) {
return; // Return HASH_BUSY timout error here
}

// store mechanism to accumulate ST_SHA256_BLOCK_SIZE bytes (512 bits) in the HW
if (currentlen == 0) { // only change HW status is size if 0
if(ctx->hhash_sha256.Phase == HAL_HASH_PHASE_READY) {
/* Select the SHA256 or SHA224 mode and reset the HASH processor core, so that the HASH will be ready to compute
the message digest of a new message */
if (ctx->is224 == 0) {
HASH->CR |= HASH_ALGOSELECTION_SHA256 | HASH_CR_INIT;
} else {
HASH->CR |= HASH_ALGOSELECTION_SHA224 | HASH_CR_INIT;
}
}
ctx->hhash_sha256.Phase = HAL_HASH_PHASE_PROCESS;
} else if (currentlen < (ST_SHA256_BLOCK_SIZE - ctx->sbuf_len)) {
// only buffurize
memcpy(ctx->sbuf + ctx->sbuf_len, input, currentlen);
ctx->sbuf_len += currentlen;
} else {
// fill buffer and process it
memcpy(ctx->sbuf + ctx->sbuf_len, input, (ST_SHA256_BLOCK_SIZE - ctx->sbuf_len));
currentlen -= (ST_SHA256_BLOCK_SIZE - ctx->sbuf_len);
mbedtls_sha256_process(ctx, ctx->sbuf);
// Process every input as long as it is %64 bytes, ie 512 bits
size_t iter = currentlen / ST_SHA256_BLOCK_SIZE;
if (iter !=0) {
if (ctx->is224 == 0) {
if (HAL_HASHEx_SHA256_Accumulate(&ctx->hhash_sha256, (uint8_t *)(input + ST_SHA256_BLOCK_SIZE - ctx->sbuf_len), (iter * ST_SHA256_BLOCK_SIZE)) != 0) {
return; // Return error code here
}
} else {
if (HAL_HASHEx_SHA224_Accumulate(&ctx->hhash_sha256, (uint8_t *)(input + ST_SHA256_BLOCK_SIZE - ctx->sbuf_len), (iter * ST_SHA256_BLOCK_SIZE)) != 0) {
return; // Return error code here
}
}
}
// sbuf is completely accumulated, now copy up to 63 remaining bytes
ctx->sbuf_len = currentlen % ST_SHA256_BLOCK_SIZE;
if (ctx->sbuf_len !=0) {
memcpy(ctx->sbuf, input + ilen - ctx->sbuf_len, ctx->sbuf_len);
}
}
if (st_sha256_save_hw_context(ctx) != 1) {
return; // return HASH_BUSY timeout Error here
}
}

void mbedtls_sha256_finish( mbedtls_sha256_context *ctx, unsigned char output[32] )
{
if (st_sha256_restore_hw_context(ctx) != 1) {
return; // Return HASH_BUSY timout error here
}
if (ctx->sbuf_len > 0) {
if (ctx->is224 == 0) {
if (HAL_HASHEx_SHA256_Accumulate(&ctx->hhash_sha256, ctx->sbuf, ctx->sbuf_len) != 0) {
return; // Return error code here
}
} else {
if (HAL_HASHEx_SHA224_Accumulate(&ctx->hhash_sha256, ctx->sbuf, ctx->sbuf_len) != 0) {
return; // Return error code here
}
}
}
mbedtls_zeroize(ctx->sbuf, ST_SHA256_BLOCK_SIZE);
ctx->sbuf_len = 0;
__HAL_HASH_START_DIGEST();

if (ctx->is224 == 0) {
if (HAL_HASHEx_SHA256_Finish(&ctx->hhash_sha256, output, 10) != 0) {
return; // Return error code here
}
} else {
if (HAL_HASHEx_SHA224_Finish(&ctx->hhash_sha256, output, 10) != 0) {
return; // Return error code here
}
}
if (st_sha256_save_hw_context(ctx) != 1) {
return; // return HASH_BUSY timeout Error here
}
}

#endif /*MBEDTLS_SHA256_ALT*/
Loading