feat(mbedtls): bring mbedtls and openssl based on mbedtls from esp-idf

Commit ID: 97959e77.

Using submodule instead of source code.

It is brought from esp-idf, and some origin dependent code or configuration of hardware have not been removed.
But it maybe not affect using at the ESP8266 platform.
This commit is contained in:
dongheng
2019-09-19 10:39:31 +08:00
parent 6cfeb14102
commit 35d8262b25
260 changed files with 6450 additions and 109602 deletions

View File

@ -0,0 +1,41 @@
idf_component_register(INCLUDE_DIRS "port/include" "mbedtls/include"
REQUIRES lwip)
# Only build mbedtls libraries
set(ENABLE_TESTING CACHE BOOL OFF)
set(ENABLE_PROGRAMS CACHE BOOL OFF)
# Needed to for include_next includes to work from within mbedtls
include_directories("${COMPONENT_DIR}/port/include")
# Import mbedtls library targets
add_subdirectory(mbedtls)
# Use port specific implementation of net_socket.c instead of one from mbedtls
get_target_property(src_tls mbedtls SOURCES)
list(REMOVE_ITEM src_tls net_sockets.c)
set_property(TARGET mbedtls PROPERTY SOURCES ${src_tls})
set(mbedtls_targets mbedtls mbedcrypto mbedx509)
# Add port files to mbedtls targets
target_sources(mbedtls PRIVATE "${COMPONENT_DIR}/port/mbedtls_debug.c"
"${COMPONENT_DIR}/port/net_sockets.c")
target_sources(mbedcrypto PRIVATE "${COMPONENT_DIR}/port/esp_bignum.c"
"${COMPONENT_DIR}/port/esp_hardware.c"
"${COMPONENT_DIR}/port/esp_mem.c"
"${COMPONENT_DIR}/port/esp_sha.c"
"${COMPONENT_DIR}/port/esp_sha1.c"
"${COMPONENT_DIR}/port/esp_sha256.c"
"${COMPONENT_DIR}/port/esp_sha512.c"
"${COMPONENT_DIR}/port/esp_timing.c"
"${COMPONENT_DIR}/port/esp32/aes.c"
"${COMPONENT_DIR}/port/esp32/sha.c")
foreach(target ${mbedtls_targets})
target_compile_definitions(${target} PUBLIC -DMBEDTLS_CONFIG_FILE="mbedtls/esp_config.h")
endforeach()
# Link mbedtls libraries to component library
target_link_libraries(${COMPONENT_LIB} INTERFACE ${mbedtls_targets})

599
components/mbedtls/Kconfig Normal file
View File

@ -0,0 +1,599 @@
menu "mbedTLS"
choice MBEDTLS_MEM_ALLOC_MODE
prompt "Memory allocation strategy"
default MBEDTLS_INTERNAL_MEM_ALLOC
help
Allocation strategy for mbedTLS, essentially provides ability to
allocate all required dynamic allocations from,
- Internal DRAM memory only
- External SPIRAM memory only
- Either internal or external memory based on default malloc()
behavior in ESP-IDF
- Custom allocation mode, by overwriting calloc()/free() using
mbedtls_platform_set_calloc_free() function
Recommended mode here is always internal, since that is most preferred
from security perspective. But if application requirement does not
allow sufficient free internal memory then alternate mode can be
selected.
config MBEDTLS_INTERNAL_MEM_ALLOC
bool "Internal memory"
config MBEDTLS_EXTERNAL_MEM_ALLOC
bool "External SPIRAM"
depends on ESP32_SPIRAM_SUPPORT
config MBEDTLS_DEFAULT_MEM_ALLOC
bool "Default alloc mode"
config MBEDTLS_CUSTOM_MEM_ALLOC
bool "Custom alloc mode"
endchoice #MBEDTLS_MEM_ALLOC_MODE
config MBEDTLS_SSL_MAX_CONTENT_LEN
int "TLS maximum message content length"
default 16384
range 512 16384
depends on !MBEDTLS_ASYMMETRIC_CONTENT_LEN
help
Maximum TLS message length (in bytes) supported by mbedTLS.
16384 is the default and this value is required to comply
fully with TLS standards.
However you can set a lower value in order to save RAM. This
is safe if the other end of the connection supports Maximum
Fragment Length Negotiation Extension (max_fragment_length,
see RFC6066) or you know for certain that it will never send a
message longer than a certain number of bytes.
If the value is set too low, symptoms are a failed TLS
handshake or a return value of MBEDTLS_ERR_SSL_INVALID_RECORD
(-0x7200).
config MBEDTLS_ASYMMETRIC_CONTENT_LEN
bool "Asymmetric in/out fragment length"
default y
help
If enabled, this option allows customizing TLS in/out fragment length
in asymmetric way. Please note that enabling this with default values
saves 12KB of dynamic memory per TLS connection.
config MBEDTLS_SSL_IN_CONTENT_LEN
int "TLS maximum incoming fragment length"
default 16384
range 512 16384
depends on MBEDTLS_ASYMMETRIC_CONTENT_LEN
help
This defines maximum incoming fragment length, overriding default
maximum content length (MBEDTLS_SSL_MAX_CONTENT_LEN).
config MBEDTLS_SSL_OUT_CONTENT_LEN
int "TLS maximum outgoing fragment length"
default 4096
range 512 16384
depends on MBEDTLS_ASYMMETRIC_CONTENT_LEN
help
This defines maximum outgoing fragment length, overriding default
maximum content length (MBEDTLS_SSL_MAX_CONTENT_LEN).
config MBEDTLS_DEBUG
bool "Enable mbedTLS debugging"
default n
help
Enable mbedTLS debugging functions at compile time.
If this option is enabled, you can include
"mbedtls/esp_debug.h" and call mbedtls_esp_enable_debug_log()
at runtime in order to enable mbedTLS debug output via the ESP
log mechanism.
choice MBEDTLS_DEBUG_LEVEL
bool "Set mbedTLS debugging level"
depends on MBEDTLS_DEBUG
default MBEDTLS_DEBUG_LEVEL_VERBOSE
help
Set mbedTLS debugging level
config MBEDTLS_DEBUG_LEVEL_WARN
bool "Warning"
config MBEDTLS_DEBUG_LEVEL_INFO
bool "Info"
config MBEDTLS_DEBUG_LEVEL_DEBUG
bool "Debug"
config MBEDTLS_DEBUG_LEVEL_VERBOSE
bool "Verbose"
endchoice
config MBEDTLS_DEBUG_LEVEL
int
default 1 if MBEDTLS_DEBUG_LEVEL_WARN
default 2 if MBEDTLS_DEBUG_LEVEL_INFO
default 3 if MBEDTLS_DEBUG_LEVEL_DEBUG
default 4 if MBEDTLS_DEBUG_LEVEL_VERBOSE
config MBEDTLS_HARDWARE_AES
bool "Enable hardware AES acceleration"
default y
help
Enable hardware accelerated AES encryption & decryption.
Note that if the ESP32 CPU is running at 240MHz, hardware AES does not
offer any speed boost over software AES.
config MBEDTLS_HARDWARE_MPI
bool "Enable hardware MPI (bignum) acceleration"
default n
help
Enable hardware accelerated multiple precision integer operations.
Hardware accelerated multiplication, modulo multiplication,
and modular exponentiation for up to 4096 bit results.
These operations are used by RSA.
config MBEDTLS_MPI_USE_INTERRUPT
bool "Use interrupt for MPI operations"
depends on MBEDTLS_HARDWARE_MPI
default n
help
Use an interrupt to coordinate MPI operations.
This allows other code to run on the CPU while an MPI operation is pending.
Otherwise the CPU busy-waits.
config MBEDTLS_HARDWARE_SHA
bool "Enable hardware SHA acceleration"
default n
help
Enable hardware accelerated SHA1, SHA256, SHA384 & SHA512 in mbedTLS.
Due to a hardware limitation, hardware acceleration is only
guaranteed if SHA digests are calculated one at a time. If more
than one SHA digest is calculated at the same time, one will
be calculated fully in hardware and the rest will be calculated
(at least partially calculated) in software. This happens automatically.
SHA hardware acceleration is faster than software in some situations but
slower in others. You should benchmark to find the best setting for you.
config MBEDTLS_HAVE_TIME
bool "Enable mbedtls time"
depends on !ESP32_TIME_SYSCALL_USE_NONE
default y
help
System has time.h and time().
The time does not need to be correct, only time differences are used.
config MBEDTLS_HAVE_TIME_DATE
bool "Enable mbedtls certificate expiry check"
depends on MBEDTLS_HAVE_TIME
default n
help
System has time.h and time(), gmtime() and the clock is correct.
The time needs to be correct (not necesarily very accurate, but at least
the date should be correct). This is used to verify the validity period of
X.509 certificates.
It is suggested that you should get the real time by "SNTP".
choice MBEDTLS_TLS_MODE
bool "TLS Protocol Role"
default MBEDTLS_TLS_SERVER_AND_CLIENT
help
mbedTLS can be compiled with protocol support for the TLS
server, TLS client, or both server and client.
Reducing the number of TLS roles supported saves code size.
config MBEDTLS_TLS_SERVER_AND_CLIENT
bool "Server & Client"
select MBEDTLS_TLS_SERVER
select MBEDTLS_TLS_CLIENT
config MBEDTLS_TLS_SERVER_ONLY
bool "Server"
select MBEDTLS_TLS_SERVER
config MBEDTLS_TLS_CLIENT_ONLY
bool "Client"
select MBEDTLS_TLS_CLIENT
config MBEDTLS_TLS_DISABLED
bool "None"
endchoice
config MBEDTLS_TLS_SERVER
bool
select MBEDTLS_TLS_ENABLED
config MBEDTLS_TLS_CLIENT
bool
select MBEDTLS_TLS_ENABLED
config MBEDTLS_TLS_ENABLED
bool
menu "TLS Key Exchange Methods"
depends on MBEDTLS_TLS_ENABLED
config MBEDTLS_PSK_MODES
bool "Enable pre-shared-key ciphersuites"
default n
help
Enable to show configuration for different types of pre-shared-key TLS authentatication methods.
Leaving this options disabled will save code size if they are not used.
config MBEDTLS_KEY_EXCHANGE_PSK
bool "Enable PSK based ciphersuite modes"
depends on MBEDTLS_PSK_MODES
default n
help
Enable to support symmetric key PSK (pre-shared-key) TLS key exchange modes.
config MBEDTLS_KEY_EXCHANGE_DHE_PSK
bool "Enable DHE-PSK based ciphersuite modes"
depends on MBEDTLS_PSK_MODES
default y
help
Enable to support Diffie-Hellman PSK (pre-shared-key) TLS authentication modes.
config MBEDTLS_KEY_EXCHANGE_ECDHE_PSK
bool "Enable ECDHE-PSK based ciphersuite modes"
depends on MBEDTLS_PSK_MODES && MBEDTLS_ECDH_C
default y
help
Enable to support Elliptic-Curve-Diffie-Hellman PSK (pre-shared-key) TLS authentication modes.
config MBEDTLS_KEY_EXCHANGE_RSA_PSK
bool "Enable RSA-PSK based ciphersuite modes"
depends on MBEDTLS_PSK_MODES
default y
help
Enable to support RSA PSK (pre-shared-key) TLS authentication modes.
config MBEDTLS_KEY_EXCHANGE_RSA
bool "Enable RSA-only based ciphersuite modes"
default y
help
Enable to support ciphersuites with prefix TLS-RSA-WITH-
config MBEDTLS_KEY_EXCHANGE_DHE_RSA
bool "Enable DHE-RSA based ciphersuite modes"
default y
help
Enable to support ciphersuites with prefix TLS-DHE-RSA-WITH-
config MBEDTLS_KEY_EXCHANGE_ELLIPTIC_CURVE
bool "Support Elliptic Curve based ciphersuites"
depends on MBEDTLS_ECP_C
default y
help
Enable to show Elliptic Curve based ciphersuite mode options.
Disabling all Elliptic Curve ciphersuites saves code size and
can give slightly faster TLS handshakes, provided the server supports
RSA-only ciphersuite modes.
config MBEDTLS_KEY_EXCHANGE_ECDHE_RSA
bool "Enable ECDHE-RSA based ciphersuite modes"
depends on MBEDTLS_KEY_EXCHANGE_ELLIPTIC_CURVE && MBEDTLS_ECDH_C
default y
help
Enable to support ciphersuites with prefix TLS-ECDHE-RSA-WITH-
config MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA
bool "Enable ECDHE-ECDSA based ciphersuite modes"
depends on MBEDTLS_KEY_EXCHANGE_ELLIPTIC_CURVE && MBEDTLS_ECDH_C && MBEDTLS_ECDSA_C
default y
help
Enable to support ciphersuites with prefix TLS-ECDHE-RSA-WITH-
config MBEDTLS_KEY_EXCHANGE_ECDH_ECDSA
bool "Enable ECDH-ECDSA based ciphersuite modes"
depends on MBEDTLS_KEY_EXCHANGE_ELLIPTIC_CURVE && MBEDTLS_ECDH_C && MBEDTLS_ECDSA_C
default y
help
Enable to support ciphersuites with prefix TLS-ECDHE-RSA-WITH-
config MBEDTLS_KEY_EXCHANGE_ECDH_RSA
bool "Enable ECDH-RSA based ciphersuite modes"
depends on MBEDTLS_KEY_EXCHANGE_ELLIPTIC_CURVE && MBEDTLS_ECDH_C
default y
help
Enable to support ciphersuites with prefix TLS-ECDHE-RSA-WITH-
endmenu # TLS key exchange modes
config MBEDTLS_SSL_RENEGOTIATION
bool "Support TLS renegotiation"
depends on MBEDTLS_TLS_ENABLED
default y
help
The two main uses of renegotiation are (1) refresh keys on long-lived
connections and (2) client authentication after the initial handshake.
If you don't need renegotiation, disabling it will save code size and
reduce the possibility of abuse/vulnerability.
config MBEDTLS_SSL_PROTO_SSL3
bool "Legacy SSL 3.0 support"
depends on MBEDTLS_TLS_ENABLED
default n
help
Support the legacy SSL 3.0 protocol. Most servers will speak a newer
TLS protocol these days.
config MBEDTLS_SSL_PROTO_TLS1
bool "Support TLS 1.0 protocol"
depends on MBEDTLS_TLS_ENABLED
default y
config MBEDTLS_SSL_PROTO_TLS1_1
bool "Support TLS 1.1 protocol"
depends on MBEDTLS_TLS_ENABLED
default y
config MBEDTLS_SSL_PROTO_TLS1_2
bool "Support TLS 1.2 protocol"
depends on MBEDTLS_TLS_ENABLED
default y
config MBEDTLS_SSL_PROTO_DTLS
bool "Support DTLS protocol (all versions)"
default n
depends on MBEDTLS_SSL_PROTO_TLS1_1 || MBEDTLS_SSL_PROTO_TLS1_2
help
Requires TLS 1.1 to be enabled for DTLS 1.0
Requires TLS 1.2 to be enabled for DTLS 1.2
config MBEDTLS_SSL_ALPN
bool "Support ALPN (Application Layer Protocol Negotiation)"
depends on MBEDTLS_TLS_ENABLED
default y
help
Disabling this option will save some code size if it is not needed.
config MBEDTLS_CLIENT_SSL_SESSION_TICKETS
bool "TLS: Client Support for RFC 5077 SSL session tickets"
default y
depends on MBEDTLS_TLS_ENABLED
help
Client support for RFC 5077 session tickets. See mbedTLS documentation for more details.
Disabling this option will save some code size.
config MBEDTLS_SERVER_SSL_SESSION_TICKETS
bool "TLS: Server Support for RFC 5077 SSL session tickets"
default y
depends on MBEDTLS_TLS_ENABLED
help
Server support for RFC 5077 session tickets. See mbedTLS documentation for more details.
Disabling this option will save some code size.
menu "Symmetric Ciphers"
config MBEDTLS_AES_C
bool "AES block cipher"
default y
config MBEDTLS_CAMELLIA_C
bool "Camellia block cipher"
default n
config MBEDTLS_DES_C
bool "DES block cipher (legacy, insecure)"
default n
help
Enables the DES block cipher to support 3DES-based TLS ciphersuites.
3DES is vulnerable to the Sweet32 attack and should only be enabled
if absolutely necessary.
choice MBEDTLS_RC4_MODE
prompt "RC4 Stream Cipher (legacy, insecure)"
default MBEDTLS_RC4_DISABLED
help
ARCFOUR (RC4) stream cipher can be disabled entirely, enabled but not
added to default ciphersuites, or enabled completely.
Please consider the security implications before enabling RC4.
config MBEDTLS_RC4_DISABLED
bool "Disabled"
config MBEDTLS_RC4_ENABLED_NO_DEFAULT
bool "Enabled, not in default ciphersuites"
config MBEDTLS_RC4_ENABLED
bool "Enabled"
endchoice
config MBEDTLS_BLOWFISH_C
bool "Blowfish block cipher (read help)"
default n
help
Enables the Blowfish block cipher (not used for TLS sessions.)
The Blowfish cipher is not used for mbedTLS TLS sessions but can be
used for other purposes. Read up on the limitations of Blowfish (including
Sweet32) before enabling.
config MBEDTLS_XTEA_C
bool "XTEA block cipher"
default n
help
Enables the XTEA block cipher.
config MBEDTLS_CCM_C
bool "CCM (Counter with CBC-MAC) block cipher modes"
default y
depends on MBEDTLS_AES_C || MBEDTLS_CAMELLIA_C
help
Enable Counter with CBC-MAC (CCM) modes for AES and/or Camellia ciphers.
Disabling this option saves some code size.
config MBEDTLS_GCM_C
bool "GCM (Galois/Counter) block cipher modes"
default y
depends on MBEDTLS_AES_C || MBEDTLS_CAMELLIA_C
help
Enable Galois/Counter Mode for AES and/or Camellia ciphers.
This option is generally faster than CCM.
endmenu # Symmetric Ciphers
config MBEDTLS_RIPEMD160_C
bool "Enable RIPEMD-160 hash algorithm"
default n
help
Enable the RIPEMD-160 hash algorithm.
menu "Certificates"
config MBEDTLS_PEM_PARSE_C
bool "Read & Parse PEM formatted certificates"
default y
help
Enable decoding/parsing of PEM formatted certificates.
If your certificates are all in the simpler DER format, disabling
this option will save some code size.
config MBEDTLS_PEM_WRITE_C
bool "Write PEM formatted certificates"
default y
help
Enable writing of PEM formatted certificates.
If writing certificate data only in DER format, disabling this
option will save some code size.
config MBEDTLS_X509_CRL_PARSE_C
bool "X.509 CRL parsing"
default y
help
Support for parsing X.509 Certifificate Revocation Lists.
config MBEDTLS_X509_CSR_PARSE_C
bool "X.509 CSR parsing"
default y
help
Support for parsing X.509 Certifificate Signing Requests
endmenu # Certificates
menuconfig MBEDTLS_ECP_C
bool "Elliptic Curve Ciphers"
default y
config MBEDTLS_ECDH_C
bool "Elliptic Curve Diffie-Hellman (ECDH)"
depends on MBEDTLS_ECP_C
default y
help
Enable ECDH. Needed to use ECDHE-xxx TLS ciphersuites.
config MBEDTLS_ECDSA_C
bool "Elliptic Curve DSA"
depends on MBEDTLS_ECDH_C
default y
help
Enable ECDSA. Needed to use ECDSA-xxx TLS ciphersuites.
config MBEDTLS_ECP_DP_SECP192R1_ENABLED
bool "Enable SECP192R1 curve"
depends on MBEDTLS_ECP_C
default y
help
Enable support for SECP192R1 Elliptic Curve.
config MBEDTLS_ECP_DP_SECP224R1_ENABLED
bool "Enable SECP224R1 curve"
depends on MBEDTLS_ECP_C
default y
help
Enable support for SECP224R1 Elliptic Curve.
config MBEDTLS_ECP_DP_SECP256R1_ENABLED
bool "Enable SECP256R1 curve"
depends on MBEDTLS_ECP_C
default y
help
Enable support for SECP256R1 Elliptic Curve.
config MBEDTLS_ECP_DP_SECP384R1_ENABLED
bool "Enable SECP384R1 curve"
depends on MBEDTLS_ECP_C
default y
help
Enable support for SECP384R1 Elliptic Curve.
config MBEDTLS_ECP_DP_SECP521R1_ENABLED
bool "Enable SECP521R1 curve"
depends on MBEDTLS_ECP_C
default y
help
Enable support for SECP521R1 Elliptic Curve.
config MBEDTLS_ECP_DP_SECP192K1_ENABLED
bool "Enable SECP192K1 curve"
depends on MBEDTLS_ECP_C
default y
help
Enable support for SECP192K1 Elliptic Curve.
config MBEDTLS_ECP_DP_SECP224K1_ENABLED
bool "Enable SECP224K1 curve"
depends on MBEDTLS_ECP_C
default y
help
Enable support for SECP224K1 Elliptic Curve.
config MBEDTLS_ECP_DP_SECP256K1_ENABLED
bool "Enable SECP256K1 curve"
depends on MBEDTLS_ECP_C
default y
help
Enable support for SECP256K1 Elliptic Curve.
config MBEDTLS_ECP_DP_BP256R1_ENABLED
bool "Enable BP256R1 curve"
depends on MBEDTLS_ECP_C
default y
help
support for DP Elliptic Curve.
config MBEDTLS_ECP_DP_BP384R1_ENABLED
bool "Enable BP384R1 curve"
depends on MBEDTLS_ECP_C
default y
help
support for DP Elliptic Curve.
config MBEDTLS_ECP_DP_BP512R1_ENABLED
bool "Enable BP512R1 curve"
depends on MBEDTLS_ECP_C
default y
help
support for DP Elliptic Curve.
config MBEDTLS_ECP_DP_CURVE25519_ENABLED
bool "Enable CURVE25519 curve"
depends on MBEDTLS_ECP_C
default y
help
Enable support for CURVE25519 Elliptic Curve.
config MBEDTLS_ECP_NIST_OPTIM
bool "NIST 'modulo p' optimisations"
depends on MBEDTLS_ECP_C
default y
help
NIST 'modulo p' optimisations increase Elliptic Curve operation performance.
Disabling this option saves some code size.
# end of Elliptic Curve options
endmenu # mbedTLS

View File

@ -0,0 +1,8 @@
# Anyone compiling mbedTLS code needs the name of the
# alternative config file
CPPFLAGS += -DMBEDTLS_CONFIG_FILE='"mbedtls/esp_config.h"'
# Catch usage of deprecated mbedTLS functions when building tests
ifneq ("$(filter mbedtls,$(TEST_COMPONENTS_LIST))","")
CPPFLAGS += -DMBEDTLS_DEPRECATED_WARNING
endif

View File

@ -0,0 +1,12 @@
#
# Component Makefile
#
COMPONENT_ADD_INCLUDEDIRS := port/include mbedtls/include
COMPONENT_SRCDIRS := mbedtls/library port port/esp32
COMPONENT_OBJEXCLUDE := mbedtls/library/net_sockets.o
COMPONENT_SUBMODULES += mbedtls

View File

