M467: Support Crypto SHA/ECC H/W

1.  Prepare crypto common code
2.  Support list
    -   SHA
    -   ECC
    NOTE: AES/RSA are to support in other works
    NOTE: Compared to M487, M467's SHA supports context save & restore (DMA Cascade mode) and so no software fallback is needed.
    NOTE: M467's ECC, following M487, goes partial-module replacement and it can just improve primitives e.g. point addition/doubling by 2X,
          and cannot improve high level point multiplication because MbedTLS doesn’t open it.
          To improve performance best, full-module replacement is needed.
    NOTE: Continuing above, add support for Montgomery curve
pull/15337/head
Chun-Chieh Li 2022-03-24 10:54:56 +08:00
parent ec2c15533e
commit 24b0feb17f
20 changed files with 2989 additions and 1 deletions

View File

@ -1,7 +1,9 @@
# Copyright (c) 2020 ARM Limited. All rights reserved.
# SPDX-License-Identifier: Apache-2.0
if("M480" IN_LIST MBED_TARGET_LABELS)
if("M460" IN_LIST MBED_TARGET_LABELS)
add_subdirectory(TARGET_M460)
elseif("M480" IN_LIST MBED_TARGET_LABELS)
add_subdirectory(TARGET_M480)
elseif("NUC472" IN_LIST MBED_TARGET_LABELS)
add_subdirectory(TARGET_NUC472)

View File

@ -0,0 +1,22 @@
# Copyright (c) 2020 ARM Limited. All rights reserved.
# SPDX-License-Identifier: Apache-2.0
target_include_directories(mbed-mbedtls
INTERFACE
.
./aes
./ecp
./rsa
./sha
)
target_sources(mbed-mbedtls
INTERFACE
aes/aes_alt.c
ecp/ecp_internal_alt.c
rsa/rsa_alt.c
sha/sha1_alt.c
sha/sha256_alt.c
sha/sha512_alt.c
sha/sha_alt_hw.c
)

View File

@ -0,0 +1 @@
/* TODO */

View File

@ -0,0 +1 @@
/* TODO */

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,42 @@
/*
* Copyright (c) 2022, Nuvoton Technology Corporation
*
* 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.
*/
#ifndef MBEDTLS_DEVICE_H
#define MBEDTLS_DEVICE_H
#define MBEDTLS_SHA1_ALT
#define MBEDTLS_SHA256_ALT
#define MBEDTLS_SHA512_ALT
//#define MBEDTLS_AES_ALT
#define MBEDTLS_ECP_INTERNAL_ALT
/* Support for Weierstrass curves with Jacobi representation */
#define MBEDTLS_ECP_RANDOMIZE_JAC_ALT
#define MBEDTLS_ECP_ADD_MIXED_ALT
#define MBEDTLS_ECP_DOUBLE_JAC_ALT
#define MBEDTLS_ECP_NORMALIZE_JAC_ALT
#define MBEDTLS_ECP_NORMALIZE_JAC_MANY_ALT
/* Support for curves with Montgomery arithmetic */
//#define MBEDTLS_ECP_DOUBLE_ADD_MXZ_ALT
#define MBEDTLS_ECP_RANDOMIZE_MXZ_ALT
#define MBEDTLS_ECP_NORMALIZE_MXZ_ALT
//#define MBEDTLS_RSA_ALT
#endif /* MBEDTLS_DEVICE_H */

View File

@ -0,0 +1 @@
/* TODO */

View File

@ -0,0 +1 @@
/* TODO */

View File

@ -0,0 +1,99 @@
/*
* Copyright (c) 2022, Nuvoton Technology Corporation
*
* 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/sha1.h"
#if defined(MBEDTLS_SHA1_C)
#if defined(MBEDTLS_SHA1_ALT)
#include "crypto-misc.h"
#include "nu_bitutil.h"
#include "string.h"
void mbedtls_sha1_init(mbedtls_sha1_context *ctx)
{
crypto_sha_init(&ctx->hw_ctx, SHA_MODE_SHA1);
}
void mbedtls_sha1_free(mbedtls_sha1_context *ctx)
{
if (ctx == NULL) {
return;
}
crypto_sha_free(&ctx->hw_ctx);
}
void mbedtls_sha1_clone(mbedtls_sha1_context *dst,
const mbedtls_sha1_context *src)
{
// Corner case: Destination/source contexts are the same
if (dst == src) {
return;
}
memcpy(dst, src, sizeof(mbedtls_sha1_context));
}
/*
* SHA-1 context setup
*/
int mbedtls_sha1_starts_ret(mbedtls_sha1_context *ctx)
{
if (ctx == NULL) {
return MBEDTLS_ERR_SHA1_BAD_INPUT_DATA;
}
return crypto_sha_starts(&ctx->hw_ctx, 0);
}
/*
* SHA-1 process buffer
*/
int mbedtls_sha1_update_ret(mbedtls_sha1_context *ctx, const unsigned char *input, size_t ilen)
{
if (ctx == NULL || (input == NULL && ilen == 0)) {
return MBEDTLS_ERR_SHA1_BAD_INPUT_DATA;
}
return crypto_sha_update(&ctx->hw_ctx, input, ilen);
}
/*
* SHA-1 final digest
*/
int mbedtls_sha1_finish_ret(mbedtls_sha1_context *ctx, unsigned char output[20])
{
if (ctx == NULL || output == NULL) {
return MBEDTLS_ERR_SHA1_BAD_INPUT_DATA;
}
return crypto_sha_finish(&ctx->hw_ctx, output, 20);
}
int mbedtls_internal_sha1_process(mbedtls_sha1_context *ctx, const unsigned char data[64])
{
if (ctx == NULL || data == NULL) {
return MBEDTLS_ERR_SHA1_BAD_INPUT_DATA;
}
return crypto_sha_update(&ctx->hw_ctx, data, 64);
}
#endif /* MBEDTLS_SHA1_ALT */
#endif /* MBEDTLS_SHA1_C */

View File

