diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml index 96006f8c8..e7b240a4f 100644 --- a/.gitlab-ci.yml +++ b/.gitlab-ci.yml @@ -37,7 +37,7 @@ build_template_app: # branch - git checkout ${CI_BUILD_REF_NAME} || echo "Using esp-idf-template default branch..." - make defconfig - - make all + - make all V=1 .build_gitlab: &build_template diff --git a/components/bootloader/Makefile.projbuild b/components/bootloader/Makefile.projbuild index aaebd4d26..cf8b05673 100644 --- a/components/bootloader/Makefile.projbuild +++ b/components/bootloader/Makefile.projbuild @@ -18,15 +18,11 @@ BOOTLOADER_BIN=$(BOOTLOADER_BUILD_DIR)/bootloader.bin $(BOOTLOADER_BIN): $(COMPONENT_PATH)/src/sdkconfig $(Q) PROJECT_PATH= \ - LDFLAGS= \ - CFLAGS= \ BUILD_DIR_BASE=$(BOOTLOADER_BUILD_DIR) \ $(MAKE) -C $(BOOTLOADER_COMPONENT_PATH)/src MAKEFLAGS= V=$(V) TARGET_BIN_LAYOUT="$(BOOTLOADER_TARGET_BIN_LAYOUT)" $(BOOTLOADER_BIN) bootloader-clean: $(Q) PROJECT_PATH= \ - LDFLAGS= \ - CFLAGS= \ BUILD_DIR_BASE=$(BOOTLOADER_BUILD_DIR) \ $(MAKE) -C $(BOOTLOADER_COMPONENT_PATH)/src app-clean MAKEFLAGS= V=$(V) diff --git a/components/esp32/component.mk b/components/esp32/component.mk index 6bb7c951a..e7397b2a1 100644 --- a/components/esp32/component.mk +++ b/components/esp32/component.mk @@ -8,6 +8,8 @@ # -include $(PROJECT_PATH)/build/include/config/auto.conf +COMPONENT_SRCDIRS := . hwcrypto + LIBS := crypto core net80211 phy rtc pp wpa wps ifeq ($(CONFIG_MEMMAP_BT),y) diff --git a/components/esp32/hwcrypto/aes.c b/components/esp32/hwcrypto/aes.c new file mode 100644 index 000000000..169465822 --- /dev/null +++ b/components/esp32/hwcrypto/aes.c @@ -0,0 +1,354 @@ +/** + * \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. + * + */ +/* + * 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 +#include "hwcrypto/aes.h" +#include "rom/aes.h" +#include + +static _lock_t aes_lock; + +void esp_aes_acquire_hardware( void ) +{ + /* newlib locks lazy initialize on ESP-IDF */ + _lock_acquire(&aes_lock); + ets_aes_enable(); +} + +void esp_aes_release_hardware( void ) +{ + uint8_t zero[256/8] = { 0 }; + ets_aes_setkey_enc(zero, AES256); + ets_aes_disable(); + _lock_release(&aes_lock); +} + +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 ) ); +} + +/* Translate number of bits to an AES_BITS enum */ +static int keybits_to_aesbits(unsigned int keybits) +{ + switch (keybits) { + case 128: + return AES128; + case 192: + return AES192; + break; + case 256: + return AES256; + default: + return ( ERR_ESP_AES_INVALID_KEY_LENGTH ); + } +} + +/* + * AES key schedule (encryption) + * + */ +int esp_aes_setkey_enc( esp_aes_context *ctx, const unsigned char *key, + unsigned int keybits ) +{ + uint16_t keybytes = keybits / 8; + int aesbits = keybits_to_aesbits(keybits); + if (aesbits < 0) { + return aesbits; + } + ctx->enc.aesbits = aesbits; + bzero(ctx->enc.key, sizeof(ctx->enc.key)); + memcpy(ctx->enc.key, key, keybytes); + return 0; +} + +/* + * AES key schedule (decryption) + * + */ +int esp_aes_setkey_dec( esp_aes_context *ctx, const unsigned char *key, + unsigned int keybits ) +{ + uint16_t keybytes = keybits / 8; + int aesbits = keybits_to_aesbits(keybits); + if (aesbits < 0) { + return aesbits; + } + ctx->dec.aesbits = aesbits; + bzero(ctx->dec.key, sizeof(ctx->dec.key)); + memcpy(ctx->dec.key, key, keybytes); + return 0; +} + +/* + * Helper function to copy key from esp_aes_context buffer + * to hardware key registers. + * + * Only call when protected by esp_aes_acquire_hardware(). + */ +static inline int esp_aes_setkey_hardware( esp_aes_context *ctx, int mode) +{ + if ( mode == ESP_AES_ENCRYPT ) { + ets_aes_setkey_enc(ctx->enc.key, ctx->enc.aesbits); + } else { + ets_aes_setkey_dec(ctx->dec.key, ctx->dec.aesbits); + } + return 0; +} + +/* + * AES-ECB block encryption + */ +void esp_aes_encrypt( esp_aes_context *ctx, + const unsigned char input[16], + unsigned char output[16] ) +{ + esp_aes_acquire_hardware(); + esp_aes_setkey_hardware(ctx, ESP_AES_ENCRYPT); + ets_aes_crypt(input, output); + esp_aes_release_hardware(); +} + +/* + * AES-ECB block decryption + */ + +void esp_aes_decrypt( esp_aes_context *ctx, + const unsigned char input[16], + unsigned char output[16] ) +{ + esp_aes_acquire_hardware(); + esp_aes_setkey_hardware(ctx, ESP_AES_DECRYPT); + ets_aes_crypt(input, output); + esp_aes_release_hardware(); +} + + +/* + * 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] ) +{ + esp_aes_acquire_hardware(); + esp_aes_setkey_hardware(ctx, mode); + ets_aes_crypt(input, output); + esp_aes_release_hardware(); + return 0; +} + + +/* + * 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; + unsigned char temp[16]; + + if ( length % 16 ) { + return ( ERR_ESP_AES_INVALID_INPUT_LENGTH ); + } + + esp_aes_acquire_hardware(); + esp_aes_setkey_hardware(ctx, mode); + + if ( mode == ESP_AES_DECRYPT ) { + while ( length > 0 ) { + memcpy( temp, input, 16 ); + ets_aes_crypt(input, output); + + for ( i = 0; i < 16; i++ ) { + output[i] = (unsigned char)( output[i] ^ iv[i] ); + } + + memcpy( iv, temp, 16 ); + + input += 16; + output += 16; + length -= 16; + } + } else { + while ( length > 0 ) { + for ( i = 0; i < 16; i++ ) { + output[i] = (unsigned char)( input[i] ^ iv[i] ); + } + + ets_aes_crypt(output, output); + memcpy( iv, output, 16 ); + + input += 16; + output += 16; + 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; + + esp_aes_acquire_hardware(); + esp_aes_setkey_hardware(ctx, ESP_AES_ENCRYPT); + + if ( mode == ESP_AES_DECRYPT ) { + while ( length-- ) { + if ( n == 0 ) { + ets_aes_crypt(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 ) { + ets_aes_crypt(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]; + + esp_aes_acquire_hardware(); + esp_aes_setkey_hardware(ctx, ESP_AES_ENCRYPT); + + while ( length-- ) { + memcpy( ov, iv, 16 ); + ets_aes_crypt(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; + + esp_aes_acquire_hardware(); + esp_aes_setkey_hardware(ctx, ESP_AES_ENCRYPT); + + while ( length-- ) { + if ( n == 0 ) { + ets_aes_crypt(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; +} diff --git a/components/esp32/hwcrypto/sha.c b/components/esp32/hwcrypto/sha.c new file mode 100644 index 000000000..06b00c54a --- /dev/null +++ b/components/esp32/hwcrypto/sha.c @@ -0,0 +1,267 @@ +/* + * 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 +#include +#include "hwcrypto/sha.h" +#include "rom/ets_sys.h" + + +static _lock_t sha_lock; + +void esp_sha_acquire_hardware( void ) +{ + /* newlib locks lazy initialize on ESP-IDF */ + _lock_acquire(&sha_lock); + ets_sha_enable(); +} + +void esp_sha_release_hardware( void ) +{ + /* Want to empty internal SHA buffers where possible, + need to check if this is sufficient for this. */ + SHA_CTX zero = { 0 }; + ets_sha_init(&zero); + ets_sha_disable(); + _lock_release(&sha_lock); +} + +/* Generic esp_shaX_update implementation */ +static void esp_sha_update( esp_sha_context *ctx, const unsigned char *input, size_t ilen, size_t block_size) +{ + /* Feed the SHA engine one block at a time */ + while(ilen > 0) { + size_t chunk_len = (ilen > block_size) ? block_size : ilen; + ets_sha_update(&ctx->context, ctx->context_type, input, chunk_len * 8); + input += chunk_len; + ilen -= chunk_len; + } +} + +void esp_sha1_init( esp_sha_context *ctx ) +{ + bzero( ctx, sizeof( esp_sha_context ) ); +} + +void esp_sha1_free( esp_sha_context *ctx ) +{ + if ( ctx == NULL ) { + return; + } + + bzero( ctx, sizeof( esp_sha_context ) ); +} + +void esp_sha1_clone( esp_sha_context *dst, const esp_sha_context *src ) +{ + *dst = *src; +} + +/* + * SHA-1 context setup + */ +void esp_sha1_start( esp_sha_context *ctx ) +{ + ctx->context_type = SHA1; + esp_sha_acquire_hardware(); + ets_sha_init(&ctx->context); +} + +/* + * SHA-1 process buffer + */ +void esp_sha1_update( esp_sha_context *ctx, const unsigned char *input, size_t ilen ) +{ + esp_sha_update(ctx, input, ilen, 64); +} + +/* + * SHA-1 final digest + */ +void esp_sha1_finish( esp_sha_context *ctx, unsigned char output[20] ) +{ + ets_sha_finish(&ctx->context, ctx->context_type, output); + esp_sha_release_hardware(); +} + +/* Full SHA-1 calculation */ +void esp_sha1( const unsigned char *input, size_t ilen, unsigned char output[20] ) +{ + esp_sha_context ctx; + + esp_sha1_init( &ctx ); + esp_sha1_start( &ctx ); + esp_sha1_update( &ctx, input, ilen ); + esp_sha1_finish( &ctx, output ); + esp_sha1_free( &ctx ); +} + +void esp_sha256_init( esp_sha_context *ctx ) +{ + bzero( ctx, sizeof( esp_sha_context ) ); +} + +void esp_sha256_free( esp_sha_context *ctx ) +{ + if ( ctx == NULL ) { + return; + } + + bzero( ctx, sizeof( esp_sha_context ) ); +} + +void esp_sha256_clone( esp_sha_context *dst, const esp_sha_context *src ) +{ + *dst = *src; +} + +/* + * SHA-256 context setup + */ +void esp_sha256_start( esp_sha_context *ctx, int is224 ) +{ + if ( is224 == 0 ) { + /* SHA-256 */ + ctx->context_type = SHA2_256; + esp_sha_acquire_hardware(); + ets_sha_init(&ctx->context); + } else { + /* SHA-224 is not supported! */ + ctx->context_type = SHA_INVALID; + } +} + +/* + * SHA-256 process buffer + */ +void esp_sha256_update( esp_sha_context *ctx, const unsigned char *input, size_t ilen ) +{ + if( ctx->context_type == SHA2_256 ) { + esp_sha_update(ctx, input, ilen, 64); + } + /* SHA-224 is a no-op */ +} + +/* + * SHA-256 final digest + */ +void esp_sha256_finish( esp_sha_context *ctx, unsigned char output[32] ) +{ + if ( ctx->context_type == SHA2_256 ) { + ets_sha_finish(&ctx->context, ctx->context_type, output); + esp_sha_release_hardware(); + } else { + /* No hardware SHA-224 support, but mbedTLS API doesn't allow failure. + For now, zero the output to make it clear it's not valid. */ + bzero( output, 28 ); + } +} + +/* + * Full SHA-256 calculation + */ +void esp_sha256( const unsigned char *input, size_t ilen, unsigned char output[32], int is224 ) +{ + esp_sha_context ctx; + + esp_sha256_init( &ctx ); + esp_sha256_start( &ctx, is224 ); + esp_sha256_update( &ctx, input, ilen ); + esp_sha256_finish( &ctx, output ); + esp_sha256_free( &ctx ); +} + + +///// +void esp_sha512_init( esp_sha_context *ctx ) +{ + memset( ctx, 0, sizeof( esp_sha_context ) ); +} + +void esp_sha512_free( esp_sha_context *ctx ) +{ + if ( ctx == NULL ) { + return; + } + + bzero( ctx, sizeof( esp_sha_context ) ); +} + +void esp_sha512_clone( esp_sha_context *dst, const esp_sha_context *src ) +{ + *dst = *src; +} + +/* + * SHA-512 context setup + */ +void esp_sha512_start( esp_sha_context *ctx, int is384 ) +{ + if ( is384 == 0 ) { + /* SHA-512 */ + ctx->context_type = SHA2_512; + } else { + /* SHA-384 */ + ctx->context_type = SHA2_384; + } + esp_sha_acquire_hardware(); + ets_sha_init(&ctx->context); +} + +/* + * SHA-512 process buffer + */ +void esp_sha512_update( esp_sha_context *ctx, const unsigned char *input, size_t ilen ) +{ + esp_sha_update(ctx, input, ilen, 128); +} + +/* + * SHA-512 final digest + */ +void esp_sha512_finish( esp_sha_context *ctx, unsigned char output[64] ) +{ + ets_sha_finish(&ctx->context, ctx->context_type, output); + esp_sha_release_hardware(); +} + +/* + * Full SHA-512 calculation + */ +void esp_sha512( const unsigned char *input, size_t ilen, unsigned char output[64], int is384 ) +{ + esp_sha_context ctx; + + esp_sha512_init( &ctx ); + esp_sha512_start( &ctx, is384 ); + esp_sha512_update( &ctx, input, ilen ); + esp_sha512_finish( &ctx, output ); + esp_sha512_free( &ctx ); +} + +//// + diff --git a/components/esp32/include/hwcrypto/aes.h b/components/esp32/include/hwcrypto/aes.h new file mode 100644 index 000000000..b6a632aff --- /dev/null +++ b/components/esp32/include/hwcrypto/aes.h @@ -0,0 +1,281 @@ +/** + * \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 "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. */ + +typedef struct { + enum AES_BITS aesbits; + uint8_t key[32]; +} key_context, KEY_CTX; + +/** + * \brief AES context structure + * + * \note buf is able to hold 32 extra bytes, which can be used: + * - for alignment purposes if VIA padlock is used, and/or + * - to simplify key expansion in the 256-bit case by + * generating an extra round key + */ +typedef struct { + int nr; /*!< number of rounds */ + uint32_t *rk; /*!< AES round keys */ + KEY_CTX enc; + KEY_CTX dec; +} esp_aes_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 AES key schedule (encryption) + * + * \param ctx AES context to be initialized + * \param key encryption key + * \param keybits must be 128, 192 or 256 + * + * \return 0 if successful, or ERR_AES_INVALID_KEY_LENGTH + */ +int esp_aes_setkey_enc( esp_aes_context *ctx, const unsigned char *key, unsigned int keybits ); + +/** + * \brief AES key schedule (decryption) + * + * \param ctx AES context to be initialized + * \param key decryption key + * \param keybits must be 128, 192 or 256 + * + * \return 0 if successful, or ERR_AES_INVALID_KEY_LENGTH + */ +int esp_aes_setkey_dec( 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 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 + */ +void esp_aes_encrypt( esp_aes_context *ctx, const unsigned char input[16], unsigned char output[16] ); + +/** + * \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 + */ +void esp_aes_decrypt( esp_aes_context *ctx, const unsigned char input[16], unsigned char output[16] ); + +#ifdef __cplusplus +} +#endif + +#endif /* aes.h */ diff --git a/components/esp32/include/hwcrypto/sha.h b/components/esp32/include/hwcrypto/sha.h new file mode 100644 index 000000000..a165c46c1 --- /dev/null +++ b/components/esp32/include/hwcrypto/sha.h @@ -0,0 +1,250 @@ +/* + * 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. + * + */ + +#ifndef _ESP_SHA_H_ +#define _ESP_SHA_H_ + +#include "rom/sha.h" + +#include "esp_types.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * \brief SHA-1 context structure + */ +typedef struct { + /* both types defined in rom/sha.h */ + SHA_CTX context; + enum SHA_TYPE context_type; +} esp_sha_context; + +/** + * \brief Lock access to SHA hardware unit + * + * SHA hardware unit can only be used by one + * consumer at a time. + * + * esp_sha_xxx API calls automatically manage locking & unlocking of + * hardware, this function is only needed if you want to call + * ets_sha_xxx functions directly. + */ +void esp_sha_acquire_hardware( void ); + +/** + * \brief Unlock access to SHA hardware unit + * + * esp_sha_xxx API calls automatically manage locking & unlocking of + * hardware, this function is only needed if you want to call + * ets_sha_xxx functions directly. + */ +void esp_sha_release_hardware( void ); + +/** + * \brief Initialize SHA-1 context + * + * \param ctx SHA-1 context to be initialized + */ +void esp_sha1_init( esp_sha_context *ctx ); + +/** + * \brief Clear SHA-1 context + * + * \param ctx SHA-1 context to be cleared + */ +void esp_sha1_free( esp_sha_context *ctx ); + +/** + * \brief Clone (the state of) a SHA-1 context + * + * \param dst The destination context + * \param src The context to be cloned + */ +void esp_sha1_clone( esp_sha_context *dst, const esp_sha_context *src ); + +/** + * \brief SHA-1 context setup + * + * \param ctx context to be initialized + */ +void esp_sha1_start( esp_sha_context *ctx ); + +/** + * \brief SHA-1 process buffer + * + * \param ctx SHA-1 context + * \param input buffer holding the data + * \param ilen length of the input data + */ +void esp_sha1_update( esp_sha_context *ctx, const unsigned char *input, size_t ilen ); + +/** + * \brief SHA-1 final digest + * + * \param ctx SHA-1 context + * \param output SHA-1 checksum result + */ +void esp_sha1_finish( esp_sha_context *ctx, unsigned char output[20] ); + +/** + * \brief Calculate SHA-1 of input buffer + * + * \param input buffer holding the data + * \param ilen length of the input data + * \param output SHA-1 checksum result + */ +void esp_sha1( const unsigned char *input, size_t ilen, unsigned char output[20] ); + +/** + * \brief SHA-256 context structure + */ + +/** + * \brief Initialize SHA-256 context + * + * \param ctx SHA-256 context to be initialized + */ +void esp_sha256_init( esp_sha_context *ctx ); + +/** + * \brief Clear SHA-256 context + * + * \param ctx SHA-256 context to be cleared + */ +void esp_sha256_free( esp_sha_context *ctx ); + +/** + * \brief Clone (the state of) a SHA-256 context + * + * \param dst The destination context + * \param src The context to be cloned + */ +void esp_sha256_clone( esp_sha_context *dst, const esp_sha_context *src ); + +/** + * \brief SHA-256 context setup + * + * \param ctx context to be initialized + * \param is224 0 = use SHA256, 1 = use SHA224 + */ +void esp_sha256_start( esp_sha_context *ctx, int is224 ); + +/** + * \brief SHA-256 process buffer + * + * \param ctx SHA-256 context + * \param input buffer holding the data + * \param ilen length of the input data + */ +void esp_sha256_update( esp_sha_context *ctx, const unsigned char *input, size_t ilen ); + +/** + * \brief SHA-256 final digest + * + * \param ctx SHA-256 context + * \param output SHA-224/256 checksum result + */ +void esp_sha256_finish( esp_sha_context *ctx, unsigned char output[32] ); + +/** + * \brief Calculate SHA-256 of input buffer + * + * \param input buffer holding the data + * \param ilen length of the input data + * \param output SHA-224/256 checksum result + * \param is224 0 = use SHA256, 1 = use SHA224 + */ +void esp_sha256( const unsigned char *input, size_t ilen, unsigned char output[32], int is224 ); + +// + +/** + * \brief SHA-512 context structure + */ + +/** + * \brief Initialize SHA-512 context + * + * \param ctx SHA-512 context to be initialized + */ +void esp_sha512_init( esp_sha_context *ctx ); + +/** + * \brief Clear SHA-512 context + * + * \param ctx SHA-512 context to be cleared + */ +void esp_sha512_free( esp_sha_context *ctx ); + +/** + * \brief Clone (the state of) a SHA-512 context + * + * \param dst The destination context + * \param src The context to be cloned + */ +void esp_sha512_clone( esp_sha_context *dst, const esp_sha_context *src ); + +/** + * \brief SHA-512 context setup + * + * \param ctx context to be initialized + * \param is384 0 = use SHA512, 1 = use SHA384 + */ +void esp_sha512_start( esp_sha_context *ctx, int is384 ); + +/** + * \brief SHA-512 process buffer + * + * \param ctx SHA-512 context + * \param input buffer holding the data + * \param ilen length of the input data + */ +void esp_sha512_update( esp_sha_context *ctx, const unsigned char *input, size_t ilen ); + +/** + * \brief SHA-512 final digest + * + * \param ctx SHA-512 context + * \param output SHA-384/512 checksum result + */ +void esp_sha512_finish( esp_sha_context *ctx, unsigned char output[64] ); + +/** + * \brief Calculate SHA-512 of input buffer. + * + * \param input buffer holding the data + * \param ilen length of the input data + * \param output SHA-384/512 checksum result + * \param is384 0 = use SHA512, 1 = use SHA384 + */ +void esp_sha512( const unsigned char *input, size_t ilen, unsigned char output[64], int is384 ); + +// + +#ifdef __cplusplus +} +#endif + +#endif + diff --git a/components/esp32/include/rom/aes.h b/components/esp32/include/rom/aes.h index d81d8f6f9..80eca973f 100644 --- a/components/esp32/include/rom/aes.h +++ b/components/esp32/include/rom/aes.h @@ -1,3 +1,10 @@ +/* + ROM functions for hardware AES support. + + It is not recommended to use these functions directly, + use the wrapper functions in hwcrypto/aes.h instead. + + */ // Copyright 2015-2016 Espressif Systems (Shanghai) PTE LTD // // Licensed under the Apache License, Version 2.0 (the "License"); diff --git a/components/esp32/include/rom/bigint.h b/components/esp32/include/rom/bigint.h index ab4246c6d..97ad72202 100644 --- a/components/esp32/include/rom/bigint.h +++ b/components/esp32/include/rom/bigint.h @@ -1,3 +1,10 @@ +/* + ROM functions for hardware bigint support. + + It is not recommended to use these functions directly, + use the wrapper functions in hwcrypto/mpi.h instead. + + */ // Copyright 2015-2016 Espressif Systems (Shanghai) PTE LTD // // Licensed under the Apache License, Version 2.0 (the "License"); diff --git a/components/esp32/include/rom/sha.h b/components/esp32/include/rom/sha.h index a5536bd3b..8082a394c 100644 --- a/components/esp32/include/rom/sha.h +++ b/components/esp32/include/rom/sha.h @@ -1,3 +1,10 @@ +/* + ROM functions for hardware SHA support. + + It is not recommended to use these functions directly, + use the wrapper functions in hwcrypto/sha.h instead. + + */ // Copyright 2015-2016 Espressif Systems (Shanghai) PTE LTD // // Licensed under the Apache License, Version 2.0 (the "License"); @@ -30,7 +37,8 @@ enum SHA_TYPE { SHA1 = 0, SHA2_256, SHA2_384, - SHA2_512 + SHA2_512, + SHA_INVALID = -1, }; void ets_sha_init(SHA_CTX *ctx); diff --git a/components/expat/Makefile b/components/expat/component.mk similarity index 80% rename from components/expat/Makefile rename to components/expat/component.mk index 96b74ce25..69595d7b2 100644 --- a/components/expat/Makefile +++ b/components/expat/component.mk @@ -10,6 +10,6 @@ COMPONENT_ADD_INCLUDEDIRS := port/include include/expat COMPONENT_SRCDIRS := library port -EXTRA_CFLAGS := -Wno-error=address -Waddress -DHAVE_EXPAT_CONFIG_H +CFLAGS += -Wno-error=address -Waddress -DHAVE_EXPAT_CONFIG_H -include $(IDF_PATH)/make/component.mk +include $(IDF_PATH)/make/component_common.mk diff --git a/components/json/Makefile b/components/json/component.mk similarity index 90% rename from components/json/Makefile rename to components/json/component.mk index ebddafdd1..311a902f9 100644 --- a/components/json/Makefile +++ b/components/json/component.mk @@ -10,4 +10,4 @@ COMPONENT_ADD_INCLUDEDIRS := include port/include COMPONENT_SRCDIRS := library port -include $(IDF_PATH)/make/component.mk +include $(IDF_PATH)/make/component_common.mk diff --git a/components/lwip/component.mk b/components/lwip/component.mk index 4fb0be5b6..3e6b26c0f 100644 --- a/components/lwip/component.mk +++ b/components/lwip/component.mk @@ -2,10 +2,10 @@ # Component Makefile # -COMPONENT_ADD_INCLUDEDIRS := include/lwip include/lwip/port +COMPONENT_ADD_INCLUDEDIRS := include/lwip include/lwip/port include/lwip/posix COMPONENT_SRCDIRS := api apps/sntp apps core/ipv4 core/ipv6 core netif port/freertos port/netif port -EXTRA_CFLAGS := -Wno-error=address -Waddress +CFLAGS += -Wno-error=address -Waddress include $(IDF_PATH)/make/component_common.mk diff --git a/components/mbedtls/Makefile b/components/mbedtls/Makefile deleted file mode 100755 index e44ce2b53..000000000 --- a/components/mbedtls/Makefile +++ /dev/null @@ -1,8 +0,0 @@ -# -# Component Makefile - -COMPONENT_SRCDIRS := library port - -EXTRA_CFLAGS += -DMBEDTLS_CONFIG_FILE='"mbedtls/esp_config.h"' - -include $(IDF_PATH)/make/component.mk diff --git a/components/mbedtls/Makefile.projbuild b/components/mbedtls/Makefile.projbuild new file mode 100644 index 000000000..51300efd1 --- /dev/null +++ b/components/mbedtls/Makefile.projbuild @@ -0,0 +1,4 @@ +# Anyone compiling mbedTLS code needs the name of the +# alternative config file +CFLAGS += -DMBEDTLS_CONFIG_FILE='"mbedtls/esp_config.h"' + diff --git a/components/mbedtls/component.mk b/components/mbedtls/component.mk new file mode 100644 index 000000000..98838d4d7 --- /dev/null +++ b/components/mbedtls/component.mk @@ -0,0 +1,9 @@ +# +# Component Makefile +# + +COMPONENT_ADD_INCLUDEDIRS := port/include include + +COMPONENT_SRCDIRS := library port + +include $(IDF_PATH)/make/component_common.mk diff --git a/components/mbedtls/include/mbedtls/bignum.h b/components/mbedtls/include/mbedtls/bignum.h index aa51556a5..46f250762 100644 --- a/components/mbedtls/include/mbedtls/bignum.h +++ b/components/mbedtls/include/mbedtls/bignum.h @@ -100,6 +100,8 @@ #define MBEDTLS_LN_2_DIV_LN_10_SCALE100 332 #define MBEDTLS_MPI_RW_BUFFER_SIZE ( ((MBEDTLS_MPI_MAX_BITS_SCALE100 + MBEDTLS_LN_2_DIV_LN_10_SCALE100 - 1) / MBEDTLS_LN_2_DIV_LN_10_SCALE100) + 10 + 6 ) +#if !defined(MBEDTLS_BIGNUM_ALT) + /* * Define the base integer type, architecture-wise. * @@ -702,6 +704,9 @@ int mbedtls_mpi_is_prime( const mbedtls_mpi *X, int mbedtls_mpi_gen_prime( mbedtls_mpi *X, size_t nbits, int dh_flag, int (*f_rng)(void *, unsigned char *, size_t), void *p_rng ); +#else /* MBEDTLS_BIGNUM_ALT */ +#include "bignum_alt.h" +#endif /* MBEDTLS_BIGNUM_ALT */ /** * \brief Checkup routine diff --git a/components/mbedtls/include/mbedtls/sha512.h b/components/mbedtls/include/mbedtls/sha512.h index 627694f42..12f4fab4f 100644 --- a/components/mbedtls/include/mbedtls/sha512.h +++ b/components/mbedtls/include/mbedtls/sha512.h @@ -101,6 +101,9 @@ void mbedtls_sha512_update( mbedtls_sha512_context *ctx, const unsigned char *in */ void mbedtls_sha512_finish( mbedtls_sha512_context *ctx, unsigned char output[64] ); +/* Internal use */ +void mbedtls_sha512_process( mbedtls_sha512_context *ctx, const unsigned char data[128] ); + #ifdef __cplusplus } #endif @@ -131,9 +134,6 @@ void mbedtls_sha512( const unsigned char *input, size_t ilen, */ int mbedtls_sha512_self_test( int verbose ); -/* Internal use */ -void mbedtls_sha512_process( mbedtls_sha512_context *ctx, const unsigned char data[128] ); - #ifdef __cplusplus } #endif diff --git a/components/mbedtls/library/bignum.c b/components/mbedtls/library/bignum.c index 4c99e04d6..e739bc1d3 100644 --- a/components/mbedtls/library/bignum.c +++ b/components/mbedtls/library/bignum.c @@ -58,6 +58,8 @@ #define mbedtls_free free #endif +#if !defined(MBEDTLS_BIGNUM_ALT) + /* Implementation that should never be optimized out by the compiler */ static void mbedtls_mpi_zeroize( mbedtls_mpi_uint *v, size_t n ) { volatile mbedtls_mpi_uint *p = v; while( n-- ) *p++ = 0; @@ -1162,6 +1164,7 @@ void mpi_mul_hlp( size_t i, mbedtls_mpi_uint *s, mbedtls_mpi_uint *d, mbedtls_mp while( c != 0 ); } +#if !defined(MBEDTLS_MPI_MUL_MPI_ALT) /* * Baseline multiplication: X = A * B (HAC 14.12) */ @@ -1198,6 +1201,7 @@ cleanup: return( ret ); } +#endif /* * Baseline multiplication: X = A * b @@ -1596,6 +1600,7 @@ static int mpi_montred( mbedtls_mpi *A, const mbedtls_mpi *N, mbedtls_mpi_uint m return( mpi_montmul( A, &U, N, mm, T ) ); } +#if !defined(MBEDTLS_MPI_EXP_MOD_ALT) /* * Sliding-window exponentiation: X = A^E mod N (HAC 14.85) */ @@ -1803,6 +1808,7 @@ cleanup: return( ret ); } +#endif /* * Greatest common divisor: G = gcd(A, B) (HAC 14.54) @@ -2264,6 +2270,7 @@ cleanup: } #endif /* MBEDTLS_GENPRIME */ +#endif /* MBEDTLS_BIGNUM_ALT */ #if defined(MBEDTLS_SELF_TEST) diff --git a/components/mbedtls/port/esp_bignum.c b/components/mbedtls/port/esp_bignum.c new file mode 100644 index 000000000..59bdc8726 --- /dev/null +++ b/components/mbedtls/port/esp_bignum.c @@ -0,0 +1,536 @@ +/** + * \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 +#include +#include +#include "mbedtls/bignum.h" +#include "mbedtls/bn_mul.h" +#include "rom/bigint.h" + +#if defined(MBEDTLS_MPI_MUL_MPI_ALT) || defined(MBEDTLS_MPI_EXP_MOD_ALT) + +/* Constants from mbedTLS bignum.c */ +#define ciL (sizeof(mbedtls_mpi_uint)) /* chars in limb */ +#define biL (ciL << 3) /* bits in limb */ + +static _lock_t mpi_lock; + +/* At the moment these hardware locking functions aren't exposed publically + for MPI. If you want to use the ROM bigint functions and co-exist with mbedTLS, + please raise a feature request. +*/ +static void esp_mpi_acquire_hardware( void ) +{ + /* newlib locks lazy initialize on ESP-IDF */ + _lock_acquire(&mpi_lock); + ets_bigint_enable(); +} + +static void esp_mpi_release_hardware( void ) +{ + ets_bigint_disable(); + _lock_release(&mpi_lock); +} + +/* + * Helper for mbedtls_mpi multiplication + * copied/trimmed from mbedtls bignum.c + */ +static void mpi_mul_hlp( size_t i, mbedtls_mpi_uint *s, mbedtls_mpi_uint *d, mbedtls_mpi_uint b ) +{ + mbedtls_mpi_uint c = 0, t = 0; + + for( ; i >= 16; i -= 16 ) + { + MULADDC_INIT + MULADDC_CORE MULADDC_CORE + MULADDC_CORE MULADDC_CORE + MULADDC_CORE MULADDC_CORE + MULADDC_CORE MULADDC_CORE + + MULADDC_CORE MULADDC_CORE + MULADDC_CORE MULADDC_CORE + MULADDC_CORE MULADDC_CORE + MULADDC_CORE MULADDC_CORE + MULADDC_STOP + } + + for( ; i >= 8; i -= 8 ) + { + MULADDC_INIT + MULADDC_CORE MULADDC_CORE + MULADDC_CORE MULADDC_CORE + + MULADDC_CORE MULADDC_CORE + MULADDC_CORE MULADDC_CORE + MULADDC_STOP + } + + + for( ; i > 0; i-- ) + { + MULADDC_INIT + MULADDC_CORE + MULADDC_STOP + } + + t++; + + do { + *d += c; c = ( *d < c ); d++; + } + while( c != 0 ); +} + + +/* + * Helper for mbedtls_mpi subtraction + * Copied/adapter from mbedTLS bignum.c + */ +static void mpi_sub_hlp( size_t n, mbedtls_mpi_uint *s, mbedtls_mpi_uint *d ) +{ + size_t i; + mbedtls_mpi_uint c, z; + + for( i = c = 0; i < n; i++, s++, d++ ) + { + z = ( *d < c ); *d -= c; + c = ( *d < *s ) + z; *d -= *s; + } + + while( c != 0 ) + { + z = ( *d < c ); *d -= c; + c = z; i++; d++; + } +} + + +/* The following 3 Montgomery arithmetic function are + copied from mbedTLS bigint.c verbatim as they are static. + + TODO: find a way to support making the versions in mbedtls + non-static. +*/ + +/* + * Fast Montgomery initialization (thanks to Tom St Denis) + */ +static void mpi_montg_init( mbedtls_mpi_uint *mm, const mbedtls_mpi *N ) +{ + mbedtls_mpi_uint x, m0 = N->p[0]; + unsigned int i; + + x = m0; + x += ( ( m0 + 2 ) & 4 ) << 1; + + for( i = biL; i >= 8; i /= 2 ) + x *= ( 2 - ( m0 * x ) ); + + *mm = ~x + 1; +} + +/* + * Montgomery multiplication: A = A * B * R^-1 mod N (HAC 14.36) + */ +static int mpi_montmul( mbedtls_mpi *A, const mbedtls_mpi *B, const mbedtls_mpi *N, mbedtls_mpi_uint mm, + const mbedtls_mpi *T ) +{ + size_t i, n, m; + mbedtls_mpi_uint u0, u1, *d; + + if( T->n < N->n + 1 || T->p == NULL ) + return( MBEDTLS_ERR_MPI_BAD_INPUT_DATA ); + + memset( T->p, 0, T->n * ciL ); + + d = T->p; + n = N->n; + m = ( B->n < n ) ? B->n : n; + + for( i = 0; i < n; i++ ) + { + /* + * T = (T + u0*B + u1*N) / 2^biL + */ + u0 = A->p[i]; + u1 = ( d[0] + u0 * B->p[0] ) * mm; + + mpi_mul_hlp( m, B->p, d, u0 ); + mpi_mul_hlp( n, N->p, d, u1 ); + + *d++ = u0; d[n + 1] = 0; + } + + memcpy( A->p, d, ( n + 1 ) * ciL ); + + if( mbedtls_mpi_cmp_abs( A, N ) >= 0 ) + mpi_sub_hlp( n, N->p, A->p ); + else + /* prevent timing attacks */ + mpi_sub_hlp( n, A->p, T->p ); + + return( 0 ); +} + +/* + * Montgomery reduction: A = A * R^-1 mod N + */ +static int mpi_montred( mbedtls_mpi *A, const mbedtls_mpi *N, mbedtls_mpi_uint mm, const mbedtls_mpi *T ) +{ + mbedtls_mpi_uint z = 1; + mbedtls_mpi U; + + U.n = U.s = (int) z; + U.p = &z; + + return( mpi_montmul( A, &U, N, mm, T ) ); +} + + +/* Allocate parameters used by hardware MPI multiply, + and copy mbedtls_mpi structures into them */ +static int mul_pram_alloc(const mbedtls_mpi *A, const mbedtls_mpi *B, char **pA, char **pB, char **pX, size_t *bites) +{ + char *sa, *sb, *sx; +// int algn; + int words, bytes; + int abytes, bbytes; + + if (A->n > B->n) + words = A->n; + else + words = B->n; + + bytes = (words / 16 + ((words % 16) ? 1 : 0 )) * 16 * 4 * 2; + + abytes = A->n * 4; + bbytes = B->n * 4; + + sa = malloc(bytes); + if (!sa) { + return -1; + } + + sb = malloc(bytes); + if (!sb) { + free(sa); + return -1; + } + + sx = malloc(bytes); + if (!sx) { + free(sa); + free(sb); + return -1; + } + + memcpy(sa, A->p, abytes); + memset(sa + abytes, 0, bytes - abytes); + + memcpy(sb, B->p, bbytes); + memset(sb + bbytes, 0, bytes - bbytes); + + *pA = sa; + *pB = sb; + + *pX = sx; + + *bites = bytes * 4; + + return 0; +} + +#if defined(MBEDTLS_MPI_MUL_MPI_ALT) + +int mbedtls_mpi_mul_mpi( mbedtls_mpi *X, const mbedtls_mpi *A, const mbedtls_mpi *B ) +{ + int ret = -1; + size_t i, j; + char *s1 = NULL, *s2 = NULL, *dest = NULL; + size_t bites; + + mbedtls_mpi TA, TB; + + mbedtls_mpi_init( &TA ); mbedtls_mpi_init( &TB ); + + if( X == A ) { MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &TA, A ) ); A = &TA; } + if( X == B ) { MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &TB, B ) ); B = &TB; } + + for( i = A->n; i > 0; i-- ) + if( A->p[i - 1] != 0 ) + break; + + for( j = B->n; j > 0; j-- ) + if( B->p[j - 1] != 0 ) + break; + + MBEDTLS_MPI_CHK( mbedtls_mpi_grow( X, i + j ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_lset( X, 0 ) ); + + if (mul_pram_alloc(A, B, &s1, &s2, &dest, &bites)) { + goto cleanup; + } + + esp_mpi_acquire_hardware(); + if (ets_bigint_mult_prepare((uint32_t *)s1, (uint32_t *)s2, bites)){ + ets_bigint_wait_finish(); + if (ets_bigint_mult_getz((uint32_t *)dest, bites) == true) { + memcpy(X->p, dest, (i + j) * 4); + ret = 0; + } else { + printf("ets_bigint_mult_getz failed\n"); + } + } else{ + printf("Baseline multiplication failed\n"); + } + esp_mpi_release_hardware(); + + X->s = A->s * B->s; + + free(s1); + free(s2); + free(dest); + +cleanup: + + mbedtls_mpi_free( &TB ); mbedtls_mpi_free( &TA ); + + return( ret ); +} + +#endif /* MBEDTLS_MPI_MUL_MPI_ALT */ + +#if defined(MBEDTLS_MPI_EXP_MOD_ALT) +/* + * Sliding-window exponentiation: X = A^E mod N (HAC 14.85) + */ +int mbedtls_mpi_exp_mod( mbedtls_mpi* X, const mbedtls_mpi* A, const mbedtls_mpi* E, const mbedtls_mpi* N, mbedtls_mpi* _RR ) +{ + int ret; + size_t wbits, wsize, one = 1; + size_t i, j, nblimbs; + size_t bufsize, nbits; + mbedtls_mpi_uint ei, mm, state; + mbedtls_mpi RR, T, W[ 2 << MBEDTLS_MPI_WINDOW_SIZE ], Apos; + int neg; + + if( mbedtls_mpi_cmp_int( N, 0 ) < 0 || ( N->p[0] & 1 ) == 0 ) + return( MBEDTLS_ERR_MPI_BAD_INPUT_DATA ); + + if( mbedtls_mpi_cmp_int( E, 0 ) < 0 ) + return( MBEDTLS_ERR_MPI_BAD_INPUT_DATA ); + + /* + * Init temps and window size + */ + mpi_montg_init( &mm, N ); + mbedtls_mpi_init( &RR ); mbedtls_mpi_init( &T ); + mbedtls_mpi_init( &Apos ); + memset( W, 0, sizeof( W ) ); + + i = mbedtls_mpi_bitlen( E ); + + wsize = ( i > 671 ) ? 6 : ( i > 239 ) ? 5 : + ( i > 79 ) ? 4 : ( i > 23 ) ? 3 : 1; + + if( wsize > MBEDTLS_MPI_WINDOW_SIZE ) + wsize = MBEDTLS_MPI_WINDOW_SIZE; + + j = N->n + 1; + MBEDTLS_MPI_CHK( mbedtls_mpi_grow( X, j ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_grow( &W[1], j ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_grow( &T, j * 2 ) ); + + /* + * Compensate for negative A (and correct at the end) + */ + neg = ( A->s == -1 ); + if( neg ) + { + MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &Apos, A ) ); + Apos.s = 1; + A = &Apos; + } + + /* + * If 1st call, pre-compute R^2 mod N + */ + if( _RR == NULL || _RR->p == NULL ) + { + MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &RR, 1 ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_shift_l( &RR, N->n * 2 * biL ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_mod_mpi( &RR, &RR, N ) ); + + if( _RR != NULL ) + memcpy( _RR, &RR, sizeof( mbedtls_mpi) ); + } + else + memcpy( &RR, _RR, sizeof( mbedtls_mpi) ); + + /* + * W[1] = A * R^2 * R^-1 mod N = A * R mod N + */ + if( mbedtls_mpi_cmp_mpi( A, N ) >= 0 ) + MBEDTLS_MPI_CHK( mbedtls_mpi_mod_mpi( &W[1], A, N ) ); + else + MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &W[1], A ) ); + + mpi_montmul( &W[1], &RR, N, mm, &T ); + + /* + * X = R^2 * R^-1 mod N = R mod N + */ + MBEDTLS_MPI_CHK( mbedtls_mpi_copy( X, &RR ) ); + mpi_montred( X, N, mm, &T ); + + if( wsize > 1 ) + { + /* + * W[1 << (wsize - 1)] = W[1] ^ (wsize - 1) + */ + j = one << ( wsize - 1 ); + + MBEDTLS_MPI_CHK( mbedtls_mpi_grow( &W[j], N->n + 1 ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &W[j], &W[1] ) ); + + for( i = 0; i < wsize - 1; i++ ) + mpi_montmul( &W[j], &W[j], N, mm, &T ); + + /* + * W[i] = W[i - 1] * W[1] + */ + for( i = j + 1; i < ( one << wsize ); i++ ) + { + MBEDTLS_MPI_CHK( mbedtls_mpi_grow( &W[i], N->n + 1 ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &W[i], &W[i - 1] ) ); + + mpi_montmul( &W[i], &W[1], N, mm, &T ); + } + } + + nblimbs = E->n; + bufsize = 0; + nbits = 0; + wbits = 0; + state = 0; + + while( 1 ) + { + if( bufsize == 0 ) + { + if( nblimbs == 0 ) + break; + + nblimbs--; + + bufsize = sizeof( mbedtls_mpi_uint ) << 3; + } + + bufsize--; + + ei = (E->p[nblimbs] >> bufsize) & 1; + + /* + * skip leading 0s + */ + if( ei == 0 && state == 0 ) + continue; + + if( ei == 0 && state == 1 ) + { + /* + * out of window, square X + */ + mpi_montmul( X, X, N, mm, &T ); + continue; + } + + /* + * add ei to current window + */ + state = 2; + + nbits++; + wbits |= ( ei << ( wsize - nbits ) ); + + if( nbits == wsize ) + { + /* + * X = X^wsize R^-1 mod N + */ + for( i = 0; i < wsize; i++ ) + mpi_montmul( X, X, N, mm, &T ); + + /* + * X = X * W[wbits] R^-1 mod N + */ + mpi_montmul( X, &W[wbits], N, mm, &T ); + + state--; + nbits = 0; + wbits = 0; + } + } + + /* + * process the remaining bits + */ + for( i = 0; i < nbits; i++ ) + { + mpi_montmul( X, X, N, mm, &T ); + + wbits <<= 1; + + if( ( wbits & ( one << wsize ) ) != 0 ) + mpi_montmul( X, &W[1], N, mm, &T ); + } + + /* + * X = A^E * R * R^-1 mod N = A^E mod N + */ + mpi_montred( X, N, mm, &T ); + + if( neg ) + { + X->s = -1; + MBEDTLS_MPI_CHK( mbedtls_mpi_add_mpi( X, N, X ) ); + } + +cleanup: + + for( i = ( one << ( wsize - 1 ) ); i < ( one << wsize ); i++ ) + mbedtls_mpi_free( &W[i] ); + + mbedtls_mpi_free( &W[1] ); mbedtls_mpi_free( &T ); mbedtls_mpi_free( &Apos ); + + if( _RR == NULL || _RR->p == NULL ) + mbedtls_mpi_free( &RR ); + + return( ret ); +} + +#endif /* MBEDTLS_MPI_EXP_MOD_ALT */ + +#endif /* MBEDTLS_MPI_MUL_MPI_ALT || MBEDTLS_MPI_EXP_MOD_ALT */ + diff --git a/components/mbedtls/port/esp_hardware.c b/components/mbedtls/port/esp_hardware.c new file mode 100644 index 000000000..915766249 --- /dev/null +++ b/components/mbedtls/port/esp_hardware.c @@ -0,0 +1,23 @@ +#if !defined(MBEDTLS_CONFIG_FILE) +#include "mbedtls/config.h" +#else +#include MBEDTLS_CONFIG_FILE +#endif + +#include +#include +#include + +#if defined(MBEDTLS_ENTROPY_HARDWARE_ALT) + +extern int os_get_random(unsigned char *buf, size_t len); +int mbedtls_hardware_poll( void *data, + unsigned char *output, size_t len, size_t *olen ) +{ + os_get_random(output, len); + *olen = len; + + return 0; +} +#endif + diff --git a/components/mbedtls/port/include/aes_alt.h b/components/mbedtls/port/include/aes_alt.h new file mode 100644 index 000000000..7161b282c --- /dev/null +++ b/components/mbedtls/port/include/aes_alt.h @@ -0,0 +1,59 @@ +/** + * \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 "hwcrypto/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_enc +#define mbedtls_aes_setkey_dec esp_aes_setkey_dec +#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 +#define mbedtls_aes_encrypt esp_aes_encrypt +#define mbedtls_aes_decrypt esp_aes_decrypt +#endif /* MBEDTLS_AES_ALT */ + +#ifdef __cplusplus +} +#endif + +#endif /* aes.h */ diff --git a/components/mbedtls/include/mbedtls/esp_config.h b/components/mbedtls/port/include/mbedtls/esp_config.h similarity index 98% rename from components/mbedtls/include/mbedtls/esp_config.h rename to components/mbedtls/port/include/mbedtls/esp_config.h index 50c3ee2af..68be319c3 100644 --- a/components/mbedtls/include/mbedtls/esp_config.h +++ b/components/mbedtls/port/include/mbedtls/esp_config.h @@ -1,7 +1,6 @@ /** - * \file config.h * - * \brief Configuration options (set of defines) + * \brief Default mbedTLS configuration options for esp-idf * * This set of compile-time options may be used to enable * or disable features selectively, and reduce the global @@ -225,7 +224,6 @@ * Uncomment a macro to enable alternate implementation of the corresponding * module. */ -//#define MBEDTLS_AES_ALT //#define MBEDTLS_ARC4_ALT //#define MBEDTLS_BLOWFISH_ALT //#define MBEDTLS_CAMELLIA_ALT @@ -235,10 +233,27 @@ //#define MBEDTLS_MD4_ALT //#define MBEDTLS_MD5_ALT //#define MBEDTLS_RIPEMD160_ALT + +/* The following units have ESP32 hardware support, + uncommenting each _ALT macro will use the + hardware-accelerated implementation. */ +#define MBEDTLS_AES_ALT + +/* Currently hardware SHA does not work with TLS handshake, + due to concurrency issue. Internal TW#7111. */ //#define MBEDTLS_SHA1_ALT //#define MBEDTLS_SHA256_ALT //#define MBEDTLS_SHA512_ALT +/* The following MPI (bignum) functions have ESP32 hardware support, + Uncommenting these macros will use the hardware-accelerated + implementations. + + Disabled as number of limbs limited by bug. Internal TW#7112. +*/ +//#define MBEDTLS_MPI_EXP_MOD_ALT +//#define MBEDTLS_MPI_MUL_MPI_ALT + /** * \def MBEDTLS_MD2_PROCESS_ALT * @@ -297,7 +312,7 @@ * * Uncomment this macro to store the AES tables in ROM. */ -//#define MBEDTLS_AES_ROM_TABLES +#define MBEDTLS_AES_ROM_TABLES /** * \def MBEDTLS_CAMELLIA_SMALL_MEMORY @@ -2465,7 +2480,8 @@ //#define MBEDTLS_SSL_CACHE_DEFAULT_MAX_ENTRIES 50 /**< Maximum entries in cache */ /* SSL options */ -//#define MBEDTLS_SSL_MAX_CONTENT_LEN 16384 /**< Maxium fragment length in bytes, determines the size of each of the two internal I/O buffers */ + +#define MBEDTLS_SSL_MAX_CONTENT_LEN 5120 /**< Maxium fragment length in bytes, determines the size of each of the two internal I/O buffers */ //#define MBEDTLS_SSL_DEFAULT_TICKET_LIFETIME 86400 /**< Lifetime of session tickets (if enabled) */ //#define MBEDTLS_PSK_MAX_LEN 32 /**< Max size of TLS pre-shared keys, in bytes (default 256 bits) */ //#define MBEDTLS_SSL_COOKIE_TIMEOUT 60 /**< Default expiration delay of DTLS cookies, in seconds if HAVE_TIME, or in number of cookies issued */ @@ -2506,6 +2522,6 @@ #include MBEDTLS_USER_CONFIG_FILE #endif -#include "check_config.h" +#include "mbedtls/check_config.h" #endif /* MBEDTLS_CONFIG_H */ diff --git a/components/mbedtls/port/include/sha1_alt.h b/components/mbedtls/port/include/sha1_alt.h new file mode 100644 index 000000000..60297b9fb --- /dev/null +++ b/components/mbedtls/port/include/sha1_alt.h @@ -0,0 +1,33 @@ +/* + * copyright (c) 2010 - 2012 Espressif System + * + */ +#ifndef _SHA1_ALT_H_ +#define _SHA1_ALT_H_ + +#ifdef __cplusplus +extern "C" { +#endif + +#if defined(MBEDTLS_SHA1_ALT) + +#include "hwcrypto/sha.h" + +typedef esp_sha_context mbedtls_sha1_context; + +#define mbedtls_sha1_init esp_sha1_init +#define mbedtls_sha1_starts esp_sha1_start +#define mbedtls_sha1_clone esp_sha1_clone +#define mbedtls_sha1_update esp_sha1_update +#define mbedtls_sha1_finish esp_sha1_finish +#define mbedtls_sha1_free esp_sha1_free +#define mbedtls_sha1_process(...) + +#endif + +#ifdef __cplusplus +} +#endif + +#endif + diff --git a/components/mbedtls/port/include/sha256_alt.h b/components/mbedtls/port/include/sha256_alt.h new file mode 100644 index 000000000..6d9986b3a --- /dev/null +++ b/components/mbedtls/port/include/sha256_alt.h @@ -0,0 +1,33 @@ +/* + * copyright (c) 2010 - 2012 Espressif System + * + */ + +#ifndef _SHA256_ALT_H_ +#define _SHA256_ALT_H_ + +#ifdef __cplusplus +extern "C" { +#endif + +#if defined(MBEDTLS_SHA256_ALT) + +#include "hwcrypto/sha.h" + +typedef esp_sha_context mbedtls_sha256_context; + +#define mbedtls_sha256_init esp_sha256_init +#define mbedtls_sha256_clone esp_sha256_clone +#define mbedtls_sha256_starts esp_sha256_start +#define mbedtls_sha256_update esp_sha256_update +#define mbedtls_sha256_finish esp_sha256_finish +#define mbedtls_sha256_free esp_sha256_free +#define mbedtls_sha256_process(...) + +#endif + +#ifdef __cplusplus +} +#endif + +#endif /* sha256.h */ diff --git a/components/mbedtls/port/include/sha512_alt.h b/components/mbedtls/port/include/sha512_alt.h new file mode 100644 index 000000000..241f2be3b --- /dev/null +++ b/components/mbedtls/port/include/sha512_alt.h @@ -0,0 +1,33 @@ +/* + * copyright (c) 2010 - 2012 Espressif System + * + * esf Link List Descriptor + */ + +#ifndef _SHA512_ALT_H_ +#define _SHA512_ALT_H_ + +#ifdef __cplusplus +extern "C" { +#endif + +#if defined(MBEDTLS_SHA512_ALT) +#include "hwcrypto/sha.h" + +typedef esp_sha_context mbedtls_sha512_context; + +#define mbedtls_sha512_init esp_sha512_init +#define mbedtls_sha512_clone esp_sha512_clone +#define mbedtls_sha512_starts esp_sha512_start +#define mbedtls_sha512_update esp_sha512_update +#define mbedtls_sha512_finish esp_sha512_finish +#define mbedtls_sha512_free esp_sha512_free +#define mbedtls_sha512_process(...) + +#endif + +#ifdef __cplusplus +} +#endif + +#endif /* sha512.h */ diff --git a/components/mbedtls/port/net.c b/components/mbedtls/port/net.c new file mode 100644 index 000000000..482a11f97 --- /dev/null +++ b/components/mbedtls/port/net.c @@ -0,0 +1,452 @@ +/* + * 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) + +#include "mbedtls/net.h" + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +/* + * Prepare for using the sockets interface + */ +static int net_prepare( void ) +{ + return ( 0 ); +} + +static int mbedtls_net_errno(int fd) +{ + int sock_errno = 0; + u32_t optlen = sizeof(sock_errno); + + getsockopt(fd, SOL_SOCKET, SO_ERROR, &sock_errno, &optlen); + + return sock_errno; +} + +/* + * 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 ) { + ctx->fd = (int) socket( cur->ai_family, cur->ai_socktype, + cur->ai_protocol ); + if ( ctx->fd < 0 ) { + ret = MBEDTLS_ERR_NET_SOCKET_FAILED; + continue; + } + + if ( connect( ctx->fd, cur->ai_addr, cur->ai_addrlen ) == 0 ) { + ret = 0; + break; + } + + close( ctx->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; + + 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 ) { + ctx->fd = (int) socket( cur->ai_family, cur->ai_socktype, + cur->ai_protocol ); + if ( ctx->fd < 0 ) { + ret = MBEDTLS_ERR_NET_SOCKET_FAILED; + continue; + } + + /*SO_REUSEADDR option dafault is disable in source code(lwip)*/ +#if SO_REUSE + n = 1; + if ( setsockopt( ctx->fd, SOL_SOCKET, SO_REUSEADDR, + (const char *) &n, sizeof( n ) ) != 0 ) { + close( ctx->fd ); + ret = MBEDTLS_ERR_NET_SOCKET_FAILED; + continue; + } +#endif + /*bind interface dafault don't process the addr is 0xffffffff for TCP Protocol*/ + struct sockaddr_in *serv_addr = NULL; + serv_addr = (struct sockaddr_in *)cur->ai_addr; + serv_addr->sin_addr.s_addr = htonl(INADDR_ANY); /* Any incoming interface */ + if ( bind( ctx->fd, (struct sockaddr *)serv_addr, cur->ai_addrlen ) != 0 ) { + close( ctx->fd ); + ret = MBEDTLS_ERR_NET_BIND_FAILED; + continue; + } + + /* Listen only makes sense for TCP */ + if ( proto == MBEDTLS_NET_PROTO_TCP ) { + if ( listen( ctx->fd, MBEDTLS_NET_LISTEN_BACKLOG ) != 0 ) { + close( ctx->fd ); + ret = MBEDTLS_ERR_NET_LISTEN_FAILED; + continue; + } + } + + /* I we ever get there, it's a success */ + 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 ) +{ + /* + * Never return 'WOULD BLOCK' on a non-blocking socket + */ + if ( ( fcntl( ctx->fd, F_GETFL, 0) & O_NONBLOCK ) != O_NONBLOCK ) { + return ( 0 ); + } + + int error = mbedtls_net_errno(ctx->fd); + + switch ( 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; + int error = 0; + + 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 ); + } + + error = mbedtls_net_errno(fd); + if ( error == EPIPE || error == ECONNRESET ) { + return ( MBEDTLS_ERR_NET_CONN_RESET ); + } + + if ( error == 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; + + int error = 0; + + 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 ); + } + + error = mbedtls_net_errno(fd); + if ( error == EPIPE || error == ECONNRESET ) { + return ( MBEDTLS_ERR_NET_CONN_RESET ); + } + + if ( error == 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 */ diff --git a/docs/build_system.rst b/docs/build_system.rst index 24381019b..43055a478 100644 --- a/docs/build_system.rst +++ b/docs/build_system.rst @@ -60,7 +60,7 @@ influencing the build process of the component as well as the project it's used in. Components may also include a Kconfig file defining the compile-time options that are settable by means of the menu system. -Project makefile variables that can be set by the programmer:: +Project Makefile variables that can be set by the programmer:: PROJECT_NAME: Mandatory. Name for the project BUILD_DIR_BASE: Set the directory where all objects/libraries/binaries end up in. @@ -76,17 +76,20 @@ Project makefile variables that can be set by the programmer:: include directories that are passed to the compilation pass of all components and they do not have a Kconfig option. -Component makefile variables that can be set by the programmer:: +Component-specific component.mk variables that can be set by the programmer:: COMPONENT_ADD_INCLUDEDIRS: Relative path to include directories to be added to - the entire project + the entire project. If an include directory is only needed to compile this + specific component, don't add it here. COMPONENT_PRIV_INCLUDEDIRS: Relative path to include directories that are only used - when compiling this specific component + when compiling this specific component. COMPONENT_DEPENDS: Names of any components that need to be compiled before this component. - COMPONENT_ADD_LDFLAGS: Ld flags to add for this project. Defaults to -l$(COMPONENT_NAME). + COMPONENT_ADD_LDFLAGS: LD flags to add for the entire project. Defaults to -l$(COMPONENT_NAME). Add libraries etc in the current directory as $(abspath libwhatever.a) - COMPONENT_EXTRA_INCLUDES: Any extra include paths. These will be prefixed with '-I' and - passed to the compiler; please put absolute paths here. + COMPONENT_EXTRA_INCLUDES: Any extra include paths used when compiling the component's + source files. These will be prefixed with '-I' and passed to the compiler. + Similar to COMPONENT_PRIV_INCLUDEDIRS, but these paths are passed as-is instead of + expanded relative to the component directory. COMPONENT_SRCDIRS: Relative directories to look in for sources. Defaults to '.', the current directory (the root of the component) only. Use this to specify any subdirectories. Note that specifying this overwrites the default action of compiling everything in the @@ -114,6 +117,10 @@ be usable in component or project Makefiles:: COMPONENTS: Name of the components to be included CONFIG_*: All values set by 'make menuconfig' have corresponding Makefile variables. +Inside your component's component.mk makefile, you can override or add to these variables +as necessary. The changes are isolated from other components (see Makefile.projbuild below +if you want to share these changes with all other components.) + For components, there also are these defines:: COMPONENT_PATH: Absolute path to the root of the source tree of the component we're @@ -152,10 +159,16 @@ details to add to "menuconfig" for this component. Makefile.projbuild ------------------ -For components that have parts that need to be run when building of the -project is done, you can create a file called Makefile.projbuild in the -component root directory. This file will be included in the main -Makefile. +For components that have parts that need to be evaluated in the top-level +project context, you can create a file called Makefile.projbuild in the +component root directory. These files is included into the project's +top-level Makefile. + +For example, if your component needs to add to CFLAGS for the entire +project (not just for its own source files) then you can set +``CFLAGS +=`` in Makefile.projbuild. Note that this isn't necessary for +adding include directories to the project, you can set +``COMPONENT_ADD_INCLUDEDIRS`` (see above) in the component.mk. KConfig.projbuild diff --git a/make/common.mk b/make/common.mk index adae46738..a515584a9 100644 --- a/make/common.mk +++ b/make/common.mk @@ -8,32 +8,6 @@ # see project_config.mk for details.) -include $(PROJECT_PATH)/build/include/config/auto.conf -ifeq ("$(LDFLAGS)","") -LDFLAGS = -nostdlib \ - -L$(IDF_PATH)/lib \ - -L$(IDF_PATH)/ld \ - $(addprefix -L$(BUILD_DIR_BASE)/,$(COMPONENTS) $(SRCDIRS)) \ - -u call_user_start_cpu0 \ - -Wl,--gc-sections \ - -Wl,-static \ - -Wl,--start-group \ - $(COMPONENT_LDFLAGS) \ - -lgcc \ - -Wl,--end-group -endif - -ifeq ("$(CFLAGS)","") -CFLAGS = -DESP_PLATFORM -Og -std=gnu99 -g3 \ - -Wpointer-arith -Werror -Wno-error=unused-function -Wno-error=unused-but-set-variable -Wno-error=unused-variable \ - -Wl,-EL -fno-inline-functions -nostdlib -mlongcalls -Wall -ffunction-sections -fdata-sections $(EXTRA_CFLAGS) -endif - -ifeq ("$(CXXFLAGS)","") -CXXFLAGS = -DESP_PLATFORM -Og -std=gnu++11 -g3 \ - -Wpointer-arith -Werror -Wno-error=unused-function -Wno-error=unused-but-set-variable -Wno-error=unused-variable \ - -Wl,-EL -nostdlib -mlongcalls -Wall -ffunction-sections -fdata-sections $(EXTRA_CFLAGS) -fno-exceptions -endif - #Handling of V=1/VERBOSE=1 flag # # if V=1, $(summary) does nothing and $(details) will echo extra details diff --git a/make/component_common.mk b/make/component_common.mk index 1a3d9281c..ebad525a7 100644 --- a/make/component_common.mk +++ b/make/component_common.mk @@ -25,7 +25,7 @@ export COMPONENT_PATH include $(IDF_PATH)/make/common.mk -#Some of these options are overridable by the components Makefile. +#Some of these options are overridable by the component's component.mk Makefile #Name of the component COMPONENT_NAME ?= $(lastword $(subst /, ,$(realpath $(COMPONENT_PATH)))) @@ -58,7 +58,8 @@ COMPONENT_ADD_LDFLAGS ?= -l$(COMPONENT_NAME) OWN_INCLUDES:=$(abspath $(addprefix $(COMPONENT_PATH)/,$(COMPONENT_ADD_INCLUDEDIRS) $(COMPONENT_PRIV_INCLUDEDIRS))) COMPONENT_INCLUDES := $(OWN_INCLUDES) $(filter-out $(OWN_INCLUDES),$(COMPONENT_INCLUDES)) -#This target is used to collect variable values from inside the main makefile +#This target is used to collect variable values from inside project.mk +# see project.mk GetVariable macro for details. get_variable: @echo "$(GET_VARIABLE)=$(call $(GET_VARIABLE)) " @@ -82,9 +83,6 @@ clean: $(Q) rm -f $(COMPONENT_LIBRARY) $(COMPONENT_OBJS) $(COMPONENT_OBJS:.o=.d) $(COMPONENT_EXTRA_CLEAN) endif -#Also generate dependency files -CFLAGS+=-MMD -MP -CXXFLAGS+=-MMD -MP #Include all dependency files already generated -include $(COMPONENT_OBJS:.o=.d) diff --git a/make/project.mk b/make/project.mk index ca80697cb..b86470bf6 100644 --- a/make/project.mk +++ b/make/project.mk @@ -133,6 +133,41 @@ export PROJECT_PATH #Include functionality common to both project & component -include $(IDF_PATH)/make/common.mk +# Set default LDFLAGS + +LDFLAGS ?= -nostdlib \ + -L$(IDF_PATH)/lib \ + -L$(IDF_PATH)/ld \ + $(addprefix -L$(BUILD_DIR_BASE)/,$(COMPONENTS) $(SRCDIRS)) \ + -u call_user_start_cpu0 \ + -Wl,--gc-sections \ + -Wl,-static \ + -Wl,--start-group \ + $(COMPONENT_LDFLAGS) \ + -lgcc \ + -Wl,--end-group \ + -Wl,-EL + +# Set default CPPFLAGS, CFLAGS, CXXFLAGS +# +# These are exported so that components can use them when compiling. +# +# If you need your component to add CFLAGS/etc for it's own source compilation only, set CFLAGS += in your component's Makefile. +# +# If you need your component to add CFLAGS/etc globally for all source +# files, set CFLAGS += in your component's Makefile.projbuild + +# CPPFLAGS used by an compile pass that uses the C preprocessor +CPPFLAGS = -DESP_PLATFORM -Og -g3 -Wpointer-arith -Werror -Wno-error=unused-function -Wno-error=unused-but-set-variable -Wno-error=unused-variable -Wall -ffunction-sections -fdata-sections -mlongcalls -nostdlib -MMD -MP + +# C flags use by C only +CFLAGS = $(CPPFLAGS) -std=gnu99 -g3 -fno-inline-functions + +# CXXFLAGS uses by C++ only +CXXFLAGS = $(CPPFLAGS) -Og -std=gnu++11 -g3 -fno-exceptions + +export CFLAGS CPPFLAGS CXXFLAGS + #Set host compiler and binutils HOSTCC := $(CC) HOSTLD := $(LD) @@ -158,6 +193,7 @@ APP_BIN:=$(APP_ELF:.elf=.bin) # Include any Makefile.projbuild file letting components add # configuration at the project level define includeProjBuildMakefile +$(if $(V),$(if $(wildcard $(1)/Makefile.projbuild),$(info including $(1)/Makefile.projbuild...))) COMPONENT_PATH := $(1) -include $(1)/Makefile.projbuild endef diff --git a/make/project_config.mk b/make/project_config.mk index e39fdac3b..d2909bb30 100644 --- a/make/project_config.mk +++ b/make/project_config.mk @@ -10,8 +10,6 @@ KCONFIG_TOOL_DIR=$(IDF_PATH)/tools/kconfig # clear MAKEFLAGS as the menuconfig makefile uses implicit compile rules $(KCONFIG_TOOL_DIR)/mconf $(KCONFIG_TOOL_DIR)/conf: MAKEFLAGS="" \ - CFLAGS="" \ - LDFLAGS="" \ CC=$(HOSTCC) LD=$(HOSTLD) \ $(MAKE) -C $(KCONFIG_TOOL_DIR) diff --git a/tools/kconfig/Makefile b/tools/kconfig/Makefile index b265e9b38..2df04f3f2 100644 --- a/tools/kconfig/Makefile +++ b/tools/kconfig/Makefile @@ -18,6 +18,10 @@ endif # We need this, in case the user has it in its environment unexport CONFIG_ +# Unset some environment variables set in the project environment +CFLAGS := +CPPFLAGS := +LDFLAGS := default: mconf conf