@ -0,0 +1,768 @@
/**
* \brief AES block cipher, ESP32 hardware accelerated version
* Based on mbedTLS FIPS-197 compliant version.
*
* Copyright (C) 2006-2015, ARM Limited, All Rights Reserved
* Additions Copyright (C) 2016-2017, Espressif Systems (Shanghai) PTE Ltd
* 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.
*
*/
/*
* 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
*/
#include <string.h>
#include "mbedtls/aes.h"
#include "mbedtls/platform_util.h"
#include "esp32/aes.h"
#include "soc/hwcrypto_periph.h"
#include <sys/lock.h>
#include <freertos/FreeRTOS.h>
#include "soc/cpu.h"
#include <stdio.h>
#include "driver/periph_ctrl.h"
/* AES uses a spinlock mux not a lock as the underlying block operation
only takes 208 cycles (to write key & compute block), +600 cycles
for DPORT protection but +3400 cycles again if you use a full sized lock.
For CBC, CFB, etc. this may mean that interrupts are disabled for a longer
period of time for bigger lengths. However at the moment this has to happen
anyway due to DPORT protection...
*/
static portMUX_TYPE aes_spinlock = portMUX_INITIALIZER_UNLOCKED;
static inline bool valid_key_length(const esp_aes_context *ctx)
{
return ctx->key_bytes == 128/8 || ctx->key_bytes == 192/8 || ctx->key_bytes == 256/8;
}
void esp_aes_acquire_hardware( void )
{
portENTER_CRITICAL(&aes_spinlock);
/* Enable AES hardware */
periph_module_enable(PERIPH_AES_MODULE);
}
void esp_aes_release_hardware( void )
{
/* Disable AES hardware */
periph_module_disable(PERIPH_AES_MODULE);
portEXIT_CRITICAL(&aes_spinlock);
}
void esp_aes_init( esp_aes_context *ctx )
{
bzero( ctx, sizeof( esp_aes_context ) );
}
void esp_aes_free( esp_aes_context *ctx )
{
if ( ctx == NULL ) {
return;
}
bzero( ctx, sizeof( esp_aes_context ) );
}
/*
* AES key schedule (same for encryption or decryption, as hardware handles schedule)
*
*/
int esp_aes_setkey( esp_aes_context *ctx, const unsigned char *key,
unsigned int keybits )
{
if (keybits != 128 && keybits != 192 && keybits != 256) {
return MBEDTLS_ERR_AES_INVALID_KEY_LENGTH;
}
ctx->key_bytes = keybits / 8;
memcpy(ctx->key, key, ctx->key_bytes);
ctx->key_in_hardware = 0;
return 0;
}
/*
* Helper function to copy key from esp_aes_context buffer
* to hardware key registers.
*
* Call only while holding esp_aes_acquire_hardware().
*/
static void esp_aes_setkey_hardware(esp_aes_context *ctx, int mode)
{
const uint32_t MODE_DECRYPT_BIT = 4;
unsigned mode_reg_base = (mode == ESP_AES_ENCRYPT) ? 0 : MODE_DECRYPT_BIT;
ctx->key_in_hardware = 0;
for (int i = 0; i < ctx->key_bytes/4; ++i) {
DPORT_REG_WRITE(AES_KEY_BASE + i * 4, *(((uint32_t *)ctx->key) + i));
ctx->key_in_hardware += 4;
}
DPORT_REG_WRITE(AES_MODE_REG, mode_reg_base + ((ctx->key_bytes / 8) - 2));
/* Fault injection check: all words of key data should have been written to hardware */
if (ctx->key_in_hardware < 16
|| ctx->key_in_hardware != ctx->key_bytes) {
abort();
}
}
/* Run a single 16 byte block of AES, using the hardware engine.
*
* Call only while holding esp_aes_acquire_hardware().
*/
static int esp_aes_block(esp_aes_context *ctx, const void *input, void *output)
{
const uint32_t *input_words = (const uint32_t *)input;
uint32_t i0, i1, i2, i3;
uint32_t *output_words = (uint32_t *)output;
/* If no key is written to hardware yet, either the user hasn't called
mbedtls_aes_setkey_enc/mbedtls_aes_setkey_dec - meaning we also don't
know which mode to use - or a fault skipped the
key write to hardware. Treat this as a fatal error and zero the output block.
*/
if (ctx->key_in_hardware != ctx->key_bytes) {
bzero(output, 16);
return MBEDTLS_ERR_AES_INVALID_INPUT_LENGTH;
}
/* Storing i0,i1,i2,i3 in registers not an array
helps a lot with optimisations at -Os level */
i0 = input_words[0];
DPORT_REG_WRITE(AES_TEXT_BASE, i0);
i1 = input_words[1];
DPORT_REG_WRITE(AES_TEXT_BASE + 4, i1);
i2 = input_words[2];
DPORT_REG_WRITE(AES_TEXT_BASE + 8, i2);
i3 = input_words[3];
DPORT_REG_WRITE(AES_TEXT_BASE + 12, i3);
DPORT_REG_WRITE(AES_START_REG, 1);
while (DPORT_REG_READ(AES_IDLE_REG) != 1) { }
esp_dport_access_read_buffer(output_words, AES_TEXT_BASE, 4);
/* Physical security check: Verify the AES accelerator actually ran, and wasn't
skipped due to external fault injection while starting the peripheral.
Note that i0,i1,i2,i3 are copied from input buffer in case input==output.
Bypassing this check requires at least one additional fault.
*/
if(i0 == output_words[0] && i1 == output_words[1] && i2 == output_words[2] && i3 == output_words[3]) {
// calling zeroing functions to narrow the
// window for a double-fault of the abort step, here
memset(output, 0, 16);
mbedtls_platform_zeroize(output, 16);
abort();
}
return 0;
}
/*
* AES-ECB block encryption
*/
int esp_internal_aes_encrypt( esp_aes_context *ctx,
const unsigned char input[16],
unsigned char output[16] )
{
int r;
if (!valid_key_length(ctx)) {
return MBEDTLS_ERR_AES_INVALID_KEY_LENGTH;
}
esp_aes_acquire_hardware();
ctx->key_in_hardware = 0;
esp_aes_setkey_hardware(ctx, ESP_AES_ENCRYPT);
r = esp_aes_block(ctx, input, output);
esp_aes_release_hardware();
return r;
}
void esp_aes_encrypt( esp_aes_context *ctx,
const unsigned char input[16],
unsigned char output[16] )
{
esp_internal_aes_encrypt(ctx, input, output);
}
/*
* AES-ECB block decryption
*/
int esp_internal_aes_decrypt( esp_aes_context *ctx,
const unsigned char input[16],
unsigned char output[16] )
{
int r;
if (!valid_key_length(ctx)) {
return MBEDTLS_ERR_AES_INVALID_KEY_LENGTH;
}
esp_aes_acquire_hardware();
ctx->key_in_hardware = 0;
esp_aes_setkey_hardware(ctx, ESP_AES_DECRYPT);
r = esp_aes_block(ctx, input, output);
esp_aes_release_hardware();
return r;
}
void esp_aes_decrypt( esp_aes_context *ctx,
const unsigned char input[16],
unsigned char output[16] )
{
esp_internal_aes_decrypt(ctx, input, output);
}
/*
* AES-ECB block encryption/decryption
*/
int esp_aes_crypt_ecb( esp_aes_context *ctx,
int mode,
const unsigned char input[16],
unsigned char output[16] )
{
int r;
if (!valid_key_length(ctx)) {
return MBEDTLS_ERR_AES_INVALID_KEY_LENGTH;
}
esp_aes_acquire_hardware();
ctx->key_in_hardware = 0;
esp_aes_setkey_hardware(ctx, mode);
r = esp_aes_block(ctx, input, output);
esp_aes_release_hardware();
return r;
}
/*
* AES-CBC buffer encryption/decryption
*/
int esp_aes_crypt_cbc( esp_aes_context *ctx,
int mode,
size_t length,
unsigned char iv[16],
const unsigned char *input,
unsigned char *output )
{
int i;
uint32_t *output_words = (uint32_t *)output;
const uint32_t *input_words = (const uint32_t *)input;
uint32_t *iv_words = (uint32_t *)iv;
unsigned char temp[16];
if ( length % 16 ) {
return ( ERR_ESP_AES_INVALID_INPUT_LENGTH );
}
if (!valid_key_length(ctx)) {
return MBEDTLS_ERR_AES_INVALID_KEY_LENGTH;
}
esp_aes_acquire_hardware();
ctx->key_in_hardware = 0;
esp_aes_setkey_hardware(ctx, mode);
if ( mode == ESP_AES_DECRYPT ) {
while ( length > 0 ) {
memcpy(temp, input_words, 16);
esp_aes_block(ctx, input_words, output_words);
for ( i = 0; i < 4; i++ ) {
output_words[i] = output_words[i] ^ iv_words[i];
}
memcpy( iv_words, temp, 16 );
input_words += 4;
output_words += 4;
length -= 16;
}
} else { // ESP_AES_ENCRYPT
while ( length > 0 ) {
for ( i = 0; i < 4; i++ ) {
output_words[i] = input_words[i] ^ iv_words[i];
}
esp_aes_block(ctx, output_words, output_words);
memcpy( iv_words, output_words, 16 );
input_words += 4;
output_words += 4;
length -= 16;
}
}
esp_aes_release_hardware();
return 0;
}
/*
* AES-CFB128 buffer encryption/decryption
*/
int esp_aes_crypt_cfb128( esp_aes_context *ctx,
int mode,
size_t length,
size_t *iv_off,
unsigned char iv[16],
const unsigned char *input,
unsigned char *output )
{
int c;
size_t n = *iv_off;
if (!valid_key_length(ctx)) {
return MBEDTLS_ERR_AES_INVALID_KEY_LENGTH;
}
esp_aes_acquire_hardware();
ctx->key_in_hardware = 0;
esp_aes_setkey_hardware(ctx, ESP_AES_ENCRYPT);
if ( mode == ESP_AES_DECRYPT ) {
while ( length-- ) {
if ( n == 0 ) {
esp_aes_block(ctx, 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 ) {
esp_aes_block(ctx, iv, iv);
}
iv[n] = *output++ = (unsigned char)( iv[n] ^ *input++ );
n = ( n + 1 ) & 0x0F;
}
}
*iv_off = n;
esp_aes_release_hardware();
return 0;
}
/*
* AES-CFB8 buffer encryption/decryption
*/
int esp_aes_crypt_cfb8( esp_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];
if (!valid_key_length(ctx)) {
return MBEDTLS_ERR_AES_INVALID_KEY_LENGTH;
}
esp_aes_acquire_hardware();
ctx->key_in_hardware = 0;
esp_aes_setkey_hardware(ctx, ESP_AES_ENCRYPT);
while ( length-- ) {
memcpy( ov, iv, 16 );
esp_aes_block(ctx, iv, iv);
if ( mode == ESP_AES_DECRYPT ) {
ov[16] = *input;
}
c = *output++ = (unsigned char)( iv[0] ^ *input++ );
if ( mode == ESP_AES_ENCRYPT ) {
ov[16] = c;
}
memcpy( iv, ov + 1, 16 );
}
esp_aes_release_hardware();
return 0;
}
/*
* AES-CTR buffer encryption/decryption
*/
int esp_aes_crypt_ctr( esp_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 )
{
int c, i;
size_t n = *nc_off;
if (!valid_key_length(ctx)) {
return MBEDTLS_ERR_AES_INVALID_KEY_LENGTH;
}
esp_aes_acquire_hardware();
ctx->key_in_hardware = 0;
esp_aes_setkey_hardware(ctx, ESP_AES_ENCRYPT);
while ( length-- ) {
if ( n == 0 ) {
esp_aes_block(ctx, 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;
esp_aes_release_hardware();
return 0;
}
/*
* AES-OFB (Output Feedback Mode) buffer encryption/decryption
*/
int esp_aes_crypt_ofb( esp_aes_context *ctx,
size_t length,
size_t *iv_off,
unsigned char iv[16],
const unsigned char *input,
unsigned char *output )
{
int ret = 0;
size_t n;
if ( ctx == NULL || iv_off == NULL || iv == NULL ||
input == NULL || output == NULL ) {
return MBEDTLS_ERR_AES_BAD_INPUT_DATA;
}
n = *iv_off;
if( n > 15 ) {
return( MBEDTLS_ERR_AES_BAD_INPUT_DATA );
}
if (!valid_key_length(ctx)) {
return MBEDTLS_ERR_AES_INVALID_KEY_LENGTH;
}
esp_aes_acquire_hardware();
esp_aes_setkey_hardware(ctx, ESP_AES_ENCRYPT);
while( length-- ) {
if( n == 0 ) {
esp_aes_block(ctx, iv, iv);
}
*output++ = *input++ ^ iv[n];
n = ( n + 1 ) & 0x0F;
}
*iv_off = n;
esp_aes_release_hardware();
return( ret );
}
/* Below XTS implementation is copied aes.c of mbedtls library.
* When MBEDTLS_AES_ALT is defined mbedtls expects alternate
* definition of XTS functions to be available. Even if this
* could have been avoided, it is done for consistency reason.
*/
void esp_aes_xts_init( esp_aes_xts_context *ctx )
{
esp_aes_init( &ctx->crypt );
esp_aes_init( &ctx->tweak );
}
void esp_aes_xts_free( esp_aes_xts_context *ctx )
{
esp_aes_free( &ctx->crypt );
esp_aes_free( &ctx->tweak );
}
static int esp_aes_xts_decode_keys( const unsigned char *key,
unsigned int keybits,
const unsigned char **key1,
unsigned int *key1bits,
const unsigned char **key2,
unsigned int *key2bits )
{
const unsigned int half_keybits = keybits / 2;
const unsigned int half_keybytes = half_keybits / 8;
switch( keybits )
{
case 256: break;
case 512: break;
default : return( MBEDTLS_ERR_AES_INVALID_KEY_LENGTH );
}
*key1bits = half_keybits;
*key2bits = half_keybits;
*key1 = &key[0];
*key2 = &key[half_keybytes];
return 0;
}
int esp_aes_xts_setkey_enc( esp_aes_xts_context *ctx,
const unsigned char *key,
unsigned int keybits)
{
int ret;
const unsigned char *key1, *key2;
unsigned int key1bits, key2bits;
ret = esp_aes_xts_decode_keys( key, keybits, &key1, &key1bits,
&key2, &key2bits );
if( ret != 0 )
return( ret );
/* Set the tweak key. Always set tweak key for the encryption mode. */
ret = esp_aes_setkey( &ctx->tweak, key2, key2bits );
if( ret != 0 )
return( ret );
/* Set crypt key for encryption. */
return esp_aes_setkey( &ctx->crypt, key1, key1bits );
}
int esp_aes_xts_setkey_dec( esp_aes_xts_context *ctx,
const unsigned char *key,
unsigned int keybits)
{
int ret;
const unsigned char *key1, *key2;
unsigned int key1bits, key2bits;
ret = esp_aes_xts_decode_keys( key, keybits, &key1, &key1bits,
&key2, &key2bits );
if( ret != 0 )
return( ret );
/* Set the tweak key. Always set tweak key for encryption. */
ret = esp_aes_setkey( &ctx->tweak, key2, key2bits );
if( ret != 0 )
return( ret );
/* Set crypt key for decryption. */
return esp_aes_setkey( &ctx->crypt, key1, key1bits );
}
/* Endianess with 64 bits values */
#ifndef GET_UINT64_LE
#define GET_UINT64_LE(n,b,i) \
{ \
(n) = ( (uint64_t) (b)[(i) + 7] << 56 ) \
| ( (uint64_t) (b)[(i) + 6] << 48 ) \
| ( (uint64_t) (b)[(i) + 5] << 40 ) \
| ( (uint64_t) (b)[(i) + 4] << 32 ) \
| ( (uint64_t) (b)[(i) + 3] << 24 ) \
| ( (uint64_t) (b)[(i) + 2] << 16 ) \
| ( (uint64_t) (b)[(i) + 1] << 8 ) \
| ( (uint64_t) (b)[(i) ] ); \
}
#endif
#ifndef PUT_UINT64_LE
#define PUT_UINT64_LE(n,b,i) \
{ \
(b)[(i) + 7] = (unsigned char) ( (n) >> 56 ); \
(b)[(i) + 6] = (unsigned char) ( (n) >> 48 ); \
(b)[(i) + 5] = (unsigned char) ( (n) >> 40 ); \
(b)[(i) + 4] = (unsigned char) ( (n) >> 32 ); \
(b)[(i) + 3] = (unsigned char) ( (n) >> 24 ); \
(b)[(i) + 2] = (unsigned char) ( (n) >> 16 ); \
(b)[(i) + 1] = (unsigned char) ( (n) >> 8 ); \
(b)[(i) ] = (unsigned char) ( (n) ); \
}
#endif
typedef unsigned char esp_be128[16];
/*
* GF(2^128) multiplication function
*
* This function multiplies a field element by x in the polynomial field
* representation. It uses 64-bit word operations to gain speed but compensates
* for machine endianess and hence works correctly on both big and little
* endian machines.
*/
static void esp_gf128mul_x_ble( unsigned char r[16],
const unsigned char x[16] )
{
uint64_t a, b, ra, rb;
GET_UINT64_LE( a, x, 0 );
GET_UINT64_LE( b, x, 8 );
ra = ( a << 1 ) ^ 0x0087 >> ( 8 - ( ( b >> 63 ) << 3 ) );
rb = ( a >> 63 ) | ( b << 1 );
PUT_UINT64_LE( ra, r, 0 );
PUT_UINT64_LE( rb, r, 8 );
}
/*
* AES-XTS buffer encryption/decryption
*/
int esp_aes_crypt_xts( esp_aes_xts_context *ctx,
int mode,
size_t length,
const unsigned char data_unit[16],
const unsigned char *input,
unsigned char *output )
{
int ret;
size_t blocks = length / 16;
size_t leftover = length % 16;
unsigned char tweak[16];
unsigned char prev_tweak[16];
unsigned char tmp[16];
/* Sectors must be at least 16 bytes. */
if( length < 16 )
return MBEDTLS_ERR_AES_INVALID_INPUT_LENGTH;
/* NIST SP 80-38E disallows data units larger than 2**20 blocks. */
if( length > ( 1 << 20 ) * 16 )
return MBEDTLS_ERR_AES_INVALID_INPUT_LENGTH;
/* Compute the tweak. */
ret = esp_aes_crypt_ecb( &ctx->tweak, MBEDTLS_AES_ENCRYPT,
data_unit, tweak );
if( ret != 0 )
return( ret );
while( blocks-- )
{
size_t i;
if( leftover && ( mode == MBEDTLS_AES_DECRYPT ) && blocks == 0 )
{
/* We are on the last block in a decrypt operation that has
* leftover bytes, so we need to use the next tweak for this block,
* and this tweak for the lefover bytes. Save the current tweak for
* the leftovers and then update the current tweak for use on this,
* the last full block. */
memcpy( prev_tweak, tweak, sizeof( tweak ) );
esp_gf128mul_x_ble( tweak, tweak );
}
for( i = 0; i < 16; i++ )
tmp[i] = input[i] ^ tweak[i];
ret = esp_aes_crypt_ecb( &ctx->crypt, mode, tmp, tmp );
if( ret != 0 )
return( ret );
for( i = 0; i < 16; i++ )
output[i] = tmp[i] ^ tweak[i];
/* Update the tweak for the next block. */
esp_gf128mul_x_ble( tweak, tweak );
output += 16;
input += 16;
}
if( leftover )
{
/* If we are on the leftover bytes in a decrypt operation, we need to
* use the previous tweak for these bytes (as saved in prev_tweak). */
unsigned char *t = mode == MBEDTLS_AES_DECRYPT ? prev_tweak : tweak;
/* We are now on the final part of the data unit, which doesn't divide
* evenly by 16. It's time for ciphertext stealing. */
size_t i;
unsigned char *prev_output = output - 16;
/* Copy ciphertext bytes from the previous block to our output for each
* byte of cyphertext we won't steal. At the same time, copy the
* remainder of the input for this final round (since the loop bounds
* are the same). */
for( i = 0; i < leftover; i++ )
{
output[i] = prev_output[i];
tmp[i] = input[i] ^ t[i];
}
/* Copy ciphertext bytes from the previous block for input in this
* round. */
for( ; i < 16; i++ )
tmp[i] = prev_output[i] ^ t[i];
ret = esp_aes_crypt_ecb( &ctx->crypt, mode, tmp, tmp );
if( ret != 0 )
return ret;
/* Write the result back to the previous block, overriding the previous
* output we copied. */
for( i = 0; i < 16; i++ )
prev_output[i] = tmp[i] ^ t[i];
}
return( 0 );
}

View File

@ -0,0 +1,314 @@
/*
* ESP32 hardware accelerated SHA1/256/512 implementation
* based on mbedTLS FIPS-197 compliant version.
*
* Copyright (C) 2006-2015, ARM Limited, All Rights Reserved
* Additions Copyright (C) 2016, Espressif Systems (Shanghai) PTE Ltd
* 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.
*
*/
/*
* The SHA-1 standard was published by NIST in 1993.
*
* http://www.itl.nist.gov/fipspubs/fip180-1.htm
*/
#include <string.h>
#include <stdio.h>
#include <machine/endian.h>
#include <assert.h>
#include "freertos/FreeRTOS.h"
#include "freertos/semphr.h"
#include "esp32/sha.h"
#include "esp32/rom/ets_sys.h"
#include "soc/hwcrypto_periph.h"
#include "driver/periph_ctrl.h"
inline static uint32_t SHA_LOAD_REG(esp_sha_type sha_type) {
return SHA_1_LOAD_REG + sha_type * 0x10;
}
inline static uint32_t SHA_BUSY_REG(esp_sha_type sha_type) {
return SHA_1_BUSY_REG + sha_type * 0x10;
}
inline static uint32_t SHA_START_REG(esp_sha_type sha_type) {
return SHA_1_START_REG + sha_type * 0x10;
}
inline static uint32_t SHA_CONTINUE_REG(esp_sha_type sha_type) {
return SHA_1_CONTINUE_REG + sha_type * 0x10;
}
/* Single spinlock for SHA engine memory block
*/
static portMUX_TYPE memory_block_lock = portMUX_INITIALIZER_UNLOCKED;
/* Binary semaphore managing the state of each concurrent SHA engine.
Available = noone is using this SHA engine
Taken = a SHA session is running on this SHA engine
Indexes:
0 = SHA1
1 = SHA2_256
2 = SHA2_384 or SHA2_512
*/
static SemaphoreHandle_t engine_states[3];
static uint8_t engines_in_use;
/* Spinlock for engines_in_use counter
*/
static portMUX_TYPE engines_in_use_lock = portMUX_INITIALIZER_UNLOCKED;
/* Index into the engine_states array */
inline static size_t sha_engine_index(esp_sha_type type) {
switch(type) {
case SHA1:
return 0;
case SHA2_256:
return 1;
default:
return 2;
}
}
/* Return digest length (in bytes) for a given SHA type */
inline static size_t sha_length(esp_sha_type type) {
switch(type) {
case SHA1:
return 20;
case SHA2_256:
return 32;
case SHA2_384:
return 48;
case SHA2_512:
return 64;
default:
return 0;
}
}
/* Return block size (in bytes) for a given SHA type */
inline static size_t block_length(esp_sha_type type) {
switch(type) {
case SHA1:
case SHA2_256:
return 64;
case SHA2_384:
case SHA2_512:
return 128;
default:
return 0;
}
}
void esp_sha_lock_memory_block(void)
{
portENTER_CRITICAL(&memory_block_lock);
}
void esp_sha_unlock_memory_block(void)
{
portEXIT_CRITICAL(&memory_block_lock);
}
static SemaphoreHandle_t sha_get_engine_state(esp_sha_type sha_type)
{
unsigned idx = sha_engine_index(sha_type);
volatile SemaphoreHandle_t *engine = &engine_states[idx];
SemaphoreHandle_t result = *engine;
uint32_t set_engine = 0;
if (result == NULL) {
// Create a new semaphore for 'in use' flag
SemaphoreHandle_t new_engine = xSemaphoreCreateBinary();
assert(new_engine != NULL);
xSemaphoreGive(new_engine); // start available
// try to atomically set the previously NULL *engine to new_engine
set_engine = (uint32_t)new_engine;
uxPortCompareSet((volatile uint32_t *)engine, 0, &set_engine);
if (set_engine != 0) { // we lost a race setting *engine
vSemaphoreDelete(new_engine);
}
result = *engine;
}
return result;
}
static bool esp_sha_lock_engine_common(esp_sha_type sha_type, TickType_t ticks_to_wait);
bool esp_sha_try_lock_engine(esp_sha_type sha_type)
{
return esp_sha_lock_engine_common(sha_type, 0);
}
void esp_sha_lock_engine(esp_sha_type sha_type)
{
esp_sha_lock_engine_common(sha_type, portMAX_DELAY);
}
static bool esp_sha_lock_engine_common(esp_sha_type sha_type, TickType_t ticks_to_wait)
{
SemaphoreHandle_t engine_state = sha_get_engine_state(sha_type);
BaseType_t result = xSemaphoreTake(engine_state, ticks_to_wait);
if (result == pdFALSE) {
// failed to take semaphore
return false;
}
portENTER_CRITICAL(&engines_in_use_lock);
if (engines_in_use == 0) {
/* Just locked first engine,
so enable SHA hardware */
periph_module_enable(PERIPH_SHA_MODULE);
}
engines_in_use++;
assert(engines_in_use <= 3);
portEXIT_CRITICAL(&engines_in_use_lock);
return true;
}
void esp_sha_unlock_engine(esp_sha_type sha_type)
{
SemaphoreHandle_t *engine_state = sha_get_engine_state(sha_type);
portENTER_CRITICAL(&engines_in_use_lock);
engines_in_use--;
if (engines_in_use == 0) {
/* About to release last engine, so
disable SHA hardware */
periph_module_disable(PERIPH_SHA_MODULE);
}
portEXIT_CRITICAL(&engines_in_use_lock);
xSemaphoreGive(engine_state);
}
void esp_sha_wait_idle(void)
{
while(1) {
if(DPORT_REG_READ(SHA_1_BUSY_REG) == 0
&& DPORT_REG_READ(SHA_256_BUSY_REG) == 0
&& DPORT_REG_READ(SHA_384_BUSY_REG) == 0
&& DPORT_REG_READ(SHA_512_BUSY_REG) == 0) {
break;
}
}
}
void esp_sha_read_digest_state(esp_sha_type sha_type, void *digest_state)
{
uint32_t *digest_state_words = NULL;
uint32_t *reg_addr_buf = NULL;
uint32_t word_len = sha_length(sha_type)/4;
#ifndef NDEBUG
{
SemaphoreHandle_t *engine_state = sha_get_engine_state(sha_type);
assert(uxSemaphoreGetCount(engine_state) == 0 &&
"SHA engine should be locked" );
}
#endif
// preemptively do this before entering the critical section, then re-check once in it
esp_sha_wait_idle();
esp_sha_lock_memory_block();
esp_sha_wait_idle();
DPORT_REG_WRITE(SHA_LOAD_REG(sha_type), 1);
while(DPORT_REG_READ(SHA_BUSY_REG(sha_type)) == 1) { }
digest_state_words = (uint32_t *)digest_state;
reg_addr_buf = (uint32_t *)(SHA_TEXT_BASE);
if(sha_type == SHA2_384 || sha_type == SHA2_512) {
/* for these ciphers using 64-bit states, swap each pair of words */
DPORT_INTERRUPT_DISABLE(); // Disable interrupt only on current CPU.
for(int i = 0; i < word_len; i += 2) {
digest_state_words[i+1] = DPORT_SEQUENCE_REG_READ((uint32_t)&reg_addr_buf[i]);
digest_state_words[i] = DPORT_SEQUENCE_REG_READ((uint32_t)&reg_addr_buf[i+1]);
}
DPORT_INTERRUPT_RESTORE(); // restore the previous interrupt level
} else {
esp_dport_access_read_buffer(digest_state_words, (uint32_t)&reg_addr_buf[0], word_len);
}
esp_sha_unlock_memory_block();
/* Fault injection check: verify SHA engine actually ran,
state is not all zeroes.
*/
for (int i = 0; i < word_len; i++) {
if (digest_state_words[i] != 0) {
return;
}
}
abort(); // SHA peripheral returned all zero state, probably due to fault injection
}
void esp_sha_block(esp_sha_type sha_type, const void *data_block, bool is_first_block)
{
uint32_t *reg_addr_buf = NULL;
uint32_t *data_words = NULL;
#ifndef NDEBUG
{
SemaphoreHandle_t *engine_state = sha_get_engine_state(sha_type);
assert(uxSemaphoreGetCount(engine_state) == 0 &&
"SHA engine should be locked" );
}
#endif
// preemptively do this before entering the critical section, then re-check once in it
esp_sha_wait_idle();
esp_sha_lock_memory_block();
esp_sha_wait_idle();
/* Fill the data block */
reg_addr_buf = (uint32_t *)(SHA_TEXT_BASE);
data_words = (uint32_t *)data_block;
for (int i = 0; i < block_length(sha_type) / 4; i++) {
reg_addr_buf[i] = __builtin_bswap32(data_words[i]);
}
asm volatile ("memw");
if(is_first_block) {
DPORT_REG_WRITE(SHA_START_REG(sha_type), 1);
} else {
DPORT_REG_WRITE(SHA_CONTINUE_REG(sha_type), 1);
}
esp_sha_unlock_memory_block();
/* Note: deliberately not waiting for this operation to complete,
as a performance tweak - delay waiting until the next time we need the SHA
unit, instead.
*/
}

View File

@ -0,0 +1,683 @@
/**
* \brief Multi-precision integer library, ESP32 hardware accelerated parts
*
* based on mbedTLS implementation
*
* Copyright (C) 2006-2015, ARM Limited, All Rights Reserved
* Additions Copyright (C) 2016, Espressif Systems (Shanghai) PTE Ltd
* SPDX-License-Identifier: Apache-2.0
*
* Licensed under the Apache License, Version 2.0 (the "License"); you may
* not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
*/
#include <stdio.h>
#include <string.h>
#include <malloc.h>
#include <limits.h>
#include <assert.h>
#include <stdlib.h>
#include <sys/param.h>
#include "esp32/rom/bigint.h"
#include "soc/hwcrypto_periph.h"
#include "esp_system.h"
#include "esp_log.h"
#include "esp_intr_alloc.h"
#include "esp_attr.h"
#include <mbedtls/bignum.h>
#include "freertos/FreeRTOS.h"
#include "freertos/task.h"
#include "freertos/semphr.h"
#include "driver/periph_ctrl.h"
/* Some implementation notes:
*
* - Naming convention x_words, y_words, z_words for number of words (limbs) used in a particular
* bignum. This number may be less than the size of the bignum
*
* - Naming convention hw_words for the hardware length of the operation. This number is always
* rounded up to a 512 bit multiple, and may be larger than any of the numbers involved in the
* calculation.
*
* - Timing behaviour of these functions will depend on the length of the inputs. This is fundamentally
* the same constraint as the software mbedTLS implementations, and relies on the same
* countermeasures (exponent blinding, etc) which are used in mbedTLS.
*/
static const __attribute__((unused)) char *TAG = "bignum";
#define ciL (sizeof(mbedtls_mpi_uint)) /* chars in limb */
#define biL (ciL << 3) /* bits in limb */
#if defined(CONFIG_MBEDTLS_MPI_USE_INTERRUPT)
static SemaphoreHandle_t op_complete_sem;
static IRAM_ATTR void rsa_complete_isr(void *arg)
{
BaseType_t higher_woken;
DPORT_REG_WRITE(RSA_INTERRUPT_REG, 1);
xSemaphoreGiveFromISR(op_complete_sem, &higher_woken);
if (higher_woken) {
portYIELD_FROM_ISR();
}
}
static void rsa_isr_initialise(void)
{
if (op_complete_sem == NULL) {
op_complete_sem = xSemaphoreCreateBinary();
esp_intr_alloc(ETS_RSA_INTR_SOURCE, 0, rsa_complete_isr, NULL, NULL);
}
}
#endif /* CONFIG_MBEDTLS_MPI_USE_INTERRUPT */
static _lock_t mpi_lock;
void esp_mpi_acquire_hardware( void )
{
/* newlib locks lazy initialize on ESP-IDF */
_lock_acquire(&mpi_lock);
/* Enable RSA hardware */
periph_module_enable(PERIPH_RSA_MODULE);
DPORT_REG_CLR_BIT(DPORT_RSA_PD_CTRL_REG, DPORT_RSA_PD);
while(DPORT_REG_READ(RSA_CLEAN_REG) != 1);
// Note: from enabling RSA clock to here takes about 1.3us
#ifdef CONFIG_MBEDTLS_MPI_USE_INTERRUPT
rsa_isr_initialise();
#endif
}
void esp_mpi_release_hardware( void )
{
DPORT_REG_SET_BIT(DPORT_RSA_PD_CTRL_REG, DPORT_RSA_PD);
/* Disable RSA hardware */
periph_module_disable(PERIPH_RSA_MODULE);
_lock_release(&mpi_lock);
}
/* Convert bit count to word count
*/
static inline size_t bits_to_words(size_t bits)
{
return (bits + 31) / 32;
}
/* Round up number of words to nearest
512 bit (16 word) block count.
*/
static inline size_t hardware_words(size_t words)
{
return (words + 0xF) & ~0xF;
}
/* Number of words used to hold 'mpi'.
Equivalent of bits_to_words(mbedtls_mpi_bitlen(mpi)), but uses less cycles if the
exact bit count is not needed.
Note that mpi->n (size of memory buffer) may be higher than this
number, if the high bits are mostly zeroes.
*/
static inline size_t word_length(const mbedtls_mpi *mpi)
{
for(size_t i = mpi->n; i > 0; i--) {
if( mpi->p[i - 1] != 0 ) {
return i;
}
}
return 0;
}
/* Copy mbedTLS MPI bignum 'mpi' to hardware memory block at 'mem_base'.
If hw_words is higher than the number of words in the bignum then
these additional words will be zeroed in the memory buffer.
*/
static inline void mpi_to_mem_block(uint32_t mem_base, const mbedtls_mpi *mpi, size_t hw_words)
{
uint32_t *pbase = (uint32_t *)mem_base;
uint32_t copy_words = hw_words < mpi->n ? hw_words : mpi->n;
/* Copy MPI data to memory block registers */
for (int i = 0; i < copy_words; i++) {
pbase[i] = mpi->p[i];
}
/* Zero any remaining memory block data */
for (int i = copy_words; i < hw_words; i++) {
pbase[i] = 0;
}
/* Note: not executing memw here, can do it before we start a bignum operation */
}
/* Read mbedTLS MPI bignum back from hardware memory block.
Reads num_words words from block.
Bignum 'x' should already be grown to at least num_words by caller (can be done while
calculation is in progress, to save some cycles)
*/
static inline void mem_block_to_mpi(mbedtls_mpi *x, uint32_t mem_base, int num_words)
{
assert(x->n >= num_words);
/* Copy data from memory block registers */
esp_dport_access_read_buffer(x->p, mem_base, num_words);
/* Zero any remaining limbs in the bignum, if the buffer is bigger
than num_words */
for(size_t i = num_words; i < x->n; i++) {
x->p[i] = 0;
}
}
/**
*
* There is a need for the value of integer N' such that B^-1(B-1)-N^-1N'=1,
* where B^-1(B-1) mod N=1. Actually, only the least significant part of
* N' is needed, hence the definition N0'=N' mod b. We reproduce below the
* simple algorithm from an article by Dusse and Kaliski to efficiently
* find N0' from N0 and b
*/
static mbedtls_mpi_uint modular_inverse(const mbedtls_mpi *M)
{
int i;
uint64_t t = 1;
uint64_t two_2_i_minus_1 = 2; /* 2^(i-1) */
uint64_t two_2_i = 4; /* 2^i */
uint64_t N = M->p[0];
for (i = 2; i <= 32; i++) {
if ((mbedtls_mpi_uint) N * t % two_2_i >= two_2_i_minus_1) {
t += two_2_i_minus_1;
}
two_2_i_minus_1 <<= 1;
two_2_i <<= 1;
}
return (mbedtls_mpi_uint)(UINT32_MAX - t + 1);
}
/* Calculate Rinv = RR^2 mod M, where:
*
* R = b^n where b = 2^32, n=num_words,
* R = 2^N (where N=num_bits)
* RR = R^2 = 2^(2*N) (where N=num_bits=num_words*32)
*
* This calculation is computationally expensive (mbedtls_mpi_mod_mpi)
* so caller should cache the result where possible.
*
* DO NOT call this function while holding esp_mpi_acquire_hardware().
*
*/
static int calculate_rinv(mbedtls_mpi *Rinv, const mbedtls_mpi *M, int num_words)
{
int ret;
size_t num_bits = num_words * 32;
mbedtls_mpi RR;
mbedtls_mpi_init(&RR);
MBEDTLS_MPI_CHK(mbedtls_mpi_set_bit(&RR, num_bits * 2, 1));
MBEDTLS_MPI_CHK(mbedtls_mpi_mod_mpi(Rinv, &RR, M));
cleanup:
mbedtls_mpi_free(&RR);
return ret;
}
/* Begin an RSA operation. op_reg specifies which 'START' register
to write to.
*/
static inline void start_op(uint32_t op_reg)
{
/* Clear interrupt status */
DPORT_REG_WRITE(RSA_INTERRUPT_REG, 1);
/* Note: above REG_WRITE includes a memw, so we know any writes
to the memory blocks are also complete. */
DPORT_REG_WRITE(op_reg, 1);
}
/* Wait for an RSA operation to complete.
*/
static inline void wait_op_complete(uint32_t op_reg)
{
#ifdef CONFIG_MBEDTLS_MPI_USE_INTERRUPT
if (!xSemaphoreTake(op_complete_sem, 2000 / portTICK_PERIOD_MS)) {
ESP_LOGE(TAG, "Timed out waiting for RSA operation (op_reg 0x%x int_reg 0x%x)",
op_reg, DPORT_REG_READ(RSA_INTERRUPT_REG));
abort(); /* indicates a fundamental problem with driver */
}
#else
while(DPORT_REG_READ(RSA_INTERRUPT_REG) != 1)
{ }
/* clear the interrupt */
DPORT_REG_WRITE(RSA_INTERRUPT_REG, 1);
#endif
}
/* Sub-stages of modulo multiplication/exponentiation operations */
inline static int modular_multiply_finish(mbedtls_mpi *Z, const mbedtls_mpi *X, const mbedtls_mpi *Y, size_t hw_words, size_t z_words);
/* Z = (X * Y) mod M
Not an mbedTLS function
*/
int esp_mpi_mul_mpi_mod(mbedtls_mpi *Z, const mbedtls_mpi *X, const mbedtls_mpi *Y, const mbedtls_mpi *M)
{
int ret;
size_t x_bits = mbedtls_mpi_bitlen(X);
size_t y_bits = mbedtls_mpi_bitlen(Y);
size_t m_bits = mbedtls_mpi_bitlen(M);
size_t z_bits = MIN(m_bits, x_bits + y_bits);
size_t x_words = bits_to_words(x_bits);
size_t y_words = bits_to_words(y_bits);
size_t m_words = bits_to_words(m_bits);
size_t z_words = bits_to_words(z_bits);
size_t hw_words = hardware_words(MAX(x_words, MAX(y_words, m_words))); /* longest operand */
mbedtls_mpi Rinv;
mbedtls_mpi_uint Mprime;
/* Calculate and load the first stage montgomery multiplication */
mbedtls_mpi_init(&Rinv);
MBEDTLS_MPI_CHK(calculate_rinv(&Rinv, M, hw_words));
Mprime = modular_inverse(M);
esp_mpi_acquire_hardware();
/* Load M, X, Rinv, Mprime (Mprime is mod 2^32) */
mpi_to_mem_block(RSA_MEM_M_BLOCK_BASE, M, hw_words);
mpi_to_mem_block(RSA_MEM_X_BLOCK_BASE, X, hw_words);
mpi_to_mem_block(RSA_MEM_RB_BLOCK_BASE, &Rinv, hw_words);
DPORT_REG_WRITE(RSA_M_DASH_REG, (uint32_t)Mprime);
/* "mode" register loaded with number of 512-bit blocks, minus 1 */
DPORT_REG_WRITE(RSA_MULT_MODE_REG, (hw_words / 16) - 1);
/* Execute first stage montgomery multiplication */
start_op(RSA_MULT_START_REG);
wait_op_complete(RSA_MULT_START_REG);
/* execute second stage */
ret = modular_multiply_finish(Z, X, Y, hw_words, z_words);
esp_mpi_release_hardware();
cleanup:
mbedtls_mpi_free(&Rinv);
return ret;
}
#if defined(MBEDTLS_MPI_EXP_MOD_ALT)
/*
* Sliding-window exponentiation: Z = X^Y mod M (HAC 14.85)
*
* _Rinv is optional pre-calculated version of Rinv (via calculate_rinv()).
*
* (See RSA Accelerator section in Technical Reference for more about Mprime, Rinv)
*
*/
int mbedtls_mpi_exp_mod( mbedtls_mpi* Z, const mbedtls_mpi* X, const mbedtls_mpi* Y, const mbedtls_mpi* M, mbedtls_mpi* _Rinv )
{
int ret = 0;
size_t x_words = word_length(X);
size_t y_words = word_length(Y);
size_t m_words = word_length(M);
/* "all numbers must be the same length", so choose longest number
as cardinal length of operation...
*/
size_t hw_words = hardware_words(MAX(m_words, MAX(x_words, y_words)));
mbedtls_mpi Rinv_new; /* used if _Rinv == NULL */
mbedtls_mpi *Rinv; /* points to _Rinv (if not NULL) othwerwise &RR_new */
mbedtls_mpi_uint Mprime;
if (mbedtls_mpi_cmp_int(M, 0) <= 0 || (M->p[0] & 1) == 0) {
return MBEDTLS_ERR_MPI_BAD_INPUT_DATA;
}
if (mbedtls_mpi_cmp_int(Y, 0) < 0) {
return MBEDTLS_ERR_MPI_BAD_INPUT_DATA;
}
if (mbedtls_mpi_cmp_int(Y, 0) == 0) {
return mbedtls_mpi_lset(Z, 1);
}
if (hw_words * 32 > 4096) {
return MBEDTLS_ERR_MPI_NOT_ACCEPTABLE;
}
/* Determine RR pointer, either _RR for cached value
or local RR_new */
if (_Rinv == NULL) {
mbedtls_mpi_init(&Rinv_new);
Rinv = &Rinv_new;
} else {
Rinv = _Rinv;
}
if (Rinv->p == NULL) {
MBEDTLS_MPI_CHK(calculate_rinv(Rinv, M, hw_words));
}
Mprime = modular_inverse(M);
esp_mpi_acquire_hardware();
/* "mode" register loaded with number of 512-bit blocks, minus 1 */
DPORT_REG_WRITE(RSA_MODEXP_MODE_REG, (hw_words / 16) - 1);
/* Load M, X, Rinv, M-prime (M-prime is mod 2^32) */
mpi_to_mem_block(RSA_MEM_X_BLOCK_BASE, X, hw_words);
mpi_to_mem_block(RSA_MEM_Y_BLOCK_BASE, Y, hw_words);
mpi_to_mem_block(RSA_MEM_M_BLOCK_BASE, M, hw_words);
mpi_to_mem_block(RSA_MEM_RB_BLOCK_BASE, Rinv, hw_words);
DPORT_REG_WRITE(RSA_M_DASH_REG, Mprime);
start_op(RSA_START_MODEXP_REG);
/* X ^ Y may actually be shorter than M, but unlikely when used for crypto */
if ((ret = mbedtls_mpi_grow(Z, m_words)) != 0) {
esp_mpi_release_hardware();
goto cleanup;
}
wait_op_complete(RSA_START_MODEXP_REG);
mem_block_to_mpi(Z, RSA_MEM_Z_BLOCK_BASE, m_words);
esp_mpi_release_hardware();
// Compensate for negative X
if (X->s == -1 && (Y->p[0] & 1) != 0) {
Z->s = -1;
MBEDTLS_MPI_CHK(mbedtls_mpi_add_mpi(Z, M, Z));
} else {
Z->s = 1;
}
cleanup:
if (_Rinv == NULL) {
mbedtls_mpi_free(&Rinv_new);
}
return ret;
}
#endif /* MBEDTLS_MPI_EXP_MOD_ALT */
/* Second & final step of a modular multiply - load second multiplication
* factor Y, run the operation (modular inverse), read back the result
* into Z.
*
* Called from both mbedtls_mpi_exp_mod and mbedtls_mpi_mod_mpi.
*
* @param Z result value
* @param X first multiplication factor (used to set sign of result).
* @param Y second multiplication factor.
* @param hw_words Size of the hardware operation, in words
* @param z_words Size of the expected result, in words (may be less than hw_words).
* Z will be grown to at least this length.
*
* Caller must have already called esp_mpi_acquire_hardware().
*/
static int modular_multiply_finish(mbedtls_mpi *Z, const mbedtls_mpi *X, const mbedtls_mpi *Y, size_t hw_words, size_t z_words)
{
int ret = 0;
/* Load Y to X input memory block, rerun */
mpi_to_mem_block(RSA_MEM_X_BLOCK_BASE, Y, hw_words);
start_op(RSA_MULT_START_REG);
MBEDTLS_MPI_CHK( mbedtls_mpi_grow(Z, z_words) );
wait_op_complete(RSA_MULT_START_REG);
mem_block_to_mpi(Z, RSA_MEM_Z_BLOCK_BASE, z_words);
Z->s = X->s * Y->s;
cleanup:
return ret;
}
#if defined(MBEDTLS_MPI_MUL_MPI_ALT) /* MBEDTLS_MPI_MUL_MPI_ALT */
static int mpi_mult_mpi_failover_mod_mult(mbedtls_mpi *Z, const mbedtls_mpi *X, const mbedtls_mpi *Y, size_t z_words);
static int mpi_mult_mpi_overlong(mbedtls_mpi *Z, const mbedtls_mpi *X, const mbedtls_mpi *Y, size_t Y_bits, size_t z_words);
/* Z = X * Y */
int mbedtls_mpi_mul_mpi( mbedtls_mpi *Z, const mbedtls_mpi *X, const mbedtls_mpi *Y )
{
int ret = 0;
size_t x_bits = mbedtls_mpi_bitlen(X);
size_t y_bits = mbedtls_mpi_bitlen(Y);
size_t x_words = bits_to_words(x_bits);
size_t y_words = bits_to_words(y_bits);
size_t z_words = bits_to_words(x_bits + y_bits);
size_t hw_words = hardware_words(MAX(x_words, y_words)); // length of one operand in hardware
/* Short-circuit eval if either argument is 0 or 1.
This is needed as the mpi modular division
argument will sometimes call in here when one
argument is too large for the hardware unit, but the other
argument is zero or one.
*/
if (x_bits == 0 || y_bits == 0) {
mbedtls_mpi_lset(Z, 0);
return 0;
}
if (x_bits == 1) {
ret = mbedtls_mpi_copy(Z, Y);
Z->s *= X->s;
return ret;
}
if (y_bits == 1) {
ret = mbedtls_mpi_copy(Z, X);
Z->s *= Y->s;
return ret;
}
/* If either factor is over 2048 bits, we can't use the standard hardware multiplier
(it assumes result is double longest factor, and result is max 4096 bits.)
However, we can fail over to mod_mult for up to 4096 bits of result (modulo
multiplication doesn't have the same restriction, so result is simply the
number of bits in X plus number of bits in in Y.)
*/
if (hw_words * 32 > 2048) {
if (z_words * 32 <= 4096) {
/* Note: it's possible to use mpi_mult_mpi_overlong
for this case as well, but it's very slightly
slower and requires a memory allocation.
*/
return mpi_mult_mpi_failover_mod_mult(Z, X, Y, z_words);
} else {
/* Still too long for the hardware unit... */
if(y_words > x_words) {
return mpi_mult_mpi_overlong(Z, X, Y, y_words, z_words);
} else {
return mpi_mult_mpi_overlong(Z, Y, X, x_words, z_words);
}
}
}
/* Otherwise, we can use the (faster) multiply hardware unit */
esp_mpi_acquire_hardware();
/* Copy X (right-extended) & Y (left-extended) to memory block */
mpi_to_mem_block(RSA_MEM_X_BLOCK_BASE, X, hw_words);
mpi_to_mem_block(RSA_MEM_Z_BLOCK_BASE + hw_words * 4, Y, hw_words);
/* NB: as Y is left-extended, we don't zero the bottom words_mult words of Y block.
This is OK for now because zeroing is done by hardware when we do esp_mpi_acquire_hardware().
*/
DPORT_REG_WRITE(RSA_M_DASH_REG, 0);
/* "mode" register loaded with number of 512-bit blocks in result,
plus 7 (for range 9-12). (this is ((N~ / 32) - 1) + 8))
*/
DPORT_REG_WRITE(RSA_MULT_MODE_REG, ((hw_words * 2) / 16) + 7);
start_op(RSA_MULT_START_REG);
MBEDTLS_MPI_CHK( mbedtls_mpi_grow(Z, z_words) );
wait_op_complete(RSA_MULT_START_REG);
/* Read back the result */
mem_block_to_mpi(Z, RSA_MEM_Z_BLOCK_BASE, z_words);
Z->s = X->s * Y->s;
cleanup:
esp_mpi_release_hardware();
return ret;
}
/* Special-case of mbedtls_mpi_mult_mpi(), where we use hardware montgomery mod
multiplication to calculate an mbedtls_mpi_mult_mpi result where either
A or B are >2048 bits so can't use the standard multiplication method.
Result (z_words, based on A bits + B bits) must still be less than 4096 bits.
This case is simpler than the general case modulo multiply of
esp_mpi_mul_mpi_mod() because we can control the other arguments:
* Modulus is chosen with M=(2^num_bits - 1) (ie M=R-1), so output
isn't actually modulo anything.
* Mprime and Rinv are therefore predictable as follows:
Mprime = 1
Rinv = 1
(See RSA Accelerator section in Technical Reference for more about Mprime, Rinv)
*/
static int mpi_mult_mpi_failover_mod_mult(mbedtls_mpi *Z, const mbedtls_mpi *X, const mbedtls_mpi *Y, size_t z_words)
{
int ret = 0;
size_t hw_words = hardware_words(z_words);
/* Load coefficients to hardware */
esp_mpi_acquire_hardware();
/* M = 2^num_words - 1, so block is entirely FF */
for(int i = 0; i < hw_words; i++) {
DPORT_REG_WRITE(RSA_MEM_M_BLOCK_BASE + i * 4, UINT32_MAX);
}
/* Mprime = 1 */
DPORT_REG_WRITE(RSA_M_DASH_REG, 1);
/* "mode" register loaded with number of 512-bit blocks, minus 1 */
DPORT_REG_WRITE(RSA_MULT_MODE_REG, (hw_words / 16) - 1);
/* Load X */
mpi_to_mem_block(RSA_MEM_X_BLOCK_BASE, X, hw_words);
/* Rinv = 1 */
DPORT_REG_WRITE(RSA_MEM_RB_BLOCK_BASE, 1);
for(int i = 1; i < hw_words; i++) {
DPORT_REG_WRITE(RSA_MEM_RB_BLOCK_BASE + i * 4, 0);
}
start_op(RSA_MULT_START_REG);
wait_op_complete(RSA_MULT_START_REG);
/* finish the modular multiplication */
ret = modular_multiply_finish(Z, X, Y, hw_words, z_words);
esp_mpi_release_hardware();
return ret;
}
/* Deal with the case when X & Y are too long for the hardware unit, by splitting one operand
into two halves.
Y must be the longer operand
Slice Y into Yp, Ypp such that:
Yp = lower 'b' bits of Y
Ypp = upper 'b' bits of Y (right shifted)
Such that
Z = X * Y
Z = X * (Yp + Ypp<<b)
Z = (X * Yp) + (X * Ypp<<b)
Note that this function may recurse multiple times, if both X & Y
are too long for the hardware multiplication unit.
*/
static int mpi_mult_mpi_overlong(mbedtls_mpi *Z, const mbedtls_mpi *X, const mbedtls_mpi *Y, size_t y_words, size_t z_words)
{
int ret = 0;
mbedtls_mpi Ztemp;
/* Rather than slicing in two on bits we slice on limbs (32 bit words) */
const size_t words_slice = y_words / 2;
/* Yp holds lower bits of Y (declared to reuse Y's array contents to save on copying) */
const mbedtls_mpi Yp = {
.p = Y->p,
.n = words_slice,
.s = Y->s
};
/* Ypp holds upper bits of Y, right shifted (also reuses Y's array contents) */
const mbedtls_mpi Ypp = {
.p = Y->p + words_slice,
.n = y_words - words_slice,
.s = Y->s
};
mbedtls_mpi_init(&Ztemp);
/* Grow Z to result size early, avoid interim allocations */
mbedtls_mpi_grow(Z, z_words);
/* Get result Ztemp = Yp * X (need temporary variable Ztemp) */
MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi(&Ztemp, X, &Yp) );
/* Z = Ypp * Y */
MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi(Z, X, &Ypp) );
/* Z = Z << b */
MBEDTLS_MPI_CHK( mbedtls_mpi_shift_l(Z, words_slice * 32) );
/* Z += Ztemp */
MBEDTLS_MPI_CHK( mbedtls_mpi_add_mpi(Z, Z, &Ztemp) );
cleanup:
mbedtls_mpi_free(&Ztemp);
return ret;
}
#endif /* MBEDTLS_MPI_MUL_MPI_ALT */

View File

@ -0,0 +1,26 @@
#if !defined(MBEDTLS_CONFIG_FILE)
#include "mbedtls/config.h"
#else
#include MBEDTLS_CONFIG_FILE
#endif
#include <sys/types.h>
#include <stdlib.h>
#include <stdio.h>
#include <esp_system.h>
#include "mbedtls/entropy_poll.h"
#ifndef MBEDTLS_ENTROPY_HARDWARE_ALT
#error "MBEDTLS_ENTROPY_HARDWARE_ALT should always be set in ESP-IDF"
#endif
int mbedtls_hardware_poll( void *data,
unsigned char *output, size_t len, size_t *olen )
{
esp_fill_random(output, len);
*olen = len;
return 0;
}

View File

@ -0,0 +1,38 @@
// Copyright 2018 Espressif Systems (Shanghai) PTE LTD
//
// 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 <esp_attr.h>
#include <esp_heap_caps.h>
#include <sdkconfig.h>
#include "esp_mem.h"
#ifndef CONFIG_MBEDTLS_CUSTOM_MEM_ALLOC
IRAM_ATTR void *esp_mbedtls_mem_calloc(size_t n, size_t size)
{
#ifdef CONFIG_MBEDTLS_INTERNAL_MEM_ALLOC
return heap_caps_calloc(n, size, MALLOC_CAP_INTERNAL|MALLOC_CAP_8BIT);
#elif CONFIG_MBEDTLS_EXTERNAL_MEM_ALLOC
return heap_caps_calloc(n, size, MALLOC_CAP_SPIRAM|MALLOC_CAP_8BIT);
#else
return calloc(n, size);
#endif
}
IRAM_ATTR void esp_mbedtls_mem_free(void *ptr)
{
return heap_caps_free(ptr);
}
#endif /* !CONFIG_MBEDTLS_CUSTOM_MEM_ALLOC */

View File

@ -0,0 +1,79 @@
// Copyright 2018-2019 Espressif Systems (Shanghai) PTE LTD
//
// 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 <string.h>
#include <stdio.h>
#include <assert.h>
#include "esp32/sha.h"
#include <mbedtls/sha1.h>
#include <mbedtls/sha256.h>
#include <mbedtls/sha512.h>
void esp_sha(esp_sha_type sha_type, const unsigned char *input, size_t ilen, unsigned char *output)
{
int ret;
assert(input != NULL && output != NULL);
if (sha_type == SHA1) {
mbedtls_sha1_context *ctx1 = (mbedtls_sha1_context *)malloc(sizeof(mbedtls_sha1_context));
assert(ctx1 != NULL);
mbedtls_sha1_starts_ret(ctx1);
ret = mbedtls_sha1_update_ret(ctx1, input, ilen);
assert(ret == 0);
ret = mbedtls_sha1_finish_ret(ctx1, output);
assert(ret == 0);
mbedtls_sha1_free(ctx1);
free(ctx1);
} else if (sha_type == SHA2_256) {
mbedtls_sha256_context *ctx256 = (mbedtls_sha256_context *)malloc(sizeof(mbedtls_sha256_context));
assert(ctx256 != NULL);
mbedtls_sha256_starts_ret(ctx256, 0);
ret = mbedtls_sha256_update_ret(ctx256, input, ilen);
assert(ret == 0);
ret = mbedtls_sha256_finish_ret(ctx256, output);
assert(ret == 0);
mbedtls_sha256_free(ctx256);
free(ctx256);
} else if (sha_type == SHA2_384) {
mbedtls_sha512_context *ctx384 = (mbedtls_sha512_context *)malloc(sizeof(mbedtls_sha512_context));
assert(ctx384 != NULL);
mbedtls_sha512_starts_ret(ctx384, 1);
ret = mbedtls_sha512_update_ret(ctx384, input, ilen);
assert(ret == 0);
ret = mbedtls_sha512_finish_ret(ctx384, output);
assert(ret == 0);
mbedtls_sha512_free(ctx384);
free(ctx384);
} else if (sha_type == SHA2_512) {
mbedtls_sha512_context *ctx512 = (mbedtls_sha512_context *)malloc(sizeof(mbedtls_sha512_context));
assert(ctx512 != NULL);
mbedtls_sha512_starts_ret(ctx512, 0);
ret = mbedtls_sha512_update_ret(ctx512, input, ilen);
assert(ret == 0);
ret = mbedtls_sha512_finish_ret(ctx512, output);
assert(ret == 0);
mbedtls_sha512_free(ctx512);
free(ctx512);
}
}

View File

@ -0,0 +1,451 @@
/*
* SHA-1 implementation with hardware ESP32 support added.
* Uses mbedTLS software implementation for failover when concurrent
* SHA operations are in use.
*
* Copyright (C) 2006-2015, ARM Limited, All Rights Reserved
* Additions Copyright (C) 2016, Espressif Systems (Shanghai) PTE LTD
* 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.
*
*/
/*
* 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) && defined(MBEDTLS_SHA1_ALT)
#include "mbedtls/sha1.h"
#include <string.h>
#if defined(MBEDTLS_SELF_TEST)
#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 */
#include "esp32/sha.h"
/* Implementation that should never be optimized out by the compiler */
static void mbedtls_zeroize( void *v, size_t n ) {
volatile unsigned char *p = (unsigned char*)v; while( n-- ) *p++ = 0;
}
/*
* 32-bit integer manipulation macros (big endian)
*/
#ifndef GET_UINT32_BE
#define GET_UINT32_BE(n,b,i) \
{ \
(n) = ( (uint32_t) (b)[(i) ] << 24 ) \
| ( (uint32_t) (b)[(i) + 1] << 16 ) \
| ( (uint32_t) (b)[(i) + 2] << 8 ) \
| ( (uint32_t) (b)[(i) + 3] ); \
}
#endif
#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;
if (ctx->mode == ESP_MBEDTLS_SHA1_HARDWARE) {
esp_sha_unlock_engine(SHA1);
}
mbedtls_zeroize( ctx, sizeof( mbedtls_sha1_context ) );
}
void mbedtls_sha1_clone( mbedtls_sha1_context *dst,
const mbedtls_sha1_context *src )
{
*dst = *src;
if (src->mode == ESP_MBEDTLS_SHA1_HARDWARE) {
/* Copy hardware digest state out to cloned state,
which will be a software digest.
*/
esp_sha_read_digest_state(SHA1, dst->state);
dst->mode = ESP_MBEDTLS_SHA1_SOFTWARE;
}
}
/*
* SHA-1 context setup
*/
int mbedtls_sha1_starts_ret( mbedtls_sha1_context *ctx )
{
ctx->total[0] = 0;
ctx->total[1] = 0;
ctx->state[0] = 0x67452301;
ctx->state[1] = 0xEFCDAB89;
ctx->state[2] = 0x98BADCFE;
ctx->state[3] = 0x10325476;
ctx->state[4] = 0xC3D2E1F0;
if (ctx->mode == ESP_MBEDTLS_SHA1_HARDWARE) {
esp_sha_unlock_engine(SHA1);
}
ctx->mode = ESP_MBEDTLS_SHA1_UNUSED;
return 0;
}
#if !defined(MBEDTLS_DEPRECATED_REMOVED)
void mbedtls_sha1_starts( mbedtls_sha1_context *ctx )
{
mbedtls_sha1_starts_ret( ctx );
}
#endif
static void mbedtls_sha1_software_process( mbedtls_sha1_context *ctx, const unsigned char data[64] );
int mbedtls_internal_sha1_process( mbedtls_sha1_context *ctx, const unsigned char data[64] )
{
bool first_block = false;
if (ctx->mode == ESP_MBEDTLS_SHA1_UNUSED) {
/* try to use hardware for this digest */
if (esp_sha_try_lock_engine(SHA1)) {
ctx->mode = ESP_MBEDTLS_SHA1_HARDWARE;
first_block = true;
} else {
ctx->mode = ESP_MBEDTLS_SHA1_SOFTWARE;
}
}
if (ctx->mode == ESP_MBEDTLS_SHA1_HARDWARE) {
esp_sha_block(SHA1, data, first_block);
} else {
mbedtls_sha1_software_process(ctx, data);
}
return 0;
}
#if !defined(MBEDTLS_DEPRECATED_REMOVED)
void mbedtls_sha1_process( mbedtls_sha1_context *ctx,
const unsigned char data[64] )
{
mbedtls_internal_sha1_process( ctx, data );
}
#endif
static void mbedtls_sha1_software_process( mbedtls_sha1_context *ctx, const unsigned char data[64] )
{
uint32_t temp, W[16], A, B, C, D, E;
GET_UINT32_BE( W[ 0], data, 0 );
GET_UINT32_BE( W[ 1], data, 4 );
GET_UINT32_BE( W[ 2], data, 8 );
GET_UINT32_BE( W[ 3], data, 12 );
GET_UINT32_BE( W[ 4], data, 16 );
GET_UINT32_BE( W[ 5], data, 20 );
GET_UINT32_BE( W[ 6], data, 24 );
GET_UINT32_BE( W[ 7], data, 28 );
GET_UINT32_BE( W[ 8], data, 32 );
GET_UINT32_BE( W[ 9], data, 36 );
GET_UINT32_BE( W[10], data, 40 );
GET_UINT32_BE( W[11], data, 44 );
GET_UINT32_BE( W[12], data, 48 );
GET_UINT32_BE( W[13], data, 52 );
GET_UINT32_BE( W[14], data, 56 );
GET_UINT32_BE( W[15], data, 60 );
#define S(x,n) ((x << n) | ((x & 0xFFFFFFFF) >> (32 - n)))
#define R(t) \
( \
temp = W[( t - 3 ) & 0x0F] ^ W[( t - 8 ) & 0x0F] ^ \
W[( t - 14 ) & 0x0F] ^ W[ t & 0x0F], \
( W[t & 0x0F] = S(temp,1) ) \
)
#define P(a,b,c,d,e,x) \
{ \
e += S(a,5) + F(b,c,d) + K + x; b = S(b,30); \
}
A = ctx->state[0];
B = ctx->state[1];
C = ctx->state[2];
D = ctx->state[3];
E = ctx->state[4];
#define F(x,y,z) (z ^ (x & (y ^ z)))
#define K 0x5A827999
P( A, B, C, D, E, W[0] );
P( E, A, B, C, D, W[1] );
P( D, E, A, B, C, W[2] );
P( C, D, E, A, B, W[3] );
P( B, C, D, E, A, W[4] );
P( A, B, C, D, E, W[5] );
P( E, A, B, C, D, W[6] );
P( D, E, A, B, C, W[7] );
P( C, D, E, A, B, W[8] );
P( B, C, D, E, A, W[9] );
P( A, B, C, D, E, W[10] );
P( E, A, B, C, D, W[11] );
P( D, E, A, B, C, W[12] );
P( C, D, E, A, B, W[13] );
P( B, C, D, E, A, W[14] );
P( A, B, C, D, E, W[15] );
P( E, A, B, C, D, R(16) );
P( D, E, A, B, C, R(17) );
P( C, D, E, A, B, R(18) );
P( B, C, D, E, A, R(19) );
#undef K
#undef F
#define F(x,y,z) (x ^ y ^ z)
#define K 0x6ED9EBA1
P( A, B, C, D, E, R(20) );
P( E, A, B, C, D, R(21) );
P( D, E, A, B, C, R(22) );
P( C, D, E, A, B, R(23) );
P( B, C, D, E, A, R(24) );
P( A, B, C, D, E, R(25) );
P( E, A, B, C, D, R(26) );
P( D, E, A, B, C, R(27) );
P( C, D, E, A, B, R(28) );
P( B, C, D, E, A, R(29) );
P( A, B, C, D, E, R(30) );
P( E, A, B, C, D, R(31) );
P( D, E, A, B, C, R(32) );
P( C, D, E, A, B, R(33) );
P( B, C, D, E, A, R(34) );
P( A, B, C, D, E, R(35) );
P( E, A, B, C, D, R(36) );
P( D, E, A, B, C, R(37) );
P( C, D, E, A, B, R(38) );
P( B, C, D, E, A, R(39) );
#undef K
#undef F
#define F(x,y,z) ((x & y) | (z & (x | y)))
#define K 0x8F1BBCDC
P( A, B, C, D, E, R(40) );
P( E, A, B, C, D, R(41) );
P( D, E, A, B, C, R(42) );
P( C, D, E, A, B, R(43) );
P( B, C, D, E, A, R(44) );
P( A, B, C, D, E, R(45) );
P( E, A, B, C, D, R(46) );
P( D, E, A, B, C, R(47) );
P( C, D, E, A, B, R(48) );
P( B, C, D, E, A, R(49) );
P( A, B, C, D, E, R(50) );
P( E, A, B, C, D, R(51) );
P( D, E, A, B, C, R(52) );
P( C, D, E, A, B, R(53) );
P( B, C, D, E, A, R(54) );
P( A, B, C, D, E, R(55) );
P( E, A, B, C, D, R(56) );
P( D, E, A, B, C, R(57) );
P( C, D, E, A, B, R(58) );
P( B, C, D, E, A, R(59) );
#undef K
#undef F
#define F(x,y,z) (x ^ y ^ z)
#define K 0xCA62C1D6
P( A, B, C, D, E, R(60) );
P( E, A, B, C, D, R(61) );
P( D, E, A, B, C, R(62) );
P( C, D, E, A, B, R(63) );
P( B, C, D, E, A, R(64) );
P( A, B, C, D, E, R(65) );
P( E, A, B, C, D, R(66) );
P( D, E, A, B, C, R(67) );
P( C, D, E, A, B, R(68) );
P( B, C, D, E, A, R(69) );
P( A, B, C, D, E, R(70) );
P( E, A, B, C, D, R(71) );
P( D, E, A, B, C, R(72) );
P( C, D, E, A, B, R(73) );
P( B, C, D, E, A, R(74) );
P( A, B, C, D, E, R(75) );
P( E, A, B, C, D, R(76) );
P( D, E, A, B, C, R(77) );
P( C, D, E, A, B, R(78) );
P( B, C, D, E, A, R(79) );
#undef K
#undef F
ctx->state[0] += A;
ctx->state[1] += B;
ctx->state[2] += C;
ctx->state[3] += D;
ctx->state[4] += E;
}
/*
* SHA-1 process buffer
*/
int mbedtls_sha1_update_ret( mbedtls_sha1_context *ctx, const unsigned char *input, size_t ilen )
{
int ret;
size_t fill;
uint32_t left;
if( ilen == 0 )
return 0;
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 );
if ( ( ret = mbedtls_internal_sha1_process( ctx, ctx->buffer ) ) != 0 ) {
return ret;
}
input += fill;
ilen -= fill;
left = 0;
}
while( ilen >= 64 )
{
if ( ( ret = mbedtls_internal_sha1_process( ctx, input ) ) != 0 ) {
return ret;
}
input += 64;
ilen -= 64;
}
if( ilen > 0 )
memcpy( (void *) (ctx->buffer + left), input, ilen );
return 0;
}
#if !defined(MBEDTLS_DEPRECATED_REMOVED)
void mbedtls_sha1_update( mbedtls_sha1_context *ctx,
const unsigned char *input,
size_t ilen )
{
mbedtls_sha1_update_ret( ctx, input, ilen );
}
#endif
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
*/
int mbedtls_sha1_finish_ret( mbedtls_sha1_context *ctx, unsigned char output[20] )
{
int ret;
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 );
if ( ( ret = mbedtls_sha1_update_ret( ctx, sha1_padding, padn ) ) != 0 ) {
goto out;
}
if ( ( ret = mbedtls_sha1_update_ret( ctx, msglen, 8 ) ) != 0 ) {
goto out;
}
/* if state is in hardware, read it out */
if (ctx->mode == ESP_MBEDTLS_SHA1_HARDWARE) {
esp_sha_read_digest_state(SHA1, ctx->state);
}
PUT_UINT32_BE( ctx->state[0], output, 0 );
PUT_UINT32_BE( ctx->state[1], output, 4 );
PUT_UINT32_BE( ctx->state[2], output, 8 );
PUT_UINT32_BE( ctx->state[3], output, 12 );
PUT_UINT32_BE( ctx->state[4], output, 16 );
out:
if (ctx->mode == ESP_MBEDTLS_SHA1_HARDWARE) {
esp_sha_unlock_engine(SHA1);
ctx->mode = ESP_MBEDTLS_SHA1_SOFTWARE;
}
return ret;
}
#if !defined(MBEDTLS_DEPRECATED_REMOVED)
void mbedtls_sha1_finish( mbedtls_sha1_context *ctx,
unsigned char output[20] )
{
mbedtls_sha1_finish_ret( ctx, output );
}
#endif
#endif /* MBEDTLS_SHA1_C && MBEDTLS_SHA1_ALT */