@ -0,0 +1,177 @@
/*
* Copyright (c) 2022, Nuvoton Technology Corporation
*
* 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.
*/
#ifndef MBEDTLS_SHA1_ALT_H
#define MBEDTLS_SHA1_ALT_H
#include "mbedtls/sha1.h"
#if defined(MBEDTLS_SHA1_ALT)
#include "sha_alt_hw.h"
#ifdef __cplusplus
extern "C" {
#endif
struct mbedtls_sha1_context_s;
/**
* \brief SHA-1 context structure
*/
typedef struct mbedtls_sha1_context_s {
crypto_sha_context hw_ctx;
}
mbedtls_sha1_context;
/**
* \brief Initialize SHA-1 context
*
* \param ctx SHA-1 context to be initialized
*/
void mbedtls_sha1_init( mbedtls_sha1_context *ctx );
/**
* \brief Clear SHA-1 context
*
* \param ctx SHA-1 context to be cleared
*/
void mbedtls_sha1_free( mbedtls_sha1_context *ctx );
/**
* \brief Clone (the state of) a SHA-1 context
*
* \param dst The destination context
* \param src The context to be cloned
*/
void mbedtls_sha1_clone( mbedtls_sha1_context *dst,
const mbedtls_sha1_context *src );
/**
* \brief SHA-1 context setup
*
* \param ctx context to be initialized
*
* \returns error code
*/
int mbedtls_sha1_starts_ret( mbedtls_sha1_context *ctx );
/**
* \brief SHA-1 process buffer
*
* \param ctx SHA-1 context
* \param input buffer holding the data
* \param ilen length of the input data
*
* \returns error code
*/
int mbedtls_sha1_update_ret( mbedtls_sha1_context *ctx, const unsigned char *input, size_t ilen );
/**
* \brief SHA-1 final digest
*
* \param ctx SHA-1 context
* \param output SHA-1 checksum result
*
* \returns error code
*/
int mbedtls_sha1_finish_ret( mbedtls_sha1_context *ctx, unsigned char output[20] );
/* Internal use */
int mbedtls_internal_sha1_process( mbedtls_sha1_context *ctx, const unsigned char data[64] );
#if !defined(MBEDTLS_DEPRECATED_REMOVED)
#if defined(MBEDTLS_DEPRECATED_WARNING)
#define MBEDTLS_DEPRECATED __attribute__((deprecated))
#else
#define MBEDTLS_DEPRECATED
#endif
/**
* \brief SHA-1 context setup
*
* \deprecated Superseded by mbedtls_sha1_starts_ret() in 2.7.0
*
* \param ctx The SHA-1 context to be initialized.
*
* \warning SHA-1 is considered a weak message digest and its use
* constitutes a security risk. We recommend considering
* stronger message digests instead.
*
*/
MBEDTLS_DEPRECATED void mbedtls_sha1_starts( mbedtls_sha1_context *ctx );
/**
* \brief SHA-1 process buffer
*
* \deprecated Superseded by mbedtls_sha1_update_ret() in 2.7.0
*
* \param ctx The SHA-1 context.
* \param input The buffer holding the input data.
* \param ilen The length of the input data.
*
* \warning SHA-1 is considered a weak message digest and its use
* constitutes a security risk. We recommend considering
* stronger message digests instead.
*
*/
MBEDTLS_DEPRECATED void mbedtls_sha1_update( mbedtls_sha1_context *ctx,
const unsigned char *input,
size_t ilen );
/**
* \brief SHA-1 final digest
*
* \deprecated Superseded by mbedtls_sha1_finish_ret() in 2.7.0
*
* \param ctx The SHA-1 context.
* \param output The SHA-1 checksum result.
*
* \warning SHA-1 is considered a weak message digest and its use
* constitutes a security risk. We recommend considering
* stronger message digests instead.
*
*/
MBEDTLS_DEPRECATED void mbedtls_sha1_finish( mbedtls_sha1_context *ctx,
unsigned char output[20] );
/**
* \brief SHA-1 process data block (internal use only)
*
* \deprecated Superseded by mbedtls_internal_sha1_process() in 2.7.0
*
* \param ctx The SHA-1 context.
* \param data The data block being processed.
*
* \warning SHA-1 is considered a weak message digest and its use
* constitutes a security risk. We recommend considering
* stronger message digests instead.
*
*/
MBEDTLS_DEPRECATED void mbedtls_sha1_process( mbedtls_sha1_context *ctx,
const unsigned char data[64] );
#undef MBEDTLS_DEPRECATED
#endif /* !MBEDTLS_DEPRECATED_REMOVED */
#ifdef __cplusplus
}
#endif
#endif /* MBEDTLS_SHA1_ALT */
#endif /* sha1_alt.h */

View File

@ -0,0 +1,99 @@
/*
* Copyright (c) 2022, Nuvoton Technology Corporation
*
* 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_C)
#if defined(MBEDTLS_SHA256_ALT)
#include "crypto-misc.h"
#include "nu_bitutil.h"
#include "string.h"
void mbedtls_sha256_init(mbedtls_sha256_context *ctx)
{
crypto_sha_init(&ctx->hw_ctx, SHA_MODE_SHA256);
}
void mbedtls_sha256_free(mbedtls_sha256_context *ctx)
{
if (ctx == NULL) {
return;
}
crypto_sha_free(&ctx->hw_ctx);
}
void mbedtls_sha256_clone(mbedtls_sha256_context *dst,
const mbedtls_sha256_context *src)
{
// Corner case: Destination/source contexts are the same
if (dst == src) {
return;
}
memcpy(dst, src, sizeof(mbedtls_sha256_context));
}
/*
* SHA-256 context setup
*/
int mbedtls_sha256_starts_ret(mbedtls_sha256_context *ctx, int is224)
{
if (ctx == NULL) {
return MBEDTLS_ERR_SHA256_BAD_INPUT_DATA;
}
return crypto_sha_starts(&ctx->hw_ctx, is224);
}
/*
* SHA-256 process buffer
*/
int mbedtls_sha256_update_ret(mbedtls_sha256_context *ctx, const unsigned char *input, size_t ilen)
{
if (ctx == NULL || (input == NULL && ilen == 0)) {
return MBEDTLS_ERR_SHA256_BAD_INPUT_DATA;
}
return crypto_sha_update(&ctx->hw_ctx, input, ilen);
}
/*
* SHA-256 final digest
*/
int mbedtls_sha256_finish_ret(mbedtls_sha256_context *ctx, unsigned char output[32])
{
if (ctx == NULL || output == NULL) {
return MBEDTLS_ERR_SHA256_BAD_INPUT_DATA;
}
return crypto_sha_finish(&ctx->hw_ctx, output, ctx->hw_ctx.is224_384 ? 28 : 32);
}
int mbedtls_internal_sha256_process(mbedtls_sha256_context *ctx, const unsigned char data[64])
{
if (ctx == NULL || data == NULL) {
return MBEDTLS_ERR_SHA256_BAD_INPUT_DATA;
}
return crypto_sha_update(&ctx->hw_ctx, data, 64);
}
#endif /* MBEDTLS_SHA256_ALT */
#endif /* MBEDTLS_SHA256_C */

View File

