mirror of https://github.com/ARMmbed/mbed-os.git
[EFR32] Adding hardware acceleration for mbed TLS
Initial check-in of hardware acceleration support on EFR32 for mbed TLS (AES, SHA and ECC).pull/3157/head
parent
035c08dcfd
commit
c0301b15d2
|
@ -20,3 +20,21 @@
|
|||
#if defined(DEVICE_TRNG)
|
||||
#define MBEDTLS_ENTROPY_HARDWARE_ALT
|
||||
#endif
|
||||
|
||||
#if defined(DEVICE_AES)
|
||||
#define MBEDTLS_AES_ALT
|
||||
#endif
|
||||
|
||||
#if defined(DEVICE_SHA)
|
||||
#define MBEDTLS_SHA1_ALT
|
||||
#define MBEDTLS_SHA256_ALT
|
||||
#endif
|
||||
|
||||
#if defined(DEVICE_ECC)
|
||||
#define MBEDTLS_ECP_DEVICE_ALT
|
||||
#define MBEDTLS_ECP_DOUBLE_JAC_ALT
|
||||
#define MBEDTLS_ECP_DEVICE_ADD_MIXED_ALT
|
||||
#define MBEDTLS_ECP_NORMALIZE_JAC_ALT
|
||||
#define MBEDTLS_ECP_NORMALIZE_JAC_MANY_ALT
|
||||
#define MBEDTLS_MPI_MODULAR_DIVISION_ALT
|
||||
#endif
|
|
@ -0,0 +1,67 @@
|
|||
================ Revision history ============================================
|
||||
5.0.0:
|
||||
- Added basic support for Series 1 Configuration 2 devices (EFR32MG12, etc.)
|
||||
- Bugfix: The asynchronous callback of mbedtls_ccm_auth_decrypt and
|
||||
mbedtls_cmac_verify_tag reported incorrect error codes when authentication
|
||||
verification fails.
|
||||
- Bugfix: In asynchronous mode, the output buffer of mbedtls_ccm_auth_decrypt
|
||||
was not properly cleared when authentication verification fails.
|
||||
|
||||
4.4.0:
|
||||
- Added CMAC support with a Silicon Labs specific API (slcl_cmac.c).
|
||||
CMAC is not covered by the standard mbedtls interface.
|
||||
The CMAC plugin use the CRYPTO hardware module for acceleration.
|
||||
- Added CCM plugin (slcl_ccm.c) with CRYPTO hardware acceleration and
|
||||
optimized CCM functions for BLE (mbedtls_ccm_encrypt_and_tag_ble and
|
||||
mbedtls_ccm_auth_decrypt_ble).
|
||||
- Added CRYPTO preemption support in the following plugins:
|
||||
slcl_aes.c, slcl_ccm.c, slcl_cmac.c, slcl_ecp.c, slcl_sha1.c and
|
||||
slcl_sha256.c.
|
||||
- Added support for alternative CRYPTO critical region implementations
|
||||
(for the CRYPTO preemption support).
|
||||
- Added support for asynchronous (non-blocking) API calls in the following
|
||||
plugins: slcl_aes.c, slcl_ccm.c and slcl_cmac.c.
|
||||
- Added support for moving data with BUFC and DMA (to/from CRYPTO registers)
|
||||
in the following plugins: slcl_aes.c and slcl_ccm.c.
|
||||
- In order to support error codes in new SIlicon Labs specific APIs
|
||||
extended error code interface of the standard mbedtls by using the full
|
||||
32-bit integer range, see details in mbedtls_ecode.h.
|
||||
- Added support for AES module on EFM32GG (Giant Gecko) in slcl_aes.c.
|
||||
Compile with MBEDTLS_SLCL_PLUGINS in order to enable EFM32GG support.
|
||||
|
||||
4.3.1:
|
||||
- No changes.
|
||||
|
||||
4.3.0:
|
||||
- Updated to mbedtls-2.2.0 including EC JPAKE support.
|
||||
- sl_aes.c:
|
||||
In mbedtls_aes_setkey_enc and mbedtls_aes_setkey_dec change return value to
|
||||
MBEDTLS_ERR_AES_INVALID_KEY_LENGTH when key length is not 128 or 256 bits.
|
||||
In mbedtls_aes_crypt_cfb128 added support for data lengths not dividable
|
||||
with 16 (AES block size), by using software (no crypto) implementation.
|
||||
In mbedtls_aes_crypt_cfb8 return errors from mbedtls_aes_crypt_ecb.
|
||||
- library/bignum.c:
|
||||
In mbedtls_mpi_sub_abs and mbedtls_mpi_mul_mpi copy to and use local
|
||||
variables only if necessary.
|
||||
- library/ecp.c:
|
||||
In ecp_modp call halResetWatchdog #ifdef MBEDTLS_HAVE_HAL_WATCHDOG_TIMER
|
||||
for Thread stack integration.
|
||||
- library/aes.c:
|
||||
In mbedtls_aes_self_test allow failure when setting 192 bit keys which is
|
||||
not supported by CRYPTO.
|
||||
- library/gcm.c:
|
||||
In mbedtls_gcm_self_test allow failure when setting 192 bit keys which is
|
||||
not supported by CRYPTO.
|
||||
- library/x509.c and x509_crt.c:
|
||||
Excluded code when MBEDTLS_FS_IO is defined which is not supported on
|
||||
Silicon Labs devices.
|
||||
- Added sl_timing.c and timing_alt.h in order to compiler modules depending on
|
||||
MBEDTLS_TIMING_C. The user should #define MBEDTLS_TIMING_ALT in order to
|
||||
compile.
|
||||
|
||||
4.2.1:
|
||||
- No changes.
|
||||
|
||||
4.2.0:
|
||||
- First version including support for mbedtls 2.0.0 and CRYPTO acceleration of
|
||||
AES (sl_aes.c), ECC (sl_ecp.c), SHA1 (sl_sha1.c) and SHA256 (sl_sha256.c).
|
|
@ -0,0 +1,34 @@
|
|||
README for mbed TLS CRYPTO hardware acceleraton plugins from Silicon Labs
|
||||
=========================================================================
|
||||
|
||||
Introduction
|
||||
------------
|
||||
This folder include alternative implementations (plugins) from Silicon Labs for some of the mbed TLS library functions, including AES, CCM, CMAC, ECC (ECP, ECDH, ECDSA, ECJPAKE), SHA1 and SHA256. The plugins use the AES and CRYPTO hardware modules to accelerate the standard mbed TLS library functions that are implemented in C. The CRYPTO hardware module is incorporated in the new generations of MCUs from SIlicon Labs and the AES hardware module is incorporated in the classic EFM32 MCUs from Silicon Labs.
|
||||
|
||||
Please refer to the mbedTLS section of the Gecko SDK documentation for more information on using mbed TLS on Silicon Labs devices.
|
||||
|
||||
Configuration
|
||||
-------------
|
||||
The configuration macros of the CRYPTO hardware acceleraton plugins from Silicon Labs are documented in configs/config-sl-crypto-all-acceleration.h. The configs/config-sl-crypto-all-acceleration.h enables acceleration of all plugins from Silicon Labs and provides a full mbedtls configuration which can be used to get started with application development. Please refer to the Gecko SDK documentation for more information on using mbed TLS on Silicon Labs devices. Please refer to the main README file (in the mbedtls base folder) and `include/mbedtls/config.h` for general mbed TLS configuration. Below is a summary of the configuration macros of the CRYPTO hardware acceleraton plugins:
|
||||
|
||||
#define MBEDTLS_AES_ALT /* Includes CRYPTO accelerated implementation of the aes.h interface. */
|
||||
#define MBEDTLS_SHA1_ALT /* Includes CRYPTO accelerated implementation of the sha1.h interface. */
|
||||
#define MBEDTLS_SHA256_ALT /* Includes CRYPTO accelerated implementation of the sha256.h interface. */
|
||||
#define MBEDTLS_ECP_DEVICE_ALT /* Includes CRYPTO accelerated implementation of some functions in ecp.c. */
|
||||
#define MBEDTLS_ECP_DOUBLE_JAC_ALT /* Includes CRYPTO accelerated implementation of the ecp_double_jac function. */
|
||||
#define MBEDTLS_ECP_DEVICE_ADD_MIXED_ALT /* Includes CRYPTO accelerated implementation of the ecp_add_mixed function. */
|
||||
#define MBEDTLS_ECP_NORMALIZE_JAC_ALT /* Includes CRYPTO accelerated implementation of the ecp_normalize_jac function. */
|
||||
#define MBEDTLS_ECP_NORMALIZE_JAC_MANY_ALT /* Includes CRYPTO accelerated implementation of the ecp_normalize_jac_many function. */
|
||||
#define MBEDTLS_MPI_MODULAR_DIVISION_ALT /* Includes the CRYPTO accelerated function mbedtls_mpi_div_mod which can serve as a replacement of the regular mbedtls_mpi_inv_mod function of mbedtls. */
|
||||
#define MBEDTLS_SLCL_PLUGINS /* Enables group 2 plugins (slcl_xxx.c) including support for CRYPTO preemption, asynchronous API support, DMA and BUFC I/O modes, and support for classic EFM32 devices with AES module, EFM32GG, etc. */
|
||||
#define MBEDTLS_CRYPTO_DEVICE_PREEMPTION /* Include CRYPTO preemption */
|
||||
#define MBEDTLS_CRYPTO_CRITICAL_REGION_ALT /* Include alternative implementation of CRYPTO critical regions (of CRYPTO preemption support). */
|
||||
#define MBEDTLS_INCLUDE_ASYNCH_API /* Include asynchronous API support */
|
||||
#define MBEDTLS_INCLUDE_IO_MODE_DMA /* Include support for moving data to/from CRYPTO with DMA */
|
||||
|
||||
Compiling
|
||||
---------
|
||||
Please refer to the example programs in the EFM32 SDK for project files examples for various IDE/toolchains.
|
||||
I.e:
|
||||
kits/SLSTK3401A_EFM32PG/examples/mbedtls_aescrypt
|
||||
kits/SLSTK3401A_EFM32PG/examples/mbedtls_ecdsa
|
|
@ -0,0 +1 @@
|
|||
*~
|
|
@ -0,0 +1,397 @@
|
|||
/**
|
||||
* \file aes_alt.h
|
||||
*
|
||||
* \brief AES block cipher
|
||||
*
|
||||
* Copyright (C) 2015-2016, Silicon Labs, http://www.silabs.com
|
||||
* 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_AES_ALT_H
|
||||
#define MBEDTLS_AES_ALT_H
|
||||
|
||||
#if !defined(MBEDTLS_CONFIG_FILE)
|
||||
#include "config.h"
|
||||
#else
|
||||
#include MBEDTLS_CONFIG_FILE
|
||||
#endif
|
||||
|
||||
/***************************************************************************//**
|
||||
* \addtogroup sl_crypto
|
||||
* \{
|
||||
******************************************************************************/
|
||||
|
||||
/***************************************************************************//**
|
||||
* \addtogroup sl_crypto_aes AES block cipher
|
||||
* \brief CRYPTO hardware accelerated AES block cipher.
|
||||
* \{
|
||||
******************************************************************************/
|
||||
|
||||
#if defined( MBEDTLS_SLCL_PLUGINS )
|
||||
#include "aesdrv.h"
|
||||
#include "sl_crypto.h"
|
||||
#endif
|
||||
|
||||
#include <stddef.h>
|
||||
#include <stdint.h>
|
||||
|
||||
#define MBEDTLS_AES_ENCRYPT 1
|
||||
#define MBEDTLS_AES_DECRYPT 0
|
||||
|
||||
/* Silicon Labs specific error codes: */
|
||||
#define MBEDTLS_ERR_AES_NOT_SUPPORTED ((int)MBEDTLS_ECODE_AESDRV_NOT_SUPPORTED)
|
||||
#define MBEDTLS_ERR_AES_AUTHENTICATION_FAILED ((int)MBEDTLS_ECODE_AESDRV_AUTHENTICATION_FAILED)
|
||||
#define MBEDTLS_ERR_AES_OUT_OF_RESOURCES ((int)MBEDTLS_ECODE_AESDRV_OUT_OF_RESOURCES)
|
||||
#define MBEDTLS_ERR_AES_INVALID_PARAM ((int)MBEDTLS_ECODE_AESDRV_INVALID_PARAM)
|
||||
|
||||
#if defined(MBEDTLS_AES_ALT)
|
||||
/* SiliconLabs CRYPTO hardware acceleration implementation */
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#if defined( MBEDTLS_SLCL_PLUGINS )
|
||||
#if defined( MBEDTLS_INCLUDE_ASYNCH_API )
|
||||
|
||||
/**
|
||||
* \brief AES asynchronous context structure
|
||||
*/
|
||||
typedef struct
|
||||
{
|
||||
AESDRV_BlockCipherAsynchContext_t aesdrv_asynch_ctx;/*!< AESDRV asynchronous
|
||||
context */
|
||||
}
|
||||
mbedtls_aes_asynch_context;
|
||||
|
||||
#endif /* #if defined( MBEDTLS_INCLUDE_ASYNCH_API ) */
|
||||
#endif /* #if defined( MBEDTLS_SLCL_PLUGINS ) */
|
||||
|
||||
/**
|
||||
* \brief AES context structure
|
||||
*/
|
||||
typedef struct
|
||||
{
|
||||
#if defined( MBEDTLS_SLCL_PLUGINS )
|
||||
AESDRV_Context_t aesdrv_ctx; /*!< AESDRV context */
|
||||
mbedtls_device_io_mode io_mode; /*!< I/O mode */
|
||||
mbedtls_device_io_mode_specific io_mode_specific; /*!< I/O mode specific
|
||||
data */
|
||||
#endif
|
||||
unsigned int keybits; /*!< size of key */
|
||||
uint32_t key[8]; /*!< AES key 128 or 256 bits */
|
||||
}
|
||||
mbedtls_aes_context;
|
||||
|
||||
/**
|
||||
* \brief Initialize AES context
|
||||
*
|
||||
* \param ctx AES context to be initialized
|
||||
*/
|
||||
void mbedtls_aes_init( mbedtls_aes_context *ctx );
|
||||
|
||||
/**
|
||||
* \brief Clear AES context
|
||||
*
|
||||
* \param ctx AES context to be cleared
|
||||
*/
|
||||
void mbedtls_aes_free( mbedtls_aes_context *ctx );
|
||||
|
||||
#if defined( MBEDTLS_SLCL_PLUGINS )
|
||||
/**
|
||||
* \brief
|
||||
* Set the device instance of an AES context.
|
||||
*
|
||||
* \details
|
||||
* This function sets the AES/CRYPTO device instance of an AES context.
|
||||
* Subsequent calls to AES API functions with this context will use the
|
||||
* new AES/CRYPTO device instance.
|
||||
*
|
||||
* \param[in] ctx
|
||||
* AES device context.
|
||||
*
|
||||
* \param[in] devno
|
||||
* AES/CRYPTO hardware device instance to use.
|
||||
*
|
||||
* \return
|
||||
* 0 if success. Error code if failure, see \ref aes.h.
|
||||
******************************************************************************/
|
||||
int mbedtls_aes_set_device_instance(mbedtls_aes_context *ctx,
|
||||
unsigned int devno);
|
||||
|
||||
#if defined( MBEDTLS_INCLUDE_ASYNCH_API )
|
||||
/**
|
||||
* \brief Set an AES context in asynchronous mode.
|
||||
*
|
||||
* \details
|
||||
* This function enables or disables asynchronous (non-blocking) mode of an
|
||||
* AES context. In order to enable, the user must set the
|
||||
* @p asynch_ctx parameter to point to an asynchronous aes context structure
|
||||
* @ref mbedtls_aes_asynch_context. Subsequent calls to the AES API
|
||||
* functions with the specified context will behave asynchronously, i.e.
|
||||
* initiate the hardware to execute the operation and return as soon as
|
||||
* possible. The user may specify a callback function by setting the
|
||||
* @p asynch_callback parameter which will called when the operation has
|
||||
* completed.
|
||||
* In order to disable, the user must set the @p asynch_context parameter
|
||||
* to NULL. All subsequent calls to AES API functions with the specified
|
||||
* context will block until the corresponding operation has completed, and
|
||||
* then return.
|
||||
*
|
||||
* \param ctx AES context
|
||||
* \param asynch_ctx AES asynchronous context structure
|
||||
* \param asynch_callback Asynchronous callback
|
||||
* \param user_arg User specific argument which will be
|
||||
* sent to callback.
|
||||
*
|
||||
* \return 0 if successful, or error code
|
||||
*/
|
||||
int mbedtls_aes_set_asynch( mbedtls_aes_context *ctx,
|
||||
mbedtls_aes_asynch_context *asynch_ctx,
|
||||
mbedtls_asynch_callback asynch_callback,
|
||||
void* user_arg );
|
||||
|
||||
#endif /* #if defined( MBEDTLS_INCLUDE_ASYNCH_API ) */
|
||||
|
||||
/**
|
||||
* \brief
|
||||
* Set the device I/O mode of an AES context.
|
||||
*
|
||||
* \details
|
||||
* This function sets the device data I/O mode of an AES context. The data
|
||||
* can be moved by Core CPU, DMA or BUFC between CRYPTO and RAM.
|
||||
*
|
||||
* \param[in] ctx
|
||||
* AES device context.
|
||||
*
|
||||
* \param[in] mode
|
||||
* I/O mode (Core CPU, DMA or BUFC).
|
||||
*
|
||||
* \param[in] specific
|
||||
* I/O mode specific configuration \ref mbedtls_device_io_mode_specific.
|
||||
*
|
||||
* \warning
|
||||
* If BUFC is selected (\ref MBEDTLS_DEVICE_IO_MODE_BUFC), this function does
|
||||
* not enable the BUFC clock and does not do any global BUFC initialization.
|
||||
* I.e. the user is responsible for performing BUFC initialization prior to
|
||||
* calling this function.
|
||||
* If DMA is selected (\ref MBEDTLS_INCLUDE_IO_MODE_DMA), this function
|
||||
* performs full DMA driver initialization by calling DMADRV_Init
|
||||
* (non-destructive) and allocates DMA channel resources to be used by CCM.
|
||||
*
|
||||
* \return
|
||||
* 0 if success. Error code if failure, see \ref aes.h.
|
||||
******************************************************************************/
|
||||
int mbedtls_aes_set_device_io_mode( mbedtls_aes_context *ctx,
|
||||
mbedtls_device_io_mode mode,
|
||||
mbedtls_device_io_mode_specific *specific );
|
||||
|
||||
#endif
|
||||
|
||||
/**
|
||||
* \brief AES key schedule (encryption)
|
||||
*
|
||||
* \param ctx AES context to be initialized
|
||||
* \param key encryption key
|
||||
* \param keybits must be 128, 192 or 256
|
||||
*
|
||||
* \return 0 if successful, or MBEDTLS_ERR_AES_INVALID_KEY_LENGTH
|
||||
*/
|
||||
int mbedtls_aes_setkey_enc( mbedtls_aes_context *ctx, const unsigned char *key,
|
||||
unsigned int keybits );
|
||||
|
||||
/**
|
||||
* \brief AES key schedule (decryption)
|
||||
*
|
||||
* \param ctx AES context to be initialized
|
||||
* \param key decryption key
|
||||
* \param keybits must be 128, 192 or 256
|
||||
*
|
||||
* \return 0 if successful, or MBEDTLS_ERR_AES_INVALID_KEY_LENGTH
|
||||
*/
|
||||
int mbedtls_aes_setkey_dec( mbedtls_aes_context *ctx, const unsigned char *key,
|
||||
unsigned int keybits );
|
||||
|
||||
/**
|
||||
* \brief AES-ECB block encryption/decryption
|
||||
*
|
||||
* \details
|
||||
* TODO: doc asynch mode output buffer not ready until completion
|
||||
*
|
||||
* \param ctx AES context
|
||||
* \param mode MBEDTLS_AES_ENCRYPT or MBEDTLS_AES_DECRYPT
|
||||
* \param input 16-byte input block
|
||||
* \param output 16-byte output block
|
||||
*
|
||||
* \return 0 if successful
|
||||
*/
|
||||
int mbedtls_aes_crypt_ecb( mbedtls_aes_context *ctx,
|
||||
int mode,
|
||||
const unsigned char input[16],
|
||||
unsigned char output[16] );
|
||||
|
||||
#if defined(MBEDTLS_CIPHER_MODE_CBC)
|
||||
/**
|
||||
* \brief AES-CBC buffer encryption/decryption
|
||||
* Length should be a multiple of the block
|
||||
* size (16 bytes)
|
||||
*
|
||||
* \note Upon exit, the content of the IV is updated so that you can
|
||||
* call the function same function again on the following
|
||||
* block(s) of data and get the same result as if it was
|
||||
* encrypted in one call. This allows a "streaming" usage.
|
||||
* If on the other hand you need to retain the contents of the
|
||||
* IV, you should either save it manually or use the cipher
|
||||
* module instead.
|
||||
*
|
||||
* \param ctx AES context
|
||||
* \param mode MBEDTLS_AES_ENCRYPT or MBEDTLS_AES_DECRYPT
|
||||
* \param length length of the input data
|
||||
* \param iv initialization vector (updated after use)
|
||||
* \param input buffer holding the input data
|
||||
* \param output buffer holding the output data
|
||||
*
|
||||
* \return 0 if successful, or MBEDTLS_ERR_AES_INVALID_INPUT_LENGTH
|
||||
*/
|
||||
int mbedtls_aes_crypt_cbc( mbedtls_aes_context *ctx,
|
||||
int mode,
|
||||
size_t length,
|
||||
unsigned char iv[16],
|
||||
const unsigned char *input,
|
||||
unsigned char *output );
|
||||
#endif /* MBEDTLS_CIPHER_MODE_CBC */
|
||||
|
||||
#if defined(MBEDTLS_CIPHER_MODE_CFB)
|
||||
/**
|
||||
* \brief AES-CFB128 buffer encryption/decryption.
|
||||
*
|
||||
* Note: Due to the nature of CFB you should use the same key schedule for
|
||||
* both encryption and decryption. So a context initialized with
|
||||
* mbedtls_aes_setkey_enc() for both MBEDTLS_AES_ENCRYPT and MBEDTLS_AES_DECRYPT.
|
||||
*
|
||||
* \note Upon exit, the content of the IV is updated so that you can
|
||||
* call the function same function again on the following
|
||||
* block(s) of data and get the same result as if it was
|
||||
* encrypted in one call. This allows a "streaming" usage.
|
||||
* If on the other hand you need to retain the contents of the
|
||||
* IV, you should either save it manually or use the cipher
|
||||
* module instead.
|
||||
*
|
||||
* \param ctx AES context
|
||||
* \param mode MBEDTLS_AES_ENCRYPT or MBEDTLS_AES_DECRYPT
|
||||
* \param length length of the input data
|
||||
* \param iv_off offset in IV (updated after use)
|
||||
* \param iv initialization vector (updated after use)
|
||||
* \param input buffer holding the input data
|
||||
* \param output buffer holding the output data
|
||||
*
|
||||
* \return 0 if successful
|
||||
*/
|
||||
int mbedtls_aes_crypt_cfb128( mbedtls_aes_context *ctx,
|
||||
int mode,
|
||||
size_t length,
|
||||
size_t *iv_off,
|
||||
unsigned char iv[16],
|
||||
const unsigned char *input,
|
||||
unsigned char *output );
|
||||
|
||||
/**
|
||||
* \brief AES-CFB8 buffer encryption/decryption.
|
||||
*
|
||||
* Note: Due to the nature of CFB you should use the same key schedule for
|
||||
* both encryption and decryption. So a context initialized with
|
||||
* mbedtls_aes_setkey_enc() for both MBEDTLS_AES_ENCRYPT and MBEDTLS_AES_DECRYPT.
|
||||
*
|
||||
* \note Upon exit, the content of the IV is updated so that you can
|
||||
* call the function same function again on the following
|
||||
* block(s) of data and get the same result as if it was
|
||||
* encrypted in one call. This allows a "streaming" usage.
|
||||
* If on the other hand you need to retain the contents of the
|
||||
* IV, you should either save it manually or use the cipher
|
||||
* module instead.
|
||||
*
|
||||
* \param ctx AES context
|
||||
* \param mode MBEDTLS_AES_ENCRYPT or MBEDTLS_AES_DECRYPT
|
||||
* \param length length of the input data
|
||||
* \param iv initialization vector (updated after use)
|
||||
* \param input buffer holding the input data
|
||||
* \param output buffer holding the output data
|
||||
*
|
||||
* \return 0 if successful
|
||||
*/
|
||||
int mbedtls_aes_crypt_cfb8( mbedtls_aes_context *ctx,
|
||||
int mode,
|
||||
size_t length,
|
||||
unsigned char iv[16],
|
||||
const unsigned char *input,
|
||||
unsigned char *output );
|
||||
#endif /*MBEDTLS_CIPHER_MODE_CFB */
|
||||
|
||||
#if defined(MBEDTLS_CIPHER_MODE_CTR)
|
||||
/**
|
||||
* \brief AES-CTR buffer encryption/decryption
|
||||
*
|
||||
* Warning: You have to keep the maximum use of your counter in mind!
|
||||
*
|
||||
* Note: Due to the nature of CTR you should use the same key schedule for
|
||||
* both encryption and decryption. So a context initialized with
|
||||
* mbedtls_aes_setkey_enc() for both MBEDTLS_AES_ENCRYPT and MBEDTLS_AES_DECRYPT.
|
||||
*
|
||||
* \param ctx AES context
|
||||
* \param length The length of the data
|
||||
* \param nc_off The offset in the current stream_block (for resuming
|
||||
* within current cipher stream). The offset pointer to
|
||||
* should be 0 at the start of a stream.
|
||||
* \param nonce_counter The 128-bit nonce and counter.
|
||||
* \param stream_block The saved stream-block for resuming. Is overwritten
|
||||
* by the function.
|
||||
* \param input The input data stream
|
||||
* \param output The output data stream
|
||||
*
|
||||
* \return 0 if successful
|
||||
*/
|
||||
int mbedtls_aes_crypt_ctr( mbedtls_aes_context *ctx,
|
||||
size_t length,
|
||||
size_t *nc_off,
|
||||
unsigned char nonce_counter[16],
|
||||
unsigned char stream_block[16],
|
||||
const unsigned char *input,
|
||||
unsigned char *output );
|
||||
#endif /* MBEDTLS_CIPHER_MODE_CTR */
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* MBEDTLS_AES_ALT */
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/**
|
||||
* \brief Checkup routine
|
||||
*
|
||||
* \return 0 if successful, or 1 if the test failed
|
||||
*/
|
||||
int mbedtls_aes_self_test( int verbose );
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
/** \} (end addtogroup sl_crypto) */
|
||||
/** \} (end addtogroup sl_crypto_aes) */
|
||||
|
||||
#endif /* MBEDTLS_AES_ALT_H */
|
|
@ -0,0 +1,213 @@
|
|||
/**
|
||||
* \file aesdrv.h
|
||||
*
|
||||
* \brief Definitions for AES based ciphers with CRYPTO hw acceleration
|
||||
*
|
||||
* Copyright (C) 2016, Silicon Labs, http://www.silabs.com
|
||||
* 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 __SILICON_LABS_AESDRV_H
|
||||
#define __SILICON_LABS_AESDRV_H
|
||||
|
||||
#if !defined(MBEDTLS_CONFIG_FILE)
|
||||
#include "config.h"
|
||||
#else
|
||||
#include MBEDTLS_CONFIG_FILE
|
||||
#endif
|
||||
|
||||
#include "em_device.h"
|
||||
#if ( defined(CRYPTO_COUNT) && (CRYPTO_COUNT > 0) ) || \
|
||||
( defined(AES_COUNT) && (AES_COUNT > 0) )
|
||||
|
||||
#include "mbedtls_ecode.h"
|
||||
#include <stdint.h>
|
||||
#include <stdbool.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/*******************************************************************************
|
||||
******************************* ERROR CODES **********************************
|
||||
******************************************************************************/
|
||||
|
||||
#define MBEDTLS_ECODE_AESDRV_NOT_SUPPORTED (MBEDTLS_ECODE_AESDRV_BASE | 0x1)
|
||||
#define MBEDTLS_ECODE_AESDRV_AUTHENTICATION_FAILED (MBEDTLS_ECODE_AESDRV_BASE | 0x2)
|
||||
#define MBEDTLS_ECODE_AESDRV_OUT_OF_RESOURCES (MBEDTLS_ECODE_AESDRV_BASE | 0x3)
|
||||
#define MBEDTLS_ECODE_AESDRV_INVALID_PARAM (MBEDTLS_ECODE_AESDRV_BASE | 0x4)
|
||||
|
||||
/*******************************************************************************
|
||||
******************************* TYPEDEFS **********************************
|
||||
******************************************************************************/
|
||||
|
||||
/** Enum defines which data I/O mode to use for moving data to/from the
|
||||
AES/CRYPTO hardware module. */
|
||||
typedef enum
|
||||
{
|
||||
aesdrvIoModeCore, /** Core CPU moves data to/from the data registers. */
|
||||
|
||||
aesdrvIoModeBufc, /** Buffer Controller moves data to/from the CRYPTO
|
||||
data registers. */
|
||||
|
||||
aesdrvIoModeDma /** DMA moves data to/from the CRYPTO data registers. */
|
||||
} AESDRV_IoMode_t;
|
||||
|
||||
/** DMA I/O mode specific configuration structure. */
|
||||
typedef struct
|
||||
{
|
||||
unsigned int dmaChIn; /**< DMA input channel. Allocated by AESDRV. */
|
||||
unsigned int dmaChOut; /**< DMA output channel. Allocated by AESDRV. */
|
||||
} AESDRV_DmaConfig_t;
|
||||
|
||||
#if defined(BUFC_PRESENT)
|
||||
/** BUFC I/O mode specific configuration structure. */
|
||||
typedef struct
|
||||
{
|
||||
uint8_t bufId; /**< BUFC buffer id. Must be setup by user. */
|
||||
} AESDRV_BufcConfig_t;
|
||||
#endif
|
||||
|
||||
/** Data I/O mode specific configuration structure. */
|
||||
typedef union
|
||||
{
|
||||
AESDRV_DmaConfig_t dmaConfig;
|
||||
#if defined(BUFC_PRESENT)
|
||||
AESDRV_BufcConfig_t bufcConfig;
|
||||
#endif
|
||||
} AESDRV_IoModeSpecific_t;
|
||||
|
||||
/** Prototype of counter callback function provided by user. */
|
||||
typedef void (*AESDRV_CtrCallback_t)(uint8_t *ctr);
|
||||
|
||||
#if defined(MBEDTLS_INCLUDE_ASYNCH_API)
|
||||
|
||||
/***************************************************************************//**
|
||||
* @brief
|
||||
* AESDRV asynchronous (non-blocking) operation completion callback function.
|
||||
*
|
||||
* @details
|
||||
* The callback function is called when an asynchronous (non-blocking)
|
||||
* AES operation has completed.
|
||||
*
|
||||
* @param[in] result
|
||||
* The result of the AES operation.
|
||||
*
|
||||
* @param[in] userArgument
|
||||
* Optional user defined argument supplied when starting the asynchronous
|
||||
* AES operation.
|
||||
******************************************************************************/
|
||||
typedef void (*AESDRV_AsynchCallback_t)(int result, void* userArgument);
|
||||
|
||||
/** AESDRV cipher modes, used to specify type of asynchronous context. */
|
||||
typedef enum
|
||||
{
|
||||
cipherModeNone,
|
||||
cipherModeBlockCipher, /**< Basic AES block cipher modes (CBC, CFB etc.) */
|
||||
cipherModeCcm, /**< CCM and CCM* - Counter Mode with CBC-MAC */
|
||||
cipherModeCcmBle, /**< CCM optimized for BLE. */
|
||||
cipherModeCmac, /**< Cipher-based Message Authentication Code -
|
||||
variation of CBC-MAC, equivalent to OMAC1 */
|
||||
cipherModeGcm /**< Galois/Counter mode including message
|
||||
authentication code (GMAC).*/
|
||||
} AESDRV_CipherMode_t;
|
||||
|
||||
/** AESDRV Context structures.*/
|
||||
|
||||
/** Context structure for asynchronous basic AES block cipher operations. */
|
||||
typedef struct
|
||||
{
|
||||
unsigned int remainingBlocks;
|
||||
uint32_t* pBlockIn;
|
||||
uint32_t* pBlockOut;
|
||||
uint8_t* pInitialVector;
|
||||
AESDRV_AsynchCallback_t asynchCallback;
|
||||
void* asynchCallbackArgument;
|
||||
} AESDRV_BlockCipherAsynchContext_t;
|
||||
|
||||
/** Context structure for asynchronous CCM(*) and GCM operations. */
|
||||
typedef struct
|
||||
{
|
||||
const uint8_t* pHdr;
|
||||
const uint8_t* pDataInput;
|
||||
uint8_t* pDataOutput;
|
||||
uint32_t la;
|
||||
uint32_t lm;
|
||||
uint32_t hdrLength;
|
||||
uint32_t dataLength;
|
||||
uint8_t* pAuthTag;
|
||||
uint8_t authTagLength;
|
||||
bool encryptingHeader;
|
||||
bool encrypt;
|
||||
AESDRV_AsynchCallback_t asynchCallback;
|
||||
void* asynchCallbackArgument;
|
||||
} AESDRV_CCM_AsynchContext_t, AESDRV_GCM_AsynchContext_t;
|
||||
|
||||
/** Context structure for asynchronous CMAC operations. */
|
||||
typedef struct
|
||||
{
|
||||
uint32_t* dataPointer;
|
||||
uint32_t dataBlocks;
|
||||
uint32_t lastBlock[4];
|
||||
uint8_t* digest;
|
||||
uint16_t digestLengthBits;
|
||||
bool encrypt;
|
||||
AESDRV_AsynchCallback_t asynchCallback;
|
||||
void* asynchCallbackArgument;
|
||||
} AESDRV_CMAC_AsynchContext_t;
|
||||
|
||||
#endif /* #if defined(MBEDTLS_INCLUDE_ASYNCH_API) */
|
||||
|
||||
#if ( defined(CRYPTO_COUNT) && (CRYPTO_COUNT > 0) )
|
||||
#include "cryptodrv.h"
|
||||
|
||||
/* Main AESDRV context structure. */
|
||||
typedef struct
|
||||
{
|
||||
CRYPTODRV_Context_t cryptodrvContext; /**< CRYPTO driver context */
|
||||
AESDRV_IoMode_t ioMode; /**< Data I/O mode. */
|
||||
AESDRV_IoModeSpecific_t ioModeSpecific; /**< Data I/O mode specific
|
||||
config. */
|
||||
bool authTagOptimize; /**< Enable/disable optimized
|
||||
handling of authentication
|
||||
tag in CCM/GCM. Tag
|
||||
optimization expects tag size
|
||||
0,4,8,12 or 16 bytes.*/
|
||||
#if defined(MBEDTLS_INCLUDE_ASYNCH_API)
|
||||
|
||||
AESDRV_CipherMode_t cipherMode; /**< Asynch mode */
|
||||
void* pAsynchContext; /**< Asynch context */
|
||||
|
||||
#endif /* #if defined(MBEDTLS_INCLUDE_ASYNCH_API) */
|
||||
|
||||
} AESDRV_Context_t;
|
||||
|
||||
#elif ( defined(AES_COUNT) && (AES_COUNT > 0) )
|
||||
|
||||
typedef struct
|
||||
{
|
||||
uint32_t ccmCounter[4]; /**< CCM counter */
|
||||
} AESDRV_Context_t;
|
||||
|
||||
#endif
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* #if ( defined(CRYPTO_COUNT) && (CRYPTO_COUNT > 0) ) || \
|
||||
( defined(AES_COUNT) && (AES_COUNT > 0) ) */
|
||||
|
||||
#endif /* __SILICON_LABS_AESDRV_H */
|
|
@ -0,0 +1,313 @@
|
|||
/**
|
||||
* \file ccm_alt.h
|
||||
*
|
||||
* \brief Counter with CBC-MAC (CCM) for 128-bit block ciphers
|
||||
*
|
||||
* Copyright (C) 2016, Silicon Labs, http://www.silabs.com
|
||||
* 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_CCM_ALT_H
|
||||
#define MBEDTLS_CCM_ALT_H
|
||||
|
||||
#if !defined(MBEDTLS_CONFIG_FILE)
|
||||
#include "config.h"
|
||||
#else
|
||||
#include MBEDTLS_CONFIG_FILE
|
||||
#endif
|
||||
|
||||
/***************************************************************************//**
|
||||
* \addtogroup sl_crypto
|
||||
* \{
|
||||
******************************************************************************/
|
||||
|
||||
/***************************************************************************//**
|
||||
* \addtogroup sl_crypto_ccm CBC-MAC (CCM) for 128-bit block ciphers
|
||||
* \brief CRYPTO hardware accelerated counter with CBC-MAC (CCM) for 128-bit block ciphers.
|
||||
* \{
|
||||
******************************************************************************/
|
||||
|
||||
#if defined( MBEDTLS_CCM_ALT )
|
||||
/* SiliconLabs CRYPTO hardware acceleration implementation */
|
||||
|
||||
#include "aesdrv.h"
|
||||
#include "sl_crypto.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#if defined( MBEDTLS_INCLUDE_ASYNCH_API )
|
||||
/**
|
||||
* \brief CCM asynchronous context structure
|
||||
*/
|
||||
typedef struct
|
||||
{
|
||||
AESDRV_CCM_AsynchContext_t aesdrv_asynch_ctx; /*!< AESDRV CCM asynchronous
|
||||
context */
|
||||
}
|
||||
mbedtls_ccm_asynch_context;
|
||||
#endif /* #if defined( MBEDTLS_INCLUDE_ASYNCH_API ) */
|
||||
|
||||
/**
|
||||
* \brief CCM context structure
|
||||
*/
|
||||
typedef struct
|
||||
{
|
||||
AESDRV_Context_t aesdrv_ctx; /*!< AESDRV context */
|
||||
unsigned int keybits; /*!< size of key */
|
||||
uint32_t key[8]; /*!< AES key 128 or 256 bits */
|
||||
mbedtls_device_io_mode io_mode; /*!< I/O mode */
|
||||
mbedtls_device_io_mode_specific io_mode_specific; /*!< IO mode specific
|
||||
data. */
|
||||
}
|
||||
mbedtls_ccm_context;
|
||||
|
||||
/**
|
||||
* \brief Initialize CCM context (just makes references valid)
|
||||
* Makes the context ready for mbedtls_ccm_setkey() or
|
||||
* mbedtls_ccm_free().
|
||||
*
|
||||
* \param ctx CCM context to initialize
|
||||
*/
|
||||
void mbedtls_ccm_init( mbedtls_ccm_context *ctx );
|
||||
|
||||
/**
|
||||
* \brief
|
||||
* Set the device instance of an CCM context.
|
||||
*
|
||||
* \details
|
||||
* This function sets the AES/CRYPTO device instance of an CCM context.
|
||||
* Subsequent calls to CCM API functions with this context will use the
|
||||
* new AES/CRYPTO device instance.
|
||||
*
|
||||
* \param[in] ctx
|
||||
* CCM device context.
|
||||
*
|
||||
* \param[in] devno
|
||||
* AES/CRYPTO hardware device instance to use.
|
||||
*
|
||||
* \return
|
||||
* 0 if success. Error code if failure, see \ref ccm.h.
|
||||
******************************************************************************/
|
||||
int mbedtls_ccm_set_device_instance(mbedtls_ccm_context* ctx,
|
||||
unsigned int devno);
|
||||
|
||||
/**
|
||||
* \brief
|
||||
* Set the device I/O mode of an CCM context.
|
||||
*
|
||||
* \details
|
||||
* This function sets the device data I/O mode of an CCM context. The data
|
||||
* can be moved by Core CPU, DMA or BUFC between CRYPTO and RAM.
|
||||
*
|
||||
* \param[in] ctx
|
||||
* CCM device context.
|
||||
*
|
||||
* \param[in] mode
|
||||
* I/O mode (Core CPU, DMA or BUFC).
|
||||
*
|
||||
* \param[in] specific
|
||||
* I/O mode specific configuration \ref mbedtls_device_io_mode_specific.
|
||||
*
|
||||
* \warning
|
||||
* If BUFC is selected (\ref MBEDTLS_DEVICE_IO_MODE_BUFC), this function does
|
||||
* not enable the BUFC clock and does not do any global BUFC initialization.
|
||||
* I.e. the user is responsible for performing BUFC initialization prior to
|
||||
* calling this function.
|
||||
* If DMA is selected (\ref MBEDTLS_INCLUDE_IO_MODE_DMA), this function
|
||||
* performs full DMA driver initialization by calling DMADRV_Init
|
||||
* (non-destructive) and allocates DMA channel resources to be used by CCM.
|
||||
*
|
||||
* \return
|
||||
* 0 if success. Error code if failure, see \ref ccm.h.
|
||||
******************************************************************************/
|
||||
int mbedtls_ccm_set_device_io_mode
|
||||
(
|
||||
mbedtls_ccm_context* ctx,
|
||||
mbedtls_device_io_mode mode,
|
||||
mbedtls_device_io_mode_specific* specific
|
||||
);
|
||||
|
||||
/**
|
||||
* \brief CCM initialization (encryption and decryption)
|
||||
*
|
||||
* \param ctx CCM context to be initialized
|
||||
* \param cipher cipher to use (a 128-bit block cipher)
|
||||
* \param key encryption key
|
||||
* \param keybits key size in bits (must be acceptable by the cipher)
|
||||
*
|
||||
* \return 0 if successful, or a cipher specific error code
|
||||
*/
|
||||
int mbedtls_ccm_setkey( mbedtls_ccm_context *ctx,
|
||||
mbedtls_cipher_id_t cipher,
|
||||
const unsigned char *key,
|
||||
unsigned int keybits );
|
||||
|
||||
#if defined( MBEDTLS_INCLUDE_ASYNCH_API )
|
||||
|
||||
/**
|
||||
* \brief Set an CCM context in asynchronous mode.
|
||||
*
|
||||
* \details
|
||||
* This function enables or disables asynchronous (non-blocking) mode of an
|
||||
* CCM context. In order to enable, the user must set the
|
||||
* @p asynch_ctx parameter to point to an asynchronous ccm context structure
|
||||
* @ref mbedtls_ccm_asynch_context. Subsequent calls to the CCM API
|
||||
* functions with the specified context will behave asynchronously, i.e.
|
||||
* initiate the hardware to execute the operation and return as soon as
|
||||
* possible. The user may specify a callback function by setting the
|
||||
* @p asynch_callback parameter which will called when the operation has
|
||||
* completed.
|
||||
* In order to disable, the user must set the @p asynch_context parameter
|
||||
* to NULL. All subsequent calls to CCM API functions with the specified
|
||||
* context will block until the corresponding operation has completed, and
|
||||
* then return.
|
||||
*
|
||||
* \param ctx CCM context
|
||||
* \param asynch_ctx CCM asynchronous context structure
|
||||
* \param asynch_callback Asynchronous callback
|
||||
* \param user_arg User specific argument which will be
|
||||
* sent to callback.
|
||||
*
|
||||
* \return 0 if successful, or error code
|
||||
*/
|
||||
int mbedtls_ccm_set_asynch( mbedtls_ccm_context *ctx,
|
||||
mbedtls_ccm_asynch_context *asynch_ctx,
|
||||
mbedtls_asynch_callback asynch_callback,
|
||||
void* user_arg );
|
||||
|
||||
#endif /* #if defined( MBEDTLS_INCLUDE_ASYNCH_API ) */
|
||||
|
||||
/**
|
||||
* \brief Free a CCM context and underlying cipher sub-context
|
||||
*
|
||||
* \param ctx CCM context to free
|
||||
*/
|
||||
void mbedtls_ccm_free( mbedtls_ccm_context *ctx );
|
||||
|
||||
/**
|
||||
* \brief CCM buffer encryption
|
||||
*
|
||||
* \param ctx CCM context
|
||||
* \param length length of the input data in bytes
|
||||
* \param iv nonce (initialization vector)
|
||||
* \param iv_len length of IV in bytes
|
||||
* must be 2, 3, 4, 5, 6, 7 or 8
|
||||
* \param add additional data
|
||||
* \param add_len length of additional data in bytes
|
||||
* must be less than 2^16 - 2^8
|
||||
* \param input buffer holding the input data
|
||||
* \param output buffer for holding the output data
|
||||
* must be at least 'length' bytes wide
|
||||
* \param tag buffer for holding the tag
|
||||
* \param tag_len length of the tag to generate in bytes
|
||||
* must be 4, 6, 8, 10, 14 or 16
|
||||
*
|
||||
* \note The tag is written to a separate buffer. To get the tag
|
||||
* concatenated with the output as in the CCM spec, use
|
||||
* tag = output + length and make sure the output buffer is
|
||||
* at least length + tag_len wide.
|
||||
*
|
||||
* \return 0 if successful
|
||||
*/
|
||||
int mbedtls_ccm_encrypt_and_tag( mbedtls_ccm_context *ctx, size_t length,
|
||||
const unsigned char *iv, size_t iv_len,
|
||||
const unsigned char *add, size_t add_len,
|
||||
const unsigned char *input, unsigned char *output,
|
||||
unsigned char *tag, size_t tag_len );
|
||||
|
||||
/**
|
||||
* \brief CCM buffer authenticated decryption
|
||||
*
|
||||
* \param ctx CCM context
|
||||
* \param length length of the input data
|
||||
* \param iv initialization vector
|
||||
* \param iv_len length of IV
|
||||
* \param add additional data
|
||||
* \param add_len length of additional data
|
||||
* \param input buffer holding the input data
|
||||
* \param output buffer for holding the output data
|
||||
* \param tag buffer holding the tag
|
||||
* \param tag_len length of the tag
|
||||
*
|
||||
* \return 0 if successful and authenticated,
|
||||
* MBEDTLS_ERR_CCM_AUTH_FAILED if tag does not match
|
||||
*/
|
||||
int mbedtls_ccm_auth_decrypt( mbedtls_ccm_context *ctx, size_t length,
|
||||
const unsigned char *iv, size_t iv_len,
|
||||
const unsigned char *add, size_t add_len,
|
||||
const unsigned char *input, unsigned char *output,
|
||||
const unsigned char *tag, size_t tag_len );
|
||||
|
||||
/**
|
||||
* \brief CCM buffer encryption optimized for BLE
|
||||
*
|
||||
* \param ctx CCM context
|
||||
* \param data Input/output buffer of payload data of BLE packet
|
||||
* \param length length of input data
|
||||
* \param iv nonce (initialization vector)
|
||||
* must be 13 bytes
|
||||
* \param header header of BLE packet (1 byte)
|
||||
* \param tag buffer where the BLE packet tag (4 bytes) will be written
|
||||
*
|
||||
* \return 0 if successful
|
||||
*/
|
||||
int mbedtls_ccm_encrypt_and_tag_ble( mbedtls_ccm_context *ctx,
|
||||
unsigned char *data,
|
||||
size_t length,
|
||||
const unsigned char *iv,
|
||||
unsigned char header,
|
||||
unsigned char *tag );
|
||||
|
||||
/**
|
||||
* \brief CCM buffer authenticated decryption optimized for BLE
|
||||
*
|
||||
* \param ctx CCM context
|
||||
* \param data Input/output buffer of payload data of BLE packet
|
||||
* \param length length of input data
|
||||
* \param iv nonce (initialization vector)
|
||||
* must be 13 bytes
|
||||
* \param header header of BLE packet (1 byte)
|
||||
* \param tag authentication tag of BLE packet (4 bytes)
|
||||
*
|
||||
* \return 0 if successful and authenticated,
|
||||
* MBEDTLS_ERR_CCM_AUTH_FAILED if tag does not match payload
|
||||
*/
|
||||
int mbedtls_ccm_auth_decrypt_ble( mbedtls_ccm_context *ctx,
|
||||
unsigned char *data,
|
||||
size_t length,
|
||||
const unsigned char *iv,
|
||||
unsigned char header,
|
||||
unsigned char *tag );
|
||||
|
||||
#if defined(MBEDTLS_SELF_TEST) && defined(MBEDTLS_AES_C)
|
||||
/**
|
||||
* \brief Checkup routine
|
||||
*
|
||||
* \return 0 if successful, or 1 if the test failed
|
||||
*/
|
||||
int mbedtls_ccm_self_test( int verbose );
|
||||
#endif /* MBEDTLS_SELF_TEST && MBEDTLS_AES_C */
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* #if defined( MBEDTLS_CCM_ALT ) */
|
||||
|
||||
/** \} (end addtogroup sl_crypto) */
|
||||
/** \} (end addtogroup sl_crypto_ccm) */
|
||||
|
||||
#endif /* MBEDTLS_CCM_ALT_H */
|
|
@ -0,0 +1,47 @@
|
|||
/**
|
||||
* \file cmac.h
|
||||
*
|
||||
* \brief CMAC cipher mode based on 128 bit AES.
|
||||
*
|
||||
* Copyright (C) 2016, Silicon Labs, 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.
|
||||
*
|
||||
* This file is part of the mbedTLS plugins package from Silicon Labs
|
||||
*/
|
||||
#ifndef MBEDTLS_CMAC_H
|
||||
#define MBEDTLS_CMAC_H
|
||||
|
||||
/*
|
||||
* This file implements CMAC (Cipher-based Message Authentication Code)
|
||||
* cipher mode encryption/decryption based on 128 bit AES.
|
||||
* For a general description please see
|
||||
* https://en.wikipedia.org/wiki/CMAC
|
||||
* or for detailed specification see
|
||||
* http://csrc.nist.gov/publications/nistpubs/800-38B/SP_800-38B.pdf
|
||||
* http://dl.acm.org/citation.cfm?id=2206249
|
||||
*/
|
||||
|
||||
#if defined( MBEDTLS_CMAC_ALT )
|
||||
/* SiliconLabs CRYPTO hardware acceleration implementation */
|
||||
|
||||
#include "cmac_alt.h"
|
||||
|
||||
#else /* #if defined( MBEDTLS_CMAC_ALT ) */
|
||||
|
||||
// Regular implementation does not exist yet.
|
||||
|
||||
#endif /* #if defined( MBEDTLS_CMAC_ALT ) */
|
||||
|
||||
#endif /* MBEDTLS_CMAC_H */
|
|
@ -0,0 +1,231 @@
|
|||
/**
|
||||
* \file cmac_alt.h
|
||||
*
|
||||
* \brief CMAC cipher mode based on 128 bit AES.
|
||||
*
|
||||
* Copyright (C) 2016, Silicon Labs, 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.
|
||||
*/
|
||||
#ifndef MBEDTLS_CMAC_ALT_H
|
||||
#define MBEDTLS_CMAC_ALT_H
|
||||
|
||||
#if !defined(MBEDTLS_CONFIG_FILE)
|
||||
#include "config.h"
|
||||
#else
|
||||
#include MBEDTLS_CONFIG_FILE
|
||||
#endif
|
||||
|
||||
/***************************************************************************//**
|
||||
* \addtogroup sl_crypto
|
||||
* \{
|
||||
******************************************************************************/
|
||||
|
||||
/***************************************************************************//**
|
||||
* \addtogroup sl_crypto_cmac CMAC cipher mode based on 128 bit AES
|
||||
* \brief CRYPTO hardware accelerated CMAC (Cipher-based Message Authentication Code)
|
||||
* \details
|
||||
* Encryption and decryption based on 128-bit AES.
|
||||
* For a general description please see
|
||||
* https://en.wikipedia.org/wiki/CMAC
|
||||
* or for detailed specification see
|
||||
* http://csrc.nist.gov/publications/nistpubs/800-38B/SP_800-38B.pdf
|
||||
* http://dl.acm.org/citation.cfm?id=2206249
|
||||
* \{
|
||||
******************************************************************************/
|
||||
|
||||
#if defined( MBEDTLS_CMAC_ALT )
|
||||
/* SiliconLabs CRYPTO hardware acceleration implementation */
|
||||
|
||||
#include "aesdrv.h"
|
||||
#include "sl_crypto.h"
|
||||
#include "cipher.h"
|
||||
#include <stddef.h>
|
||||
|
||||
#define MBEDTLS_ERR_CMAC_BAD_INPUT ((int)MBEDTLS_ERR_CMAC_BASE | 0x01)
|
||||
#define MBEDTLS_ERR_CMAC_AUTH_FAILED ((int)MBEDTLS_ERR_CMAC_BASE | 0x02)
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#if defined( MBEDTLS_INCLUDE_ASYNCH_API )
|
||||
/**
|
||||
* \brief CMAC asynchronous context structure
|
||||
*/
|
||||
typedef struct
|
||||
{
|
||||
AESDRV_CMAC_AsynchContext_t aesdrv_asynch_ctx; /*!< AESDRV CMAC asynchronous
|
||||
context */
|
||||
}
|
||||
mbedtls_cmac_asynch_context;
|
||||
#endif /* #if defined( MBEDTLS_INCLUDE_ASYNCH_API ) */
|
||||
|
||||
/**
|
||||
* \brief CMAC context structure
|
||||
*/
|
||||
typedef struct
|
||||
{
|
||||
AESDRV_Context_t aesdrv_ctx; /*!< AESDRV context */
|
||||
unsigned int keybits; /*!< size of key */
|
||||
uint32_t key[8]; /*!< AES key 128 or 256 bits */
|
||||
}
|
||||
mbedtls_cmac_context;
|
||||
|
||||
/**
|
||||
* \brief Initialize CMAC context (just makes references valid)
|
||||
* Makes the context ready for mbedtls_cmac_setkey() or
|
||||
* mbedtls_cmac_free().
|
||||
*
|
||||
* \param ctx CMAC context to initialize
|
||||
*/
|
||||
void mbedtls_cmac_init( mbedtls_cmac_context *ctx );
|
||||
|
||||
/**
|
||||
* \brief
|
||||
* Set the device instance of an CMAC context.
|
||||
*
|
||||
* \details
|
||||
* This function sets the AES/CRYPTO device instance of an CMAC context.
|
||||
* Subsequent calls to CMAC API functions with this context will use the
|
||||
* new AES/CRYPTO device instance.
|
||||
*
|
||||
* \param[in] ctx
|
||||
* CMAC device context.
|
||||
*
|
||||
* \param[in] devno
|
||||
* AES/CRYPTO hardware device instance to use.
|
||||
*
|
||||
* \return
|
||||
* 0 if success. Error code if failure, see \ref cmac.h.
|
||||
******************************************************************************/
|
||||
int mbedtls_cmac_set_device_instance(mbedtls_cmac_context* ctx,
|
||||
unsigned int devno);
|
||||
|
||||
#if defined( MBEDTLS_INCLUDE_ASYNCH_API )
|
||||
/**
|
||||
* \brief Set an CMAC context in asynchronous mode.
|
||||
*
|
||||
* \details
|
||||
* This function enables or disables asynchronous (non-blocking) mode of an
|
||||
* CMAC context. In order to enable, the user must set the
|
||||
* @p asynch_ctx parameter to point to an asynchronous cmac context structure
|
||||
* @ref mbedtls_cmac_asynch_context. Subsequent calls to the CMAC API
|
||||
* functions with the specified context will behave asynchronously, i.e.
|
||||
* initiate the hardware to execute the operation and return as soon as
|
||||
* possible. The user may specify a callback function by setting the
|
||||
* @p asynch_callback parameter which will called when the operation has
|
||||
* completed.
|
||||
* In order to disable, the user must set the @p asynch_ctx parameter
|
||||
* to NULL. All subsequent calls to CMAC API functions with the specified
|
||||
* context will block until the corresponding operation has completed, and
|
||||
* then return.
|
||||
*
|
||||
* \param ctx CMAC context
|
||||
* \param asynch_ctx CMAC asynchronous context structure
|
||||
* \param asynch_callback Asynchronous callback
|
||||
* \param user_arg User specific argument which will be
|
||||
* sent to callback.
|
||||
*
|
||||
* \return 0 if successful, or error code
|
||||
*/
|
||||
int mbedtls_cmac_set_asynch( mbedtls_cmac_context *ctx,
|
||||
mbedtls_cmac_asynch_context *asynch_ctx,
|
||||
mbedtls_asynch_callback asynch_callback,
|
||||
void* user_arg );
|
||||
#endif /* #if defined( MBEDTLS_INCLUDE_ASYNCH_API ) */
|
||||
|
||||
/**
|
||||
* \brief CMAC initialization (encryption and decryption)
|
||||
*
|
||||
* \param ctx CMAC context to be initialized
|
||||
* \param cipher cipher to use (a 128-bit block cipher)
|
||||
* \param key encryption key
|
||||
* \param keybits key size in bits (must be acceptable by the cipher)
|
||||
*
|
||||
* \return 0 if successful, or a cipher specific error code
|
||||
*/
|
||||
int mbedtls_cmac_setkey( mbedtls_cmac_context *ctx,
|
||||
mbedtls_cipher_id_t cipher,
|
||||
const unsigned char *key,
|
||||
unsigned int keybits );
|
||||
|
||||
/**
|
||||
* \brief Free a CMAC context and underlying cipher sub-context
|
||||
*
|
||||
* \param ctx CMAC context to free
|
||||
*/
|
||||
void mbedtls_cmac_free( mbedtls_cmac_context *ctx );
|
||||
|
||||
/**
|
||||
* \brief Generate CMAC tag
|
||||
*
|
||||
* \param ctx CMAC context
|
||||
* \param data buffer holding the input data
|
||||
* \param data_len length of the input data in bits
|
||||
* \param tag buffer for holding the tag
|
||||
* \param tag_len length of the tag to generate in bits
|
||||
* must be less than 128 bits
|
||||
*
|
||||
* \note The tag is written to a separate buffer. To get the tag
|
||||
* concatenated with the output as in the CMAC spec, use
|
||||
* tag = data + length and make sure the output buffer is
|
||||
* at least data_len + tag_len wide.
|
||||
*
|
||||
* \return 0 if successful
|
||||
*/
|
||||
int mbedtls_cmac_generate_tag( mbedtls_cmac_context *ctx,
|
||||
const unsigned char *data,
|
||||
size_t data_len,
|
||||
unsigned char *tag,
|
||||
size_t tag_len );
|
||||
|
||||
/**
|
||||
* \brief Verify CMAC tag
|
||||
*
|
||||
* \param ctx CMAC context
|
||||
* \param data buffer holding the input data
|
||||
* \param data_len length of the input data in bits
|
||||
* \param tag buffer holding the tag
|
||||
* \param tag_len length of the tag in bits
|
||||
* must be less than 128 bits
|
||||
*
|
||||
* \return 0 if successful and authenticated,
|
||||
* MBEDTLS_ERR_CMAC_AUTH_FAILED if tag does not match data
|
||||
*/
|
||||
int mbedtls_cmac_verify_tag( mbedtls_cmac_context *ctx,
|
||||
const unsigned char *data,
|
||||
size_t data_len,
|
||||
unsigned char *tag,
|
||||
size_t tag_len );
|
||||
|
||||
#if defined(MBEDTLS_SELF_TEST) && defined(MBEDTLS_CMAC_C)
|
||||
/**
|
||||
* \brief Checkup routine
|
||||
*
|
||||
* \return 0 if successful, or 1 if the test failed
|
||||
*/
|
||||
int mbedtls_cmac_self_test( int verbose );
|
||||
#endif /* MBEDTLS_SELF_TEST && MBEDTLS_CMAC_C */
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* #if defined( MBEDTLS_CMAC_ALT ) */
|
||||
|
||||
/** \} (end addtogroup sl_crypto) */
|
||||
/** \} (end addtogroup sl_crypto_cmac) */
|
||||
|
||||
#endif /* MBEDTLS_CMAC_ALT_H */
|
|
@ -0,0 +1,149 @@
|
|||
/*
|
||||
* \file cryptodrv.h
|
||||
*
|
||||
* \brief CRYPTO driver definitions including CRYPTO preemption and
|
||||
* asynchronous (non-blocking) support.
|
||||
*
|
||||
* Copyright (C) 2016 Silicon Labs, http://www.silabs.com
|
||||
* 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 __SILICON_LABS_CRYPTODRV_H
|
||||
#define __SILICON_LABS_CRYPTODRV_H
|
||||
|
||||
#if !defined(MBEDTLS_CONFIG_FILE)
|
||||
#include "config.h"
|
||||
#else
|
||||
#include MBEDTLS_CONFIG_FILE
|
||||
#endif
|
||||
|
||||
#include "em_device.h"
|
||||
|
||||
#if ( defined(CRYPTO_COUNT) && (CRYPTO_COUNT > 0) )
|
||||
|
||||
#include "mbedtls_ecode.h"
|
||||
#include "em_crypto.h"
|
||||
#if defined( MBEDTLS_INCLUDE_IO_MODE_DMA )
|
||||
#include "dmadrv.h"
|
||||
#endif
|
||||
#include <stdint.h>
|
||||
#include <stdbool.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/*******************************************************************************
|
||||
******************************* ERROR CODES **********************************
|
||||
******************************************************************************/
|
||||
|
||||
#define MBEDTLS_ECODE_CRYPTODRV_OPERATION_ABORTED (MBEDTLS_ECODE_CRYPTODRV_BASE | 0x1) /**< Operation was aborted. Possibly by higher priority task. The user will need to retry the operation in order to complete. */
|
||||
#define MBEDTLS_ECODE_CRYPTODRV_BUSY (MBEDTLS_ECODE_CRYPTODRV_BASE | 0x2) /**< The CRYPTO module is busy. */
|
||||
|
||||
/*******************************************************************************
|
||||
******************************* TYPEDEFS **********************************
|
||||
******************************************************************************/
|
||||
|
||||
#if defined(MBEDTLS_CRYPTO_DEVICE_PREEMPTION)
|
||||
|
||||
/** Context of CRYPTO hardware module. */
|
||||
typedef struct
|
||||
{
|
||||
uint32_t CTRL; /**< Control Register */
|
||||
uint32_t WAC; /**< Wide Arithmetic Configuration */
|
||||
uint32_t SEQCTRL; /**< Sequence Control */
|
||||
uint32_t SEQCTRLB; /**< Sequence Control B */
|
||||
uint32_t IEN; /**< Interrupt Enable Register */
|
||||
uint32_t SEQ[5]; /**< Instruction Sequence registers */
|
||||
CRYPTO_DData_TypeDef DDATA[5]; /**< DDATA registers. Covers all data registers
|
||||
of CRYPTO, including DATA(128 bit), DDATA (256bit),
|
||||
QDATA (512bit) registers. */
|
||||
} CRYPTO_Context_t;
|
||||
|
||||
#endif /* #if defined(MBEDTLS_CRYPTO_DEVICE_PREEMPTION) */
|
||||
|
||||
/***************************************************************************//**
|
||||
* @brief
|
||||
* CRYPTODRV asynchronous (non-blocking) operation completion callback function.
|
||||
*
|
||||
* @details
|
||||
* The callback function is called when an asynchronous (non-blocking)
|
||||
* CRYPTO operation has completed.
|
||||
*
|
||||
* @param[in] result
|
||||
* The result of the CRYPTO operation.
|
||||
*
|
||||
* @param[in] userArgument
|
||||
* Optional user defined argument supplied when starting the asynchronous
|
||||
* CRYPTO operation.
|
||||
******************************************************************************/
|
||||
typedef void (*CRYPTODRV_AsynchCallback_t)(void* userArgument);
|
||||
|
||||
/** CRYPTO device structure. */
|
||||
typedef struct
|
||||
{
|
||||
CRYPTO_TypeDef* crypto; /**< CRYPTO hw instance */
|
||||
IRQn_Type irqn; /**< CRYPTO irq number */
|
||||
uint32_t clk; /**< CRYPTO clock */
|
||||
#if defined( MBEDTLS_CRYPTO_DEVICE_PREEMPTION )
|
||||
void* pCryptoOwner; /**< Pointer to pointer of
|
||||
CRYPTO unit owner */
|
||||
uint32_t* pNvicIser; /**< Pointer to storage
|
||||
of NVIC ISER values. */
|
||||
#endif
|
||||
#if defined( MBEDTLS_INCLUDE_IO_MODE_DMA )
|
||||
DMADRV_PeripheralSignal_t dmaReqSigChIn; /**< DMA req signal channel in */
|
||||
DMADRV_PeripheralSignal_t dmaReqSigChOut;/**< DMA req signal channel out */
|
||||
#endif
|
||||
} CRYPTO_Device_t;
|
||||
|
||||
/** CRYPTODRV operation context. */
|
||||
typedef struct
|
||||
{
|
||||
const CRYPTO_Device_t* device; /**< CRYPTO hw instance */
|
||||
|
||||
#if defined( MBEDTLS_CRYPTO_DEVICE_PREEMPTION )
|
||||
|
||||
CRYPTO_Context_t cryptoContext; /**< CRYPTO hw context */
|
||||
bool aborted; /**< 'true' if an ongoing CRYPTO
|
||||
instruction sequence was
|
||||
aborted.*/
|
||||
unsigned long threadPriority; /**< Priority of thread/context */
|
||||
void* threadId; /**< Pointer to thread identifier*/
|
||||
|
||||
/* Double linked-list for CRYPTO context preemption. */
|
||||
void* pContextPreempted; /* Context preempted by _this_
|
||||
context. */
|
||||
void* pContextPreemptor; /* Context of preemptor
|
||||
of _this_ context. */
|
||||
#if defined(MBEDTLS_INCLUDE_ASYNCH_API)
|
||||
|
||||
CRYPTODRV_AsynchCallback_t asynchCallback; /**< Asynch callback */
|
||||
void* asynchCallbackArgument; /**< Parameter for
|
||||
asynch callback */
|
||||
|
||||
#endif /* #if defined(MBEDTLS_INCLUDE_ASYNCH_API) */
|
||||
|
||||
#endif /* #if defined(MBEDTLS_CRYPTO_DEVICE_PREEMPTION) */
|
||||
|
||||
} CRYPTODRV_Context_t;
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* #if ( defined(CRYPTO_COUNT) && (CRYPTO_COUNT > 0) ) || \
|
||||
( defined(AES_COUNT) && (AES_COUNT > 0) ) */
|
||||
|
||||
#endif /* #ifndef __SILICON_LABS_CRYPTODRV_H */
|
|
@ -0,0 +1,73 @@
|
|||
/***************************************************************************//**
|
||||
* @file ecode.h
|
||||
* @brief Energy Aware drivers error code definitions.
|
||||
* @version 4.4.0
|
||||
*******************************************************************************
|
||||
* @section License
|
||||
* <b>(C) Copyright 2015 Silicon Labs, http://www.silabs.com</b>
|
||||
*******************************************************************************
|
||||
*
|
||||
* This file is licensed under the Silabs License Agreement. See the file
|
||||
* "Silabs_License_Agreement.txt" for details. Before using this software for
|
||||
* any purpose, you must agree to the terms of that agreement.
|
||||
*
|
||||
******************************************************************************/
|
||||
#ifndef __SILICON_LABS_ECODE_H__
|
||||
#define __SILICON_LABS_ECODE_H__
|
||||
|
||||
/***************************************************************************//**
|
||||
* @defgroup emdrv EMDRV
|
||||
* @brief energyAware drivers
|
||||
* @details
|
||||
*
|
||||
* EMDRV is a set of function specific high performance drivers for EFM32, EZR32
|
||||
* and EFR32 on-chip peripherals. Drivers are typically DMA based and are using
|
||||
* all available low-energy features. For most drivers, the API offers both
|
||||
* synchronous and asynchronous functions. The APIs are fully reentrant and
|
||||
* callback based.
|
||||
*
|
||||
* Most drivers are compile-time configurable to allow the highest possible
|
||||
* code size optimization for the application. Compile-time configuration is
|
||||
* defined in *_config.h files. Templates for the configuration files can be
|
||||
* found in emdrv\\config.
|
||||
*
|
||||
* @note
|
||||
* EMDRV APIs use Ecode_t to return status.
|
||||
* @n @n
|
||||
* With the exception of ezradiodrv, EMDRV does not implement RF support.
|
||||
* Please refer to stack documentation for more information.
|
||||
*
|
||||
* @{
|
||||
******************************************************************************/
|
||||
|
||||
/***************************************************************************//**
|
||||
* @brief Typedef for API function errorcode return values.
|
||||
*
|
||||
* @details
|
||||
* Bit 24-31: sub-system, for example emLib, eaDrivers,... @n
|
||||
* Bit 16-23: module, for example UART, LCD,... @n
|
||||
* Bit 0-15: error code, specific error code
|
||||
******************************************************************************/
|
||||
typedef uint32_t Ecode_t;
|
||||
|
||||
#define ECODE_EMDRV_BASE ( 0xF0000000 ) ///< Base value for all EMDRV errorcodes.
|
||||
|
||||
#define ECODE_OK ( 0 ) ///< Generic success return value.
|
||||
|
||||
#define ECODE_EMDRV_RTCDRV_BASE ( ECODE_EMDRV_BASE | 0x00001000 ) ///< Base value for RTCDRV error codes.
|
||||
#define ECODE_EMDRV_SPIDRV_BASE ( ECODE_EMDRV_BASE | 0x00002000 ) ///< Base value for SPIDRV error codes.
|
||||
#define ECODE_EMDRV_NVM_BASE ( ECODE_EMDRV_BASE | 0x00003000 ) ///< Base value for NVM error codes.
|
||||
#define ECODE_EMDRV_USTIMER_BASE ( ECODE_EMDRV_BASE | 0x00004000 ) ///< Base value for USTIMER error codes.
|
||||
#define ECODE_EMDRV_AESDRV_BASE ( ECODE_EMDRV_BASE | 0x00005000 ) ///< Base value for AESDRV error codes.
|
||||
#define ECODE_EMDRV_ECC_BASE ( ECODE_EMDRV_BASE | 0x00006000 ) ///< Base value for ECC error codes.
|
||||
#define ECODE_EMDRV_UARTDRV_BASE ( ECODE_EMDRV_BASE | 0x00007000 ) ///< Base value for UARTDRV error codes.
|
||||
#define ECODE_EMDRV_DMADRV_BASE ( ECODE_EMDRV_BASE | 0x00008000 ) ///< Base value for DMADRV error codes.
|
||||
#define ECODE_EMDRV_EZRADIODRV_BASE ( ECODE_EMDRV_BASE | 0x00009000 ) ///< Base value for EZRADIODRV error codes.
|
||||
#define ECODE_EMDRV_SHADRV_BASE ( ECODE_EMDRV_BASE | 0x0000A000 ) ///< Base value for SHADRV error codes.
|
||||
#define ECODE_EMDRV_RSADRV_BASE ( ECODE_EMDRV_BASE | 0x0000B000 ) ///< Base value for RSADRV error codes.
|
||||
#define ECODE_EMDRV_CRYPTO_BASE ( ECODE_EMDRV_BASE | 0x0000C000 ) ///< Base value for CRYPTO error codes.
|
||||
#define ECODE_EMDRV_TEMPDRV_BASE ( ECODE_EMDRV_BASE | 0x0000D000 ) ///< Base value for TEMPDRV error codes.
|
||||
|
||||
/** @} (end addtogroup emdrv) */
|
||||
|
||||
#endif // __SILICON_LABS_ECODE_H__
|
|
@ -0,0 +1,703 @@
|
|||
/**
|
||||
* \file ecp_alt.h
|
||||
*
|
||||
* \brief Elliptic curves over GF(p)
|
||||
*
|
||||
* Copyright (C) 2015-2016, Silicon Labs, http://www.silabs.com
|
||||
* 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_ECP_ALT_H
|
||||
#define MBEDTLS_ECP_ALT_H
|
||||
|
||||
#if !defined(MBEDTLS_CONFIG_FILE)
|
||||
#include "config.h"
|
||||
#else
|
||||
#include MBEDTLS_CONFIG_FILE
|
||||
#endif
|
||||
|
||||
/***************************************************************************//**
|
||||
* \addtogroup sl_crypto
|
||||
* \{
|
||||
******************************************************************************/
|
||||
|
||||
/***************************************************************************//**
|
||||
* \addtogroup sl_crypto_ecp Elliptic curves over GF(p)
|
||||
* \brief CRYPTO hardware accelerated elliptic curves over GF(p).
|
||||
* \{
|
||||
******************************************************************************/
|
||||
|
||||
#if defined( MBEDTLS_ECP_ALT )
|
||||
/* SiliconLabs CRYPTO hardware acceleration implementation */
|
||||
|
||||
#include "cryptodrv.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/**
|
||||
* Domain parameters (curve, subgroup and generator) identifiers.
|
||||
*
|
||||
* Only curves over prime fields are supported.
|
||||
*
|
||||
* \warning This library does not support validation of arbitrary domain
|
||||
* parameters. Therefore, only well-known domain parameters from trusted
|
||||
* sources should be used. See mbedtls_ecp_group_load().
|
||||
*/
|
||||
typedef enum
|
||||
{
|
||||
MBEDTLS_ECP_DP_NONE = 0,
|
||||
MBEDTLS_ECP_DP_SECP192R1, /*!< 192-bits NIST curve */
|
||||
MBEDTLS_ECP_DP_SECP224R1, /*!< 224-bits NIST curve */
|
||||
MBEDTLS_ECP_DP_SECP256R1, /*!< 256-bits NIST curve */
|
||||
MBEDTLS_ECP_DP_SECP384R1, /*!< 384-bits NIST curve */
|
||||
MBEDTLS_ECP_DP_SECP521R1, /*!< 521-bits NIST curve */
|
||||
MBEDTLS_ECP_DP_BP256R1, /*!< 256-bits Brainpool curve */
|
||||
MBEDTLS_ECP_DP_BP384R1, /*!< 384-bits Brainpool curve */
|
||||
MBEDTLS_ECP_DP_BP512R1, /*!< 512-bits Brainpool curve */
|
||||
MBEDTLS_ECP_DP_CURVE25519, /*!< Curve25519 */
|
||||
MBEDTLS_ECP_DP_SECP192K1, /*!< 192-bits "Koblitz" curve */
|
||||
MBEDTLS_ECP_DP_SECP224K1, /*!< 224-bits "Koblitz" curve */
|
||||
MBEDTLS_ECP_DP_SECP256K1, /*!< 256-bits "Koblitz" curve */
|
||||
} mbedtls_ecp_group_id;
|
||||
|
||||
/**
|
||||
* Number of supported curves (plus one for NONE).
|
||||
*
|
||||
* (Montgomery curves excluded for now.)
|
||||
*/
|
||||
#define MBEDTLS_ECP_DP_MAX 12
|
||||
|
||||
/**
|
||||
* Curve information for use by other modules
|
||||
*/
|
||||
typedef struct
|
||||
{
|
||||
mbedtls_ecp_group_id grp_id; /*!< Internal identifier */
|
||||
uint16_t tls_id; /*!< TLS NamedCurve identifier */
|
||||
uint16_t bit_size; /*!< Curve size in bits */
|
||||
const char *name; /*!< Human-friendly name */
|
||||
} mbedtls_ecp_curve_info;
|
||||
|
||||
/**
|
||||
* \brief ECP point structure (jacobian coordinates)
|
||||
*
|
||||
* \note All functions expect and return points satisfying
|
||||
* the following condition: Z == 0 or Z == 1. (Other
|
||||
* values of Z are used by internal functions only.)
|
||||
* The point is zero, or "at infinity", if Z == 0.
|
||||
* Otherwise, X and Y are its standard (affine) coordinates.
|
||||
*/
|
||||
typedef struct
|
||||
{
|
||||
mbedtls_mpi X; /*!< the point's X coordinate */
|
||||
mbedtls_mpi Y; /*!< the point's Y coordinate */
|
||||
mbedtls_mpi Z; /*!< the point's Z coordinate */
|
||||
}
|
||||
mbedtls_ecp_point;
|
||||
|
||||
/**
|
||||
* \brief ECP group structure
|
||||
*
|
||||
* We consider two types of curves equations:
|
||||
* 1. Short Weierstrass y^2 = x^3 + A x + B mod P (SEC1 + RFC 4492)
|
||||
* 2. Montgomery, y^2 = x^3 + A x^2 + x mod P (Curve25519 + draft)
|
||||
* In both cases, a generator G for a prime-order subgroup is fixed. In the
|
||||
* short weierstrass, this subgroup is actually the whole curve, and its
|
||||
* cardinal is denoted by N.
|
||||
*
|
||||
* In the case of Short Weierstrass curves, our code requires that N is an odd
|
||||
* prime. (Use odd in mbedtls_ecp_mul() and prime in mbedtls_ecdsa_sign() for blinding.)
|
||||
*
|
||||
* In the case of Montgomery curves, we don't store A but (A + 2) / 4 which is
|
||||
* the quantity actually used in the formulas. Also, nbits is not the size of N
|
||||
* but the required size for private keys.
|
||||
*
|
||||
* If modp is NULL, reduction modulo P is done using a generic algorithm.
|
||||
* Otherwise, it must point to a function that takes an mbedtls_mpi in the range
|
||||
* 0..2^(2*pbits)-1 and transforms it in-place in an integer of little more
|
||||
* than pbits, so that the integer may be efficiently brought in the 0..P-1
|
||||
* range by a few additions or substractions. It must return 0 on success and
|
||||
* non-zero on failure.
|
||||
*/
|
||||
typedef struct
|
||||
{
|
||||
mbedtls_ecp_group_id id; /*!< internal group identifier */
|
||||
mbedtls_mpi P; /*!< prime modulus of the base field */
|
||||
mbedtls_mpi A; /*!< 1. A in the equation, or 2. (A + 2) / 4 */
|
||||
mbedtls_mpi B; /*!< 1. B in the equation, or 2. unused */
|
||||
mbedtls_ecp_point G; /*!< generator of the (sub)group used */
|
||||
mbedtls_mpi N; /*!< 1. the order of G, or 2. unused */
|
||||
size_t pbits; /*!< number of bits in P */
|
||||
size_t nbits; /*!< number of bits in 1. P, or 2. private keys */
|
||||
unsigned int h; /*!< internal: 1 if the constants are static */
|
||||
int (*modp)(mbedtls_mpi *); /*!< function for fast reduction mod P */
|
||||
int (*t_pre)(mbedtls_ecp_point *, void *); /*!< unused */
|
||||
int (*t_post)(mbedtls_ecp_point *, void *); /*!< unused */
|
||||
void *t_data; /*!< unused */
|
||||
mbedtls_ecp_point *T; /*!< pre-computed points for ecp_mul_comb() */
|
||||
size_t T_size; /*!< number for pre-computed points */
|
||||
|
||||
CRYPTODRV_Context_t cryptodrv_ctx;
|
||||
}
|
||||
mbedtls_ecp_group;
|
||||
|
||||
/**
|
||||
* \brief ECP key pair structure
|
||||
*
|
||||
* A generic key pair that could be used for ECDSA, fixed ECDH, etc.
|
||||
*
|
||||
* \note Members purposefully in the same order as struc mbedtls_ecdsa_context.
|
||||
*/
|
||||
typedef struct
|
||||
{
|
||||
mbedtls_ecp_group grp; /*!< Elliptic curve and base point */
|
||||
mbedtls_mpi d; /*!< our secret value */
|
||||
mbedtls_ecp_point Q; /*!< our public value */
|
||||
}
|
||||
mbedtls_ecp_keypair;
|
||||
|
||||
/**
|
||||
* \name SECTION: Module settings
|
||||
*
|
||||
* The configuration options you can set for this module are in this section.
|
||||
* Either change them in config.h or define them on the compiler command line.
|
||||
* \{
|
||||
*/
|
||||
|
||||
#if !defined(MBEDTLS_ECP_MAX_BITS)
|
||||
/**
|
||||
* Maximum size of the groups (that is, of N and P)
|
||||
*/
|
||||
#define MBEDTLS_ECP_MAX_BITS 521 /**< Maximum bit size of groups */
|
||||
#endif
|
||||
|
||||
#define MBEDTLS_ECP_MAX_BYTES ( ( MBEDTLS_ECP_MAX_BITS + 7 ) / 8 )
|
||||
#define MBEDTLS_ECP_MAX_PT_LEN ( 2 * MBEDTLS_ECP_MAX_BYTES + 1 )
|
||||
|
||||
#if !defined(MBEDTLS_ECP_WINDOW_SIZE)
|
||||
/*
|
||||
* Maximum "window" size used for point multiplication.
|
||||
* Default: 6.
|
||||
* Minimum value: 2. Maximum value: 7.
|
||||
*
|
||||
* Result is an array of at most ( 1 << ( MBEDTLS_ECP_WINDOW_SIZE - 1 ) )
|
||||
* points used for point multiplication. This value is directly tied to EC
|
||||
* peak memory usage, so decreasing it by one should roughly cut memory usage
|
||||
* by two (if large curves are in use).
|
||||
*
|
||||
* Reduction in size may reduce speed, but larger curves are impacted first.
|
||||
* Sample performances (in ECDHE handshakes/s, with FIXED_POINT_OPTIM = 1):
|
||||
* w-size: 6 5 4 3 2
|
||||
* 521 145 141 135 120 97
|
||||
* 384 214 209 198 177 146
|
||||
* 256 320 320 303 262 226
|
||||
|
||||
* 224 475 475 453 398 342
|
||||
* 192 640 640 633 587 476
|
||||
*/
|
||||
#define MBEDTLS_ECP_WINDOW_SIZE 6 /**< Maximum window size used */
|
||||
#endif /* MBEDTLS_ECP_WINDOW_SIZE */
|
||||
|
||||
#if !defined(MBEDTLS_ECP_FIXED_POINT_OPTIM)
|
||||
/*
|
||||
* Trade memory for speed on fixed-point multiplication.
|
||||
*
|
||||
* This speeds up repeated multiplication of the generator (that is, the
|
||||
* multiplication in ECDSA signatures, and half of the multiplications in
|
||||
* ECDSA verification and ECDHE) by a factor roughly 3 to 4.
|
||||
*
|
||||
* The cost is increasing EC peak memory usage by a factor roughly 2.
|
||||
*
|
||||
* Change this value to 0 to reduce peak memory usage.
|
||||
*/
|
||||
#define MBEDTLS_ECP_FIXED_POINT_OPTIM 1 /**< Enable fixed-point speed-up */
|
||||
#endif /* MBEDTLS_ECP_FIXED_POINT_OPTIM */
|
||||
|
||||
/* \} name SECTION: Module settings */
|
||||
|
||||
/*
|
||||
* Point formats, from RFC 4492's enum ECPointFormat
|
||||
*/
|
||||
#define MBEDTLS_ECP_PF_UNCOMPRESSED 0 /**< Uncompressed point format */
|
||||
#define MBEDTLS_ECP_PF_COMPRESSED 1 /**< Compressed point format */
|
||||
|
||||
/*
|
||||
* Some other constants from RFC 4492
|
||||
*/
|
||||
#define MBEDTLS_ECP_TLS_NAMED_CURVE 3 /**< ECCurveType's named_curve */
|
||||
|
||||
/**
|
||||
* \brief
|
||||
* Set the device instance of an ECP group context.
|
||||
*
|
||||
* \details
|
||||
* This function sets the CRYPTO device instance of an ECP group context.
|
||||
* Subsequent calls to the ECP functions with this group context will use the
|
||||
* new CRYPTO device instance.
|
||||
*
|
||||
* \param[in] grp
|
||||
* ECP group context.
|
||||
*
|
||||
* \param[in] devno
|
||||
* CRYPTO hardware device instance to use.
|
||||
*
|
||||
* \return
|
||||
* 0 if success. Error code if failure, see \ref aes.h.
|
||||
******************************************************************************/
|
||||
int mbedtls_ecp_set_device_instance(mbedtls_ecp_group *grp,
|
||||
unsigned int devno);
|
||||
|
||||
/**
|
||||
* \brief Get the list of supported curves in order of preferrence
|
||||
* (full information)
|
||||
*
|
||||
* \return A statically allocated array, the last entry is 0.
|
||||
*/
|
||||
const mbedtls_ecp_curve_info *mbedtls_ecp_curve_list( void );
|
||||
|
||||
/**
|
||||
* \brief Get the list of supported curves in order of preferrence
|
||||
* (grp_id only)
|
||||
*
|
||||
* \return A statically allocated array,
|
||||
* terminated with MBEDTLS_ECP_DP_NONE.
|
||||
*/
|
||||
const mbedtls_ecp_group_id *mbedtls_ecp_grp_id_list( void );
|
||||
|
||||
/**
|
||||
* \brief Get curve information from an internal group identifier
|
||||
*
|
||||
* \param grp_id A MBEDTLS_ECP_DP_XXX value
|
||||
*
|
||||
* \return The associated curve information or NULL
|
||||
*/
|
||||
const mbedtls_ecp_curve_info *mbedtls_ecp_curve_info_from_grp_id( mbedtls_ecp_group_id grp_id );
|
||||
|
||||
/**
|
||||
* \brief Get curve information from a TLS NamedCurve value
|
||||
*
|
||||
* \param tls_id A MBEDTLS_ECP_DP_XXX value
|
||||
*
|
||||
* \return The associated curve information or NULL
|
||||
*/
|
||||
const mbedtls_ecp_curve_info *mbedtls_ecp_curve_info_from_tls_id( uint16_t tls_id );
|
||||
|
||||
/**
|
||||
* \brief Get curve information from a human-readable name
|
||||
*
|
||||
* \param name The name
|
||||
*
|
||||
* \return The associated curve information or NULL
|
||||
*/
|
||||
const mbedtls_ecp_curve_info *mbedtls_ecp_curve_info_from_name( const char *name );
|
||||
|
||||
/**
|
||||
* \brief Initialize a point (as zero)
|
||||
*/
|
||||
void mbedtls_ecp_point_init( mbedtls_ecp_point *pt );
|
||||
|
||||
/**
|
||||
* \brief Initialize a group (to something meaningless)
|
||||
*/
|
||||
void mbedtls_ecp_group_init( mbedtls_ecp_group *grp );
|
||||
|
||||
/**
|
||||
* \brief Initialize a key pair (as an invalid one)
|
||||
*/
|
||||
void mbedtls_ecp_keypair_init( mbedtls_ecp_keypair *key );
|
||||
|
||||
/**
|
||||
* \brief Free the components of a point
|
||||
*/
|
||||
void mbedtls_ecp_point_free( mbedtls_ecp_point *pt );
|
||||
|
||||
/**
|
||||
* \brief Free the components of an ECP group
|
||||
*/
|
||||
void mbedtls_ecp_group_free( mbedtls_ecp_group *grp );
|
||||
|
||||
/**
|
||||
* \brief Free the components of a key pair
|
||||
*/
|
||||
void mbedtls_ecp_keypair_free( mbedtls_ecp_keypair *key );
|
||||
|
||||
/**
|
||||
* \brief Copy the contents of point Q into P
|
||||
*
|
||||
* \param P Destination point
|
||||
* \param Q Source point
|
||||
*
|
||||
* \return 0 if successful,
|
||||
* MBEDTLS_ERR_MPI_ALLOC_FAILED if memory allocation failed
|
||||
*/
|
||||
int mbedtls_ecp_copy( mbedtls_ecp_point *P, const mbedtls_ecp_point *Q );
|
||||
|
||||
/**
|
||||
* \brief Copy the contents of a group object
|
||||
*
|
||||
* \param dst Destination group
|
||||
* \param src Source group
|
||||
*
|
||||
* \return 0 if successful,
|
||||
* MBEDTLS_ERR_MPI_ALLOC_FAILED if memory allocation failed
|
||||
*/
|
||||
int mbedtls_ecp_group_copy( mbedtls_ecp_group *dst, const mbedtls_ecp_group *src );
|
||||
|
||||
/**
|
||||
* \brief Set a point to zero
|
||||
*
|
||||
* \param pt Destination point
|
||||
*
|
||||
* \return 0 if successful,
|
||||
* MBEDTLS_ERR_MPI_ALLOC_FAILED if memory allocation failed
|
||||
*/
|
||||
int mbedtls_ecp_set_zero( mbedtls_ecp_point *pt );
|
||||
|
||||
/**
|
||||
* \brief Tell if a point is zero
|
||||
*
|
||||
* \param pt Point to test
|
||||
*
|
||||
* \return 1 if point is zero, 0 otherwise
|
||||
*/
|
||||
int mbedtls_ecp_is_zero( mbedtls_ecp_point *pt );
|
||||
|
||||
/**
|
||||
* \brief Compare two points
|
||||
*
|
||||
* \note This assumes the points are normalized. Otherwise,
|
||||
* they may compare as "not equal" even if they are.
|
||||
*
|
||||
* \param P First point to compare
|
||||
* \param Q Second point to compare
|
||||
*
|
||||
* \return 0 if the points are equal,
|
||||
* MBEDTLS_ERR_ECP_BAD_INPUT_DATA otherwise
|
||||
*/
|
||||
int mbedtls_ecp_point_cmp( const mbedtls_ecp_point *P,
|
||||
const mbedtls_ecp_point *Q );
|
||||
|
||||
/**
|
||||
* \brief Import a non-zero point from two ASCII strings
|
||||
*
|
||||
* \param P Destination point
|
||||
* \param radix Input numeric base
|
||||
* \param x First affine coordinate as a null-terminated string
|
||||
* \param y Second affine coordinate as a null-terminated string
|
||||
*
|
||||
* \return 0 if successful, or a MBEDTLS_ERR_MPI_XXX error code
|
||||
*/
|
||||
int mbedtls_ecp_point_read_string( mbedtls_ecp_point *P, int radix,
|
||||
const char *x, const char *y );
|
||||
|
||||
/**
|
||||
* \brief Export a point into unsigned binary data
|
||||
*
|
||||
* \param grp Group to which the point should belong
|
||||
* \param P Point to export
|
||||
* \param format Point format, should be a MBEDTLS_ECP_PF_XXX macro
|
||||
* \param olen Length of the actual output
|
||||
* \param buf Output buffer
|
||||
* \param buflen Length of the output buffer
|
||||
*
|
||||
* \return 0 if successful,
|
||||
* or MBEDTLS_ERR_ECP_BAD_INPUT_DATA
|
||||
* or MBEDTLS_ERR_ECP_BUFFER_TOO_SMALL
|
||||
*/
|
||||
int mbedtls_ecp_point_write_binary( const mbedtls_ecp_group *grp, const mbedtls_ecp_point *P,
|
||||
int format, size_t *olen,
|
||||
unsigned char *buf, size_t buflen );
|
||||
|
||||
/**
|
||||
* \brief Import a point from unsigned binary data
|
||||
*
|
||||
* \param grp Group to which the point should belong
|
||||
* \param P Point to import
|
||||
* \param buf Input buffer
|
||||
* \param ilen Actual length of input
|
||||
*
|
||||
* \return 0 if successful,
|
||||
* MBEDTLS_ERR_ECP_BAD_INPUT_DATA if input is invalid,
|
||||
* MBEDTLS_ERR_MPI_ALLOC_FAILED if memory allocation failed,
|
||||
* MBEDTLS_ERR_ECP_FEATURE_UNAVAILABLE if the point format
|
||||
* is not implemented.
|
||||
*
|
||||
* \note This function does NOT check that the point actually
|
||||
* belongs to the given group, see mbedtls_ecp_check_pubkey() for
|
||||
* that.
|
||||
*/
|
||||
int mbedtls_ecp_point_read_binary( const mbedtls_ecp_group *grp, mbedtls_ecp_point *P,
|
||||
const unsigned char *buf, size_t ilen );
|
||||
|
||||
/**
|
||||
* \brief Import a point from a TLS ECPoint record
|
||||
*
|
||||
* \param grp ECP group used
|
||||
* \param pt Destination point
|
||||
* \param buf $(Start of input buffer)
|
||||
* \param len Buffer length
|
||||
*
|
||||
* \note buf is updated to point right after the ECPoint on exit
|
||||
*
|
||||
* \return 0 if successful,
|
||||
* MBEDTLS_ERR_MPI_XXX if initialization failed
|
||||
* MBEDTLS_ERR_ECP_BAD_INPUT_DATA if input is invalid
|
||||
*/
|
||||
int mbedtls_ecp_tls_read_point( const mbedtls_ecp_group *grp, mbedtls_ecp_point *pt,
|
||||
const unsigned char **buf, size_t len );
|
||||
|
||||
/**
|
||||
* \brief Export a point as a TLS ECPoint record
|
||||
*
|
||||
* \param grp ECP group used
|
||||
* \param pt Point to export
|
||||
* \param format Export format
|
||||
* \param olen length of data written
|
||||
* \param buf Buffer to write to
|
||||
* \param blen Buffer length
|
||||
*
|
||||
* \return 0 if successful,
|
||||
* or MBEDTLS_ERR_ECP_BAD_INPUT_DATA
|
||||
* or MBEDTLS_ERR_ECP_BUFFER_TOO_SMALL
|
||||
*/
|
||||
int mbedtls_ecp_tls_write_point( const mbedtls_ecp_group *grp, const mbedtls_ecp_point *pt,
|
||||
int format, size_t *olen,
|
||||
unsigned char *buf, size_t blen );
|
||||
|
||||
/**
|
||||
* \brief Set a group using well-known domain parameters
|
||||
*
|
||||
* \param grp Destination group
|
||||
* \param index Index in the list of well-known domain parameters
|
||||
*
|
||||
* \return 0 if successful,
|
||||
* MBEDTLS_ERR_MPI_XXX if initialization failed
|
||||
* MBEDTLS_ERR_ECP_FEATURE_UNAVAILABLE for unkownn groups
|
||||
*
|
||||
* \note Index should be a value of RFC 4492's enum NamedCurve,
|
||||
* usually in the form of a MBEDTLS_ECP_DP_XXX macro.
|
||||
*/
|
||||
int mbedtls_ecp_group_load( mbedtls_ecp_group *grp, mbedtls_ecp_group_id index );
|
||||
|
||||
/**
|
||||
* \brief Set a group from a TLS ECParameters record
|
||||
*
|
||||
* \param grp Destination group
|
||||
* \param buf &(Start of input buffer)
|
||||
* \param len Buffer length
|
||||
*
|
||||
* \note buf is updated to point right after ECParameters on exit
|
||||
*
|
||||
* \return 0 if successful,
|
||||
* MBEDTLS_ERR_MPI_XXX if initialization failed
|
||||
* MBEDTLS_ERR_ECP_BAD_INPUT_DATA if input is invalid
|
||||
*/
|
||||
int mbedtls_ecp_tls_read_group( mbedtls_ecp_group *grp, const unsigned char **buf, size_t len );
|
||||
|
||||
/**
|
||||
* \brief Write the TLS ECParameters record for a group
|
||||
*
|
||||
* \param grp ECP group used
|
||||
* \param olen Number of bytes actually written
|
||||
* \param buf Buffer to write to
|
||||
* \param blen Buffer length
|
||||
*
|
||||
* \return 0 if successful,
|
||||
* or MBEDTLS_ERR_ECP_BUFFER_TOO_SMALL
|
||||
*/
|
||||
int mbedtls_ecp_tls_write_group( const mbedtls_ecp_group *grp, size_t *olen,
|
||||
unsigned char *buf, size_t blen );
|
||||
|
||||
/**
|
||||
* \brief Multiplication by an integer: R = m * P
|
||||
* (Not thread-safe to use same group in multiple threads)
|
||||
*
|
||||
* \note In order to prevent timing attacks, this function
|
||||
* executes the exact same sequence of (base field)
|
||||
* operations for any valid m. It avoids any if-branch or
|
||||
* array index depending on the value of m.
|
||||
*
|
||||
* \note If f_rng is not NULL, it is used to randomize intermediate
|
||||
* results in order to prevent potential timing attacks
|
||||
* targeting these results. It is recommended to always
|
||||
* provide a non-NULL f_rng (the overhead is negligible).
|
||||
*
|
||||
* \param grp ECP group
|
||||
* \param R Destination point
|
||||
* \param m Integer by which to multiply
|
||||
* \param P Point to multiply
|
||||
* \param f_rng RNG function (see notes)
|
||||
* \param p_rng RNG parameter
|
||||
*
|
||||
* \return 0 if successful,
|
||||
* MBEDTLS_ERR_ECP_INVALID_KEY if m is not a valid privkey
|
||||
* or P is not a valid pubkey,
|
||||
* MBEDTLS_ERR_MPI_ALLOC_FAILED if memory allocation failed
|
||||
*/
|
||||
int mbedtls_ecp_mul( mbedtls_ecp_group *grp, mbedtls_ecp_point *R,
|
||||
const mbedtls_mpi *m, const mbedtls_ecp_point *P,
|
||||
int (*f_rng)(void *, unsigned char *, size_t), void *p_rng );
|
||||
|
||||
/**
|
||||
* \brief Multiplication and addition of two points by integers:
|
||||
* R = m * P + n * Q
|
||||
* (Not thread-safe to use same group in multiple threads)
|
||||
*
|
||||
* \note In contrast to mbedtls_ecp_mul(), this function does not guarantee
|
||||
* a constant execution flow and timing.
|
||||
*
|
||||
* \param grp ECP group
|
||||
* \param R Destination point
|
||||
* \param m Integer by which to multiply P
|
||||
* \param P Point to multiply by m
|
||||
* \param n Integer by which to multiply Q
|
||||
* \param Q Point to be multiplied by n
|
||||
*
|
||||
* \return 0 if successful,
|
||||
* MBEDTLS_ERR_ECP_INVALID_KEY if m or n is not a valid privkey
|
||||
* or P or Q is not a valid pubkey,
|
||||
* MBEDTLS_ERR_MPI_ALLOC_FAILED if memory allocation failed
|
||||
*/
|
||||
int mbedtls_ecp_muladd( mbedtls_ecp_group *grp, mbedtls_ecp_point *R,
|
||||
const mbedtls_mpi *m, const mbedtls_ecp_point *P,
|
||||
const mbedtls_mpi *n, const mbedtls_ecp_point *Q );
|
||||
|
||||
/**
|
||||
* \brief Check that a point is a valid public key on this curve
|
||||
*
|
||||
* \param grp Curve/group the point should belong to
|
||||
* \param pt Point to check
|
||||
*
|
||||
* \return 0 if point is a valid public key,
|
||||
* MBEDTLS_ERR_ECP_INVALID_KEY otherwise.
|
||||
*
|
||||
* \note This function only checks the point is non-zero, has valid
|
||||
* coordinates and lies on the curve, but not that it is
|
||||
* indeed a multiple of G. This is additional check is more
|
||||
* expensive, isn't required by standards, and shouldn't be
|
||||
* necessary if the group used has a small cofactor. In
|
||||
* particular, it is useless for the NIST groups which all
|
||||
* have a cofactor of 1.
|
||||
*
|
||||
* \note Uses bare components rather than an mbedtls_ecp_keypair structure
|
||||
* in order to ease use with other structures such as
|
||||
* mbedtls_ecdh_context of mbedtls_ecdsa_context.
|
||||
*/
|
||||
int mbedtls_ecp_check_pubkey( const mbedtls_ecp_group *grp, const mbedtls_ecp_point *pt );
|
||||
|
||||
/**
|
||||
* \brief Check that an mbedtls_mpi is a valid private key for this curve
|
||||
*
|
||||
* \param grp Group used
|
||||
* \param d Integer to check
|
||||
*
|
||||
* \return 0 if point is a valid private key,
|
||||
* MBEDTLS_ERR_ECP_INVALID_KEY otherwise.
|
||||
*
|
||||
* \note Uses bare components rather than an mbedtls_ecp_keypair structure
|
||||
* in order to ease use with other structures such as
|
||||
* mbedtls_ecdh_context of mbedtls_ecdsa_context.
|
||||
*/
|
||||
int mbedtls_ecp_check_privkey( const mbedtls_ecp_group *grp, const mbedtls_mpi *d );
|
||||
|
||||
/**
|
||||
* \brief Generate a keypair with configurable base point
|
||||
*
|
||||
* \param grp ECP group
|
||||
* \param G Chosen base point
|
||||
* \param d Destination MPI (secret part)
|
||||
* \param Q Destination point (public part)
|
||||
* \param f_rng RNG function
|
||||
* \param p_rng RNG parameter
|
||||
*
|
||||
* \return 0 if successful,
|
||||
* or a MBEDTLS_ERR_ECP_XXX or MBEDTLS_MPI_XXX error code
|
||||
*
|
||||
* \note Uses bare components rather than an mbedtls_ecp_keypair structure
|
||||
* in order to ease use with other structures such as
|
||||
* mbedtls_ecdh_context of mbedtls_ecdsa_context.
|
||||
*/
|
||||
int mbedtls_ecp_gen_keypair_base( mbedtls_ecp_group *grp,
|
||||
const mbedtls_ecp_point *G,
|
||||
mbedtls_mpi *d, mbedtls_ecp_point *Q,
|
||||
int (*f_rng)(void *, unsigned char *, size_t),
|
||||
void *p_rng );
|
||||
|
||||
/**
|
||||
* \brief Generate a keypair
|
||||
*
|
||||
* \param grp ECP group
|
||||
* \param d Destination MPI (secret part)
|
||||
* \param Q Destination point (public part)
|
||||
* \param f_rng RNG function
|
||||
* \param p_rng RNG parameter
|
||||
*
|
||||
* \return 0 if successful,
|
||||
* or a MBEDTLS_ERR_ECP_XXX or MBEDTLS_MPI_XXX error code
|
||||
*
|
||||
* \note Uses bare components rather than an mbedtls_ecp_keypair structure
|
||||
* in order to ease use with other structures such as
|
||||
* mbedtls_ecdh_context of mbedtls_ecdsa_context.
|
||||
*/
|
||||
int mbedtls_ecp_gen_keypair( mbedtls_ecp_group *grp, mbedtls_mpi *d, mbedtls_ecp_point *Q,
|
||||
int (*f_rng)(void *, unsigned char *, size_t),
|
||||
void *p_rng );
|
||||
|
||||
/**
|
||||
* \brief Generate a keypair
|
||||
*
|
||||
* \param grp_id ECP group identifier
|
||||
* \param key Destination keypair
|
||||
* \param f_rng RNG function
|
||||
* \param p_rng RNG parameter
|
||||
*
|
||||
* \return 0 if successful,
|
||||
* or a MBEDTLS_ERR_ECP_XXX or MBEDTLS_MPI_XXX error code
|
||||
*/
|
||||
int mbedtls_ecp_gen_key( mbedtls_ecp_group_id grp_id, mbedtls_ecp_keypair *key,
|
||||
int (*f_rng)(void *, unsigned char *, size_t), void *p_rng );
|
||||
|
||||
/**
|
||||
* \brief Check a public-private key pair
|
||||
*
|
||||
* \param pub Keypair structure holding a public key
|
||||
* \param prv Keypair structure holding a private (plus public) key
|
||||
*
|
||||
* \return 0 if successful (keys are valid and match), or
|
||||
* MBEDTLS_ERR_ECP_BAD_INPUT_DATA, or
|
||||
* a MBEDTLS_ERR_ECP_XXX or MBEDTLS_ERR_MPI_XXX code.
|
||||
*/
|
||||
int mbedtls_ecp_check_pub_priv( const mbedtls_ecp_keypair *pub, const mbedtls_ecp_keypair *prv );
|
||||
|
||||
#if defined(MBEDTLS_SELF_TEST)
|
||||
/**
|
||||
* \brief Checkup routine
|
||||
*
|
||||
* \return 0 if successful, or 1 if a test failed
|
||||
*/
|
||||
int mbedtls_ecp_self_test( int verbose );
|
||||
#endif
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* #if defined( MBEDTLS_ECP_ALT ) */
|
||||
|
||||
/** \} (end addtogroup sl_crypto) */
|
||||
/** \} (end addtogroup sl_crypto_ecp) */
|
||||
|
||||
#endif /* #ifndef MBEDTLS_ECP_ALT_H */
|
|
@ -0,0 +1,64 @@
|
|||
/**
|
||||
* \file mbedtls_ecode.h
|
||||
*
|
||||
* \brief Silicon Labs specific mbedtls error code definitions.
|
||||
*
|
||||
* Copyright (C) 2016, Silicon Labs, http://www.silabs.com
|
||||
* 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_ECODE_H
|
||||
#define MBEDTLS_ECODE_H
|
||||
|
||||
/**
|
||||
* This file defines the Silicon Labs specific mbedtls error code layout
|
||||
* and values.
|
||||
*
|
||||
* Error code layout.
|
||||
*
|
||||
* The standard mbedtls error code layout use the negative space of 16 bits
|
||||
* signed integers in order to support all architectures. However the standard
|
||||
* mbedtls error code layout is fixed by ARM and does not define a sub-space
|
||||
* for additional vendor specific error codes. Additionally the 16 bit
|
||||
* requirement is not relevant for the Silicon Labs 32bit MCUs. Therefore
|
||||
* Silicon Labs defines a 32 bit signed integer error code layout which does
|
||||
* not use the values of the standard mbedtls error code layout given that the
|
||||
* 16 most significant bits of standard mbedtls error codes are all ones (which
|
||||
* should be the case when running on 32-bit architectures and the application
|
||||
* does not strip off the 16 most significant bits):
|
||||
*
|
||||
* bit 31: Sign bit. 1 to signify that the value is part of the error
|
||||
* code space. 0 for non error codes, in which case all 32 bits
|
||||
* are 0 which means OK (i.e. operation succeded).
|
||||
* bits 24-30: sub-system id, for example mbedtls, emdrv, etc
|
||||
* bits 16-23: module id, for example UART, LCD,...
|
||||
* bits 0-15: error code, specific error code
|
||||
*
|
||||
* The sub-system id and module id are not allowed to be all ones.
|
||||
*
|
||||
* Below is the list of module ids for the mbedtls sub-system.
|
||||
* Module specific error codes are defined in the header file of
|
||||
* each respective module.
|
||||
*/
|
||||
|
||||
#define MBEDTLS_ECODE_BASE ( 0xF1000000 ) /*!< Base value for all error codes. */
|
||||
|
||||
#define MBEDTLS_ECODE_AESDRV_BASE ( MBEDTLS_ECODE_BASE | 0x00005000 ) /*!< Base value for AESDRV error codes. */
|
||||
#define MBEDTLS_ECODE_ECC_BASE ( MBEDTLS_ECODE_BASE | 0x00006000 ) /*!< Base value for ECC error codes. */
|
||||
#define MBEDTLS_ECODE_SHA_BASE ( MBEDTLS_ECODE_BASE | 0x0000A000 ) /*!< Base value for SHA error codes. */
|
||||
#define MBEDTLS_ECODE_CRYPTODRV_BASE ( MBEDTLS_ECODE_BASE | 0x0000C000 ) /*!< Base value for CRYPTO error codes. */
|
||||
#define MBEDTLS_ERR_CMAC_BASE ( MBEDTLS_ECODE_AESDRV_BASE | 0xf00) /**< Base value of error codes for CMAC submodule (of AESDRV module). */
|
||||
|
||||
#endif /* #ifndef MBEDTLS_ECODE_H */
|
|
@ -0,0 +1,167 @@
|
|||
/**
|
||||
* \file sha1_alt.h
|
||||
*
|
||||
* \brief SHA-1 cryptographic hash function
|
||||
*
|
||||
* Copyright (C) 2015-2016, Silicon Labs, http://www.silabs.com
|
||||
* 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
|
||||
|
||||
#if !defined(MBEDTLS_CONFIG_FILE)
|
||||
#include "config.h"
|
||||
#else
|
||||
#include MBEDTLS_CONFIG_FILE
|
||||
#endif
|
||||
|
||||
/***************************************************************************//**
|
||||
* \addtogroup sl_crypto
|
||||
* \{
|
||||
******************************************************************************/
|
||||
|
||||
/***************************************************************************//**
|
||||
* \addtogroup sl_crypto_sha1 SHA-1 cryptographic hash function
|
||||
* \brief CRYPTO hardware accelerated SHA-1 cryptographic hash function.
|
||||
* \{
|
||||
******************************************************************************/
|
||||
|
||||
#if defined(MBEDTLS_SHA1_ALT)
|
||||
|
||||
/* SiliconLabs CRYPTO hardware acceleration implementation */
|
||||
|
||||
#include "sl_crypto.h"
|
||||
#include <stddef.h>
|
||||
#include <stdint.h>
|
||||
|
||||
#define MBEDTLS_ERR_SHA1_BAD_INPUT -0x5100 /**< Bad input parameters to function. */
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/**
|
||||
* \brief SHA-1 context structure
|
||||
*/
|
||||
typedef struct
|
||||
{
|
||||
#if defined( MBEDTLS_SLCL_PLUGINS )
|
||||
CRYPTODRV_Context_t cryptodrv_ctx; /*!< CRYPTODRV Context */
|
||||
#else
|
||||
uint32_t state[8]; /*!< intermediate digest state */
|
||||
#endif
|
||||
uint32_t total[2]; /*!< number of bytes processed */
|
||||
unsigned char buffer[64]; /*!< data block being processed */
|
||||
}
|
||||
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 );
|
||||
|
||||
#if defined( MBEDTLS_SLCL_PLUGINS )
|
||||
/**
|
||||
* \brief
|
||||
* Set the device instance of an SHA1 context.
|
||||
*
|
||||
* \details
|
||||
* This function sets the AES/CRYPTO device instance of an SHA1 context.
|
||||
* Subsequent calls to SHA1 API functions with this context will use the
|
||||
* new AES/CRYPTO device instance.
|
||||
*
|
||||
* \param[in] ctx
|
||||
* SHA1 device context.
|
||||
*
|
||||
* \param[in] devno
|
||||
* AES/CRYPTO hardware device instance to use.
|
||||
*
|
||||
* \return
|
||||
* 0 if success. Error code if failure, see \ref sha1.h.
|
||||
******************************************************************************/
|
||||
int mbedtls_sha1_set_device_instance(mbedtls_sha1_context* ctx,
|
||||
unsigned int devno);
|
||||
#endif /* #if defined( MBEDTLS_SLCL_PLUGINS ) */
|
||||
|
||||
/**
|
||||
* \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
|
||||
*/
|
||||
void mbedtls_sha1_starts( 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
|
||||
*/
|
||||
void mbedtls_sha1_update( 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
|
||||
*/
|
||||
void mbedtls_sha1_finish( mbedtls_sha1_context *ctx, unsigned char output[20] );
|
||||
|
||||
/* Internal use */
|
||||
void mbedtls_sha1_process( mbedtls_sha1_context *ctx, const unsigned char data[64] );
|
||||
|
||||
/**
|
||||
* \brief Output = SHA-1( input buffer )
|
||||
*
|
||||
* \param input Buffer holding the data. The input buffer needs to be big
|
||||
* enough to hold the padding (MD-strenghtening) at the end,
|
||||
* after the message of 'ilen' length. This function will
|
||||
* perform MD-strengthening and append to the end of the
|
||||
* input buffer.
|
||||
* \param ilen length of the input data
|
||||
* \param output SHA-1 checksum result
|
||||
*
|
||||
*/
|
||||
void mbedtls_sha1( const unsigned char *input, size_t ilen,
|
||||
unsigned char output[20]);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* #if defined(MBEDTLS_SHA1_ALT) */
|
||||
|
||||
/** \} (end addtogroup sl_crypto) */
|
||||
/** \} (end addtogroup sl_crypto_sha1) */
|
||||
|
||||
#endif /* #ifndef MBEDTLS_SHA1_ALT_H */
|
|
@ -0,0 +1,171 @@
|
|||
/**
|
||||
* \file sha256_alt.h
|
||||
*
|
||||
* \brief SHA-224 and SHA-256 cryptographic hash function
|
||||
*
|
||||
* Copyright (C) 2015-2016, Silicon Labs, http://www.silabs.com
|
||||
* 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
|
||||
|
||||
#if !defined(MBEDTLS_CONFIG_FILE)
|
||||
#include "config.h"
|
||||
#else
|
||||
#include MBEDTLS_CONFIG_FILE
|
||||
#endif
|
||||
|
||||
/***************************************************************************//**
|
||||
* \addtogroup sl_crypto
|
||||
* \{
|
||||
******************************************************************************/
|
||||
|
||||
/***************************************************************************//**
|
||||
* \addtogroup sl_crypto_sha256 SHA-224 and SHA-256 cryptographic hash function
|
||||
* \brief CRYPTO hardware accelerated SHA-224 and SHA-256 cryptographic hash function.
|
||||
* \{
|
||||
******************************************************************************/
|
||||
|
||||
#if defined(MBEDTLS_SHA256_ALT)
|
||||
|
||||
/* SiliconLabs CRYPTO hardware acceleration implementation */
|
||||
|
||||
#include "sl_crypto.h"
|
||||
#include <stddef.h>
|
||||
#include <stdint.h>
|
||||
|
||||
#define MBEDTLS_ERR_SHA256_BAD_INPUT -0x5100 /**< Bad input parameters to function. */
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/**
|
||||
* \brief SHA-256 context structure
|
||||
*/
|
||||
typedef struct
|
||||
{
|
||||
#if defined( MBEDTLS_SLCL_PLUGINS )
|
||||
CRYPTODRV_Context_t cryptodrv_ctx; /*!< CRYPTODRV Context */
|
||||
#else
|
||||
uint32_t state[8]; /*!< intermediate digest state */
|
||||
#endif
|
||||
uint32_t total[2]; /*!< number of bytes processed */
|
||||
unsigned char buffer[64]; /*!< data block being processed */
|
||||
int is224; /*!< 0 => SHA-256, else SHA-224 */
|
||||
}
|
||||
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 );
|
||||
|
||||
#if defined( MBEDTLS_SLCL_PLUGINS )
|
||||
/**
|
||||
* \brief
|
||||
* Set the device instance of an SHA256 context.
|
||||
*
|
||||
* \details
|
||||
* This function sets the AES/CRYPTO device instance of an SHA256 context.
|
||||
* Subsequent calls to SHA256 API functions with this context will use the
|
||||
* new AES/CRYPTO device instance.
|
||||
*
|
||||
* \param[in] ctx
|
||||
* SHA256 device context.
|
||||
*
|
||||
* \param[in] devno
|
||||
* AES/CRYPTO hardware device instance to use.
|
||||
*
|
||||
* \return
|
||||
* 0 if success. Error code if failure, see \ref sha256.h.
|
||||
******************************************************************************/
|
||||
int mbedtls_sha256_set_device_instance(mbedtls_sha256_context *ctx,
|
||||
unsigned int devno);
|
||||
#endif /* #if defined( MBEDTLS_SLCL_PLUGINS ) */
|
||||
|
||||
/**
|
||||
* \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
|
||||
*/
|
||||
void mbedtls_sha256_starts( 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
|
||||
*/
|
||||
void mbedtls_sha256_update( 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
|
||||
*/
|
||||
void mbedtls_sha256_finish( mbedtls_sha256_context *ctx, unsigned char output[32] );
|
||||
|
||||
/* Internal use */
|
||||
void mbedtls_sha256_process( mbedtls_sha256_context *ctx, const unsigned char data[64] );
|
||||
|
||||
/**
|
||||
* \brief Output = SHA-256( input buffer )
|
||||
*
|
||||
* \param input Buffer holding the data. The input buffer needs to be big
|
||||
* enough to hold the padding (MD-strenghtening) at the end,
|
||||
* after the message of 'ilen' length. This function will
|
||||
* perform MD-strengthening and append to the end of the
|
||||
* input buffer.
|
||||
* \param ilen length of the input data
|
||||
* \param output SHA-224/256 checksum result
|
||||
* \param is224 0 = use SHA256, 1 = use SHA224
|
||||
*
|
||||
*/
|
||||
void mbedtls_sha256( const unsigned char *input, size_t ilen,
|
||||
unsigned char output[32], int is224 );
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* #if defined(MBEDTLS_SHA256_ALT) */
|
||||
|
||||
/** \} (end addtogroup sl_crypto) */
|
||||
/** \} (end addtogroup sl_crypto_sha256) */
|
||||
|
||||
#endif /* #ifndef MBEDTLS_SHA256_ALT_H */
|
|
@ -0,0 +1,125 @@
|
|||
/**
|
||||
* \file sl_crypto.h
|
||||
*
|
||||
* \brief Silicon Labs specific mbedTLS defintitions
|
||||
*
|
||||
* Copyright (C) 2016, Silicon Labs, 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.
|
||||
*/
|
||||
#ifndef MBEDTLS_SL_CRYPTO_H
|
||||
#define MBEDTLS_SL_CRYPTO_H
|
||||
|
||||
#include "em_device.h"
|
||||
|
||||
#if ( defined(CRYPTO_COUNT) && (CRYPTO_COUNT > 0) ) || \
|
||||
( defined(AES_COUNT) && (AES_COUNT > 0) )
|
||||
|
||||
#if !defined(MBEDTLS_CONFIG_FILE)
|
||||
#include "mbedtls/config.h"
|
||||
#else
|
||||
#include MBEDTLS_CONFIG_FILE
|
||||
#endif
|
||||
|
||||
#if defined( MBEDTLS_SLCL_PLUGINS )
|
||||
|
||||
#if defined(CRYPTO_COUNT) && (CRYPTO_COUNT > 0)
|
||||
#include "cryptodrv.h"
|
||||
#endif
|
||||
|
||||
#include "mbedtls_ecode.h"
|
||||
#include <stdbool.h>
|
||||
|
||||
/** Error codes */
|
||||
|
||||
#if defined(CRYPTO_COUNT) && (CRYPTO_COUNT > 0)
|
||||
#define MBEDTLS_ERR_ABORTED ((int)MBEDTLS_ECODE_CRYPTODRV_OPERATION_ABORTED) /**< Operation was aborted. */
|
||||
#define MBEDTLS_ERR_DEVICE_BUSY ((int)MBEDTLS_ECODE_CRYPTODRV_BUSY) /**< CRYPTO/AES device busy */
|
||||
#endif
|
||||
#endif /* #if defined( MBEDTLS_SLCL_PLUGINS ) */
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/**
|
||||
* \brief Asynchronous (non-blocking) operation completion callback function.
|
||||
*
|
||||
* \details
|
||||
* The callback function is called when an asynchronous (non-blocking)
|
||||
* mbedtls operation has completed.
|
||||
*
|
||||
* \param[in] result
|
||||
* The result of the asynchronous operation.
|
||||
*
|
||||
* \param[in] user_arg
|
||||
* Optional user defined argument
|
||||
******************************************************************************/
|
||||
typedef void (*mbedtls_asynch_callback)(int result, void* user_arg);
|
||||
|
||||
/** Enum defines which data I/O mode to use for moving data to/from the
|
||||
AES/CRYPTO hardware module. */
|
||||
typedef enum
|
||||
{
|
||||
MBEDTLS_DEVICE_IO_MODE_CORE, /*!< Core CPU moves data to/from the data
|
||||
registers. */
|
||||
|
||||
MBEDTLS_DEVICE_IO_MODE_BUFC, /*!< Buffer Controller moves data to/from the
|
||||
CRYPTO data registers. */
|
||||
|
||||
#if defined( MBEDTLS_INCLUDE_IO_MODE_DMA )
|
||||
MBEDTLS_DEVICE_IO_MODE_DMA /*!< DMA moves data to/from the CRYPTO data
|
||||
registers. */
|
||||
#endif
|
||||
} mbedtls_device_io_mode;
|
||||
|
||||
#if defined( MBEDTLS_INCLUDE_IO_MODE_DMA )
|
||||
/** DMA I/O mode specific configuration structure. */
|
||||
typedef struct
|
||||
{
|
||||
unsigned int dma_ch_in; /*!< DMA input channel. Allocated by mbedtls. */
|
||||
unsigned int dma_ch_out; /*!< DMA output channel. Allocated by mbedtls. */
|
||||
} mbedtls_device_dma_config;
|
||||
#endif
|
||||
|
||||
#if defined(BUFC_PRESENT)
|
||||
/** BUFC I/O mode specific configuration structure. */
|
||||
typedef struct
|
||||
{
|
||||
uint8_t buf_id; /*!< BUFC buffer id. Must be setup by user. */
|
||||
} mbedtls_device_bufc_config;
|
||||
#endif
|
||||
|
||||
/** Data I/O mode specific configuration structure. */
|
||||
typedef union
|
||||
{
|
||||
#if defined( MBEDTLS_INCLUDE_IO_MODE_DMA )
|
||||
mbedtls_device_dma_config dma_config; /*!< DMA specific config */
|
||||
#endif
|
||||
#if defined(BUFC_PRESENT)
|
||||
mbedtls_device_bufc_config bufc_config; /*!< BUFC specific config */
|
||||
#endif
|
||||
void* placeholder; /*!< Dummy place holder to
|
||||
keep compiler happy when both
|
||||
BUFC and DMA are disabled. */
|
||||
} mbedtls_device_io_mode_specific;
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* #if ( defined(CRYPTO_COUNT) && (CRYPTO_COUNT > 0) ) || \
|
||||
( defined(AES_COUNT) && (AES_COUNT > 0) ) */
|
||||
|
||||
#endif /* #ifndef MBEDTLS_SL_CRYPTO_H */
|
|
@ -0,0 +1,83 @@
|
|||
/**
|
||||
* \file timing_alt.h
|
||||
*
|
||||
* \brief Portable interface to the CPU cycle counter
|
||||
*
|
||||
* Copyright (C) 2016, Silicon Labs, 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.
|
||||
*/
|
||||
#ifndef MBEDTLS_TIMING_ALT_H
|
||||
#define MBEDTLS_TIMING_ALT_H
|
||||
|
||||
#if !defined(MBEDTLS_CONFIG_FILE)
|
||||
#include "config.h"
|
||||
#else
|
||||
#include MBEDTLS_CONFIG_FILE
|
||||
#endif
|
||||
|
||||
/***************************************************************************//**
|
||||
* \addtogroup sl_crypto
|
||||
* \{
|
||||
******************************************************************************/
|
||||
|
||||
/***************************************************************************//**
|
||||
* \addtogroup sl_crypto_timing Portable timing interface
|
||||
* \brief Portable interface to the CPU cycle counter.
|
||||
* \{
|
||||
******************************************************************************/
|
||||
|
||||
#if defined(MBEDTLS_TIMING_ALT)
|
||||
|
||||
/* SiliconLabs timing implementation */
|
||||
|
||||
#include "em_device.h"
|
||||
#include <stdint.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/**
|
||||
* \brief Initialize timing resources.
|
||||
*
|
||||
*/
|
||||
void mbedtls_timing_init( void );
|
||||
|
||||
/**
|
||||
* \brief Stop and free up timing resources.
|
||||
*
|
||||
*/
|
||||
void mbedtls_timing_free( void );
|
||||
|
||||
/**
|
||||
* \brief Return the CPU cycle counter value
|
||||
*
|
||||
*/
|
||||
static inline unsigned long mbedtls_timing_hardclock( void )
|
||||
{
|
||||
return( DWT->CYCCNT );
|
||||
}
|
||||
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* MBEDTLS_TIMING_ALT */
|
||||
|
||||
/** \} (end addtogroup sl_crypto) */
|
||||
/** \} (end addtogroup sl_crypto_timing) */
|
||||
|
||||
#endif /* MBEDTLS_TIMING_ALT_H */
|
|
@ -0,0 +1 @@
|
|||
*~
|
|
@ -0,0 +1,41 @@
|
|||
/*
|
||||
* Definitions for authenticated encryption algorithms common to
|
||||
* all crypto devices (AES, CRYPTO, etc.)
|
||||
*
|
||||
* Copyright (C) 2016 Silicon Labs, http://www.silabs.com
|
||||
* 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 __SILICON_LABS_AESDRV_AUTHENCR_H
|
||||
#define __SILICON_LABS_AESDRV_AUTHENCR_H
|
||||
|
||||
#define CCM_MAX_DATA_LENGTH (0x10000-1)
|
||||
|
||||
Ecode_t AESDRV_CCM_Generalized(AESDRV_Context_t* pAesdrvContext,
|
||||
const uint8_t* pDataInput,
|
||||
uint8_t* pOutputData,
|
||||
const uint32_t dataLength,
|
||||
const uint8_t* pHdr,
|
||||
const uint32_t hdrLength,
|
||||
const uint8_t* pKey,
|
||||
const uint32_t keyLength,
|
||||
const uint8_t* pNonce,
|
||||
const uint32_t nonceLength,
|
||||
uint8_t* pAuthTag,
|
||||
const uint8_t authTagLength,
|
||||
const bool encrypt,
|
||||
const bool encryptedPayload);
|
||||
|
||||
#endif /* __SILICON_LABS_AESDRV_AUTHENCR_H */
|
|
@ -0,0 +1,701 @@
|
|||
/*
|
||||
* Authenticated encryption algorithms implementation using AES hw module.
|
||||
*
|
||||
* Copyright (C) 2016 Silicon Labs, http://www.silabs.com
|
||||
* 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 "em_device.h"
|
||||
|
||||
#if defined(AES_COUNT) && (AES_COUNT > 0)
|
||||
|
||||
#if defined( AES_CTRL_KEYBUFEN )
|
||||
|
||||
#if !defined(MBEDTLS_CONFIG_FILE)
|
||||
#include "mbedtls/config.h"
|
||||
#else
|
||||
#include MBEDTLS_CONFIG_FILE
|
||||
#endif
|
||||
|
||||
#include "aesdrv_internal.h"
|
||||
#include "aesdrv_authencr.h"
|
||||
#include "aesdrv_common_aes.h"
|
||||
#include "em_aes.h"
|
||||
#include "em_assert.h"
|
||||
#include "string.h"
|
||||
|
||||
/** @cond DO_NOT_INCLUDE_WITH_DOXYGEN */
|
||||
|
||||
/*******************************************************************************
|
||||
****************************** PROTOTYPES *********************************
|
||||
******************************************************************************/
|
||||
static Ecode_t aesdrv_CCM_MICCompute(AESDRV_Context_t* pAesdrvContext,
|
||||
const uint8_t* pDataInput,
|
||||
const uint32_t dataLength,
|
||||
const uint8_t* pHdr,
|
||||
const uint32_t hdrLength,
|
||||
const uint8_t* pAuthTag,
|
||||
const uint8_t authTagLength,
|
||||
const bool encryptedPayload,
|
||||
const bool encrypt);
|
||||
static inline void aesdrv_CCM_CtrInit(const uint8_t* pNonce,
|
||||
uint32_t* ctr,
|
||||
bool ctrToZero);
|
||||
static inline void aesdrv_CCM_Nonce(uint32_t* ccmCounter,
|
||||
uint32_t* ctr0,
|
||||
uint8_t authTagLength,
|
||||
uint32_t la,
|
||||
uint32_t lm);
|
||||
static inline void aesdrv_CCM_AMICCompute(const uint8_t* pHdr,
|
||||
uint32_t hdrLength);
|
||||
static inline void aesdrv_CCM_PMICCompute(const uint8_t* pDataInput,
|
||||
uint32_t length);
|
||||
static inline void aesdrv_CCM_CTR128(uint32_t* ccmCounter,
|
||||
uint32_t* out,
|
||||
uint32_t* in,
|
||||
uint32_t loopLength);
|
||||
static inline void aesdrv_CCM_CTR128Single(uint32_t* ccmCounter,
|
||||
uint32_t* out,
|
||||
uint32_t* in);
|
||||
static inline void aesdrv_CCM_DataWrite(const uint32_t* in);
|
||||
static inline void aesdrv_CCM_DataRead(uint32_t* out);
|
||||
static inline void aesdrv_CCM_DataRevRead(uint32_t* out);
|
||||
static inline void aesdrv_CCM_XorDataWrite(const uint32_t* in);
|
||||
static inline void aesdrv_CCM_XorDataRevWrite(const uint32_t* in);
|
||||
|
||||
/** @endcond */
|
||||
|
||||
/*******************************************************************************
|
||||
*************************** GLOBAL FUNCTIONS ******************************
|
||||
******************************************************************************/
|
||||
|
||||
/***************************************************************************//**
|
||||
* @brief
|
||||
* CCM optimized for BLE
|
||||
*
|
||||
* @details
|
||||
* This function is an implementation of CCM optimized for Bluetooth Low Energy
|
||||
* (BLE). This function assumes fixed header size (1 byte),
|
||||
* fixed authentication tag (4bytes), fixed length field size (2 bytes)
|
||||
*
|
||||
* @param pData
|
||||
* Pointer to data
|
||||
*
|
||||
* @param dataLength
|
||||
* length of data (max. 27)
|
||||
*
|
||||
* @param hdr
|
||||
* 1 byte header
|
||||
*
|
||||
* @param pKey
|
||||
* 10 byte Security Key. If pKey is NULL, the current key will be used.
|
||||
*
|
||||
* @param pNonce
|
||||
* 13 byte nonce
|
||||
*
|
||||
* @param encrypt
|
||||
* true - encrypt
|
||||
* false - decrypt
|
||||
*
|
||||
* @return
|
||||
* ECODE_OK if success. Error code if failure.
|
||||
* Encryption will always succeed.
|
||||
* Decryption may fail if the authentication fails.
|
||||
*/
|
||||
Ecode_t AESDRV_CCMBLE(AESDRV_Context_t* pAesdrvContext,
|
||||
uint8_t* pData,
|
||||
const uint32_t dataLength,
|
||||
uint8_t hdr,
|
||||
const uint8_t* pKey,
|
||||
const uint8_t* pNonce,
|
||||
uint8_t* pAuthTag,
|
||||
const bool encrypt
|
||||
)
|
||||
{
|
||||
return AESDRV_CCM(pAesdrvContext,
|
||||
pData, pData, dataLength,
|
||||
&hdr, 1,
|
||||
pKey, 128/8, /* keyLength */
|
||||
pNonce, 13,
|
||||
pAuthTag, 4,
|
||||
encrypt);
|
||||
}
|
||||
|
||||
/** @cond DO_NOT_INCLUDE_WITH_DOXYGEN */
|
||||
|
||||
/***************************************************************************//**
|
||||
* @brief
|
||||
* Generalized, internal CCM function supporting both CCM and CCM*.
|
||||
******************************************************************************/
|
||||
Ecode_t AESDRV_CCM_Generalized(AESDRV_Context_t* pAesdrvContext,
|
||||
const uint8_t* pDataInput,
|
||||
uint8_t* pDataOutput,
|
||||
const uint32_t dataLength,
|
||||
const uint8_t* pHdr,
|
||||
const uint32_t hdrLength,
|
||||
const uint8_t* pKey,
|
||||
const uint32_t keyLength,
|
||||
const uint8_t* pNonce,
|
||||
const uint32_t nonceLength,
|
||||
uint8_t* pAuthTag,
|
||||
const uint8_t authTagLength,
|
||||
const bool encrypt,
|
||||
const bool encryptedPayload)
|
||||
{
|
||||
int32_t i;
|
||||
uint8_t lastBlock[16];
|
||||
uint32_t lastBlockLen;
|
||||
uint32_t wholeBlockLen;
|
||||
Ecode_t status = ECODE_OK;
|
||||
const uint32_t * const _pKey = (const uint32_t *)pKey;
|
||||
|
||||
if ( (keyLength != 128/8) ||
|
||||
(nonceLength != 13) ||
|
||||
(dataLength > CCM_MAX_DATA_LENGTH) )
|
||||
{
|
||||
return MBEDTLS_ECODE_AESDRV_INVALID_PARAM;
|
||||
}
|
||||
|
||||
/* Enable AES clock. */
|
||||
AESDRV_CLOCK_ENABLE;
|
||||
|
||||
AES->CTRL = AES_CTRL_KEYBUFEN | AES_CTRL_XORSTART | AES_CTRL_DATASTART;
|
||||
|
||||
/* Load key into high key for key buffer usage */
|
||||
for (i = 3; i >= 0; i--)
|
||||
{
|
||||
AES->KEYHA = __REV(_pKey[i]);
|
||||
}
|
||||
|
||||
/* Compute counter and store in CCM counter in context structure. */
|
||||
aesdrv_CCM_CtrInit(pNonce,
|
||||
pAesdrvContext->ccmCounter,
|
||||
authTagLength && encrypt);
|
||||
if (authTagLength)
|
||||
{
|
||||
if (encrypt)
|
||||
{
|
||||
status =
|
||||
aesdrv_CCM_MICCompute(pAesdrvContext,
|
||||
pDataInput, dataLength,
|
||||
pHdr, hdrLength,
|
||||
pAuthTag, authTagLength,
|
||||
encryptedPayload,
|
||||
encrypt);
|
||||
}
|
||||
}
|
||||
|
||||
/* Encrypt / decrypt data */
|
||||
if (encryptedPayload)
|
||||
{
|
||||
lastBlockLen = dataLength%16;
|
||||
wholeBlockLen = dataLength/16;
|
||||
|
||||
/* Handle whole blocks first. Last one needs zero padding if it is smaller
|
||||
* than block size (16 bytes).*/
|
||||
if (wholeBlockLen)
|
||||
{
|
||||
aesdrv_CCM_CTR128(pAesdrvContext->ccmCounter,
|
||||
(uint32_t*)pDataOutput,
|
||||
(uint32_t*)pDataInput,
|
||||
wholeBlockLen);
|
||||
}
|
||||
|
||||
if (lastBlockLen)
|
||||
{
|
||||
aesdrv_CCM_CTR128Single(pAesdrvContext->ccmCounter,
|
||||
(uint32_t*)lastBlock,
|
||||
(uint32_t*)&pDataInput[dataLength-lastBlockLen]);
|
||||
(void) memcpy(&pDataOutput[dataLength-lastBlockLen],
|
||||
lastBlock,
|
||||
lastBlockLen);
|
||||
}
|
||||
}
|
||||
|
||||
/* Compute authentication part for decryption */
|
||||
if (!encrypt && authTagLength)
|
||||
{
|
||||
aesdrv_CCM_CtrInit(pNonce, pAesdrvContext->ccmCounter, !encrypt);
|
||||
/* Compute the authentication tag MACTag from decrypted data */
|
||||
status = aesdrv_CCM_MICCompute(pAesdrvContext,
|
||||
pDataOutput, dataLength,
|
||||
pHdr, hdrLength,
|
||||
pAuthTag, authTagLength,
|
||||
encryptedPayload,
|
||||
encrypt);
|
||||
if (MBEDTLS_ECODE_AESDRV_AUTHENTICATION_FAILED == status)
|
||||
{
|
||||
memset(pDataOutput, 0, dataLength);
|
||||
}
|
||||
}
|
||||
|
||||
/* Disable AES clock. */
|
||||
AESDRV_CLOCK_DISABLE;
|
||||
return status;
|
||||
}
|
||||
|
||||
/*******************************************************************************
|
||||
*************************** LOCAL FUNCTIONS *******************************
|
||||
******************************************************************************/
|
||||
|
||||
/**
|
||||
* Function calculates CCM MIC. Function assumes that CTR IV counter is already
|
||||
* initialized. In case of encryption calculated tag is appended to pData. In
|
||||
* case of decryption calculated tag is compared against tag located at the end
|
||||
* of pData.
|
||||
*
|
||||
* @param pDataInput
|
||||
* A pointer to PlainText.
|
||||
*
|
||||
* @param dataLength
|
||||
* PlainText Length.
|
||||
*
|
||||
* @param pHdr
|
||||
* A pointer to AuthData.
|
||||
*
|
||||
* @param hdrLength
|
||||
* AuthData length.
|
||||
*
|
||||
* @param authTagLength
|
||||
* Length of AuthenticationTag
|
||||
*
|
||||
* @param encryptedPayload
|
||||
* true - authentication and encryption
|
||||
* false - authentication only
|
||||
*
|
||||
* @param encrypt
|
||||
* true - encryption
|
||||
* false - decryption
|
||||
*
|
||||
* @return Error code
|
||||
*/
|
||||
static Ecode_t aesdrv_CCM_MICCompute(AESDRV_Context_t* pAesdrvContext,
|
||||
const uint8_t* pDataInput,
|
||||
const uint32_t dataLength,
|
||||
const uint8_t* pHdr,
|
||||
const uint32_t hdrLength,
|
||||
const uint8_t* pAuthTag,
|
||||
const uint8_t authTagLength,
|
||||
const bool encryptedPayload,
|
||||
const bool encrypt)
|
||||
{
|
||||
uint32_t tmpBuf[4];
|
||||
uint32_t tmpCtrl;
|
||||
uint32_t *pTag = (uint32_t*)pAuthTag;
|
||||
uint32_t lm;
|
||||
uint32_t la;
|
||||
Ecode_t status = ECODE_OK;
|
||||
|
||||
if (encryptedPayload)
|
||||
{
|
||||
lm = dataLength;
|
||||
la = hdrLength;
|
||||
}
|
||||
else
|
||||
{
|
||||
la = hdrLength + dataLength;
|
||||
lm = 0;
|
||||
}
|
||||
|
||||
aesdrv_CCM_Nonce(pAesdrvContext->ccmCounter, tmpBuf, authTagLength, la, lm);
|
||||
|
||||
/* Calculate authenticaton part of MIC. */
|
||||
if (la)
|
||||
{
|
||||
aesdrv_CCM_AMICCompute(pHdr, la);
|
||||
}
|
||||
|
||||
/* Calculate plaintext part of MIC. */
|
||||
aesdrv_CCM_PMICCompute(pDataInput, lm);
|
||||
|
||||
/* Disable AES functionality - auto start after writing to XORDATA. Writing
|
||||
* to XORDATA will just do XOR. */
|
||||
tmpCtrl = AES->CTRL;
|
||||
AES->CTRL = tmpCtrl & (~AES_CTRL_XORSTART);
|
||||
|
||||
/* AES_DATA register contains MIC which is not CTR encrypted. Xor already
|
||||
* calculated CTR cipher block with clear MIC. After that operation AES_DATA
|
||||
* contains proper MIC.*/
|
||||
aesdrv_CCM_XorDataWrite(tmpBuf);
|
||||
|
||||
/* Reenable auto AES start after writing to XORDATA. */
|
||||
AES->CTRL = tmpCtrl;
|
||||
|
||||
/* Read out 16 byte long authentication tag. */
|
||||
aesdrv_CCM_DataRevRead(tmpBuf);
|
||||
|
||||
if (encrypt)
|
||||
{
|
||||
/* In case of encryption, copy authentication tag to packet. */
|
||||
memcpy(pTag,tmpBuf,authTagLength);
|
||||
}
|
||||
else
|
||||
{
|
||||
/* In case of decryption compare provided authentication tag with one
|
||||
* which was calculated. */
|
||||
if (memcmp(pTag,tmpBuf,authTagLength))
|
||||
{
|
||||
status = MBEDTLS_ECODE_AESDRV_AUTHENTICATION_FAILED;
|
||||
}
|
||||
}
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief
|
||||
* Function initializes counter. It can initialize counter to 0 or 1 based on
|
||||
* function parameter.
|
||||
*
|
||||
* @param pNonce
|
||||
* A pointer to 13 bytes long nonce.
|
||||
*
|
||||
* @param ctr
|
||||
* A pointer to 16 byte CTR counter.
|
||||
*
|
||||
* @param ctrToZero
|
||||
* true - counter initialized to 0
|
||||
* false - counter initialized to 1
|
||||
*/
|
||||
static inline void aesdrv_CCM_CtrInit(const uint8_t* pNonce,
|
||||
uint32_t* ctr,
|
||||
bool ctrToZero)
|
||||
{
|
||||
uint32_t ctrValue = ctrToZero ? 0 : 0x01000000;
|
||||
|
||||
/* CCM Counter consists of:
|
||||
* flags - 1 byte
|
||||
* Nonce - 13 bytes
|
||||
* counter - 2 bytes
|
||||
* Counter is initialized taking into account that AES is working with reversed
|
||||
* byte order. */
|
||||
ctr[0] = __REV(ctrValue | *(uint16_t *)(&pNonce[11]));
|
||||
ctr[1] = __REV(*(uint32_t *)(&pNonce[7]));
|
||||
ctr[2] = __REV(*(uint32_t *)(&pNonce[3]));
|
||||
ctr[3] = __REV((2-1) | (*(uint32_t *)(&pNonce[0]) << 8));
|
||||
}
|
||||
|
||||
static inline void aesdrv_CCM_DataWrite(const uint32_t* in)
|
||||
{
|
||||
AES->DATA = in[0];
|
||||
AES->DATA = in[1];
|
||||
AES->DATA = in[2];
|
||||
AES->DATA = in[3];
|
||||
}
|
||||
|
||||
static inline void aesdrv_CCM_DataRead(uint32_t * out)
|
||||
{
|
||||
out[0] = AES->DATA;
|
||||
out[1] = AES->DATA;
|
||||
out[2] = AES->DATA;
|
||||
out[3] = AES->DATA;
|
||||
}
|
||||
|
||||
static inline void aesdrv_CCM_DataRevRead(uint32_t * out)
|
||||
{
|
||||
out[3] = __REV(AES->DATA);
|
||||
out[2] = __REV(AES->DATA);
|
||||
out[1] = __REV(AES->DATA);
|
||||
out[0] = __REV(AES->DATA);
|
||||
}
|
||||
|
||||
static inline void aesdrv_CCM_XorDataWrite(const uint32_t* in)
|
||||
{
|
||||
AES->XORDATA = in[0];
|
||||
AES->XORDATA = in[1];
|
||||
AES->XORDATA = in[2];
|
||||
AES->XORDATA = in[3];
|
||||
}
|
||||
|
||||
static inline void aesdrv_CCM_XorDataRevWrite(const uint32_t* in)
|
||||
{
|
||||
AES->XORDATA = __REV(in[3]);
|
||||
AES->XORDATA = __REV(in[2]);
|
||||
AES->XORDATA = __REV(in[1]);
|
||||
AES->XORDATA = __REV(in[0]);
|
||||
}
|
||||
|
||||
/**
|
||||
* Function prepares IV value for CBC according to CCM spec and calculates
|
||||
* counter key to be XOR'ed with authentication tag.
|
||||
*
|
||||
* @param ctr0
|
||||
* A pointer to memory where encrypted counter will be stored. It is later used
|
||||
* to encrypt authentication tag.
|
||||
*
|
||||
* @param authTagLength
|
||||
* Length of Authentication tag. Can be 0,4,8,16
|
||||
*
|
||||
* @param lm
|
||||
* Lm parameter from CCM spec.
|
||||
*
|
||||
*/
|
||||
static inline void aesdrv_CCM_Nonce(uint32_t* ccmCounter,
|
||||
uint32_t* ctr0,
|
||||
uint8_t authTagLength,
|
||||
uint32_t la,
|
||||
uint32_t lm)
|
||||
{
|
||||
uint8_t flags;
|
||||
uint8_t lenEnc;
|
||||
|
||||
/* Counter is written to AES, AES starts encryption. While AES is processing
|
||||
* first block for CCM CBC (B0) can be prepared utilizing similarities between
|
||||
* CTR counter and B0.
|
||||
*/
|
||||
aesdrv_CCM_DataWrite(ccmCounter);
|
||||
|
||||
/* Prepare flags to form B0 block. */
|
||||
flags = la ? 0x41 : 1;
|
||||
if (authTagLength)
|
||||
{
|
||||
flags |= ((authTagLength-2)/2)<<3;
|
||||
}
|
||||
|
||||
/* Modify CTR counter to form B0. */
|
||||
ccmCounter[0] |= lm;
|
||||
lenEnc = ccmCounter[3] >> 24;
|
||||
ccmCounter[3] &= 0x00FFFFFF;
|
||||
ccmCounter[3] |= (flags << 24);
|
||||
|
||||
while (AES->STATUS & AES_STATUS_RUNNING)
|
||||
;
|
||||
|
||||
/* Read out encrypted counter to be used to encrypt authentication tag. */
|
||||
aesdrv_CCM_DataRead(ctr0);
|
||||
|
||||
/* Process block B0. */
|
||||
aesdrv_CCM_DataWrite(ccmCounter);
|
||||
|
||||
/* Transform back B0 to CTR counter. Setting counter to 1. It will be later on
|
||||
* used when payload will be encrypted. It's done while waiting for AES to
|
||||
* complete B0 encryption.
|
||||
*/
|
||||
ccmCounter[3] &= 0x00FFFFFF;
|
||||
ccmCounter[3] |= lenEnc<<24;
|
||||
ccmCounter[0] &= 0xFFFF0000;
|
||||
ccmCounter[0] |= 0x00000001;
|
||||
|
||||
while (AES->STATUS & AES_STATUS_RUNNING)
|
||||
;
|
||||
}
|
||||
|
||||
/**
|
||||
* Function calculates a Auth part of CBC Authentication tag. Once function
|
||||
* terminates AES->DATA register contains partial authentication tag.
|
||||
*
|
||||
* @param pHdr
|
||||
* A pointer to AuthData.
|
||||
*
|
||||
* @param hdrLength
|
||||
* Length of AuthData
|
||||
*/
|
||||
static inline void aesdrv_CCM_AMICCompute(const uint8_t * pHdr, uint32_t hdrLength)
|
||||
{
|
||||
bool firstBlock = true;
|
||||
uint16_t length = hdrLength+2;
|
||||
uint8_t * _pData = (uint8_t *)pHdr;
|
||||
uint32_t tmp = 0;
|
||||
uint32_t padBuf[4];
|
||||
|
||||
/* Prepare first block of AuthData - starting with L(a) field. */
|
||||
if (length > 16)
|
||||
{
|
||||
hdrLength = __REV16(hdrLength);
|
||||
tmp = __REV(hdrLength | ((*(uint16_t*)_pData)<<16));
|
||||
_pData -= 2;
|
||||
}
|
||||
|
||||
while (length)
|
||||
{
|
||||
if (length > 16)
|
||||
{
|
||||
/* For each AuthData block perform CBC. Last word (first in CCM spec
|
||||
* byte order) is different for first block (contains length field). It's
|
||||
* handled in loop prolog. */
|
||||
AES->XORDATA = __REV(((uint32_t *)_pData)[3]);
|
||||
AES->XORDATA = __REV(((uint32_t *)_pData)[2]);
|
||||
AES->XORDATA = __REV(((uint32_t *)_pData)[1]);
|
||||
AES->XORDATA = tmp;
|
||||
|
||||
_pData +=16;
|
||||
length -= 16;
|
||||
|
||||
firstBlock = false;
|
||||
/* Clear padBuf while waiting for AES completion - to be used in last,
|
||||
* incomplete block. */
|
||||
memset(padBuf,0,16);
|
||||
|
||||
/* Prepare in advance last word for next block - it is done while waiting
|
||||
* for AES completion. */
|
||||
tmp = __REV(((uint32_t *)_pData)[0]);
|
||||
|
||||
while (AES->STATUS & AES_STATUS_RUNNING)
|
||||
;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (firstBlock)
|
||||
{
|
||||
/* In case first block is also last block length field L(a) must be
|
||||
* concatenated with AuthData. */
|
||||
memset(padBuf,0,16);
|
||||
padBuf[0] = __REV16(hdrLength);
|
||||
memcpy( &((uint8_t*)padBuf)[2], _pData, length-2);
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Copy last portion of data to zero padded buffer.*/
|
||||
memcpy(padBuf,_pData,length);
|
||||
}
|
||||
|
||||
aesdrv_CCM_XorDataRevWrite(padBuf);
|
||||
length = 0;
|
||||
|
||||
while (AES->STATUS & AES_STATUS_RUNNING)
|
||||
;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Function calculates PlainText part of CBC Authentication tag.
|
||||
*
|
||||
* @param pDataInput
|
||||
* A pointer to PlainText
|
||||
*
|
||||
* @param length
|
||||
* Length of PlainText
|
||||
*/
|
||||
static inline void aesdrv_CCM_PMICCompute(const uint8_t * pDataInput, uint32_t length)
|
||||
{
|
||||
uint32_t padBuf[4];
|
||||
uint32_t * _pDataInput = (uint32_t *)pDataInput;
|
||||
|
||||
while (length)
|
||||
{
|
||||
/* First process all full blcoks. */
|
||||
if (length > 16)
|
||||
{
|
||||
aesdrv_CCM_XorDataRevWrite(_pDataInput);
|
||||
|
||||
_pDataInput +=4;
|
||||
length -= 16;
|
||||
while (AES->STATUS & AES_STATUS_RUNNING)
|
||||
;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Zero pad last, incomplete block. */
|
||||
memset(padBuf,0,16);
|
||||
memcpy(padBuf,_pDataInput,length);
|
||||
aesdrv_CCM_XorDataRevWrite(padBuf);
|
||||
length = 0;
|
||||
|
||||
while (AES->STATUS & AES_STATUS_RUNNING)
|
||||
;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Function performs CTR with 128bit AES on multiple blocks.
|
||||
*
|
||||
* @param out
|
||||
* A pointer to output data.
|
||||
*
|
||||
* @param in
|
||||
* A pointer to input data.
|
||||
*
|
||||
* @param loopLength
|
||||
* Number of blocks
|
||||
*/
|
||||
static inline void aesdrv_CCM_CTR128(uint32_t* ccmCounter,
|
||||
uint32_t* out,
|
||||
uint32_t* in,
|
||||
uint32_t loopLength)
|
||||
{
|
||||
uint32_t ctrProduct[4];
|
||||
|
||||
memset(ctrProduct,0,16);
|
||||
|
||||
/* Encrypt counter */
|
||||
aesdrv_CCM_DataWrite(ccmCounter);
|
||||
/* Increment counter during encryption. */
|
||||
ccmCounter[0]++;
|
||||
while (AES->STATUS & AES_STATUS_RUNNING);
|
||||
aesdrv_CCM_DataRead(ctrProduct);
|
||||
|
||||
while (--loopLength)
|
||||
{
|
||||
aesdrv_CCM_DataWrite(ccmCounter);
|
||||
|
||||
/* Perform XOR with CTR product of previous block while waiting for AES
|
||||
* completion. */
|
||||
out[0] = in[0] ^ __REV(ctrProduct[3]);
|
||||
out[1] = in[1] ^ __REV(ctrProduct[2]);
|
||||
out[2] = in[2] ^ __REV(ctrProduct[1]);
|
||||
out[3] = in[3] ^ __REV(ctrProduct[0]);
|
||||
|
||||
/* Increment counter */
|
||||
ccmCounter[0]++;
|
||||
|
||||
while (AES->STATUS & AES_STATUS_RUNNING)
|
||||
;
|
||||
|
||||
aesdrv_CCM_DataRead(ctrProduct);
|
||||
|
||||
out += 4;
|
||||
in += 4;
|
||||
}
|
||||
|
||||
/* Perform XOR with CTR product */
|
||||
out[0] = in[0] ^ __REV(ctrProduct[3]);
|
||||
out[1] = in[1] ^ __REV(ctrProduct[2]);
|
||||
out[2] = in[2] ^ __REV(ctrProduct[1]);
|
||||
out[3] = in[3] ^ __REV(ctrProduct[0]);
|
||||
}
|
||||
|
||||
/**
|
||||
* Function performs 128bit AES CTR on Single block.
|
||||
*
|
||||
* @param out
|
||||
* A pointer to output data.
|
||||
*
|
||||
* @param in
|
||||
* A pointer to input data.
|
||||
*/
|
||||
static inline void aesdrv_CCM_CTR128Single(uint32_t* ccmCounter,
|
||||
uint32_t* out,
|
||||
uint32_t* in)
|
||||
{
|
||||
|
||||
aesdrv_CCM_DataWrite(ccmCounter);
|
||||
|
||||
ccmCounter[0]++;
|
||||
|
||||
while (AES->STATUS & AES_STATUS_RUNNING)
|
||||
;
|
||||
|
||||
out[3] = in[3] ^ __REV(AES->DATA);
|
||||
out[2] = in[2] ^ __REV(AES->DATA);
|
||||
out[1] = in[1] ^ __REV(AES->DATA);
|
||||
out[0] = in[0] ^ __REV(AES->DATA);
|
||||
}
|
||||
/** @endcond */
|
||||
|
||||
#endif /* #if defined( AES_CTRL_KEYBUFEN ) */
|
||||
|
||||
#endif /* #if defined(AES_COUNT) && (AES_COUNT > 0) */
|
File diff suppressed because it is too large
Load Diff
|
@ -0,0 +1,403 @@
|
|||
/*
|
||||
* AES block cipher algorithms implementation using AES hw module
|
||||
*
|
||||
* Copyright (C) 2016 Silicon Labs, http://www.silabs.com
|
||||
* 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.
|
||||
*/
|
||||
/*
|
||||
* This is an implementation of block cipher function using the AES hw
|
||||
* module for acceleration.
|
||||
*
|
||||
* The module implements following interfaces:
|
||||
*
|
||||
* AESDRV_CBCx()
|
||||
* AESDRV_CFBx()
|
||||
* AESDRV_CTRx()
|
||||
* AESDRV_DecryptKey128()
|
||||
* AESDRV_DecryptKey256()
|
||||
* AESDRV_ECBx()
|
||||
* AESDRV_OFBx()
|
||||
*
|
||||
* Functions are mostly wrappers of emlib AES (em_aes.h) since block cipher
|
||||
* functionality is provided by emlib.
|
||||
*/
|
||||
|
||||
#include "em_device.h"
|
||||
|
||||
#if defined(AES_COUNT) && (AES_COUNT > 0)
|
||||
|
||||
#if !defined(MBEDTLS_CONFIG_FILE)
|
||||
#include "mbedtls/config.h"
|
||||
#else
|
||||
#include MBEDTLS_CONFIG_FILE
|
||||
#endif
|
||||
|
||||
#include "aesdrv_internal.h"
|
||||
#include "aesdrv_common_aes.h"
|
||||
#include "em_aes.h"
|
||||
#include <string.h>
|
||||
|
||||
/*******************************************************************************
|
||||
************************** GLOBAL FUNCTIONS *******************************
|
||||
******************************************************************************/
|
||||
|
||||
/*
|
||||
* Generate 128 bit decryption key from 128 bit encryption key. The decryption
|
||||
* key is used for some cipher modes when decrypting.
|
||||
* Please refer to aesdrv.h for detailed description.
|
||||
*/
|
||||
Ecode_t AESDRV_DecryptKey128(AESDRV_Context_t* pAesdrvContext,
|
||||
uint8_t* out,
|
||||
const uint8_t* in)
|
||||
{
|
||||
(void) pAesdrvContext; /* The pAesdrvContext parameter is not used for
|
||||
basic AES block cipher mode. */
|
||||
AESDRV_CLOCK_ENABLE;
|
||||
AES_DecryptKey128(out,in);
|
||||
AESDRV_CLOCK_DISABLE;
|
||||
return ECODE_OK;
|
||||
}
|
||||
|
||||
/*
|
||||
* Generate 256 bit decryption key from 256 bit encryption key. The decryption
|
||||
* key is used for some cipher modes when decrypting.
|
||||
* Please refer to aesdrv.h for detailed description.
|
||||
*/
|
||||
Ecode_t AESDRV_DecryptKey256(AESDRV_Context_t* pAesdrvContext,
|
||||
uint8_t* out,
|
||||
const uint8_t * in)
|
||||
{
|
||||
(void) pAesdrvContext; /* The pAesdrvContext parameter is not used for
|
||||
basic AES block cipher mode. */
|
||||
#if defined( AES_CTRL_AES256 )
|
||||
AESDRV_CLOCK_ENABLE;
|
||||
AES_DecryptKey256(out,in);
|
||||
AESDRV_CLOCK_DISABLE;
|
||||
return ECODE_OK;
|
||||
#else
|
||||
(void) out; (void) in;
|
||||
return MBEDTLS_ECODE_AESDRV_NOT_SUPPORTED;
|
||||
#endif
|
||||
}
|
||||
|
||||
/*
|
||||
* Cipher-block chaining (CBC) cipher mode encryption/decryption, 128 bit key.
|
||||
* Please refer to aesdrv.h for detailed description.
|
||||
*/
|
||||
Ecode_t AESDRV_CBC128(AESDRV_Context_t* pAesdrvContext,
|
||||
uint8_t* out,
|
||||
const uint8_t* in,
|
||||
unsigned int len,
|
||||
const uint8_t* key,
|
||||
uint8_t* iv,
|
||||
bool encrypt
|
||||
)
|
||||
{
|
||||
(void) pAesdrvContext; /* The pAesdrvContext parameter is not used for
|
||||
basic AES block cipher mode. */
|
||||
uint8_t tmpIv[16];
|
||||
if (false == encrypt)
|
||||
{
|
||||
if (len>=16)
|
||||
memcpy(tmpIv, &in[len-16], 16);
|
||||
}
|
||||
AESDRV_CLOCK_ENABLE;
|
||||
AES_CBC128(out,in,len,key,iv,encrypt);
|
||||
AESDRV_CLOCK_DISABLE;
|
||||
if (len>=16)
|
||||
{
|
||||
if (encrypt)
|
||||
memcpy(iv, &out[len-16], 16);
|
||||
else
|
||||
memcpy(iv, tmpIv, 16);
|
||||
}
|
||||
return ECODE_OK;
|
||||
}
|
||||
|
||||
/*
|
||||
* Cipher-block chaining (CBC) cipher mode encryption/decryption, 256 bit key.
|
||||
* Please refer to aesdrv.h for detailed description.
|
||||
*/
|
||||
Ecode_t AESDRV_CBC256(AESDRV_Context_t* pAesdrvContext,
|
||||
uint8_t* out,
|
||||
const uint8_t* in,
|
||||
unsigned int len,
|
||||
const uint8_t* key,
|
||||
uint8_t* iv,
|
||||
bool encrypt
|
||||
)
|
||||
{
|
||||
(void) pAesdrvContext; /* The pAesdrvContext parameter is not used for
|
||||
basic AES block cipher mode. */
|
||||
#if defined( AES_CTRL_AES256 )
|
||||
uint8_t tmpIv[16];
|
||||
if (false == encrypt)
|
||||
{
|
||||
if (len>=16)
|
||||
memcpy(tmpIv, &in[len-16], 16);
|
||||
}
|
||||
|
||||
AESDRV_CLOCK_ENABLE;
|
||||
AES_CBC256(out,in,len,key,iv,encrypt);
|
||||
AESDRV_CLOCK_DISABLE;
|
||||
|
||||
if (len>=16)
|
||||
{
|
||||
if (encrypt)
|
||||
memcpy(iv, &out[len-16], 16);
|
||||
else
|
||||
memcpy(iv, tmpIv, 16);
|
||||
}
|
||||
return ECODE_OK;
|
||||
#else
|
||||
(void) out; (void) in; (void) len; (void) key; (void) iv; (void) encrypt;
|
||||
return MBEDTLS_ECODE_AESDRV_NOT_SUPPORTED;
|
||||
#endif
|
||||
}
|
||||
|
||||
/*
|
||||
* Cipher feedback (CFB) cipher mode encryption/decryption, 128 bit key.
|
||||
* Please refer to aesdrv.h for detailed description.
|
||||
*/
|
||||
Ecode_t AESDRV_CFB128(AESDRV_Context_t* pAesdrvContext,
|
||||
uint8_t* out,
|
||||
const uint8_t* in,
|
||||
unsigned int len,
|
||||
const uint8_t* key,
|
||||
uint8_t* iv,
|
||||
bool encrypt
|
||||
)
|
||||
{
|
||||
(void) pAesdrvContext; /* The pAesdrvContext parameter is not used for
|
||||
basic AES block cipher mode. */
|
||||
uint8_t tmpIv[16];
|
||||
if (false == encrypt)
|
||||
{
|
||||
if (len>=16)
|
||||
memcpy(tmpIv, &in[len-16], 16);
|
||||
}
|
||||
|
||||
AESDRV_CLOCK_ENABLE;
|
||||
AES_CFB128(out,in,len,key,iv,encrypt);
|
||||
AESDRV_CLOCK_DISABLE;
|
||||
|
||||
if (len>=16)
|
||||
{
|
||||
if (encrypt)
|
||||
memcpy(iv, &out[len-16], 16);
|
||||
else
|
||||
memcpy(iv, tmpIv, 16);
|
||||
}
|
||||
return ECODE_OK;
|
||||
}
|
||||
|
||||
/*
|
||||
* Cipher feedback (CFB) cipher mode encryption/decryption, 256 bit key.
|
||||
* Please refer to aesdrv.h for detailed description.
|
||||
*/
|
||||
Ecode_t AESDRV_CFB256(AESDRV_Context_t* pAesdrvContext,
|
||||
uint8_t* out,
|
||||
const uint8_t* in,
|
||||
unsigned int len,
|
||||
const uint8_t* key,
|
||||
uint8_t* iv,
|
||||
bool encrypt
|
||||
)
|
||||
{
|
||||
(void) pAesdrvContext; /* The pAesdrvContext parameter is not used for
|
||||
basic AES block cipher mode. */
|
||||
#if defined( AES_CTRL_AES256 )
|
||||
uint8_t tmpIv[16];
|
||||
if (false == encrypt)
|
||||
{
|
||||
if (len>=16)
|
||||
memcpy(tmpIv, &in[len-16], 16);
|
||||
}
|
||||
|
||||
AESDRV_CLOCK_ENABLE;
|
||||
AES_CFB256(out,in,len,key,iv,encrypt);
|
||||
AESDRV_CLOCK_DISABLE;
|
||||
|
||||
if (len>=16)
|
||||
{
|
||||
if (encrypt)
|
||||
memcpy(iv, &out[len-16], 16);
|
||||
else
|
||||
memcpy(iv, tmpIv, 16);
|
||||
}
|
||||
return ECODE_OK;
|
||||
#else
|
||||
(void) out; (void) in; (void) len; (void) key; (void) iv; (void) encrypt;
|
||||
return MBEDTLS_ECODE_AESDRV_NOT_SUPPORTED;
|
||||
#endif
|
||||
}
|
||||
|
||||
/*
|
||||
* Counter (CTR) cipher mode encryption/decryption, 128 bit key.
|
||||
* Please refer to aesdrv.h for detailed description.
|
||||
*/
|
||||
Ecode_t AESDRV_CTR128(AESDRV_Context_t* pAesdrvContext,
|
||||
uint8_t* out,
|
||||
const uint8_t* in,
|
||||
unsigned int len,
|
||||
const uint8_t* key,
|
||||
uint8_t* ctr,
|
||||
AESDRV_CtrCallback_t ctrCallback
|
||||
)
|
||||
{
|
||||
(void) pAesdrvContext; /* The pAesdrvContext parameter is not used for
|
||||
basic AES block cipher mode. */
|
||||
AESDRV_CtrCallback_t pCtrFunc;
|
||||
|
||||
if (ctrCallback)
|
||||
{
|
||||
pCtrFunc = ctrCallback;
|
||||
}
|
||||
else
|
||||
{
|
||||
pCtrFunc = AES_CTRUpdate32Bit;
|
||||
}
|
||||
|
||||
AESDRV_CLOCK_ENABLE;
|
||||
AES_CTR128(out,in,len,key,ctr,pCtrFunc);
|
||||
AESDRV_CLOCK_DISABLE;
|
||||
return ECODE_OK;
|
||||
}
|
||||
|
||||
/*
|
||||
* Counter (CTR) cipher mode encryption/decryption, 256 bit key.
|
||||
* Please refer to aesdrv.h for detailed description.
|
||||
*/
|
||||
Ecode_t AESDRV_CTR256(AESDRV_Context_t* pAesdrvContext,
|
||||
uint8_t* out,
|
||||
const uint8_t* in,
|
||||
unsigned int len,
|
||||
const uint8_t* key,
|
||||
uint8_t* ctr,
|
||||
AESDRV_CtrCallback_t ctrCallback
|
||||
)
|
||||
{
|
||||
(void) pAesdrvContext; /* The pAesdrvContext parameter is not used for
|
||||
basic AES block cipher mode. */
|
||||
#if defined( AES_CTRL_AES256 )
|
||||
AESDRV_CtrCallback_t pCtrFunc;
|
||||
|
||||
if (ctrCallback)
|
||||
{
|
||||
pCtrFunc = ctrCallback;
|
||||
}
|
||||
else
|
||||
{
|
||||
pCtrFunc = AES_CTRUpdate32Bit;
|
||||
}
|
||||
|
||||
AESDRV_CLOCK_ENABLE;
|
||||
AES_CTR256(out,in,len,key,ctr,pCtrFunc);
|
||||
AESDRV_CLOCK_DISABLE;
|
||||
return ECODE_OK;
|
||||
#else
|
||||
(void) out; (void) in; (void) len; (void) key; (void) ctr; (void) ctrCallback;
|
||||
return MBEDTLS_ECODE_AESDRV_NOT_SUPPORTED;
|
||||
#endif
|
||||
}
|
||||
|
||||
/*
|
||||
* Electronic Codebook (ECB) cipher mode encryption/decryption, 128 bit key.
|
||||
* Please refer to aesdrv.h for detailed description.
|
||||
*/
|
||||
Ecode_t AESDRV_ECB128(AESDRV_Context_t* pAesdrvContext,
|
||||
uint8_t* out,
|
||||
const uint8_t* in,
|
||||
unsigned int len,
|
||||
const uint8_t* key,
|
||||
bool encrypt
|
||||
)
|
||||
{
|
||||
(void) pAesdrvContext; /* The pAesdrvContext parameter is not used for
|
||||
basic AES block cipher mode. */
|
||||
AESDRV_CLOCK_ENABLE;
|
||||
AES_ECB128(out,in,len,key,encrypt);
|
||||
AESDRV_CLOCK_DISABLE;
|
||||
return ECODE_OK;
|
||||
}
|
||||
|
||||
/*
|
||||
* Electronic Codebook (ECB) cipher mode encryption/decryption, 256 bit key.
|
||||
* Please refer to aesdrv.h for detailed description.
|
||||
*/
|
||||
Ecode_t AESDRV_ECB256(AESDRV_Context_t* pAesdrvContext,
|
||||
uint8_t* out,
|
||||
const uint8_t* in,
|
||||
unsigned int len,
|
||||
const uint8_t* key,
|
||||
bool encrypt)
|
||||
{
|
||||
(void) pAesdrvContext; /* The pAesdrvContext parameter is not used for
|
||||
basic AES block cipher mode. */
|
||||
#if defined( AES_CTRL_AES256 )
|
||||
AESDRV_CLOCK_ENABLE;
|
||||
AES_ECB256(out,in,len,key,encrypt);
|
||||
AESDRV_CLOCK_DISABLE;
|
||||
return ECODE_OK;
|
||||
#else
|
||||
(void) out; (void) in; (void) len; (void) key; (void) encrypt;
|
||||
return MBEDTLS_ECODE_AESDRV_NOT_SUPPORTED;
|
||||
#endif
|
||||
}
|
||||
|
||||
/*
|
||||
* Output feedback (OFB) cipher mode encryption/decryption, 128 bit key.
|
||||
* Please refer to aesdrv.h for detailed description.
|
||||
*/
|
||||
Ecode_t AESDRV_OFB128(AESDRV_Context_t* pAesdrvContext,
|
||||
uint8_t* out,
|
||||
const uint8_t* in,
|
||||
unsigned int len,
|
||||
const uint8_t* key,
|
||||
uint8_t* iv)
|
||||
{
|
||||
(void) pAesdrvContext; /* The pAesdrvContext parameter is not used for
|
||||
basic AES block cipher mode. */
|
||||
AESDRV_CLOCK_ENABLE;
|
||||
AES_OFB128(out,in,len,key,iv);
|
||||
AESDRV_CLOCK_DISABLE;
|
||||
return ECODE_OK;
|
||||
}
|
||||
|
||||
/*
|
||||
* Output feedback (OFB) cipher mode encryption/decryption, 256 bit key.
|
||||
* Please refer to aesdrv.h for detailed description.
|
||||
*/
|
||||
Ecode_t AESDRV_OFB256(AESDRV_Context_t* pAesdrvContext,
|
||||
uint8_t* out,
|
||||
const uint8_t* in,
|
||||
unsigned int len,
|
||||
const uint8_t* key,
|
||||
uint8_t* iv)
|
||||
{
|
||||
(void) pAesdrvContext; /* The pAesdrvContext parameter is not used for
|
||||
basic AES block cipher mode. */
|
||||
#if defined( AES_CTRL_AES256 )
|
||||
AESDRV_CLOCK_ENABLE;
|
||||
AES_OFB256(out,in,len,key,iv);
|
||||
AESDRV_CLOCK_DISABLE;
|
||||
return ECODE_OK;
|
||||
#else
|
||||
(void) out; (void) in; (void) len; (void) key; (void) iv;
|
||||
return MBEDTLS_ECODE_AESDRV_NOT_SUPPORTED;
|
||||
#endif
|
||||
}
|
||||
|
||||
#endif /* #if defined(AES_COUNT) && (AES_COUNT > 0) */
|
File diff suppressed because it is too large
Load Diff
|
@ -0,0 +1,278 @@
|
|||
/*
|
||||
* Common functions for AES based algorithms for AES and CRYPTO hw modules.
|
||||
*
|
||||
* Copyright (C) 2016 Silicon Labs, http://www.silabs.com
|
||||
* 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 "em_device.h"
|
||||
|
||||
#if ( defined(CRYPTO_COUNT) && (CRYPTO_COUNT > 0) ) || \
|
||||
( defined(AES_COUNT) && (AES_COUNT > 0) )
|
||||
|
||||
#if !defined(MBEDTLS_CONFIG_FILE)
|
||||
#include "mbedtls/config.h"
|
||||
#else
|
||||
#include MBEDTLS_CONFIG_FILE
|
||||
#endif
|
||||
|
||||
#include "aesdrv_internal.h"
|
||||
#include "aesdrv_authencr.h"
|
||||
|
||||
#if defined(CRYPTO_PRESENT)
|
||||
#include "cryptodrv_internal.h"
|
||||
#include "aesdrv_common_crypto.h"
|
||||
#include "em_crypto.h"
|
||||
#endif
|
||||
|
||||
#include "em_assert.h"
|
||||
|
||||
/*******************************************************************************
|
||||
*************************** GLOBAL FUNCTIONS ******************************
|
||||
******************************************************************************/
|
||||
|
||||
/***************************************************************************//**
|
||||
* @brief
|
||||
* Computes the length of the MIC (Message Integrity Code)
|
||||
* for a given security level, as defined in IEEE Std 802.15.4-2006 table 95.
|
||||
*
|
||||
* @details
|
||||
* The two LSBs of securityLevel encodes a MIC length of 0, 4, 8, or 16.
|
||||
*
|
||||
* @param[in] securityLevel
|
||||
* Security level to use.
|
||||
*
|
||||
* @return
|
||||
* The length of the MIC for the given @p securityLevel
|
||||
******************************************************************************/
|
||||
uint8_t AESDRV_CCMStar_LengthOfMIC(uint8_t securityLevel)
|
||||
{
|
||||
securityLevel &= 3;
|
||||
if (securityLevel == 3)
|
||||
{
|
||||
securityLevel++;
|
||||
}
|
||||
return securityLevel * 4;
|
||||
}
|
||||
|
||||
/***************************************************************************//**
|
||||
* @brief
|
||||
* CCM block cipher mode encryption/decryption based on 128 bit AES.
|
||||
*
|
||||
* @details
|
||||
* Please see http://en.wikipedia.org/wiki/CCM_mode for a general description
|
||||
* of CCM.
|
||||
*
|
||||
* @param[in] pAesdrvContext
|
||||
* Pointer to AESDRV context structure.
|
||||
*
|
||||
* @param[in] pInputData
|
||||
* If @p encrypt is true, pInputData is the 'P' (payload) parameter in CCM.
|
||||
* I.e. the Payload data to encrypt.
|
||||
* If @p encrypt is false, pInputData is the 'C' (ciphertext) parameter in CCM.
|
||||
* I.e. the ciphertext data to decrypt.
|
||||
*
|
||||
* @param[out] pOutputData
|
||||
* If @p encrypt is true, pOututData is the 'C' (ciphertext) parameter in CCM.
|
||||
* I.e. the Ciphertext data as a result of encrypting the payload data.
|
||||
* If @p encrypt is false, pOutputData is the 'P' (payload) parameter in CCM.
|
||||
* I.e. the Payload data as a result of decrypting the ciphertext.
|
||||
*
|
||||
* @param[in] dataLength
|
||||
* Length of data to be encrypted/decrypted, referred to as 'p' in CCM.
|
||||
* Note that this does not include the length of the MIC which is specified
|
||||
* with @p authTagLength.
|
||||
*
|
||||
* @param[in] pHdr
|
||||
* The 'A' parameter in CCM.
|
||||
* Header is used for MIC calculation.
|
||||
* Must be at least @p hdrLength long.
|
||||
*
|
||||
* @param[in] hdrLength
|
||||
* The 'a' parameter in CCM.
|
||||
* Length of header.
|
||||
*
|
||||
* @param[in] pKey
|
||||
* The 'K' parameter in CCM.
|
||||
* Pointer to key buffer.
|
||||
* Currently only 128 bit keys (16 bytes) are supported.
|
||||
*
|
||||
* @param[in] keyLength
|
||||
* The length in bytes, of the @p pKey, i.e. the 'K' parameter in CCM.
|
||||
* Currently only 128 bit keys (16 bytes) are supported.
|
||||
*
|
||||
* @param[in] pNonce
|
||||
* The 'N' parameter in CCM.
|
||||
* Pointer to the nonce, which must have length 15-authTagLength
|
||||
* See @p authTagLength
|
||||
*
|
||||
* @param[in] nonceLength
|
||||
* The length in bytes, of the @p pNonce, i.e. the 'N' parameter in CCM.
|
||||
* Currently only nonce size equal to 13 bytes is supported.
|
||||
*
|
||||
* @param[in] pAuthTag
|
||||
* The 'MIC' parameter in CCM.
|
||||
* Pointer to the MIC buffer, which must have length @p authTagLength.
|
||||
*
|
||||
* @param[in] authTagLength
|
||||
* The 't' parameter in CCM.
|
||||
* The number of bytes used for the authentication tag.
|
||||
* Possible values are 0, 4, 6, 8, 10, 12, 14, 16.
|
||||
* Note that 0 is not a legal value in CCM, but is used for CCM*.
|
||||
*
|
||||
* @param[in] encrypt
|
||||
* Set to true to run the generation-encryption process,
|
||||
* false to run the decryption-verification process.
|
||||
*
|
||||
* @return
|
||||
* ECODE_OK if success. Error code if failure.
|
||||
* Encryption will always succeed.
|
||||
* Decryption may fail if the authentication fails.
|
||||
******************************************************************************/
|
||||
Ecode_t AESDRV_CCM(AESDRV_Context_t* pAesdrvContext,
|
||||
const uint8_t* pDataInput,
|
||||
uint8_t* pDataOutput,
|
||||
const uint32_t dataLength,
|
||||
const uint8_t* pHdr,
|
||||
const uint32_t hdrLength,
|
||||
const uint8_t* pKey,
|
||||
const uint32_t keyLength,
|
||||
const uint8_t* pNonce,
|
||||
const uint32_t nonceLength,
|
||||
uint8_t* pAuthTag,
|
||||
const uint8_t authTagLength,
|
||||
const bool encrypt)
|
||||
{
|
||||
return AESDRV_CCM_Generalized( pAesdrvContext,
|
||||
pDataInput,
|
||||
pDataOutput,
|
||||
dataLength,
|
||||
pHdr,
|
||||
hdrLength,
|
||||
pKey,
|
||||
keyLength,
|
||||
pNonce,
|
||||
nonceLength,
|
||||
pAuthTag,
|
||||
authTagLength,
|
||||
encrypt,
|
||||
true);
|
||||
}
|
||||
|
||||
/***************************************************************************//**
|
||||
* @brief
|
||||
* CCM* block cipher mode encryption/decryption based on 128 bit AES.
|
||||
*
|
||||
* @details
|
||||
* Please see IEEE Std 802.15.4-2006 Annex B for a description of CCM*.
|
||||
*
|
||||
* @param[in] pAesdrvContext
|
||||
* Pointer to AESDRV context structure.
|
||||
*
|
||||
* @param[in] pDataInput
|
||||
* If @p encrypt is true, pDataInput is the plaintext.
|
||||
* I.e. the payload data to encrypt.
|
||||
* If @p encrypt is false, pDataInput is the ciphertext.
|
||||
* I.e. the ciphertext data to decrypt.
|
||||
*
|
||||
* @param[out] pDataOutput
|
||||
* If @p encrypt is true, pDataOutput is the ciphertext.
|
||||
* I.e. the Ciphertext data as a result of encrypting the payload data.
|
||||
* If @p encrypt is false, pDataOutput is the plaintext.
|
||||
* I.e. the Payload data as a result of decrypting the ciphertext.
|
||||
*
|
||||
* @param[in] dataLength
|
||||
* Length of data to be encrypted/decrypted, referred to as l(m) in CCM*.
|
||||
* Note that this does not include the length of the MIC,
|
||||
* so for decryption there are
|
||||
* l(c) = @p dataLength + CCM_LengthOfMIC(securityLevel)
|
||||
* bytes available in the buffer.
|
||||
*
|
||||
* @param[in] pHdr
|
||||
* The 'a' parameter in CCM*.
|
||||
* Header is used for MIC calculation.
|
||||
* Must be at least @p hdrLength long.
|
||||
*
|
||||
* @param[in] hdrLength
|
||||
* Length of header.
|
||||
* Referred to as l(a) in CCM*
|
||||
*
|
||||
* @param[in] pKey
|
||||
* The 'K' parameter in CCM*.
|
||||
* Pointer to key to use.
|
||||
* Currently only 128 bit keys (16 bytes) are supported.
|
||||
*
|
||||
* @param[in] keyLength
|
||||
* The length in bytes, of the @p pKey, i.e. the 'K' parameter in CCM.
|
||||
* Currently only 128 bit keys (16 bytes) are supported.
|
||||
*
|
||||
* @param[in] pNonce
|
||||
* The 'N' parameter in CCM.
|
||||
* Pointer to the nonce, which has length 13 bytes.
|
||||
*
|
||||
* @param[in] nonceLength
|
||||
* The length in bytes, of the @p pNonce, i.e. the 'N' parameter in CCM*.
|
||||
*
|
||||
* @param[in] securityLevel
|
||||
* Security level to use. See table 95 in IEEE Std 802.15.4-2006
|
||||
* See also function CCM_LengthOfMIC
|
||||
* Level 0: No encryption, no authentication
|
||||
* Level 1: No encryption, M=4 bytes authentication tag
|
||||
* Level 2: No encryption, M=8 bytes authentication tag
|
||||
* Level 3: No encryption, M=16 bytes authentication tag
|
||||
* Level 4: Encryption, no authentication
|
||||
* Level 5: Encryption, M=4 bytes authentication tag
|
||||
* Level 6: Encryption, M=8 bytes authentication tag
|
||||
* Level 7: Encryption, M=16 bytes authentication tag
|
||||
*
|
||||
* @param[in] encrypt
|
||||
* Set to true to encrypt, false to decrypt.
|
||||
*
|
||||
* @return
|
||||
* ECODE_OK if success. Error code if failure.
|
||||
* Encryption will always succeed.
|
||||
* Decryption may fail if the authentication fails.
|
||||
******************************************************************************/
|
||||
Ecode_t AESDRV_CCMStar(AESDRV_Context_t* pAesdrvContext,
|
||||
const uint8_t* pDataInput,
|
||||
uint8_t* pDataOutput,
|
||||
const uint32_t dataLength,
|
||||
const uint8_t* pHdr,
|
||||
const uint32_t hdrLength,
|
||||
const uint8_t* pKey,
|
||||
const uint32_t keyLength,
|
||||
const uint8_t* pNonce,
|
||||
const uint32_t nonceLength,
|
||||
uint8_t* pAuthTag,
|
||||
const uint8_t securityLevel,
|
||||
const bool encrypt)
|
||||
{
|
||||
return AESDRV_CCM_Generalized( pAesdrvContext,
|
||||
pDataInput,
|
||||
pDataOutput,
|
||||
dataLength,
|
||||
pHdr,
|
||||
hdrLength,
|
||||
pKey,
|
||||
keyLength,
|
||||
pNonce,
|
||||
nonceLength,
|
||||
pAuthTag,
|
||||
AESDRV_CCMStar_LengthOfMIC(securityLevel),
|
||||
encrypt,
|
||||
(securityLevel > 3));
|
||||
}
|
||||
|
||||
#endif /* #if ( defined(CRYPTO_COUNT) && (CRYPTO_COUNT > 0) ) || \
|
||||
( defined(AES_COUNT) && (AES_COUNT > 0) ) */
|
|
@ -0,0 +1,195 @@
|
|||
/*
|
||||
* Common functions for AES based algorithms for the AES hw module.
|
||||
*
|
||||
* Copyright (C) 2016 Silicon Labs, http://www.silabs.com
|
||||
* 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 "em_device.h"
|
||||
|
||||
#if defined(AES_COUNT) && (AES_COUNT > 0)
|
||||
|
||||
#if !defined(MBEDTLS_CONFIG_FILE)
|
||||
#include "mbedtls/config.h"
|
||||
#else
|
||||
#include MBEDTLS_CONFIG_FILE
|
||||
#endif
|
||||
|
||||
#include "aesdrv_internal.h"
|
||||
#include "aesdrv_common_aes.h"
|
||||
#include "em_assert.h"
|
||||
#include <string.h>
|
||||
|
||||
/*******************************************************************************
|
||||
************************** GLOBAL FUNCTIONS *******************************
|
||||
******************************************************************************/
|
||||
|
||||
/*
|
||||
* Initializes an AESDRV context structure.
|
||||
* Please refer to aesdrv.h for detailed description.
|
||||
*/
|
||||
Ecode_t AESDRV_Init(AESDRV_Context_t* pAesdrvContext)
|
||||
{
|
||||
/* Clear the driver context. */
|
||||
memset(pAesdrvContext, 0, sizeof(AESDRV_Context_t));
|
||||
return ECODE_OK;
|
||||
}
|
||||
|
||||
/*
|
||||
* DeInitializes an AESDRV context structure.
|
||||
* Please refer to aesdrv.h for detailed description.
|
||||
*/
|
||||
Ecode_t AESDRV_DeInit(AESDRV_Context_t* pAesdrvContext)
|
||||
{
|
||||
/* Clear the driver context. */
|
||||
memset(pAesdrvContext, 0, sizeof(AESDRV_Context_t));
|
||||
return ECODE_OK;
|
||||
}
|
||||
|
||||
/*
|
||||
* Set the AES encryption key.
|
||||
* Please refer to aesdrv.h for detailed description.
|
||||
*/
|
||||
Ecode_t AESDRV_SetKey(AESDRV_Context_t* pAesdrvContext,
|
||||
const uint8_t* pKey,
|
||||
uint32_t keyLength)
|
||||
{
|
||||
(void) pAesdrvContext; /* Key is stored directly in AES hw module and
|
||||
not set in context structure. */
|
||||
Ecode_t retval = ECODE_OK;
|
||||
const uint32_t * const _pKey = (const uint32_t *)pKey;
|
||||
|
||||
if (pKey == NULL)
|
||||
{
|
||||
return MBEDTLS_ECODE_AESDRV_INVALID_PARAM;
|
||||
}
|
||||
|
||||
/* Enable AES clock. */
|
||||
AESDRV_CLOCK_ENABLE;
|
||||
|
||||
/* Load key */
|
||||
#if defined( AES_CTRL_AES256 )
|
||||
if (32==keyLength)
|
||||
{
|
||||
int i, j;
|
||||
for (i = 3, j = 7; i >= 0; i--, j--)
|
||||
{
|
||||
AES->KEYLA = __REV(_pKey[j]);
|
||||
AES->KEYHA = __REV(_pKey[i]);
|
||||
}
|
||||
}
|
||||
else
|
||||
#endif
|
||||
{
|
||||
if (16==keyLength)
|
||||
{
|
||||
int i;
|
||||
#if defined( AES_CTRL_KEYBUFEN )
|
||||
AES->CTRL |= AES_CTRL_KEYBUFEN;
|
||||
/* Load key into high key for key buffer usage */
|
||||
for (i = 3; i >= 0; i--)
|
||||
{
|
||||
AES->KEYHA = __REV(_pKey[i]);
|
||||
}
|
||||
#else
|
||||
for (i = 3; i >= 0; i--)
|
||||
{
|
||||
AES->KEYLA = __REV(_pKey[i]);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
else
|
||||
{
|
||||
retval = MBEDTLS_ECODE_AESDRV_INVALID_PARAM;
|
||||
}
|
||||
}
|
||||
|
||||
/* Disable AES clock. */
|
||||
AESDRV_CLOCK_DISABLE;
|
||||
|
||||
return retval;
|
||||
}
|
||||
|
||||
/*
|
||||
* Set the AES device instance.
|
||||
* Please refer to aesdrv.h for detailed description.
|
||||
*/
|
||||
Ecode_t AESDRV_SetDeviceInstance(AESDRV_Context_t* pAesdrvContext,
|
||||
unsigned int devno)
|
||||
{
|
||||
(void) pAesdrvContext; /* Multiple instances not supported for AES module. */
|
||||
|
||||
if (devno >= AES_COUNT)
|
||||
return MBEDTLS_ECODE_AESDRV_INVALID_PARAM;
|
||||
else
|
||||
return ECODE_OK;
|
||||
}
|
||||
|
||||
#if defined(MBEDTLS_INCLUDE_ASYNCH_API)
|
||||
|
||||
/*
|
||||
* Setup the asynchronous mode of an AESDRV context.
|
||||
* Please refer to aesdrv.h for detailed description.
|
||||
*/
|
||||
Ecode_t AESDRV_SetAsynchMode
|
||||
(
|
||||
AESDRV_Context_t* pAesdrvContext,
|
||||
AESDRV_CipherMode_t cipherMode,
|
||||
void* pAsynchContext,
|
||||
AESDRV_AsynchCallback_t asynchCallback,
|
||||
void* asynchCallbackArgument
|
||||
)
|
||||
{
|
||||
(void) pAesdrvContext; /* Asynch mode not supported for AES module. */
|
||||
(void) cipherMode; /* Asynch mode not supported for AES module. */
|
||||
(void) asynchCallback; /* Asynch mode not supported for AES module. */
|
||||
(void) asynchCallbackArgument; /* Asynch mode not supported for AES module. */
|
||||
|
||||
if (pAsynchContext)
|
||||
{
|
||||
/* The EFM32 AES implementation does not support asynchronous mode yet. */
|
||||
return MBEDTLS_ECODE_AESDRV_NOT_SUPPORTED;
|
||||
}
|
||||
else
|
||||
{
|
||||
return ECODE_OK;
|
||||
}
|
||||
}
|
||||
|
||||
#endif /* #if defined(MBEDTLS_INCLUDE_ASYNCH_API) */
|
||||
|
||||
/*
|
||||
* Setup CRYPTO I/O mode.
|
||||
* Please refer to aesdrv.h for detailed description.
|
||||
*/
|
||||
Ecode_t AESDRV_SetIoMode
|
||||
(
|
||||
AESDRV_Context_t* pAesdrvContext,
|
||||
AESDRV_IoMode_t ioMode,
|
||||
AESDRV_IoModeSpecific_t* ioModeSpecific
|
||||
)
|
||||
{
|
||||
(void) pAesdrvContext; /* Not supported for AES module. */
|
||||
(void) ioModeSpecific; /* Not supported for AES module. */
|
||||
if (ioMode == aesdrvIoModeCore)
|
||||
{
|
||||
return ECODE_OK;
|
||||
}
|
||||
else
|
||||
{
|
||||
return MBEDTLS_ECODE_AESDRV_NOT_SUPPORTED;
|
||||
}
|
||||
}
|
||||
|
||||
#endif /* #if defined(AES_COUNT) && (AES_COUNT > 0) */
|
|
@ -0,0 +1,34 @@
|
|||
/*
|
||||
* Common definitions for AES based algorithms for the AES hw module.
|
||||
*
|
||||
* Copyright (C) 2016 Silicon Labs, http://www.silabs.com
|
||||
* 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 __SILICON_LABS_AESDRV_COMMON_AES_H
|
||||
#define __SILICON_LABS_AESDRV_COMMON_AES_H
|
||||
|
||||
#include "em_device.h"
|
||||
|
||||
#if defined(AES_COUNT) && (AES_COUNT > 0)
|
||||
|
||||
/*******************************************************************************
|
||||
******************************* MACROS ************************************
|
||||
******************************************************************************/
|
||||
#define AESDRV_CLOCK_ENABLE CMU->HFCORECLKEN0 |= CMU_HFCORECLKEN0_AES
|
||||
#define AESDRV_CLOCK_DISABLE CMU->HFCORECLKEN0 &= ~CMU_HFCORECLKEN0_AES
|
||||
|
||||
#endif /* #if defined(AES_COUNT) && (AES_COUNT > 0) */
|
||||
|
||||
#endif /* __SILICON_LABS_AESDRV_COMMON_AES_H */
|
|
@ -0,0 +1,708 @@
|
|||
/*
|
||||
* Common functions for AES based algorithms for the CRYPTO hw module.
|
||||
*
|
||||
* Copyright (C) 2016 Silicon Labs, http://www.silabs.com
|
||||
* 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 "em_device.h"
|
||||
|
||||
#if defined(CRYPTO_COUNT) && (CRYPTO_COUNT > 0)
|
||||
|
||||
#if !defined(MBEDTLS_CONFIG_FILE)
|
||||
#include "mbedtls/config.h"
|
||||
#else
|
||||
#include MBEDTLS_CONFIG_FILE
|
||||
#endif
|
||||
|
||||
#include "aesdrv_common_crypto.h"
|
||||
#include "cryptodrv_internal.h"
|
||||
#if defined( MBEDTLS_INCLUDE_IO_MODE_DMA )
|
||||
#include "dmadrv.h"
|
||||
#endif
|
||||
#include "em_crypto.h"
|
||||
#if defined(BUFC_PRESENT)
|
||||
#include "em_bufc.h"
|
||||
#endif
|
||||
#include "em_assert.h"
|
||||
#include <string.h>
|
||||
|
||||
/*******************************************************************************
|
||||
******************************* DEFINES ***********************************
|
||||
******************************************************************************/
|
||||
#define AESDRV_UTILS_BUFC_BUFFER_NOT_SET 0xFF
|
||||
#define AESDRV_UTILS_DMA_CHANNEL_NOT_SET 0xFFFF
|
||||
|
||||
/*******************************************************************************
|
||||
************************** STATIC FUNCTIONS *******************************
|
||||
******************************************************************************/
|
||||
#if defined( MBEDTLS_INCLUDE_IO_MODE_DMA )
|
||||
static void aesdrvDmaReset (AESDRV_Context_t* pAesdrvContext);
|
||||
static Ecode_t aesdrvDmaInit (AESDRV_Context_t* pAesdrvContext);
|
||||
static void aesdrvDmaSetup (AESDRV_Context_t* pAesdrvContext,
|
||||
uint8_t const* pData,
|
||||
uint32_t authDataLength,
|
||||
uint32_t textLength
|
||||
);
|
||||
static void aesdrvDmaAddrLenGet(uint8_t** pBufIn,
|
||||
uint8_t** pBufOut,
|
||||
uint16_t lengthA,
|
||||
uint16_t lengthB,
|
||||
uint16_t* dmaLengthIn,
|
||||
uint16_t* dmaLengthOut);
|
||||
#endif /* #if defined( MBEDTLS_INCLUDE_IO_MODE_DMA ) */
|
||||
|
||||
#if defined(BUFC_PRESENT)
|
||||
static void aesdrvBufcInit (AESDRV_Context_t* pAesdrvContext,
|
||||
uint8_t bufId
|
||||
);
|
||||
static void aesdrvBufcSetup (AESDRV_Context_t* pAesdrvContext,
|
||||
uint8_t const* pData,
|
||||
uint32_t authDataLength);
|
||||
#endif
|
||||
|
||||
/*******************************************************************************
|
||||
************************** GLOBAL FUNCTIONS *******************************
|
||||
******************************************************************************/
|
||||
|
||||
/*
|
||||
* Initializes an AESDRV context structure.
|
||||
* Please refer to aesdrv.h for detailed description.
|
||||
*/
|
||||
Ecode_t AESDRV_Init(AESDRV_Context_t* pAesdrvContext)
|
||||
{
|
||||
/* Start by clearing the device context. */
|
||||
memset(pAesdrvContext, 0, sizeof(AESDRV_Context_t));
|
||||
|
||||
/* Set I/O mode to mcu core. */
|
||||
pAesdrvContext->ioMode = aesdrvIoModeCore;
|
||||
|
||||
/* Clear the DMA channel config */
|
||||
pAesdrvContext->ioModeSpecific.dmaConfig.dmaChIn =
|
||||
AESDRV_UTILS_DMA_CHANNEL_NOT_SET;
|
||||
pAesdrvContext->ioModeSpecific.dmaConfig.dmaChOut =
|
||||
AESDRV_UTILS_DMA_CHANNEL_NOT_SET;
|
||||
|
||||
#if defined(BUFC_PRESENT)
|
||||
/* Clear the bufc buffer id */
|
||||
pAesdrvContext->ioModeSpecific.bufcConfig.bufId =
|
||||
AESDRV_UTILS_BUFC_BUFFER_NOT_SET;
|
||||
#endif
|
||||
|
||||
/* Disable authentication tag optimization */
|
||||
pAesdrvContext->authTagOptimize = false;
|
||||
|
||||
/* Set default CRYPTO device instance to use. */
|
||||
cryptodrvSetDeviceInstance(&pAesdrvContext->cryptodrvContext, 0);
|
||||
|
||||
/* Set I/O mode to mcu core. */
|
||||
return AESDRV_SetIoMode(pAesdrvContext, aesdrvIoModeCore, 0);
|
||||
}
|
||||
|
||||
/*
|
||||
* DeInitializes AESDRV context.
|
||||
* Please refer to aesdrv.h for detailed description.
|
||||
*/
|
||||
Ecode_t AESDRV_DeInit(AESDRV_Context_t* pAesdrvContext)
|
||||
{
|
||||
switch( pAesdrvContext->ioMode )
|
||||
{
|
||||
case aesdrvIoModeCore:
|
||||
/* Do nothing. */
|
||||
break;
|
||||
case aesdrvIoModeDma:
|
||||
#if defined( MBEDTLS_INCLUDE_IO_MODE_DMA )
|
||||
aesdrvDmaReset(pAesdrvContext);
|
||||
#endif
|
||||
break;
|
||||
case aesdrvIoModeBufc:
|
||||
#if defined(BUFC_PRESENT)
|
||||
/* Clear the bufc buffer id */
|
||||
aesdrvBufcInit(pAesdrvContext, AESDRV_UTILS_BUFC_BUFFER_NOT_SET);
|
||||
#endif
|
||||
break;
|
||||
}
|
||||
|
||||
#if defined(MBEDTLS_INCLUDE_ASYNCH_API)
|
||||
/* If set, clear the asynch context. The size to clear depends on the
|
||||
cipher mode. */
|
||||
if (pAesdrvContext->pAsynchContext)
|
||||
{
|
||||
switch (pAesdrvContext->cipherMode)
|
||||
{
|
||||
case cipherModeBlockCipher:
|
||||
memset(pAesdrvContext->pAsynchContext, 0,
|
||||
sizeof(AESDRV_BlockCipherAsynchContext_t));
|
||||
break;
|
||||
case cipherModeCcm:
|
||||
case cipherModeCcmBle:
|
||||
memset(pAesdrvContext->pAsynchContext, 0,
|
||||
sizeof(AESDRV_CCM_AsynchContext_t));
|
||||
break;
|
||||
case cipherModeCmac:
|
||||
memset(pAesdrvContext->pAsynchContext, 0,
|
||||
sizeof(AESDRV_CMAC_AsynchContext_t));
|
||||
break;
|
||||
case cipherModeGcm:
|
||||
memset(pAesdrvContext->pAsynchContext, 0,
|
||||
sizeof(AESDRV_GCM_AsynchContext_t));
|
||||
break;
|
||||
case cipherModeNone:
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
#endif /* #if defined(MBEDTLS_INCLUDE_ASYNCH_API) */
|
||||
|
||||
/* Clear the device context. */
|
||||
memset(pAesdrvContext, 0, sizeof(AESDRV_Context_t));
|
||||
|
||||
return ECODE_OK;
|
||||
}
|
||||
|
||||
/*
|
||||
* Set the AES/CRYPTO device instance.
|
||||
* Please refer to aesdrv.h for detailed description.
|
||||
*/
|
||||
Ecode_t AESDRV_SetDeviceInstance(AESDRV_Context_t* pAesdrvContext,
|
||||
unsigned int devno)
|
||||
{
|
||||
/* Set default CRYPTO device instance to use. */
|
||||
return cryptodrvSetDeviceInstance(&pAesdrvContext->cryptodrvContext,
|
||||
devno);
|
||||
}
|
||||
|
||||
/*
|
||||
* Set the AES encryption key.
|
||||
* Please refer to aesdrv.h for detailed description.
|
||||
*/
|
||||
Ecode_t AESDRV_SetKey(AESDRV_Context_t* pAesdrvContext,
|
||||
const uint8_t* pKey,
|
||||
uint32_t keyLength)
|
||||
{
|
||||
Ecode_t retval = ECODE_OK;
|
||||
CRYPTODRV_Context_t* pCryptodrvContext = &pAesdrvContext->cryptodrvContext;
|
||||
|
||||
EFM_ASSERT(pKey);
|
||||
|
||||
retval = CRYPTODRV_Arbitrate(pCryptodrvContext);
|
||||
if (ECODE_OK != retval)
|
||||
return retval;
|
||||
|
||||
CRYPTODRV_EnterCriticalRegion(pCryptodrvContext);
|
||||
|
||||
if (32==keyLength)
|
||||
{
|
||||
CRYPTO_KeyBufWrite(pCryptodrvContext->device->crypto,
|
||||
(uint32_t*)pKey, cryptoKey256Bits);
|
||||
}
|
||||
else
|
||||
{
|
||||
if (16==keyLength)
|
||||
{
|
||||
CRYPTO_KeyBufWrite(pCryptodrvContext->device->crypto,
|
||||
(uint32_t*)pKey, cryptoKey128Bits);
|
||||
}
|
||||
else
|
||||
{
|
||||
retval = MBEDTLS_ECODE_AESDRV_INVALID_PARAM;
|
||||
}
|
||||
}
|
||||
|
||||
CRYPTODRV_ExitCriticalRegion(pCryptodrvContext);
|
||||
retval = CRYPTODRV_Release(pCryptodrvContext);
|
||||
return retval;
|
||||
}
|
||||
|
||||
#if defined(MBEDTLS_INCLUDE_ASYNCH_API)
|
||||
/*
|
||||
* Setup the asynchronous mode of an AESDRV context.
|
||||
* Please refer to aesdrv.h for detailed description.
|
||||
*/
|
||||
Ecode_t AESDRV_SetAsynchMode
|
||||
(
|
||||
AESDRV_Context_t* pAesdrvContext,
|
||||
AESDRV_CipherMode_t cipherMode,
|
||||
void* pAsynchContext,
|
||||
AESDRV_AsynchCallback_t asynchCallback,
|
||||
void* asynchCallbackArgument
|
||||
)
|
||||
{
|
||||
pAesdrvContext->pAsynchContext = pAsynchContext;
|
||||
pAesdrvContext->cipherMode = cipherMode;
|
||||
|
||||
switch (cipherMode)
|
||||
{
|
||||
default:
|
||||
pAesdrvContext->pAsynchContext = 0;
|
||||
break;
|
||||
case cipherModeBlockCipher:
|
||||
{
|
||||
AESDRV_BlockCipherAsynchContext_t* pBlockCipherAsynchContext =
|
||||
(AESDRV_BlockCipherAsynchContext_t*) pAsynchContext;
|
||||
pBlockCipherAsynchContext->asynchCallback = asynchCallback;
|
||||
pBlockCipherAsynchContext->asynchCallbackArgument = asynchCallbackArgument;
|
||||
}
|
||||
break;
|
||||
case cipherModeCcm:
|
||||
case cipherModeCcmBle:
|
||||
{
|
||||
AESDRV_CCM_AsynchContext_t* pCcmAsynchContext =
|
||||
(AESDRV_CCM_AsynchContext_t*) pAsynchContext;
|
||||
pCcmAsynchContext->asynchCallback = asynchCallback;
|
||||
pCcmAsynchContext->asynchCallbackArgument = asynchCallbackArgument;
|
||||
}
|
||||
break;
|
||||
case cipherModeCmac:
|
||||
{
|
||||
AESDRV_CMAC_AsynchContext_t* pCmacAsynchContext =
|
||||
(AESDRV_CMAC_AsynchContext_t*) pAsynchContext;
|
||||
pCmacAsynchContext->asynchCallback = asynchCallback;
|
||||
pCmacAsynchContext->asynchCallbackArgument = asynchCallbackArgument;
|
||||
}
|
||||
break;
|
||||
case cipherModeGcm:
|
||||
{
|
||||
AESDRV_GCM_AsynchContext_t* pGcmAsynchContext =
|
||||
(AESDRV_GCM_AsynchContext_t*) pAsynchContext;
|
||||
pGcmAsynchContext->asynchCallback = asynchCallback;
|
||||
pGcmAsynchContext->asynchCallbackArgument = asynchCallbackArgument;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
return ECODE_OK;
|
||||
}
|
||||
#endif /* #if defined(MBEDTLS_INCLUDE_ASYNCH_API) */
|
||||
|
||||
/*
|
||||
* Check if ioMode is valid for crypto device of context.
|
||||
*/
|
||||
bool aesdrvIoModeValid
|
||||
(
|
||||
AESDRV_Context_t* pAesdrvContext,
|
||||
AESDRV_IoMode_t ioMode
|
||||
)
|
||||
{
|
||||
if (ioMode != aesdrvIoModeBufc)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
else
|
||||
{
|
||||
#if (CRYPTO_COUNT == 1)
|
||||
(void) pAesdrvContext;
|
||||
return true;
|
||||
#elif (CRYPTO_COUNT == 2)
|
||||
if ( pAesdrvContext->cryptodrvContext.device->crypto == CRYPTO1 )
|
||||
{
|
||||
return true;
|
||||
}
|
||||
else
|
||||
{
|
||||
return false;
|
||||
}
|
||||
#else
|
||||
#error Unsupported CRYPTO_COUNT.
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Setup CRYPTO I/O mode.
|
||||
* Please refer to aesdrv.h for detailed description.
|
||||
*/
|
||||
Ecode_t AESDRV_SetIoMode
|
||||
(
|
||||
AESDRV_Context_t* pAesdrvContext,
|
||||
AESDRV_IoMode_t ioMode,
|
||||
AESDRV_IoModeSpecific_t* ioModeSpecific
|
||||
)
|
||||
{
|
||||
Ecode_t retval = ECODE_OK;
|
||||
#if !defined(BUFC_PRESENT)
|
||||
(void) ioModeSpecific;
|
||||
#endif
|
||||
|
||||
if (aesdrvIoModeValid(pAesdrvContext, ioMode) == false)
|
||||
{
|
||||
return MBEDTLS_ECODE_AESDRV_NOT_SUPPORTED;
|
||||
}
|
||||
|
||||
/* Start by reseting any previous settings, if applicable. */
|
||||
if ( ioMode != pAesdrvContext->ioMode )
|
||||
{
|
||||
switch(pAesdrvContext->ioMode )
|
||||
{
|
||||
case aesdrvIoModeCore:
|
||||
break;
|
||||
case aesdrvIoModeDma:
|
||||
#if defined( MBEDTLS_INCLUDE_IO_MODE_DMA )
|
||||
aesdrvDmaReset(pAesdrvContext);
|
||||
#endif
|
||||
break;
|
||||
case aesdrvIoModeBufc:
|
||||
#if defined(BUFC_PRESENT)
|
||||
/* Clear the bufc buffer id */
|
||||
aesdrvBufcInit(pAesdrvContext, AESDRV_UTILS_BUFC_BUFFER_NOT_SET);
|
||||
#endif
|
||||
break;
|
||||
}
|
||||
|
||||
/* Set requested I/O mode now. */
|
||||
switch( ioMode )
|
||||
{
|
||||
case aesdrvIoModeCore:
|
||||
/* Do nothing. Just continue without hitting default label which signals
|
||||
error.*/
|
||||
break;
|
||||
|
||||
case aesdrvIoModeBufc:
|
||||
#if defined(BUFC_PRESENT)
|
||||
{
|
||||
BUFC_Init_TypeDef bufcInit = BUFC_INIT_DEFAULT;
|
||||
|
||||
/* Make sure BUFC clock is running. */
|
||||
#if defined (CMU_HFRADIOCLKEN0_BUFC)
|
||||
CMU->HFRADIOCLKEN0 |= CMU_HFRADIOCLKEN0_BUFC;
|
||||
#endif
|
||||
#if defined (CMU_HFRADIOALTCLKEN0_BUFC)
|
||||
CMU->HFRADIOALTCLKEN0 |= CMU_HFRADIOALTCLKEN0_BUFC;
|
||||
#endif
|
||||
|
||||
BUFC_Init(&bufcInit);
|
||||
|
||||
aesdrvBufcInit(pAesdrvContext, ioModeSpecific->bufcConfig.bufId);
|
||||
}
|
||||
#else
|
||||
retval = MBEDTLS_ECODE_AESDRV_NOT_SUPPORTED;
|
||||
#endif
|
||||
break;
|
||||
case aesdrvIoModeDma:
|
||||
#if defined( MBEDTLS_INCLUDE_IO_MODE_DMA )
|
||||
/* Start by reseting previous settings.*/
|
||||
aesdrvDmaReset(pAesdrvContext);
|
||||
retval = aesdrvDmaInit(pAesdrvContext);
|
||||
#else
|
||||
retval = MBEDTLS_ECODE_AESDRV_NOT_SUPPORTED;
|
||||
#endif
|
||||
break;
|
||||
|
||||
default:
|
||||
retval = MBEDTLS_ECODE_AESDRV_NOT_SUPPORTED;
|
||||
}
|
||||
|
||||
if (ECODE_OK == retval)
|
||||
{
|
||||
/* If success we store the I/O mode for later references. */
|
||||
pAesdrvContext->ioMode = ioMode;
|
||||
}
|
||||
}
|
||||
|
||||
return retval;
|
||||
}
|
||||
|
||||
/*
|
||||
* Prepare CRYPTO I/O mode to transfer data
|
||||
*/
|
||||
void AESDRV_HwIoSetup(AESDRV_Context_t* pAesdrvContext,
|
||||
uint8_t* pData,
|
||||
uint32_t authDataLength,
|
||||
uint32_t textLength)
|
||||
{
|
||||
#if !defined( MBEDTLS_INCLUDE_IO_MODE_DMA )
|
||||
(void)pAesdrvContext; (void)pData; (void)authDataLength; (void)textLength;
|
||||
#endif
|
||||
switch (pAesdrvContext->ioMode)
|
||||
{
|
||||
case aesdrvIoModeBufc:
|
||||
#if defined(BUFC_PRESENT)
|
||||
aesdrvBufcSetup( pAesdrvContext, pData, authDataLength );
|
||||
#endif
|
||||
break;
|
||||
case aesdrvIoModeDma:
|
||||
#if defined( MBEDTLS_INCLUDE_IO_MODE_DMA )
|
||||
aesdrvDmaSetup( pAesdrvContext, pData, authDataLength, textLength );
|
||||
#endif
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/*******************************************************************************
|
||||
*********************** LOCAL STATIC FUNCTIONS ****************************
|
||||
******************************************************************************/
|
||||
|
||||
#if defined(BUFC_PRESENT)
|
||||
/**
|
||||
* Function initializes BUFC for CRYPTO
|
||||
*
|
||||
* @details
|
||||
* Function only needs to store buffer id to be used.
|
||||
*
|
||||
* @param bufId
|
||||
* BUFC Buffer Id to be used later on by CRYPTO.
|
||||
*/
|
||||
static void aesdrvBufcInit(AESDRV_Context_t* pAesdrvContext,
|
||||
uint8_t bufId)
|
||||
{
|
||||
pAesdrvContext->ioModeSpecific.bufcConfig.bufId = bufId;
|
||||
}
|
||||
|
||||
/**
|
||||
* Function setup BUFC for CRYPTO.
|
||||
*
|
||||
* @details
|
||||
* Function assumes that same buffer is used for input and output (in place).
|
||||
* Additionally, it supports packet authentication&encryption where first part
|
||||
* of the packet is only authenticated (CCM,GCM).
|
||||
*
|
||||
* @param pData
|
||||
* Address of input-output buffer.
|
||||
*
|
||||
* @param authDataLen
|
||||
* Length of authentication part.
|
||||
*
|
||||
* @warning
|
||||
* Function is modifying CRYPTO_CTRL register by doing
|
||||
* OR operation assuming that bit fields which are set have previously been
|
||||
* cleared. It must be ensured that access to this register is done in
|
||||
* correct order and settings are not overwritten.
|
||||
*/
|
||||
static void aesdrvBufcSetup(AESDRV_Context_t* pAesdrvContext,
|
||||
uint8_t const* pData,
|
||||
uint32_t authDataLength)
|
||||
{
|
||||
uint8_t bufId = pAesdrvContext->ioModeSpecific.bufcConfig.bufId;
|
||||
CRYPTO_TypeDef* crypto = pAesdrvContext->cryptodrvContext.device->crypto;
|
||||
uint32_t ctrl;
|
||||
|
||||
EFM_ASSERT(bufId != AESDRV_UTILS_BUFC_BUFFER_NOT_SET);
|
||||
|
||||
/* Setup BUFC */
|
||||
BUFC->BUF[bufId].CTRL = BUFC_BUF_CTRL_SIZE_SIZE2048;
|
||||
BUFC->BUF[bufId].ADDR = (uint32_t)pData;
|
||||
BUFC->BUF[bufId].CMD = BUFC_BUF_CMD_CLEAR;
|
||||
BUFC->BUF[bufId].WRITEOFFSET = 2048 + (authDataLength);
|
||||
BUFC->BUF[bufId].CMD = BUFC_BUF_CMD_PREFETCH;
|
||||
|
||||
ctrl = crypto->CTRL;
|
||||
ctrl &= ~_CRYPTO_CTRL_READBUFSEL_MASK & ~_CRYPTO_CTRL_WRITEBUFSEL_MASK;
|
||||
ctrl |= bufId << _CRYPTO_CTRL_READBUFSEL_SHIFT
|
||||
| bufId << _CRYPTO_CTRL_WRITEBUFSEL_SHIFT;
|
||||
crypto->CTRL = ctrl;
|
||||
}
|
||||
#endif
|
||||
|
||||
#if defined( MBEDTLS_INCLUDE_IO_MODE_DMA )
|
||||
|
||||
/***************************************************************************//**
|
||||
* Function resets DMA settings for CRYPTO.
|
||||
*
|
||||
* @details
|
||||
* Function clears trigger settings for channel setup to be used by CRYPTO.
|
||||
*
|
||||
******************************************************************************/
|
||||
static void aesdrvDmaReset(AESDRV_Context_t* pAesdrvContext)
|
||||
{
|
||||
AESDRV_DmaConfig_t* dmaConfig= &pAesdrvContext->ioModeSpecific.dmaConfig;
|
||||
|
||||
if (dmaConfig->dmaChIn != AESDRV_UTILS_DMA_CHANNEL_NOT_SET)
|
||||
{
|
||||
DMADRV_FreeChannel(dmaConfig->dmaChIn);
|
||||
}
|
||||
|
||||
if (dmaConfig->dmaChOut != AESDRV_UTILS_DMA_CHANNEL_NOT_SET)
|
||||
{
|
||||
DMADRV_FreeChannel(dmaConfig->dmaChOut);
|
||||
}
|
||||
dmaConfig->dmaChIn = AESDRV_UTILS_DMA_CHANNEL_NOT_SET;
|
||||
dmaConfig->dmaChOut = AESDRV_UTILS_DMA_CHANNEL_NOT_SET;
|
||||
}
|
||||
|
||||
/***************************************************************************//**
|
||||
* Function initializes DMADRV for CRYPTO and allocates two channels.
|
||||
*
|
||||
* @details
|
||||
* Function assumes that same buffer is used for input and output (in place).
|
||||
* Additionally, it supports packet authentication&encryption where first part
|
||||
* of the packet is only authenticated (CCM,GCM).
|
||||
*
|
||||
* @return
|
||||
* OK when DMA channel allocation completed, OUT_OF_RESOURCES if not
|
||||
*
|
||||
******************************************************************************/
|
||||
static Ecode_t aesdrvDmaInit( AESDRV_Context_t* pAesdrvContext )
|
||||
{
|
||||
Ecode_t retval;
|
||||
AESDRV_DmaConfig_t* dmaConfig = &pAesdrvContext->ioModeSpecific.dmaConfig;
|
||||
|
||||
retval = DMADRV_Init();
|
||||
if ( retval == ECODE_EMDRV_DMADRV_ALREADY_INITIALIZED ||
|
||||
retval == ECODE_EMDRV_DMADRV_OK )
|
||||
{
|
||||
retval = ECODE_OK;
|
||||
}
|
||||
else
|
||||
{
|
||||
return MBEDTLS_ECODE_AESDRV_OUT_OF_RESOURCES;
|
||||
}
|
||||
|
||||
// Allocate first DMA channel
|
||||
retval = DMADRV_AllocateChannel(&dmaConfig->dmaChIn, NULL);
|
||||
if ( retval != ECODE_EMDRV_DMADRV_OK )
|
||||
{
|
||||
return MBEDTLS_ECODE_AESDRV_OUT_OF_RESOURCES;
|
||||
}
|
||||
// Allocate second DMA channel
|
||||
retval = DMADRV_AllocateChannel(&dmaConfig->dmaChOut, NULL);
|
||||
if ( retval != ECODE_EMDRV_DMADRV_OK ) {
|
||||
DMADRV_FreeChannel(dmaConfig->dmaChIn);
|
||||
dmaConfig->dmaChIn = AESDRV_UTILS_DMA_CHANNEL_NOT_SET;
|
||||
return MBEDTLS_ECODE_AESDRV_OUT_OF_RESOURCES;
|
||||
}
|
||||
|
||||
return ECODE_OK;
|
||||
}
|
||||
|
||||
/**
|
||||
* Function setup DMA for CRYPTO.
|
||||
*
|
||||
* @details
|
||||
* Function assumes that same buffer is used for input and output (in place).
|
||||
* Additionally, it supports packet authentication&encryption where first part
|
||||
* of the packet is only authenticated (CCM,GCM).
|
||||
*
|
||||
* @param authDataLen
|
||||
* Length of authentication part.
|
||||
*
|
||||
* @param textLength
|
||||
* Length of encrypted part.
|
||||
*
|
||||
* @warning
|
||||
* Function is modifying CRYPTO_SEQCTRL and CRYPTO_SEQCTRLB registers. It must
|
||||
* be ensured that access to those registers is done in
|
||||
* correct order and settings are not overwritten.
|
||||
*
|
||||
*/
|
||||
static void aesdrvDmaSetup(AESDRV_Context_t* pAesdrvContext,
|
||||
uint8_t const* pData,
|
||||
uint32_t authDataLength,
|
||||
uint32_t textLength)
|
||||
{
|
||||
uint8_t * _authData = (uint8_t*)pData;
|
||||
uint8_t * _textData = (uint8_t*)((uint32_t)pData + authDataLength);
|
||||
CRYPTO_TypeDef* crypto = pAesdrvContext->cryptodrvContext.device->crypto;
|
||||
AESDRV_DmaConfig_t* dmaConfig = &pAesdrvContext->ioModeSpecific.dmaConfig;
|
||||
uint16_t lenIn, lenOut;
|
||||
uint32_t seqctrl;
|
||||
|
||||
/* Ensure that dma for crypto was initialized. */
|
||||
EFM_ASSERT((dmaConfig->dmaChIn != AESDRV_UTILS_DMA_CHANNEL_NOT_SET) &&
|
||||
(dmaConfig->dmaChOut != AESDRV_UTILS_DMA_CHANNEL_NOT_SET));
|
||||
|
||||
crypto->CTRL &= (~_CRYPTO_CTRL_DMA0RSEL_MASK) & (~_CRYPTO_CTRL_DMA1RSEL_MASK);
|
||||
seqctrl = crypto->SEQCTRL;
|
||||
seqctrl &= (~_CRYPTO_SEQCTRL_DMA0SKIP_MASK) & (~_CRYPTO_SEQCTRL_DMA0PRESA_MASK);
|
||||
seqctrl |= (uint32_t)_authData % 4 << _CRYPTO_SEQCTRL_DMA0SKIP_SHIFT;
|
||||
crypto->SEQCTRL = seqctrl;
|
||||
crypto->SEQCTRLB |= CRYPTO_SEQCTRLB_DMA0PRESB;
|
||||
aesdrvDmaAddrLenGet((uint8_t **)&_authData,
|
||||
(uint8_t **)&_textData,
|
||||
authDataLength,
|
||||
textLength,
|
||||
&lenIn, &lenOut);
|
||||
|
||||
DMADRV_MemoryPeripheral( dmaConfig->dmaChIn,
|
||||
#ifdef EMDRV_DMADRV_LDMA
|
||||
pAesdrvContext->cryptodrvContext.device->dmaReqSigChIn,
|
||||
#else
|
||||
#error "UDMA + CRYPTO is a non-exisiting combination"
|
||||
#endif
|
||||
(void*)&crypto->DATA0,
|
||||
(void *)_authData,
|
||||
true,
|
||||
lenIn / 4,
|
||||
dmadrvDataSize4,
|
||||
NULL,
|
||||
NULL );
|
||||
|
||||
if (textLength)
|
||||
{
|
||||
DMADRV_PeripheralMemory( dmaConfig->dmaChOut,
|
||||
pAesdrvContext->cryptodrvContext.device->dmaReqSigChOut,
|
||||
(void *)_textData,
|
||||
(void*)&crypto->DATA0,
|
||||
true,
|
||||
lenOut / 4,
|
||||
dmadrvDataSize4,
|
||||
NULL,
|
||||
NULL );
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Function calculates length transfers for reading to crypto and from crypto.
|
||||
*
|
||||
* @details
|
||||
* Function takes into account address alignment for input and output buffer.
|
||||
* It overwrites provided addresses applying alignment.
|
||||
*
|
||||
* @param pBufIn
|
||||
* Address of input buffer. Will be modified by the function if not word
|
||||
* aligned.
|
||||
*
|
||||
* @param pBufOut
|
||||
* Address of output buffer. Will be modified by the function if not word
|
||||
* aligned.
|
||||
*
|
||||
* @param lengthA
|
||||
* Length of authentication part of CCM.
|
||||
* @param lengthB
|
||||
* Length of payload to be encrypted.
|
||||
* @return
|
||||
*/
|
||||
static void aesdrvDmaAddrLenGet(uint8_t** pBufIn,
|
||||
uint8_t** pBufOut,
|
||||
uint16_t lengthA,
|
||||
uint16_t lengthB,
|
||||
uint16_t* dmaLengthIn,
|
||||
uint16_t* dmaLengthOut)
|
||||
{
|
||||
uint8_t* pIn = *pBufIn;
|
||||
uint8_t* pOut = *pBufOut;
|
||||
uint8_t moduloA = (uint32_t)pIn % 4;
|
||||
uint8_t moduloB = (uint32_t)pOut % 4;
|
||||
|
||||
*dmaLengthIn = lengthA+lengthB;
|
||||
*dmaLengthOut = lengthB;
|
||||
|
||||
pIn -= moduloA;
|
||||
*dmaLengthIn += moduloA;
|
||||
*dmaLengthIn = (*dmaLengthIn+3) & 0xFFFC;
|
||||
|
||||
pOut -= moduloB;
|
||||
*dmaLengthOut += moduloB;
|
||||
*dmaLengthOut = (*dmaLengthOut+3) & 0xFFFC;
|
||||
|
||||
*pBufIn = pIn;
|
||||
*pBufOut = pOut;
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
#endif /* #if defined( MBEDTLS_INCLUDE_IO_MODE_DMA ) */
|
||||
|
||||
#endif /* #if defined(CRYPTO_COUNT) && (CRYPTO_COUNT > 0) */
|
|
@ -0,0 +1,29 @@
|
|||
/*
|
||||
* Common interface for AES based algorithms for the CRYPTO hw module.
|
||||
*
|
||||
* Copyright (C) 2016 Silicon Labs, http://www.silabs.com
|
||||
* 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 __SILICON_LABS_AESDRV_COMMON_CRYPTO_H
|
||||
#define __SILICON_LABS_AESDRV_COMMON_CRYPTO_H
|
||||
|
||||
#include "aesdrv_internal.h"
|
||||
|
||||
void AESDRV_HwIoSetup(AESDRV_Context_t* pAesdrvContext,
|
||||
uint8_t* pData,
|
||||
uint32_t authDataLength,
|
||||
uint32_t textLength);
|
||||
|
||||
#endif /* __SILICON_LABS_AESDRV_COMMON_CRYPTO_H */
|
File diff suppressed because it is too large
Load Diff
|
@ -0,0 +1,669 @@
|
|||
/*
|
||||
* CRYPTO driver implementation including CRYPTO preemption and asynchronous
|
||||
* (non-blocking) support.
|
||||
*
|
||||
* Copyright (C) 2016, Silicon Labs, http://www.silabs.com
|
||||
* 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 "em_device.h"
|
||||
|
||||
#if defined(CRYPTO_COUNT) && (CRYPTO_COUNT > 0)
|
||||
|
||||
#if !defined(MBEDTLS_CONFIG_FILE)
|
||||
#include "mbedtls/config.h"
|
||||
#else
|
||||
#include MBEDTLS_CONFIG_FILE
|
||||
#endif
|
||||
|
||||
#include "cryptodrv_internal.h"
|
||||
#include "em_crypto.h"
|
||||
#include "em_assert.h"
|
||||
#include "em_core.h"
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <stdarg.h>
|
||||
#include <string.h>
|
||||
#if defined( CRYPTODRV_PAL_FREERTOS )
|
||||
#include "FreeRTOS.h"
|
||||
#include "task.h"
|
||||
#include "semphr.h"
|
||||
#define CRYPTO_IRQn_PRIORITY (configMAX_SYSCALL_INTERRUPT_PRIORITY-1)
|
||||
#endif
|
||||
|
||||
/*******************************************************************************
|
||||
******************************** MACROS ***********************************
|
||||
******************************************************************************/
|
||||
#if defined(MBEDTLS_CRYPTO_DEVICE_PREEMPTION)
|
||||
|
||||
#define CRYPTODRV_CLOCK_ENABLE(clk) CMU->HFBUSCLKEN0 |= clk
|
||||
#define CRYPTODRV_CLOCK_DISABLE(clk) CMU->HFBUSCLKEN0 &= ~(clk)
|
||||
|
||||
#define RUNNING_AT_INTERRUPT_LEVEL (SCB->ICSR & SCB_ICSR_VECTACTIVE_Msk)
|
||||
|
||||
#if defined( _EFR32_MIGHTY_FAMILY ) || defined( _EFM32_PEARL_FAMILY )
|
||||
#define MAX_NVIC_ISER (2) /* FPUEH_IRQn = 33 is the highest IRQn
|
||||
and all IRQns fits inside 2 ISERs
|
||||
ISER[0] and ISER[1]. */
|
||||
#elif defined( _EFM32_JADE_FAMILY )
|
||||
#define MAX_NVIC_ISER (1) /* CRYOTIMER_IRQn = 31 is the highest IRQn
|
||||
and all IRQns fits inside one ISER[0]. */
|
||||
#else
|
||||
#error Device not supported.
|
||||
#endif
|
||||
|
||||
#endif /* #if defined(MBEDTLS_CRYPTO_DEVICE_PREEMPTION) */
|
||||
|
||||
/*******************************************************************************
|
||||
******************************** STATICS **********************************
|
||||
******************************************************************************/
|
||||
|
||||
#if defined(MBEDTLS_CRYPTO_DEVICE_PREEMPTION)
|
||||
/* Pointer to current owner context of the CRYPTO unit. The @ref cryptoOwner
|
||||
pointer serves as the anchor to a double linked list of all current "active"
|
||||
CRYPTODRV contexts. The @ref CRYPTODRV_Arbitrate function adds a new owner
|
||||
if ownership is won, and CRYPTODRV_Release removes a context that is done.*/
|
||||
static struct CRYPTODRV_Context_t* cryptoOwner[CRYPTO_COUNT] =
|
||||
{
|
||||
NULL
|
||||
#if CRYPTO_COUNT==2
|
||||
, NULL
|
||||
#endif
|
||||
};
|
||||
|
||||
/* Flag which indicates whether a CRYPTO critical region is active. */
|
||||
static uint32_t nvicIser[CRYPTO_COUNT][MAX_NVIC_ISER];
|
||||
|
||||
#endif
|
||||
|
||||
/* CRYPTO device instance structures. */
|
||||
static const CRYPTO_Device_t cryptoDevice[CRYPTO_COUNT] =
|
||||
{
|
||||
#if defined( CRYPTO0 )
|
||||
{
|
||||
CRYPTO0,
|
||||
CRYPTO0_IRQn,
|
||||
CMU_HFBUSCLKEN0_CRYPTO0
|
||||
#if defined( MBEDTLS_CRYPTO_DEVICE_PREEMPTION )
|
||||
,
|
||||
(void*)&cryptoOwner[0],
|
||||
nvicIser[0]
|
||||
#endif
|
||||
#if defined( MBEDTLS_INCLUDE_IO_MODE_DMA )
|
||||
,
|
||||
dmadrvPeripheralSignal_CRYPTO0_DATA0WR,
|
||||
dmadrvPeripheralSignal_CRYPTO0_DATA0RD
|
||||
#endif
|
||||
}
|
||||
#elif defined( CRYPTO )
|
||||
{
|
||||
CRYPTO,
|
||||
CRYPTO_IRQn,
|
||||
CMU_HFBUSCLKEN0_CRYPTO
|
||||
#if defined( MBEDTLS_CRYPTO_DEVICE_PREEMPTION )
|
||||
,
|
||||
(void*)&cryptoOwner[0],
|
||||
nvicIser[0]
|
||||
#endif
|
||||
#if defined( MBEDTLS_INCLUDE_IO_MODE_DMA )
|
||||
,
|
||||
dmadrvPeripheralSignal_CRYPTO_DATA0WR,
|
||||
dmadrvPeripheralSignal_CRYPTO_DATA0RD
|
||||
#endif
|
||||
}
|
||||
#endif
|
||||
#if defined( CRYPTO1 )
|
||||
,
|
||||
{
|
||||
CRYPTO1,
|
||||
CRYPTO1_IRQn,
|
||||
CMU_HFBUSCLKEN0_CRYPTO1
|
||||
#if defined( MBEDTLS_CRYPTO_DEVICE_PREEMPTION )
|
||||
,
|
||||
(void*)&cryptoOwner[1],
|
||||
nvicIser[1]
|
||||
#endif
|
||||
#if defined( MBEDTLS_INCLUDE_IO_MODE_DMA )
|
||||
,
|
||||
dmadrvPeripheralSignal_CRYPTO1_DATA0WR,
|
||||
dmadrvPeripheralSignal_CRYPTO1_DATA0RD
|
||||
#endif
|
||||
}
|
||||
#endif
|
||||
};
|
||||
|
||||
#if defined(MBEDTLS_CRYPTO_DEVICE_PREEMPTION)
|
||||
|
||||
#if defined( CRYPTODRV_PAL_FREERTOS )
|
||||
|
||||
#define CRYPTODRV_PAL_THREADS_LOCK \
|
||||
if (false == RUNNING_AT_INTERRUPT_LEVEL) \
|
||||
vTaskSuspendAll();
|
||||
#define CRYPTODRV_PAL_THREADS_UNLOCK \
|
||||
if (false == RUNNING_AT_INTERRUPT_LEVEL) \
|
||||
xTaskResumeAll();
|
||||
|
||||
#define CRYPTODRV_PAL_THREAD_ID_GET (void*)xTaskGetCurrentTaskHandle()
|
||||
|
||||
#define CRYPTODRV_PAL_THREAD_PRIORITY_GET \
|
||||
((unsigned long)uxTaskPriorityGet(NULL))
|
||||
|
||||
#define CRYPTODRV_PAL_THREAD_RESUME(threadId) \
|
||||
xTaskResumeFromISR((TaskHandle_t)threadId)
|
||||
|
||||
#define CRYPTODRV_PAL_WAIT_FOR_OWNERSHIP(pCryptodrvContext) \
|
||||
cryptodrvPalWaitForOwnership(pCryptodrvContext)
|
||||
|
||||
__STATIC_INLINE void cryptodrvPalWaitForOwnership(CRYPTODRV_Context_t* pCryptodrvContext)
|
||||
{
|
||||
CRYPTODRV_Context_t** pCryptoOwner =
|
||||
(CRYPTODRV_Context_t**) pCryptodrvContext->device->pCryptoOwner;
|
||||
while (pCryptodrvContext != *pCryptoOwner)
|
||||
{
|
||||
vTaskSuspend(xTaskGetCurrentTaskHandle());
|
||||
}
|
||||
}
|
||||
|
||||
#else /* #if defined( CRYPTODRV_PAL_FREERTOS ) */
|
||||
|
||||
#define CRYPTODRV_PAL_THREADS_LOCK
|
||||
#define CRYPTODRV_PAL_THREADS_UNLOCK
|
||||
#define CRYPTODRV_PAL_THREAD_ID_GET (0)
|
||||
#define CRYPTODRV_PAL_THREAD_PRIORITY_GET (RUNNING_AT_INTERRUPT_LEVEL ? 1 : 0)
|
||||
#define CRYPTODRV_PAL_THREAD_RESUME(threadId)
|
||||
#define CRYPTODRV_PAL_WAIT_FOR_OWNERSHIP(pCryptodrvContext)
|
||||
|
||||
#endif /* #if defined( CRYPTODRV_PAL_FREERTOS ) */
|
||||
|
||||
#endif /* #if defined(MBEDTLS_CRYPTO_DEVICE_PREEMPTION) */
|
||||
|
||||
#if defined(MBEDTLS_INCLUDE_ASYNCH_API)
|
||||
/* Current callback function called from CRYPTO_IRQHandler. */
|
||||
static CRYPTODRV_AsynchCallback_t cryptoDrvAsynchCallback = 0;
|
||||
static void* cryptoDrvAsynchCallbackArgument;
|
||||
#endif
|
||||
|
||||
/*******************************************************************************
|
||||
****************************** FUNCTIONS **********************************
|
||||
******************************************************************************/
|
||||
|
||||
/***************************************************************************//**
|
||||
* @brief
|
||||
* Select which CRYPTO device instance to use in CRYPTO context.
|
||||
*
|
||||
* @param pCryptoContext
|
||||
* Pointer to CRYPTO context.
|
||||
*
|
||||
* @param devno
|
||||
* CRYPTO device instance number.
|
||||
*
|
||||
* @return
|
||||
* 0 if OK, or -1 if device number is invalid.
|
||||
******************************************************************************/
|
||||
int cryptodrvSetDeviceInstance(CRYPTODRV_Context_t* pCryptodrvContext,
|
||||
unsigned int devno)
|
||||
{
|
||||
if (devno > CRYPTO_COUNT)
|
||||
return( -1 );
|
||||
|
||||
pCryptodrvContext->device = &cryptoDevice[devno];
|
||||
return( 0 );
|
||||
}
|
||||
|
||||
#if defined MBEDTLS_CRYPTO_DEVICE_PREEMPTION
|
||||
|
||||
/***************************************************************************//**
|
||||
* @brief
|
||||
* Check state of a CRYPTO device instance.
|
||||
*
|
||||
* @details
|
||||
* Checks if a CRYPTO device is idle and ready for new operation, or busy
|
||||
* running an ongoing operation.
|
||||
*
|
||||
* @return
|
||||
* MBEDTLS_ECODE_CRYPTODRV_BUSY if CRYPTO is busy running an ongoing operation.
|
||||
* ECODE_OK if idle and ready for new operation.
|
||||
******************************************************************************/
|
||||
Ecode_t CRYPTODRV_CheckState( unsigned int devno )
|
||||
{
|
||||
/* The 'cryptoOwner' pointer indicates whether someone is already running a
|
||||
CRYPTO operation. */
|
||||
return cryptoOwner[devno] ? MBEDTLS_ECODE_CRYPTODRV_BUSY : ECODE_OK;
|
||||
}
|
||||
|
||||
/***************************************************************************//**
|
||||
* @brief
|
||||
* Arbitrate for exclusive access to CRYPTO unit.
|
||||
*
|
||||
* @details
|
||||
* This function will arbitrate for the ownership of the CRYPTO unit in order
|
||||
* to execute CRYPTO operations. If the ownership is won and there is an
|
||||
* ongoing CRYPTO operation, this function will preempt the ongoing operation
|
||||
* by storing the full CRYPTODRV context inlcuding hardware context
|
||||
* (register values) of the CRYPTO unit. When the caller is ready to release
|
||||
* CRYPTO, the caller should call CRYPTODRV_Release in
|
||||
* order to restore the context of the ongoing operation, in order for that to
|
||||
* continue operation. The function call of the ongoing operation may try to
|
||||
* restore and continue after the abort event, but may fail and return
|
||||
* MBEDTLS_ECODE_CRYPTODRV_OPERATION_ABORTED.
|
||||
* This function may be called from an interrupt handler in order to perform
|
||||
* time critical CRYPTO operations.
|
||||
*
|
||||
* @param pCryptodrvContext
|
||||
* Pointer to CRYPTODRV context which should be used in subsequent calls,
|
||||
* like @ref CRYPTODRV_Release.
|
||||
*
|
||||
* @return
|
||||
* MBEDTLS_ECODE_CRYPTODRV_OK if success. Error code if failure.
|
||||
* MBEDTLS_ECODE_CRYPTODRV_BUSY if priority is lower than or equal to the
|
||||
* pririty of the running thread.
|
||||
*/
|
||||
Ecode_t CRYPTODRV_Arbitrate (CRYPTODRV_Context_t* pCryptodrvContext)
|
||||
{
|
||||
CRYPTO_TypeDef* crypto = pCryptodrvContext->device->crypto;
|
||||
CRYPTODRV_Context_t** pCryptoOwner =
|
||||
(CRYPTODRV_Context_t**) pCryptodrvContext->device->pCryptoOwner;
|
||||
CRYPTODRV_Context_t* cryptoOwner;
|
||||
Ecode_t retval = ECODE_OK;
|
||||
CORE_DECLARE_IRQ_STATE;
|
||||
|
||||
CORE_ENTER_CRITICAL();
|
||||
CRYPTODRV_PAL_THREADS_LOCK;
|
||||
|
||||
cryptoOwner = *pCryptoOwner;
|
||||
|
||||
/* Check if someone is already running a CRYPTO operation. */
|
||||
if (cryptoOwner)
|
||||
{
|
||||
if (CRYPTODRV_PAL_THREAD_PRIORITY_GET <= cryptoOwner->threadPriority)
|
||||
{
|
||||
retval = MBEDTLS_ECODE_CRYPTODRV_BUSY;
|
||||
}
|
||||
else
|
||||
{
|
||||
CRYPTO_Context_t* pCryptoContext;
|
||||
uint8_t* pExecCmd;
|
||||
|
||||
/* We are running an ISR or thread of higher priority than the
|
||||
current crypto owner. If crypto is running, stop it and mark
|
||||
context as aborted. */
|
||||
if (crypto->STATUS
|
||||
& (CRYPTO_STATUS_INSTRRUNNING | CRYPTO_STATUS_SEQRUNNING))
|
||||
{
|
||||
crypto->CMD = CRYPTO_CMD_SEQSTOP;
|
||||
cryptoOwner->aborted = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
cryptoOwner->aborted = false;
|
||||
}
|
||||
|
||||
cryptoOwner->pContextPreemptor = pCryptodrvContext;
|
||||
|
||||
#if defined(MBEDTLS_INCLUDE_ASYNCH_API)
|
||||
/* Store the asynch callback state */
|
||||
cryptoOwner->asynchCallback = cryptoDrvAsynchCallback;
|
||||
cryptoOwner->asynchCallbackArgument = cryptoDrvAsynchCallbackArgument;
|
||||
#endif
|
||||
|
||||
/* Store the hardware state */
|
||||
pCryptoContext = &cryptoOwner->cryptoContext;
|
||||
|
||||
pCryptoContext->CTRL = crypto->CTRL;
|
||||
pCryptoContext->WAC = crypto->WAC;
|
||||
pCryptoContext->SEQCTRL = crypto->SEQCTRL;
|
||||
pCryptoContext->SEQCTRLB = crypto->SEQCTRLB;
|
||||
pCryptoContext->IEN = crypto->IEN;
|
||||
pCryptoContext->SEQ[0] = crypto->SEQ0;
|
||||
pCryptoContext->SEQ[1] = crypto->SEQ1;
|
||||
pCryptoContext->SEQ[2] = crypto->SEQ2;
|
||||
pCryptoContext->SEQ[3] = crypto->SEQ3;
|
||||
pCryptoContext->SEQ[4] = crypto->SEQ4;
|
||||
|
||||
/* Search for possible EXEC commands and replace with END. */
|
||||
pExecCmd = (uint8_t*) memchr(&pCryptoContext->SEQ,
|
||||
CRYPTO_CMD_INSTR_EXEC,
|
||||
sizeof(pCryptoContext->SEQ));
|
||||
if (pExecCmd)
|
||||
{
|
||||
memset(pExecCmd,
|
||||
(uint8_t) CRYPTO_CMD_INSTR_END,
|
||||
sizeof(pCryptoContext->SEQ) -
|
||||
((uint32_t)pExecCmd-(uint32_t)&pCryptoContext->SEQ));
|
||||
}
|
||||
CRYPTO_DDataRead(&crypto->DDATA0, pCryptoContext->DDATA[0]);
|
||||
CRYPTO_DDataRead(&crypto->DDATA1, pCryptoContext->DDATA[1]);
|
||||
CRYPTO_DDataRead(&crypto->DDATA2, pCryptoContext->DDATA[2]);
|
||||
CRYPTO_DDataRead(&crypto->DDATA3, pCryptoContext->DDATA[3]);
|
||||
CRYPTO_DDataRead(&crypto->DDATA4, pCryptoContext->DDATA[4]);
|
||||
|
||||
retval = ECODE_OK;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
CRYPTODRV_CLOCK_ENABLE(pCryptodrvContext->device->clk);
|
||||
}
|
||||
|
||||
if (ECODE_OK == retval)
|
||||
{
|
||||
pCryptodrvContext->pContextPreempted = cryptoOwner;
|
||||
*pCryptoOwner = pCryptodrvContext;
|
||||
pCryptodrvContext->pContextPreemptor = 0;
|
||||
pCryptodrvContext->aborted = false;
|
||||
pCryptodrvContext->threadPriority = CRYPTODRV_PAL_THREAD_PRIORITY_GET;
|
||||
pCryptodrvContext->threadId = CRYPTODRV_PAL_THREAD_ID_GET;
|
||||
|
||||
#if defined(MBEDTLS_INCLUDE_ASYNCH_API)
|
||||
CRYPTODRV_SetAsynchCallback(pCryptodrvContext, 0, 0);
|
||||
#endif
|
||||
}
|
||||
|
||||
CRYPTODRV_PAL_THREADS_UNLOCK;
|
||||
CORE_EXIT_CRITICAL();
|
||||
|
||||
return retval;
|
||||
}
|
||||
|
||||
/***************************************************************************//**
|
||||
* @brief
|
||||
* Release a CRYPTODRV context and possibly ownership of CRYPTO unit.
|
||||
*
|
||||
* @details
|
||||
* This function removes a CRYPTODRV context from the CRYPTODRV context list
|
||||
* (which includes current owner and preempted contexts).
|
||||
* If the specified context is the owner of the CRYPTO unit, this function
|
||||
* will release the ownership of the CRYPTO unit. If there is a preempted
|
||||
* context in the context list, then the preempted context is restored
|
||||
* by updating the hardware state of the CRYPTO unit.
|
||||
*
|
||||
* @param pCryptodrvContext
|
||||
* The CRYPTODRV context to remove from CRYPTODRV context list.
|
||||
*
|
||||
* @return
|
||||
* MBEDTLS_ECODE_CRYPTODRV_OK if success. Error code if failure.
|
||||
*/
|
||||
Ecode_t CRYPTODRV_Release (CRYPTODRV_Context_t* pCryptodrvContext)
|
||||
{
|
||||
CRYPTODRV_Context_t* preempted =
|
||||
(CRYPTODRV_Context_t*) pCryptodrvContext->pContextPreempted;
|
||||
CRYPTODRV_Context_t* preemptor =
|
||||
(CRYPTODRV_Context_t*) pCryptodrvContext->pContextPreemptor;
|
||||
CRYPTO_TypeDef* crypto = pCryptodrvContext->device->crypto;
|
||||
CRYPTODRV_Context_t** pCryptoOwner =
|
||||
(CRYPTODRV_Context_t**) pCryptodrvContext->device->pCryptoOwner;
|
||||
CRYPTODRV_Context_t* cryptoOwner;
|
||||
CORE_DECLARE_IRQ_STATE;
|
||||
|
||||
CORE_ENTER_CRITICAL();
|
||||
CRYPTODRV_PAL_THREADS_LOCK;
|
||||
|
||||
if ( (0==preempted) && (0==preemptor))
|
||||
{
|
||||
*pCryptoOwner = NULL;
|
||||
CRYPTODRV_CLOCK_DISABLE(pCryptodrvContext->device->clk);
|
||||
}
|
||||
else
|
||||
{
|
||||
cryptoOwner = *pCryptoOwner;
|
||||
|
||||
/* If _this_ context was preempted, and the preemptor is still running,
|
||||
then inform the preemptor that _this_ context is not valid any more
|
||||
by linking to _this_ preempted context (which may be NULL). */
|
||||
if (preemptor)
|
||||
{
|
||||
preemptor->pContextPreempted = preempted;
|
||||
}
|
||||
|
||||
if (preempted)
|
||||
{
|
||||
/* Remove _this_ context from preemption list (double linked) by
|
||||
replacing preempted preemptor (_this_) with preemptor of _this_
|
||||
context (may be NULL if _this_ is owner of crypto). */
|
||||
preempted->pContextPreemptor = preemptor;
|
||||
|
||||
/* If _this_ conxtext is the owner of crypto, restore preempted
|
||||
context and set it to owner. */
|
||||
if (cryptoOwner == pCryptodrvContext)
|
||||
{
|
||||
CRYPTO_Context_t* pCryptoContext = &preempted->cryptoContext;
|
||||
|
||||
crypto->CTRL = pCryptoContext->CTRL;
|
||||
crypto->WAC = pCryptoContext->WAC;
|
||||
crypto->SEQCTRL = pCryptoContext->SEQCTRL;
|
||||
crypto->SEQCTRLB = pCryptoContext->SEQCTRLB;
|
||||
crypto->IEN = pCryptoContext->IEN;
|
||||
crypto->SEQ0 = pCryptoContext->SEQ[0];
|
||||
crypto->SEQ1 = pCryptoContext->SEQ[1];
|
||||
crypto->SEQ2 = pCryptoContext->SEQ[2];
|
||||
crypto->SEQ3 = pCryptoContext->SEQ[3];
|
||||
crypto->SEQ4 = pCryptoContext->SEQ[4];
|
||||
CRYPTO_DDataWrite(&crypto->DDATA0, pCryptoContext->DDATA[0]);
|
||||
CRYPTO_DDataWrite(&crypto->DDATA1, pCryptoContext->DDATA[1]);
|
||||
CRYPTO_DDataWrite(&crypto->DDATA2, pCryptoContext->DDATA[2]);
|
||||
CRYPTO_DDataWrite(&crypto->DDATA3, pCryptoContext->DDATA[3]);
|
||||
CRYPTO_DDataWrite(&crypto->DDATA4, pCryptoContext->DDATA[4]);
|
||||
|
||||
#if defined(MBEDTLS_INCLUDE_ASYNCH_API)
|
||||
CRYPTODRV_SetAsynchCallback(pCryptodrvContext,
|
||||
preempted->asynchCallback,
|
||||
preempted->asynchCallbackArgument);
|
||||
#endif
|
||||
|
||||
cryptoOwner = *pCryptoOwner = preempted;
|
||||
/* Resume new owner task (which may be suspended by now). */
|
||||
CRYPTODRV_PAL_THREAD_RESUME(cryptoOwner->threadId);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
CRYPTODRV_PAL_THREADS_UNLOCK;
|
||||
CORE_EXIT_CRITICAL();
|
||||
|
||||
return ECODE_OK;
|
||||
}
|
||||
|
||||
#if !defined( MBEDTLS_CRYPTO_CRITICAL_REGION_ALT )
|
||||
|
||||
/***************************************************************************//**
|
||||
* @brief
|
||||
* Enter a critical CRYPTO region.
|
||||
*
|
||||
* @details
|
||||
* This function enters a critical region of a CRYPTO operation by disabling
|
||||
* all interrupts, except the CRYPTO interrupt. If a thread which is not the
|
||||
* owner of CRYPTO tries to enter the critical region, it will be suspended.
|
||||
* The thread will be resumed when the preemptor calls CRYPTODRV_Release.
|
||||
*
|
||||
* @return
|
||||
* ECODE_OK
|
||||
*/
|
||||
Ecode_t CRYPTODRV_EnterCriticalRegion (CRYPTODRV_Context_t* pCryptodrvContext)
|
||||
{
|
||||
int i;
|
||||
IRQn_Type irqn = pCryptodrvContext->device->irqn;
|
||||
uint32_t* pNvicIser = pCryptodrvContext->device->pNvicIser;
|
||||
CORE_DECLARE_IRQ_STATE;
|
||||
|
||||
CRYPTODRV_PAL_WAIT_FOR_OWNERSHIP(pCryptodrvContext);
|
||||
|
||||
CORE_ENTER_CRITICAL();
|
||||
CRYPTODRV_PAL_THREADS_LOCK;
|
||||
|
||||
/* Disable all interrupts except the CRYPTO IRQ. Remember which interrupts
|
||||
that was enabled in order to enable them when exiting the critical
|
||||
region. */
|
||||
for (i=0; i<MAX_NVIC_ISER; i++)
|
||||
{
|
||||
pNvicIser[i] = NVIC->ISER[i];
|
||||
NVIC->ICER[i] = pNvicIser[i];
|
||||
}
|
||||
NVIC->ISER[(uint32_t)((int32_t)irqn) >> 5] =
|
||||
(uint32_t)(1 << ((uint32_t)((int32_t)irqn) & (uint32_t)0x1F));
|
||||
|
||||
CRYPTODRV_PAL_THREADS_UNLOCK;
|
||||
CORE_EXIT_CRITICAL();
|
||||
|
||||
return ECODE_OK;
|
||||
}
|
||||
|
||||
/***************************************************************************//**
|
||||
* @brief
|
||||
* Exit a critical CRYPTO region.
|
||||
*
|
||||
* @details
|
||||
* This function exits a critical region of a CRYPTO operation.
|
||||
* This function will enable all interrupts that was enabled when the initial
|
||||
* nested critical region was entered.
|
||||
*
|
||||
* @return
|
||||
* ECODE_OK
|
||||
*/
|
||||
Ecode_t CRYPTODRV_ExitCriticalRegion (CRYPTODRV_Context_t* pCryptodrvContext)
|
||||
{
|
||||
int i;
|
||||
(void) pCryptodrvContext; /* remove compiler warning when pCryptodrvContext
|
||||
is not used.*/
|
||||
uint32_t* pNvicIser = pCryptodrvContext->device->pNvicIser;
|
||||
CORE_DECLARE_IRQ_STATE;
|
||||
|
||||
CORE_ENTER_CRITICAL();
|
||||
CRYPTODRV_PAL_THREADS_LOCK;
|
||||
|
||||
/* Enable all interrupts that was enabled when entering the critical
|
||||
region. */
|
||||
for (i=0; i<MAX_NVIC_ISER; i++)
|
||||
{
|
||||
NVIC->ISER[i] |= pNvicIser[i];
|
||||
}
|
||||
|
||||
CRYPTODRV_PAL_THREADS_UNLOCK;
|
||||
CORE_EXIT_CRITICAL();
|
||||
|
||||
return ECODE_OK;
|
||||
}
|
||||
|
||||
#endif /* #if !defined( MBEDTLS_CRYPTO_CRITICAL_REGION_ALT ) */
|
||||
|
||||
#endif /* #if defined( MBEDTLS_CRYPTO_DEVICE_PREEMPTION ) */
|
||||
|
||||
#if defined(MBEDTLS_INCLUDE_ASYNCH_API)
|
||||
|
||||
/***************************************************************************//**
|
||||
* @brief
|
||||
* Set asynchronous callback to be called when crypto operations complete.
|
||||
*
|
||||
* @details
|
||||
* This function sets the asynchronous callback function to be called when
|
||||
* crypto operations complete. This function should be called inside _the_
|
||||
* critical region of an asynchronous operation.
|
||||
*
|
||||
* @return
|
||||
* N/A
|
||||
*/
|
||||
void CRYPTODRV_SetAsynchCallback
|
||||
(
|
||||
CRYPTODRV_Context_t* pCryptodrvContext,
|
||||
CRYPTODRV_AsynchCallback_t asynchCallback,
|
||||
void* callbackArgument
|
||||
)
|
||||
{
|
||||
CRYPTO_TypeDef* crypto = pCryptodrvContext->device->crypto;
|
||||
IRQn_Type irqn = pCryptodrvContext->device->irqn;
|
||||
if (asynchCallback)
|
||||
{
|
||||
cryptoDrvAsynchCallback = asynchCallback;
|
||||
cryptoDrvAsynchCallbackArgument = callbackArgument;
|
||||
crypto->IFC = _CRYPTO_IFC_MASK;
|
||||
crypto->IEN = CRYPTO_IEN_SEQDONE;
|
||||
NVIC_ClearPendingIRQ(irqn);
|
||||
NVIC_EnableIRQ(irqn);
|
||||
#if defined( CRYPTODRV_PAL_FREERTOS )
|
||||
/* Set priority below the configured maximum system call priority */
|
||||
NVIC_SetPriority(irqn, CRYPTO_IRQn_PRIORITY);
|
||||
#endif
|
||||
}
|
||||
else
|
||||
{
|
||||
cryptoDrvAsynchCallback = 0;
|
||||
crypto->IEN = 0;
|
||||
crypto->IFC = _CRYPTO_IFC_MASK;
|
||||
NVIC_DisableIRQ(irqn);
|
||||
}
|
||||
}
|
||||
|
||||
/***************************************************************************//**
|
||||
* @brief
|
||||
* Interrupt service routine for CRYPTO module instances.
|
||||
*
|
||||
* @details
|
||||
* CRYPTO_IRQHandler, CRYPTO0_IRQHandler, etc are the first functions to be
|
||||
* called when an interrupt from the respective CRYPTO instance is being
|
||||
* serviced by the MCU. The function cryptoIrqHandlerGeneric is called with
|
||||
* a pointer to the respective CRYPTO unit, and it will clear the interrupt
|
||||
* and call the interrupt service routine associated with the operation that
|
||||
* caused the interrupt. The operation specific ISR must be registered by
|
||||
* calling @ref CRYPTODRV_SetAsynchCallback before the operation is started.
|
||||
*
|
||||
* @return
|
||||
* N/A
|
||||
*/
|
||||
void cryptoIrqHandlerGeneric( const CRYPTO_Device_t* cryptoDevice )
|
||||
{
|
||||
CRYPTO_TypeDef* crypto = cryptoDevice->crypto;
|
||||
uint32_t flags = crypto->IF;
|
||||
|
||||
while (flags)
|
||||
{
|
||||
crypto->IFC = flags;
|
||||
NVIC_ClearPendingIRQ(cryptoDevice->irqn);
|
||||
|
||||
if (flags & CRYPTO_IF_SEQDONE)
|
||||
{
|
||||
if (cryptoDrvAsynchCallback)
|
||||
{
|
||||
cryptoDrvAsynchCallback (cryptoDrvAsynchCallbackArgument);
|
||||
}
|
||||
}
|
||||
if (CMU->HFBUSCLKEN0 & cryptoDevice->clk)
|
||||
flags = crypto->IF;
|
||||
else
|
||||
flags = 0;
|
||||
}
|
||||
}
|
||||
|
||||
#if defined(CRYPTO)
|
||||
void CRYPTO_IRQHandler(void)
|
||||
{
|
||||
cryptoIrqHandlerGeneric( &cryptoDevice[0] );
|
||||
}
|
||||
#endif
|
||||
|
||||
#if defined(CRYPTO0)
|
||||
void CRYPTO0_IRQHandler(void)
|
||||
{
|
||||
cryptoIrqHandlerGeneric( &cryptoDevice[0] );
|
||||
}
|
||||
#endif
|
||||
|
||||
#if defined(CRYPTO1)
|
||||
void CRYPTO1_IRQHandler(void)
|
||||
{
|
||||
cryptoIrqHandlerGeneric( &cryptoDevice[1] );
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* #if defined(MBEDTLS_INCLUDE_ASYNCH_API) */
|
||||
|
||||
#endif /* #if defined(CRYPTO_COUNT) && (CRYPTO_COUNT > 0) */
|
|
@ -0,0 +1,337 @@
|
|||
/*
|
||||
* CRYPTO driver internal definitions including CRYPTO preemption and
|
||||
* asynchronous (non-blocking) support.
|
||||
*
|
||||
* Copyright (C) 2016, Silicon Labs, http://www.silabs.com
|
||||
* 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 __SILICON_LABS_CRYPTODRV_INTERNAL_H
|
||||
#define __SILICON_LABS_CRYPTODRV_INTERNAL_H
|
||||
|
||||
#include "em_device.h"
|
||||
|
||||
#if ( defined(CRYPTO_COUNT) && (CRYPTO_COUNT > 0) )
|
||||
|
||||
#if !defined(MBEDTLS_CONFIG_FILE)
|
||||
#include "mbedtls/config.h"
|
||||
#else
|
||||
#include MBEDTLS_CONFIG_FILE
|
||||
#endif
|
||||
|
||||
#include "cryptodrv.h"
|
||||
#include "ecode.h"
|
||||
#include <stdint.h>
|
||||
#include <string.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/*******************************************************************************
|
||||
****************************** Functions **********************************
|
||||
******************************************************************************/
|
||||
|
||||
/***************************************************************************//**
|
||||
* @brief
|
||||
* Select which CRYPTO device instance to use in CRYPTO context.
|
||||
*
|
||||
* @param pCryptoContext
|
||||
* Pointer to CRYPTO context.
|
||||
*
|
||||
* @param devno
|
||||
* CRYPTO device instance number.
|
||||
*
|
||||
* @return
|
||||
* 0 if OK, or -1 if device number is invalid.
|
||||
******************************************************************************/
|
||||
int cryptodrvSetDeviceInstance(CRYPTODRV_Context_t* pCryptodrvContext,
|
||||
unsigned int devno);
|
||||
|
||||
/***************************************************************************//**
|
||||
* @brief
|
||||
* Write a 128 bit value (optionally unaligned) into a crypto register.
|
||||
*
|
||||
* @note
|
||||
* This function provide a low-level api for writing to the multi-word
|
||||
* registers in the crypto peripheral. Applications should prefer to use
|
||||
* @ref CRYPTO_DataWrite, @ref CRYPTO_DDataWrite or @ref CRYPTO_QDataWrite
|
||||
* for writing to the DATA, DDATA and QDATA registers.
|
||||
*
|
||||
* @param[in] reg
|
||||
* Pointer to the crypto register.
|
||||
*
|
||||
* @param[in] val
|
||||
* This is a pointer to 4 32 bit integers that contains the 128 bit value
|
||||
* which will be written to the crypto register.
|
||||
******************************************************************************/
|
||||
__STATIC_INLINE void CRYPTODRV_DataWriteUnaligned(volatile uint32_t * reg,
|
||||
const uint8_t * val)
|
||||
{
|
||||
/* Check data is 32bit aligned, if not move to temporary buffer before
|
||||
writing.*/
|
||||
if ((uint32_t)val & 0x3)
|
||||
{
|
||||
uint32_t temp[4];
|
||||
memcpy(temp, val, 16);
|
||||
CRYPTO_DataWrite(reg, temp);
|
||||
}
|
||||
else
|
||||
{
|
||||
CRYPTO_DataWrite(reg, (uint32_t*)val);
|
||||
}
|
||||
}
|
||||
|
||||
/***************************************************************************//**
|
||||
* @brief
|
||||
* Read a 128 bit value from a crypto register into optionally unaligned
|
||||
* buffer.
|
||||
*
|
||||
* @note
|
||||
* This function provide a low-level api for reading one of the multi-word
|
||||
* registers in the crypto peripheral. Applications should prefer to use
|
||||
* @ref CRYPTO_DataRead, @ref CRYPTO_DDataRead or @ref CRYPTO_QDataRead
|
||||
* for reading the value of the DATA, DDATA and QDATA registers.
|
||||
*
|
||||
* @param[in] reg
|
||||
* Pointer to the crypto register.
|
||||
*
|
||||
* @param[out] val
|
||||
* This is a pointer to an array that is capable of holding 4 32 bit integers
|
||||
* that will be filled with the 128 bit value from the crypto register.
|
||||
******************************************************************************/
|
||||
__STATIC_INLINE void CRYPTODRV_DataReadUnaligned(volatile uint32_t * reg,
|
||||
uint8_t * val)
|
||||
{
|
||||
/* Check data is 32bit aligned, if not, read into temporary buffer and
|
||||
then move to user buffer. */
|
||||
if ((uint32_t)val & 0x3)
|
||||
{
|
||||
uint32_t temp[4];
|
||||
CRYPTO_DataRead(reg, temp);
|
||||
memcpy(val, temp, 16);
|
||||
}
|
||||
else
|
||||
{
|
||||
CRYPTO_DataRead(reg, (uint32_t*)val);
|
||||
}
|
||||
}
|
||||
|
||||
/***************************************************************************//**
|
||||
* @brief
|
||||
* Read a 256 bit value from a crypto register into optionally unaligned
|
||||
* buffer.
|
||||
*
|
||||
* @note
|
||||
* This function provide a low-level api for reading one of the multi-word
|
||||
* registers in the crypto peripheral. Applications should prefer to use
|
||||
* @ref CRYPTO_DataRead, @ref CRYPTO_DDataRead or @ref CRYPTO_QDataRead
|
||||
* for reading the value of the DATA, DDATA and QDATA registers.
|
||||
*
|
||||
* @param[in] reg
|
||||
* Pointer to the crypto register.
|
||||
*
|
||||
* @param[out] val
|
||||
* This is a pointer to a byte array of at least 32 bytes
|
||||
* that will be filled with the 256 bit value from the crypto register.
|
||||
******************************************************************************/
|
||||
__STATIC_INLINE void CRYPTODRV_DDataReadUnaligned(volatile uint32_t * reg,
|
||||
uint8_t * val)
|
||||
{
|
||||
/* Check data is 32bit aligned, if not, read into temporary buffer and
|
||||
then move to user buffer. */
|
||||
if ((uint32_t)val & 0x3)
|
||||
{
|
||||
uint32_t temp[8];
|
||||
CRYPTO_DDataRead(reg, temp);
|
||||
memcpy(val, temp, 32);
|
||||
}
|
||||
else
|
||||
{
|
||||
CRYPTO_DDataRead(reg, (uint32_t*)val);
|
||||
}
|
||||
}
|
||||
|
||||
/***************************************************************************//**
|
||||
* @brief
|
||||
* Check status of CRYPTO operation.
|
||||
*
|
||||
* @details
|
||||
* This function checks the status of a specific CRYPTO operation.
|
||||
*
|
||||
* @param pCryptoContext
|
||||
* Pointer to CRYPTO context associated with operation.
|
||||
*
|
||||
* @return
|
||||
* ECODE_OK if operation completed successfully.
|
||||
* ECODE_CRYPTODRV_RUNNING if CRYPTO is executing operation.
|
||||
* ECODE_CRYPTODRV_ABORTED if operation was aborted.
|
||||
*/
|
||||
Ecode_t CRYPTODRV_CheckStatus (CRYPTODRV_Context_t* pCryptoContext);
|
||||
|
||||
#if defined(MBEDTLS_INCLUDE_ASYNCH_API)
|
||||
|
||||
/***************************************************************************//**
|
||||
* @brief
|
||||
* Set asynchronous callback to be called when crypto operations complete.
|
||||
*
|
||||
* @details
|
||||
* This function sets the asynchronous callback function to be called when
|
||||
* crypto operations complete.
|
||||
*
|
||||
* @return
|
||||
* N/A
|
||||
*/
|
||||
void CRYPTODRV_SetAsynchCallback
|
||||
(
|
||||
CRYPTODRV_Context_t* pCryptodrvContext,
|
||||
CRYPTODRV_AsynchCallback_t asynchCallback,
|
||||
void* callbackArgument
|
||||
);
|
||||
|
||||
#else /* #if defined(MBEDTLS_INCLUDE_ASYNCH_API) */
|
||||
|
||||
__STATIC_INLINE void CRYPTODRV_SetAsynchCallback
|
||||
(
|
||||
CRYPTODRV_Context_t* pCryptodrvContext,
|
||||
CRYPTODRV_AsynchCallback_t asynchCallback,
|
||||
void* callbackArgument
|
||||
)
|
||||
{
|
||||
(void) pCryptodrvContext;
|
||||
(void) asynchCallback;
|
||||
(void) callbackArgument;
|
||||
}
|
||||
|
||||
#endif /* #if defined(MBEDTLS_INCLUDE_ASYNCH_API) */
|
||||
|
||||
#if defined MBEDTLS_CRYPTO_DEVICE_PREEMPTION
|
||||
|
||||
/***************************************************************************//**
|
||||
* @brief
|
||||
* Arbitrate for exclusive access to CRYPTO unit.
|
||||
*
|
||||
* @details
|
||||
* This function will arbitrate for the ownership of the CRYPTO unit in order
|
||||
* to execute CRYPTO operations. If the ownership is won and there is an
|
||||
* ongoing CRYPTO operation, this function will preempt the ongoing operation
|
||||
* by storing the full CRYPTODRV context inlcuding hardware context
|
||||
* (register values) of the CRYPTO unit. When the caller is ready to release
|
||||
* CRYPTO, the caller should call CRYPTODRV_Release in
|
||||
* order to restore the context of the ongoing operation, in order for that to
|
||||
* continue operation. The function call of the ongoing operation may try to
|
||||
* restore and continue after the abort event, but may fail and return
|
||||
* MBEDTLS_ECODE_CRYPTODRV_OPERATION_ABORTED.
|
||||
* This function may be called from an interrupt handler in order to perform
|
||||
* time critical CRYPTO operations.
|
||||
*
|
||||
* @param pCryptodrvContext
|
||||
* Pointer to CRYPTODRV context which should be used in subsequent calls,
|
||||
* like @ref CRYPTODRV_Release.
|
||||
*
|
||||
* @return
|
||||
* ECODE_OK if success. Error code if failure.
|
||||
* MBEDTLS_ECODE_CRYPTODRV_BUSY if priority is lower than or equal to running thread.
|
||||
*/
|
||||
Ecode_t CRYPTODRV_Arbitrate (CRYPTODRV_Context_t* pCryptodrvContext);
|
||||
|
||||
/***************************************************************************//**
|
||||
* @brief
|
||||
* Release a CRYPTODRV context and possibly ownership of CRYPTO unit.
|
||||
*
|
||||
* @details
|
||||
* This function removes a CRYPTODRV context from the CRYPTODRV context list
|
||||
* (which includes current owner and preempted contexts).
|
||||
* If the specified context is the owner of the CRYPTO unit, this function
|
||||
* will release the ownership of the CRYPTO unit. If there is a preempted
|
||||
* context in the context list, then the preempted context is restored
|
||||
* by updating the hardware state of the CRYPTO unit.
|
||||
*
|
||||
* @param pCryptodrvContext
|
||||
* The CRYPTODRV context to remove from CRYPTODRV context list.
|
||||
*
|
||||
* @return
|
||||
* ECODE_OK if success. Error code if failure.
|
||||
*/
|
||||
Ecode_t CRYPTODRV_Release (CRYPTODRV_Context_t* pCryptodrvContext);
|
||||
|
||||
/***************************************************************************//**
|
||||
* @brief
|
||||
* Enter critical CRYPTO operation region.
|
||||
*
|
||||
* @details
|
||||
* This function will enter a critical region by disabling potential harmful
|
||||
* interrupts and thread scheduling, in order to protect a CRYPTO operation
|
||||
* from being interrupted and aborted by higher priority threads/ISRs.
|
||||
* The implementation of this function is OS/runtime platform dependent and
|
||||
* there should be one version per supported OS/runtime platform.
|
||||
*
|
||||
* @return
|
||||
* ECODE_OK if success. Error code if failure.
|
||||
*/
|
||||
Ecode_t CRYPTODRV_EnterCriticalRegion (CRYPTODRV_Context_t* pCryptodrvContext);
|
||||
|
||||
/***************************************************************************//**
|
||||
* @brief
|
||||
* Exit critical CRYPTO operation region.
|
||||
*
|
||||
* @details
|
||||
* This function exits from a critical region by enabling interrupts and
|
||||
* thread scheduling, in order to allow higher priority threads/ISRs to
|
||||
* arbitrate for CRYPTO ownership.
|
||||
* The implementation of this function is OS/runtime platform dependent and
|
||||
* there should be one version per supported OS/runtime platform.
|
||||
*
|
||||
* @return
|
||||
* ECODE_OK if success. Error code if failure.
|
||||
*/
|
||||
Ecode_t CRYPTODRV_ExitCriticalRegion (CRYPTODRV_Context_t* pCryptodrvContext);
|
||||
|
||||
#else /* #if defined MBEDTLS_CRYPTO_DEVICE_PREEMPTION */
|
||||
|
||||
__STATIC_INLINE
|
||||
Ecode_t CRYPTODRV_Arbitrate (CRYPTODRV_Context_t* pCryptodrvContext)
|
||||
{
|
||||
CMU->HFBUSCLKEN0 |= pCryptodrvContext->device->clk;
|
||||
return ECODE_OK;
|
||||
}
|
||||
__STATIC_INLINE
|
||||
Ecode_t CRYPTODRV_Release (CRYPTODRV_Context_t* pCryptodrvContext)
|
||||
{
|
||||
CMU->HFBUSCLKEN0 &= ~pCryptodrvContext->device->clk;
|
||||
return ECODE_OK;
|
||||
}
|
||||
__STATIC_INLINE
|
||||
Ecode_t CRYPTODRV_EnterCriticalRegion (CRYPTODRV_Context_t* pCryptodrvContext)
|
||||
{
|
||||
(void) pCryptodrvContext;
|
||||
return ECODE_OK;
|
||||
}
|
||||
__STATIC_INLINE
|
||||
Ecode_t CRYPTODRV_ExitCriticalRegion (CRYPTODRV_Context_t* pCryptodrvContext)
|
||||
{
|
||||
(void) pCryptodrvContext;
|
||||
return ECODE_OK;
|
||||
}
|
||||
|
||||
#endif /* #if defined MBEDTLS_CRYPTO_DEVICE_PREEMPTION */
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* #if ( defined(CRYPTO_COUNT) && (CRYPTO_COUNT > 0) ) || \
|
||||
( defined(AES_COUNT) && (AES_COUNT > 0) ) */
|
||||
|
||||
#endif /* #ifndef __SILICON_LABS_CRYPTODRV_INTERNAL_H */
|
|
@ -0,0 +1,433 @@
|
|||
/*
|
||||
* Buffer Controller (BUFC) interface implementation.
|
||||
*
|
||||
* Copyright (C) 2016 Silicon Labs, http://www.silabs.com
|
||||
* 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 "em_device.h"
|
||||
|
||||
#if defined(BUFC_COUNT) && (BUFC_COUNT > 0)
|
||||
|
||||
#if !defined(MBEDTLS_CONFIG_FILE)
|
||||
#include "mbedtls/config.h"
|
||||
#else
|
||||
#include MBEDTLS_CONFIG_FILE
|
||||
#endif
|
||||
|
||||
#include "em_bufc.h"
|
||||
#include "em_assert.h"
|
||||
|
||||
/***************************************************************************//**
|
||||
* @addtogroup EM_Library
|
||||
* @{
|
||||
******************************************************************************/
|
||||
|
||||
/***************************************************************************//**
|
||||
* @addtogroup BUFC
|
||||
* @{
|
||||
******************************************************************************/
|
||||
|
||||
/*******************************************************************************
|
||||
******************************** ENUMS ************************************
|
||||
******************************************************************************/
|
||||
|
||||
|
||||
/*******************************************************************************
|
||||
******************************* STRUCTS ***********************************
|
||||
******************************************************************************/
|
||||
|
||||
|
||||
/*******************************************************************************
|
||||
*************************** GLOBAL FUNCTIONS ******************************
|
||||
******************************************************************************/
|
||||
|
||||
|
||||
/***************************************************************************//**
|
||||
* @brief
|
||||
* Initialize the Buffer Controller (BUFC) of EFR.
|
||||
*
|
||||
* @details
|
||||
* Use this function to initialize the 4 buffers controlled by the Buffer
|
||||
* Controller (BUFC).
|
||||
* Refer to EFR Reference Manual Chapter 5.8 and the configuration structure
|
||||
* BUFC_Init_TypeDef for more details.
|
||||
*
|
||||
* @note
|
||||
* Internal notes:
|
||||
* Init should map all the buffers (/w starter address), set threshold mode, etc
|
||||
* Init should use the BufferConfig()
|
||||
* It would be important to enforce the use of Init() as it would be required
|
||||
* (and safe) to initialize all the buffers in each RESET or WAKEUP cycle.
|
||||
* => this shall be handled by higher layers (platform)
|
||||
* Note: These kinda cases are not optimal for SPI access, (starter addr mixed
|
||||
* with thrsh mode ("fragmentation")
|
||||
*
|
||||
* - BUFC_ThresholdOnPinSet() should be part of init?
|
||||
*
|
||||
* @param[in] init
|
||||
* Pointer to initialization structure used to configure the buffers.
|
||||
******************************************************************************/
|
||||
void BUFC_Init(BUFC_Init_TypeDef const *init)
|
||||
{
|
||||
uint32_t i;
|
||||
|
||||
|
||||
/* Iterate through all the buffers. */
|
||||
for (i = 0U; i < 4U; i++)
|
||||
{
|
||||
BUFC_BufferConfig(i, &(init->buffer[i]));
|
||||
/* BUFC_ThresholdOnPinSet() ? */
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/***************************************************************************//**
|
||||
* @brief
|
||||
* Reset BUFC registers to the hardware reset state.
|
||||
*
|
||||
* @details
|
||||
* This function resets all the buffer configurations (incl. address, size,
|
||||
* buffer pointers, etc.).
|
||||
******************************************************************************/
|
||||
void BUFC_Reset(void)
|
||||
{
|
||||
uint32_t i;
|
||||
|
||||
/* Reset all buffers (0-3). */
|
||||
for (i = 0U; i < 4U; i++)
|
||||
{
|
||||
/* Clear the buffer. */
|
||||
BUFC_Clear(i);
|
||||
|
||||
/* Reset BUF[i] registers to their default values. */
|
||||
BUFC->BUF[i].CTRL = _BUFC_BUF_CTRL_RESETVALUE;
|
||||
BUFC->BUF[i].ADDR = _BUFC_BUF_ADDR_RESETVALUE;
|
||||
BUFC->BUF[i].WRITEOFFSET = _BUFC_BUF_WRITEOFFSET_RESETVALUE;
|
||||
BUFC->BUF[i].READOFFSET = _BUFC_BUF_READOFFSET_RESETVALUE;
|
||||
BUFC->BUF[i].WRITEDATA = _BUFC_BUF_WRITEDATA_RESETVALUE;
|
||||
BUFC->BUF[i].THRESHOLDCTRL = _BUFC_BUF_THRESHOLDCTRL_RESETVALUE;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/***************************************************************************//**
|
||||
* @brief
|
||||
* Configures all parameters of the selected buffer.
|
||||
*
|
||||
* @details
|
||||
* Use this function to initialize the 4 buffers controlled by the Buffer
|
||||
* Controller (BUFC).
|
||||
* Refer to EFR Reference Manual Chapter 5.8 and the configuration structure
|
||||
* BUFC_Init_TypeDef for more details.
|
||||
*
|
||||
* @note
|
||||
* Internal notes:
|
||||
* This should not use the INLINEs provided below.
|
||||
* Think with a MANAGEMENT sublayer in mind when designing this API.
|
||||
* eg. single buffer manipulation could possibly be done by higher level
|
||||
* using this function. Think of run-time services.
|
||||
* - buffer size enums are used because its more consistent for higher level
|
||||
* layers to handle allocated RAM size and BUFC buffer size with them
|
||||
*
|
||||
* @param[in] confPtr
|
||||
* Pointer to configuration structure used to configure the buffers.
|
||||
******************************************************************************/
|
||||
void BUFC_BufferConfig(uint32_t bufId,
|
||||
BUFC_BufferConf_TypeDef const *confPtr)
|
||||
{
|
||||
uint32_t tmp;
|
||||
|
||||
|
||||
/* Sanity check of bufId. */
|
||||
EFM_ASSERT(bufId < 4U);
|
||||
EFM_ASSERT((confPtr->size == bufcSize64) ||
|
||||
(confPtr->size == bufcSize128) ||
|
||||
(confPtr->size == bufcSize256) ||
|
||||
(confPtr->size == bufcSize1024) ||
|
||||
(confPtr->size == bufcSize2048) ||
|
||||
(confPtr->size == bufcSize512));
|
||||
|
||||
|
||||
/* Get buffer size from configuration. */
|
||||
switch (confPtr->size)
|
||||
{
|
||||
case bufcSize64:
|
||||
{
|
||||
tmp = BUFC_BUF_CTRL_SIZE_SIZE64;
|
||||
} break;
|
||||
|
||||
case bufcSize128:
|
||||
{
|
||||
tmp = BUFC_BUF_CTRL_SIZE_SIZE128;
|
||||
} break;
|
||||
|
||||
case bufcSize256:
|
||||
{
|
||||
tmp = BUFC_BUF_CTRL_SIZE_SIZE256;
|
||||
} break;
|
||||
|
||||
case bufcSize512:
|
||||
{
|
||||
tmp = BUFC_BUF_CTRL_SIZE_SIZE512;
|
||||
} break;
|
||||
|
||||
case bufcSize1024:
|
||||
{
|
||||
tmp = BUFC_BUF_CTRL_SIZE_SIZE1024;
|
||||
} break;
|
||||
|
||||
case bufcSize2048:
|
||||
{
|
||||
tmp = BUFC_BUF_CTRL_SIZE_SIZE2048;
|
||||
} break;
|
||||
|
||||
default:
|
||||
{
|
||||
EFM_ASSERT(0);
|
||||
return; /* Early return on error. */
|
||||
}
|
||||
/* Note: intentionally missing "break;" from the end of the branch as it
|
||||
* would be an unreachable statement due to the early return! */
|
||||
}
|
||||
|
||||
/* Set buffer size. */
|
||||
BUFC->BUF[bufId].CTRL = tmp;
|
||||
|
||||
/* Set the start address of the buffer. */
|
||||
BUFC->BUF[bufId].ADDR = (uint32_t)confPtr->addr;
|
||||
|
||||
/* Set buffer threshold and threshold mode. */
|
||||
BUFC->BUF[bufId].THRESHOLDCTRL = (uint32_t)confPtr->threshMode |
|
||||
((uint32_t)confPtr->thresh <<
|
||||
_BUFC_BUF_THRESHOLDCTRL_THRESHOLD_SHIFT);
|
||||
}
|
||||
|
||||
|
||||
/***************************************************************************//**
|
||||
* @brief
|
||||
* Sets the address of the selected buffer.
|
||||
*
|
||||
* @details
|
||||
*
|
||||
* @note
|
||||
* Internal notes: buffer address will be 32bit on the SoC.
|
||||
*
|
||||
* @param[in] bufId
|
||||
* Buffer ID, possible values: 0-3.
|
||||
*
|
||||
* @param[in] addr
|
||||
* Address to be set.
|
||||
******************************************************************************/
|
||||
void BUFC_AddrSet(uint32_t bufId, uint32_t addr)
|
||||
{
|
||||
/* Set the start address of the buffer. */
|
||||
BUFC->BUF[bufId].ADDR = (uint32_t)addr;
|
||||
}
|
||||
|
||||
|
||||
/***************************************************************************//**
|
||||
* @brief
|
||||
* Sets the size of the selected buffer.
|
||||
*
|
||||
* @details
|
||||
*
|
||||
* @param[in] bufId
|
||||
* Buffer ID, possible values: 0-3.
|
||||
*
|
||||
* @param[in] size
|
||||
* Size to be set.
|
||||
* @li bufcSize64 - Buffer size 64 bytes.
|
||||
* @li bufcSize128 - Buffer size 128 bytes.
|
||||
* @li bufcSize256 - Buffer size 256 bytes.
|
||||
* @li bufcSize512 - Buffer size 512 bytes.
|
||||
******************************************************************************/
|
||||
void BUFC_SizeSet(uint32_t bufId, BUFC_Size_TypeDef size)
|
||||
{
|
||||
/* Set buffer size. */
|
||||
BUFC->BUF[bufId].CTRL = (uint32_t)size;
|
||||
}
|
||||
|
||||
|
||||
/***************************************************************************//**
|
||||
* @brief
|
||||
* Sets the threshold options of the selected buffer.
|
||||
*
|
||||
* @details
|
||||
*
|
||||
* @param[in] bufId
|
||||
* Buffer ID, possible values: 0-3.
|
||||
*
|
||||
* @param[in] thresh
|
||||
* Threshold to be set.
|
||||
*
|
||||
* @param[in] threshMode
|
||||
* Threshold mode to be set.
|
||||
* @li false: THRESHOLDIF will be set if BYTES is larger than THRESHOLD
|
||||
* @li true: THRESHOLDIF will be set if BYTES is less than or equal to THRESHOLD
|
||||
******************************************************************************/
|
||||
void BUFC_ThresholdSet(uint32_t bufId,
|
||||
uint32_t thresh,
|
||||
BUFC_ThreshMode_TypeDef threshMode)
|
||||
{
|
||||
/* Set buffer threshold and threshold mode. */
|
||||
BUFC->BUF[bufId].THRESHOLDCTRL = (uint32_t)threshMode |
|
||||
(thresh << _BUFC_BUF_THRESHOLDCTRL_THRESHOLD_SHIFT);
|
||||
}
|
||||
|
||||
/***************************************************************************//**
|
||||
* @brief
|
||||
* Clears the selected buffer, resets the offset pointers.
|
||||
*
|
||||
* @details
|
||||
* ...
|
||||
*
|
||||
* @note
|
||||
* Internal note: CMD register
|
||||
*
|
||||
* @param[in] bufId
|
||||
* Buffer ID, possible values: 0-3.
|
||||
******************************************************************************/
|
||||
void BUFC_Clear(uint32_t bufId)
|
||||
{
|
||||
BUFC->BUF[bufId].CMD = BUFC_BUF_CMD_CLEAR;
|
||||
}
|
||||
|
||||
|
||||
/***************************************************************************//**
|
||||
* @brief
|
||||
* Prefetch read data if the buffer was written outside of the buffer
|
||||
* controller (BUFC).
|
||||
*
|
||||
* @details
|
||||
* If a write to the location indicated by the READOFFSET is performed outside
|
||||
* the BUFC, the prefetched value will not be updated. In this case use this
|
||||
* function to update the prefetched value.
|
||||
*
|
||||
* @note
|
||||
* Internal note: consider if its really necessary as an API function!
|
||||
*
|
||||
* @param[in] bufId
|
||||
* Buffer ID, possible values: 0-3.
|
||||
******************************************************************************/
|
||||
void BUFC_Prefetch(uint32_t bufId)
|
||||
{
|
||||
BUFC->BUF[bufId].CMD = BUFC_BUF_CMD_PREFETCH;
|
||||
}
|
||||
|
||||
#if defined(EFR4DFULL)
|
||||
/***************************************************************************//**
|
||||
* @brief
|
||||
* Update the write start value to the value of the write offset.
|
||||
*
|
||||
* @details
|
||||
* Use this function to set the write start value (WRITESTART) to the value of
|
||||
* the write offset (WRITEOFFSET). This is normally done before receiving a
|
||||
* new frame. The write start value is used to store the initial value of the
|
||||
* write offset prior to receiving a frame. This value is basically used to
|
||||
* remove a partly received frame which is to be removed.
|
||||
*
|
||||
* @param[in] bufId
|
||||
* Buffer ID, possible values: 0-3.
|
||||
******************************************************************************/
|
||||
void BUFC_WriteStartUpdate(uint32_t bufId)
|
||||
{
|
||||
BUFC->BUF[bufId].CMD = BUFC_BUF_CMD_UPDATEWRITESTART;
|
||||
}
|
||||
|
||||
|
||||
/***************************************************************************//**
|
||||
* @brief
|
||||
* Restore the write offset value to the value of the write start.
|
||||
*
|
||||
* @details
|
||||
* Use this function to set the write offset value (WRITEOFFSET) to the value
|
||||
* of the write start (WRITESTART). This is normally done before discarding a
|
||||
* partly received frame.
|
||||
*
|
||||
* @param[in] bufId
|
||||
* Buffer ID, possible values: 0-3.
|
||||
******************************************************************************/
|
||||
void BUFC_WriteOffsetRestore(uint32_t bufId)
|
||||
{
|
||||
BUFC->BUF[bufId].CMD = BUFC_BUF_CMD_RESTOREWRITEOFFSET;
|
||||
}
|
||||
#endif
|
||||
|
||||
/***************************************************************************//**
|
||||
* @brief
|
||||
* Gets the current number of bytes in the selected buffer.
|
||||
*
|
||||
* @details
|
||||
* BYTES = (WRITEOFFSET - READOFFSET)modulo(SIZE)
|
||||
*
|
||||
* @note
|
||||
* Internal note: BUFn_STATUS
|
||||
*
|
||||
* @param[in] bufId
|
||||
* Buffer ID, possible values: 0-3.
|
||||
*
|
||||
* @return
|
||||
* Number of bytes in the selected buffer.
|
||||
******************************************************************************/
|
||||
uint32_t BUFC_NumOfBytesGet(uint32_t bufId)
|
||||
{
|
||||
return (BUFC->BUF[bufId].STATUS & _BUFC_BUF_STATUS_BYTES_MASK);
|
||||
}
|
||||
|
||||
|
||||
/***************************************************************************//**
|
||||
* @brief
|
||||
* Gets the current WriteOffset value of the selected buffer.
|
||||
*
|
||||
* @note
|
||||
* Internal note: consider int16_t instead of int
|
||||
*
|
||||
* @param[in] bufId
|
||||
* Buffer ID, possible values: 0-3.
|
||||
*
|
||||
* @return
|
||||
* Current WriteOffset value of the selected buffer.
|
||||
******************************************************************************/
|
||||
int32_t BUFC_WriteOffsetGet(uint32_t bufId)
|
||||
{
|
||||
/* Casting 2's complement offset value to int32_t. */
|
||||
return (int32_t)BUFC->BUF[bufId].WRITEOFFSET;
|
||||
}
|
||||
|
||||
|
||||
/***************************************************************************//**
|
||||
* @brief
|
||||
* Gets the current ReadOffset value of the selected buffer.
|
||||
*
|
||||
* @note
|
||||
* Internal note: consider int16_t instead of int
|
||||
*
|
||||
* @param[in] bufId
|
||||
* Buffer ID, possible values: 0-3.
|
||||
*
|
||||
* @return
|
||||
* Current ReadOffset value of the selected buffer.
|
||||
******************************************************************************/
|
||||
int32_t BUFC_ReadOffsetGet(uint32_t bufId)
|
||||
{
|
||||
/* Casting 2's complement offset value to int32_t. */
|
||||
return (int32_t)BUFC->BUF[bufId].READOFFSET;
|
||||
}
|
||||
|
||||
|
||||
/** @} (end addtogroup BUFC) */
|
||||
/** @} (end addtogroup EM_Library) */
|
||||
|
||||
#endif /* defined(BUFC_COUNT) && (BUFC_COUNT > 0) */
|
|
@ -0,0 +1,403 @@
|
|||
/*
|
||||
* Buffer Controller (BUFC) interface definition.
|
||||
*
|
||||
* Copyright (C) 2016 Silicon Labs, http://www.silabs.com
|
||||
* 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 __EM_BUFC_H
|
||||
#define __EM_BUFC_H
|
||||
|
||||
#include "em_device.h"
|
||||
|
||||
#if defined(BUFC_COUNT) && (BUFC_COUNT > 0)
|
||||
|
||||
#include <stdint.h>
|
||||
#include <stdbool.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/***************************************************************************//**
|
||||
* @addtogroup EM_Library
|
||||
* @{
|
||||
******************************************************************************/
|
||||
|
||||
/***************************************************************************//**
|
||||
* @addtogroup BUFC
|
||||
* @{
|
||||
******************************************************************************/
|
||||
|
||||
/*******************************************************************************
|
||||
******************************** ENUMS ************************************
|
||||
******************************************************************************/
|
||||
|
||||
/** Buffer size options. */
|
||||
typedef enum
|
||||
{
|
||||
/** Buffer size of 64 bytes. */
|
||||
bufcSize64 = 64,
|
||||
|
||||
/** Buffer size of 128 bytes. */
|
||||
bufcSize128 = 128,
|
||||
|
||||
/** Buffer size of 256 bytes. */
|
||||
bufcSize256 = 256,
|
||||
|
||||
/** Buffer size of 512 bytes. */
|
||||
bufcSize512 = 512,
|
||||
|
||||
bufcSize1024 = 1024,
|
||||
bufcSize2048 = 2048
|
||||
} BUFC_Size_TypeDef;
|
||||
|
||||
|
||||
/** Buffer threshold mode options. */
|
||||
typedef enum
|
||||
{
|
||||
/** Set threshold interrupt flag (BUFn_IF_THRESHOLDIF) if the number of bytes
|
||||
* in the buffer is larger than threshold value. */
|
||||
bufcThreshModeLarger = BUFC_BUF_THRESHOLDCTRL_THRESHOLDMODE_LARGER,
|
||||
|
||||
/** Set threshold interrupt flag (BUFn_IF_THRESHOLDIF) if the number of bytes
|
||||
* in the buffer is less or equal than threshold value. */
|
||||
bufcThreshModeLessOrEq = BUFC_BUF_THRESHOLDCTRL_THRESHOLDMODE_LESSOREQUAL
|
||||
} BUFC_ThreshMode_TypeDef;
|
||||
|
||||
|
||||
/*******************************************************************************
|
||||
******************************* STRUCTS ***********************************
|
||||
******************************************************************************/
|
||||
|
||||
/** Buffer configuration structure. */
|
||||
typedef struct
|
||||
{
|
||||
/** Buffer size.
|
||||
* Note: make sure the memory range is reserved for the buffer in RAM! */
|
||||
BUFC_Size_TypeDef size;
|
||||
|
||||
/** Buffer address.
|
||||
* Note: make sure the memory range is reserved for the buffer in RAM! */
|
||||
uint32_t addr;
|
||||
|
||||
/** Buffer threshold (number of bytes). This value is used to trigger the
|
||||
* threshold interrupt flag (BUFn_IF_THRESHOLDIF), the compare mode is
|
||||
* defined by #threshMode. */
|
||||
uint32_t thresh;
|
||||
|
||||
/** Buffer threshold mode. Defines how to compare the threshold value with the
|
||||
* number of bytes in the buffer.
|
||||
* number of bytes = (WRITEOFFSET - READOFFSET) mod (buffer size) */
|
||||
BUFC_ThreshMode_TypeDef threshMode;
|
||||
} BUFC_BufferConf_TypeDef;
|
||||
|
||||
/** Default configuration for BUFC_BufferConf_TypeDef structure. */
|
||||
#define BUFC_BUFFER_CONF_DEFAULT \
|
||||
{ \
|
||||
bufcSize512, /* Buffer size is 512 bytes. */ \
|
||||
0x0000U, /* Buffer start address is 0x00000. */ \
|
||||
256U, /* Threshold set to 256 bytes. */ \
|
||||
bufcThreshModeLarger /* Threshold mode set to "larger". */ \
|
||||
}
|
||||
|
||||
|
||||
/** Buffer controller (BUFC) initialization structure. */
|
||||
typedef struct
|
||||
{
|
||||
/** Configuration structures for all buffers instances. */
|
||||
BUFC_BufferConf_TypeDef buffer[4U];
|
||||
} BUFC_Init_TypeDef;
|
||||
|
||||
/** Default configuration for BUFC_Init_TypeDef structure. */
|
||||
#define BUFC_INIT_DEFAULT \
|
||||
{ \
|
||||
{ \
|
||||
BUFC_BUFFER_CONF_DEFAULT, /* Buffer 0 default configuration. */ \
|
||||
BUFC_BUFFER_CONF_DEFAULT, /* Buffer 1 default configuration. */ \
|
||||
BUFC_BUFFER_CONF_DEFAULT, /* Buffer 2 default configuration. */ \
|
||||
BUFC_BUFFER_CONF_DEFAULT /* Buffer 3 default configuration. */ \
|
||||
} \
|
||||
}
|
||||
|
||||
|
||||
/*******************************************************************************
|
||||
****************************** PROTOTYPES *********************************
|
||||
******************************************************************************/
|
||||
|
||||
void BUFC_Init(BUFC_Init_TypeDef const *init);
|
||||
void BUFC_Reset(void);
|
||||
void BUFC_BufferConfig(uint32_t bufId,
|
||||
BUFC_BufferConf_TypeDef const *confPtr);
|
||||
|
||||
/* Note:
|
||||
* Consider if these should be really offered as API functions as reconfiguring
|
||||
* only one buffer can mess up the others! */
|
||||
void BUFC_AddrSet(uint32_t bufId, uint32_t addr);
|
||||
void BUFC_SizeSet(uint32_t bufId, BUFC_Size_TypeDef size);
|
||||
void BUFC_ThresholdSet(uint32_t bufId,
|
||||
uint32_t thresh,
|
||||
BUFC_ThreshMode_TypeDef threshMode);
|
||||
|
||||
void BUFC_Clear(uint32_t bufId);
|
||||
void BUFC_Prefetch(uint32_t bufId);
|
||||
|
||||
#if defined(EFR4DFULL)
|
||||
void BUFC_WriteStartUpdate(uint32_t bufId);
|
||||
void BUFC_WriteOffsetRestore(uint32_t bufId);
|
||||
#endif
|
||||
|
||||
uint32_t BUFC_NumOfBytesGet(uint32_t bufId);
|
||||
int32_t BUFC_WriteOffsetGet(uint32_t bufId);
|
||||
int32_t BUFC_ReadOffsetGet(uint32_t bufId);
|
||||
|
||||
static __INLINE void BUFC_XORDataWrite(uint32_t bufId, uint8_t data);
|
||||
static __INLINE void BUFC_DataWrite(uint32_t bufId, uint8_t data);
|
||||
static __INLINE uint8_t BUFC_DataRead(uint32_t bufId);
|
||||
|
||||
static __INLINE void BUFC_IntEnable(uint32_t flags);
|
||||
/*, INT_IntLocation_TypeDef loc) */
|
||||
static __INLINE void BUFC_IntDisable(uint32_t flags);
|
||||
/*, INT_IntLocation_TypeDef loc) */
|
||||
|
||||
static __INLINE void BUFC_IntClear(uint32_t flags);
|
||||
static __INLINE void BUFC_IntSet(uint32_t flags);
|
||||
|
||||
static __INLINE uint32_t BUFC_IntGet(void); /* INT_IntLocation_TypeDef loc); */
|
||||
static __INLINE uint32_t BUFC_IntGetEnabled(void); /* INT_IntLocation_TypeDef loc); */
|
||||
|
||||
/***************************************************************************//**
|
||||
* @brief
|
||||
* Writes data to the selected buffer with XOR.
|
||||
*
|
||||
* @details
|
||||
* Using this function, the data is written to the buffer through
|
||||
* BUFn_XWRITE resulting in a XOR write that means the data to be written
|
||||
* XOR'ed with the data already in the buffer.
|
||||
* When writing data to the buffer, the WRITEOFFSET is being incremented by 1
|
||||
* for each write. Refer to the Buffer Controller Chapter in EFR Reference
|
||||
* Manual for more details.
|
||||
*
|
||||
* @note
|
||||
* Internal note: 32bit value on SoC.
|
||||
* +DataWriteOffsetGet()? - (would save one switch or if)
|
||||
*
|
||||
* @param[in] bufId
|
||||
* Buffer ID, possible values: 0-3.
|
||||
*
|
||||
* @param[in] data
|
||||
* Data to write to the selected buffer.
|
||||
******************************************************************************/
|
||||
static __INLINE void BUFC_XORDataWrite(uint32_t bufId, uint8_t data)
|
||||
{
|
||||
BUFC->BUF[bufId].XWRITE = (uint8_t)data;
|
||||
}
|
||||
|
||||
/***************************************************************************//**
|
||||
* @brief
|
||||
* Writes data to the selected buffer.
|
||||
*
|
||||
* @details
|
||||
* When writing data to the buffer, the WRITEOFFSET is being incremented by 1
|
||||
* for each write. Refer to the Buffer Controller Chapter in EFR Reference
|
||||
* Manual for more details.
|
||||
*
|
||||
* @note
|
||||
* Internal note:
|
||||
* +DataWriteOffsetGet()? - (would save one switch or if)
|
||||
*
|
||||
* @param[in] bufId
|
||||
* Buffer ID, possible values: 0-3.
|
||||
*
|
||||
* @param[in] data
|
||||
* Data to write to the selected buffer.
|
||||
******************************************************************************/
|
||||
static __INLINE void BUFC_DataWrite(uint32_t bufId, uint8_t data)
|
||||
{
|
||||
BUFC->BUF[bufId].WRITEDATA = (uint8_t)data;
|
||||
}
|
||||
|
||||
|
||||
/***************************************************************************//**
|
||||
* @brief
|
||||
* Reads from the selected buffer.
|
||||
*
|
||||
* @note
|
||||
* ...
|
||||
*
|
||||
* @param[in] bufId
|
||||
* Buffer ID, possible values: 0-3.
|
||||
*
|
||||
* @return
|
||||
*
|
||||
******************************************************************************/
|
||||
static __INLINE uint8_t BUFC_DataRead(uint32_t bufId)
|
||||
{
|
||||
return (uint8_t)BUFC->BUF[bufId].READDATA;
|
||||
}
|
||||
|
||||
/***************************************************************************//**
|
||||
* @brief
|
||||
* Enable one or more BUFC interrupts.
|
||||
*
|
||||
* @param[in] flags
|
||||
* BUFC interrupt sources to enable. Use a set of interrupt flags OR-ed
|
||||
* together to enable multiple interrupt sources of the BUFC module
|
||||
* (IRH_BUFC_nIEN_nnn).
|
||||
* Internal note: consider different scenarios, host vs M3, asserts
|
||||
*
|
||||
* @param[in] loc
|
||||
* Interrupt flag location, possible values:
|
||||
* (list of enum values of INT_IntLocation_TypeDef)
|
||||
* (list of enum values of INT_IntLocation_TypeDef)
|
||||
******************************************************************************/
|
||||
static __INLINE void BUFC_IntEnable(uint32_t flags)
|
||||
/*, INT_IntLocation_TypeDef loc) */
|
||||
{
|
||||
BUFC->IEN |= flags;
|
||||
}
|
||||
|
||||
|
||||
/***************************************************************************//**
|
||||
* @brief
|
||||
* Disable one or more BUFC interrupts.
|
||||
*
|
||||
* @param[in] flags
|
||||
* BUFC interrupt sources to disable. Use a set of interrupt flags OR-ed
|
||||
* together to disable multiple interrupt sources of the BUFC module
|
||||
* (IRH_BUFC_nIEN_nnn).
|
||||
* Internal note: consider different scenarios, host vs M3, asserts
|
||||
*
|
||||
* @param[in] loc
|
||||
* Interrupt flag location, possible values:
|
||||
* (list of enum values of INT_IntLocation_TypeDef)
|
||||
* (list of enum values of INT_IntLocation_TypeDef)
|
||||
******************************************************************************/
|
||||
static __INLINE void BUFC_IntDisable(uint32_t flags)
|
||||
/*, INT_IntLocation_TypeDef loc) */
|
||||
{
|
||||
BUFC->IEN &= ~(flags);
|
||||
}
|
||||
|
||||
|
||||
/***************************************************************************//**
|
||||
* @brief
|
||||
* Clear one or more pending BUFC interrupts.
|
||||
*
|
||||
* @param[in] flags
|
||||
* BUFC interrupt sources to clear. Use a set of interrupt flags OR-ed together
|
||||
* to clear multiple interrupt sources of the BUFC module (IRH_BUFC_FLAGCLEAR_nnn).
|
||||
******************************************************************************/
|
||||
static __INLINE void BUFC_IntClear(uint32_t flags)
|
||||
{
|
||||
BUFC->IFC = flags;
|
||||
}
|
||||
|
||||
|
||||
/***************************************************************************//**
|
||||
* @brief
|
||||
* Set one or more pending BUFC interrupts from SW.
|
||||
*
|
||||
* @param[in] flags
|
||||
* BUFC interrupt sources to set to pending. Use a set of interrupt
|
||||
* flags OR-ed together to set multiple interrupt sources of the BUFC module
|
||||
* (IRH_BUFC_FLAGSET_nnn).
|
||||
******************************************************************************/
|
||||
static __INLINE void BUFC_IntSet(uint32_t flags)
|
||||
{
|
||||
BUFC->IFC = flags;
|
||||
}
|
||||
|
||||
|
||||
/***************************************************************************//**
|
||||
* @brief
|
||||
* Get pending BUFC interrupt flags.
|
||||
*
|
||||
* @note
|
||||
* The effect of reading the interrupt flags is dependent on the configuration
|
||||
* of the Interrupt Handler module (IRH) as reading the interrupt flags from
|
||||
* an external host can clear the interrupt if the EIREADCLEAR bit is set
|
||||
* in IRH_CTRL. Refer to EFR Reference Manual Chapter 13 and _irh.c for
|
||||
* more details.
|
||||
* Internal note: consider different scenarios, host vs M3, asserts
|
||||
*
|
||||
* @param[in] loc
|
||||
* Interrupt flag location, possible values:
|
||||
* (list of enum values of INT_IntLocation_TypeDef)
|
||||
* (list of enum values of INT_IntLocation_TypeDef)
|
||||
* (both should not be supported)
|
||||
*
|
||||
* @return
|
||||
* Pending BUFC interrupt sources. The OR combination of valid interrupt flags
|
||||
* of the BUFC module (IRH_BUFC_FLAG_nnn).
|
||||
******************************************************************************/
|
||||
static __INLINE uint32_t BUFC_IntGet(void) /* INT_IntLocation_TypeDef loc) */
|
||||
{
|
||||
return BUFC->IF;
|
||||
}
|
||||
|
||||
|
||||
/***************************************************************************//**
|
||||
* @brief
|
||||
* Get enabled and pending BUFC interrupt flags.
|
||||
*
|
||||
* @details
|
||||
* Useful for handling more interrupt sources in the same interrupt handler.
|
||||
*
|
||||
* @note
|
||||
* The effect of reading the interrupt flags is dependent on the configuration
|
||||
* of the Interrupt Handler module (IRH) as reading the interrupt flags from
|
||||
* an external host can clear the interrupt if the EIREADCLEAR bit is set
|
||||
* in IRH_CTRL. Refer to EFR Reference Manual Chapter 13 and _irh.c for
|
||||
* more details.
|
||||
* Internal note: consider different scenarios, host vs M3, asserts
|
||||
*
|
||||
* @param[in] loc
|
||||
* Interrupt flag location, possible values:
|
||||
* (list of enum values of INT_IntLocation_TypeDef)
|
||||
* (for external its the same as the simple xxxIntGet() as the external flag register only shows the enabled flags)
|
||||
* (both should not be supported)
|
||||
*
|
||||
* @return
|
||||
* Pending BUFC interrupt sources.
|
||||
* The return value is the bitwise AND combination of
|
||||
* - the OR combination of enabled interrupt sources in IRH_BUFC_xIEN register
|
||||
* (IRH_BUFC_nIEN_nnn) and
|
||||
* - the OR combination of valid interrupt flags of the BUFC module
|
||||
* (IRH_BUFC_FLAG_nnn).
|
||||
******************************************************************************/
|
||||
static __INLINE uint32_t BUFC_IntGetEnabled(void) /* INT_IntLocation_TypeDef loc) */
|
||||
{
|
||||
uint32_t tmp = 0U;
|
||||
|
||||
|
||||
/* Store BUFC->IEN in temporary variable in order to define explicit order
|
||||
* of volatile accesses. */
|
||||
tmp = BUFC->IEN;
|
||||
|
||||
/* Bitwise AND of pending and enabled interrupt flags. */
|
||||
return BUFC->IF & tmp;
|
||||
}
|
||||
|
||||
|
||||
/** @} (end addtogroup BUFC) */
|
||||
/** @} (end addtogroup EM_Library) */
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* defined(BUFC_COUNT) && (BUFC_COUNT > 0) */
|
||||
|
||||
#endif /* __EM_BUFC_H */
|
|
@ -0,0 +1,594 @@
|
|||
/*
|
||||
* FIPS-197 compliant AES implementation
|
||||
*
|
||||
* Copyright (C) 2015-2016 Silicon Labs, http://www.silabs.com
|
||||
* 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.
|
||||
*/
|
||||
|
||||
/*
|
||||
* This file includes alternative plugin implementations of various
|
||||
* functions in aes.c using the CRYPTO hardware accelerator incorporated
|
||||
* in MCU devices from Silicon Laboratories.
|
||||
*/
|
||||
|
||||
/*
|
||||
* The AES block cipher was designed by Vincent Rijmen and Joan Daemen.
|
||||
*
|
||||
* http://csrc.nist.gov/encryption/aes/rijndael/Rijndael.pdf
|
||||
* http://csrc.nist.gov/publications/fips/fips197/fips-197.pdf
|
||||
*/
|
||||
|
||||
#if !defined(MBEDTLS_CONFIG_FILE)
|
||||
#include "mbedtls/config.h"
|
||||
#else
|
||||
#include MBEDTLS_CONFIG_FILE
|
||||
#endif
|
||||
|
||||
#if defined(MBEDTLS_AES_C)
|
||||
|
||||
#if defined(MBEDTLS_AES_ALT)
|
||||
|
||||
#if !defined( MBEDTLS_SLCL_PLUGINS )
|
||||
|
||||
#include "em_device.h"
|
||||
|
||||
#if defined(CRYPTO_COUNT) && (CRYPTO_COUNT > 0)
|
||||
|
||||
#include "cryptodrv_internal.h"
|
||||
#include "em_crypto.h"
|
||||
|
||||
#include "mbedtls/aes.h"
|
||||
|
||||
#include <string.h>
|
||||
|
||||
#define CRYPTO_AES_BLOCKSIZE ( 16 )
|
||||
|
||||
#define MBEDTLS_RETVAL_CHK(f) do { if( ( ret = f ) != 0 ) goto cleanup; } while( 0 )
|
||||
|
||||
#define CRYPTO_CLOCK_ENABLE CMU->HFBUSCLKEN0 |= CMU_HFBUSCLKEN0_CRYPTO;
|
||||
|
||||
#define CRYPTO_CLOCK_DISABLE CMU->HFBUSCLKEN0 &= ~CMU_HFBUSCLKEN0_CRYPTO;
|
||||
|
||||
/* 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;
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief Internal function for setting encryption key in CRYPTO.
|
||||
*
|
||||
* \param ctx AES context including key
|
||||
*/
|
||||
static inline int crypto_setkey_enc( mbedtls_aes_context *ctx )
|
||||
{
|
||||
uint32_t* _key = (uint32_t*) ctx->key;
|
||||
|
||||
switch( ctx->keybits )
|
||||
{
|
||||
case 128:
|
||||
/* Set AES-128 mode */
|
||||
BUS_RegMaskedClear(&CRYPTO->CTRL, 1<<_CRYPTO_CTRL_AES_SHIFT);
|
||||
/* Load key in KEYBUF register */
|
||||
CRYPTO->KEYBUF = _key[0];
|
||||
CRYPTO->KEYBUF = _key[1];
|
||||
CRYPTO->KEYBUF = _key[2];
|
||||
CRYPTO->KEYBUF = _key[3];
|
||||
return( 0 );
|
||||
case 256:
|
||||
/* Set AES-256 mode */
|
||||
BUS_RegMaskedSet(&CRYPTO->CTRL, 1<<_CRYPTO_CTRL_AES_SHIFT);
|
||||
/* Load key in KEYBUF register (= DDATA4) */
|
||||
CRYPTO_DDataWrite( &CRYPTO->DDATA4, _key );
|
||||
return( 0 );
|
||||
default:
|
||||
/* Unsupported key size */
|
||||
return( MBEDTLS_ERR_AES_INVALID_KEY_LENGTH );
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief Internal function for setting decryption key in CRYPTO.
|
||||
*
|
||||
* \param ctx AES context including key
|
||||
*/
|
||||
static int crypto_setkey_dec( mbedtls_aes_context *ctx )
|
||||
{
|
||||
uint32_t* _key = (uint32_t*) ctx->key;
|
||||
|
||||
switch( ctx->keybits )
|
||||
{
|
||||
case 128:
|
||||
/* Set AES-128 mode */
|
||||
BUS_RegMaskedClear(&CRYPTO->CTRL, 1<<_CRYPTO_CTRL_AES_SHIFT);
|
||||
/* Load key in KEYBUF register */
|
||||
CRYPTO->KEYBUF = _key[0];
|
||||
CRYPTO->KEYBUF = _key[1];
|
||||
CRYPTO->KEYBUF = _key[2];
|
||||
CRYPTO->KEYBUF = _key[3];
|
||||
/* Do dummy encryption to generate decrypt key, and move result to
|
||||
KEYBUF = DDATA4. */
|
||||
CRYPTO_EXECUTE_2(CRYPTO,
|
||||
CRYPTO_CMD_INSTR_AESENC,
|
||||
CRYPTO_CMD_INSTR_DDATA1TODDATA4);
|
||||
return( 0 );
|
||||
case 256:
|
||||
/* Set AES-256 mode */
|
||||
BUS_RegMaskedSet(&CRYPTO->CTRL, 1<<_CRYPTO_CTRL_AES_SHIFT);
|
||||
/* Load key in KEYBUF register (= DDATA4) */
|
||||
CRYPTO_DDataWrite( &CRYPTO->DDATA4, _key );
|
||||
/* Do dummy encryption to generate decrypt key, and move result to
|
||||
KEYBUF = DDATA4. */
|
||||
CRYPTO_EXECUTE_2(CRYPTO,
|
||||
CRYPTO_CMD_INSTR_AESENC,
|
||||
CRYPTO_CMD_INSTR_DDATA1TODDATA4);
|
||||
return( 0 );
|
||||
default:
|
||||
/* Unsupported key size */
|
||||
return( MBEDTLS_ERR_AES_INVALID_KEY_LENGTH );
|
||||
}
|
||||
}
|
||||
|
||||
#if defined(MBEDTLS_CIPHER_MODE_CBC) || \
|
||||
defined(MBEDTLS_CIPHER_MODE_CFB) || \
|
||||
defined(MBEDTLS_CIPHER_MODE_CTR)
|
||||
/**
|
||||
* \brief Process multiple AES blocks using current CRYPTO
|
||||
* instruction sequence.
|
||||
*
|
||||
* \param len Length of input buffer (in bytes)
|
||||
* \param inReg Which CRYPTO register that expects input block
|
||||
* \param in Input buffer
|
||||
* \param outReg Which CRYPTO register where result ends up
|
||||
* \param out Output buffer where result should be written
|
||||
* \param iv If 'iv' is non-NULL, copy input to iv for
|
||||
* subsequent iterative calls.
|
||||
*/
|
||||
static void crypto_aes_processloop(uint32_t len,
|
||||
CRYPTO_DataReg_TypeDef inReg,
|
||||
const uint8_t* in,
|
||||
CRYPTO_DataReg_TypeDef outReg,
|
||||
uint8_t* out,
|
||||
uint8_t* iv)
|
||||
{
|
||||
len /= CRYPTO_AES_BLOCKSIZE;
|
||||
CRYPTO->SEQCTRL = 16 << _CRYPTO_SEQCTRL_LENGTHA_SHIFT;
|
||||
|
||||
while (len--)
|
||||
{
|
||||
/* Save initial vector for last block */
|
||||
if (iv && 0==len)
|
||||
memcpy(iv, in, 16);
|
||||
|
||||
/* Load data and trigger encryption */
|
||||
CRYPTODRV_DataWriteUnaligned(inReg, in);
|
||||
|
||||
CRYPTO->CMD = CRYPTO_CMD_SEQSTART;
|
||||
|
||||
/* Save encrypted/decrypted data */
|
||||
CRYPTODRV_DataReadUnaligned(outReg, out);
|
||||
|
||||
out += 16;
|
||||
in += 16;
|
||||
}
|
||||
}
|
||||
#endif /* #if defined(MBEDTLS_CIPHER_MODE_CBC) || \
|
||||
defined(MBEDTLS_CIPHER_MODE_CFB) || \
|
||||
defined(MBEDTLS_CIPHER_MODE_CTR) */
|
||||
|
||||
/*
|
||||
* Initialize AES context
|
||||
*/
|
||||
void mbedtls_aes_init( mbedtls_aes_context *ctx )
|
||||
{
|
||||
memset( ctx, 0, sizeof( mbedtls_aes_context ) );
|
||||
}
|
||||
|
||||
/*
|
||||
* Clear AES context
|
||||
*/
|
||||
void mbedtls_aes_free( mbedtls_aes_context *ctx )
|
||||
{
|
||||
if( ctx == NULL )
|
||||
return;
|
||||
|
||||
mbedtls_zeroize( ctx, sizeof( mbedtls_aes_context ) );
|
||||
}
|
||||
|
||||
/*
|
||||
* AES key schedule (encryption)
|
||||
*/
|
||||
int mbedtls_aes_setkey_enc( mbedtls_aes_context *ctx, const unsigned char *key,
|
||||
unsigned int keybits )
|
||||
{
|
||||
if ( ( 128 != keybits ) && ( 256 != keybits ) )
|
||||
/* Unsupported key size */
|
||||
return( MBEDTLS_ERR_AES_INVALID_KEY_LENGTH );
|
||||
|
||||
ctx->keybits = keybits;
|
||||
memcpy(ctx->key, key, keybits/8);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* AES key schedule (decryption)
|
||||
*/
|
||||
int mbedtls_aes_setkey_dec( mbedtls_aes_context *ctx, const unsigned char *key,
|
||||
unsigned int keybits )
|
||||
{
|
||||
if ( ( 128 != keybits ) && ( 256 != keybits ) )
|
||||
/* Unsupported key size */
|
||||
return( MBEDTLS_ERR_AES_INVALID_KEY_LENGTH );
|
||||
|
||||
ctx->keybits = keybits;
|
||||
memcpy(ctx->key, key, keybits/8);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* AES-ECB block encryption/decryption
|
||||
*/
|
||||
int mbedtls_aes_crypt_ecb( mbedtls_aes_context *ctx,
|
||||
int mode,
|
||||
const unsigned char input[16],
|
||||
unsigned char output[16] )
|
||||
{
|
||||
int ret = 0;
|
||||
|
||||
/* Initialize CRYPTO */
|
||||
CRYPTO_CLOCK_ENABLE;
|
||||
CRYPTO->CTRL = 0;
|
||||
CRYPTO->WAC = 0;
|
||||
CRYPTO->SEQCTRL = 0;
|
||||
CRYPTO->SEQCTRLB = 0;
|
||||
|
||||
if( mode == MBEDTLS_AES_ENCRYPT )
|
||||
{
|
||||
/* Load plaintext */
|
||||
CRYPTODRV_DataWriteUnaligned( &CRYPTO->DATA0, input );
|
||||
|
||||
/* Set encryption key */
|
||||
MBEDTLS_RETVAL_CHK( crypto_setkey_enc (ctx) );
|
||||
|
||||
/* Trigger encryption */
|
||||
CRYPTO->CMD = CRYPTO_CMD_INSTR_AESENC;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Set/calculate decryption key */
|
||||
MBEDTLS_RETVAL_CHK( crypto_setkey_dec (ctx) );
|
||||
|
||||
/* Load ciphertext. Must be done after decryption key calculation
|
||||
which is destructive for value in DATA0. */
|
||||
CRYPTODRV_DataWriteUnaligned( &CRYPTO->DATA0, input );
|
||||
|
||||
/* Trigger decryption */
|
||||
CRYPTO->CMD = CRYPTO_CMD_INSTR_AESDEC;
|
||||
}
|
||||
|
||||
/* Save encrypted/decrypted data */
|
||||
CRYPTODRV_DataReadUnaligned( &CRYPTO->DATA0, output);
|
||||
|
||||
cleanup:
|
||||
|
||||
CRYPTO_CLOCK_DISABLE;
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
#if defined(MBEDTLS_CIPHER_MODE_CBC)
|
||||
|
||||
/*
|
||||
* AES-CBC buffer encryption/decryption
|
||||
*/
|
||||
int mbedtls_aes_crypt_cbc( mbedtls_aes_context *ctx,
|
||||
int mode,
|
||||
size_t length,
|
||||
unsigned char iv[16],
|
||||
const unsigned char *input,
|
||||
unsigned char *output )
|
||||
{
|
||||
int ret;
|
||||
|
||||
/* Input length must be a multiple of 16 bytes which is the AES block
|
||||
length. */
|
||||
if( length & 0xf )
|
||||
return( MBEDTLS_ERR_AES_INVALID_INPUT_LENGTH );
|
||||
|
||||
CRYPTO_CLOCK_ENABLE;
|
||||
CRYPTO->CTRL = 0;
|
||||
CRYPTO->WAC = 0;
|
||||
CRYPTO->SEQCTRL = 0;
|
||||
CRYPTO->SEQCTRLB = 0;
|
||||
|
||||
if( mode == MBEDTLS_AES_ENCRYPT )
|
||||
{
|
||||
/* Set encryption key */
|
||||
MBEDTLS_RETVAL_CHK( crypto_setkey_enc (ctx) );
|
||||
|
||||
CRYPTODRV_DataWriteUnaligned( &CRYPTO->DATA0, iv );
|
||||
|
||||
CRYPTO->SEQ0 =
|
||||
CRYPTO_CMD_INSTR_DATA1TODATA0XOR << _CRYPTO_SEQ0_INSTR0_SHIFT |
|
||||
CRYPTO_CMD_INSTR_AESENC << _CRYPTO_SEQ0_INSTR1_SHIFT;
|
||||
|
||||
crypto_aes_processloop( length,
|
||||
&CRYPTO->DATA1, input,
|
||||
&CRYPTO->DATA0, output,
|
||||
0 );
|
||||
/* Copy last output block to iv */
|
||||
memcpy (iv, &output[length-16], 16);
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Set key */
|
||||
MBEDTLS_RETVAL_CHK( crypto_setkey_dec (ctx) );
|
||||
|
||||
CRYPTODRV_DataWriteUnaligned( &CRYPTO->DATA2, iv );
|
||||
|
||||
CRYPTO->SEQ0 =
|
||||
CRYPTO_CMD_INSTR_DATA1TODATA0 << _CRYPTO_SEQ0_INSTR0_SHIFT |
|
||||
CRYPTO_CMD_INSTR_AESDEC << _CRYPTO_SEQ0_INSTR1_SHIFT |
|
||||
CRYPTO_CMD_INSTR_DATA2TODATA0XOR << _CRYPTO_SEQ0_INSTR2_SHIFT |
|
||||
CRYPTO_CMD_INSTR_DATA1TODATA2 << _CRYPTO_SEQ0_INSTR3_SHIFT;
|
||||
|
||||
CRYPTO->SEQ1 = 0;
|
||||
|
||||
/* The following call is equivalent to the last call in the
|
||||
'if( mode == MBEDTLS_AES_ENCRYPT )' branch. However moving this
|
||||
call outside the conditional scope results in slightly poorer
|
||||
performance for some compiler optimizations. */
|
||||
crypto_aes_processloop( length,
|
||||
&CRYPTO->DATA1, input,
|
||||
&CRYPTO->DATA0, output,
|
||||
iv );
|
||||
}
|
||||
|
||||
cleanup:
|
||||
|
||||
CRYPTO_CLOCK_DISABLE;
|
||||
|
||||
return( ret );
|
||||
}
|
||||
#endif /* MBEDTLS_CIPHER_MODE_CBC */
|
||||
|
||||
#if defined(MBEDTLS_CIPHER_MODE_CFB)
|
||||
/*
|
||||
* AES-CFB128 buffer encryption/decryption
|
||||
*/
|
||||
int mbedtls_aes_crypt_cfb128( mbedtls_aes_context *ctx,
|
||||
int mode,
|
||||
size_t length,
|
||||
size_t *iv_off,
|
||||
unsigned char iv[16],
|
||||
const unsigned char *input,
|
||||
unsigned char *output )
|
||||
{
|
||||
if ( (iv_off && *iv_off) || ( length % 16 ) )
|
||||
{
|
||||
int c;
|
||||
size_t n = *iv_off;
|
||||
|
||||
if( mode == MBEDTLS_AES_DECRYPT )
|
||||
{
|
||||
while( length-- )
|
||||
{
|
||||
if( n == 0 )
|
||||
mbedtls_aes_crypt_ecb( ctx, MBEDTLS_AES_ENCRYPT, iv, iv );
|
||||
|
||||
c = *input++;
|
||||
*output++ = (unsigned char)( c ^ iv[n] );
|
||||
iv[n] = (unsigned char) c;
|
||||
|
||||
n = ( n + 1 ) & 0x0F;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
while( length-- )
|
||||
{
|
||||
if( n == 0 )
|
||||
mbedtls_aes_crypt_ecb( ctx, MBEDTLS_AES_ENCRYPT, iv, iv );
|
||||
|
||||
iv[n] = *output++ = (unsigned char)( iv[n] ^ *input++ );
|
||||
|
||||
n = ( n + 1 ) & 0x0F;
|
||||
}
|
||||
}
|
||||
|
||||
*iv_off = n;
|
||||
|
||||
return( 0 );
|
||||
}
|
||||
else
|
||||
{
|
||||
int ret = 0;
|
||||
|
||||
CRYPTO_CLOCK_ENABLE;
|
||||
CRYPTO->CTRL = 0;
|
||||
CRYPTO->WAC = 0;
|
||||
CRYPTO->SEQCTRL = 0;
|
||||
CRYPTO->SEQCTRLB = 0;
|
||||
|
||||
/* Set key */
|
||||
MBEDTLS_RETVAL_CHK( crypto_setkey_enc (ctx) );
|
||||
|
||||
if( mode == MBEDTLS_AES_DECRYPT )
|
||||
{
|
||||
/* Load IV */
|
||||
CRYPTODRV_DataWriteUnaligned( &CRYPTO->DATA2, iv);
|
||||
|
||||
/* Load instructions to CRYPTO sequencer. */
|
||||
CRYPTO->SEQ0 =
|
||||
CRYPTO_CMD_INSTR_DATA2TODATA0 << _CRYPTO_SEQ0_INSTR0_SHIFT |
|
||||
CRYPTO_CMD_INSTR_AESENC << _CRYPTO_SEQ0_INSTR1_SHIFT |
|
||||
CRYPTO_CMD_INSTR_DATA1TODATA0XOR << _CRYPTO_SEQ0_INSTR2_SHIFT |
|
||||
CRYPTO_CMD_INSTR_DATA1TODATA2 << _CRYPTO_SEQ0_INSTR3_SHIFT;
|
||||
CRYPTO->SEQ1 = 0;
|
||||
|
||||
crypto_aes_processloop(length,
|
||||
&CRYPTO->DATA1, input,
|
||||
&CRYPTO->DATA0, output,
|
||||
iv );
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Load IV */
|
||||
CRYPTODRV_DataWriteUnaligned( &CRYPTO->DATA0, iv);
|
||||
|
||||
/* Load instructions to CRYPTO sequencer. */
|
||||
CRYPTO->SEQ0 =
|
||||
CRYPTO_CMD_INSTR_AESENC << _CRYPTO_SEQ0_INSTR0_SHIFT |
|
||||
CRYPTO_CMD_INSTR_DATA1TODATA0XOR << _CRYPTO_SEQ0_INSTR1_SHIFT;
|
||||
|
||||
crypto_aes_processloop(length,
|
||||
&CRYPTO->DATA1, input,
|
||||
&CRYPTO->DATA0, output,
|
||||
0 );
|
||||
|
||||
/* Copy last output block to iv */
|
||||
memcpy (iv, &output[length-16], 16);
|
||||
}
|
||||
|
||||
cleanup:
|
||||
CRYPTO_CLOCK_DISABLE;
|
||||
|
||||
return( ret );
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* AES-CFB8 buffer encryption/decryption
|
||||
*/
|
||||
int mbedtls_aes_crypt_cfb8( mbedtls_aes_context *ctx,
|
||||
int mode,
|
||||
size_t length,
|
||||
unsigned char iv[16],
|
||||
const unsigned char *input,
|
||||
unsigned char *output )
|
||||
{
|
||||
unsigned char c;
|
||||
unsigned char ov[17];
|
||||
int ret = 0;
|
||||
|
||||
while( length-- )
|
||||
{
|
||||
memcpy( ov, iv, 16 );
|
||||
MBEDTLS_RETVAL_CHK( mbedtls_aes_crypt_ecb( ctx, MBEDTLS_AES_ENCRYPT, iv, iv ) );
|
||||
|
||||
if( mode == MBEDTLS_AES_DECRYPT )
|
||||
ov[16] = *input;
|
||||
|
||||
c = *output++ = (unsigned char)( iv[0] ^ *input++ );
|
||||
|
||||
if( mode == MBEDTLS_AES_ENCRYPT )
|
||||
ov[16] = c;
|
||||
|
||||
memcpy( iv, ov + 1, 16 );
|
||||
}
|
||||
|
||||
cleanup:
|
||||
|
||||
return( ret );
|
||||
}
|
||||
#endif /*MBEDTLS_CIPHER_MODE_CFB */
|
||||
|
||||
#if defined(MBEDTLS_CIPHER_MODE_CTR)
|
||||
/*
|
||||
* AES-CTR buffer encryption/decryption
|
||||
*/
|
||||
int mbedtls_aes_crypt_ctr( mbedtls_aes_context *ctx,
|
||||
size_t length,
|
||||
size_t *nc_off,
|
||||
unsigned char nonce_counter[16],
|
||||
unsigned char stream_block[16],
|
||||
const unsigned char *input,
|
||||
unsigned char *output )
|
||||
{
|
||||
if (( length & 0xf ) || (nc_off && *nc_off) )
|
||||
{
|
||||
int c, i;
|
||||
size_t n = *nc_off;
|
||||
|
||||
while( length-- )
|
||||
{
|
||||
if( n == 0 )
|
||||
{
|
||||
mbedtls_aes_crypt_ecb( ctx, MBEDTLS_AES_ENCRYPT, nonce_counter, stream_block );
|
||||
|
||||
for( i = 16; i > 0; i-- )
|
||||
if( ++nonce_counter[i - 1] != 0 )
|
||||
break;
|
||||
}
|
||||
c = *input++;
|
||||
*output++ = (unsigned char)( c ^ stream_block[n] );
|
||||
|
||||
n = ( n + 1 ) & 0x0F;
|
||||
}
|
||||
|
||||
*nc_off = n;
|
||||
|
||||
return( 0 );
|
||||
}
|
||||
else
|
||||
{
|
||||
int ret = 0;
|
||||
|
||||
CRYPTO_CLOCK_ENABLE;
|
||||
CRYPTO->CTRL = 0;
|
||||
CRYPTO->WAC = 0;
|
||||
CRYPTO->SEQCTRL = 0;
|
||||
CRYPTO->SEQCTRLB = 0;
|
||||
|
||||
/* Set key */
|
||||
MBEDTLS_RETVAL_CHK( crypto_setkey_enc (ctx) );
|
||||
|
||||
BUS_RegMaskedClear(&CRYPTO->CTRL, _CRYPTO_CTRL_INCWIDTH_MASK);
|
||||
BUS_RegMaskedSet(&CRYPTO->CTRL, CRYPTO_CTRL_INCWIDTH_INCWIDTH4);
|
||||
|
||||
CRYPTODRV_DataWriteUnaligned( &CRYPTO->DATA1, nonce_counter );
|
||||
|
||||
CRYPTO->SEQ0 = CRYPTO_CMD_INSTR_DATA1TODATA0 << _CRYPTO_SEQ0_INSTR0_SHIFT |
|
||||
CRYPTO_CMD_INSTR_AESENC << _CRYPTO_SEQ0_INSTR1_SHIFT |
|
||||
CRYPTO_CMD_INSTR_DATA0TODATA3 << _CRYPTO_SEQ0_INSTR2_SHIFT |
|
||||
CRYPTO_CMD_INSTR_DATA1INC << _CRYPTO_SEQ0_INSTR3_SHIFT;
|
||||
|
||||
CRYPTO->SEQ1 = CRYPTO_CMD_INSTR_DATA2TODATA0XOR << _CRYPTO_SEQ1_INSTR4_SHIFT;
|
||||
|
||||
crypto_aes_processloop( length,
|
||||
&CRYPTO->DATA2, input,
|
||||
&CRYPTO->DATA0, output,
|
||||
0);
|
||||
|
||||
CRYPTODRV_DataReadUnaligned( &CRYPTO->DATA1, nonce_counter );
|
||||
|
||||
cleanup:
|
||||
|
||||
CRYPTO_CLOCK_DISABLE;
|
||||
|
||||
return ret;
|
||||
}
|
||||
}
|
||||
#endif /* #if defined(MBEDTLS_CIPHER_MODE_CTR) */
|
||||
|
||||
#endif /* #if defined(CRYPTO_COUNT) && (CRYPTO_COUNT > 0) */
|
||||
|
||||
#endif /* #if defined(MBEDTLS_SLCL_PLUGINS) */
|
||||
|
||||
#endif /* #if defined(MBEDTLS_AES_ALT) */
|
||||
|
||||
#endif /* #if defined(MBEDTLS_AES_C) */
|
File diff suppressed because it is too large
Load Diff
|
@ -0,0 +1,258 @@
|
|||
/*
|
||||
* FIPS-180-1 compliant SHA-1 implementation
|
||||
*
|
||||
* Copyright (C) 2015-2016, Silicon Labs, http://www.silabs.com
|
||||
* 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.
|
||||
*/
|
||||
/*
|
||||
* This file includes alternative plugin implementations of various
|
||||
* functions in sha1.c using the CRYPTO hardware accelerator incorporated
|
||||
* in MCU devices from Silicon Laboratories.
|
||||
*/
|
||||
/*
|
||||
* The SHA-1 standard was published by NIST in 1993.
|
||||
*
|
||||
* http://www.itl.nist.gov/fipspubs/fip180-1.htm
|
||||
*/
|
||||
|
||||
#if !defined(MBEDTLS_CONFIG_FILE)
|
||||
#include "mbedtls/config.h"
|
||||
#else
|
||||
#include MBEDTLS_CONFIG_FILE
|
||||
#endif
|
||||
|
||||
#if defined(MBEDTLS_SHA1_C)
|
||||
|
||||
#if defined(MBEDTLS_SHA1_ALT)
|
||||
|
||||
#if !defined( MBEDTLS_SLCL_PLUGINS )
|
||||
|
||||
#include "em_device.h"
|
||||
|
||||
#if defined(CRYPTO_COUNT) && (CRYPTO_COUNT > 0)
|
||||
|
||||
#include "em_crypto.h"
|
||||
|
||||
#include "mbedtls/sha1.h"
|
||||
|
||||
#include <string.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;
|
||||
}
|
||||
|
||||
#define CRYPTO_CLOCK_ENABLE CMU->HFBUSCLKEN0 |= CMU_HFBUSCLKEN0_CRYPTO;
|
||||
#define CRYPTO_CLOCK_DISABLE CMU->HFBUSCLKEN0 &= ~CMU_HFBUSCLKEN0_CRYPTO;
|
||||
|
||||
/*
|
||||
* 32-bit integer manipulation macros (big endian)
|
||||
*/
|
||||
#ifndef PUT_UINT32_BE
|
||||
#define PUT_UINT32_BE(n,b,i) \
|
||||
{ \
|
||||
(b)[(i) ] = (unsigned char) ( (n) >> 24 ); \
|
||||
(b)[(i) + 1] = (unsigned char) ( (n) >> 16 ); \
|
||||
(b)[(i) + 2] = (unsigned char) ( (n) >> 8 ); \
|
||||
(b)[(i) + 3] = (unsigned char) ( (n) ); \
|
||||
}
|
||||
#endif
|
||||
|
||||
void mbedtls_sha1_init( mbedtls_sha1_context *ctx )
|
||||
{
|
||||
memset( ctx, 0, sizeof( mbedtls_sha1_context ) );
|
||||
}
|
||||
|
||||
void mbedtls_sha1_free( mbedtls_sha1_context *ctx )
|
||||
{
|
||||
if( ctx == NULL )
|
||||
return;
|
||||
|
||||
mbedtls_zeroize( ctx, sizeof( mbedtls_sha1_context ) );
|
||||
}
|
||||
|
||||
void mbedtls_sha1_clone( mbedtls_sha1_context *dst,
|
||||
const mbedtls_sha1_context *src )
|
||||
{
|
||||
*dst = *src;
|
||||
}
|
||||
|
||||
/*
|
||||
* SHA-1 context setup
|
||||
*/
|
||||
void mbedtls_sha1_starts( mbedtls_sha1_context *ctx )
|
||||
{
|
||||
ctx->state[0] = 0x67452301;
|
||||
ctx->state[1] = 0xEFCDAB89;
|
||||
ctx->state[2] = 0x98BADCFE;
|
||||
ctx->state[3] = 0x10325476;
|
||||
ctx->state[4] = 0xC3D2E1F0;
|
||||
ctx->state[5] = 0x0;
|
||||
ctx->state[6] = 0x0;
|
||||
ctx->state[7] = 0x0;
|
||||
|
||||
ctx->total[0] = 0;
|
||||
ctx->total[1] = 0;
|
||||
}
|
||||
|
||||
void mbedtls_sha1_process( mbedtls_sha1_context *ctx, const unsigned char data[64] )
|
||||
{
|
||||
CRYPTO_CLOCK_ENABLE;
|
||||
|
||||
/* Setup crypto module to do SHA-1. */
|
||||
CRYPTO->CTRL = CRYPTO_CTRL_SHA_SHA1 |
|
||||
/* Set DMA0 source to DDATA0 and transfer mode */
|
||||
CRYPTO_CTRL_DMA0RSEL_DDATA0 | CRYPTO_CTRL_DMA0MODE_FULL |
|
||||
/* Set DMA1 source to QDATA1BIG and transfer mode */
|
||||
CRYPTO_CTRL_DMA1RSEL_QDATA1BIG | CRYPTO_CTRL_DMA1MODE_FULL;
|
||||
|
||||
/* Set result width of MADD32 operation. */
|
||||
CRYPTO_ResultWidthSet(CRYPTO, cryptoResult256Bits);
|
||||
|
||||
/* Set sequence control registers */
|
||||
CRYPTO->SEQCTRL = 16 & _CRYPTO_SEQCTRL_LENGTHA_MASK;
|
||||
CRYPTO->SEQCTRLB = 0;
|
||||
|
||||
/* Initiate SHA instruction sequence. */
|
||||
CRYPTO_EXECUTE_6( CRYPTO,
|
||||
CRYPTO_CMD_INSTR_DMA0TODATA,
|
||||
CRYPTO_CMD_INSTR_DDATA0TODDATA1,
|
||||
CRYPTO_CMD_INSTR_SELDDATA0DDATA1,
|
||||
CRYPTO_CMD_INSTR_DMA1TODATA,
|
||||
CRYPTO_CMD_INSTR_SHA,
|
||||
CRYPTO_CMD_INSTR_MADD32);
|
||||
|
||||
/* Write the state to crypto */
|
||||
CRYPTO_DDataWrite(&CRYPTO->DDATA0, ctx->state);
|
||||
|
||||
/* Write block to QDATA1. */
|
||||
/* Check data is 32bit aligned, if not move to temporary buffer. */
|
||||
if ((uint32_t)data & 0x3)
|
||||
{
|
||||
uint32_t temp[16];
|
||||
memcpy(temp, data, 64);
|
||||
CRYPTO_QDataWrite(&CRYPTO->QDATA1BIG, temp);
|
||||
}
|
||||
else
|
||||
{
|
||||
CRYPTO_QDataWrite(&CRYPTO->QDATA1BIG, (uint32_t*) data);
|
||||
}
|
||||
|
||||
/* Read the state from crypto. */
|
||||
CRYPTO_DDataRead(&CRYPTO->DDATA0, ctx->state);
|
||||
|
||||
#if !defined( MBEDTLS_MPI_MUL_MPI_ALT )
|
||||
CRYPTO_CLOCK_DISABLE;
|
||||
#endif
|
||||
}
|
||||
|
||||
/*
|
||||
* SHA-1 process buffer
|
||||
*/
|
||||
void mbedtls_sha1_update( mbedtls_sha1_context *ctx, const unsigned char *input, size_t ilen )
|
||||
{
|
||||
size_t fill;
|
||||
uint32_t left;
|
||||
|
||||
if( ilen == 0 )
|
||||
return;
|
||||
|
||||
left = ctx->total[0] & 0x3F;
|
||||
fill = 64 - left;
|
||||
|
||||
ctx->total[0] += (uint32_t) ilen;
|
||||
ctx->total[0] &= 0xFFFFFFFF;
|
||||
|
||||
if( ctx->total[0] < (uint32_t) ilen )
|
||||
ctx->total[1]++;
|
||||
|
||||
if( left && ilen >= fill )
|
||||
{
|
||||
memcpy( (void *) (ctx->buffer + left), input, fill );
|
||||
mbedtls_sha1_process( ctx, ctx->buffer );
|
||||
input += fill;
|
||||
ilen -= fill;
|
||||
left = 0;
|
||||
}
|
||||
|
||||
while( ilen >= 64 )
|
||||
{
|
||||
mbedtls_sha1_process( ctx, input );
|
||||
input += 64;
|
||||
ilen -= 64;
|
||||
}
|
||||
|
||||
if( ilen > 0 )
|
||||
memcpy( (void *) (ctx->buffer + left), input, ilen );
|
||||
}
|
||||
|
||||
static const unsigned char sha1_padding[64] =
|
||||
{
|
||||
0x80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
|
||||
};
|
||||
|
||||
/*
|
||||
* SHA-1 final digest
|
||||
*/
|
||||
void mbedtls_sha1_finish( mbedtls_sha1_context *ctx, unsigned char output[20] )
|
||||
{
|
||||
uint32_t last, padn;
|
||||
uint32_t high, low;
|
||||
unsigned char msglen[8];
|
||||
|
||||
high = ( ctx->total[0] >> 29 )
|
||||
| ( ctx->total[1] << 3 );
|
||||
low = ( ctx->total[0] << 3 );
|
||||
|
||||
PUT_UINT32_BE( high, msglen, 0 );
|
||||
PUT_UINT32_BE( low, msglen, 4 );
|
||||
|
||||
last = ctx->total[0] & 0x3F;
|
||||
padn = ( last < 56 ) ? ( 56 - last ) : ( 120 - last );
|
||||
|
||||
mbedtls_sha1_update( ctx, sha1_padding, padn );
|
||||
mbedtls_sha1_update( ctx, msglen, 8 );
|
||||
|
||||
/* Read resulting digest (big endian) */
|
||||
CRYPTO_CLOCK_ENABLE;
|
||||
((uint32_t*)output)[0] = CRYPTO->DDATA0BIG;
|
||||
((uint32_t*)output)[1] = CRYPTO->DDATA0BIG;
|
||||
((uint32_t*)output)[2] = CRYPTO->DDATA0BIG;
|
||||
((uint32_t*)output)[3] = CRYPTO->DDATA0BIG;
|
||||
((uint32_t*)output)[4] = CRYPTO->DDATA0BIG;
|
||||
{
|
||||
/* Read 3 remaining 32-bit words from DDATA0BIG (shift register). */
|
||||
volatile uint32_t temp;
|
||||
temp = CRYPTO->DDATA0BIG;
|
||||
temp = CRYPTO->DDATA0BIG;
|
||||
temp = CRYPTO->DDATA0BIG;
|
||||
(void) temp;
|
||||
}
|
||||
|
||||
#if !defined( MBEDTLS_MPI_MUL_MPI_ALT )
|
||||
CRYPTO_CLOCK_DISABLE;
|
||||
#endif
|
||||
}
|
||||
|
||||
#endif /* #if defined(CRYPTO_COUNT) && (CRYPTO_COUNT > 0) */
|
||||
|
||||
#endif /* #if !defined(MBEDTLS_SLCL_PLUGINS) */
|
||||
|
||||
#endif /* #if defined(MBEDTLS_SHA1_ALT) */
|
||||
|
||||
#endif /* #if defined(MBEDTLS_SHA1_C) */
|
|
@ -0,0 +1,270 @@
|
|||
/*
|
||||
* FIPS-180-2 compliant SHA-256 implementation
|
||||
*
|
||||
* Copyright (C) 2015-2016, Silicon Labs, http://www.silabs.com
|
||||
* 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.
|
||||
*/
|
||||
/*
|
||||
* This file includes alternative plugin implementations of various
|
||||
* functions in sha256.c using the CRYPTO hardware accelerator incorporated
|
||||
* in MCU devices from Silicon Laboratories.
|
||||
*/
|
||||
/*
|
||||
* The SHA-256 Secure Hash Standard was published by NIST in 2002.
|
||||
*
|
||||
* http://csrc.nist.gov/publications/fips/fips180-2/fips180-2.pdf
|
||||
*/
|
||||
|
||||
#if !defined(MBEDTLS_CONFIG_FILE)
|
||||
#include "mbedtls/config.h"
|
||||
#else
|
||||
#include MBEDTLS_CONFIG_FILE
|
||||
#endif
|
||||
|
||||
#if defined(MBEDTLS_SHA256_C)
|
||||
|
||||
#if defined(MBEDTLS_SHA256_ALT)
|
||||
|
||||
#if !defined( MBEDTLS_SLCL_PLUGINS )
|
||||
|
||||
#include "em_device.h"
|
||||
|
||||
#if defined(CRYPTO_COUNT) && (CRYPTO_COUNT > 0)
|
||||
|
||||
#include "em_crypto.h"
|
||||
#include "cryptodrv_internal.h"
|
||||
#include "mbedtls/sha256.h"
|
||||
#include <string.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;
|
||||
}
|
||||
|
||||
#define CRYPTO_CLOCK_ENABLE CMU->HFBUSCLKEN0 |= CMU_HFBUSCLKEN0_CRYPTO;
|
||||
#define CRYPTO_CLOCK_DISABLE CMU->HFBUSCLKEN0 &= ~CMU_HFBUSCLKEN0_CRYPTO;
|
||||
|
||||
/*
|
||||
* 32-bit integer manipulation macros (big endian)
|
||||
*/
|
||||
#ifndef PUT_UINT32_BE
|
||||
#define PUT_UINT32_BE(n,b,i) \
|
||||
do { \
|
||||
(b)[(i) ] = (unsigned char) ( (n) >> 24 ); \
|
||||
(b)[(i) + 1] = (unsigned char) ( (n) >> 16 ); \
|
||||
(b)[(i) + 2] = (unsigned char) ( (n) >> 8 ); \
|
||||
(b)[(i) + 3] = (unsigned char) ( (n) ); \
|
||||
} while( 0 )
|
||||
#endif
|
||||
|
||||
void mbedtls_sha256_init( mbedtls_sha256_context *ctx )
|
||||
{
|
||||
memset( ctx, 0, sizeof( mbedtls_sha256_context ) );
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
/*
|
||||
* SHA-256 context setup
|
||||
*/
|
||||
void mbedtls_sha256_starts( mbedtls_sha256_context *ctx, int is224 )
|
||||
{
|
||||
/* Create the init vector */
|
||||
if( is224 == 0 )
|
||||
{
|
||||
/* SHA-256 */
|
||||
ctx->state[0] = 0x6A09E667;
|
||||
ctx->state[1] = 0xBB67AE85;
|
||||
ctx->state[2] = 0x3C6EF372;
|
||||
ctx->state[3] = 0xA54FF53A;
|
||||
ctx->state[4] = 0x510E527F;
|
||||
ctx->state[5] = 0x9B05688C;
|
||||
ctx->state[6] = 0x1F83D9AB;
|
||||
ctx->state[7] = 0x5BE0CD19;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* SHA-224 */
|
||||
ctx->state[0] = 0xC1059ED8;
|
||||
ctx->state[1] = 0x367CD507;
|
||||
ctx->state[2] = 0x3070DD17;
|
||||
ctx->state[3] = 0xF70E5939;
|
||||
ctx->state[4] = 0xFFC00B31;
|
||||
ctx->state[5] = 0x68581511;
|
||||
ctx->state[6] = 0x64F98FA7;
|
||||
ctx->state[7] = 0xBEFA4FA4;
|
||||
}
|
||||
|
||||
ctx->total[0] = 0;
|
||||
ctx->total[1] = 0;
|
||||
|
||||
ctx->is224 = is224;
|
||||
}
|
||||
|
||||
void mbedtls_sha256_process( mbedtls_sha256_context *ctx, const unsigned char data[64] )
|
||||
{
|
||||
CRYPTO_CLOCK_ENABLE;
|
||||
|
||||
/* Setup crypto module to do SHA-2. */
|
||||
CRYPTO->CTRL = CRYPTO_CTRL_SHA_SHA2 |
|
||||
/* Set DMA0 source to DDATA0 and transfer mode */
|
||||
CRYPTO_CTRL_DMA0RSEL_DDATA0 | CRYPTO_CTRL_DMA0MODE_FULL |
|
||||
/* Set DMA1 source to QDATA1BIG and transfer mode */
|
||||
CRYPTO_CTRL_DMA1RSEL_QDATA1BIG | CRYPTO_CTRL_DMA1MODE_FULL;
|
||||
|
||||
/* Set result width of MADD32 operation. */
|
||||
CRYPTO_ResultWidthSet(CRYPTO, cryptoResult256Bits);
|
||||
|
||||
/* Set sequence control registers */
|
||||
CRYPTO->SEQCTRL = 16 & _CRYPTO_SEQCTRL_LENGTHA_MASK;
|
||||
CRYPTO->SEQCTRLB = 0;
|
||||
|
||||
/* Initiate SHA instruction sequence. */
|
||||
CRYPTO_EXECUTE_6( CRYPTO,
|
||||
CRYPTO_CMD_INSTR_DMA0TODATA,
|
||||
CRYPTO_CMD_INSTR_DDATA0TODDATA1,
|
||||
CRYPTO_CMD_INSTR_SELDDATA0DDATA1,
|
||||
CRYPTO_CMD_INSTR_DMA1TODATA,
|
||||
CRYPTO_CMD_INSTR_SHA,
|
||||
CRYPTO_CMD_INSTR_MADD32);
|
||||
|
||||
/* Write the state to crypto */
|
||||
CRYPTO_DDataWrite(&CRYPTO->DDATA0, ctx->state);
|
||||
|
||||
/* Write block to QDATA1. */
|
||||
/* Check data is 32bit aligned, if not move to temporary buffer. */
|
||||
if ((uint32_t)data & 0x3)
|
||||
{
|
||||
uint32_t temp[16];
|
||||
memcpy(temp, data, 64);
|
||||
CRYPTO_QDataWrite(&CRYPTO->QDATA1BIG, temp);
|
||||
}
|
||||
else
|
||||
{
|
||||
CRYPTO_QDataWrite(&CRYPTO->QDATA1BIG, (uint32_t*) data);
|
||||
}
|
||||
|
||||
/* Read the state from crypto. */
|
||||
CRYPTO_DDataRead(&CRYPTO->DDATA0, ctx->state);
|
||||
|
||||
#if !defined( MBEDTLS_MPI_MUL_MPI_ALT )
|
||||
CRYPTO_CLOCK_DISABLE;
|
||||
#endif
|
||||
}
|
||||
|
||||
/*
|
||||
* SHA-256 process buffer
|
||||
*/
|
||||
void mbedtls_sha256_update( mbedtls_sha256_context *ctx, const unsigned char *input,
|
||||
size_t ilen )
|
||||
{
|
||||
size_t fill;
|
||||
uint32_t left;
|
||||
|
||||
if( ilen == 0 )
|
||||
return;
|
||||
|
||||
left = ctx->total[0] & 0x3F;
|
||||
fill = 64 - left;
|
||||
|
||||
ctx->total[0] += (uint32_t) ilen;
|
||||
ctx->total[0] &= 0xFFFFFFFF;
|
||||
|
||||
if( ctx->total[0] < (uint32_t) ilen )
|
||||
ctx->total[1]++;
|
||||
|
||||
if( left && ilen >= fill )
|
||||
{
|
||||
memcpy( (void *) (ctx->buffer + left), input, fill );
|
||||
mbedtls_sha256_process( ctx, ctx->buffer );
|
||||
input += fill;
|
||||
ilen -= fill;
|
||||
left = 0;
|
||||
}
|
||||
|
||||
while( ilen >= 64 )
|
||||
{
|
||||
mbedtls_sha256_process( ctx, input );
|
||||
input += 64;
|
||||
ilen -= 64;
|
||||
}
|
||||
|
||||
if( ilen > 0 )
|
||||
memcpy( (void *) (ctx->buffer + left), input, ilen );
|
||||
}
|
||||
|
||||
static const unsigned char sha256_padding[64] =
|
||||
{
|
||||
0x80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
|
||||
};
|
||||
|
||||
/*
|
||||
* SHA-256 final digest
|
||||
*/
|
||||
void mbedtls_sha256_finish( mbedtls_sha256_context *ctx, unsigned char output[32] )
|
||||
{
|
||||
uint32_t last, padn;
|
||||
uint32_t high, low;
|
||||
unsigned char msglen[8];
|
||||
|
||||
high = ( ctx->total[0] >> 29 )
|
||||
| ( ctx->total[1] << 3 );
|
||||
low = ( ctx->total[0] << 3 );
|
||||
|
||||
PUT_UINT32_BE( high, msglen, 0 );
|
||||
PUT_UINT32_BE( low, msglen, 4 );
|
||||
|
||||
last = ctx->total[0] & 0x3F;
|
||||
padn = ( last < 56 ) ? ( 56 - last ) : ( 120 - last );
|
||||
|
||||
mbedtls_sha256_update( ctx, sha256_padding, padn );
|
||||
mbedtls_sha256_update( ctx, msglen, 8 );
|
||||
|
||||
/* Read resulting digest (big endian) */
|
||||
CRYPTO_CLOCK_ENABLE;
|
||||
|
||||
/* Read the digest from crypto (big endian). */
|
||||
CRYPTODRV_DDataReadUnaligned(&CRYPTO->DDATA0BIG, output);
|
||||
|
||||
#if !defined( MBEDTLS_MPI_MUL_MPI_ALT )
|
||||
CRYPTO_CLOCK_DISABLE;
|
||||
#endif
|
||||
|
||||
if( ctx->is224 )
|
||||
memset(&output[28], 0, 4);
|
||||
}
|
||||
|
||||
#endif /* #if defined(CRYPTO_COUNT) && (CRYPTO_COUNT > 0) */
|
||||
|
||||
#endif /* #if !defined( MBEDTLS_SLCL_PLUGINS ) */
|
||||
|
||||
#endif /* #if defined(MBEDTLS_SHA256_ALT) */
|
||||
|
||||
#endif /* #if defined(MBEDTLS_SHA256_C) */
|
|
@ -0,0 +1,79 @@
|
|||
/*
|
||||
* Portable interface to the CPU cycle counter
|
||||
*
|
||||
* Copyright (C) 2016, Silicon Labs, http://www.silabs.com
|
||||
* 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.
|
||||
*/
|
||||
|
||||
#if !defined(MBEDTLS_CONFIG_FILE)
|
||||
#include "mbedtls/config.h"
|
||||
#else
|
||||
#include MBEDTLS_CONFIG_FILE
|
||||
#endif
|
||||
|
||||
#if defined(MBEDTLS_SELF_TEST) && defined(MBEDTLS_PLATFORM_C)
|
||||
#include "mbedtls/platform.h"
|
||||
#else
|
||||
#include <stdio.h>
|
||||
#define mbedtls_printf printf
|
||||
#endif
|
||||
|
||||
#if defined(MBEDTLS_TIMING_C)
|
||||
|
||||
#include "em_device.h"
|
||||
#include "em_cmu.h"
|
||||
|
||||
#include "mbedtls/timing.h"
|
||||
|
||||
#if defined(MBEDTLS_TIMING_ALT)
|
||||
|
||||
void mbedtls_timing_init( void )
|
||||
{
|
||||
if ((CMU->STATUS & _CMU_STATUS_AUXHFRCOENS_MASK) == 0)
|
||||
{
|
||||
/* Enable debug clock AUXHFRCO */
|
||||
CMU_OscillatorEnable(cmuOsc_AUXHFRCO, true, true);
|
||||
}
|
||||
|
||||
if ((CoreDebug->DHCSR & CoreDebug_DHCSR_C_DEBUGEN_Msk) == 0)
|
||||
{
|
||||
/* Enable trace in core debug */
|
||||
CoreDebug->DHCSR |= CoreDebug_DHCSR_C_DEBUGEN_Msk;
|
||||
CoreDebug->DEMCR |= CoreDebug_DEMCR_TRCENA_Msk;
|
||||
}
|
||||
if ((ITM->TCR & ITM_TCR_DWTENA_Msk) == 0)
|
||||
{
|
||||
/* Unlock ITM and output data */
|
||||
ITM->LAR = 0xC5ACCE55;
|
||||
ITM->TCR |= ITM_TCR_DWTENA_Msk;
|
||||
}
|
||||
if ((DWT->CTRL & DWT_CTRL_CYCCNTENA_Msk) == 0)
|
||||
{
|
||||
/* Enable DWT bits */
|
||||
DWT->CTRL |= DWT_CTRL_CYCCNTENA_Msk;
|
||||
DWT->CYCCNT = 0;
|
||||
}
|
||||
}
|
||||
|
||||
void mbedtls_timing_free( void )
|
||||
{
|
||||
/* Disable the DWT and debug clock */
|
||||
DWT->CTRL = 0;
|
||||
CMU_OscillatorEnable( cmuOsc_AUXHFRCO, false, true );
|
||||
}
|
||||
|
||||
#endif /* !MBEDTLS_TIMING_ALT */
|
||||
|
||||
#endif /* MBEDTLS_TIMING_C */
|
|
@ -0,0 +1,551 @@
|
|||
/*
|
||||
* FIPS-197 compliant AES implementation
|
||||
*
|
||||
* Copyright (C) 2016, Silicon Labs, http://www.silabs.com
|
||||
* 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.
|
||||
*/
|
||||
|
||||
/*
|
||||
* This file includes alternative plugin implementations of various
|
||||
* functions in aes.c using the CRYPTO hardware accelerator incorporated
|
||||
* in MCU devices from Silicon Laboratories.
|
||||
*/
|
||||
|
||||
/*
|
||||
* The AES block cipher was designed by Vincent Rijmen and Joan Daemen.
|
||||
*
|
||||
* http://csrc.nist.gov/encryption/aes/rijndael/Rijndael.pdf
|
||||
* http://csrc.nist.gov/publications/fips/fips197/fips-197.pdf
|
||||
*/
|
||||
|
||||
#if !defined(MBEDTLS_CONFIG_FILE)
|
||||
#include "mbedtls/config.h"
|
||||
#else
|
||||
#include MBEDTLS_CONFIG_FILE
|
||||
#endif
|
||||
|
||||
#if defined(MBEDTLS_AES_C)
|
||||
|
||||
#if defined(MBEDTLS_AES_ALT)
|
||||
|
||||
#if defined( MBEDTLS_SLCL_PLUGINS )
|
||||
|
||||
#include "mbedtls/aes.h"
|
||||
#include "sl_crypto.h"
|
||||
#include "aesdrv_internal.h"
|
||||
#include "cryptodrv_internal.h"
|
||||
#include <string.h>
|
||||
|
||||
#define AES_BLOCKSIZE ( 16 )
|
||||
|
||||
#define MBEDTLS_RETVAL_CHK(f) do { if( ( ret = f ) != 0 ) goto cleanup; } while( 0 )
|
||||
|
||||
/* 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;
|
||||
}
|
||||
|
||||
/*
|
||||
* Initialize AES context
|
||||
*/
|
||||
void mbedtls_aes_init( mbedtls_aes_context *ctx )
|
||||
{
|
||||
memset( ctx, 0, sizeof( mbedtls_aes_context ) );
|
||||
|
||||
AESDRV_Init ( &ctx->aesdrv_ctx );
|
||||
AESDRV_SetDeviceInstance ( &ctx->aesdrv_ctx, 0 );
|
||||
AESDRV_SetIoMode ( &ctx->aesdrv_ctx, aesdrvIoModeCore, 0 );
|
||||
}
|
||||
|
||||
/*
|
||||
* Clear AES context
|
||||
*/
|
||||
void mbedtls_aes_free( mbedtls_aes_context *ctx )
|
||||
{
|
||||
if( ctx == NULL )
|
||||
return;
|
||||
|
||||
AESDRV_DeInit ( &ctx->aesdrv_ctx );
|
||||
|
||||
mbedtls_zeroize( ctx, sizeof( mbedtls_aes_context ) );
|
||||
}
|
||||
|
||||
/*
|
||||
* Set the device instance of an AES context.
|
||||
*/
|
||||
int mbedtls_aes_set_device_instance(mbedtls_aes_context *ctx,
|
||||
unsigned int devno)
|
||||
{
|
||||
#if defined(AES_COUNT) && (AES_COUNT > 0)
|
||||
(void) ctx;
|
||||
if ((devno > AES_COUNT) || (devno != 0))
|
||||
return( MBEDTLS_ERR_AES_INVALID_PARAM );
|
||||
else
|
||||
return( 0 );
|
||||
#endif
|
||||
|
||||
#if defined(CRYPTO_COUNT) && (CRYPTO_COUNT > 0)
|
||||
if (devno > CRYPTO_COUNT)
|
||||
return( MBEDTLS_ERR_AES_INVALID_PARAM );
|
||||
|
||||
return cryptodrvSetDeviceInstance( &ctx->aesdrv_ctx.cryptodrvContext,
|
||||
devno );
|
||||
#endif /* #if defined(CRYPTO_COUNT) && (CRYPTO_COUNT > 0) */
|
||||
}
|
||||
|
||||
#if defined( MBEDTLS_INCLUDE_ASYNCH_API )
|
||||
/*
|
||||
* Set an AES context in asynchronous mode.
|
||||
*/
|
||||
int mbedtls_aes_set_asynch( mbedtls_aes_context *ctx,
|
||||
mbedtls_aes_asynch_context *asynch_ctx,
|
||||
mbedtls_asynch_callback asynch_callback,
|
||||
void* asynch_callback_user_arg )
|
||||
{
|
||||
Ecode_t status;
|
||||
|
||||
AESDRV_BlockCipherAsynchContext_t *aesdrv_asynch_ctx =
|
||||
asynch_ctx ? &asynch_ctx->aesdrv_asynch_ctx : 0;
|
||||
|
||||
status = AESDRV_SetAsynchMode(&ctx->aesdrv_ctx,
|
||||
cipherModeBlockCipher,
|
||||
aesdrv_asynch_ctx,
|
||||
(AESDRV_AsynchCallback_t) asynch_callback,
|
||||
asynch_callback_user_arg);
|
||||
if (status != ECODE_OK)
|
||||
{
|
||||
return (int)status;
|
||||
}
|
||||
|
||||
return( 0 );
|
||||
}
|
||||
#endif /* #if defined( MBEDTLS_INCLUDE_ASYNCH_API ) */
|
||||
|
||||
/*
|
||||
* Set the device I/O mode of an AES context.
|
||||
*/
|
||||
int mbedtls_aes_set_device_io_mode( mbedtls_aes_context *ctx,
|
||||
mbedtls_device_io_mode mode,
|
||||
mbedtls_device_io_mode_specific *specific )
|
||||
{
|
||||
return AESDRV_SetIoMode(&ctx->aesdrv_ctx,
|
||||
(AESDRV_IoMode_t) mode,
|
||||
(AESDRV_IoModeSpecific_t*) specific);
|
||||
}
|
||||
|
||||
/*
|
||||
* AES key schedule (encryption)
|
||||
*/
|
||||
int mbedtls_aes_setkey_enc( mbedtls_aes_context *ctx, const unsigned char *key,
|
||||
unsigned int keybits )
|
||||
{
|
||||
if ( ( 128 != keybits ) && ( 256 != keybits ) )
|
||||
/* Unsupported key size */
|
||||
return( MBEDTLS_ERR_AES_INVALID_KEY_LENGTH );
|
||||
|
||||
ctx->keybits = keybits;
|
||||
memcpy(ctx->key, key, keybits/8);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* AES key schedule (decryption)
|
||||
*/
|
||||
int mbedtls_aes_setkey_dec( mbedtls_aes_context *ctx, const unsigned char *key,
|
||||
unsigned int keybits )
|
||||
{
|
||||
int ret = 0;
|
||||
Ecode_t status;
|
||||
|
||||
switch( keybits )
|
||||
{
|
||||
case 128:
|
||||
status = AESDRV_DecryptKey128( &ctx->aesdrv_ctx,
|
||||
(uint8_t*)ctx->key,
|
||||
key );
|
||||
if (status != ECODE_OK)
|
||||
ret = status;
|
||||
break;
|
||||
|
||||
case 256:
|
||||
status = AESDRV_DecryptKey256( &ctx->aesdrv_ctx,
|
||||
(uint8_t*)ctx->key,
|
||||
key );
|
||||
if (status != ECODE_OK)
|
||||
ret = status;
|
||||
break;
|
||||
|
||||
default:
|
||||
/* Unsupported key size */
|
||||
ret = MBEDTLS_ERR_AES_INVALID_KEY_LENGTH;
|
||||
break;
|
||||
}
|
||||
|
||||
ctx->keybits = keybits;
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
/*
|
||||
* AES-ECB block encryption/decryption
|
||||
*/
|
||||
int mbedtls_aes_crypt_ecb( mbedtls_aes_context *ctx,
|
||||
int mode,
|
||||
const unsigned char input[16],
|
||||
unsigned char output[16] )
|
||||
{
|
||||
int ret = 0;
|
||||
Ecode_t status;
|
||||
|
||||
switch( ctx->keybits )
|
||||
{
|
||||
case 128:
|
||||
status = AESDRV_ECB128( &ctx->aesdrv_ctx,
|
||||
output,
|
||||
input,
|
||||
16,
|
||||
(uint8_t*)ctx->key,
|
||||
mode == MBEDTLS_AES_ENCRYPT ? true : false );
|
||||
|
||||
if (status != ECODE_OK)
|
||||
ret = status;
|
||||
break;
|
||||
|
||||
case 256:
|
||||
status = AESDRV_ECB256( &ctx->aesdrv_ctx,
|
||||
output,
|
||||
input,
|
||||
16,
|
||||
(uint8_t*)ctx->key,
|
||||
mode == MBEDTLS_AES_ENCRYPT ? true : false );
|
||||
|
||||
if (status != ECODE_OK)
|
||||
ret = status;
|
||||
break;
|
||||
|
||||
default:
|
||||
ret = MBEDTLS_ERR_AES_INVALID_KEY_LENGTH;
|
||||
break;
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
#if defined(MBEDTLS_CIPHER_MODE_CBC)
|
||||
|
||||
/*
|
||||
* AES-CBC buffer encryption/decryption
|
||||
*/
|
||||
int mbedtls_aes_crypt_cbc( mbedtls_aes_context *ctx,
|
||||
int mode,
|
||||
size_t length,
|
||||
unsigned char iv[16],
|
||||
const unsigned char *input,
|
||||
unsigned char *output )
|
||||
{
|
||||
int ret = 0;
|
||||
Ecode_t status;
|
||||
|
||||
/* Input length must be a multiple of 16 bytes which is the AES block
|
||||
length. */
|
||||
if( length & 0xf )
|
||||
return( MBEDTLS_ERR_AES_INVALID_INPUT_LENGTH );
|
||||
|
||||
switch( ctx->keybits )
|
||||
{
|
||||
case 128:
|
||||
status = AESDRV_CBC128( &ctx->aesdrv_ctx,
|
||||
output,
|
||||
input,
|
||||
length,
|
||||
(uint8_t*)ctx->key,
|
||||
iv,
|
||||
mode == MBEDTLS_AES_ENCRYPT ? true : false );
|
||||
|
||||
if (status != ECODE_OK)
|
||||
ret = status;
|
||||
break;
|
||||
|
||||
case 256:
|
||||
status = AESDRV_CBC256( &ctx->aesdrv_ctx,
|
||||
output,
|
||||
input,
|
||||
length,
|
||||
(uint8_t*)ctx->key,
|
||||
iv,
|
||||
mode == MBEDTLS_AES_ENCRYPT ? true : false );
|
||||
|
||||
if (status != ECODE_OK)
|
||||
ret = status;
|
||||
break;
|
||||
|
||||
default:
|
||||
ret = MBEDTLS_ERR_AES_INVALID_KEY_LENGTH;
|
||||
break;
|
||||
}
|
||||
|
||||
return( ret );
|
||||
}
|
||||
#endif /* MBEDTLS_CIPHER_MODE_CBC */
|
||||
|
||||
#if defined(MBEDTLS_CIPHER_MODE_CFB)
|
||||
/*
|
||||
* AES-CFB128 buffer encryption/decryption
|
||||
*/
|
||||
int mbedtls_aes_crypt_cfb128( mbedtls_aes_context *ctx,
|
||||
int mode,
|
||||
size_t length,
|
||||
size_t *iv_off,
|
||||
unsigned char iv[16],
|
||||
const unsigned char *input,
|
||||
unsigned char *output )
|
||||
{
|
||||
size_t n = iv_off ? *iv_off : 0;
|
||||
|
||||
if ( n || ( length & 0xf ) )
|
||||
{
|
||||
int c;
|
||||
|
||||
#if defined(CRYPTO_COUNT) && (CRYPTO_COUNT > 0)
|
||||
#if defined( MBEDTLS_INCLUDE_ASYNCH_API )
|
||||
if (ctx->aesdrv_ctx.pAsynchContext)
|
||||
{
|
||||
/* Asynchronous calls are not supported when iv_off is non-zero. */
|
||||
return MBEDTLS_ERR_AES_NOT_SUPPORTED;
|
||||
}
|
||||
#endif /* #if defined( MBEDTLS_INCLUDE_ASYNCH_API ) */
|
||||
#endif /* #if defined(CRYPTO_COUNT) && (CRYPTO_COUNT > 0) */
|
||||
|
||||
if( mode == MBEDTLS_AES_DECRYPT )
|
||||
{
|
||||
while( length-- )
|
||||
{
|
||||
if( n == 0 )
|
||||
mbedtls_aes_crypt_ecb( ctx, MBEDTLS_AES_ENCRYPT, iv, iv );
|
||||
|
||||
c = *input++;
|
||||
*output++ = (unsigned char)( c ^ iv[n] );
|
||||
iv[n] = (unsigned char) c;
|
||||
|
||||
n = ( n + 1 ) & 0x0F;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
while( length-- )
|
||||
{
|
||||
if( n == 0 )
|
||||
mbedtls_aes_crypt_ecb( ctx, MBEDTLS_AES_ENCRYPT, iv, iv );
|
||||
|
||||
iv[n] = *output++ = (unsigned char)( iv[n] ^ *input++ );
|
||||
|
||||
n = ( n + 1 ) & 0x0F;
|
||||
}
|
||||
}
|
||||
|
||||
if (iv_off)
|
||||
{
|
||||
*iv_off = n;
|
||||
}
|
||||
return( 0 );
|
||||
}
|
||||
else
|
||||
{
|
||||
int ret = 0;
|
||||
Ecode_t status;
|
||||
|
||||
switch( ctx->keybits )
|
||||
{
|
||||
case 128:
|
||||
status = AESDRV_CFB128( &ctx->aesdrv_ctx,
|
||||
output,
|
||||
input,
|
||||
length,
|
||||
(uint8_t*)ctx->key,
|
||||
iv,
|
||||
mode == MBEDTLS_AES_ENCRYPT ?
|
||||
true : false );
|
||||
|
||||
if (status != ECODE_OK)
|
||||
ret = status;
|
||||
break;
|
||||
|
||||
case 256:
|
||||
status = AESDRV_CFB256( &ctx->aesdrv_ctx,
|
||||
output,
|
||||
input,
|
||||
length,
|
||||
(uint8_t*)ctx->key,
|
||||
iv,
|
||||
mode == MBEDTLS_AES_ENCRYPT ?
|
||||
true : false );
|
||||
|
||||
if (status != ECODE_OK)
|
||||
ret = status;
|
||||
break;
|
||||
|
||||
default:
|
||||
ret = MBEDTLS_ERR_AES_INVALID_KEY_LENGTH;
|
||||
break;
|
||||
}
|
||||
|
||||
return( ret );
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* AES-CFB8 buffer encryption/decryption
|
||||
*/
|
||||
int mbedtls_aes_crypt_cfb8( mbedtls_aes_context *ctx,
|
||||
int mode,
|
||||
size_t length,
|
||||
unsigned char iv[16],
|
||||
const unsigned char *input,
|
||||
unsigned char *output )
|
||||
{
|
||||
unsigned char c;
|
||||
unsigned char ov[17];
|
||||
int ret = 0;
|
||||
|
||||
#if defined(CRYPTO_COUNT) && (CRYPTO_COUNT > 0)
|
||||
#if defined( MBEDTLS_INCLUDE_ASYNCH_API )
|
||||
if (ctx->aesdrv_ctx.pAsynchContext)
|
||||
{
|
||||
/* Asynchronous calls are not supported by this function. */
|
||||
return MBEDTLS_ERR_AES_NOT_SUPPORTED;
|
||||
}
|
||||
#endif /* #if defined( MBEDTLS_INCLUDE_ASYNCH_API ) */
|
||||
#endif /* #if defined(CRYPTO_COUNT) && (CRYPTO_COUNT > 0) */
|
||||
|
||||
while( length-- )
|
||||
{
|
||||
memcpy( ov, iv, 16 );
|
||||
MBEDTLS_RETVAL_CHK( mbedtls_aes_crypt_ecb( ctx, MBEDTLS_AES_ENCRYPT, iv, iv ) );
|
||||
|
||||
if( mode == MBEDTLS_AES_DECRYPT )
|
||||
ov[16] = *input;
|
||||
|
||||
c = *output++ = (unsigned char)( iv[0] ^ *input++ );
|
||||
|
||||
if( mode == MBEDTLS_AES_ENCRYPT )
|
||||
ov[16] = c;
|
||||
|
||||
memcpy( iv, ov + 1, 16 );
|
||||
}
|
||||
|
||||
cleanup:
|
||||
|
||||
return( ret );
|
||||
}
|
||||
#endif /*MBEDTLS_CIPHER_MODE_CFB */
|
||||
|
||||
#if defined(MBEDTLS_CIPHER_MODE_CTR)
|
||||
/*
|
||||
* AES-CTR buffer encryption/decryption
|
||||
*/
|
||||
int mbedtls_aes_crypt_ctr( mbedtls_aes_context *ctx,
|
||||
size_t length,
|
||||
size_t *nc_off,
|
||||
unsigned char nonce_counter[16],
|
||||
unsigned char stream_block[16],
|
||||
const unsigned char *input,
|
||||
unsigned char *output )
|
||||
{
|
||||
size_t n = nc_off ? *nc_off : 0;
|
||||
|
||||
if ( n || ( length & 0xf ) )
|
||||
{
|
||||
int c, i;
|
||||
|
||||
#if defined(CRYPTO_COUNT) && (CRYPTO_COUNT > 0)
|
||||
#if defined( MBEDTLS_INCLUDE_ASYNCH_API )
|
||||
if (ctx->aesdrv_ctx.pAsynchContext)
|
||||
{
|
||||
/* Asynchronous calls are not supported when nc_off is non-zero. */
|
||||
return MBEDTLS_ERR_AES_NOT_SUPPORTED;
|
||||
}
|
||||
#endif /* #if defined( MBEDTLS_INCLUDE_ASYNCH_API ) */
|
||||
#endif /* #if defined(CRYPTO_COUNT) && (CRYPTO_COUNT > 0) */
|
||||
|
||||
while( length-- )
|
||||
{
|
||||
if( n == 0 )
|
||||
{
|
||||
mbedtls_aes_crypt_ecb( ctx, MBEDTLS_AES_ENCRYPT, nonce_counter, stream_block );
|
||||
|
||||
for( i = 16; i > 0; i-- )
|
||||
if( ++nonce_counter[i - 1] != 0 )
|
||||
break;
|
||||
}
|
||||
c = *input++;
|
||||
*output++ = (unsigned char)( c ^ stream_block[n] );
|
||||
|
||||
n = ( n + 1 ) & 0x0F;
|
||||
}
|
||||
|
||||
if (nc_off)
|
||||
{
|
||||
*nc_off = n;
|
||||
}
|
||||
return( 0 );
|
||||
}
|
||||
else
|
||||
{
|
||||
int ret = 0;
|
||||
Ecode_t status;
|
||||
|
||||
switch( ctx->keybits )
|
||||
{
|
||||
case 128:
|
||||
status = AESDRV_CTR128( &ctx->aesdrv_ctx,
|
||||
output,
|
||||
input,
|
||||
length,
|
||||
(uint8_t*)ctx->key,
|
||||
nonce_counter,
|
||||
0);
|
||||
if (status != ECODE_OK)
|
||||
ret = status;
|
||||
break;
|
||||
|
||||
case 256:
|
||||
status = AESDRV_CTR256( &ctx->aesdrv_ctx,
|
||||
output,
|
||||
input,
|
||||
length,
|
||||
(uint8_t*)ctx->key,
|
||||
nonce_counter,
|
||||
0);
|
||||
if (status != ECODE_OK)
|
||||
ret = status;
|
||||
break;
|
||||
|
||||
default:
|
||||
ret = MBEDTLS_ERR_AES_INVALID_KEY_LENGTH;
|
||||
break;
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
}
|
||||
#endif /* MBEDTLS_CIPHER_MODE_CTR */
|
||||
|
||||
#endif /* MBEDTLS_SLCL_PLUGINS */
|
||||
|
||||
#endif /* MBEDTLS_AES_ALT */
|
||||
|
||||
#endif /* MBEDTLS_AES_C */
|
|
@ -0,0 +1,429 @@
|
|||
/*
|
||||
* CCM cipher mode based on 128 bit AES and CRYPTO hw acceleration
|
||||
*
|
||||
* Copyright (C) 2016, Silicon Labs, http://www.silabs.com
|
||||
* 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.
|
||||
*/
|
||||
|
||||
/*
|
||||
* Definition of CCM:
|
||||
* http://csrc.nist.gov/publications/nistpubs/800-38C/SP800-38C_updated-July20_2007.pdf
|
||||
* RFC 3610 "Counter with CBC-MAC (CCM)"
|
||||
*
|
||||
* Related:
|
||||
* RFC 5116 "An Interface and Algorithms for Authenticated Encryption"
|
||||
*/
|
||||
|
||||
#if !defined(MBEDTLS_CONFIG_FILE)
|
||||
#include "mbedtls/config.h"
|
||||
#else
|
||||
#include MBEDTLS_CONFIG_FILE
|
||||
#endif
|
||||
|
||||
#if defined( MBEDTLS_CCM_C )
|
||||
|
||||
#if defined( MBEDTLS_CCM_ALT )
|
||||
|
||||
#if defined( MBEDTLS_SLCL_PLUGINS )
|
||||
|
||||
#include "em_device.h"
|
||||
#include "mbedtls/ccm.h"
|
||||
#include "mbedtls/aes.h"
|
||||
#include "sl_crypto.h"
|
||||
#include "aesdrv_internal.h"
|
||||
#include "cryptodrv_internal.h"
|
||||
#include "em_assert.h"
|
||||
#include <string.h>
|
||||
|
||||
#if defined(MBEDTLS_SELF_TEST) && defined(MBEDTLS_AES_C)
|
||||
#if defined(MBEDTLS_PLATFORM_C)
|
||||
#include "mbedtls/platform.h"
|
||||
#else
|
||||
#include <stdio.h>
|
||||
#define mbedtls_printf printf
|
||||
#endif /* MBEDTLS_PLATFORM_C */
|
||||
#endif /* MBEDTLS_SELF_TEST && MBEDTLS_AES_C */
|
||||
|
||||
/* 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;
|
||||
}
|
||||
|
||||
/*
|
||||
* Initialize context
|
||||
*/
|
||||
void mbedtls_ccm_init( mbedtls_ccm_context *ctx )
|
||||
{
|
||||
memset( ctx, 0, sizeof( mbedtls_ccm_context ) );
|
||||
|
||||
AESDRV_Init ( &ctx->aesdrv_ctx );
|
||||
AESDRV_SetDeviceInstance ( &ctx->aesdrv_ctx, 0 );
|
||||
AESDRV_SetIoMode ( &ctx->aesdrv_ctx, aesdrvIoModeCore, 0 );
|
||||
}
|
||||
|
||||
int mbedtls_ccm_setkey( mbedtls_ccm_context *ctx,
|
||||
mbedtls_cipher_id_t cipher,
|
||||
const unsigned char *key,
|
||||
unsigned int keybits )
|
||||
{
|
||||
if ( cipher != MBEDTLS_CIPHER_ID_AES )
|
||||
return( MBEDTLS_ERR_CCM_BAD_INPUT );
|
||||
|
||||
switch( keybits )
|
||||
{
|
||||
case 128:
|
||||
break;
|
||||
case 192:
|
||||
case 256:
|
||||
return( MBEDTLS_ERR_AES_INVALID_KEY_LENGTH );
|
||||
default:
|
||||
return( MBEDTLS_ERR_CCM_BAD_INPUT );
|
||||
}
|
||||
|
||||
ctx->keybits = keybits;
|
||||
memcpy(ctx->key, key, keybits/8);
|
||||
|
||||
return( 0 );
|
||||
}
|
||||
|
||||
/*
|
||||
* Set the device instance of an CCM context.
|
||||
*/
|
||||
int mbedtls_ccm_set_device_instance(mbedtls_ccm_context *ctx,
|
||||
unsigned int devno)
|
||||
{
|
||||
#if defined(AES_COUNT) && (AES_COUNT > 0)
|
||||
(void) ctx;
|
||||
if ((devno > AES_COUNT) || (devno != 0))
|
||||
return( MBEDTLS_ERR_CCM_BAD_INPUT );
|
||||
else
|
||||
return( 0 );
|
||||
#endif
|
||||
|
||||
#if defined(CRYPTO_COUNT) && (CRYPTO_COUNT > 0)
|
||||
if (devno > CRYPTO_COUNT)
|
||||
return( MBEDTLS_ERR_CCM_BAD_INPUT );
|
||||
|
||||
return cryptodrvSetDeviceInstance( &ctx->aesdrv_ctx.cryptodrvContext,
|
||||
devno );
|
||||
#endif /* #if defined(CRYPTO_COUNT) && (CRYPTO_COUNT > 0) */
|
||||
}
|
||||
|
||||
#if defined( MBEDTLS_INCLUDE_ASYNCH_API )
|
||||
|
||||
/*
|
||||
* Set an CCM context in asynchronous mode.
|
||||
*/
|
||||
int mbedtls_ccm_set_asynch( mbedtls_ccm_context *ctx,
|
||||
mbedtls_ccm_asynch_context *asynch_ctx,
|
||||
mbedtls_asynch_callback asynch_callback,
|
||||
void* asynch_callback_user_arg )
|
||||
{
|
||||
Ecode_t status;
|
||||
AESDRV_CCM_AsynchContext_t *aesdrv_asynch_ctx =
|
||||
asynch_ctx ? &asynch_ctx->aesdrv_asynch_ctx : 0;
|
||||
|
||||
status = AESDRV_SetAsynchMode(&ctx->aesdrv_ctx,
|
||||
cipherModeCcm,
|
||||
aesdrv_asynch_ctx,
|
||||
(AESDRV_AsynchCallback_t) asynch_callback,
|
||||
asynch_callback_user_arg);
|
||||
if (status != ECODE_OK)
|
||||
{
|
||||
return (int)status;
|
||||
}
|
||||
|
||||
return( 0 );
|
||||
}
|
||||
|
||||
#endif /* #if defined( MBEDTLS_INCLUDE_ASYNCH_API ) */
|
||||
|
||||
/*
|
||||
* Set the device I/O mode of an CCM context.
|
||||
*/
|
||||
int mbedtls_ccm_set_device_io_mode( mbedtls_ccm_context *ctx,
|
||||
mbedtls_device_io_mode mode,
|
||||
mbedtls_device_io_mode_specific *specific )
|
||||
{
|
||||
return AESDRV_SetIoMode(&ctx->aesdrv_ctx,
|
||||
(AESDRV_IoMode_t) mode,
|
||||
(AESDRV_IoModeSpecific_t*) specific);
|
||||
}
|
||||
|
||||
/*
|
||||
* Free context
|
||||
*/
|
||||
void mbedtls_ccm_free( mbedtls_ccm_context *ctx )
|
||||
{
|
||||
AESDRV_DeInit ( &ctx->aesdrv_ctx );
|
||||
|
||||
mbedtls_zeroize( ctx, sizeof( mbedtls_ccm_context ) );
|
||||
}
|
||||
|
||||
/*
|
||||
* Authenticated encryption
|
||||
*/
|
||||
int mbedtls_ccm_encrypt_and_tag( mbedtls_ccm_context *ctx, size_t length,
|
||||
const unsigned char *iv, size_t iv_len,
|
||||
const unsigned char *add, size_t add_len,
|
||||
const unsigned char *input, unsigned char *output,
|
||||
unsigned char *tag, size_t tag_len )
|
||||
{
|
||||
Ecode_t ecode;
|
||||
|
||||
/*
|
||||
* Check length requirements: SP800-38C A.1
|
||||
* Additional requirement: a < 2^16 - 2^8 to simplify the code.
|
||||
* 'length' checked later (when writing it to the first block)
|
||||
*/
|
||||
if( tag_len < 4 || tag_len > 16 || tag_len % 2 != 0 )
|
||||
return( MBEDTLS_ERR_CCM_BAD_INPUT );
|
||||
|
||||
/* Also implies q is within bounds */
|
||||
if( iv_len < 7 || iv_len > 13 )
|
||||
return( MBEDTLS_ERR_CCM_BAD_INPUT );
|
||||
|
||||
if( add_len > 0xFF00 )
|
||||
return( MBEDTLS_ERR_CCM_BAD_INPUT );
|
||||
|
||||
ecode = AESDRV_CCM(&ctx->aesdrv_ctx,
|
||||
input, output, length,
|
||||
add, add_len,
|
||||
(uint8_t*)ctx->key, 128/8,
|
||||
iv, iv_len,
|
||||
tag, tag_len,
|
||||
true);
|
||||
|
||||
return ( ECODE_OK == ecode ? 0 :
|
||||
( MBEDTLS_ECODE_AESDRV_INVALID_PARAM == ecode ?
|
||||
MBEDTLS_ERR_CCM_BAD_INPUT : (int)ecode
|
||||
) );
|
||||
}
|
||||
|
||||
/*
|
||||
* Authenticated decryption
|
||||
*/
|
||||
int mbedtls_ccm_auth_decrypt( mbedtls_ccm_context *ctx, size_t length,
|
||||
const unsigned char *iv, size_t iv_len,
|
||||
const unsigned char *add, size_t add_len,
|
||||
const unsigned char *input, unsigned char *output,
|
||||
const unsigned char *tag, size_t tag_len )
|
||||
{
|
||||
Ecode_t ecode;
|
||||
|
||||
/*
|
||||
* Check length requirements: SP800-38C A.1
|
||||
* Additional requirement: a < 2^16 - 2^8 to simplify the code.
|
||||
* 'length' checked later (when writing it to the first block)
|
||||
*/
|
||||
if( tag_len < 4 || tag_len > 16 || tag_len % 2 != 0 )
|
||||
return( MBEDTLS_ERR_CCM_BAD_INPUT );
|
||||
|
||||
/* Also implies q is within bounds */
|
||||
if( iv_len < 7 || iv_len > 13 )
|
||||
return( MBEDTLS_ERR_CCM_BAD_INPUT );
|
||||
|
||||
if( add_len > 0xFF00 )
|
||||
return( MBEDTLS_ERR_CCM_BAD_INPUT );
|
||||
|
||||
ecode = AESDRV_CCM(&ctx->aesdrv_ctx,
|
||||
input, output, length,
|
||||
add, add_len,
|
||||
(uint8_t*)ctx->key, 128/8,
|
||||
iv, iv_len,
|
||||
(uint8_t*)tag, tag_len,
|
||||
false);
|
||||
|
||||
return ( ECODE_OK == ecode ? 0 :
|
||||
( MBEDTLS_ECODE_AESDRV_AUTHENTICATION_FAILED == ecode ?
|
||||
MBEDTLS_ERR_CCM_AUTH_FAILED :
|
||||
( MBEDTLS_ECODE_AESDRV_INVALID_PARAM == ecode ?
|
||||
MBEDTLS_ERR_CCM_BAD_INPUT : (int)ecode
|
||||
) ) );
|
||||
}
|
||||
|
||||
/*
|
||||
* CCM authenticated encryption optimized for BLE
|
||||
*/
|
||||
int mbedtls_ccm_encrypt_and_tag_ble( mbedtls_ccm_context *ctx,
|
||||
unsigned char *data,
|
||||
size_t length,
|
||||
const unsigned char *iv,
|
||||
unsigned char header,
|
||||
unsigned char *tag )
|
||||
{
|
||||
Ecode_t ecode;
|
||||
|
||||
ecode = AESDRV_CCMBLE(&ctx->aesdrv_ctx,
|
||||
data,
|
||||
length,
|
||||
header,
|
||||
(uint8_t*)ctx->key,
|
||||
iv,
|
||||
tag,
|
||||
true);
|
||||
|
||||
return ( ECODE_OK == ecode ? 0 :
|
||||
( MBEDTLS_ECODE_AESDRV_INVALID_PARAM == ecode ?
|
||||
MBEDTLS_ERR_CCM_BAD_INPUT : (int)ecode
|
||||
) );
|
||||
}
|
||||
|
||||
/*
|
||||
* CCM buffer authenticated decryption optimized for BLE
|
||||
*/
|
||||
int mbedtls_ccm_auth_decrypt_ble( mbedtls_ccm_context *ctx,
|
||||
unsigned char *data,
|
||||
size_t length,
|
||||
const unsigned char *iv,
|
||||
unsigned char header,
|
||||
unsigned char *tag )
|
||||
{
|
||||
Ecode_t ecode;
|
||||
|
||||
ecode = AESDRV_CCMBLE(&ctx->aesdrv_ctx,
|
||||
data,
|
||||
length,
|
||||
header,
|
||||
(uint8_t*)ctx->key,
|
||||
iv,
|
||||
tag,
|
||||
false );
|
||||
|
||||
return ( ECODE_OK == ecode ? 0 :
|
||||
( MBEDTLS_ECODE_AESDRV_AUTHENTICATION_FAILED == ecode ?
|
||||
MBEDTLS_ERR_CCM_AUTH_FAILED :
|
||||
( MBEDTLS_ECODE_AESDRV_INVALID_PARAM == ecode ?
|
||||
MBEDTLS_ERR_CCM_BAD_INPUT : (int)ecode
|
||||
) ) );
|
||||
}
|
||||
|
||||
#if defined(MBEDTLS_SELF_TEST) && defined(MBEDTLS_AES_C)
|
||||
/*
|
||||
* Examples 1 to 3 from SP800-38C Appendix C
|
||||
*/
|
||||
|
||||
#define NB_TESTS 3
|
||||
|
||||
/*
|
||||
* The data is the same for all tests, only the used length changes
|
||||
*/
|
||||
static const unsigned char key[] = {
|
||||
0x40, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47,
|
||||
0x48, 0x49, 0x4a, 0x4b, 0x4c, 0x4d, 0x4e, 0x4f
|
||||
};
|
||||
|
||||
static const unsigned char iv[] = {
|
||||
0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17,
|
||||
0x18, 0x19, 0x1a, 0x1b
|
||||
};
|
||||
|
||||
static const unsigned char ad[] = {
|
||||
0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
|
||||
0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
|
||||
0x10, 0x11, 0x12, 0x13
|
||||
};
|
||||
|
||||
static const unsigned char msg[] = {
|
||||
0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27,
|
||||
0x28, 0x29, 0x2a, 0x2b, 0x2c, 0x2d, 0x2e, 0x2f,
|
||||
0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37,
|
||||
};
|
||||
|
||||
static const size_t iv_len [NB_TESTS] = { 7, 8, 12 };
|
||||
static const size_t add_len[NB_TESTS] = { 8, 16, 20 };
|
||||
static const size_t msg_len[NB_TESTS] = { 4, 16, 24 };
|
||||
static const size_t tag_len[NB_TESTS] = { 4, 6, 8 };
|
||||
|
||||
static const unsigned char res[NB_TESTS][32] = {
|
||||
{ 0x71, 0x62, 0x01, 0x5b, 0x4d, 0xac, 0x25, 0x5d },
|
||||
{ 0xd2, 0xa1, 0xf0, 0xe0, 0x51, 0xea, 0x5f, 0x62,
|
||||
0x08, 0x1a, 0x77, 0x92, 0x07, 0x3d, 0x59, 0x3d,
|
||||
0x1f, 0xc6, 0x4f, 0xbf, 0xac, 0xcd },
|
||||
{ 0xe3, 0xb2, 0x01, 0xa9, 0xf5, 0xb7, 0x1a, 0x7a,
|
||||
0x9b, 0x1c, 0xea, 0xec, 0xcd, 0x97, 0xe7, 0x0b,
|
||||
0x61, 0x76, 0xaa, 0xd9, 0xa4, 0x42, 0x8a, 0xa5,
|
||||
0x48, 0x43, 0x92, 0xfb, 0xc1, 0xb0, 0x99, 0x51 }
|
||||
};
|
||||
|
||||
int mbedtls_ccm_self_test( int verbose )
|
||||
{
|
||||
mbedtls_ccm_context ctx;
|
||||
unsigned char out[32];
|
||||
size_t i;
|
||||
int ret;
|
||||
|
||||
mbedtls_ccm_init( &ctx );
|
||||
|
||||
if( mbedtls_ccm_setkey( &ctx, MBEDTLS_CIPHER_ID_AES, key, 8 * sizeof key ) != 0 )
|
||||
{
|
||||
if( verbose != 0 )
|
||||
mbedtls_printf( " CCM: setup failed" );
|
||||
|
||||
return( 1 );
|
||||
}
|
||||
|
||||
for( i = 0; i < NB_TESTS; i++ )
|
||||
{
|
||||
if( verbose != 0 )
|
||||
mbedtls_printf( " CCM-AES #%u: ", (unsigned int) i + 1 );
|
||||
|
||||
ret = mbedtls_ccm_encrypt_and_tag( &ctx, msg_len[i],
|
||||
iv, iv_len[i], ad, add_len[i],
|
||||
msg, out,
|
||||
out + msg_len[i], tag_len[i] );
|
||||
|
||||
if( ret != 0 ||
|
||||
memcmp( out, res[i], msg_len[i] + tag_len[i] ) != 0 )
|
||||
{
|
||||
if( verbose != 0 )
|
||||
mbedtls_printf( "failed\n" );
|
||||
|
||||
return( 1 );
|
||||
}
|
||||
|
||||
ret = mbedtls_ccm_auth_decrypt( &ctx, msg_len[i],
|
||||
iv, iv_len[i], ad, add_len[i],
|
||||
res[i], out,
|
||||
res[i] + msg_len[i], tag_len[i] );
|
||||
|
||||
if( ret != 0 ||
|
||||
memcmp( out, msg, msg_len[i] ) != 0 )
|
||||
{
|
||||
if( verbose != 0 )
|
||||
mbedtls_printf( "failed\n" );
|
||||
|
||||
return( 1 );
|
||||
}
|
||||
|
||||
if( verbose != 0 )
|
||||
mbedtls_printf( "passed\n" );
|
||||
}
|
||||
|
||||
mbedtls_ccm_free( &ctx );
|
||||
|
||||
if( verbose != 0 )
|
||||
mbedtls_printf( "\n" );
|
||||
|
||||
return( 0 );
|
||||
}
|
||||
|
||||
#endif /* MBEDTLS_SELF_TEST && MBEDTLS_AES_C */
|
||||
|
||||
#endif /* MBEDTLS_SLCL_PLUGINS */
|
||||
|
||||
#endif /* MBEDTLS_CCM_ALT */
|
||||
|
||||
#endif /* MBEDTLS_CCM_C */
|
|
@ -0,0 +1,435 @@
|
|||
/**
|
||||
* CMAC cipher mode based on 128 bit AES and CRYPTO hw acceleration
|
||||
*
|
||||
* Copyright (C) 2016, Silicon Labs, 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.
|
||||
*/
|
||||
|
||||
/*
|
||||
* This file implements CMAC (Cipher-based Message Authentication Code)
|
||||
* cipher mode encryption/decryption based on 128 bit AES.
|
||||
* For a general description please see
|
||||
* https://en.wikipedia.org/wiki/CMAC
|
||||
* or for detailed specification see
|
||||
* http://csrc.nist.gov/publications/nistpubs/800-38B/SP_800-38B.pdf
|
||||
* http://dl.acm.org/citation.cfm?id=2206249
|
||||
*/
|
||||
|
||||
#if !defined(MBEDTLS_CONFIG_FILE)
|
||||
#include "mbedtls/config.h"
|
||||
#else
|
||||
#include MBEDTLS_CONFIG_FILE
|
||||
#endif
|
||||
|
||||
#if defined( MBEDTLS_CMAC_C )
|
||||
|
||||
#if defined( MBEDTLS_CMAC_ALT )
|
||||
|
||||
#include "em_device.h"
|
||||
|
||||
#if defined(CRYPTO_COUNT) && (CRYPTO_COUNT > 0)
|
||||
|
||||
#if defined( MBEDTLS_SLCL_PLUGINS )
|
||||
|
||||
#include "mbedtls/cmac.h"
|
||||
#include "mbedtls/aes.h"
|
||||
#include "sl_crypto.h"
|
||||
#include "aesdrv_internal.h"
|
||||
#include "cryptodrv_internal.h"
|
||||
#include "em_assert.h"
|
||||
#include <string.h>
|
||||
|
||||
#if defined(MBEDTLS_SELF_TEST) && defined(MBEDTLS_AES_C)
|
||||
#if defined(MBEDTLS_PLATFORM_C)
|
||||
#include "mbedtls/platform.h"
|
||||
#else
|
||||
#include <stdio.h>
|
||||
#define mbedtls_printf printf
|
||||
#endif /* MBEDTLS_PLATFORM_C */
|
||||
#endif /* MBEDTLS_SELF_TEST && MBEDTLS_AES_C */
|
||||
|
||||
/* 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;
|
||||
}
|
||||
|
||||
/*
|
||||
* Initialize context
|
||||
*/
|
||||
void mbedtls_cmac_init( mbedtls_cmac_context *ctx )
|
||||
{
|
||||
memset( ctx, 0, sizeof( mbedtls_cmac_context ) );
|
||||
|
||||
AESDRV_Init ( &ctx->aesdrv_ctx );
|
||||
AESDRV_SetDeviceInstance ( &ctx->aesdrv_ctx, 0 );
|
||||
AESDRV_SetIoMode ( &ctx->aesdrv_ctx, aesdrvIoModeCore, 0 );
|
||||
}
|
||||
|
||||
/*
|
||||
* CMAC key setup
|
||||
*/
|
||||
int mbedtls_cmac_setkey( mbedtls_cmac_context *ctx,
|
||||
mbedtls_cipher_id_t cipher,
|
||||
const unsigned char *key,
|
||||
unsigned int keybits )
|
||||
{
|
||||
if ( cipher != MBEDTLS_CIPHER_ID_AES )
|
||||
return( MBEDTLS_ERR_CMAC_BAD_INPUT );
|
||||
|
||||
switch( keybits )
|
||||
{
|
||||
case 128:
|
||||
break;
|
||||
case 192:
|
||||
case 256:
|
||||
return( MBEDTLS_ERR_AES_INVALID_KEY_LENGTH );
|
||||
default:
|
||||
return( MBEDTLS_ERR_CMAC_BAD_INPUT );
|
||||
}
|
||||
|
||||
ctx->keybits = keybits;
|
||||
memcpy(ctx->key, key, keybits/8);
|
||||
|
||||
return( 0 );
|
||||
}
|
||||
|
||||
/*
|
||||
* Set the device instance of an CMAC context.
|
||||
*/
|
||||
int mbedtls_cmac_set_device_instance(mbedtls_cmac_context *ctx,
|
||||
unsigned int devno)
|
||||
{
|
||||
#if defined(AES_COUNT) && (AES_COUNT > 0)
|
||||
(void) ctx;
|
||||
if ((devno > AES_COUNT) || (devno != 0))
|
||||
return( MBEDTLS_ERR_CMAC_BAD_INPUT );
|
||||
else
|
||||
return( 0 );
|
||||
#endif
|
||||
|
||||
#if defined(CRYPTO_COUNT) && (CRYPTO_COUNT > 0)
|
||||
if (devno > CRYPTO_COUNT)
|
||||
return( MBEDTLS_ERR_CMAC_BAD_INPUT );
|
||||
|
||||
return cryptodrvSetDeviceInstance( &ctx->aesdrv_ctx.cryptodrvContext,
|
||||
devno );
|
||||
#endif /* #if defined(CRYPTO_COUNT) && (CRYPTO_COUNT > 0) */
|
||||
}
|
||||
|
||||
#if defined( MBEDTLS_INCLUDE_ASYNCH_API )
|
||||
/*
|
||||
* Set an CMAC context in asynchronous mode.
|
||||
*/
|
||||
int mbedtls_cmac_set_asynch( mbedtls_cmac_context *ctx,
|
||||
mbedtls_cmac_asynch_context *asynch_ctx,
|
||||
mbedtls_asynch_callback asynch_callback,
|
||||
void* asynch_callback_user_arg )
|
||||
{
|
||||
Ecode_t status;
|
||||
|
||||
AESDRV_CMAC_AsynchContext_t *aesdrv_asynch_ctx =
|
||||
asynch_ctx ? &asynch_ctx->aesdrv_asynch_ctx : 0;
|
||||
|
||||
status = AESDRV_SetAsynchMode(&ctx->aesdrv_ctx,
|
||||
cipherModeCmac,
|
||||
aesdrv_asynch_ctx,
|
||||
(AESDRV_AsynchCallback_t) asynch_callback,
|
||||
asynch_callback_user_arg);
|
||||
if (status != ECODE_OK)
|
||||
{
|
||||
return (int)status;
|
||||
}
|
||||
|
||||
return( 0 );
|
||||
}
|
||||
#endif /* #if defined( MBEDTLS_INCLUDE_ASYNCH_API ) */
|
||||
|
||||
/*
|
||||
* Free context
|
||||
*/
|
||||
void mbedtls_cmac_free( mbedtls_cmac_context *ctx )
|
||||
{
|
||||
AESDRV_DeInit ( &ctx->aesdrv_ctx );
|
||||
|
||||
mbedtls_zeroize( ctx, sizeof( mbedtls_cmac_context ) );
|
||||
}
|
||||
|
||||
/*
|
||||
* Generate CMAC tag
|
||||
*/
|
||||
int mbedtls_cmac_generate_tag( mbedtls_cmac_context *ctx,
|
||||
const unsigned char *data,
|
||||
size_t data_len,
|
||||
unsigned char *tag,
|
||||
size_t tag_len )
|
||||
{
|
||||
Ecode_t ecode = AESDRV_CMAC(&ctx->aesdrv_ctx,
|
||||
data, data_len,
|
||||
(uint8_t*)ctx->key, 128/8,
|
||||
tag, tag_len,
|
||||
true);
|
||||
return ( ECODE_OK == ecode ? 0 :
|
||||
( MBEDTLS_ECODE_AESDRV_INVALID_PARAM == ecode ?
|
||||
MBEDTLS_ERR_CMAC_BAD_INPUT : (int)ecode
|
||||
) );
|
||||
}
|
||||
|
||||
/*
|
||||
* Verify CMAC tag
|
||||
*
|
||||
*/
|
||||
int mbedtls_cmac_verify_tag( mbedtls_cmac_context *ctx,
|
||||
const unsigned char *data,
|
||||
size_t data_len,
|
||||
unsigned char *tag,
|
||||
size_t tag_len )
|
||||
{
|
||||
Ecode_t ecode = AESDRV_CMAC(&ctx->aesdrv_ctx,
|
||||
data, data_len,
|
||||
(uint8_t*)ctx->key, 128/8,
|
||||
tag, tag_len,
|
||||
false);
|
||||
return ( ECODE_OK == ecode ? 0 :
|
||||
( MBEDTLS_ECODE_AESDRV_AUTHENTICATION_FAILED == ecode ?
|
||||
MBEDTLS_ERR_CMAC_AUTH_FAILED :
|
||||
( MBEDTLS_ECODE_AESDRV_INVALID_PARAM == ecode ?
|
||||
MBEDTLS_ERR_CMAC_BAD_INPUT : (int)ecode
|
||||
) ) );
|
||||
}
|
||||
|
||||
#if defined(MBEDTLS_SELF_TEST) && defined(MBEDTLS_CMAC_C)
|
||||
|
||||
/*
|
||||
* CMAC self test
|
||||
*/
|
||||
|
||||
#include "timing.h"
|
||||
#include <ctype.h>
|
||||
|
||||
#define ASYNCH_TEST_LEVEL (1)
|
||||
#define ASYNCH_TEST_INIT(asynch_type) while (false)
|
||||
#define ASYNCH_TEST_SET_READY while (false)
|
||||
#define ASYNCH_TEST_HANDLE_COMPLETION while (false)
|
||||
|
||||
typedef struct {
|
||||
char* key;
|
||||
int keylen;
|
||||
char* plaintext;
|
||||
int plaintextlen;
|
||||
char* authtag;
|
||||
int authtaglen;
|
||||
} cmac_test_vector_t;
|
||||
|
||||
static const cmac_test_vector_t cmac_test_vectors [];
|
||||
static int hex2uint8array(uint8_t* u8a, int u8alen, const char* hex);
|
||||
|
||||
/* Test the CMAC algorithm. */
|
||||
static int test_single_cmac (const cmac_test_vector_t* tv,
|
||||
int verbose )
|
||||
{
|
||||
uint8_t* key = (uint8_t*) malloc (tv->keylen);
|
||||
uint8_t* message = (uint8_t*) malloc (tv->plaintextlen+16);
|
||||
uint8_t* authTagExpected = (uint8_t*) malloc (16);
|
||||
uint8_t* authTag = (uint8_t*) malloc (16);
|
||||
int ret;
|
||||
int cycles;
|
||||
mbedtls_cmac_context ctx;
|
||||
int asynchTest;
|
||||
#if defined( MBEDTLS_INCLUDE_ASYNCH_API )
|
||||
ASYNCH_TEST_INIT(mbedtls_cmac_asynch_context);
|
||||
#endif /* #if defined( MBEDTLS_INCLUDE_ASYNCH_API ) */
|
||||
|
||||
mbedtls_cmac_init( &ctx );
|
||||
|
||||
if ( (NULL==key) ||
|
||||
(NULL==message) ||
|
||||
(NULL==authTag) ||
|
||||
(NULL==authTagExpected) )
|
||||
{
|
||||
if (verbose)
|
||||
mbedtls_printf("ERROR %s, %d: Unable to allocate memory buffers.\n",
|
||||
__FILE__, __LINE__);
|
||||
return -1;
|
||||
}
|
||||
|
||||
mbedtls_timing_init();
|
||||
|
||||
for (asynchTest=0; asynchTest<ASYNCH_TEST_LEVEL; asynchTest++)
|
||||
{
|
||||
hex2uint8array(key, tv->keylen, tv->key);
|
||||
hex2uint8array(message, tv->plaintextlen, tv->plaintext);
|
||||
hex2uint8array(authTagExpected, tv->authtaglen, tv->authtag);
|
||||
|
||||
/* Set key */
|
||||
ret = mbedtls_cmac_setkey(&ctx, MBEDTLS_CIPHER_ID_AES, key, 128);
|
||||
if (0 != ret)
|
||||
{
|
||||
mbedtls_printf("mbedtls_cmac_setkey returned error code 0x%x.\n", ret);
|
||||
ret = -1;
|
||||
goto exit;
|
||||
}
|
||||
|
||||
ASYNCH_TEST_SET_READY;
|
||||
cycles = mbedtls_timing_hardclock();
|
||||
|
||||
/* Perform the CMAC */
|
||||
ret = mbedtls_cmac_generate_tag(&ctx,
|
||||
message,
|
||||
tv->plaintextlen*8,
|
||||
authTag,
|
||||
tv->authtaglen*8);
|
||||
|
||||
ASYNCH_TEST_HANDLE_COMPLETION;
|
||||
|
||||
if (0 != ret)
|
||||
{
|
||||
mbedtls_printf("mbedtls_cmac_encrypt_tag returned error code 0x%x.\n", ret);
|
||||
ret = -1;
|
||||
goto exit;
|
||||
}
|
||||
|
||||
if (0 != memcmp(authTagExpected, authTag, tv->authtaglen))
|
||||
{
|
||||
mbedtls_printf("mbedtls_cmac_encrypt_tag failed to produce expected tag.\n");
|
||||
ret = -1;
|
||||
goto exit;
|
||||
}
|
||||
|
||||
if (verbose)
|
||||
mbedtls_printf("%10d %12d %6d %s\n",
|
||||
tv->authtaglen, tv->plaintextlen, cycles,
|
||||
asynchTest? "Yes" : "No");
|
||||
}
|
||||
exit:
|
||||
mbedtls_cmac_free( &ctx );
|
||||
|
||||
if (key) free(key);
|
||||
if (message) free(message);
|
||||
if (authTag) free(authTag);
|
||||
if (authTagExpected) free(authTagExpected);
|
||||
|
||||
return( ret );
|
||||
}
|
||||
|
||||
int mbedtls_cmac_self_test( int verbose )
|
||||
{
|
||||
const cmac_test_vector_t* tv = cmac_test_vectors;
|
||||
|
||||
mbedtls_printf("\nCMAC Hashing Test AES-128\n"
|
||||
"AuthTagLen PlaintextLen Cycles Asynch?\n");
|
||||
while (tv->key)
|
||||
{
|
||||
if (test_single_cmac( tv, verbose ) != 0)
|
||||
return -1;
|
||||
tv++;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int hex2uint8array(uint8_t* u8a, int u8alen, const char* hex)
|
||||
{
|
||||
int i, j, k, c;
|
||||
int num;
|
||||
|
||||
if ((hex == NULL) || (*hex == '\0')) return(0);
|
||||
|
||||
for (i=0; isxdigit((unsigned char) hex[i]); i++)
|
||||
;
|
||||
|
||||
num=i;
|
||||
|
||||
if (num % 2)
|
||||
/* hex array must be a multiple of 2 */
|
||||
return -1;
|
||||
|
||||
if (u8a == NULL) return(num);
|
||||
|
||||
if (u8alen != num/2)
|
||||
/* size of uint8 array must be half the size of the hex array. */
|
||||
return -1;
|
||||
|
||||
memset(u8a, 0, u8alen);
|
||||
|
||||
for (i = 0; i < num/2; i++)
|
||||
{
|
||||
for (j=0; j<2; j++)
|
||||
{
|
||||
c=hex[i*2+j];
|
||||
if ((c >= '0') && (c <= '9')) k=c-'0';
|
||||
else if ((c >= 'a') && (c <= 'f')) k=c-'a'+10;
|
||||
else if ((c >= 'A') && (c <= 'F')) k=c-'A'+10;
|
||||
else k=0; /* paranoia */
|
||||
u8a[i]=(u8a[i]<<4)|k;
|
||||
}
|
||||
}
|
||||
return(num);
|
||||
}
|
||||
|
||||
/*
|
||||
** From file CMACGenAES128.rsp :
|
||||
|
||||
# CAVS 14.0
|
||||
# CMAC Encrypt with keysize 128 test information
|
||||
# Generated on Fri Aug 31 11:23:06 2012
|
||||
*/
|
||||
static const cmac_test_vector_t cmac_test_vectors [] =
|
||||
{
|
||||
{ "2b7e151628aed2a6abf7158809cf4f3c",
|
||||
16,
|
||||
"",
|
||||
0,
|
||||
"bb1d6929e95937287fa37d129b756746",
|
||||
16
|
||||
},
|
||||
{ "8eeca0d146fd09ffbbe0d47edcddfcec",
|
||||
16,
|
||||
"",
|
||||
0,
|
||||
"c3642ce5",
|
||||
4
|
||||
},
|
||||
{ "f7f922c86706277a4e98d28e1197413b",
|
||||
16,
|
||||
"33ce44bdb1ea6fffe5a29004e2cbf66c",
|
||||
16,
|
||||
"b8768355644df5a9fdff2def763f63",
|
||||
15
|
||||
},
|
||||
{ "6533780fc328a88d605268d62f295dc6",
|
||||
16,
|
||||
"02749f4f9ad82fa7ba41d935a6f1aa6376b30b8775b6445ac89b3eac50cd8d56",
|
||||
32,
|
||||
"0bfa134a",
|
||||
4
|
||||
},
|
||||
{ "e4abe343f98a2df09413c3defb85b56a",
|
||||
16,
|
||||
"f799876d19ac1b849a1a43fe9912bcaf6e1e3896ea58bcb2dfdc4716e379b440",
|
||||
32,
|
||||
"e08428dbbc13ff9432048c0ad95731",
|
||||
15
|
||||
},
|
||||
{0}
|
||||
};
|
||||
|
||||
#endif /* MBEDTLS_SELF_TEST && MBEDTLS_CMAC_C */
|
||||
|
||||
#endif /* MBEDTLS_SLCL_PLUGINS */
|
||||
|
||||
#endif /* #if defined(CRYPTO_COUNT) && (CRYPTO_COUNT > 0) */
|
||||
|
||||
#endif /* MBEDTLS_CMAC_ALT */
|
||||
|
||||
#endif /* MBEDTLS_CMAC_C */
|
File diff suppressed because it is too large
Load Diff
|
@ -0,0 +1,387 @@
|
|||
/*
|
||||
* FIPS-180-1 compliant SHA-1 implementation
|
||||
*
|
||||
* Copyright (C) 2016, Silicon Labs, http://www.silabs.com
|
||||
* 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.
|
||||
*/
|
||||
/*
|
||||
* This file includes an alternative implementation of the standard
|
||||
* mbedtls/libary/sha1.c using the CRYPTO hardware accelerator incorporated
|
||||
* in MCU devices from Silicon Laboratories.
|
||||
*/
|
||||
/*
|
||||
* The SHA-1 standard was published by NIST in 1993.
|
||||
*
|
||||
* http://www.itl.nist.gov/fipspubs/fip180-1.htm
|
||||
*/
|
||||
|
||||
#if !defined(MBEDTLS_CONFIG_FILE)
|
||||
#include "mbedtls/config.h"
|
||||
#else
|
||||
#include MBEDTLS_CONFIG_FILE
|
||||
#endif
|
||||
|
||||
#if defined(MBEDTLS_SHA1_C)
|
||||
|
||||
#if defined(MBEDTLS_SHA1_ALT)
|
||||
|
||||
#if defined(MBEDTLS_SLCL_PLUGINS)
|
||||
|
||||
#include "em_device.h"
|
||||
|
||||
#if defined(CRYPTO_COUNT) && (CRYPTO_COUNT > 0)
|
||||
|
||||
#include "mbedtls/sha1.h"
|
||||
#include "cryptodrv_internal.h"
|
||||
#include "em_assert.h"
|
||||
#include <string.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;
|
||||
}
|
||||
|
||||
/*
|
||||
* 32-bit integer manipulation macros (big endian)
|
||||
*/
|
||||
#ifndef PUT_UINT32_BE
|
||||
#define PUT_UINT32_BE(n,b,i) \
|
||||
{ \
|
||||
(b)[(i) ] = (unsigned char) ( (n) >> 24 ); \
|
||||
(b)[(i) + 1] = (unsigned char) ( (n) >> 16 ); \
|
||||
(b)[(i) + 2] = (unsigned char) ( (n) >> 8 ); \
|
||||
(b)[(i) + 3] = (unsigned char) ( (n) ); \
|
||||
}
|
||||
#endif
|
||||
|
||||
void mbedtls_sha1_init( mbedtls_sha1_context *ctx )
|
||||
{
|
||||
memset( ctx, 0, sizeof( mbedtls_sha1_context ) );
|
||||
|
||||
/* Set device instance to 0 by default. */
|
||||
mbedtls_sha1_set_device_instance(ctx, 0);
|
||||
}
|
||||
|
||||
void mbedtls_sha1_free( mbedtls_sha1_context *ctx )
|
||||
{
|
||||
if( ctx == NULL )
|
||||
return;
|
||||
|
||||
mbedtls_zeroize( ctx, sizeof( mbedtls_sha1_context ) );
|
||||
}
|
||||
|
||||
/*
|
||||
* Set the device instance of an SHA context.
|
||||
*/
|
||||
int mbedtls_sha1_set_device_instance(mbedtls_sha1_context *ctx,
|
||||
unsigned int devno)
|
||||
{
|
||||
#if defined(CRYPTO_COUNT) && (CRYPTO_COUNT > 0)
|
||||
if (devno > CRYPTO_COUNT)
|
||||
return( MBEDTLS_ERR_SHA1_BAD_INPUT );
|
||||
|
||||
return cryptodrvSetDeviceInstance( &ctx->cryptodrv_ctx, devno );
|
||||
#endif /* #if defined(CRYPTO_COUNT) && (CRYPTO_COUNT > 0) */
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief SHA-1 asynchronous context structure
|
||||
*/
|
||||
typedef struct
|
||||
{
|
||||
mbedtls_asynch_callback asynch_callback; /*!< Completion callback
|
||||
function pointer. */
|
||||
void* asynch_callback_user_arg; /*!< User defined parameter to
|
||||
completion callback. */
|
||||
}
|
||||
mbedtls_sha1_asynch_context;
|
||||
|
||||
/**
|
||||
* \brief Set an SHA1 context in asynchronous mode.
|
||||
*
|
||||
* \details
|
||||
* This function enables or disables asynchronous (non-blocking) mode of an
|
||||
* SHA1 context. In order to enable, the user must set the
|
||||
* @p asynch_ctx parameter to point to an asynchronous sha1 context structure
|
||||
* @ref mbedtls_sha1_asynch_context. Subsequent calls to the SHA1 API
|
||||
* functions with the specified context will behave asynchronously, i.e.
|
||||
* initiate the hardware to execute the operation and return as soon as
|
||||
* possible. The user may specify a callback function by setting the
|
||||
* @p asynch_callback parameter which will called when the operation has
|
||||
* completed.
|
||||
* In order to disable, the user must set the @p asynch_context parameter
|
||||
* to NULL. All subsequent calls to SHA1 API functions with the specified
|
||||
* context will block until the corresponding operation has completed, and
|
||||
* then return.
|
||||
*
|
||||
* \param ctx SHA1 context
|
||||
* \param asynch_ctx SHA1 asynchronous context structure
|
||||
* \param asynch_callback Asynchronous callback
|
||||
* \param user_arg User specific argument which will be
|
||||
* sent to callback.
|
||||
*
|
||||
* \return 0 if successful, or error code
|
||||
*/
|
||||
int mbedtls_sha1_set_asynch( mbedtls_sha1_context *ctx,
|
||||
mbedtls_sha1_asynch_context *asynch_ctx,
|
||||
mbedtls_asynch_callback asynch_callback,
|
||||
void* asynch_callback_user_arg )
|
||||
{
|
||||
(void) ctx;
|
||||
(void) asynch_ctx;
|
||||
(void) asynch_callback;
|
||||
(void) asynch_callback_user_arg;
|
||||
|
||||
/* Asynchronous mode is not supported yet. */
|
||||
while(1);
|
||||
}
|
||||
|
||||
void mbedtls_sha1_clone( mbedtls_sha1_context *dst,
|
||||
const mbedtls_sha1_context *src )
|
||||
{
|
||||
(void) dst;
|
||||
(void) src;
|
||||
|
||||
/* Cloning a SHA256 CRYPTODRV context is not supported. */
|
||||
while(1);
|
||||
}
|
||||
|
||||
/*
|
||||
* SHA-1 context setup
|
||||
*/
|
||||
int mbedtls_sha1_starts( mbedtls_sha1_context *ctx )
|
||||
{
|
||||
CRYPTODRV_Context_t* cryptodrv_ctx = &ctx->cryptodrv_ctx;
|
||||
CRYPTO_TypeDef* crypto = cryptodrv_ctx->device->crypto;
|
||||
uint32_t init_state[8];
|
||||
Ecode_t ecode;
|
||||
|
||||
/* Request CRYPTO usage. */
|
||||
ecode = CRYPTODRV_Arbitrate(cryptodrv_ctx);
|
||||
if (ECODE_OK != ecode)
|
||||
{
|
||||
return ecode;
|
||||
}
|
||||
|
||||
/* Enter critial crypto region in order to initialize crypto for
|
||||
SHA operation. */
|
||||
ecode = CRYPTODRV_EnterCriticalRegion(cryptodrv_ctx);
|
||||
EFM_ASSERT(ECODE_OK == ecode); /* Assert critical region entry is ok. */
|
||||
|
||||
/* Setup CRYPTO for SHA-1 operation: */
|
||||
crypto->CTRL = CRYPTO_CTRL_SHA_SHA1;
|
||||
crypto->WAC = 0;
|
||||
|
||||
/* Set result width of MADD32 operation. */
|
||||
CRYPTO_ResultWidthSet(crypto, cryptoResult256Bits);
|
||||
|
||||
/* Clear sequence control registers */
|
||||
crypto->SEQCTRL = 0;
|
||||
crypto->SEQCTRLB = 0;
|
||||
|
||||
/* Setup the initial sha digest state */
|
||||
init_state[0] = 0x67452301;
|
||||
init_state[1] = 0xEFCDAB89;
|
||||
init_state[2] = 0x98BADCFE;
|
||||
init_state[3] = 0x10325476;
|
||||
init_state[4] = 0xC3D2E1F0;
|
||||
init_state[5] = 0x0;
|
||||
init_state[6] = 0x0;
|
||||
init_state[7] = 0x0;
|
||||
|
||||
/* Push init vector to crypto module */
|
||||
CRYPTO_DDataWrite(&crypto->DDATA1, init_state);
|
||||
|
||||
/* Initialize CRYPTO sequencer to execute main SHA instruction
|
||||
sequence. */
|
||||
CRYPTO_EXECUTE_3( crypto,
|
||||
CRYPTO_CMD_INSTR_DDATA1TODDATA0,
|
||||
CRYPTO_CMD_INSTR_DDATA1TODDATA2,
|
||||
CRYPTO_CMD_INSTR_SELDDATA0DDATA1 );
|
||||
|
||||
/* Load main SHA instruction sequence */
|
||||
CRYPTO_SEQ_LOAD_3( crypto,
|
||||
CRYPTO_CMD_INSTR_SHA,
|
||||
CRYPTO_CMD_INSTR_MADD32,
|
||||
CRYPTO_CMD_INSTR_DDATA0TODDATA1 );
|
||||
|
||||
ecode = CRYPTODRV_ExitCriticalRegion( cryptodrv_ctx );
|
||||
EFM_ASSERT(ECODE_OK == ecode); /* Assert critical region exit is ok. */
|
||||
|
||||
ctx->total[0] = 0;
|
||||
ctx->total[1] = 0;
|
||||
|
||||
return ( ECODE_OK == ecode ? 0 : (int)ecode );
|
||||
}
|
||||
|
||||
void mbedtls_sha1_process( mbedtls_sha1_context *ctx, const unsigned char data[64] )
|
||||
{
|
||||
CRYPTODRV_Context_t* cryptodrv_ctx = &ctx->cryptodrv_ctx;
|
||||
CRYPTO_TypeDef* crypto = cryptodrv_ctx->device->crypto;
|
||||
Ecode_t ecode;
|
||||
|
||||
ecode = CRYPTODRV_EnterCriticalRegion( cryptodrv_ctx );
|
||||
EFM_ASSERT(ECODE_OK == ecode); /* Assert critical region entry is ok. */
|
||||
|
||||
/* Write block to QDATA1. */
|
||||
/* Check data is 32bit aligned, if not move via aligned buffer before writing. */
|
||||
if ((uint32_t)data & 0x3)
|
||||
{
|
||||
uint32_t temp[16];
|
||||
memcpy(temp, data, 64);
|
||||
CRYPTO_QDataWrite(&crypto->QDATA1BIG, temp);
|
||||
}
|
||||
else
|
||||
{
|
||||
CRYPTO_QDataWrite(&crypto->QDATA1BIG, (uint32_t*) data);
|
||||
}
|
||||
|
||||
/* Execute SHA */
|
||||
crypto->CMD |= CRYPTO_CMD_SEQSTART;
|
||||
|
||||
ecode = CRYPTODRV_ExitCriticalRegion( cryptodrv_ctx );
|
||||
EFM_ASSERT(ECODE_OK == ecode); /* Assert critical region exit is ok. */
|
||||
}
|
||||
|
||||
/*
|
||||
* SHA-1 process buffer
|
||||
*/
|
||||
void mbedtls_sha1_update( mbedtls_sha1_context *ctx, const unsigned char *input, size_t ilen )
|
||||
{
|
||||
size_t fill;
|
||||
uint32_t left;
|
||||
|
||||
if( ilen == 0 )
|
||||
return;
|
||||
|
||||
left = ctx->total[0] & 0x3F;
|
||||
fill = 64 - left;
|
||||
|
||||
ctx->total[0] += (uint32_t) ilen;
|
||||
ctx->total[0] &= 0xFFFFFFFF;
|
||||
|
||||
if( ctx->total[0] < (uint32_t) ilen )
|
||||
ctx->total[1]++;
|
||||
|
||||
if( left && ilen >= fill )
|
||||
{
|
||||
memcpy( (void *) (ctx->buffer + left), input, fill );
|
||||
mbedtls_sha1_process( ctx, ctx->buffer );
|
||||
input += fill;
|
||||
ilen -= fill;
|
||||
left = 0;
|
||||
}
|
||||
|
||||
while( ilen >= 64 )
|
||||
{
|
||||
mbedtls_sha1_process( ctx, input );
|
||||
input += 64;
|
||||
ilen -= 64;
|
||||
}
|
||||
|
||||
if( ilen > 0 )
|
||||
memcpy( (void *) (ctx->buffer + left), input, ilen );
|
||||
}
|
||||
|
||||
static const unsigned char sha1_padding[64] =
|
||||
{
|
||||
0x80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
|
||||
};
|
||||
|
||||
/*
|
||||
* SHA-1 final digest
|
||||
*/
|
||||
void mbedtls_sha1_finish( mbedtls_sha1_context *ctx, unsigned char output[20] )
|
||||
{
|
||||
uint32_t last, padn;
|
||||
uint32_t high, low;
|
||||
unsigned char msglen[8];
|
||||
CRYPTODRV_Context_t* cryptodrv_ctx = &ctx->cryptodrv_ctx;
|
||||
CRYPTO_TypeDef* crypto = cryptodrv_ctx->device->crypto;
|
||||
Ecode_t ecode;
|
||||
|
||||
high = ( ctx->total[0] >> 29 )
|
||||
| ( ctx->total[1] << 3 );
|
||||
low = ( ctx->total[0] << 3 );
|
||||
|
||||
PUT_UINT32_BE( high, msglen, 0 );
|
||||
PUT_UINT32_BE( low, msglen, 4 );
|
||||
|
||||
last = ctx->total[0] & 0x3F;
|
||||
padn = ( last < 56 ) ? ( 56 - last ) : ( 120 - last );
|
||||
|
||||
mbedtls_sha1_update( ctx, sha1_padding, padn );
|
||||
mbedtls_sha1_update( ctx, msglen, 8 );
|
||||
|
||||
/* Enter critical CRYPTO region in order to read final SHA digest/state. */
|
||||
ecode = CRYPTODRV_EnterCriticalRegion( cryptodrv_ctx );
|
||||
EFM_ASSERT(ECODE_OK == ecode); /* Assert critical region entry is ok. */
|
||||
|
||||
/* Read the digest from crypto (big endian). */
|
||||
((uint32_t*)output)[0] = crypto->DDATA0BIG;
|
||||
((uint32_t*)output)[1] = crypto->DDATA0BIG;
|
||||
((uint32_t*)output)[2] = crypto->DDATA0BIG;
|
||||
((uint32_t*)output)[3] = crypto->DDATA0BIG;
|
||||
((uint32_t*)output)[4] = crypto->DDATA0BIG;
|
||||
{
|
||||
/* Read 3 remaining 32-bit words from DDATA0BIG (shift register). */
|
||||
volatile uint32_t temp;
|
||||
temp = crypto->DDATA0BIG;
|
||||
temp = crypto->DDATA0BIG;
|
||||
temp = crypto->DDATA0BIG;
|
||||
(void) temp;
|
||||
}
|
||||
|
||||
ecode = CRYPTODRV_ExitCriticalRegion( cryptodrv_ctx );
|
||||
|
||||
EFM_ASSERT(ECODE_OK == ecode); /* Assert critical region exit is ok. */
|
||||
|
||||
/* Finally release CRYPTO since SHA operation has completed. */
|
||||
ecode = CRYPTODRV_Release( cryptodrv_ctx );
|
||||
|
||||
EFM_ASSERT(ECODE_OK == ecode); /* Assert crypto release is ok. */
|
||||
}
|
||||
|
||||
/*
|
||||
* output = SHA-1( input buffer )
|
||||
*/
|
||||
int mbedtls_sha1( const unsigned char *input, size_t ilen, unsigned char output[20] )
|
||||
{
|
||||
mbedtls_sha1_context ctx;
|
||||
int ret;
|
||||
|
||||
mbedtls_sha1_init( &ctx );
|
||||
|
||||
ret = mbedtls_sha1_starts( &ctx );
|
||||
if (ret != 0)
|
||||
return ret;
|
||||
|
||||
mbedtls_sha1_update( &ctx, input, ilen );
|
||||
mbedtls_sha1_finish( &ctx, output );
|
||||
mbedtls_sha1_free( &ctx );
|
||||
|
||||
return( 0 );
|
||||
}
|
||||
|
||||
#endif /* #if defined(CRYPTO_COUNT) && (CRYPTO_COUNT > 0) */
|
||||
|
||||
#endif /* #if defined(MBEDTLS_SLCL_PLUGINS) */
|
||||
|
||||
#endif /* MBEDTLS_SHA1_ALT */
|
||||
|
||||
#endif /* MBEDTLS_SHA1_C */
|
|
@ -0,0 +1,398 @@
|
|||
/*
|
||||
* FIPS-180-2 compliant SHA-256 implementation
|
||||
*
|
||||
* Copyright (C) 2016, Silicon Labs, http://www.silabs.com
|
||||
* 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.
|
||||
*/
|
||||
/*
|
||||
* This file includes an alternative implementation of the standard
|
||||
* mbedtls/libary/sha256.c using the CRYPTO hardware accelerator incorporated
|
||||
* in MCU devices from Silicon Laboratories.
|
||||
*/
|
||||
/*
|
||||
* The SHA-256 Secure Hash Standard was published by NIST in 2002.
|
||||
*
|
||||
* http://csrc.nist.gov/publications/fips/fips180-2/fips180-2.pdf
|
||||
*/
|
||||
|
||||
#if !defined(MBEDTLS_CONFIG_FILE)
|
||||
#include "mbedtls/config.h"
|
||||
#else
|
||||
#include MBEDTLS_CONFIG_FILE
|
||||
#endif
|
||||
|
||||
#if defined(MBEDTLS_SHA256_C)
|
||||
|
||||
#if defined(MBEDTLS_SHA256_ALT)
|
||||
|
||||
#if defined(MBEDTLS_SLCL_PLUGINS)
|
||||
|
||||
#include "em_device.h"
|
||||
|
||||
#if defined(CRYPTO_COUNT) && (CRYPTO_COUNT > 0)
|
||||
|
||||
#include "mbedtls/sha256.h"
|
||||
#include "cryptodrv_internal.h"
|
||||
#include "em_assert.h"
|
||||
#include <string.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;
|
||||
}
|
||||
|
||||
/*
|
||||
* 32-bit integer manipulation macros (big endian)
|
||||
*/
|
||||
#ifndef PUT_UINT32_BE
|
||||
#define PUT_UINT32_BE(n,b,i) \
|
||||
do { \
|
||||
(b)[(i) ] = (unsigned char) ( (n) >> 24 ); \
|
||||
(b)[(i) + 1] = (unsigned char) ( (n) >> 16 ); \
|
||||
(b)[(i) + 2] = (unsigned char) ( (n) >> 8 ); \
|
||||
(b)[(i) + 3] = (unsigned char) ( (n) ); \
|
||||
} while( 0 )
|
||||
#endif
|
||||
|
||||
void mbedtls_sha256_init( mbedtls_sha256_context *ctx )
|
||||
{
|
||||
memset( ctx, 0, sizeof( mbedtls_sha256_context ) );
|
||||
|
||||
/* Set device instance to 0 by default. */
|
||||
mbedtls_sha256_set_device_instance(ctx, 0);
|
||||
}
|
||||
|
||||
void mbedtls_sha256_free( mbedtls_sha256_context *ctx )
|
||||
{
|
||||
if( ctx == NULL )
|
||||
return;
|
||||
|
||||
mbedtls_zeroize( ctx, sizeof( mbedtls_sha256_context ) );
|
||||
}
|
||||
|
||||
/*
|
||||
* Set the device instance of an SHA context.
|
||||
*/
|
||||
int mbedtls_sha256_set_device_instance(mbedtls_sha256_context *ctx,
|
||||
unsigned int devno)
|
||||
{
|
||||
#if defined(CRYPTO_COUNT) && (CRYPTO_COUNT > 0)
|
||||
if (devno > CRYPTO_COUNT)
|
||||
return( MBEDTLS_ERR_SHA256_BAD_INPUT );
|
||||
|
||||
return cryptodrvSetDeviceInstance( &ctx->cryptodrv_ctx, devno );
|
||||
#endif /* #if defined(CRYPTO_COUNT) && (CRYPTO_COUNT > 0) */
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief SHA-256 asynchronous context structure
|
||||
*/
|
||||
typedef struct
|
||||
{
|
||||
mbedtls_asynch_callback asynch_callback; /*!< Completion callback
|
||||
function pointer. */
|
||||
void* asynch_callback_user_arg; /*!< User defined parameter to
|
||||
completion callback. */
|
||||
}
|
||||
mbedtls_sha256_asynch_context;
|
||||
|
||||
/**
|
||||
* \brief Set an SHA256 context in asynchronous mode.
|
||||
*
|
||||
* \details
|
||||
* This function enables or disables asynchronous (non-blocking) mode of an
|
||||
* SHA256 context. In order to enable, the user must set the
|
||||
* @p asynch_ctx parameter to point to an asynchronous sha256 context
|
||||
* structure @ref mbedtls_sha256_asynch_context. Subsequent calls to the
|
||||
* SHA256 API functions with the specified context will behave asynchronously,
|
||||
* i.e. initiate the hardware to execute the operation and return as soon as
|
||||
* possible. The user may specify a callback function by setting the
|
||||
* @p asynch_callback parameter which will called when the operation has
|
||||
* completed.
|
||||
* In order to disable, the user must set the @p asynch_context parameter
|
||||
* to NULL. All subsequent calls to SHA256 API functions with the specified
|
||||
* context will block until the corresponding operation has completed, and
|
||||
* then return.
|
||||
*
|
||||
* \param ctx SHA256 context
|
||||
* \param asynch_ctx SHA256 asynchronous context structure
|
||||
* \param asynch_callback Asynchronous callback
|
||||
* \param user_arg User specific argument which will be
|
||||
* sent to callback.
|
||||
*
|
||||
* \return 0 if successful, or error code
|
||||
*/
|
||||
int mbedtls_sha256_set_asynch( mbedtls_sha256_context *ctx,
|
||||
mbedtls_sha256_asynch_context *asynch_ctx,
|
||||
mbedtls_asynch_callback asynch_callback,
|
||||
void* asynch_callback_user_arg )
|
||||
{
|
||||
(void) ctx;
|
||||
(void) asynch_ctx;
|
||||
(void) asynch_callback;
|
||||
(void) asynch_callback_user_arg;
|
||||
|
||||
/* Asynchronous mode is not supported yet. */
|
||||
while(1);
|
||||
}
|
||||
|
||||
void mbedtls_sha256_clone( mbedtls_sha256_context *dst,
|
||||
const mbedtls_sha256_context *src )
|
||||
{
|
||||
(void) dst;
|
||||
(void) src;
|
||||
|
||||
/* Cloning a SHA256 CRYPTODRV context is not supported. */
|
||||
while(1);
|
||||
}
|
||||
|
||||
/*
|
||||
* SHA-256 context setup
|
||||
*/
|
||||
int mbedtls_sha256_starts( mbedtls_sha256_context *ctx, int is224 )
|
||||
{
|
||||
CRYPTODRV_Context_t* cryptodrv_ctx = &ctx->cryptodrv_ctx;
|
||||
CRYPTO_TypeDef* crypto = cryptodrv_ctx->device->crypto;
|
||||
uint32_t init_state[8];
|
||||
Ecode_t ecode;
|
||||
|
||||
/* Request CRYPTO usage. */
|
||||
ecode = CRYPTODRV_Arbitrate(cryptodrv_ctx);
|
||||
if (ECODE_OK != ecode)
|
||||
{
|
||||
return ecode;
|
||||
}
|
||||
|
||||
/* Enter critial crypto region in order to initialize crypto for
|
||||
SHA operation. */
|
||||
ecode = CRYPTODRV_EnterCriticalRegion(cryptodrv_ctx);
|
||||
EFM_ASSERT(ECODE_OK == ecode); /* Assert critical region entry is ok. */
|
||||
|
||||
/* Setup CRYPTO for SHA-2 operation: */
|
||||
crypto->CTRL = CRYPTO_CTRL_SHA_SHA2;
|
||||
crypto->WAC = 0;
|
||||
|
||||
/* Set result width of MADD32 operation. */
|
||||
CRYPTO_ResultWidthSet(crypto, cryptoResult256Bits);
|
||||
|
||||
/* Clear sequence control registers */
|
||||
crypto->SEQCTRL = 0;
|
||||
crypto->SEQCTRLB = 0;
|
||||
|
||||
/* Setup the initial sha digest state */
|
||||
if( is224 == 0 )
|
||||
{
|
||||
/* SHA-256 */
|
||||
init_state[0] = 0x6A09E667;
|
||||
init_state[1] = 0xBB67AE85;
|
||||
init_state[2] = 0x3C6EF372;
|
||||
init_state[3] = 0xA54FF53A;
|
||||
init_state[4] = 0x510E527F;
|
||||
init_state[5] = 0x9B05688C;
|
||||
init_state[6] = 0x1F83D9AB;
|
||||
init_state[7] = 0x5BE0CD19;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* SHA-224 */
|
||||
init_state[0] = 0xC1059ED8;
|
||||
init_state[1] = 0x367CD507;
|
||||
init_state[2] = 0x3070DD17;
|
||||
init_state[3] = 0xF70E5939;
|
||||
init_state[4] = 0xFFC00B31;
|
||||
init_state[5] = 0x68581511;
|
||||
init_state[6] = 0x64F98FA7;
|
||||
init_state[7] = 0xBEFA4FA4;
|
||||
}
|
||||
|
||||
/* Push init vector to crypto module */
|
||||
CRYPTO_DDataWrite(&crypto->DDATA1, init_state);
|
||||
|
||||
/* Initialize CRYPTO sequencer to execute main SHA instruction
|
||||
sequence. */
|
||||
CRYPTO_EXECUTE_3( crypto,
|
||||
CRYPTO_CMD_INSTR_DDATA1TODDATA0,
|
||||
CRYPTO_CMD_INSTR_DDATA1TODDATA2,
|
||||
CRYPTO_CMD_INSTR_SELDDATA0DDATA1 );
|
||||
|
||||
/* Load main SHA instruction sequence */
|
||||
CRYPTO_SEQ_LOAD_3( crypto,
|
||||
CRYPTO_CMD_INSTR_SHA,
|
||||
CRYPTO_CMD_INSTR_MADD32,
|
||||
CRYPTO_CMD_INSTR_DDATA0TODDATA1 );
|
||||
|
||||
ecode = CRYPTODRV_ExitCriticalRegion( cryptodrv_ctx );
|
||||
EFM_ASSERT(ECODE_OK == ecode); /* Assert critical region exit is ok. */
|
||||
|
||||
ctx->total[0] = 0;
|
||||
ctx->total[1] = 0;
|
||||
|
||||
ctx->is224 = is224;
|
||||
|
||||
return ( ECODE_OK == ecode ? 0 : (int)ecode );
|
||||
}
|
||||
|
||||
void mbedtls_sha256_process( mbedtls_sha256_context *ctx, const unsigned char data[64] )
|
||||
{
|
||||
CRYPTODRV_Context_t* cryptodrv_ctx = &ctx->cryptodrv_ctx;
|
||||
CRYPTO_TypeDef* crypto = cryptodrv_ctx->device->crypto;
|
||||
Ecode_t ecode;
|
||||
|
||||
ecode = CRYPTODRV_EnterCriticalRegion( cryptodrv_ctx );
|
||||
EFM_ASSERT(ECODE_OK == ecode); /* Assert critical region entry is ok. */
|
||||
|
||||
/* Write block to QDATA1. */
|
||||
/* Check data is 32bit aligned, if not move via aligned buffer before writing. */
|
||||
if ((uint32_t)data & 0x3)
|
||||
{
|
||||
uint32_t temp[16];
|
||||
memcpy(temp, data, 64);
|
||||
CRYPTO_QDataWrite(&crypto->QDATA1BIG, temp);
|
||||
}
|
||||
else
|
||||
{
|
||||
CRYPTO_QDataWrite(&crypto->QDATA1BIG, (uint32_t*) data);
|
||||
}
|
||||
|
||||
/* Execute SHA */
|
||||
crypto->CMD |= CRYPTO_CMD_SEQSTART;
|
||||
|
||||
ecode = CRYPTODRV_ExitCriticalRegion( cryptodrv_ctx );
|
||||
EFM_ASSERT(ECODE_OK == ecode); /* Assert critical region exit is ok. */
|
||||
}
|
||||
|
||||
/*
|
||||
* SHA-256 process buffer
|
||||
*/
|
||||
void mbedtls_sha256_update( mbedtls_sha256_context *ctx, const unsigned char *input,
|
||||
size_t ilen )
|
||||
{
|
||||
size_t fill;
|
||||
uint32_t left;
|
||||
|
||||
if( ilen == 0 )
|
||||
return;
|
||||
|
||||
left = ctx->total[0] & 0x3F;
|
||||
fill = 64 - left;
|
||||
|
||||
ctx->total[0] += (uint32_t) ilen;
|
||||
ctx->total[0] &= 0xFFFFFFFF;
|
||||
|
||||
if( ctx->total[0] < (uint32_t) ilen )
|
||||
ctx->total[1]++;
|
||||
|
||||
if( left && ilen >= fill )
|
||||
{
|
||||
memcpy( (void *) (ctx->buffer + left), input, fill );
|
||||
mbedtls_sha256_process( ctx, ctx->buffer );
|
||||
input += fill;
|
||||
ilen -= fill;
|
||||
left = 0;
|
||||
}
|
||||
|
||||
while( ilen >= 64 )
|
||||
{
|
||||
mbedtls_sha256_process( ctx, input );
|
||||
input += 64;
|
||||
ilen -= 64;
|
||||
}
|
||||
|
||||
if( ilen > 0 )
|
||||
memcpy( (void *) (ctx->buffer + left), input, ilen );
|
||||
}
|
||||
|
||||
static const unsigned char sha256_padding[64] =
|
||||
{
|
||||
0x80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
|
||||
};
|
||||
|
||||
/*
|
||||
* SHA-256 final digest
|
||||
*/
|
||||
void mbedtls_sha256_finish( mbedtls_sha256_context *ctx, unsigned char output[32] )
|
||||
{
|
||||
uint32_t last, padn;
|
||||
uint32_t high, low;
|
||||
unsigned char msglen[8];
|
||||
CRYPTODRV_Context_t* cryptodrv_ctx = &ctx->cryptodrv_ctx;
|
||||
CRYPTO_TypeDef* crypto = cryptodrv_ctx->device->crypto;
|
||||
Ecode_t ecode;
|
||||
|
||||
high = ( ctx->total[0] >> 29 )
|
||||
| ( ctx->total[1] << 3 );
|
||||
low = ( ctx->total[0] << 3 );
|
||||
|
||||
PUT_UINT32_BE( high, msglen, 0 );
|
||||
PUT_UINT32_BE( low, msglen, 4 );
|
||||
|
||||
last = ctx->total[0] & 0x3F;
|
||||
padn = ( last < 56 ) ? ( 56 - last ) : ( 120 - last );
|
||||
|
||||
mbedtls_sha256_update( ctx, sha256_padding, padn );
|
||||
mbedtls_sha256_update( ctx, msglen, 8 );
|
||||
|
||||
/* Enter critical CRYPTO region in order to read final SHA digest/state. */
|
||||
ecode = CRYPTODRV_EnterCriticalRegion( cryptodrv_ctx );
|
||||
EFM_ASSERT(ECODE_OK == ecode); /* Assert critical region entry is ok. */
|
||||
|
||||
/* Read the digest from crypto (big endian). */
|
||||
CRYPTODRV_DDataReadUnaligned(&crypto->DDATA0BIG, output);
|
||||
|
||||
ecode = CRYPTODRV_ExitCriticalRegion( cryptodrv_ctx );
|
||||
|
||||
EFM_ASSERT(ECODE_OK == ecode); /* Assert critical region exit is ok. */
|
||||
|
||||
/* Finally release CRYPTO since SHA operation has completed. */
|
||||
ecode = CRYPTODRV_Release( cryptodrv_ctx );
|
||||
|
||||
EFM_ASSERT(ECODE_OK == ecode); /* Assert crypto release is ok. */
|
||||
|
||||
if( ctx->is224 )
|
||||
memset(&output[28], 0, 4);
|
||||
}
|
||||
|
||||
/*
|
||||
* output = SHA-256( input buffer )
|
||||
*/
|
||||
int mbedtls_sha256( const unsigned char *input, size_t ilen,
|
||||
unsigned char output[32], int is224 )
|
||||
{
|
||||
mbedtls_sha256_context ctx;
|
||||
int ret;
|
||||
|
||||
mbedtls_sha256_init( &ctx );
|
||||
|
||||
ret = mbedtls_sha256_starts( &ctx, is224 );
|
||||
if (ret != 0)
|
||||
return ret;
|
||||
|
||||
mbedtls_sha256_update( &ctx, input, ilen );
|
||||
mbedtls_sha256_finish( &ctx, output );
|
||||
mbedtls_sha256_free( &ctx );
|
||||
|
||||
return( 0 );
|
||||
}
|
||||
|
||||
#endif /* #if defined(CRYPTO_COUNT) && (CRYPTO_COUNT > 0) */
|
||||
|
||||
#endif /* #if defined(MBEDTLS_SLCL_PLUGINS) */
|
||||
|
||||
#endif /* #if defined(MBEDTLS_SHA256_ALT) */
|
||||
|
||||
#endif /* #if defined(MBEDTLS_SHA256_C) */
|
Loading…
Reference in New Issue