View File

@ -0,0 +1,422 @@
/*
* SHA-256 implementation with hardware ESP32 support added.
* Uses mbedTLS software implementation for failover when concurrent
* SHA operations are in use.
*
* Copyright (C) 2006-2015, ARM Limited, All Rights Reserved
* Additions Copyright (C) 2016, Espressif Systems (Shanghai) PTE LTD
* 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.
*
*/
/*
* 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) && defined(MBEDTLS_SHA256_ALT)
#include "mbedtls/sha256.h"
#include <string.h>
#if defined(MBEDTLS_SELF_TEST)
#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 */
#include "esp32/sha.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 GET_UINT32_BE
#define GET_UINT32_BE(n,b,i) \
do { \
(n) = ( (uint32_t) (b)[(i) ] << 24 ) \
| ( (uint32_t) (b)[(i) + 1] << 16 ) \
| ( (uint32_t) (b)[(i) + 2] << 8 ) \
| ( (uint32_t) (b)[(i) + 3] ); \
} while( 0 )
#endif
#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;
if (ctx->mode == ESP_MBEDTLS_SHA256_HARDWARE) {
esp_sha_unlock_engine(SHA2_256);
}
mbedtls_zeroize( ctx, sizeof( mbedtls_sha256_context ) );
}
void mbedtls_sha256_clone( mbedtls_sha256_context *dst,
const mbedtls_sha256_context *src )
{
*dst = *src;
if (src->mode == ESP_MBEDTLS_SHA256_HARDWARE) {
/* Copy hardware digest state out to cloned state,
which will become a software digest.
*/
esp_sha_read_digest_state(SHA2_256, dst->state);
dst->mode = ESP_MBEDTLS_SHA256_SOFTWARE;
}
}
/*
* SHA-256 context setup
*/
int mbedtls_sha256_starts_ret( mbedtls_sha256_context *ctx, int is224 )
{
ctx->total[0] = 0;
ctx->total[1] = 0;
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->is224 = is224;
if (ctx->mode == ESP_MBEDTLS_SHA256_HARDWARE) {
esp_sha_unlock_engine(SHA2_256);
}
ctx->mode = ESP_MBEDTLS_SHA256_UNUSED;
return 0;
}
#if !defined(MBEDTLS_DEPRECATED_REMOVED)
void mbedtls_sha256_starts( mbedtls_sha256_context *ctx,
int is224 )
{
mbedtls_sha256_starts_ret( ctx, is224 );
}
#endif
static const uint32_t K[] =
{
0x428A2F98, 0x71374491, 0xB5C0FBCF, 0xE9B5DBA5,
0x3956C25B, 0x59F111F1, 0x923F82A4, 0xAB1C5ED5,
0xD807AA98, 0x12835B01, 0x243185BE, 0x550C7DC3,
0x72BE5D74, 0x80DEB1FE, 0x9BDC06A7, 0xC19BF174,
0xE49B69C1, 0xEFBE4786, 0x0FC19DC6, 0x240CA1CC,
0x2DE92C6F, 0x4A7484AA, 0x5CB0A9DC, 0x76F988DA,
0x983E5152, 0xA831C66D, 0xB00327C8, 0xBF597FC7,
0xC6E00BF3, 0xD5A79147, 0x06CA6351, 0x14292967,
0x27B70A85, 0x2E1B2138, 0x4D2C6DFC, 0x53380D13,
0x650A7354, 0x766A0ABB, 0x81C2C92E, 0x92722C85,
0xA2BFE8A1, 0xA81A664B, 0xC24B8B70, 0xC76C51A3,
0xD192E819, 0xD6990624, 0xF40E3585, 0x106AA070,
0x19A4C116, 0x1E376C08, 0x2748774C, 0x34B0BCB5,
0x391C0CB3, 0x4ED8AA4A, 0x5B9CCA4F, 0x682E6FF3,
0x748F82EE, 0x78A5636F, 0x84C87814, 0x8CC70208,
0x90BEFFFA, 0xA4506CEB, 0xBEF9A3F7, 0xC67178F2,
};
#define SHR(x,n) ((x & 0xFFFFFFFF) >> n)
#define ROTR(x,n) (SHR(x,n) | (x << (32 - n)))
#define S0(x) (ROTR(x, 7) ^ ROTR(x,18) ^ SHR(x, 3))
#define S1(x) (ROTR(x,17) ^ ROTR(x,19) ^ SHR(x,10))
#define S2(x) (ROTR(x, 2) ^ ROTR(x,13) ^ ROTR(x,22))
#define S3(x) (ROTR(x, 6) ^ ROTR(x,11) ^ ROTR(x,25))
#define F0(x,y,z) ((x & y) | (z & (x | y)))
#define F1(x,y,z) (z ^ (x & (y ^ z)))
#define R(t) \
( \
W[t] = S1(W[t - 2]) + W[t - 7] + \
S0(W[t - 15]) + W[t - 16] \
)
#define P(a,b,c,d,e,f,g,h,x,K) \
{ \
temp1 = h + S3(e) + F1(e,f,g) + K + x; \
temp2 = S2(a) + F0(a,b,c); \
d += temp1; h = temp1 + temp2; \
}
static void mbedtls_sha256_software_process( mbedtls_sha256_context *ctx, const unsigned char data[64] );
int mbedtls_internal_sha256_process( mbedtls_sha256_context *ctx, const unsigned char data[64] )
{
bool first_block = false;
if (ctx->mode == ESP_MBEDTLS_SHA256_UNUSED) {
/* try to use hardware for this digest */
if (!ctx->is224 && esp_sha_try_lock_engine(SHA2_256)) {
ctx->mode = ESP_MBEDTLS_SHA256_HARDWARE;
first_block = true;
} else {
ctx->mode = ESP_MBEDTLS_SHA256_SOFTWARE;
}
}
if (ctx->mode == ESP_MBEDTLS_SHA256_HARDWARE) {
esp_sha_block(SHA2_256, data, first_block);
} else {
mbedtls_sha256_software_process(ctx, data);
}
return 0;
}
#if !defined(MBEDTLS_DEPRECATED_REMOVED)
void mbedtls_sha256_process( mbedtls_sha256_context *ctx,
const unsigned char data[64] )
{
mbedtls_internal_sha256_process( ctx, data );
}
#endif
static void mbedtls_sha256_software_process( mbedtls_sha256_context *ctx, const unsigned char data[64] )
{
uint32_t temp1, temp2, W[64];
uint32_t A[8];
unsigned int i;
for( i = 0; i < 8; i++ )
A[i] = ctx->state[i];
#if defined(MBEDTLS_SHA256_SMALLER)
for( i = 0; i < 64; i++ )
{
if( i < 16 )
GET_UINT32_BE( W[i], data, 4 * i );
else
R( i );
P( A[0], A[1], A[2], A[3], A[4], A[5], A[6], A[7], W[i], K[i] );
temp1 = A[7]; A[7] = A[6]; A[6] = A[5]; A[5] = A[4]; A[4] = A[3];
A[3] = A[2]; A[2] = A[1]; A[1] = A[0]; A[0] = temp1;
}
#else /* MBEDTLS_SHA256_SMALLER */
for( i = 0; i < 16; i++ )
GET_UINT32_BE( W[i], data, 4 * i );
for( i = 0; i < 16; i += 8 )
{
P( A[0], A[1], A[2], A[3], A[4], A[5], A[6], A[7], W[i+0], K[i+0] );
P( A[7], A[0], A[1], A[2], A[3], A[4], A[5], A[6], W[i+1], K[i+1] );
P( A[6], A[7], A[0], A[1], A[2], A[3], A[4], A[5], W[i+2], K[i+2] );
P( A[5], A[6], A[7], A[0], A[1], A[2], A[3], A[4], W[i+3], K[i+3] );
P( A[4], A[5], A[6], A[7], A[0], A[1], A[2], A[3], W[i+4], K[i+4] );
P( A[3], A[4], A[5], A[6], A[7], A[0], A[1], A[2], W[i+5], K[i+5] );
P( A[2], A[3], A[4], A[5], A[6], A[7], A[0], A[1], W[i+6], K[i+6] );
P( A[1], A[2], A[3], A[4], A[5], A[6], A[7], A[0], W[i+7], K[i+7] );
}
for( i = 16; i < 64; i += 8 )
{
P( A[0], A[1], A[2], A[3], A[4], A[5], A[6], A[7], R(i+0), K[i+0] );
P( A[7], A[0], A[1], A[2], A[3], A[4], A[5], A[6], R(i+1), K[i+1] );
P( A[6], A[7], A[0], A[1], A[2], A[3], A[4], A[5], R(i+2), K[i+2] );
P( A[5], A[6], A[7], A[0], A[1], A[2], A[3], A[4], R(i+3), K[i+3] );
P( A[4], A[5], A[6], A[7], A[0], A[1], A[2], A[3], R(i+4), K[i+4] );
P( A[3], A[4], A[5], A[6], A[7], A[0], A[1], A[2], R(i+5), K[i+5] );
P( A[2], A[3], A[4], A[5], A[6], A[7], A[0], A[1], R(i+6), K[i+6] );
P( A[1], A[2], A[3], A[4], A[5], A[6], A[7], A[0], R(i+7), K[i+7] );
}
#endif /* MBEDTLS_SHA256_SMALLER */
for( i = 0; i < 8; i++ )
ctx->state[i] += A[i];
}
/*
* SHA-256 process buffer
*/
int mbedtls_sha256_update_ret( mbedtls_sha256_context *ctx, const unsigned char *input,
size_t ilen )
{
int ret;
size_t fill;
uint32_t left;
if( ilen == 0 )
return 0;
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 );
if ( ( ret = mbedtls_internal_sha256_process( ctx, ctx->buffer ) ) != 0 ) {
return ret;
}
input += fill;
ilen -= fill;
left = 0;
}
while( ilen >= 64 )
{
if ( ( ret = mbedtls_internal_sha256_process( ctx, input ) ) != 0 ) {
return ret;
}
input += 64;
ilen -= 64;
}
if( ilen > 0 )
memcpy( (void *) (ctx->buffer + left), input, ilen );
return 0;
}
#if !defined(MBEDTLS_DEPRECATED_REMOVED)
void mbedtls_sha256_update( mbedtls_sha256_context *ctx,
const unsigned char *input,
size_t ilen )
{
mbedtls_sha256_update_ret( ctx, input, ilen );
}
#endif
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
*/
int mbedtls_sha256_finish_ret( mbedtls_sha256_context *ctx, unsigned char output[32] )
{
int ret;
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 );
if ( ( ret = mbedtls_sha256_update_ret( ctx, sha256_padding, padn ) ) != 0 ) {
goto out;
}
if ( ( ret = mbedtls_sha256_update_ret( ctx, msglen, 8 ) ) != 0 ) {
goto out;
}
/* if state is in hardware, read it out */
if (ctx->mode == ESP_MBEDTLS_SHA256_HARDWARE) {
esp_sha_read_digest_state(SHA2_256, ctx->state);
}
PUT_UINT32_BE( ctx->state[0], output, 0 );
PUT_UINT32_BE( ctx->state[1], output, 4 );
PUT_UINT32_BE( ctx->state[2], output, 8 );
PUT_UINT32_BE( ctx->state[3], output, 12 );
PUT_UINT32_BE( ctx->state[4], output, 16 );
PUT_UINT32_BE( ctx->state[5], output, 20 );
PUT_UINT32_BE( ctx->state[6], output, 24 );
if( ctx->is224 == 0 )
PUT_UINT32_BE( ctx->state[7], output, 28 );
out:
if (ctx->mode == ESP_MBEDTLS_SHA256_HARDWARE) {
esp_sha_unlock_engine(SHA2_256);
ctx->mode = ESP_MBEDTLS_SHA256_SOFTWARE;
}
return ret;
}
#if !defined(MBEDTLS_DEPRECATED_REMOVED)
void mbedtls_sha256_finish( mbedtls_sha256_context *ctx,
unsigned char output[32] )
{
mbedtls_sha256_finish_ret( ctx, output );
}
#endif
#endif /* MBEDTLS_SHA256_C && MBEDTLS_SHA256_ALT */