@ -0,0 +1,167 @@
/*
* Copyright (c) 2022, Nuvoton Technology Corporation
*
* 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.
*/
#ifndef MBEDTLS_SHA256_ALT_H
#define MBEDTLS_SHA256_ALT_H
#include "mbedtls/sha256.h"
#if defined(MBEDTLS_SHA256_ALT)
#include "sha_alt_hw.h"
#ifdef __cplusplus
extern "C" {
#endif
struct mbedtls_sha256_context_s;
/**
* \brief SHA-256 context structure
*/
typedef struct mbedtls_sha256_context_s {
crypto_sha_context hw_ctx;
}
mbedtls_sha256_context;
/**
* \brief Initialize SHA-256 context
*
* \param ctx SHA-256 context to be initialized
*/
void mbedtls_sha256_init( mbedtls_sha256_context *ctx );
/**
* \brief Clear SHA-256 context
*
* \param ctx SHA-256 context to be cleared
*/
void mbedtls_sha256_free( mbedtls_sha256_context *ctx );
/**
* \brief Clone (the state of) a SHA-256 context
*
* \param dst The destination context
* \param src The context to be cloned
*/
void mbedtls_sha256_clone( mbedtls_sha256_context *dst,
const mbedtls_sha256_context *src );
/**
* \brief SHA-256 context setup
*
* \param ctx context to be initialized
* \param is224 0 = use SHA256, 1 = use SHA224
*
* \returns error code
*/
int mbedtls_sha256_starts_ret( mbedtls_sha256_context *ctx, int is224 );
/**
* \brief SHA-256 process buffer
*
* \param ctx SHA-256 context
* \param input buffer holding the data
* \param ilen length of the input data
*
* \returns error code
*/
int mbedtls_sha256_update_ret( mbedtls_sha256_context *ctx, const unsigned char *input,
size_t ilen );
/**
* \brief SHA-256 final digest
*
* \param ctx SHA-256 context
* \param output SHA-224/256 checksum result
*
* \returns error code
*/
int mbedtls_sha256_finish_ret( mbedtls_sha256_context *ctx, unsigned char output[32] );
/* Internal use */
int mbedtls_internal_sha256_process( mbedtls_sha256_context *ctx, const unsigned char data[64] );
#if !defined(MBEDTLS_DEPRECATED_REMOVED)
#if defined(MBEDTLS_DEPRECATED_WARNING)
#define MBEDTLS_DEPRECATED __attribute__((deprecated))
#else
#define MBEDTLS_DEPRECATED
#endif
/**
* \brief This function starts a SHA-256 checksum calculation.
*
* \deprecated Superseded by mbedtls_sha256_starts_ret() in 2.7.0.
*
* \param ctx The SHA-256 context to initialize.
* \param is224 Determines which function to use.
* <ul><li>0: Use SHA-256.</li>
* <li>1: Use SHA-224.</li></ul>
*/
MBEDTLS_DEPRECATED void mbedtls_sha256_starts( mbedtls_sha256_context *ctx,
int is224 );
/**
* \brief This function feeds an input buffer into an ongoing
* SHA-256 checksum calculation.
*
* \deprecated Superseded by mbedtls_sha256_update_ret() in 2.7.0.
*
* \param ctx The SHA-256 context to initialize.
* \param input The buffer holding the data.
* \param ilen The length of the input data.
*/
MBEDTLS_DEPRECATED void mbedtls_sha256_update( mbedtls_sha256_context *ctx,
const unsigned char *input,
size_t ilen );
/**
* \brief This function finishes the SHA-256 operation, and writes
* the result to the output buffer.
*
* \deprecated Superseded by mbedtls_sha256_finish_ret() in 2.7.0.
*
* \param ctx The SHA-256 context.
* \param output The SHA-224or SHA-256 checksum result.
*/
MBEDTLS_DEPRECATED void mbedtls_sha256_finish( mbedtls_sha256_context *ctx,
unsigned char output[32] );
/**
* \brief This function processes a single data block within
* the ongoing SHA-256 computation. This function is for
* internal use only.
*
* \deprecated Superseded by mbedtls_internal_sha256_process() in 2.7.0.
*
* \param ctx The SHA-256 context.
* \param data The buffer holding one block of data.
*/
MBEDTLS_DEPRECATED void mbedtls_sha256_process( mbedtls_sha256_context *ctx,
const unsigned char data[64] );
#undef MBEDTLS_DEPRECATED
#endif /* !MBEDTLS_DEPRECATED_REMOVED */
#ifdef __cplusplus
}
#endif
#endif /* MBEDTLS_SHA256_ALT */
#endif /* sha256_alt.h */

View File

@ -0,0 +1,99 @@
/*
* Copyright (c) 2022, Nuvoton Technology Corporation
*
* 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/sha512.h"
#if defined(MBEDTLS_SHA512_C)
#if defined(MBEDTLS_SHA512_ALT)
#include "crypto-misc.h"
#include "nu_bitutil.h"
#include "string.h"
void mbedtls_sha512_init(mbedtls_sha512_context *ctx)
{
crypto_sha_init(&ctx->hw_ctx, SHA_MODE_SHA512);
}
void mbedtls_sha512_free(mbedtls_sha512_context *ctx)
{
if (ctx == NULL) {
return;
}
crypto_sha_free(&ctx->hw_ctx);
}
void mbedtls_sha512_clone(mbedtls_sha512_context *dst,
const mbedtls_sha512_context *src)
{
// Corner case: Destination/source contexts are the same
if (dst == src) {
return;
}
memcpy(dst, src, sizeof(mbedtls_sha512_context));
}
/*
* SHA-512 context setup
*/
int mbedtls_sha512_starts_ret(mbedtls_sha512_context *ctx, int is384)
{
if (ctx == NULL) {
return MBEDTLS_ERR_SHA512_BAD_INPUT_DATA;
}
return crypto_sha_starts(&ctx->hw_ctx, is384);
}
/*
* SHA-512 process buffer
*/
int mbedtls_sha512_update_ret(mbedtls_sha512_context *ctx, const unsigned char *input, size_t ilen)
{
if (ctx == NULL || (input == NULL && ilen == 0)) {
return MBEDTLS_ERR_SHA512_BAD_INPUT_DATA;
}
return crypto_sha_update(&ctx->hw_ctx, input, ilen);
}
/*
* SHA-512 final digest
*/
int mbedtls_sha512_finish_ret(mbedtls_sha512_context *ctx, unsigned char output[64])
{
if (ctx == NULL || output == NULL) {
return MBEDTLS_ERR_SHA512_BAD_INPUT_DATA;
}
return crypto_sha_finish(&ctx->hw_ctx, output, ctx->hw_ctx.is224_384 ? 48 : 64);
}
int mbedtls_internal_sha512_process(mbedtls_sha512_context *ctx, const unsigned char data[128])
{
if (ctx == NULL || data == NULL) {
return MBEDTLS_ERR_SHA512_BAD_INPUT_DATA;
}
return crypto_sha_update(&ctx->hw_ctx, data, 128);
}
#endif /* MBEDTLS_SHA512_ALT */
#endif /* MBEDTLS_SHA512_C */

View File