View File

@ -0,0 +1,469 @@
/*
* SHA-512 implementation with hardware ESP32 support added.
* Uses mbedTLS software implementation for failover when concurrent
* SHA operations are in use.
*
* Copyright (C) 2006-2015, ARM Limited, All Rights Reserved
* Additions Copyright (C) 2016, Espressif Systems (Shanghai) PTE LTD
* 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.
*
*/
/*
* The SHA-512 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_SHA512_C) && defined(MBEDTLS_SHA512_ALT)
#include "mbedtls/sha512.h"
#if defined(_MSC_VER) || defined(__WATCOMC__)
#define UL64(x) x##ui64
#else
#define UL64(x) x##ULL
#endif
#include <string.h>
#if defined(MBEDTLS_SELF_TEST)
#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 */
#include "esp32/sha.h"
inline static esp_sha_type sha_type(const mbedtls_sha512_context *ctx)
{
return ctx->is384 ? SHA2_384 : SHA2_512;
}
/* 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;
}
/*
* 64-bit integer manipulation macros (big endian)
*/
#ifndef GET_UINT64_BE
#define GET_UINT64_BE(n,b,i) \
{ \
(n) = ( (uint64_t) (b)[(i) ] << 56 ) \
| ( (uint64_t) (b)[(i) + 1] << 48 ) \
| ( (uint64_t) (b)[(i) + 2] << 40 ) \
| ( (uint64_t) (b)[(i) + 3] << 32 ) \
| ( (uint64_t) (b)[(i) + 4] << 24 ) \
| ( (uint64_t) (b)[(i) + 5] << 16 ) \
| ( (uint64_t) (b)[(i) + 6] << 8 ) \
| ( (uint64_t) (b)[(i) + 7] ); \
}
#endif /* GET_UINT64_BE */
#ifndef PUT_UINT64_BE
#define PUT_UINT64_BE(n,b,i) \
{ \
(b)[(i) ] = (unsigned char) ( (n) >> 56 ); \
(b)[(i) + 1] = (unsigned char) ( (n) >> 48 ); \
(b)[(i) + 2] = (unsigned char) ( (n) >> 40 ); \
(b)[(i) + 3] = (unsigned char) ( (n) >> 32 ); \
(b)[(i) + 4] = (unsigned char) ( (n) >> 24 ); \
(b)[(i) + 5] = (unsigned char) ( (n) >> 16 ); \
(b)[(i) + 6] = (unsigned char) ( (n) >> 8 ); \
(b)[(i) + 7] = (unsigned char) ( (n) ); \
}
#endif /* PUT_UINT64_BE */
void mbedtls_sha512_init( mbedtls_sha512_context *ctx )
{
memset( ctx, 0, sizeof( mbedtls_sha512_context ) );
}
void mbedtls_sha512_free( mbedtls_sha512_context *ctx )
{
if( ctx == NULL )
return;
if (ctx->mode == ESP_MBEDTLS_SHA512_HARDWARE) {
esp_sha_unlock_engine(sha_type(ctx));
}
mbedtls_zeroize( ctx, sizeof( mbedtls_sha512_context ) );
}
void mbedtls_sha512_clone( mbedtls_sha512_context *dst,
const mbedtls_sha512_context *src )
{
*dst = *src;
if (src->mode == ESP_MBEDTLS_SHA512_HARDWARE) {
/* Copy hardware digest state out to cloned state,
which will be a software digest.
Always read 512 bits of state, even for SHA-384
(SHA-384 state is identical to SHA-512, only
digest is truncated.)
*/
esp_sha_read_digest_state(SHA2_512, dst->state);
dst->mode = ESP_MBEDTLS_SHA512_SOFTWARE;
}
}
/*
* SHA-512 context setup
*/
int mbedtls_sha512_starts_ret( mbedtls_sha512_context *ctx, int is384 )
{
ctx->total[0] = 0;
ctx->total[1] = 0;
if( is384 == 0 )
{
/* SHA-512 */
ctx->state[0] = UL64(0x6A09E667F3BCC908);
ctx->state[1] = UL64(0xBB67AE8584CAA73B);
ctx->state[2] = UL64(0x3C6EF372FE94F82B);
ctx->state[3] = UL64(0xA54FF53A5F1D36F1);
ctx->state[4] = UL64(0x510E527FADE682D1);
ctx->state[5] = UL64(0x9B05688C2B3E6C1F);
ctx->state[6] = UL64(0x1F83D9ABFB41BD6B);
ctx->state[7] = UL64(0x5BE0CD19137E2179);
}
else
{
/* SHA-384 */
ctx->state[0] = UL64(0xCBBB9D5DC1059ED8);
ctx->state[1] = UL64(0x629A292A367CD507);
ctx->state[2] = UL64(0x9159015A3070DD17);
ctx->state[3] = UL64(0x152FECD8F70E5939);
ctx->state[4] = UL64(0x67332667FFC00B31);
ctx->state[5] = UL64(0x8EB44A8768581511);
ctx->state[6] = UL64(0xDB0C2E0D64F98FA7);
ctx->state[7] = UL64(0x47B5481DBEFA4FA4);
}
ctx->is384 = is384;
if (ctx->mode == ESP_MBEDTLS_SHA512_HARDWARE) {
esp_sha_unlock_engine(sha_type(ctx));
}
ctx->mode = ESP_MBEDTLS_SHA512_UNUSED;
return 0;
}
#if !defined(MBEDTLS_DEPRECATED_REMOVED)
void mbedtls_sha512_starts( mbedtls_sha512_context *ctx,
int is384 )
{
mbedtls_sha512_starts_ret( ctx, is384 );
}
#endif
/*
* Round constants
*/
static const uint64_t K[80] =
{
UL64(0x428A2F98D728AE22), UL64(0x7137449123EF65CD),
UL64(0xB5C0FBCFEC4D3B2F), UL64(0xE9B5DBA58189DBBC),
UL64(0x3956C25BF348B538), UL64(0x59F111F1B605D019),
UL64(0x923F82A4AF194F9B), UL64(0xAB1C5ED5DA6D8118),
UL64(0xD807AA98A3030242), UL64(0x12835B0145706FBE),
UL64(0x243185BE4EE4B28C), UL64(0x550C7DC3D5FFB4E2),
UL64(0x72BE5D74F27B896F), UL64(0x80DEB1FE3B1696B1),
UL64(0x9BDC06A725C71235), UL64(0xC19BF174CF692694),
UL64(0xE49B69C19EF14AD2), UL64(0xEFBE4786384F25E3),
UL64(0x0FC19DC68B8CD5B5), UL64(0x240CA1CC77AC9C65),
UL64(0x2DE92C6F592B0275), UL64(0x4A7484AA6EA6E483),
UL64(0x5CB0A9DCBD41FBD4), UL64(0x76F988DA831153B5),
UL64(0x983E5152EE66DFAB), UL64(0xA831C66D2DB43210),
UL64(0xB00327C898FB213F), UL64(0xBF597FC7BEEF0EE4),
UL64(0xC6E00BF33DA88FC2), UL64(0xD5A79147930AA725),
UL64(0x06CA6351E003826F), UL64(0x142929670A0E6E70),
UL64(0x27B70A8546D22FFC), UL64(0x2E1B21385C26C926),
UL64(0x4D2C6DFC5AC42AED), UL64(0x53380D139D95B3DF),
UL64(0x650A73548BAF63DE), UL64(0x766A0ABB3C77B2A8),
UL64(0x81C2C92E47EDAEE6), UL64(0x92722C851482353B),
UL64(0xA2BFE8A14CF10364), UL64(0xA81A664BBC423001),
UL64(0xC24B8B70D0F89791), UL64(0xC76C51A30654BE30),
UL64(0xD192E819D6EF5218), UL64(0xD69906245565A910),
UL64(0xF40E35855771202A), UL64(0x106AA07032BBD1B8),
UL64(0x19A4C116B8D2D0C8), UL64(0x1E376C085141AB53),
UL64(0x2748774CDF8EEB99), UL64(0x34B0BCB5E19B48A8),
UL64(0x391C0CB3C5C95A63), UL64(0x4ED8AA4AE3418ACB),
UL64(0x5B9CCA4F7763E373), UL64(0x682E6FF3D6B2B8A3),
UL64(0x748F82EE5DEFB2FC), UL64(0x78A5636F43172F60),
UL64(0x84C87814A1F0AB72), UL64(0x8CC702081A6439EC),
UL64(0x90BEFFFA23631E28), UL64(0xA4506CEBDE82BDE9),
UL64(0xBEF9A3F7B2C67915), UL64(0xC67178F2E372532B),
UL64(0xCA273ECEEA26619C), UL64(0xD186B8C721C0C207),
UL64(0xEADA7DD6CDE0EB1E), UL64(0xF57D4F7FEE6ED178),
UL64(0x06F067AA72176FBA), UL64(0x0A637DC5A2C898A6),
UL64(0x113F9804BEF90DAE), UL64(0x1B710B35131C471B),
UL64(0x28DB77F523047D84), UL64(0x32CAAB7B40C72493),
UL64(0x3C9EBE0A15C9BEBC), UL64(0x431D67C49C100D4C),
UL64(0x4CC5D4BECB3E42B6), UL64(0x597F299CFC657E2A),
UL64(0x5FCB6FAB3AD6FAEC), UL64(0x6C44198C4A475817)
};
static void mbedtls_sha512_software_process( mbedtls_sha512_context *ctx, const unsigned char data[128] );
int mbedtls_internal_sha512_process( mbedtls_sha512_context *ctx, const unsigned char data[128] )
{
bool first_block = false;
if (ctx->mode == ESP_MBEDTLS_SHA512_UNUSED) {
/* try to use hardware for this digest */
if (esp_sha_try_lock_engine(sha_type(ctx))) {
ctx->mode = ESP_MBEDTLS_SHA512_HARDWARE;
first_block = true;
} else {
ctx->mode = ESP_MBEDTLS_SHA512_SOFTWARE;
}
}
if (ctx->mode == ESP_MBEDTLS_SHA512_HARDWARE) {
esp_sha_block(sha_type(ctx), data, first_block);
} else {
mbedtls_sha512_software_process(ctx, data);
}
return 0;
}
#if !defined(MBEDTLS_DEPRECATED_REMOVED)
void mbedtls_sha512_process( mbedtls_sha512_context *ctx,
const unsigned char data[128] )
{
mbedtls_internal_sha512_process( ctx, data );
}
#endif
static void mbedtls_sha512_software_process( mbedtls_sha512_context *ctx, const unsigned char data[128] )
{
int i;
uint64_t temp1, temp2, W[80];
uint64_t A, B, C, D, E, F, G, H;
#define SHR(x,n) (x >> n)
#define ROTR(x,n) (SHR(x,n) | (x << (64 - n)))
#define S0(x) (ROTR(x, 1) ^ ROTR(x, 8) ^ SHR(x, 7))
#define S1(x) (ROTR(x,19) ^ ROTR(x,61) ^ SHR(x, 6))
#define S2(x) (ROTR(x,28) ^ ROTR(x,34) ^ ROTR(x,39))
#define S3(x) (ROTR(x,14) ^ ROTR(x,18) ^ ROTR(x,41))
#define F0(x,y,z) ((x & y) | (z & (x | y)))
#define F1(x,y,z) (z ^ (x & (y ^ z)))
#define P(a,b,c,d,e,f,g,h,x,K) \
{ \
temp1 = h + S3(e) + F1(e,f,g) + K + x; \
temp2 = S2(a) + F0(a,b,c); \
d += temp1; h = temp1 + temp2; \
}
for( i = 0; i < 16; i++ )
{
GET_UINT64_BE( W[i], data, i << 3 );
}
for( ; i < 80; i++ )
{
W[i] = S1(W[i - 2]) + W[i - 7] +
S0(W[i - 15]) + W[i - 16];
}
A = ctx->state[0];
B = ctx->state[1];
C = ctx->state[2];
D = ctx->state[3];
E = ctx->state[4];
F = ctx->state[5];
G = ctx->state[6];
H = ctx->state[7];
i = 0;
do
{
P( A, B, C, D, E, F, G, H, W[i], K[i] ); i++;
P( H, A, B, C, D, E, F, G, W[i], K[i] ); i++;
P( G, H, A, B, C, D, E, F, W[i], K[i] ); i++;
P( F, G, H, A, B, C, D, E, W[i], K[i] ); i++;
P( E, F, G, H, A, B, C, D, W[i], K[i] ); i++;
P( D, E, F, G, H, A, B, C, W[i], K[i] ); i++;
P( C, D, E, F, G, H, A, B, W[i], K[i] ); i++;
P( B, C, D, E, F, G, H, A, W[i], K[i] ); i++;
}
while( i < 80 );
ctx->state[0] += A;
ctx->state[1] += B;
ctx->state[2] += C;
ctx->state[3] += D;
ctx->state[4] += E;
ctx->state[5] += F;
ctx->state[6] += G;
ctx->state[7] += H;
}
/*
* SHA-512 process buffer
*/
int mbedtls_sha512_update_ret( mbedtls_sha512_context *ctx, const unsigned char *input,
size_t ilen )
{
int ret;
size_t fill;
unsigned int left;
if( ilen == 0 )
return 0;
left = (unsigned int) (ctx->total[0] & 0x7F);
fill = 128 - left;
ctx->total[0] += (uint64_t) ilen;
if( ctx->total[0] < (uint64_t) ilen )
ctx->total[1]++;
if( left && ilen >= fill )
{
memcpy( (void *) (ctx->buffer + left), input, fill );
if ( ( ret = mbedtls_internal_sha512_process( ctx, ctx->buffer ) ) != 0 ) {
return ret;
}
input += fill;
ilen -= fill;
left = 0;
}
while( ilen >= 128 )
{
if ( ( ret = mbedtls_internal_sha512_process( ctx, input ) ) != 0 ) {
return ret;
}
input += 128;
ilen -= 128;
}
if( ilen > 0 )
memcpy( (void *) (ctx->buffer + left), input, ilen );
return 0;
}
#if !defined(MBEDTLS_DEPRECATED_REMOVED)
void mbedtls_sha512_update( mbedtls_sha512_context *ctx,
const unsigned char *input,
size_t ilen )
{
mbedtls_sha512_update_ret( ctx, input, ilen );
}
#endif
static const unsigned char sha512_padding[128] =
{
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,
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, 0
};
/*
* SHA-512 final digest
*/
int mbedtls_sha512_finish_ret( mbedtls_sha512_context *ctx, unsigned char output[64] )
{
int ret;
size_t last, padn;
uint64_t high, low;
unsigned char msglen[16];
high = ( ctx->total[0] >> 61 )
| ( ctx->total[1] << 3 );
low = ( ctx->total[0] << 3 );
PUT_UINT64_BE( high, msglen, 0 );
PUT_UINT64_BE( low, msglen, 8 );
last = (size_t)( ctx->total[0] & 0x7F );
padn = ( last < 112 ) ? ( 112 - last ) : ( 240 - last );
if ( ( ret = mbedtls_sha512_update_ret( ctx, sha512_padding, padn ) ) != 0 ) {
goto out;
}
if ( ( ret = mbedtls_sha512_update_ret( ctx, msglen, 16 ) ) != 0 ) {
goto out;
}
/* if state is in hardware, read it out */
if (ctx->mode == ESP_MBEDTLS_SHA512_HARDWARE) {
esp_sha_read_digest_state(sha_type(ctx), ctx->state);
}
PUT_UINT64_BE( ctx->state[0], output, 0 );
PUT_UINT64_BE( ctx->state[1], output, 8 );
PUT_UINT64_BE( ctx->state[2], output, 16 );
PUT_UINT64_BE( ctx->state[3], output, 24 );
PUT_UINT64_BE( ctx->state[4], output, 32 );
PUT_UINT64_BE( ctx->state[5], output, 40 );
if( ctx->is384 == 0 )
{
PUT_UINT64_BE( ctx->state[6], output, 48 );
PUT_UINT64_BE( ctx->state[7], output, 56 );
}
out:
if (ctx->mode == ESP_MBEDTLS_SHA512_HARDWARE) {
esp_sha_unlock_engine(sha_type(ctx));
ctx->mode = ESP_MBEDTLS_SHA512_SOFTWARE;
}
return ret;
}
#if !defined(MBEDTLS_DEPRECATED_REMOVED)
void mbedtls_sha512_finish( mbedtls_sha512_context *ctx,
unsigned char output[64] )
{
mbedtls_sha512_finish_ret( ctx, output );
}
#endif
#endif /* MBEDTLS_SHA512_C && MBEDTLS_SHA512_ALT */

View File

@ -0,0 +1,102 @@
/*
* Portable interface to the CPU cycle counter
*
* Copyright (C) 2006-2015, ARM Limited, All Rights Reserved
* SPDX-License-Identifier: Apache-2.0
*
* Licensed under the Apache License, Version 2.0 (the "License"); you may
* not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
* This file is part of mbed TLS (https://tls.mbed.org)
*/
/*
* mbedtls_timing_get_timer()m mbedtls_timing_set_delay() and
* mbedtls_timing_set_delay only abstracted from mbedtls/library/timing.c
* as that does not build on ESP-IDF but these 2 functions are needed for
* DTLS (in particular mbedtls_ssl_set_timer_cb() must be called for DTLS
* which requires these 2 delay functions).
*/
#if !defined(MBEDTLS_CONFIG_FILE)
#include "mbedtls/config.h"
#else
#include MBEDTLS_CONFIG_FILE
#endif
#if !defined(MBEDTLS_ESP_TIMING_C)
#include <sys/time.h>
#include "mbedtls/timing.h"
struct _hr_time
{
struct timeval start;
};
unsigned long mbedtls_timing_get_timer( struct mbedtls_timing_hr_time *val, int reset )
{
struct _hr_time *t = (struct _hr_time *) val;
if( reset )
{
gettimeofday( &t->start, NULL );
return( 0 );
}
else
{
unsigned long delta;
struct timeval now;
gettimeofday( &now, NULL );
delta = ( now.tv_sec - t->start.tv_sec ) * 1000ul
+ ( now.tv_usec - t->start.tv_usec ) / 1000;
return( delta );
}
}
/*
* Set delays to watch
*/
void mbedtls_timing_set_delay( void *data, uint32_t int_ms, uint32_t fin_ms )
{
mbedtls_timing_delay_context *ctx = (mbedtls_timing_delay_context *) data;
ctx->int_ms = int_ms;
ctx->fin_ms = fin_ms;
if( fin_ms != 0 )
(void) mbedtls_timing_get_timer( &ctx->timer, 1 );
}
/*
* Get number of delays expired
*/
int mbedtls_timing_get_delay( void *data )
{
mbedtls_timing_delay_context *ctx = (mbedtls_timing_delay_context *) data;
unsigned long elapsed_ms;
if( ctx->fin_ms == 0 )
return( -1 );
elapsed_ms = mbedtls_timing_get_timer( &ctx->timer, 0 );
if( elapsed_ms >= ctx->fin_ms )
return( 2 );
if( elapsed_ms >= ctx->int_ms )
return( 1 );
return( 0 );
}
#endif /* MBEDTLS_ESP_TIMING_C */

View File

@ -0,0 +1,69 @@
/**
* \file aes_alt.h
*
* \brief AES block cipher
*
* Copyright (C) 2006-2015, ARM Limited, All Rights Reserved
* SPDX-License-Identifier: Apache-2.0
*
* Licensed under the Apache License, Version 2.0 (the "License"); you may
* not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
*
*/
#ifndef AES_ALT_H
#define AES_ALT_H
#ifdef __cplusplus
extern "C" {
#endif
#if defined(MBEDTLS_AES_ALT)
#include "esp32/aes.h"
typedef esp_aes_context mbedtls_aes_context;
#define mbedtls_aes_init esp_aes_init
#define mbedtls_aes_free esp_aes_free
#define mbedtls_aes_setkey_enc esp_aes_setkey
#define mbedtls_aes_setkey_dec esp_aes_setkey
#define mbedtls_aes_crypt_ecb esp_aes_crypt_ecb
#if defined(MBEDTLS_CIPHER_MODE_CBC)
#define mbedtls_aes_crypt_cbc esp_aes_crypt_cbc
#endif
#if defined(MBEDTLS_CIPHER_MODE_CFB)
#define mbedtls_aes_crypt_cfb128 esp_aes_crypt_cfb128
#define mbedtls_aes_crypt_cfb8 esp_aes_crypt_cfb8
#endif
#if defined(MBEDTLS_CIPHER_MODE_CTR)
#define mbedtls_aes_crypt_ctr esp_aes_crypt_ctr
#endif
#if defined(MBEDTLS_CIPHER_MODE_OFB)
#define mbedtls_aes_crypt_ofb esp_aes_crypt_ofb
#endif
#if defined(MBEDTLS_CIPHER_MODE_XTS)
typedef esp_aes_xts_context mbedtls_aes_xts_context;
#define mbedtls_aes_xts_init esp_aes_xts_init
#define mbedtls_aes_xts_free esp_aes_xts_free
#define mbedtls_aes_xts_setkey_enc esp_aes_xts_setkey_enc
#define mbedtls_aes_xts_setkey_dec esp_aes_xts_setkey_dec
#define mbedtls_aes_crypt_xts esp_aes_crypt_xts
#endif
#define mbedtls_internal_aes_encrypt esp_internal_aes_encrypt
#define mbedtls_internal_aes_decrypt esp_internal_aes_decrypt
#endif /* MBEDTLS_AES_ALT */
#ifdef __cplusplus
}
#endif
#endif

View File

@ -0,0 +1,359 @@
/**
* \brief AES block cipher, ESP32 hardware accelerated version
* Based on mbedTLS FIPS-197 compliant version.
*
* Copyright (C) 2006-2015, ARM Limited, All Rights Reserved
* Additions Copyright (C) 2016, Espressif Systems (Shanghai) PTE Ltd
* 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 ESP_AES_H
#define ESP_AES_H
#include "esp_types.h"
#include "esp32/rom/aes.h"
#ifdef __cplusplus
extern "C" {
#endif
/* padlock.c and aesni.c rely on these values! */
#define ESP_AES_ENCRYPT 1
#define ESP_AES_DECRYPT 0
#define ERR_ESP_AES_INVALID_KEY_LENGTH -0x0020 /**< Invalid key length. */
#define ERR_ESP_AES_INVALID_INPUT_LENGTH -0x0022 /**< Invalid data input length. */
/**
* \brief AES context structure
*
*/
typedef struct {
uint8_t key_bytes;
volatile uint8_t key_in_hardware; /* This variable is used for fault injection checks, so marked volatile to avoid optimisation */
uint8_t key[32];
} esp_aes_context;
/**
* \brief The AES XTS context-type definition.
*/
typedef struct
{
esp_aes_context crypt; /*!< The AES context to use for AES block
encryption or decryption. */
esp_aes_context tweak; /*!< The AES context used for tweak
computation. */
} esp_aes_xts_context;
/**
* \brief Lock access to AES hardware unit
*
* AES hardware unit can only be used by one
* consumer at a time.
*
* esp_aes_xxx API calls automatically manage locking & unlocking of
* hardware, this function is only needed if you want to call
* ets_aes_xxx functions directly.
*/
void esp_aes_acquire_hardware( void );
/**
* \brief Unlock access to AES hardware unit
*
* esp_aes_xxx API calls automatically manage locking & unlocking of
* hardware, this function is only needed if you want to call
* ets_aes_xxx functions directly.
*/
void esp_aes_release_hardware( void );
/**
* \brief Initialize AES context
*
* \param ctx AES context to be initialized
*/
void esp_aes_init( esp_aes_context *ctx );
/**
* \brief Clear AES context
*
* \param ctx AES context to be cleared
*/
void esp_aes_free( esp_aes_context *ctx );
/**
* \brief This function initializes the specified AES XTS context.
*
* It must be the first API called before using
* the context.
*
* \param ctx The AES XTS context to initialize.
*/
void esp_aes_xts_init( esp_aes_xts_context *ctx );
/**
* \brief This function releases and clears the specified AES XTS context.
*
* \param ctx The AES XTS context to clear.
*/
void esp_aes_xts_free( esp_aes_xts_context *ctx );
/**
* \brief AES set key schedule (encryption or decryption)
*
* \param ctx AES context to be initialized
* \param key encryption key
* \param keybits must be 128, 192 or 256
*
* \return 0 if successful, or ERR_AES_INVALID_KEY_LENGTH
*/
int esp_aes_setkey( esp_aes_context *ctx, const unsigned char *key, unsigned int keybits );
/**
* \brief AES-ECB block encryption/decryption
*
* \param ctx AES context
* \param mode AES_ENCRYPT or AES_DECRYPT
* \param input 16-byte input block
* \param output 16-byte output block
*
* \return 0 if successful
*/
int esp_aes_crypt_ecb( esp_aes_context *ctx, int mode, const unsigned char input[16], unsigned char output[16] );
/**
* \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 AES_ENCRYPT or 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 ERR_AES_INVALID_INPUT_LENGTH
*/
int esp_aes_crypt_cbc( esp_aes_context *ctx,
int mode,
size_t length,
unsigned char iv[16],
const unsigned char *input,
unsigned char *output );
/**
* \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
* esp_aes_setkey_enc() for both AES_ENCRYPT and 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 AES_ENCRYPT or 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 esp_aes_crypt_cfb128( esp_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
* esp_aes_setkey_enc() for both AES_ENCRYPT and 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 AES_ENCRYPT or 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 esp_aes_crypt_cfb8( esp_aes_context *ctx,
int mode,
size_t length,
unsigned char iv[16],
const unsigned char *input,
unsigned char *output );
/**
* \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
* esp_aes_setkey_enc() for both AES_ENCRYPT and 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 esp_aes_crypt_ctr( esp_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 );
/**
* \brief This function prepares an XTS context for encryption and
* sets the encryption key.
*
* \param ctx The AES XTS context to which the key should be bound.
* \param key The encryption key. This is comprised of the XTS key1
* concatenated with the XTS key2.
* \param keybits The size of \p key passed in bits. Valid options are:
* <ul><li>256 bits (each of key1 and key2 is a 128-bit key)</li>
* <li>512 bits (each of key1 and key2 is a 256-bit key)</li></ul>
*
* \return \c 0 on success.
* \return #MBEDTLS_ERR_AES_INVALID_KEY_LENGTH on failure.
*/
int esp_aes_xts_setkey_enc( esp_aes_xts_context *ctx,
const unsigned char *key,
unsigned int keybits );
/**
* \brief This function performs an AES-OFB (Output Feedback Mode)
* encryption or decryption operation.
*
* \param ctx The AES context to use for encryption or decryption.
* It must be initialized and bound to a key.
* \param length The length of the input data.
* \param iv_off The offset in IV (updated after use).
* It must point to a valid \c size_t.
* \param iv The initialization vector (updated after use).
* It must be a readable and writeable buffer of \c 16 Bytes.
* \param input The buffer holding the input data.
* It must be readable and of size \p length Bytes.
* \param output The buffer holding the output data.
* It must be writeable and of size \p length Bytes.
*
* \return \c 0 on success.
*/
int esp_aes_crypt_ofb( esp_aes_context *ctx,
size_t length,
size_t *iv_off,
unsigned char iv[16],
const unsigned char *input,
unsigned char *output );
/**
* \brief This function prepares an XTS context for decryption and
* sets the decryption key.
*
* \param ctx The AES XTS context to which the key should be bound.
* \param key The decryption key. This is comprised of the XTS key1
* concatenated with the XTS key2.
* \param keybits The size of \p key passed in bits. Valid options are:
* <ul><li>256 bits (each of key1 and key2 is a 128-bit key)</li>
* <li>512 bits (each of key1 and key2 is a 256-bit key)</li></ul>
*
* \return \c 0 on success.
* \return #MBEDTLS_ERR_AES_INVALID_KEY_LENGTH on failure.
*/
int esp_aes_xts_setkey_dec( esp_aes_xts_context *ctx,
const unsigned char *key,
unsigned int keybits );
/**
* \brief Internal AES block encryption function
* (Only exposed to allow overriding it,
* see AES_ENCRYPT_ALT)
*
* \param ctx AES context
* \param input Plaintext block
* \param output Output (ciphertext) block
*/
int esp_internal_aes_encrypt( esp_aes_context *ctx, const unsigned char input[16], unsigned char output[16] );
/** Deprecated, see esp_aes_internal_encrypt */
void esp_aes_encrypt( esp_aes_context *ctx, const unsigned char input[16], unsigned char output[16] ) __attribute__((deprecated));
/**
* \brief Internal AES block decryption function
* (Only exposed to allow overriding it,
* see AES_DECRYPT_ALT)
*
* \param ctx AES context
* \param input Ciphertext block
* \param output Output (plaintext) block
*/
int esp_internal_aes_decrypt( esp_aes_context *ctx, const unsigned char input[16], unsigned char output[16] );
/** Deprecated, see esp_aes_internal_decrypt */
void esp_aes_decrypt( esp_aes_context *ctx, const unsigned char input[16], unsigned char output[16] ) __attribute__((deprecated));
/** AES-XTS buffer encryption/decryption */
int esp_aes_crypt_xts( esp_aes_xts_context *ctx, int mode, size_t length, const unsigned char data_unit[16], const unsigned char *input, unsigned char *output );
#ifdef __cplusplus
}
#endif
#endif /* aes.h */

View File

@ -0,0 +1,211 @@
// Copyright 2015-2016 Espressif Systems (Shanghai) PTE LTD
//
// 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 _ESP_SHA_H_
#define _ESP_SHA_H_
#include "esp32/rom/sha.h"
#include "esp_types.h"
/** @brief Low-level support functions for the hardware SHA engine
*
* @note If you're looking for a SHA API to use, try mbedtls component
* mbedtls/shaXX.h. That API supports hardware acceleration.
*
* The API in this header provides some building blocks for implementing a
* full SHA API such as the one in mbedtls, and also a basic SHA function esp_sha().
*
* Some technical details about the hardware SHA engine:
*
* - SHA accelerator engine calculates one digest at a time, per SHA
* algorithm type. It initialises and maintains the digest state
* internally. It is possible to read out an in-progress SHA digest
* state, but it is not possible to restore a SHA digest state
* into the engine.
*
* - The memory block SHA_TEXT_BASE is shared between all SHA digest
* engines, so all engines must be idle before this memory block is
* modified.
*
*/
#ifdef __cplusplus
extern "C" {
#endif
/* Defined in esp32/rom/sha.h */
typedef enum SHA_TYPE esp_sha_type;
/** @brief Calculate SHA1 or SHA2 sum of some data, using hardware SHA engine
*
* @note For more versatile SHA calculations, where data doesn't need
* to be passed all at once, try the mbedTLS mbedtls/shaX.h APIs. The
* hardware-accelerated mbedTLS implementation is also faster when
* hashing large amounts of data.
*
* @note It is not necessary to lock any SHA hardware before calling
* this function, thread safety is managed internally.
*
* @note If a TLS connection is open then this function may block
* indefinitely waiting for a SHA engine to become available. Use the
* mbedTLS SHA API to avoid this problem.
*
* @param sha_type SHA algorithm to use.
*
* @param input Input data buffer.
*
* @param ilen Length of input data in bytes.
*
* @param output Buffer for output SHA digest. Output is 20 bytes for
* sha_type SHA1, 32 bytes for sha_type SHA2_256, 48 bytes for
* sha_type SHA2_384, 64 bytes for sha_type SHA2_512.
*/
void esp_sha(esp_sha_type sha_type, const unsigned char *input, size_t ilen, unsigned char *output);
/* @brief Begin to execute a single SHA block operation
*
* @note This is a piece of a SHA algorithm, rather than an entire SHA
* algorithm.
*
* @note Call esp_sha_try_lock_engine() before calling this
* function. Do not call esp_sha_lock_memory_block() beforehand, this
* is done inside the function.
*
* @param sha_type SHA algorithm to use.
*
* @param data_block Pointer to block of data. Block size is
* determined by algorithm (SHA1/SHA2_256 = 64 bytes,
* SHA2_384/SHA2_512 = 128 bytes)
*
* @param is_first_block If this parameter is true, the SHA state will
* be initialised (with the initial state of the given SHA algorithm)
* before the block is calculated. If false, the existing state of the
* SHA engine will be used.
*
* @return As a performance optimisation, this function returns before
* the SHA block operation is complete. Both this function and
* esp_sha_read_state() will automatically wait for any previous
* operation to complete before they begin. If using the SHA registers
* directly in another way, call esp_sha_wait_idle() after calling this
* function but before accessing the SHA registers.
*/
void esp_sha_block(esp_sha_type sha_type, const void *data_block, bool is_first_block);
/** @brief Read out the current state of the SHA digest loaded in the engine.
*
* @note This is a piece of a SHA algorithm, rather than an entire SHA algorithm.
*
* @note Call esp_sha_try_lock_engine() before calling this
* function. Do not call esp_sha_lock_memory_block() beforehand, this
* is done inside the function.
*
* If the SHA suffix padding block has been executed already, the
* value that is read is the SHA digest (in big endian
* format). Otherwise, the value that is read is an interim SHA state.
*
* @note If sha_type is SHA2_384, only 48 bytes of state will be read.
* This is enough for the final SHA2_384 digest, but if you want the
* interim SHA-384 state (to continue digesting) then pass SHA2_512 instead.
*
* @param sha_type SHA algorithm in use.
*
* @param state Pointer to a memory buffer to hold the SHA state. Size
* is 20 bytes (SHA1), 32 bytes (SHA2_256), 48 bytes (SHA2_384) or 64 bytes (SHA2_512).
*
*/
void esp_sha_read_digest_state(esp_sha_type sha_type, void *digest_state);
/**
* @brief Obtain exclusive access to a particular SHA engine
*
* @param sha_type Type of SHA engine to use.
*
* Blocks until engine is available. Note: Can block indefinitely
* while a TLS connection is open, suggest using
* esp_sha_try_lock_engine() and failing over to software SHA.
*/
void esp_sha_lock_engine(esp_sha_type sha_type);
/**
* @brief Try and obtain exclusive access to a particular SHA engine
*
* @param sha_type Type of SHA engine to use.
*
* @return Returns true if the SHA engine is locked for exclusive
* use. Call esp_sha_unlock_sha_engine() when done. Returns false if
* the SHA engine is already in use, caller should use software SHA
* algorithm for this digest.
*/
bool esp_sha_try_lock_engine(esp_sha_type sha_type);
/**
* @brief Unlock an engine previously locked with esp_sha_lock_engine() or esp_sha_try_lock_engine()
*
* @param sha_type Type of engine to release.
*/
void esp_sha_unlock_engine(esp_sha_type sha_type);
/**
* @brief Acquire exclusive access to the SHA shared memory block at SHA_TEXT_BASE
*
* This memory block is shared across all the SHA algorithm types.
*
* Caller should have already locked a SHA engine before calling this function.
*
* Note that it is possible to obtain exclusive access to the memory block even
* while it is in use by the SHA engine. Caller should use esp_sha_wait_idle()
* to ensure the SHA engine is not reading from the memory block in hardware.
*
* @note This function enters a critical section. Do not block while holding this lock.
*
* @note You do not need to lock the memory block before calling esp_sha_block() or esp_sha_read_digest_state(), these functions handle memory block locking internally.
*
* Call esp_sha_unlock_memory_block() when done.
*/
void esp_sha_lock_memory_block(void);
/**
* @brief Release exclusive access to the SHA register memory block at SHA_TEXT_BASE
*
* Caller should have already locked a SHA engine before calling this function.
*
* This function releases the critical section entered by esp_sha_lock_memory_block().
*
* Call following esp_sha_lock_memory_block().
*/
void esp_sha_unlock_memory_block(void);
/** @brief Wait for the SHA engine to finish any current operation
*
* @note This function does not ensure exclusive access to any SHA
* engine. Caller should use esp_sha_try_lock_engine() and
* esp_sha_lock_memory_block() as required.
*
* @note Functions declared in this header file wait for SHA engine
* completion automatically, so you don't need to use this API for
* these. However if accessing SHA registers directly, you will need
* to call this before accessing SHA registers if using the
* esp_sha_block() function.
*
* @note This function busy-waits, so wastes CPU resources.
* Best to delay calling until you are about to need it.
*
*/
void esp_sha_wait_idle(void);
#ifdef __cplusplus
}
#endif
#endif

View File

@ -0,0 +1,20 @@
// Copyright 2018 Espressif Systems (Shanghai) PTE LTD
//
// 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.
#pragma once
#include <stdlib.h>
void *esp_mbedtls_mem_calloc(size_t n, size_t size);
void esp_mbedtls_mem_free(void *ptr);

View File