@ -0,0 +1,167 @@
/*
* Copyright (c) 2022, Nuvoton Technology Corporation
*
* 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.
*/
#ifndef MBEDTLS_SHA512_ALT_H
#define MBEDTLS_SHA512_ALT_H
#include "mbedtls/sha512.h"
#if defined(MBEDTLS_SHA512_ALT)
#include "sha_alt_hw.h"
#ifdef __cplusplus
extern "C" {
#endif
struct mbedtls_sha512_context_s;
/**
* \brief SHA-512 context structure
*/
typedef struct mbedtls_sha512_context_s {
crypto_sha_context hw_ctx;
}
mbedtls_sha512_context;
/**
* \brief Initialize SHA-512 context
*
* \param ctx SHA-512 context to be initialized
*/
void mbedtls_sha512_init( mbedtls_sha512_context *ctx );
/**
* \brief Clear SHA-512 context
*
* \param ctx SHA-512 context to be cleared
*/
void mbedtls_sha512_free( mbedtls_sha512_context *ctx );
/**
* \brief Clone (the state of) a SHA-512 context
*
* \param dst The destination context
* \param src The context to be cloned
*/
void mbedtls_sha512_clone( mbedtls_sha512_context *dst,
const mbedtls_sha512_context *src );
/**
* \brief SHA-512 context setup
*
* \param ctx context to be initialized
* \param is384 0 = use SHA512, 1 = use SHA384
*
* \returns error code
*/
int mbedtls_sha512_starts_ret( mbedtls_sha512_context *ctx, int is384 );
/**
* \brief SHA-512 process buffer
*
* \param ctx SHA-512 context
* \param input buffer holding the data
* \param ilen length of the input data
*
* \returns error code
*/
int mbedtls_sha512_update_ret( mbedtls_sha512_context *ctx, const unsigned char *input,
size_t ilen );
/**
* \brief SHA-512 final digest
*
* \param ctx SHA-512 context
* \param output SHA-384/512 checksum result
*
* \returns error code
*/
int mbedtls_sha512_finish_ret( mbedtls_sha512_context *ctx, unsigned char output[64] );
/* Internal use */
int mbedtls_internal_sha512_process( mbedtls_sha512_context *ctx, const unsigned char data[128] );
#if !defined(MBEDTLS_DEPRECATED_REMOVED)
#if defined(MBEDTLS_DEPRECATED_WARNING)
#define MBEDTLS_DEPRECATED __attribute__((deprecated))
#else
#define MBEDTLS_DEPRECATED
#endif
/**
* \brief This function starts a SHA-384 or SHA-512 checksum
* calculation.
*
* \deprecated Superseded by mbedtls_sha512_starts_ret() in 2.7.0
*
* \param ctx The SHA-512 context to initialize.
* \param is384 Determines which function to use.
* <ul><li>0: Use SHA-512.</li>
* <li>1: Use SHA-384.</li></ul>
*/
MBEDTLS_DEPRECATED void mbedtls_sha512_starts( mbedtls_sha512_context *ctx,
int is384 );
/**
* \brief This function feeds an input buffer into an ongoing
* SHA-512 checksum calculation.
*
* \deprecated Superseded by mbedtls_sha512_update_ret() in 2.7.0
*
* \param ctx The SHA-512 context.
* \param input The buffer holding the data.
* \param ilen The length of the input data.
*/
MBEDTLS_DEPRECATED void mbedtls_sha512_update( mbedtls_sha512_context *ctx,
const unsigned char *input,
size_t ilen );
/**
* \brief This function finishes the SHA-512 operation, and writes
* the result to the output buffer.
*
* \deprecated Superseded by mbedtls_sha512_finish_ret() in 2.7.0
*
* \param ctx The SHA-512 context.
* \param output The SHA-384 or SHA-512 checksum result.
*/
MBEDTLS_DEPRECATED void mbedtls_sha512_finish( mbedtls_sha512_context *ctx,
unsigned char output[64] );
/**
* \brief This function processes a single data block within
* the ongoing SHA-512 computation. This function is for
* internal use only.
*
* \deprecated Superseded by mbedtls_internal_sha512_process() in 2.7.0
*
* \param ctx The SHA-512 context.
* \param data The buffer holding one block of data.
*/
MBEDTLS_DEPRECATED void mbedtls_sha512_process( mbedtls_sha512_context *ctx,
const unsigned char data[128] );
#undef MBEDTLS_DEPRECATED
#endif /* !MBEDTLS_DEPRECATED_REMOVED */
#ifdef __cplusplus
}
#endif
#endif /* MBEDTLS_SHA512_ALT */
#endif /* sha512_alt.h */

View File