@ -0,0 +1,78 @@
// Copyright 2015-2016 Espressif Systems (Shanghai) PTE LTD
//
// 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 __ESP_MBEDTLS_BIGNUM_H__
#define __ESP_MBEDTLS_BIGNUM_H__
#include_next "mbedtls/bignum.h"
/**
* This is a wrapper for the main mbedtls/bignum.h. This wrapper
* provides a few additional ESP32-only functions.
*
* This is because we don't set MBEDTLS_BIGNUM_ALT in the same way we
* do for AES, SHA, etc. Because we still use most of the bignum.h
* implementation and just replace a few hardware accelerated
* functions (see MBEDTLS_MPI_EXP_MOD_ALT & MBEDTLS_MPI_MUL_MPI_ALT in
* esp_config.h).
*
* @note Unlike the other hardware accelerator support functions in esp32/hwcrypto, there is no
* generic "hwcrypto/bignum.h" header for using these functions without mbedTLS. The reason for this
* is that all of the function implementations depend strongly upon the mbedTLS MPI implementation.
*/
/**
* @brief Lock access to RSA Accelerator (MPI/bignum operations)
*
* RSA Accelerator hardware unit can only be used by one
* consumer at a time.
*
* @note This function is non-recursive (do not call it twice from the
* same task.)
*
* @note You do not need to call this if you are using the mbedTLS bignum.h
* API or esp_mpi_xxx functions. This function is only needed if you
* want to call ROM RSA functions or access the registers directly.
*
*/
void esp_mpi_acquire_hardware(void);
/**
* @brief Unlock access to RSA Accelerator (MPI/bignum operations)
*
* Has to be called once for each call to esp_mpi_acquire_hardware().
*
* @note You do not need to call this if you are using the mbedTLS bignum.h
* API or esp_mpi_xxx functions. This function is only needed if you
* want to call ROM RSA functions or access the registers directly.
*/
void esp_mpi_release_hardware(void);
/* @brief MPI modular mupltiplication function
*
* Calculates Z = (X * Y) mod M using MPI hardware acceleration.
*
* This is not part of the standard mbedTLS bignum API.
*
* @note All of X, Y & Z should be less than 4096 bit long or an error is returned.
*
* @param Z Result bignum, should be pre-initialised with mbedtls_mpi_init().
* @param X First multiplication argument.
* @param Y Second multiplication argument.
* @param M Modulus value for result.
*
* @return 0 on success, mbedTLS MPI error codes on failure.
*/
int esp_mpi_mul_mpi_mod(mbedtls_mpi *Z, const mbedtls_mpi *X, const mbedtls_mpi *Y, const mbedtls_mpi *M);
#endif

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,59 @@
// Copyright 2015-2016 Espressif Systems (Shanghai) PTE LTD
//
// 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 _ESP_DEBUG_H_
#define _ESP_DEBUG_H_
#include "mbedtls/ssl.h"
#ifdef __cplusplus
extern "C" {
#endif
#include "sdkconfig.h"
#ifdef CONFIG_MBEDTLS_DEBUG
/** @brief Enable mbedTLS debug logging via the esp_log mechanism.
*
* mbedTLS internal debugging is filtered from a specified mbedTLS
* threshold level to esp_log level at runtime:
*
* - 1 - Warning
* - 2 - Info
* - 3 - Debug
* - 4 - Verbose
*
* (Note that mbedTLS debug thresholds are not always consistently used.)
*
* This function will set the esp log level for "mbedtls" to the specified mbedTLS
* threshold level that matches. However, the overall max ESP log level must be set high
* enough in menuconfig, or some messages may be filtered at compile time.
*
* @param conf mbedtls_ssl_config structure
* @param mbedTLS debug threshold, 0-4. Messages are filtered at runtime.
*/
void mbedtls_esp_enable_debug_log(mbedtls_ssl_config *conf, int threshold);
/** @brief Disable mbedTLS debug logging via the esp_log mechanism.
*
*/
void mbedtls_esp_disable_debug_log(mbedtls_ssl_config *conf);
#endif
#ifdef __cplusplus
}
#endif
#endif /* __ESP_DEBUG_H__ */

View File

@ -0,0 +1,57 @@
/*
* SHA-1 implementation with hardware ESP32 support added.
* Uses mbedTLS software implementation for failover when concurrent
* SHA operations are in use.
*
* Copyright (C) 2006-2015, ARM Limited, All Rights Reserved
* Additions Copyright (C) 2016, Espressif Systems (Shanghai) PTE LTD
* 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 _SHA1_ALT_H_
#define _SHA1_ALT_H_
#ifdef __cplusplus
extern "C" {
#endif
#if defined(MBEDTLS_SHA1_ALT)
typedef enum {
ESP_MBEDTLS_SHA1_UNUSED, /* first block hasn't been processed yet */
ESP_MBEDTLS_SHA1_HARDWARE, /* using hardware SHA engine */
ESP_MBEDTLS_SHA1_SOFTWARE, /* using software SHA */
} esp_mbedtls_sha1_mode;
/**
* \brief SHA-1 context structure
*/
typedef struct
{
uint32_t total[2]; /*!< number of bytes processed */
uint32_t state[5]; /*!< intermediate digest state */
unsigned char buffer[64]; /*!< data block being processed */
esp_mbedtls_sha1_mode mode;
}
mbedtls_sha1_context;
#endif
#ifdef __cplusplus
}
#endif
#endif

View File

@ -0,0 +1,57 @@
/*
* SHA-256 implementation with hardware ESP32 support added.
* Uses mbedTLS software implementation for failover when concurrent
* SHA operations are in use.
*
* Copyright (C) 2006-2015, ARM Limited, All Rights Reserved
* Additions Copyright (C) 2016, Espressif Systems (Shanghai) PTE LTD
* 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 _SHA256_ALT_H_
#define _SHA256_ALT_H_
#ifdef __cplusplus
extern "C" {
#endif
#if defined(MBEDTLS_SHA256_ALT)
typedef enum {
ESP_MBEDTLS_SHA256_UNUSED, /* first block hasn't been processed yet */
ESP_MBEDTLS_SHA256_HARDWARE, /* using hardware SHA engine */
ESP_MBEDTLS_SHA256_SOFTWARE, /* using software SHA */
} esp_mbedtls_sha256_mode;
/**
* \brief SHA-256 context structure
*/
typedef struct
{
uint32_t total[2]; /*!< number of bytes processed */
uint32_t state[8]; /*!< intermediate digest state */
unsigned char buffer[64]; /*!< data block being processed */
int is224; /*!< 0 => SHA-256, else SHA-224 */
esp_mbedtls_sha256_mode mode;
}
mbedtls_sha256_context;
#endif
#ifdef __cplusplus
}
#endif
#endif

View File

@ -0,0 +1,57 @@
/*
* SHA-512 implementation with hardware ESP32 support added.
* Uses mbedTLS software implementation for failover when concurrent
* SHA operations are in use.
*
* Copyright (C) 2006-2015, ARM Limited, All Rights Reserved
* Additions Copyright (C) 2016, Espressif Systems (Shanghai) PTE LTD
* 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 _SHA512_ALT_H_
#define _SHA512_ALT_H_
#ifdef __cplusplus
extern "C" {
#endif
#if defined(MBEDTLS_SHA512_ALT)
typedef enum {
ESP_MBEDTLS_SHA512_UNUSED, /* first block hasn't been processed yet */
ESP_MBEDTLS_SHA512_HARDWARE, /* using hardware SHA engine */
ESP_MBEDTLS_SHA512_SOFTWARE, /* using software SHA */
} esp_mbedtls_sha512_mode;
/**
* \brief SHA-512 context structure
*/
typedef struct
{
uint64_t total[2]; /*!< number of bytes processed */
uint64_t state[8]; /*!< intermediate digest state */
unsigned char buffer[128]; /*!< data block being processed */
int is384; /*!< 0 => SHA-512, else SHA-384 */
esp_mbedtls_sha512_mode mode;
}
mbedtls_sha512_context;
#endif
#ifdef __cplusplus
}
#endif
#endif

View File

@ -0,0 +1,94 @@
// Copyright 2015-2016 Espressif Systems (Shanghai) PTE LTD
//
// 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 <strings.h>
#include "esp_log.h"
#include "mbedtls/platform.h"
#include "mbedtls/debug.h"
#include "mbedtls/ssl.h"
#include "mbedtls/esp_debug.h"
#ifdef CONFIG_MBEDTLS_DEBUG
static const char *TAG = "mbedtls";
static void mbedtls_esp_debug(void *ctx, int level,
const char *file, int line,
const char *str);
void mbedtls_esp_enable_debug_log(mbedtls_ssl_config *conf, int threshold)
{
esp_log_level_t level = ESP_LOG_NONE;
mbedtls_debug_set_threshold(threshold);
mbedtls_ssl_conf_dbg(conf, mbedtls_esp_debug, NULL);
switch(threshold) {
case 1:
level = ESP_LOG_WARN;
break;
case 2:
level = ESP_LOG_INFO;
break;
case 3:
level = ESP_LOG_DEBUG;
break;
case 4:
level = ESP_LOG_VERBOSE;
break;
}
esp_log_level_set(TAG, level);
}
void mbedtls_esp_disable_debug_log(mbedtls_ssl_config *conf)
{
mbedtls_ssl_conf_dbg(conf, NULL, NULL);
}
/* Default mbedtls debug function that translates mbedTLS debug output
to ESP_LOGx debug output.
*/
static void mbedtls_esp_debug(void *ctx, int level,
const char *file, int line,
const char *str)
{
char *file_sep;
/* Shorten 'file' from the whole file path to just the filename
This is a bit wasteful because the macros are compiled in with
the full _FILE_ path in each case.
*/
file_sep = rindex(file, '/');
if(file_sep)
file = file_sep+1;
switch(level) {
case 1:
ESP_LOGW(TAG, "%s:%d %s", file, line, str);
break;
case 2:
ESP_LOGI(TAG, "%s:%d %s", file, line, str);
break;
case 3:
ESP_LOGD(TAG, "%s:%d %s", file, line, str);
break;
case 4:
ESP_LOGV(TAG, "%s:%d %s", file, line, str);
break;
default:
ESP_LOGE(TAG, "Unexpected log level %d: %s", level, str);
break;
}
}
#endif

View File

@ -0,0 +1,451 @@
/*
* TCP/IP or UDP/IP networking functions
* modified for LWIP support on ESP32
*
* Copyright (C) 2006-2015, ARM Limited, All Rights Reserved
* Additions Copyright (C) 2015 Angus Gratton
* 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 mbed TLS (https://tls.mbed.org)
*/
#if !defined(MBEDTLS_CONFIG_FILE)
#include "mbedtls/config.h"
#else
#include MBEDTLS_CONFIG_FILE
#endif
#if !defined(MBEDTLS_NET_C)
#if defined(MBEDTLS_PLATFORM_C)
#include "mbedtls/platform.h"
#else
#include <stdlib.h>
#define mbedtls_calloc calloc
#define mbedtls_free free
#define mbedtls_time time
#define mbedtls_time_t time_t
#endif
#include "mbedtls/net_sockets.h"
#include <string.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <unistd.h>
#include <netdb.h>
#include <stdlib.h>
#include <stdio.h>
#include <time.h>
#include <stdint.h>
/*
* Prepare for using the sockets interface
*/
static int net_prepare( void )
{
return ( 0 );
}
/*
* Initialize a context
*/
void mbedtls_net_init( mbedtls_net_context *ctx )
{
ctx->fd = -1;
}
/*
* Initiate a TCP connection with host:port and the given protocol
*/
int mbedtls_net_connect( mbedtls_net_context *ctx, const char *host, const char *port, int proto )
{
int ret;
struct addrinfo hints, *addr_list, *cur;
if ( ( ret = net_prepare() ) != 0 ) {
return ( ret );
}
/* Do name resolution with both IPv6 and IPv4 */
memset( &hints, 0, sizeof( hints ) );
hints.ai_family = AF_UNSPEC;
hints.ai_socktype = proto == MBEDTLS_NET_PROTO_UDP ? SOCK_DGRAM : SOCK_STREAM;
hints.ai_protocol = proto == MBEDTLS_NET_PROTO_UDP ? IPPROTO_UDP : IPPROTO_TCP;
if ( getaddrinfo( host, port, &hints, &addr_list ) != 0 ) {
return ( MBEDTLS_ERR_NET_UNKNOWN_HOST );
}
/* Try the sockaddrs until a connection succeeds */
ret = MBEDTLS_ERR_NET_UNKNOWN_HOST;
for ( cur = addr_list; cur != NULL; cur = cur->ai_next ) {
int fd = socket( cur->ai_family, cur->ai_socktype, cur->ai_protocol );
if ( fd < 0 ) {
ret = MBEDTLS_ERR_NET_SOCKET_FAILED;
continue;
}
if ( connect( fd, cur->ai_addr, cur->ai_addrlen ) == 0 ) {
ctx->fd = fd; // connected!
ret = 0;
break;
}
close( fd );
ret = MBEDTLS_ERR_NET_CONNECT_FAILED;
}
freeaddrinfo( addr_list );
return ( ret );
}
/*
* Create a listening socket on bind_ip:port
*/
int mbedtls_net_bind( mbedtls_net_context *ctx, const char *bind_ip, const char *port, int proto )
{
int ret;
struct addrinfo hints, *addr_list, *cur;
struct sockaddr_in *serv_addr = NULL;
#if SO_REUSE
int n = 1;
#endif
if ( ( ret = net_prepare() ) != 0 ) {
return ( ret );
}
/* Bind to IPv6 and/or IPv4, but only in the desired protocol */
memset( &hints, 0, sizeof( hints ) );
hints.ai_family = AF_UNSPEC;
hints.ai_socktype = proto == MBEDTLS_NET_PROTO_UDP ? SOCK_DGRAM : SOCK_STREAM;
hints.ai_protocol = proto == MBEDTLS_NET_PROTO_UDP ? IPPROTO_UDP : IPPROTO_TCP;
if ( getaddrinfo( bind_ip, port, &hints, &addr_list ) != 0 ) {
return ( MBEDTLS_ERR_NET_UNKNOWN_HOST );
}
/* Try the sockaddrs until a binding succeeds */
ret = MBEDTLS_ERR_NET_UNKNOWN_HOST;
for ( cur = addr_list; cur != NULL; cur = cur->ai_next ) {
int fd = socket( cur->ai_family, cur->ai_socktype, cur->ai_protocol );
if ( fd < 0 ) {
ret = MBEDTLS_ERR_NET_SOCKET_FAILED;
continue;
}
/*SO_REUSEADDR option dafault is disable in source code(lwip)*/
#if SO_REUSE
if ( setsockopt( fd, SOL_SOCKET, SO_REUSEADDR,
(const char *) &n, sizeof( n ) ) != 0 ) {
close( fd );
ret = MBEDTLS_ERR_NET_SOCKET_FAILED;
continue;
}
#endif
/*bind interface dafault don't process the addr is 0xffffffff for TCP Protocol*/
serv_addr = (struct sockaddr_in *)cur->ai_addr;
serv_addr->sin_addr.s_addr = htonl(INADDR_ANY); /* Any incoming interface */
if ( bind( fd, (struct sockaddr *)serv_addr, cur->ai_addrlen ) != 0 ) {
close( fd );
ret = MBEDTLS_ERR_NET_BIND_FAILED;
continue;
}
/* Listen only makes sense for TCP */
if ( proto == MBEDTLS_NET_PROTO_TCP ) {
if ( listen( fd, MBEDTLS_NET_LISTEN_BACKLOG ) != 0 ) {
close( fd );
ret = MBEDTLS_ERR_NET_LISTEN_FAILED;
continue;
}
}
/* I we ever get there, it's a success */
ctx->fd = fd;
ret = 0;
break;
}
freeaddrinfo( addr_list );
return ( ret );
}
/*
* Check if the requested operation would be blocking on a non-blocking socket
* and thus 'failed' with a negative return value.
*
* Note: on a blocking socket this function always returns 0!
*/
static int net_would_block( const mbedtls_net_context *ctx )
{
int error = errno;
/*
* Never return 'WOULD BLOCK' on a non-blocking socket
*/
if ( ( fcntl( ctx->fd, F_GETFL, 0) & O_NONBLOCK ) != O_NONBLOCK ) {
errno = error;
return ( 0 );
}
switch ( errno = error ) {
#if defined EAGAIN
case EAGAIN:
#endif
#if defined EWOULDBLOCK && EWOULDBLOCK != EAGAIN
case EWOULDBLOCK:
#endif
return ( 1 );
}
return ( 0 );
}
/*
* Accept a connection from a remote client
*/
int mbedtls_net_accept( mbedtls_net_context *bind_ctx,
mbedtls_net_context *client_ctx,
void *client_ip, size_t buf_size, size_t *ip_len )
{
int ret;
int type;
struct sockaddr_in client_addr;
socklen_t n = (socklen_t) sizeof( client_addr );
socklen_t type_len = (socklen_t) sizeof( type );
/* Is this a TCP or UDP socket? */
if ( getsockopt( bind_ctx->fd, SOL_SOCKET, SO_TYPE,
(void *) &type, (socklen_t *) &type_len ) != 0 ||
( type != SOCK_STREAM && type != SOCK_DGRAM ) ) {
return ( MBEDTLS_ERR_NET_ACCEPT_FAILED );
}
if ( type == SOCK_STREAM ) {
/* TCP: actual accept() */
ret = client_ctx->fd = (int) accept( bind_ctx->fd,
(struct sockaddr *) &client_addr, &n );
} else {
/* UDP: wait for a message, but keep it in the queue */
char buf[1] = { 0 };
ret = recvfrom( bind_ctx->fd, buf, sizeof( buf ), MSG_PEEK,
(struct sockaddr *) &client_addr, &n );
}
if ( ret < 0 ) {
if ( net_would_block( bind_ctx ) != 0 ) {
return ( MBEDTLS_ERR_SSL_WANT_READ );
}
return ( MBEDTLS_ERR_NET_ACCEPT_FAILED );
}
/* UDP: hijack the listening socket to communicate with the client,
* then bind a new socket to accept new connections */
if ( type != SOCK_STREAM ) {
struct sockaddr_in local_addr;
int one = 1;
if ( connect( bind_ctx->fd, (struct sockaddr *) &client_addr, n ) != 0 ) {
return ( MBEDTLS_ERR_NET_ACCEPT_FAILED );
}
client_ctx->fd = bind_ctx->fd;
bind_ctx->fd = -1; /* In case we exit early */
n = sizeof( struct sockaddr_in );
if ( getsockname( client_ctx->fd,
(struct sockaddr *) &local_addr, &n ) != 0 ||
( bind_ctx->fd = (int) socket( AF_INET,
SOCK_DGRAM, IPPROTO_UDP ) ) < 0 ||
setsockopt( bind_ctx->fd, SOL_SOCKET, SO_REUSEADDR,
(const char *) &one, sizeof( one ) ) != 0 ) {
return ( MBEDTLS_ERR_NET_SOCKET_FAILED );
}
if ( bind( bind_ctx->fd, (struct sockaddr *) &local_addr, n ) != 0 ) {
return ( MBEDTLS_ERR_NET_BIND_FAILED );
}
}
if ( client_ip != NULL ) {
struct sockaddr_in *addr4 = (struct sockaddr_in *) &client_addr;
*ip_len = sizeof( addr4->sin_addr.s_addr );
if ( buf_size < *ip_len ) {
return ( MBEDTLS_ERR_NET_BUFFER_TOO_SMALL );
}
memcpy( client_ip, &addr4->sin_addr.s_addr, *ip_len );
}
return ( 0 );
}
/*
* Set the socket blocking or non-blocking
*/
int mbedtls_net_set_block( mbedtls_net_context *ctx )
{
return ( fcntl( ctx->fd, F_SETFL, fcntl( ctx->fd, F_GETFL, 0 ) & ~O_NONBLOCK ) );
}
int mbedtls_net_set_nonblock( mbedtls_net_context *ctx )
{
return ( fcntl( ctx->fd, F_SETFL, fcntl( ctx->fd, F_GETFL, 0 ) | O_NONBLOCK ) );
}
/*
* Portable usleep helper
*/
void mbedtls_net_usleep( unsigned long usec )
{
struct timeval tv;
tv.tv_sec = usec / 1000000;
tv.tv_usec = usec % 1000000;
select( 0, NULL, NULL, NULL, &tv );
}
/*
* Read at most 'len' characters
*/
int mbedtls_net_recv( void *ctx, unsigned char *buf, size_t len )
{
int ret;
int fd = ((mbedtls_net_context *) ctx)->fd;
if ( fd < 0 ) {
return ( MBEDTLS_ERR_NET_INVALID_CONTEXT );
}
ret = (int) read( fd, buf, len );
if ( ret < 0 ) {
if ( net_would_block( ctx ) != 0 ) {
return ( MBEDTLS_ERR_SSL_WANT_READ );
}
if ( errno == EPIPE || errno == ECONNRESET ) {
return ( MBEDTLS_ERR_NET_CONN_RESET );
}
if ( errno == EINTR ) {
return ( MBEDTLS_ERR_SSL_WANT_READ );
}
return ( MBEDTLS_ERR_NET_RECV_FAILED );
}
return ( ret );
}
/*
* Read at most 'len' characters, blocking for at most 'timeout' ms
*/
int mbedtls_net_recv_timeout( void *ctx, unsigned char *buf, size_t len,
uint32_t timeout )
{
int ret;
struct timeval tv;
fd_set read_fds;
int fd = ((mbedtls_net_context *) ctx)->fd;
if ( fd < 0 ) {
return ( MBEDTLS_ERR_NET_INVALID_CONTEXT );
}
FD_ZERO( &read_fds );
FD_SET( fd, &read_fds );
tv.tv_sec = timeout / 1000;
tv.tv_usec = ( timeout % 1000 ) * 1000;
ret = select( fd + 1, &read_fds, NULL, NULL, timeout == 0 ? NULL : &tv );
/* Zero fds ready means we timed out */
if ( ret == 0 ) {
return ( MBEDTLS_ERR_SSL_TIMEOUT );
}
if ( ret < 0 ) {
if ( errno == EINTR ) {
return ( MBEDTLS_ERR_SSL_WANT_READ );
}
return ( MBEDTLS_ERR_NET_RECV_FAILED );
}
/* This call will not block */
return ( mbedtls_net_recv( ctx, buf, len ) );
}
/*
* Write at most 'len' characters
*/
int mbedtls_net_send( void *ctx, const unsigned char *buf, size_t len )
{
int ret;
int fd = ((mbedtls_net_context *) ctx)->fd;
if ( fd < 0 ) {
return ( MBEDTLS_ERR_NET_INVALID_CONTEXT );
}
ret = (int) write( fd, buf, len );
if ( ret < 0 ) {
if ( net_would_block( ctx ) != 0 ) {
return ( MBEDTLS_ERR_SSL_WANT_WRITE );
}
if ( errno == EPIPE || errno == ECONNRESET ) {
return ( MBEDTLS_ERR_NET_CONN_RESET );
}
if ( errno == EINTR ) {
return ( MBEDTLS_ERR_SSL_WANT_WRITE );
}
return ( MBEDTLS_ERR_NET_SEND_FAILED );
}
return ( ret );
}
/*
* Gracefully close the connection
*/
void mbedtls_net_free( mbedtls_net_context *ctx )
{
if ( ctx->fd == -1 ) {
return;
}
shutdown( ctx->fd, 2 );
close( ctx->fd );
ctx->fd = -1;
}
#endif /* MBEDTLS_NET_C */

View File

@ -0,0 +1,9 @@
idf_component_register(SRC_DIRS "."
INCLUDE_DIRS "."
REQUIRES unity test_utils mbedtls)
idf_component_get_property(mbedtls mbedtls COMPONENT_LIB)
target_compile_definitions(${mbedtls} INTERFACE "-DMBEDTLS_DEPRECATED_WARNING")
target_compile_definitions(mbedtls PUBLIC "-DMBEDTLS_DEPRECATED_WARNING")
target_compile_definitions(mbedcrypto PUBLIC "-DMBEDTLS_DEPRECATED_WARNING")
target_compile_definitions(mbedx509 PUBLIC "-DMBEDTLS_DEPRECATED_WARNING")

View File

@ -0,0 +1,5 @@
#
#Component Makefile
#
COMPONENT_ADD_LDFLAGS = -Wl,--whole-archive -l$(COMPONENT_NAME) -Wl,--no-whole-archive

View File

@ -0,0 +1,71 @@
/* mbedTLS AES performance test
*/
#include <string.h>
#include <stdio.h>
#include <stdbool.h>
#include <esp_system.h>
#include "mbedtls/aes.h"
#include "unity.h"
#include "sdkconfig.h"
#include "esp_timer.h"
#include "esp_heap_caps.h"
#include "test_utils.h"
TEST_CASE("mbedtls AES performance", "[aes]")
{
const unsigned CALLS = 256;
const unsigned CALL_SZ = 32*1024;
mbedtls_aes_context ctx;
int64_t start, end;
uint8_t iv[16];
uint8_t key[16];
memset(iv, 0xEE, 16);
memset(key, 0x44, 16);
// allocate internal memory
uint8_t *buf = heap_caps_malloc(CALL_SZ, MALLOC_CAP_8BIT|MALLOC_CAP_INTERNAL);
TEST_ASSERT_NOT_NULL(buf);
mbedtls_aes_init(&ctx);
mbedtls_aes_setkey_enc(&ctx, key, 128);
start = esp_timer_get_time();
for (int c = 0; c < CALLS; c++) {
memset(buf, 0xAA, CALL_SZ);
mbedtls_aes_crypt_cbc(&ctx, MBEDTLS_AES_ENCRYPT, CALL_SZ, iv, buf, buf);
}
end = esp_timer_get_time();
/* Sanity check: make sure the last ciphertext block matches
what we expect to see.
Last block produced via this Python:
import os, binascii
from cryptography.hazmat.primitives.ciphers import Cipher, algorithms, modes
from cryptography.hazmat.backends import default_backend
key = b'\x44' * 16
iv = b'\xee' * 16
cipher = Cipher(algorithms.AES(key), modes.CBC(iv), backend=default_backend())
encryptor = cipher.encryptor()
ct = encryptor.update(b'\xaa' * 256 * 32 * 1024) + encryptor.finalize()
print(binascii.hexlify(ct[-16:]))
*/
const uint8_t expected_last_block[] = {
0x50, 0x81, 0xe0, 0xe1, 0x15, 0x2f, 0x14, 0xe9,
0x97, 0xa0, 0xc6, 0xe6, 0x36, 0xf3, 0x5c, 0x25,
};
TEST_ASSERT_EQUAL_HEX8_ARRAY(expected_last_block, buf + CALL_SZ - 16, 16);
free(buf);
float usecs = end - start;
// bytes/usec = MB/sec
float mb_sec = (CALL_SZ * CALLS) / usecs;
printf("Encryption rate %.3fMB/sec\n", mb_sec);
#ifdef CONFIG_MBEDTLS_HARDWARE_AES
// Don't put a hard limit on software AES performance (software is approx 2.3MB/sec on Release config)
TEST_PERFORMANCE_GREATER_THAN(AES_CBC_THROUGHPUT_MBSEC, "%.3fMB/sec", mb_sec);
#endif
}

View File

@ -0,0 +1,56 @@
/* Implementation of utility functions to verify
unit tests aren't performing SMP-unsafe DPORT reads.
*/
#include "unity.h"
#include "sdkconfig.h"
#include "freertos/FreeRTOS.h"
#include "freertos/task.h"
#include "soc/uart_periph.h"
#include "test_apb_dport_access.h"
#include "test_utils.h"
#ifndef CONFIG_FREERTOS_UNICORE
static void apb_access_loop_task(void *ignore);
static volatile bool apb_access_corrupt;
static TaskHandle_t apb_task_handle;
void start_apb_access_loop(void)
{
apb_access_corrupt = false;
xTaskCreatePinnedToCore(apb_access_loop_task, "accessAPB", 2048, NULL,
UNITY_FREERTOS_PRIORITY - 1,
&apb_task_handle, !UNITY_FREERTOS_CPU);
}
void verify_apb_access_loop(void)
{
vTaskDelete(apb_task_handle);
apb_task_handle = NULL;
TEST_ASSERT_FALSE(apb_access_corrupt);
printf("Verified no APB corruption from operations\n");
}
static void apb_access_loop_task(void *ignore)
{
uint32_t initial = REG_READ(UART_DATE_REG(0));
while(1) {
if (REG_READ(UART_DATE_REG(0)) != initial) {
apb_access_corrupt = true;
}
}
}
#else /*CONFIG_FREERTOS_UNICORE */
void start_apb_access_loop(void)
{
}
void verify_apb_access_loop(void)
{
}
#endif

View File

@ -0,0 +1,18 @@
/* Utility functions to test that APB access is still safe
while the other CPU performs some set of DPORT accesses
(see ECO 3.10 and the standalone esp32 test_dport.c for more).
*/
/* start_apb_access_loop() starts a task reading from APB in a loop on the non-Unity-test CPU.
Call this before doing something which involes DPORT reads.
Does nothing in unicore mode.
*/
void start_apb_access_loop(void);
/* verify_apb_access_loop() kills the task started by start_apb_access_loop()
and verifies that none of the APB reads were corrupted by unsafe DPORT reads.
*/
void verify_apb_access_loop(void);

View File

@ -0,0 +1,77 @@
/* mbedTLS Elliptic Curve functionality tests
Focus on testing functionality where we use ESP32 hardware
accelerated crypto features.
*/
#include <string.h>
#include <stdio.h>
#include <stdbool.h>
#include <esp_system.h>
#include <mbedtls/entropy.h>
#include <mbedtls/ctr_drbg.h>
#include <mbedtls/ecdh.h>
#include <mbedtls/ecdsa.h>
#include <mbedtls/error.h>
#include "unity.h"
/* Note: negative value here so that assert message prints a grep-able
error hex value (mbedTLS uses -N for error codes) */
#define TEST_ASSERT_MBEDTLS_OK(X) TEST_ASSERT_EQUAL_HEX32(0, -(X))
TEST_CASE("mbedtls ECDH Generate Key", "[mbedtls]")
{
mbedtls_ecdh_context ctx;
mbedtls_entropy_context entropy;
mbedtls_ctr_drbg_context ctr_drbg;
mbedtls_ecdh_init(&ctx);
mbedtls_ctr_drbg_init(&ctr_drbg);
mbedtls_entropy_init(&entropy);
TEST_ASSERT_MBEDTLS_OK( mbedtls_ctr_drbg_seed(&ctr_drbg, mbedtls_entropy_func, &entropy, NULL, 0) );
TEST_ASSERT_MBEDTLS_OK( mbedtls_ecp_group_load(&ctx.grp, MBEDTLS_ECP_DP_CURVE25519) );
TEST_ASSERT_MBEDTLS_OK( mbedtls_ecdh_gen_public(&ctx.grp, &ctx.d, &ctx.Q,
mbedtls_ctr_drbg_random, &ctr_drbg ) );
mbedtls_ecdh_free(&ctx);
mbedtls_ctr_drbg_free(&ctr_drbg);
mbedtls_entropy_free(&entropy);
}
TEST_CASE("mbedtls ECP self-tests", "[mbedtls]")
{
TEST_ASSERT_EQUAL(0, mbedtls_ecp_self_test(1));
}
TEST_CASE("mbedtls ECP mul w/ koblitz", "[mbedtls]")
{
/* Test case code via https://github.com/espressif/esp-idf/issues/1556 */
mbedtls_entropy_context ctxEntropy;
mbedtls_ctr_drbg_context ctxRandom;
mbedtls_ecdsa_context ctxECDSA;
const char* pers = "myecdsa";
mbedtls_entropy_init(&ctxEntropy);
mbedtls_ctr_drbg_init(&ctxRandom);
TEST_ASSERT_MBEDTLS_OK( mbedtls_ctr_drbg_seed(&ctxRandom, mbedtls_entropy_func, &ctxEntropy,
(const unsigned char*) pers, strlen(pers)) );
mbedtls_ecdsa_init(&ctxECDSA);
TEST_ASSERT_MBEDTLS_OK( mbedtls_ecdsa_genkey(&ctxECDSA, MBEDTLS_ECP_DP_SECP256K1,
mbedtls_ctr_drbg_random, &ctxRandom) );
TEST_ASSERT_MBEDTLS_OK(mbedtls_ecp_mul(&ctxECDSA.grp, &ctxECDSA.Q, &ctxECDSA.d, &ctxECDSA.grp.G,
mbedtls_ctr_drbg_random, &ctxRandom) );
mbedtls_ecdsa_free(&ctxECDSA);
mbedtls_ctr_drbg_free(&ctxRandom);
mbedtls_entropy_free(&ctxEntropy);
}

View File

@ -0,0 +1,45 @@
/* mbedTLS self-tests as unit tests
Focus on testing functionality where we use ESP32 hardware
accelerated crypto features.
See also test_hwcrypto.c in esp32 component, which tests hardware crypto without mbedTLS.
*/
#include <string.h>
#include <stdio.h>
#include <stdbool.h>
#include <esp_system.h>
#include "mbedtls/sha1.h"
#include "mbedtls/sha256.h"
#include "mbedtls/sha512.h"
#include "mbedtls/aes.h"
#include "mbedtls/bignum.h"
#include "mbedtls/rsa.h"
#include "freertos/FreeRTOS.h"
#include "freertos/task.h"
#include "freertos/semphr.h"
#include "unity.h"
#include "sdkconfig.h"
#include "test_apb_dport_access.h"
TEST_CASE("mbedtls AES self-tests", "[aes]")
{
start_apb_access_loop();
TEST_ASSERT_FALSE_MESSAGE(mbedtls_aes_self_test(1), "AES self-tests should pass.");
verify_apb_access_loop();
}
TEST_CASE("mbedtls MPI self-tests", "[bignum]")
{
start_apb_access_loop();
TEST_ASSERT_FALSE_MESSAGE(mbedtls_mpi_self_test(1), "MPI self-tests should pass.");
verify_apb_access_loop();
}
TEST_CASE("mbedtls RSA self-tests", "[bignum]")
{
start_apb_access_loop();
TEST_ASSERT_FALSE_MESSAGE(mbedtls_rsa_self_test(1), "RSA self-tests should pass.");
verify_apb_access_loop();
}

View File

@ -0,0 +1,211 @@
/* mbedTLS bignum (MPI) self-tests as unit tests
*/
#include <string.h>
#include <stdio.h>
#include <stdbool.h>
#include <esp_system.h>
#include "mbedtls/bignum.h"
#include "freertos/FreeRTOS.h"
#include "freertos/task.h"
#include "freertos/semphr.h"
#include "unity.h"
#include "sdkconfig.h"
#define MBEDTLS_OK 0
/* Debugging function to print an MPI number to stdout. Happens to
print output that can be copy-pasted directly into a Python shell.
*/
void mbedtls_mpi_printf(const char *name, const mbedtls_mpi *X)
{
static char buf[1024];
size_t n;
memset(buf, 0, sizeof(buf));
mbedtls_mpi_write_string(X, 16, buf, sizeof(buf)-1, &n);
if(n) {
printf("%s = 0x%s\n", name, buf);
} else {
printf("%s = TOOLONG\n", name);
}
}
/* Assert E = A * B */
static void test_bignum_mult(const char *a_str, const char *b_str, const char *e_str, size_t mod_bits)
{
mbedtls_mpi A, B, X, E, M;
char x_buf[1024] = { 0 };
size_t x_buf_len = 0;
mbedtls_mpi_init(&A);
mbedtls_mpi_init(&B);
mbedtls_mpi_init(&X);
mbedtls_mpi_init(&E);
TEST_ASSERT_FALSE(mbedtls_mpi_read_string(&A, 16, a_str));
TEST_ASSERT_FALSE(mbedtls_mpi_read_string(&B, 16, b_str));
/* E = A * B */
TEST_ASSERT_FALSE(mbedtls_mpi_read_string(&E, 16, e_str));
TEST_ASSERT_FALSE(mbedtls_mpi_mul_mpi(&X, &A, &B));
mbedtls_mpi_write_string(&X, 16, x_buf, sizeof(x_buf)-1, &x_buf_len);
TEST_ASSERT_EQUAL_STRING_MESSAGE(e_str, x_buf, "mbedtls_mpi_mul_mpi result wrong");
/* if mod_bits arg is set, also do a esp_mpi_mul_mod() call */
if (mod_bits > 0) {
mbedtls_mpi_init(&M);
for(int i = 0; i < mod_bits; i++) {
mbedtls_mpi_set_bit(&M, i, 1);
}
TEST_ASSERT_FALSE(esp_mpi_mul_mpi_mod(&X, &A, &B, &M));
mbedtls_mpi_write_string(&X, 16, x_buf, sizeof(x_buf)-1, &x_buf_len);
TEST_ASSERT_EQUAL_STRING_MESSAGE(e_str, x_buf, "esp_mpi_mul_mpi_mod result wrong");
mbedtls_mpi_free(&M);
}
mbedtls_mpi_free(&A);
mbedtls_mpi_free(&B);
mbedtls_mpi_free(&X);
mbedtls_mpi_free(&E);
}
TEST_CASE("test MPI multiplication", "[bignum]")
{
/* Run some trivial numbers tests w/ various high modulo bit counts,
should make no difference to the result
*/
for(int i = 512; i <= 4096; i+= 512) {
test_bignum_mult("10", "100", "1000",
i);
}
test_bignum_mult("60006FA8D3E3BD746BE39B860FFAADB4F108E15CF2ED8F685FB0E86CC4CB107A488720B41C3F1E18550F00619CD3CA8442296ECB54D2F52ECEE5346D310195700000000",
"BF474CA7",
"047BB102CAF58A48D3D97E4231BC0B753051D8232B9B939A2A4E310F88E65FEFD7762FC2DE0E2BAD6AA51A391DFFABD120653A312E4998F42E2C03AA404EE63B67275BC100000000",
1024);
test_bignum_mult("49493AC229831EC01EEB01EAF3BBEBC44768EADF9ABC30C87D1791F5E04245756ED4965361EC0599626884DF079B6B5738985CE76BD66FAA67E3AAAD60775D5C9D44C09FDF9E27C033696C007BE1C540D718CA148BA01FFA4A358541E9E9F02F72BE37AFAB037DAEA5E3669A770400D2F4A5DBBD83A83919D05E3DD64787BC80000000",
"B878CC29",
"34CF37013066D5BDA2C86CF1FE7BDA66604E0D55DAFF9864B6E727BFF5871012B0AB73D28D4E100BA1E4607AA2A247C912FDBC435C6BF7C5F8E00278AE1381B1E5F6E3D52D2CBE819F0D65CB37370666D156E7A7B1FD4698D8C9D3165FC8A83F9293C839521993619CCF8180E521300C4306206C9121D629754F1FCC7839BF6DFAF33080000000",
3072);
test_bignum_mult("24BF6185468786FDD303083D25E64EFC66CA472BC44D253102F8B4A9D3BFA75091386C0077937FE33FA3252D28855837AE1B484A8A9A45F7EE8C0C634F9E8CDDF79C5CE07EE72C7F123142198164234CABB724CF78B8173B9F880FC86322407AF1FEDFDDE2BEB674CA15F3E81A1521E071513A1E85B5DFA031F21ECAE9A34D",
"010001",
"24BF8644A80CCD855A00DB402E2374E2B5C6ADF60B78E97E2829B7A288697B103888FD38E393F776BF8664D04DB280BD0652F665D2E4D0923483FAEF5C01DC7C847A547CDBC7AB663EB0544AC37DA4B0CF03D0869D878FF3B6C3AF5072EAA39D3279D1DCC29C9933808ABDFE0DFD3BF59331AB6FBFD46556119250BD086E36A34D",
1536);
test_bignum_mult("-5D88B669C417EDD02213723546A906B7E9DA7683780E9B54856A2147467ADA316F8819D69486FC8056FE1E8EA7DEC5D5EF12340B95C4FC966F4B348D35893620",
"9AE7FBC99546432DF71896FC239EADAEF38D18D2B2F0E2DD275AA977E2BF4411F5A3B2A5D33605AEBBCCBA7FEB9F2D2FA74206CEC169D74BF5A8C50D6F48EA08",
"-38990016EB21810E3B5E6AEE339AEE72BB7CD629C4C9270A3D832701A2949BC82B2BE5A7F900C0C9937464699862821976095187D646884E8FBF01DE8C3442F3BC97B670AF573EFB74A9BBEBE4432EE74B0A83BBCDF59485D332B1FF49EB461A3A8B12C38FD72C7772D75EC6EBA5633199540C47678BD2F4ADEEA40830C2F100",
2048);
/* 1 << 2050 * 0X1234 */
test_bignum_mult("400000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
"1234",
"48D000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
3072);
/* multiply a 1178 bit number by a 2050 bit number */
test_bignum_mult("AAAAAAAAAA75124938ABBECD0EEEEE333333333333333333333FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFAAAAAAABBBBBBBBBBBBBBBBBBBB000000000000000000000000000000000004988A5293848932948872398400000000000FFFFFFFFFFF0000000000000EDFABC0204048975876873487387478327482374871327482347328742837483247283748234723874238",
"390587293875124938ABBECD0EEEEE3333333333333333333333333333333399999888000AAAAAAAAAAAAAAAAAAAAABBBBBBBBBBBBBBBBBBBB00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000EDFABC0204048975876873487387478327482374871327482347328742837483247283748234723874238478327400000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000003012111111111111111100000000000000000000000111111111111111111111111",
"02603AF70D0421C1AD82CE623F28F70B128118D06D00C27D433EC25BA86E6105C3890A0B1973B8BE068CA68E159A21078785DDB37F94216FBF4AEC939958AF4B8CEA2A48895CECA87562FC846EAAE0C866AF9D41EEABFB1D579F5828E9666A15E2AF946F16A189B5C645872FDCA247D309AB0BCAFB0D112881186FCFFEDC87061B4AE4A375E9BBCF579A7BC87A8EAC8C6F66E107986FC603F920F5E1A0FD8C619D88D90066FFFC8F4DB77437EBD7E3BD7E398C4C01F93426E347E039DCA7B0A73C0C90A9C4271BB761ADFF88971D190CE5DA98EFC5D7390D33BC034908AF81D784A4D7F32D0902E0C5DABC706635D5A28FC0E3A364EDEB21E8E117041D0E4B51CA6F9684F434057E7FCF2AF6BD050334B1D11E043B0967154E57354B681161D3C618974D5A7E0385755B80B931AE9B59DD4402BAEC206F04B8440741B3C4CA6D9F7DAF0AE6B3BF1B24B76C2F12B9E9A7C50D32E2093608FC9A30CBD852329E64A9AE0BC3F513899EBFA28629C1DF38081FB8C6630408F70D7B9A37701ABA4176C8B7DCB8CC78BD7783B861A7FC50862E75191DB8",
4096);
}
static bool test_bignum_modexp(const char *z_str, const char *x_str, const char *y_str, const char *m_str, int ret_error)
{
mbedtls_mpi Z, X, Y, M;
char z_buf[400] = { 0 };
size_t z_buf_len = 0;
bool fail = false;
printf("%s = (%s ^ %s) mod %s ret=%d ... ", z_str, x_str, y_str, m_str, ret_error);
mbedtls_mpi_init(&Z);
mbedtls_mpi_init(&X);
mbedtls_mpi_init(&Y);
mbedtls_mpi_init(&M);
TEST_ASSERT_FALSE(mbedtls_mpi_read_string(&X, 16, x_str));
TEST_ASSERT_FALSE(mbedtls_mpi_read_string(&Y, 16, y_str));
TEST_ASSERT_FALSE(mbedtls_mpi_read_string(&M, 16, m_str));
//mbedtls_mpi_printf("X", &X);
//mbedtls_mpi_printf("X", &Y);
//mbedtls_mpi_printf("M", &M);
/* Z = (X ^ Y) mod M */
if (ret_error != mbedtls_mpi_exp_mod(&Z, &X, &Y, &M, NULL)) {
fail = true;
}
if (ret_error == MBEDTLS_OK) {
mbedtls_mpi_write_string(&Z, 16, z_buf, sizeof(z_buf)-1, &z_buf_len);
if (memcmp(z_str, z_buf, strlen(z_str)) != 0) {
printf("\n Expected '%s' Was '%s' \n", z_str, z_buf);
fail = true;
}
}
mbedtls_mpi_free(&Z);
mbedtls_mpi_free(&X);
mbedtls_mpi_free(&Y);
mbedtls_mpi_free(&M);
if (fail == true) {
printf(" FAIL\n");
} else {
printf(" PASS\n");
}
return fail;
}
TEST_CASE("test MPI modexp", "[bignum]")
{
bool test_error = false;
printf("Z = (X ^ Y) mod M \n");
// test_bignum_modexp(Z, X, Y, M, ret_error);
test_error |= test_bignum_modexp("01000000", "1000", "2", "FFFFFFFF", MBEDTLS_OK);
test_error |= test_bignum_modexp("014B5A90", "1234", "2", "FFFFFFF", MBEDTLS_OK);
test_error |= test_bignum_modexp("01234321", "1111", "2", "FFFFFFFF", MBEDTLS_OK);
test_error |= test_bignum_modexp("02", "5", "1", "3", MBEDTLS_OK);
test_error |= test_bignum_modexp("22", "55", "1", "33", MBEDTLS_OK);
test_error |= test_bignum_modexp("0222", "555", "1", "333", MBEDTLS_OK);
test_error |= test_bignum_modexp("2222", "5555", "1", "3333", MBEDTLS_OK);
test_error |= test_bignum_modexp("11", "5555", "1", "33", MBEDTLS_OK);
test_error |= test_bignum_modexp("55", "1111", "1", "77", MBEDTLS_OK);
test_error |= test_bignum_modexp("88", "1111", "2", "BB", MBEDTLS_OK);
test_error |= test_bignum_modexp("01000000", "2", "128", "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF", MBEDTLS_OK);
test_error |= test_bignum_modexp("0ABCDEF12345", "ABCDEF12345", "1", "FFFFFFFFFFFF", MBEDTLS_OK);
test_error |= test_bignum_modexp("0ABCDE", "ABCDE", "1", "FFFFF", MBEDTLS_OK);
test_error |= test_bignum_modexp("04", "2", "2", "9", MBEDTLS_OK);
test_error |= test_bignum_modexp("04", "2", "-2", "9", MBEDTLS_ERR_MPI_BAD_INPUT_DATA);
test_error |= test_bignum_modexp("04", "2", "2", "-9", MBEDTLS_ERR_MPI_BAD_INPUT_DATA);
test_error |= test_bignum_modexp("04", "2", "-2", "-9", MBEDTLS_ERR_MPI_BAD_INPUT_DATA);
test_error |= test_bignum_modexp("01", "2", "0", "9", MBEDTLS_OK);
test_error |= test_bignum_modexp("04", "2", "0", "0", MBEDTLS_ERR_MPI_BAD_INPUT_DATA);
test_error |= test_bignum_modexp("04", "2", "2", "0", MBEDTLS_ERR_MPI_BAD_INPUT_DATA);
test_error |= test_bignum_modexp("00", "0", "2", "9", MBEDTLS_OK);
test_error |= test_bignum_modexp("01", "0", "0", "9", MBEDTLS_OK);
test_error |= test_bignum_modexp("04", "-2", "2", "9", MBEDTLS_OK);
test_error |= test_bignum_modexp("01", "-2", "0", "9", MBEDTLS_OK);
test_error |= test_bignum_modexp("07", "-2", "7", "9", MBEDTLS_OK);
test_error |= test_bignum_modexp("07", "-2", "1", "9", MBEDTLS_OK);
test_error |= test_bignum_modexp("02", "2", "1", "9", MBEDTLS_OK);
test_error |= test_bignum_modexp("01", "2", "0", "9", MBEDTLS_OK);
test_error |= test_bignum_modexp("05", "5", "7", "7", MBEDTLS_OK);
test_error |= test_bignum_modexp("02", "-5", "7", "7", MBEDTLS_OK);
test_error |= test_bignum_modexp("01", "-5", "7", "3", MBEDTLS_OK);
TEST_ASSERT_FALSE_MESSAGE(test_error, "mbedtls_mpi_exp_mod incorrect for some tests\n");
}

View File

@ -0,0 +1,301 @@
/* mbedTLS SHA unit tests
*/
#include <string.h>
#include <stdio.h>
#include <stdbool.h>
#include <esp_system.h>
#include "mbedtls/sha1.h"
#include "mbedtls/sha256.h"
#include "mbedtls/sha512.h"
#include "freertos/FreeRTOS.h"
#include "freertos/task.h"
#include "freertos/semphr.h"
#include "unity.h"
#include "sdkconfig.h"
#include "test_apb_dport_access.h"
TEST_CASE("mbedtls SHA self-tests", "[mbedtls]")
{
start_apb_access_loop();
TEST_ASSERT_FALSE_MESSAGE(mbedtls_sha1_self_test(1), "SHA1 self-tests should pass.");
TEST_ASSERT_FALSE_MESSAGE(mbedtls_sha256_self_test(1), "SHA256 self-tests should pass.");
TEST_ASSERT_FALSE_MESSAGE(mbedtls_sha512_self_test(1), "SHA512 self-tests should pass.");
TEST_ASSERT_FALSE_MESSAGE(mbedtls_sha512_self_test(1), "SHA512 self-tests should pass.");
verify_apb_access_loop();
}
static const unsigned char *one_hundred_as = (unsigned char *)
"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa";
static const unsigned char *one_hundred_bs = (unsigned char *)
"bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb";
static const uint8_t sha256_thousand_as[32] = {
0x41, 0xed, 0xec, 0xe4, 0x2d, 0x63, 0xe8, 0xd9, 0xbf, 0x51, 0x5a, 0x9b, 0xa6, 0x93, 0x2e, 0x1c,
0x20, 0xcb, 0xc9, 0xf5, 0xa5, 0xd1, 0x34, 0x64, 0x5a, 0xdb, 0x5d, 0xb1, 0xb9, 0x73, 0x7e, 0xa3 };
static const uint8_t sha256_thousand_bs[32] = {
0xf6, 0xf1, 0x18, 0xe1, 0x20, 0xe5, 0x2b, 0xe0, 0xbd, 0x0c, 0xfd, 0xf2, 0x79, 0x4c, 0xd1, 0x2c, 0x07, 0x68, 0x6c, 0xc8, 0x71, 0x23, 0x5a, 0xc2, 0xf1, 0x14, 0x59, 0x37, 0x8e, 0x6d, 0x23, 0x5b
};
static const uint8_t sha512_thousand_bs[64] = {
0xa6, 0x68, 0x68, 0xa3, 0x73, 0x53, 0x2a, 0x5c, 0xc3, 0x3f, 0xbf, 0x43, 0x4e, 0xba, 0x10, 0x86, 0xb3, 0x87, 0x09, 0xe9, 0x14, 0x3f, 0xbf, 0x37, 0x67, 0x8d, 0x43, 0xd9, 0x9b, 0x95, 0x08, 0xd5, 0x80, 0x2d, 0xbe, 0x9d, 0xe9, 0x1a, 0x54, 0xab, 0x9e, 0xbc, 0x8a, 0x08, 0xa0, 0x1a, 0x89, 0xd8, 0x72, 0x68, 0xdf, 0x52, 0x69, 0x7f, 0x1c, 0x70, 0xda, 0xe8, 0x3f, 0xe5, 0xae, 0x5a, 0xfc, 0x9d
};
static const uint8_t sha384_thousand_bs[48] = {
0x6d, 0xe5, 0xf5, 0x88, 0x57, 0x60, 0x83, 0xff, 0x7c, 0x94, 0x61, 0x5f, 0x8d, 0x96, 0xf2, 0x76, 0xd5, 0x3f, 0x77, 0x0c, 0x8e, 0xc1, 0xbf, 0xb6, 0x04, 0x27, 0xa4, 0xba, 0xea, 0x6c, 0x68, 0x44, 0xbd, 0xb0, 0x9c, 0xef, 0x6a, 0x09, 0x28, 0xe8, 0x1f, 0xfc, 0x95, 0x03, 0x69, 0x99, 0xab, 0x1a
};
static const uint8_t sha1_thousand_as[20] = {
0x29, 0x1e, 0x9a, 0x6c, 0x66, 0x99, 0x49, 0x49, 0xb5, 0x7b, 0xa5,
0xe6, 0x50, 0x36, 0x1e, 0x98, 0xfc, 0x36, 0xb1, 0xba };
TEST_CASE("mbedtls SHA interleaving", "[mbedtls]")
{
mbedtls_sha1_context sha1_ctx;
mbedtls_sha256_context sha256_ctx;
mbedtls_sha512_context sha512_ctx;
unsigned char sha1[20], sha256[32], sha512[64];
mbedtls_sha1_init(&sha1_ctx);
mbedtls_sha256_init(&sha256_ctx);
mbedtls_sha512_init(&sha512_ctx);
TEST_ASSERT_EQUAL(0, mbedtls_sha1_starts_ret(&sha1_ctx));
TEST_ASSERT_EQUAL(0, mbedtls_sha256_starts_ret(&sha256_ctx, false));
TEST_ASSERT_EQUAL(0, mbedtls_sha512_starts_ret(&sha512_ctx, false));
for (int i = 0; i < 10; i++) {
TEST_ASSERT_EQUAL(0, mbedtls_sha1_update_ret(&sha1_ctx, one_hundred_as, 100));
TEST_ASSERT_EQUAL(0, mbedtls_sha256_update_ret(&sha256_ctx, one_hundred_as, 100));
TEST_ASSERT_EQUAL(0, mbedtls_sha512_update_ret(&sha512_ctx, one_hundred_bs, 100));
}
TEST_ASSERT_EQUAL(0, mbedtls_sha1_finish_ret(&sha1_ctx, sha1));
TEST_ASSERT_EQUAL(0, mbedtls_sha256_finish_ret(&sha256_ctx, sha256));
TEST_ASSERT_EQUAL(0, mbedtls_sha512_finish_ret(&sha512_ctx, sha512));
TEST_ASSERT_EQUAL_MEMORY_MESSAGE(sha512_thousand_bs, sha512, 64, "SHA512 calculation");
TEST_ASSERT_EQUAL_MEMORY_MESSAGE(sha256_thousand_as, sha256, 32, "SHA256 calculation");
TEST_ASSERT_EQUAL_MEMORY_MESSAGE(sha1_thousand_as, sha1, 20, "SHA1 calculation");
}
static xSemaphoreHandle done_sem;
static void tskRunSHA1Test(void *pvParameters)
{
mbedtls_sha1_context sha1_ctx;
unsigned char sha1[20];
for (int i = 0; i < 1000; i++) {
mbedtls_sha1_init(&sha1_ctx);
TEST_ASSERT_EQUAL(0, mbedtls_sha1_starts_ret(&sha1_ctx));
for (int j = 0; j < 10; j++) {
TEST_ASSERT_EQUAL(0, mbedtls_sha1_update_ret(&sha1_ctx, (unsigned char *)one_hundred_as, 100));
}
TEST_ASSERT_EQUAL(0, mbedtls_sha1_finish_ret(&sha1_ctx, sha1));
TEST_ASSERT_EQUAL_MEMORY_MESSAGE(sha1_thousand_as, sha1, 20, "SHA1 calculation");
}
xSemaphoreGive(done_sem);
vTaskDelete(NULL);
}
static void tskRunSHA256Test(void *pvParameters)
{
mbedtls_sha256_context sha256_ctx;
unsigned char sha256[32];
for (int i = 0; i < 1000; i++) {
mbedtls_sha256_init(&sha256_ctx);
TEST_ASSERT_EQUAL(0, mbedtls_sha256_starts_ret(&sha256_ctx, false));
for (int j = 0; j < 10; j++) {
TEST_ASSERT_EQUAL(0, mbedtls_sha256_update_ret(&sha256_ctx, (unsigned char *)one_hundred_bs, 100));
}
TEST_ASSERT_EQUAL(0, mbedtls_sha256_finish_ret(&sha256_ctx, sha256));
TEST_ASSERT_EQUAL_MEMORY_MESSAGE(sha256_thousand_bs, sha256, 32, "SHA256 calculation");
}
xSemaphoreGive(done_sem);
vTaskDelete(NULL);
}
#define SHA_TASK_STACK_SIZE (10*1024)
TEST_CASE("mbedtls SHA multithreading", "[mbedtls]")
{
done_sem = xSemaphoreCreateCounting(4, 0);
xTaskCreate(tskRunSHA1Test, "SHA1Task1", SHA_TASK_STACK_SIZE, NULL, 3, NULL);
xTaskCreate(tskRunSHA1Test, "SHA1Task2", SHA_TASK_STACK_SIZE, NULL, 3, NULL);
xTaskCreate(tskRunSHA256Test, "SHA256Task1", SHA_TASK_STACK_SIZE, NULL, 3, NULL);
xTaskCreate(tskRunSHA256Test, "SHA256Task2", SHA_TASK_STACK_SIZE, NULL, 3, NULL);
for(int i = 0; i < 4; i++) {
if(!xSemaphoreTake(done_sem, 10000/portTICK_PERIOD_MS)) {
TEST_FAIL_MESSAGE("done_sem not released by test task");
}
}
vSemaphoreDelete(done_sem);
}
void tskRunSHASelftests(void *param)
{
for (int i = 0; i < 5; i++) {
if(mbedtls_sha1_self_test(1)) {
printf("SHA1 self-tests failed.\n");
while(1) {}
}
if(mbedtls_sha256_self_test(1)) {
printf("SHA256 self-tests failed.\n");
while(1) {}
}
if(mbedtls_sha512_self_test(1)) {
printf("SHA512 self-tests failed.\n");
while(1) {}
}
if(mbedtls_sha512_self_test(1)) {
printf("SHA512 self-tests failed.\n");
while(1) {}
}
}
xSemaphoreGive(done_sem);
vTaskDelete(NULL);
}
TEST_CASE("mbedtls SHA self-tests multithreaded", "[mbedtls]")
{
done_sem = xSemaphoreCreateCounting(2, 0);
xTaskCreate(tskRunSHASelftests, "SHASelftests1", SHA_TASK_STACK_SIZE, NULL, 3, NULL);
xTaskCreate(tskRunSHASelftests, "SHASelftests2", SHA_TASK_STACK_SIZE, NULL, 3, NULL);
const int TIMEOUT_MS = 20000;
for(int i = 0; i < 2; i++) {
if(!xSemaphoreTake(done_sem, TIMEOUT_MS/portTICK_PERIOD_MS)) {
TEST_FAIL_MESSAGE("done_sem not released by test task");
}
}
vSemaphoreDelete(done_sem);
}
TEST_CASE("mbedtls SHA512 clone", "[mbedtls]")
{
mbedtls_sha512_context ctx;
mbedtls_sha512_context clone;
unsigned char sha512[64];
mbedtls_sha512_init(&ctx);
TEST_ASSERT_EQUAL(0, mbedtls_sha512_starts_ret(&ctx, false));
for (int i = 0; i < 5; i++) {
TEST_ASSERT_EQUAL(0, mbedtls_sha512_update_ret(&ctx, one_hundred_bs, 100));
}
mbedtls_sha512_clone(&clone, &ctx);
for (int i = 0; i < 5; i++) {
TEST_ASSERT_EQUAL(0, mbedtls_sha512_update_ret(&ctx, one_hundred_bs, 100));
TEST_ASSERT_EQUAL(0, mbedtls_sha512_update_ret(&clone, one_hundred_bs, 100));
}
TEST_ASSERT_EQUAL(0, mbedtls_sha512_finish_ret(&ctx, sha512));
TEST_ASSERT_EQUAL_MEMORY_MESSAGE(sha512_thousand_bs, sha512, 64, "SHA512 original calculation");
TEST_ASSERT_EQUAL(0, mbedtls_sha512_finish_ret(&clone, sha512));
TEST_ASSERT_EQUAL_MEMORY_MESSAGE(sha512_thousand_bs, sha512, 64, "SHA512 cloned calculation");
}
TEST_CASE("mbedtls SHA384 clone", "[mbedtls]")
{
mbedtls_sha512_context ctx;
mbedtls_sha512_context clone;
unsigned char sha384[48];
mbedtls_sha512_init(&ctx);
TEST_ASSERT_EQUAL(0, mbedtls_sha512_starts_ret(&ctx, true));
for (int i = 0; i < 5; i++) {
TEST_ASSERT_EQUAL(0, mbedtls_sha512_update_ret(&ctx, one_hundred_bs, 100));
}
mbedtls_sha512_clone(&clone, &ctx);
for (int i = 0; i < 5; i++) {
TEST_ASSERT_EQUAL(0, mbedtls_sha512_update_ret(&ctx, one_hundred_bs, 100));
TEST_ASSERT_EQUAL(0, mbedtls_sha512_update_ret(&clone, one_hundred_bs, 100));
}
TEST_ASSERT_EQUAL(0, mbedtls_sha512_finish_ret(&ctx, sha384));
TEST_ASSERT_EQUAL_MEMORY_MESSAGE(sha384_thousand_bs, sha384, 48, "SHA512 original calculation");
TEST_ASSERT_EQUAL(0, mbedtls_sha512_finish_ret(&clone, sha384));
TEST_ASSERT_EQUAL_MEMORY_MESSAGE(sha384_thousand_bs, sha384, 48, "SHA512 cloned calculation");
}
TEST_CASE("mbedtls SHA256 clone", "[mbedtls]")
{
mbedtls_sha256_context ctx;
mbedtls_sha256_context clone;
unsigned char sha256[64];
mbedtls_sha256_init(&ctx);
TEST_ASSERT_EQUAL(0, mbedtls_sha256_starts_ret(&ctx, false));
for (int i = 0; i < 5; i++) {
TEST_ASSERT_EQUAL(0, mbedtls_sha256_update_ret(&ctx, one_hundred_as, 100));
}
mbedtls_sha256_clone(&clone, &ctx);
for (int i = 0; i < 5; i++) {
TEST_ASSERT_EQUAL(0, mbedtls_sha256_update_ret(&ctx, one_hundred_as, 100));
TEST_ASSERT_EQUAL(0, mbedtls_sha256_update_ret(&clone, one_hundred_as, 100));
}
TEST_ASSERT_EQUAL(0, mbedtls_sha256_finish_ret(&ctx, sha256));
TEST_ASSERT_EQUAL_MEMORY_MESSAGE(sha256_thousand_as, sha256, 32, "SHA256 original calculation");
TEST_ASSERT_EQUAL(0, mbedtls_sha256_finish_ret(&clone, sha256));
TEST_ASSERT_EQUAL_MEMORY_MESSAGE(sha256_thousand_as, sha256, 32, "SHA256 cloned calculation");
}
typedef struct {
mbedtls_sha256_context ctx;
uint8_t result[32];
int ret;
bool done;
} finalise_sha_param_t;
static void tskFinaliseSha(void *v_param)
{
finalise_sha_param_t *param = (finalise_sha_param_t *)v_param;
for (int i = 0; i < 5; i++) {
TEST_ASSERT_EQUAL(0, mbedtls_sha256_update_ret(&param->ctx, one_hundred_as, 100));
}
param->ret = mbedtls_sha256_finish_ret(&param->ctx, param->result);
param->done = true;
vTaskDelete(NULL);
}
TEST_CASE("mbedtls SHA session passed between tasks" , "[mbedtls]")
{
finalise_sha_param_t param = { 0 };
mbedtls_sha256_init(&param.ctx);
TEST_ASSERT_EQUAL(0, mbedtls_sha256_starts_ret(&param.ctx, false));
for (int i = 0; i < 5; i++) {
TEST_ASSERT_EQUAL(0, mbedtls_sha256_update_ret(&param.ctx, one_hundred_as, 100));
}
// pass the SHA context off to a different task
//
// note: at the moment this doesn't crash even if a mutex semaphore is used as the
// engine lock, but it can crash...
xTaskCreate(tskFinaliseSha, "SHAFinalise", SHA_TASK_STACK_SIZE, &param, 3, NULL);
while (!param.done) {
vTaskDelay(1);
}
TEST_ASSERT_EQUAL(0, param.ret);
TEST_ASSERT_EQUAL_MEMORY_MESSAGE(sha256_thousand_as, param.result, 32, "SHA256 result from other task");
}