@ -0,0 +1,349 @@
/*
* Copyright (c) 2022, Nuvoton Technology Corporation
*
* 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/sha1.h"
#include "mbedtls/sha256.h"
#include "mbedtls/sha512.h"
#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)
#include "nu_bitutil.h"
#include "nu_timer.h"
#include "mbed_assert.h"
#include "mbed_error.h"
#include "crypto-misc.h"
#include <string.h>
/* SHA context for DMA */
static struct {
MBED_ALIGN(4)
uint8_t block_imd[NU_CRYPTO_SHA_MAXSIZE_DMABLOCKRUN_BYTES]; // Intermediate data block in DMA mode
uint32_t fbinfo_imd[NU_CRYPTO_SHA_MAXSIZE_FBINFO_WORDS]; // Intermediate feedback information in DMA cascade mode
const uint8_t *block_act; // Actual of above
uint32_t *fbinfo_act; // Actual of above
} dma_ctx_inst;
/* Manage SHA H/W
*
* We follow the rules below to manage SHA H/W to share among contexts:
* 1. Go DMA cascade mode to support context save & restore.
* 2. Initialize/un-initialize crypto H/W at first context init/last context free.
* 3. All code involving SHA H/W are in between crypto_sha_acquire()/crypto_sha_release().
* 4. Interrupt is enabled (SHA_ENABLE_INT()/SHA_DISABLE_INT()) only during real SHA H/W operation.
*/
void crypto_sha_init(crypto_sha_context *ctx, uint32_t type)
{
MBED_ASSERT(type == SHA_MODE_SHA1 ||
type == SHA_MODE_SHA256 ||
type == SHA_MODE_SHA512);
/* Clean SHA context */
crypto_zeroize(ctx, sizeof(*ctx));
/* SHA operation mode */
ctx->type = type;
ctx->opmode = type;
/* Mbed TLS error code for the SHA type */
switch (type) {
case SHA_MODE_SHA1:
ctx->digestsize = 20;
ctx->err_hw_accel = MBEDTLS_ERR_SHA1_HW_ACCEL_FAILED;
ctx->err_bad_input = MBEDTLS_ERR_SHA1_BAD_INPUT_DATA;
break;
case SHA_MODE_SHA256:
ctx->digestsize = 32;
ctx->err_hw_accel = MBEDTLS_ERR_SHA256_HW_ACCEL_FAILED;
ctx->err_bad_input = MBEDTLS_ERR_SHA256_BAD_INPUT_DATA;
break;
case SHA_MODE_SHA512:
ctx->digestsize = 64;
ctx->err_hw_accel = MBEDTLS_ERR_SHA512_HW_ACCEL_FAILED;
ctx->err_bad_input = MBEDTLS_ERR_SHA512_BAD_INPUT_DATA;
break;
default:
MBED_ASSERT(0);
}
/* Acquire ownership of SHA H/W */
crypto_sha_acquire();
/* SHA H/W DMA buffer has the following requirements:
* (1) Word-aligned buffer base address
* (2) Word-aligned buffer size
* (3) Located in 0x20000000-0x2FFFFFFF region */
if ((! crypto_dma_buff_compat(dma_ctx_inst.block_imd, sizeof(dma_ctx_inst.block_imd), 4)) ||
(! crypto_dma_buff_compat(dma_ctx_inst.fbinfo_imd, sizeof(dma_ctx_inst.fbinfo_imd), 4))) {
error("Buffer for SHA H/W DMA requires to be word-aligned and located in 0x20000000-0x2FFFFFFF region.");
}
/* Initialize crypto module */
crypto_init();
/* Release ownership of SHA H/W */
crypto_sha_release();
}
void crypto_sha_free(crypto_sha_context *ctx)
{
if (ctx == NULL) {
return;
}
/* Acquire ownership of SHA H/W */
crypto_sha_acquire();
/* Un-initialize crypto module */
crypto_uninit();
/* Release ownership of SHA H/W */
crypto_sha_release();
/* Clean SHA context */
crypto_zeroize(ctx, sizeof(*ctx));
}
int crypto_sha_starts(crypto_sha_context *ctx, int is224_384)
{
MBED_ASSERT(ctx != NULL);
/* NOTE: mbedtls may call mbedtls_shaXXX_starts multiple times and then call the ending mbedtls_shaXXX_finish. Guard from it. */
/* NOTE: In DMA cascade mode, re-configure SHA H/W instead of at start */
ctx->total = 0;
ctx->buffer_left = 0;
switch (ctx->type) {
case SHA_MODE_SHA1:
ctx->blocksize = 64;
ctx->blocksize_mask = 0x3F;
break;
case SHA_MODE_SHA256:
ctx->blocksize = 64;
ctx->blocksize_mask = 0x3F;
ctx->opmode = is224_384 ? SHA_MODE_SHA224 : SHA_MODE_SHA256;
ctx->digestsize = is224_384 ? 28 : 32;
break;
case SHA_MODE_SHA512:
ctx->blocksize = 128;
ctx->blocksize_mask = 0x7F;
ctx->opmode = is224_384 ? SHA_MODE_SHA384 : SHA_MODE_SHA512;
ctx->digestsize = is224_384 ? 48 : 64;
break;
default:
MBED_ASSERT(0);
}
ctx->is224_384 = is224_384;
return 0;
}
int crypto_sha_update(crypto_sha_context *ctx, const unsigned char *input, size_t ilen)
{
MBED_ASSERT(ctx != NULL);
if (ilen == 0) {
return 0;
}
MBED_ASSERT(input != NULL);
int rc = 0;
/* One complete block = above left + new input */
size_t fill = ctx->blocksize - ctx->buffer_left;
if (ctx->buffer_left && ilen >= fill) {
memcpy((void *) (ctx->buffer + ctx->buffer_left), input, fill);
input += fill;
ilen -= fill;
ctx->buffer_left += fill;
MBED_ASSERT(ctx->buffer_left == ctx->blocksize);
rc = crypto_sha_update_nobuf(ctx, ctx->buffer, ctx->buffer_left, (ctx->total == 0), 0);
if (rc != 0) {
return rc;
}
ctx->total += ctx->buffer_left;
ctx->buffer_left = 0;
}
/* Complete blocks in block runs */
while (ilen >= NU_CRYPTO_SHA_MAXSIZE_DMABLOCKRUN_BYTES) {
rc = crypto_sha_update_nobuf(ctx, input, NU_CRYPTO_SHA_MAXSIZE_DMABLOCKRUN_BYTES, (ctx->total == 0), 0);
if (rc != 0) {
return rc;
}
ctx->total += NU_CRYPTO_SHA_MAXSIZE_DMABLOCKRUN_BYTES;
input += NU_CRYPTO_SHA_MAXSIZE_DMABLOCKRUN_BYTES;
ilen -= NU_CRYPTO_SHA_MAXSIZE_DMABLOCKRUN_BYTES;
}
/* Complete blocks modulus block run */
fill = ilen - (ilen % ctx->blocksize);
MBED_ASSERT((fill % ctx->blocksize) == 0);
if (fill) {
rc = crypto_sha_update_nobuf(ctx, input, fill, (ctx->total == 0), 0);
if (rc != 0) {
return rc;
}
ctx->total += fill;
input += fill;
ilen -= fill;
}
/* Left incomplete block */
if (ilen > 0) {
MBED_ASSERT(ilen < ctx->blocksize);
fill = ilen;
memcpy((void *) (ctx->buffer + ctx->buffer_left), input, fill);
input += fill;
ilen -= fill;
ctx->buffer_left += fill;
}
MBED_ASSERT(ilen == 0);
return rc;
}
int crypto_sha_update_nobuf(crypto_sha_context *ctx, const unsigned char *input, size_t ilen, int isfirst, int islast)
{
MBED_ASSERT(ctx != NULL);
/* Accept only:
* 1. Last block which may be incomplete
* 2. Non-last block(s) which must be complete */
MBED_ASSERT(islast || (ilen % ctx->blocksize) == 0);
int rc = 0;
/* Acquire ownership of SHA H/W */
crypto_sha_acquire();
/* Enable SHA interrupt */
SHA_ENABLE_INT(CRPT);
/* Use intermediate buffer when incompatible with SHA H/W DMA buffer */
if (!crypto_dma_buff_compat(input, ilen, 1)) {
memcpy(dma_ctx_inst.block_imd, input, ilen);
dma_ctx_inst.block_act = dma_ctx_inst.block_imd;
} else {
dma_ctx_inst.block_act = input;
}
if (!crypto_dma_buff_compat(ctx->fbinfo, sizeof(ctx->fbinfo), 4)) {
memcpy(dma_ctx_inst.fbinfo_imd, ctx->fbinfo, sizeof(ctx->fbinfo));
dma_ctx_inst.fbinfo_act = dma_ctx_inst.fbinfo_imd;
} else {
dma_ctx_inst.fbinfo_act = ctx->fbinfo;
}
SHA_Open(CRPT, ctx->opmode, SHA_IN_SWAP, 0);
SHA_SetDMATransfer(CRPT, (uint32_t) dma_ctx_inst.block_act, ilen);
/* Address of feedback information input/output */
CRPT->HMAC_FBADDR = (uint32_t) dma_ctx_inst.fbinfo_act;
/* Continue above and re-configure further */
uint32_t hmac_ctl = CRPT->HMAC_CTL |
CRPT_HMAC_CTL_START_Msk | // Start SHA/HMAC engine
(isfirst ? CRPT_HMAC_CTL_DMAFIRST_Msk : 0) | // SHA/HMAC first block in cascade function
(islast ? CRPT_HMAC_CTL_DMALAST_Msk : 0) | // SHA/HMAC last block
CRPT_HMAC_CTL_DMACSCAD_Msk | // Enable SHA/HMAC engine DMA with cascade mode
CRPT_HMAC_CTL_DMAEN_Msk | // Enable SHA/HMAC engine DMA
(isfirst ? 0 : CRPT_HMAC_CTL_FBIN_Msk) | // Feedback input to SHA/HMAC via DMA automatically
// FBIN doesn't make sense for the first block, on which
// SHA H/W isn't fool-proof. Enable FBIN for the first block
// will crash SHA H/W.
(islast ? 0 : CRPT_HMAC_CTL_FBOUT_Msk) | // Feedback output from SHA/HMAC via DMA automatically
// FBOUT is unnecessary for the last block.
0;
crypto_sha_prestart();
CRPT->HMAC_CTL = hmac_ctl;
rc = crypto_sha_wait() ? 0 : ctx->err_hw_accel;
/* On using intermediate buffer, restore output feedback information */
if (rc == 0 &&
(uint32_t) ctx->fbinfo != (uint32_t) dma_ctx_inst.fbinfo_act) {
memcpy(ctx->fbinfo, dma_ctx_inst.fbinfo_act, sizeof(ctx->fbinfo));
}
/* Disable SHA interrupt */
SHA_DISABLE_INT(CRPT);
/* Release ownership of SHA H/W */
crypto_sha_release();
return rc;
}
int crypto_sha_finish(crypto_sha_context *ctx, unsigned char output[], size_t olen)
{
MBED_ASSERT(ctx != NULL);
MBED_ASSERT(output != NULL);
MBED_ASSERT(olen != 0 && olen == ctx->digestsize);
int rc = 0;
/* NOTE: Per real test, SHA H/W can support zero data, so we needn't
* special handling for it. */
rc = crypto_sha_update_nobuf(ctx, ctx->buffer, ctx->buffer_left, (ctx->total == 0), 1);
if (rc != 0) {
return rc;
}
ctx->total += ctx->buffer_left;
ctx->buffer_left = 0;
rc = crypto_sha_getdigest(output, ctx->digestsize);
if (rc != 0) {
return rc;
}
return rc;
}
int crypto_sha_getdigest(unsigned char output[], size_t olen)
{
MBED_ASSERT(output != NULL);
MBED_ASSERT(olen != 0 && (olen % 4) == 0);
uint32_t *in_pos = (uint32_t *) &CRPT->HMAC_DGST[0];
unsigned char *out_pos = output;
uint32_t rmn = olen;
while (rmn) {
uint32_t val = *in_pos ++;
nu_set32_be(out_pos, val);
out_pos += 4;
rmn -= 4;
}
return 0;
}
#endif /* MBEDTLS_SHA1_ALT || MBEDTLS_SHA256_ALT || MBEDTLS_SHA512_ALT */
#endif /* MBEDTLS_SHA1_C || MBEDTLS_SHA256_C || MBEDTLS_SHA512_C */