View File

@ -0,0 +1,240 @@
/* mbedTLS RSA functionality tests
Focus on testing functionality where we use ESP32 hardware
accelerated crypto features.
*/
#include <string.h>
#include <stdio.h>
#include <stdbool.h>
#include <esp_system.h>
#include "mbedtls/rsa.h"
#include "mbedtls/pk.h"
#include "mbedtls/x509_crt.h"
#include "freertos/FreeRTOS.h"
#include "freertos/task.h"
#include "freertos/semphr.h"
#include "unity.h"
#include "sdkconfig.h"
/* Taken from openssl s_client -connect api.gigafive.com:443 -showcerts
*/
static const char *rsa4096_cert = "-----BEGIN CERTIFICATE-----\n"\
"MIIExzCCA6+gAwIBAgIBAzANBgkqhkiG9w0BAQsFADCBkjELMAkGA1UEBhMCVVMx\n"\
"CzAJBgNVBAgMAkNBMRQwEgYDVQQHDAtTYW50YSBDbGFyYTElMCMGA1UECgwcR2ln\n"\
"YWZpdmUgVGVjaG5vbG9neSBQYXJ0bmVyczEZMBcGA1UEAwwQR2lnYWZpdmUgUm9v\n"\
"dCBDQTEeMBwGCSqGSIb3DQEJARYPY2FAZ2lnYWZpdmUuY29tMB4XDTE2MDgyNzE2\n"\
"NDYyM1oXDTI2MDgyNTE2NDYyM1owgZcxCzAJBgNVBAYTAlVTMQswCQYDVQQIDAJD\n"\
"QTEUMBIGA1UEBwwLU2FudGEgQ2xhcmExKTAnBgNVBAoMIEdpZ2FmaXZlIFRlY2hu\n"\
"b2xvZ3kgUGFydG5lcnMgTExDMRkwFwYDVQQDDBBhcGkuZ2lnYWZpdmUuY29tMR8w\n"\
"HQYJKoZIhvcNAQkBFhBjcmxAZ2lnYWZpdmUuY29tMIICIjANBgkqhkiG9w0BAQEF\n"\
"AAOCAg8AMIICCgKCAgEAof82VrEpXMpsI/ddW6RLeTeSYtxiXZZkRbDKN6otYgEk\n"\
"vA8yRbzei2cO2A/8+Erhe9beYLAMXWF+bjoUAFwnuIcbmufgHprOYzX/7CYXCsrH\n"\
"LrJfVF6kvjCXy2W3xSvgh8ZgHNWnBGzl13tq19Fz8x0AhK5GQ9608oJCbnQjpVSI\n"\
"lZDl3JVOifCeXf2c7nMhVOC/reTeto0Gbchs8Ox50WyojmfYbVjOQcA7f8p1eI+D\n"\
"XUJK01cUGVu6/KarVArGHh5LsiyXOadbyeyOXPmjyrgarG3IIBeQSNECfJZPc/OW\n"\
"lFszjU4YLDckI4x+tReiuFQbQPN5sDplcEldmZZm/8XD36ddvAaDds+SYlPXxDK7\n"\
"7L8RBVUG2Ylc9YZf7RE6IMDmdQmsCZDX0VxySYEmzv5lnAx4mzzaXcgS+kHMOLyK\n"\
"n9UxmpzwQoqqC9tMZqwRaeKW1njR1dSwQLqirBPfGCWKkpkpm7C3HEfeeLrasral\n"\
"aPf6LAwN3A4ZKHa5Jmne7W+1eYS1aTXOAOLIPcXRAh1B80H+SusIdM9d6vk2YTIg\n"\
"khwGQV3sgM6nIO5+T/8z141UEjWbtP7pb/u0+G9Cg7TwvRoO2UukxdvOwNto1G2e\n"\
"J3rKB/JSYsYWnPHvvh9XR+55PZ4iCf9Rqw/IP82uyGipR9gxlHqN8WhMTj9tNEkC\n"\
"AwEAAaMhMB8wHQYDVR0OBBYEFISCemcSriz1HFhRXluw9H+Bv9lEMA0GCSqGSIb3\n"\
"DQEBCwUAA4IBAQCMetK0xe6Y/uZpb1ARh+hHYcHI3xI+IG4opWJeoB1gDh/xpNAW\n"\
"j6t5MGbLoqNMBXbqL26hnKVspyvCxw7ebI5ZJgjtbrD1t+0D8yrgIZzr7AWGA9Hj\n"\
"WIHqDHGDxwkmfjVVPmuO3l5RtJmL6KV6kVL2bOvVI6gECpFLddmOTtg+iXDfSw3x\n"\
"0+ueMYKr8QLF+TCxfzQTHvTHvOJtcZHecc1n7PYbRmI2p7tV6RoBpV69oM6NAVUV\n"\
"i2QoSxm0pYzDzavOaxwhEPHT34Tpg6fwXy1QokFD9OtxRFtdpTjL3bMWpatZE+ba\n"\
"cjvvf0utMW5fNjTTxu1nnpuxZM3ifTCqZJ+9\n"\
"-----END CERTIFICATE-----\n";
/* Root cert from openssl s_client -connect google.com:443 -showcerts
*/
static const char *rsa2048_cert = "-----BEGIN CERTIFICATE-----\n"\
"MIIDfTCCAuagAwIBAgIDErvmMA0GCSqGSIb3DQEBBQUAME4xCzAJBgNVBAYTAlVT\n"\
"MRAwDgYDVQQKEwdFcXVpZmF4MS0wKwYDVQQLEyRFcXVpZmF4IFNlY3VyZSBDZXJ0\n"\
"aWZpY2F0ZSBBdXRob3JpdHkwHhcNMDIwNTIxMDQwMDAwWhcNMTgwODIxMDQwMDAw\n"\
"WjBCMQswCQYDVQQGEwJVUzEWMBQGA1UEChMNR2VvVHJ1c3QgSW5jLjEbMBkGA1UE\n"\
"AxMSR2VvVHJ1c3QgR2xvYmFsIENBMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIB\n"\
"CgKCAQEA2swYYzD99BcjGlZ+W988bDjkcbd4kdS8odhM+KhDtgPpTSEHCIjaWC9m\n"\
"OSm9BXiLnTjoBbdqfnGk5sRgprDvgOSJKA+eJdbtg/OtppHHmMlCGDUUna2YRpIu\n"\
"T8rxh0PBFpVXLVDviS2Aelet8u5fa9IAjbkU+BQVNdnARqN7csiRv8lVK83Qlz6c\n"\
"JmTM386DGXHKTubU1XupGc1V3sjs0l44U+VcT4wt/lAjNvxm5suOpDkZALeVAjmR\n"\
"Cw7+OC7RHQWa9k0+bw8HHa8sHo9gOeL6NlMTOdReJivbPagUvTLrGAMoUgRx5asz\n"\
"PeE4uwc2hGKceeoWMPRfwCvocWvk+QIDAQABo4HwMIHtMB8GA1UdIwQYMBaAFEjm\n"\
"aPkr0rKV10fYIyAQTzOYkJ/UMB0GA1UdDgQWBBTAephojYn7qwVkDBF9qn1luMrM\n"\
"TjAPBgNVHRMBAf8EBTADAQH/MA4GA1UdDwEB/wQEAwIBBjA6BgNVHR8EMzAxMC+g\n"\
"LaArhilodHRwOi8vY3JsLmdlb3RydXN0LmNvbS9jcmxzL3NlY3VyZWNhLmNybDBO\n"\
"BgNVHSAERzBFMEMGBFUdIAAwOzA5BggrBgEFBQcCARYtaHR0cHM6Ly93d3cuZ2Vv\n"\
"dHJ1c3QuY29tL3Jlc291cmNlcy9yZXBvc2l0b3J5MA0GCSqGSIb3DQEBBQUAA4GB\n"\
"AHbhEm5OSxYShjAGsoEIz/AIx8dxfmbuwu3UOx//8PDITtZDOLC5MH0Y0FWDomrL\n"\
"NhGc6Ehmo21/uBPUR/6LWlxz/K7ZGzIZOKuXNBSqltLroxwUCEm2u+WR74M26x1W\n"\
"b8ravHNjkOR/ez4iyz0H7V84dJzjA1BOoa+Y7mHyhD8S\n"\
"-----END CERTIFICATE-----\n";
/* Some random input bytes to public key encrypt */
static const uint8_t pki_input[4096/8] = {
0, 1, 4, 6, 7, 9, 33, 103, 49, 11, 56, 211, 67, 92 };
/* Result of an RSA4096 operation using cert's public key
(raw PKI, no padding/etc) */
static const uint8_t pki_rsa4096_output[] = {
0x91, 0x87, 0xcd, 0x04, 0x80, 0x7c, 0x8b, 0x0b,
0x0c, 0xc0, 0x38, 0x37, 0x7a, 0xe3, 0x2c, 0x94,
0xea, 0xc4, 0xcb, 0x83, 0x2c, 0x77, 0x71, 0x14,
0x11, 0x85, 0x16, 0x61, 0xd3, 0x64, 0x2a, 0x0f,
0xf9, 0x6b, 0x45, 0x04, 0x66, 0x5d, 0x15, 0xf1,
0xcf, 0x69, 0x77, 0x90, 0xb9, 0x41, 0x68, 0xa9,
0xa6, 0xfd, 0x94, 0xdc, 0x6a, 0xce, 0xc7, 0xb6,
0x41, 0xd9, 0x44, 0x3c, 0x02, 0xb6, 0xc7, 0x26,
0xce, 0xec, 0x66, 0x21, 0xa8, 0xe8, 0xf4, 0xa9,
0x33, 0x4a, 0x6c, 0x28, 0x0f, 0x50, 0x30, 0x32,
0x28, 0x00, 0xbb, 0x2c, 0xc3, 0x44, 0x72, 0x31,
0x93, 0xd4, 0xde, 0x29, 0x6b, 0xfa, 0x31, 0xfd,
0x3a, 0x05, 0xc6, 0xb1, 0x28, 0x43, 0x57, 0x20,
0xf7, 0xf8, 0x13, 0x0c, 0x4a, 0x80, 0x00, 0xab,
0x1f, 0xe8, 0x88, 0xad, 0x56, 0xf2, 0xda, 0x5a,
0x50, 0xe9, 0x02, 0x09, 0x21, 0x2a, 0xfc, 0x82,
0x68, 0x34, 0xf9, 0x04, 0xa3, 0x25, 0xe1, 0x0f,
0xa8, 0x77, 0x29, 0x94, 0xb6, 0x9d, 0x5a, 0x08,
0x33, 0x8d, 0x27, 0x6a, 0xc0, 0x3b, 0xad, 0x91,
0x8a, 0x83, 0xa9, 0x2e, 0x48, 0xcd, 0x67, 0xa3,
0x3a, 0x35, 0x41, 0x85, 0xfa, 0x3f, 0x61, 0x1f,
0x80, 0xeb, 0xcd, 0x5a, 0xc5, 0x14, 0x7b, 0xab,
0x9c, 0x45, 0x11, 0xd2, 0x25, 0x9a, 0x16, 0xeb,
0x9c, 0xfa, 0xbe, 0x73, 0x18, 0xbd, 0x25, 0x8e,
0x99, 0x6d, 0xb3, 0xbc, 0xac, 0x2d, 0xa2, 0x53,
0xe8, 0x7c, 0x38, 0x1b, 0x7a, 0x75, 0xff, 0x76,
0x4f, 0x48, 0x5b, 0x39, 0x20, 0x5a, 0x7b, 0x82,
0xd3, 0x33, 0x33, 0x2a, 0xab, 0x6a, 0x7a, 0x42,
0x1d, 0x1f, 0xd1, 0x61, 0x58, 0xd7, 0x38, 0x52,
0xdf, 0xb0, 0x61, 0x98, 0x63, 0xb7, 0xa1, 0x4e,
0xdb, 0x9b, 0xcb, 0xb7, 0x85, 0xc4, 0x3e, 0x03,
0xe5, 0x59, 0x50, 0x28, 0x5a, 0x4d, 0x7f, 0x53,
0x2e, 0x99, 0x1d, 0x6d, 0x85, 0x27, 0x78, 0x34,
0x5e, 0xae, 0xc9, 0x1b, 0x37, 0x96, 0xde, 0x40,
0x87, 0x35, 0x3c, 0x1f, 0xe0, 0x8f, 0xfb, 0x3a,
0x58, 0x0e, 0x60, 0xe9, 0x06, 0xbd, 0x83, 0x03,
0x92, 0xde, 0x5e, 0x69, 0x28, 0xb1, 0x00, 0xeb,
0x44, 0xca, 0x3c, 0x49, 0x03, 0x10, 0xa8, 0x84,
0xa6, 0xbb, 0xd5, 0xda, 0x98, 0x8c, 0x6f, 0xa3,
0x0f, 0x39, 0xf3, 0xa7, 0x7d, 0xd5, 0x3b, 0xe2,
0x85, 0x12, 0xda, 0xa4, 0x4d, 0x80, 0x97, 0xcb,
0x11, 0xe0, 0x89, 0x90, 0xff, 0x5b, 0x72, 0x19,
0x59, 0xd1, 0x39, 0x23, 0x9f, 0xb0, 0x00, 0xe2,
0x45, 0x72, 0xc6, 0x9a, 0xbc, 0xe1, 0xd1, 0x51,
0x6b, 0x35, 0xd2, 0x49, 0xbf, 0xb6, 0xfe, 0xab,
0x09, 0xf7, 0x9d, 0xa4, 0x6e, 0x69, 0xb6, 0xf9,
0xde, 0xe3, 0x57, 0x0c, 0x1a, 0x96, 0xf1, 0xcc,
0x1c, 0x92, 0xdb, 0x44, 0xf4, 0x45, 0xfa, 0x8f,
0x87, 0xcf, 0xf4, 0xd2, 0xa1, 0xf8, 0x69, 0x18,
0xcf, 0xdc, 0xa0, 0x1f, 0xb0, 0x26, 0xad, 0x81,
0xab, 0xdf, 0x78, 0x18, 0xa2, 0x74, 0xba, 0x2f,
0xec, 0x70, 0xa2, 0x1f, 0x56, 0xee, 0xff, 0xc9,
0xfe, 0xb1, 0xe1, 0x9b, 0xea, 0x0e, 0x33, 0x14,
0x5f, 0x6e, 0xca, 0xee, 0x02, 0x56, 0x5a, 0x67,
0x42, 0x9a, 0xbf, 0x55, 0xc0, 0x0f, 0x8e, 0x01,
0x67, 0x63, 0x6e, 0xd1, 0x57, 0xf7, 0xf1, 0xc6,
0x92, 0x9e, 0xb5, 0x45, 0xe1, 0x50, 0x58, 0x94,
0x20, 0x90, 0x6a, 0x29, 0x2d, 0x4b, 0xd1, 0xb5,
0x68, 0x63, 0xb5, 0xe6, 0xd8, 0x6e, 0x84, 0x80,
0xad, 0xe6, 0x03, 0x1e, 0x51, 0xc2, 0xa8, 0x6d,
0x84, 0xec, 0x2d, 0x7c, 0x61, 0x02, 0xd1, 0xda,
0xf5, 0x94, 0xfa, 0x2d, 0xa6, 0xed, 0x89, 0x6a,
0x6a, 0xda, 0x07, 0x5d, 0x83, 0xfc, 0x43, 0x76,
0x7c, 0xca, 0x8c, 0x00, 0xfc, 0xb9, 0x2c, 0x23,
};
static const uint8_t pki_rsa2048_output[] = {
0x47, 0x0b, 0xe5, 0x8a, 0xcd, 0x2f, 0x78, 0x07,
0x69, 0x69, 0x70, 0xff, 0x81, 0xdf, 0x96, 0xf0,
0xed, 0x82, 0x3a, 0x3d, 0x46, 0xab, 0xe9, 0xc3,
0xb5, 0xd9, 0xca, 0xa2, 0x05, 0xa9, 0xf6, 0x6e,
0xad, 0x6c, 0xe0, 0xd1, 0xa2, 0xb4, 0xf2, 0x78,
0x4a, 0x93, 0xfc, 0x45, 0xe1, 0x9b, 0xdd, 0x62,
0xf9, 0x66, 0x2a, 0x14, 0x38, 0x12, 0xb6, 0x50,
0x0b, 0xe3, 0x53, 0x9c, 0x12, 0x56, 0xf1, 0xb7,
0x83, 0xd5, 0xf3, 0x24, 0x81, 0xcc, 0x5a, 0xeb,
0xec, 0xac, 0x68, 0xa8, 0x0c, 0xd7, 0x84, 0x7a,
0xbb, 0x77, 0x7b, 0xd5, 0x5b, 0xcf, 0x7b, 0x25,
0xd0, 0x75, 0x80, 0x21, 0x12, 0x97, 0x6b, 0xe1,
0xb6, 0x51, 0x12, 0x52, 0x6e, 0x01, 0x92, 0xb7,
0xcc, 0x70, 0x4b, 0x46, 0x11, 0x98, 0x5a, 0x84,
0x1c, 0x90, 0x45, 0x0f, 0x15, 0x77, 0xdb, 0x79,
0xe8, 0xff, 0x1f, 0xaa, 0x58, 0x95, 0xce, 0x3c,
0x65, 0x0c, 0x66, 0x29, 0xe1, 0x9c, 0x41, 0xbb,
0xde, 0x65, 0xb8, 0x29, 0x36, 0x94, 0xbd, 0x87,
0x93, 0x39, 0xc5, 0xeb, 0x49, 0x21, 0xc1, 0xeb,
0x48, 0xbd, 0x19, 0x13, 0x4d, 0x40, 0x90, 0x88,
0xc6, 0x12, 0xd9, 0xf7, 0xdd, 0xc8, 0x4f, 0x89,
0xc0, 0x91, 0xf8, 0xeb, 0xcf, 0xe3, 0x12, 0x17,
0x88, 0x9c, 0x88, 0xf4, 0xf5, 0xae, 0xf4, 0x15,
0xfe, 0x17, 0xf6, 0xa4, 0x74, 0x49, 0x02, 0x05,
0x11, 0x3b, 0x92, 0x25, 0x39, 0x2c, 0x4b, 0x08,
0x19, 0x76, 0x13, 0x8d, 0xf9, 0xda, 0xae, 0xdf,
0x30, 0xda, 0xcc, 0xbb, 0x3f, 0xb9, 0xb0, 0xd6,
0x5c, 0x78, 0x4b, 0x2b, 0x35, 0x51, 0x17, 0x48,
0xf5, 0xd4, 0x39, 0x7e, 0x05, 0x83, 0x68, 0x86,
0x44, 0x5f, 0x56, 0x1d, 0x2c, 0x53, 0xd3, 0x64,
0x3a, 0xb2, 0x0c, 0x4a, 0x85, 0xd6, 0x5b, 0x7e,
0xf9, 0xe9, 0x50, 0x29, 0x5d, 0x4f, 0xcc, 0xc9,
};
_Static_assert(sizeof(pki_rsa2048_output) == 2048/8, "rsa2048 output is wrong size");
_Static_assert(sizeof(pki_rsa4096_output) == 4096/8, "rsa4096 output is wrong size");
static void test_cert(const char *cert, const uint8_t *expected_output, size_t output_len);
TEST_CASE("mbedtls RSA4096 cert", "[mbedtls]")
{
test_cert(rsa4096_cert, pki_rsa4096_output, 4096/8);
}
TEST_CASE("mbedtls RSA2048 cert", "[mbedtls]")
{
test_cert(rsa2048_cert, pki_rsa2048_output, 2048/8);
}
static void test_cert(const char *cert, const uint8_t *expected_output, size_t output_len)
{
mbedtls_x509_crt crt;
mbedtls_rsa_context *rsa;
char buf[output_len];
bzero(buf, output_len);
mbedtls_x509_crt_init(&crt);
TEST_ASSERT_EQUAL_HEX16_MESSAGE(0,
-mbedtls_x509_crt_parse(&crt,
(const uint8_t *)cert,
strlen(cert)+1),
"parse cert");
rsa = mbedtls_pk_rsa(crt.pk);
TEST_ASSERT_NOT_NULL(rsa);
TEST_ASSERT_EQUAL_HEX16_MESSAGE(0,
-mbedtls_rsa_check_pubkey(rsa),
"check cert pubkey");
mbedtls_x509_crt_info(buf, sizeof(buf), "", &crt);
puts(buf);
TEST_ASSERT_EQUAL_HEX16_MESSAGE(0,
-mbedtls_rsa_public(rsa, pki_input, (uint8_t *)buf),
"RSA PK operation");
/*
// Dump buffer for debugging
for(int i = 0; i < output_len; i++) {
printf("0x%02x, ", buf[i]);
}
printf("\n");
*/
TEST_ASSERT_EQUAL_HEX8_ARRAY(expected_output, buf, output_len);
mbedtls_x509_crt_free(&crt);
}