View File

@ -0,0 +1,144 @@
/*
* Copyright (c) 2022, Nuvoton Technology Corporation
*
* 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.
*/
#ifndef MBEDTLS_SHA_ALT_HW_H
#define MBEDTLS_SHA_ALT_HW_H
#if defined(MBEDTLS_SHA1_ALT) || defined(MBEDTLS_SHA256_ALT) || defined(MBEDTLS_SHA512_ALT)
#include <stddef.h>
#include <stdint.h>
#ifdef __cplusplus
extern "C" {
#endif
/**
* \brief Max size of SHA block in bytes
*
* SHA-160/224/256: 64 bytes
* SHA-384/512: 128 bytes
*
* \note Support SHA1/2 only, no SHA3
*/
#define NU_CRYPTO_SHA_MAXSIZE_BLOCK_BYTES 128
/**
* \brief Max size of SHA DMA block run in bytes
*
* \note DMA cascade mode requires block-aligned except for the last block.
* \note This also defines DMA intermediary buffer size.
*/
#define NU_CRYPTO_SHA_MAXSIZE_DMABLOCKRUN_BYTES \
(NU_CRYPTO_SHA_MAXSIZE_BLOCK_BYTES * 4)
/**
* \brief Max size of SHA feedback information in words, used in DMA cascade mode
*
* SHA1/2: 54 words
* SHA3: 88 words
*
* \note Support SHA1/2 only, no SHA3
* \note According to spec, reserve 54 words for SHA1/2. But per real
* test, SHA H/W will overwrite beyond 54 words. Workaround by
* reserving 88 words anyway.
*/
#define NU_CRYPTO_SHA_MAXSIZE_FBINFO_WORDS 88
/**
* \brief SHA context structure
*
* \note SHA type/opmode
* 1. For type, borrow from opmode defines and can only be SHA_MODE_SHA1/SHA256/SHA512.
* 2. Initialize opmode/digestsize dependent on type
* 3. For SHA_MODE_SHA256/512, opmode will change to SHA_MODE_SHA224/384
* when is224_384 is non-zero in the call to crypto_sha_starts().
* 4. Following above, for opmode being SHA_MODE_SHA224/384, change digestsize to 28/48
*/
typedef struct {
/* These fields will initialize at crypto_sha_init() */
uint32_t type; /*!< SHA type */
uint32_t opmode; /*!< SHA operation mode */
uint32_t digestsize; /*!< SHA digest size */
int err_hw_accel; /*!< Mbed TLS error code for the SHA type */
int err_bad_input; /*!< Mbed TLS error code for the SHA type */
/* These fields will initialize at crypto_sha_starts() */
uint32_t total; /*!< number of bytes processed */
union {
uint8_t buffer[NU_CRYPTO_SHA_MAXSIZE_BLOCK_BYTES]; /*!< data block being processed. Max of SHA-1/SHA-256/SHA-512 */
uint32_t buffer_u32[NU_CRYPTO_SHA_MAXSIZE_BLOCK_BYTES/4]; /*!< make buffer word aligned */
};
uint16_t buffer_left;
uint16_t blocksize; /*!< block size */
uint32_t blocksize_mask; /*!< block size mask */
int is224_384; /*!< 0 => SHA-256/SHA-512, else SHA-224/384 */
uint32_t fbinfo[NU_CRYPTO_SHA_MAXSIZE_FBINFO_WORDS]; /*!< feedback information in DMA cascade mode */
}
crypto_sha_context;
void crypto_sha_init(crypto_sha_context *ctx, uint32_t type);
void crypto_sha_free(crypto_sha_context *ctx);
int crypto_sha_starts(crypto_sha_context *ctx, int is224_384);
int crypto_sha_update(crypto_sha_context *ctx, const unsigned char *input, size_t ilen);
int crypto_sha_update_nobuf(crypto_sha_context *ctx, const unsigned char *input, size_t ilen, int isfirst, int islast);
int crypto_sha_finish(crypto_sha_context *ctx, unsigned char output[], size_t olen);
int crypto_sha_getdigest(unsigned char output[], size_t olen);
#if defined(MBEDTLS_SHA1_ALT)
void mbedtls_sha1_hw_init( crypto_sha_context *ctx );
void mbedtls_sha1_hw_free( crypto_sha_context *ctx );
int mbedtls_sha1_hw_starts( crypto_sha_context *ctx );
int mbedtls_sha1_hw_update( crypto_sha_context *ctx, const unsigned char *input, size_t ilen );
int mbedtls_sha1_hw_finish( crypto_sha_context *ctx, unsigned char output[20] );
int mbedtls_sha1_hw_process( crypto_sha_context *ctx, const unsigned char data[64] );
#endif /* MBEDTLS_SHA1_ALT */
#if defined(MBEDTLS_SHA256_ALT)
void mbedtls_sha256_hw_init( crypto_sha_context *ctx );
void mbedtls_sha256_hw_free( crypto_sha_context *ctx );
int mbedtls_sha256_hw_starts( crypto_sha_context *ctx, int is224 );
int mbedtls_sha256_hw_update( crypto_sha_context *ctx, const unsigned char *input,
size_t ilen );
int mbedtls_sha256_hw_finish( crypto_sha_context *ctx, unsigned char output[32] );
int mbedtls_sha256_hw_process( crypto_sha_context *ctx, const unsigned char data[64] );
#endif /* MBEDTLS_SHA256_ALT */
#if defined(MBEDTLS_SHA512_ALT)
void mbedtls_sha512_hw_init( crypto_sha_context *ctx );
void mbedtls_sha512_hw_free( crypto_sha_context *ctx );
int mbedtls_sha512_hw_starts( crypto_sha_context *ctx, int is384 );
int mbedtls_sha512_hw_update( crypto_sha_context *ctx, const unsigned char *input,
size_t ilen );
int mbedtls_sha512_hw_finish( crypto_sha_context *ctx, unsigned char output[64] );
int mbedtls_sha512_hw_process( crypto_sha_context *ctx, const unsigned char data[128] );
#endif /* MBEDTLS_SHA512_ALT */
#ifdef __cplusplus
}
#endif
#endif /* MBEDTLS_SHA1_ALT || MBEDTLS_SHA256_ALT || MBEDTLS_SHA512_ALT */
#endif /* sha_alt.h */

View File

@ -14,6 +14,8 @@ target_sources(mbed-m460
analogin_api.c
analogout_api.c
crypto/crypto-misc.cpp
device/startup_M460.c
device/system_M460.c
device/StdDriver/src/m460_acmp.c
@ -83,6 +85,7 @@ target_sources(mbed-m460
target_include_directories(mbed-m460
INTERFACE
.
crypto
device
device/Reg
device/StdDriver/inc

View File

@ -0,0 +1,399 @@
/*
* Copyright (c) 2022, Nuvoton Technology Corporation
*
* 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 "cmsis.h"
#include "mbed_assert.h"
#include "mbed_atomic.h"
#include "mbed_critical.h"
#include "mbed_error.h"
#include <limits.h>
#include "nu_modutil.h"
#include "nu_bitutil.h"
#include "crypto-misc.h"
#include "platform/SingletonPtr.h"
#include "platform/PlatformMutex.h"
/* Consideration for choosing proper synchronization mechanism
*
* We choose mutex to synchronize access to crypto ACC. We can guarantee:
* (1) No deadlock
* We just lock mutex for a short sequence of operations rather than the whole lifetime
* of crypto context.
* (2) No priority inversion
* Mutex supports priority inheritance and it is enabled.
*/
/* Mutex for crypto PRNG ACC management */
static SingletonPtr<PlatformMutex> crypto_prng_mutex;
/* Mutex for crypto AES ACC management */
static SingletonPtr<PlatformMutex> crypto_aes_mutex;
/* Mutex for crypto SHA ACC management */
static SingletonPtr<PlatformMutex> crypto_sha_mutex;
/* Mutex for crypto ECC ACC management */
static SingletonPtr<PlatformMutex> crypto_ecc_mutex;
/* Mutex for crypto RSA ACC management */
static SingletonPtr<PlatformMutex> crypto_rsa_mutex;
/* Crypto init counter. Crypto keeps active as it is non-zero. */
static uint16_t crypto_init_counter = 0U;
/* Crypto done flags */
#define NU_CRYPTO_DONE_OK BIT0 // Done with OK
#define NU_CRYPTO_DONE_ERR BIT1 // Done with error
/* Track if PRNG H/W operation is done */
static volatile uint16_t crypto_prng_done;
/* Track if AES H/W operation is done */
static volatile uint16_t crypto_aes_done;
/* Track if SHA H/W operation is done */
static volatile uint16_t crypto_sha_done;
/* Track if ECC H/W operation is done */
static volatile uint16_t crypto_ecc_done;
/* Track if RSA H/W operation is done */
static volatile uint16_t crypto_rsa_done;
static void crypto_submodule_prestart(volatile uint16_t *submodule_done);
static bool crypto_submodule_wait(volatile uint16_t *submodule_done);
/* As crypto init counter changes from 0 to 1:
*
* 1. Enable crypto clock
* 2. Enable crypto interrupt
*/
void crypto_init(void)
{
core_util_critical_section_enter();
if (crypto_init_counter == USHRT_MAX) {
core_util_critical_section_exit();
error("Crypto clock enable counter would overflow (> USHRT_MAX)");
}
core_util_atomic_incr_u16(&crypto_init_counter, 1);
if (crypto_init_counter == 1) {
SYS_UnlockReg(); // Unlock protected register
CLK_EnableModuleClock(CRPT_MODULE);
SYS_ResetModule(CRPT_RST);
SYS_LockReg(); // Lock protected register
NVIC_EnableIRQ(CRPT_IRQn);
}
core_util_critical_section_exit();
}
/* As crypto init counter changes from 1 to 0:
*
* 1. Disable crypto interrupt
* 2. Disable crypto clock
*/
void crypto_uninit(void)
{
core_util_critical_section_enter();
if (crypto_init_counter == 0) {
core_util_critical_section_exit();
error("Crypto clock enable counter would underflow (< 0)");
}
core_util_atomic_decr_u16(&crypto_init_counter, 1);
if (crypto_init_counter == 0) {
NVIC_DisableIRQ(CRPT_IRQn);
SYS_UnlockReg(); // Unlock protected register
CLK_DisableModuleClock(CRPT_MODULE);
SYS_LockReg(); // Lock protected register
}
core_util_critical_section_exit();
}
/* Implementation that should never be optimized out by the compiler */
void crypto_zeroize(void *v, size_t n)
{
volatile unsigned char *p = (volatile unsigned char*) v;
while (n--) {
*p++ = 0;
}
}
/* Implementation that should never be optimized out by the compiler */
void crypto_zeroize32(uint32_t *v, size_t n)
{
volatile uint32_t *p = (volatile uint32_t*) v;
while (n--) {
*p++ = 0;
}
}
void crypto_prng_acquire(void)
{
/* Don't check return code of Mutex::lock(void)
*
* This function treats RTOS errors as fatal system errors, so it can only return osOK.
* Use of the return value is deprecated, as the return is expected to become void in
* the future.
*/
crypto_prng_mutex->lock();
}
void crypto_prng_release(void)
{
crypto_prng_mutex->unlock();
}
void crypto_aes_acquire(void)
{
/* Don't check return code of Mutex::lock(void) */
crypto_aes_mutex->lock();
}
void crypto_aes_release(void)
{
crypto_aes_mutex->unlock();
}
void crypto_sha_acquire(void)
{
/* Don't check return code of Mutex::lock(void) */
crypto_sha_mutex->lock();
}
void crypto_sha_release(void)
{
crypto_sha_mutex->unlock();
}
void crypto_ecc_acquire(void)
{
/* Don't check return code of Mutex::lock(void) */
crypto_ecc_mutex->lock();
}
void crypto_ecc_release(void)
{
crypto_ecc_mutex->unlock();
}
void crypto_rsa_acquire(void)
{
/* Don't check return code of Mutex::lock(void) */
crypto_rsa_mutex->lock();
}
void crypto_rsa_release(void)
{
crypto_rsa_mutex->unlock();
}
void crypto_prng_prestart(void)
{
crypto_submodule_prestart(&crypto_prng_done);
}
bool crypto_prng_wait(void)
{
return crypto_submodule_wait(&crypto_prng_done);
}
void crypto_aes_prestart(void)
{
crypto_submodule_prestart(&crypto_aes_done);
}
bool crypto_aes_wait(void)
{
return crypto_submodule_wait(&crypto_aes_done);
}
void crypto_sha_prestart(void)
{
crypto_submodule_prestart(&crypto_sha_done);
}
bool crypto_sha_wait(void)
{
return crypto_submodule_wait(&crypto_sha_done);
}
void crypto_ecc_prestart(void)
{
crypto_submodule_prestart(&crypto_ecc_done);
}
bool crypto_ecc_wait(void)
{
return crypto_submodule_wait(&crypto_ecc_done);
}
void crypto_rsa_prestart(void)
{
crypto_submodule_prestart(&crypto_rsa_done);
}
bool crypto_rsa_wait(void)
{
return crypto_submodule_wait(&crypto_rsa_done);
}
bool crypto_dma_buff_compat(const void *buff, size_t buff_size, size_t size_aligned_to)
{
uint32_t buff_ = (uint32_t) buff;
return (((buff_ & 0x03) == 0) && /* Word-aligned buffer base address */
((buff_size & (size_aligned_to - 1)) == 0) && /* Crypto submodule dependent buffer size alignment */
(((buff_ >> 28) == 0x2) && (buff_size <= (0x30000000 - buff_)))); /* 0x20000000-0x2FFFFFFF */
}
/* Overlap cases
*
* 1. in_buff in front of out_buff:
*
* in in_end
* | |
* ||||||||||||||||
* ||||||||||||||||
* | |
* out out_end
*
* 2. out_buff in front of in_buff:
*
* in in_end
* | |
* ||||||||||||||||
* ||||||||||||||||
* | |
* out out_end
*/
bool crypto_dma_buffs_overlap(const void *in_buff, size_t in_buff_size, const void *out_buff, size_t out_buff_size)
{
uint32_t in = (uint32_t) in_buff;
uint32_t in_end = in + in_buff_size;
uint32_t out = (uint32_t) out_buff;
uint32_t out_end = out + out_buff_size;
bool overlap = (in <= out && out < in_end) || (out <= in && in < out_end);
return overlap;
}
static void crypto_submodule_prestart(volatile uint16_t *submodule_done)
{
*submodule_done = 0;
/* Ensure memory accesses above are completed before DMA is started
*
* Replacing __DSB() with __DMB() is also OK in this case.
*
* Refer to "multi-master systems" section with DMA in:
* https://static.docs.arm.com/dai0321/a/DAI0321A_programming_guide_memory_barriers_for_m_profile.pdf
*/
__DSB();
}
static bool crypto_submodule_wait(volatile uint16_t *submodule_done)
{
while (! *submodule_done);
/* Ensure while loop above and subsequent code are not reordered */
__DSB();
if ((*submodule_done & NU_CRYPTO_DONE_OK)) {
/* Done with OK */
return true;
} else if ((*submodule_done & NU_CRYPTO_DONE_ERR)) {
/* Done with error */
return false;
}
return false;
}
/* Crypto interrupt handler */
extern "C" void CRPT_IRQHandler()
{
uint32_t intsts;
/* PRNG */
if ((intsts = PRNG_GET_INT_FLAG(CRPT)) != 0) {
/* Check interrupt flags */
if (intsts & CRPT_INTSTS_PRNGIF_Msk) {
/* Done with OK */
crypto_prng_done |= NU_CRYPTO_DONE_OK;
} else if (intsts & CRPT_INTSTS_PRNGEIF_Msk) {
/* Done with error */
crypto_prng_done |= NU_CRYPTO_DONE_ERR;
}
/* Clear interrupt flag */
PRNG_CLR_INT_FLAG(CRPT);
}
/* AES */
if ((intsts = AES_GET_INT_FLAG(CRPT)) != 0) {
/* Check interrupt flags */
if (intsts & CRPT_INTSTS_AESIF_Msk) {
/* Done with OK */
crypto_aes_done |= NU_CRYPTO_DONE_OK;
} else if (intsts & CRPT_INTSTS_AESEIF_Msk) {
/* Done with error */
crypto_aes_done |= NU_CRYPTO_DONE_ERR;
}
/* Clear interrupt flag */
AES_CLR_INT_FLAG(CRPT);
}
/* SHA */
if ((intsts = SHA_GET_INT_FLAG(CRPT)) != 0) {
/* Check interrupt flags */
if (intsts & CRPT_INTSTS_HMACIF_Msk) {
/* Done with OK */
crypto_sha_done |= NU_CRYPTO_DONE_OK;
} else if (intsts & CRPT_INTSTS_HMACEIF_Msk) {
/* Done with error */
crypto_sha_done |= NU_CRYPTO_DONE_ERR;
}
/* Clear interrupt flag */
SHA_CLR_INT_FLAG(CRPT);
}
/* ECC */
if ((intsts = ECC_GET_INT_FLAG(CRPT)) != 0) {
/* Check interrupt flags */
if (intsts & CRPT_INTSTS_ECCIF_Msk) {
/* Done with OK */
crypto_ecc_done |= NU_CRYPTO_DONE_OK;
} else if (intsts & CRPT_INTSTS_ECCEIF_Msk) {
/* Done with error */
crypto_ecc_done |= NU_CRYPTO_DONE_ERR;
}
/* Clear interrupt flag */
ECC_CLR_INT_FLAG(CRPT);
}
/* RSA */
if ((intsts = RSA_GET_INT_FLAG(CRPT)) != 0) {
/* Check interrupt flags */
if (intsts & CRPT_INTSTS_RSAIF_Msk) {
/* Done with OK */
crypto_rsa_done |= NU_CRYPTO_DONE_OK;
} else if (intsts & CRPT_INTSTS_RSAEIF_Msk) {
/* Done with error */
crypto_rsa_done |= NU_CRYPTO_DONE_ERR;
}
/* Clear interrupt flag */
RSA_CLR_INT_FLAG(CRPT);
}
}

View File

@ -0,0 +1,98 @@
/*
* Copyright (c) 2022, Nuvoton Technology Corporation
*
* 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.
*/
#ifndef MBED_CRYPTO_MISC_H
#define MBED_CRYPTO_MISC_H
#include <stdbool.h>
#ifdef __cplusplus
extern "C" {
#endif
/* Init/Uninit crypto module */
void crypto_init(void);
void crypto_uninit(void);
/* Clear buffer to zero
* Implementation that should never be optimized out by the compiler */
void crypto_zeroize(void *v, size_t n);
void crypto_zeroize32(uint32_t *v, size_t n);
/* Acquire/release ownership of crypto sub-module
*
* \note "acquire" is blocking until ownership is acquired
*
* \note "acquire"/"release" must be paired.
*
* \note Recursive "acquire" is allowed because the underlying synchronization
* primitive mutex supports it.
*/
void crypto_prng_acquire(void);
void crypto_prng_release(void);
void crypto_aes_acquire(void);
void crypto_aes_release(void);
void crypto_sha_acquire(void);
void crypto_sha_release(void);
void crypto_ecc_acquire(void);
void crypto_ecc_release(void);
void crypto_rsa_acquire(void);
void crypto_rsa_release(void);
/* Flow control between crypto/xxx start and crypto/xxx ISR
*
* crypto_xxx_prestart/crypto_xxx_wait encapsulate control flow between crypto/xxx start and crypto/xxx ISR.
*
* crypto_xxx_prestart will also address synchronization issue with memory barrier instruction.
*
* On finish, return of crypto_xxx_wait indicates success or not:
* true if successful
* false if failed
*
* Example: Start AES H/W and wait for its finish
* crypto_aes_prestart();
* AES_Start();
* crypto_aes_wait();
*/
void crypto_prng_prestart(void);
bool crypto_prng_wait(void);
void crypto_aes_prestart(void);
bool crypto_aes_wait(void);
void crypto_sha_prestart(void);
bool crypto_sha_wait(void);
void crypto_ecc_prestart(void);
bool crypto_ecc_wait(void);
void crypto_rsa_prestart(void);
bool crypto_rsa_wait(void);
/* Check if buffer can be used for crypto DMA. It has the following requirements:
* (1) Word-aligned buffer base address
* (2) Crypto submodule (AES, SHA, etc.) dependent buffer size alignment. Must be 2 power.
* (3) Located in 0x20000000-0x2FFFFFFF region
*/
bool crypto_dma_buff_compat(const void *buff, size_t buff_size, size_t size_aligned_to);
/* Check if input/output buffers are overlapped */
bool crypto_dma_buffs_overlap(const void *in_buff, size_t in_buff_size, const void *out_buff, size_t out_buff_size);
#ifdef __cplusplus
}
#endif
#endif

View File

@ -7503,6 +7503,9 @@
"inherits": [
"MCU_M460"
],
"macros_add": [
"MBEDTLS_CONFIG_HW_SUPPORT"
],
"supported_form_factors": [
"ARDUINO_UNO"
],