From 57bc38d867f1d4a60a5323b86b4349a57d3ada3e Mon Sep 17 00:00:00 2001 From: Deng Xin Date: Tue, 1 Aug 2017 22:29:16 +0800 Subject: [PATCH] Add the fast crypto function in supplicant optimize the speed when do wifi connect --- components/esp32/fast_crypto_ops.c | 61 ++++ components/esp32/include/esp_wifi.h | 7 +- .../esp32/include/esp_wifi_crypto_types.h | 301 ++++++++++++++++++ components/esp32/include/esp_wpa2.h | 15 +- components/esp32/include/esp_wps.h | 16 +- components/esp32/lib | 2 +- components/wpa_supplicant/component.mk | 4 +- .../wpa_supplicant/include/crypto/aes_wrap.h | 7 +- .../wpa_supplicant/include/crypto/crypto.h | 138 +++++++- .../wpa_supplicant/include/crypto/sha256.h | 6 + .../wpa_supplicant/src/crypto/dh_groups.c | 37 ++- .../src/fast_crypto/fast_aes-cbc.c | 78 +++++ .../src/fast_crypto/fast_aes-unwrap.c | 81 +++++ .../src/fast_crypto/fast_aes-wrap.c | 80 +++++ .../fast_crypto/fast_crypto_internal-cipher.c | 283 ++++++++++++++++ .../fast_crypto/fast_crypto_internal-modexp.c | 59 ++++ .../src/fast_crypto/fast_crypto_internal.c | 282 ++++++++++++++++ .../src/fast_crypto/fast_sha256-internal.c | 48 +++ .../src/fast_crypto/fast_sha256.c | 165 ++++++++++ docs/Doxyfile | 1 + docs/api-guides/wifi.rst | 10 + examples/wifi/power_save/main/power_save.c | 1 + .../wifi/smart_config/main/smartconfig_main.c | 2 + .../main/wpa2_enterprise_main.c | 4 +- examples/wifi/wps/main/wps.c | 11 +- 25 files changed, 1673 insertions(+), 26 deletions(-) create mode 100644 components/esp32/fast_crypto_ops.c create mode 100644 components/esp32/include/esp_wifi_crypto_types.h create mode 100644 components/wpa_supplicant/src/fast_crypto/fast_aes-cbc.c create mode 100644 components/wpa_supplicant/src/fast_crypto/fast_aes-unwrap.c create mode 100644 components/wpa_supplicant/src/fast_crypto/fast_aes-wrap.c create mode 100644 components/wpa_supplicant/src/fast_crypto/fast_crypto_internal-cipher.c create mode 100644 components/wpa_supplicant/src/fast_crypto/fast_crypto_internal-modexp.c create mode 100644 components/wpa_supplicant/src/fast_crypto/fast_crypto_internal.c create mode 100644 components/wpa_supplicant/src/fast_crypto/fast_sha256-internal.c create mode 100644 components/wpa_supplicant/src/fast_crypto/fast_sha256.c diff --git a/components/esp32/fast_crypto_ops.c b/components/esp32/fast_crypto_ops.c new file mode 100644 index 000000000..23c79885b --- /dev/null +++ b/components/esp32/fast_crypto_ops.c @@ -0,0 +1,61 @@ +// Copyright 2015-2017 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 "crypto/common.h" +#include "crypto/aes_wrap.h" +#include "crypto/sha256.h" +#include "crypto/crypto.h" +#include "esp_wifi_crypto_types.h" + +/* + * The parameters is used to set the cyrpto callback function for station connect when in security mode, + * every callback function can register as fast_xxx or normal one, i.e, fast_aes_wrap or aes_wrap, the + * difference between them is the normal API is calculate by software, the fast one use the hardware + * crypto in it, can be faster than the normal one, so the callback function register in default is which + * we recommend, so as the API in WPS default and WPA2 default. + */ +const wpa_crypto_funcs_t g_wifi_default_wpa_crypto_funcs = { + .aes_wrap = (esp_aes_wrap_t)fast_aes_wrap, + .aes_unwrap = (esp_aes_unwrap_t)fast_aes_unwrap, + .hmac_sha256_vector = (esp_hmac_sha256_vector_t)fast_hmac_sha256_vector, + .sha256_prf = (esp_sha256_prf_t)fast_sha256_prf +}; + +const wps_crypto_funcs_t g_wifi_default_wps_crypto_funcs = { + .aes_128_encrypt = (esp_aes_128_encrypt_t)fast_aes_128_cbc_encrypt, + .aes_128_decrypt = (esp_aes_128_decrypt_t)fast_aes_128_cbc_decrypt, + .crypto_mod_exp = (esp_crypto_mod_exp_t)fast_crypto_mod_exp, + .hmac_sha256 = (esp_hmac_sha256_t)fast_hmac_sha256, + .hmac_sha256_vector = (esp_hmac_sha256_vector_t)fast_hmac_sha256_vector, + .sha256_vector = (esp_sha256_vector_t)fast_sha256_vector +}; + +/* + * What should notice is that the cyrpto hash type function and crypto cipher type function can not register + * as different, i.e, if you use fast_crypto_hash_init, you should use fast_crypto_hash_update and + * fast_crypto_hash_finish for finish hash calculate, rather than call crypto_hash_update and + * crypto_hash_finish, so do crypto_cipher. + */ +const wpa2_crypto_funcs_t g_wifi_default_wpa2_crypto_funcs = { + .crypto_hash_init = (esp_crypto_hash_init_t)fast_crypto_hash_init, + .crypto_hash_update = (esp_crypto_hash_update_t)fast_crypto_hash_update, + .crypto_hash_finish = (esp_crypto_hash_finish_t)fast_crypto_hash_finish, + .crypto_cipher_init = (esp_crypto_cipher_init_t)fast_crypto_cipher_init, + .crypto_cipher_encrypt = (esp_crypto_cipher_encrypt_t)fast_crypto_cipher_encrypt, + .crypto_cipher_decrypt = (esp_crypto_cipher_decrypt_t)fast_crypto_cipher_decrypt, + .crypto_cipher_deinit = (esp_crypto_cipher_deinit_t)fast_crypto_cipher_deinit, + .sha256_vector = (esp_sha256_vector_t)fast_sha256_vector, + .crypto_mod_exp = (esp_crypto_mod_exp_t)crypto_mod_exp +}; + diff --git a/components/esp32/include/esp_wifi.h b/components/esp32/include/esp_wifi.h index 2881eb1fe..b6450c7fa 100755 --- a/components/esp32/include/esp_wifi.h +++ b/components/esp32/include/esp_wifi.h @@ -65,6 +65,7 @@ #include "sdkconfig.h" #include "esp_err.h" #include "esp_wifi_types.h" +#include "esp_wifi_crypto_types.h" #include "esp_event.h" #ifdef __cplusplus @@ -96,6 +97,7 @@ extern "C" { */ typedef struct { system_event_handler_t event_handler; /**< WiFi event handler */ + wpa_crypto_funcs_t wpa_crypto_funcs; /**< WiFi station crypto functions when connect */ int static_rx_buf_num; /**< WiFi static RX buffer number */ int dynamic_rx_buf_num; /**< WiFi dynamic RX buffer number */ int tx_buf_type; /**< WiFi TX buffer type */ @@ -138,11 +140,14 @@ typedef struct { #else #define WIFI_NANO_FORMAT_ENABLED 0 #endif - + +extern const wpa_crypto_funcs_t g_wifi_default_wpa_crypto_funcs; + #define WIFI_INIT_CONFIG_MAGIC 0x1F2F3F4F #ifdef CONFIG_WIFI_ENABLED #define WIFI_INIT_CONFIG_DEFAULT() { \ .event_handler = &esp_event_send, \ + .wpa_crypto_funcs = g_wifi_default_wpa_crypto_funcs, \ .static_rx_buf_num = CONFIG_ESP32_WIFI_STATIC_RX_BUFFER_NUM,\ .dynamic_rx_buf_num = CONFIG_ESP32_WIFI_DYNAMIC_RX_BUFFER_NUM,\ .tx_buf_type = CONFIG_ESP32_WIFI_TX_BUFFER_TYPE,\ diff --git a/components/esp32/include/esp_wifi_crypto_types.h b/components/esp32/include/esp_wifi_crypto_types.h new file mode 100644 index 000000000..10a55a708 --- /dev/null +++ b/components/esp32/include/esp_wifi_crypto_types.h @@ -0,0 +1,301 @@ +// Hardware crypto support Copyright 2017 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_WIFI_CRYPTO_TYPES_H__ +#define __ESP_WIFI_CRYPTO_TYPES_H__ + +#ifdef __cplusplus +extern "C" { +#endif + +/* + * This enumation is about alorigthm will be set when do crypt hash + * operation.When do wpa2 connecting, after invoke crypto_hash_xxx of + * fast_crypto_hash_xxx API, it will do relation crypt operation according + * to the enumation. + */ +typedef enum { + ESP_CRYPTO_HASH_ALG_MD5, ESP_CRYPTO_HASH_ALG_SHA1, + ESP_CRYPTO_HASH_ALG_HMAC_MD5, ESP_CRYPTO_HASH_ALG_HMAC_SHA1, + ESP_CRYPTO_HASH_ALG_SHA256, ESP_CRYPTO_HASH_ALG_HMAC_SHA256 +}esp_crypto_hash_alg_t; + +/* + * This enumation is about alorigthm will be set when do crypt cipher + * operation.When do wpa2 connecting, after invoke crypto_cipher_xxx of + * fast_crypto_cipher_xxx API, it will do relation crypt operation according + * to the enumation. + */ +typedef enum { + ESP_CRYPTO_CIPHER_NULL, ESP_CRYPTO_CIPHER_ALG_AES, ESP_CRYPTO_CIPHER_ALG_3DES, + ESP_CRYPTO_CIPHER_ALG_DES, ESP_CRYPTO_CIPHER_ALG_RC2, ESP_CRYPTO_CIPHER_ALG_RC4 +} esp_crypto_cipher_alg_t; + +/* + * This structure is about the algorithm when do crypto_hash operation, for detail, + * please reference to the structure crypto_hash. + */ +typedef struct crypto_hash esp_crypto_hash_t; + +/* + * This structure is about the algorithm when do crypto_cipher operation, for detail, + * please reference to the structure crypto_cipher. + */ +typedef struct crypto_cipher esp_crypto_cipher_t; + +/** + * @brief The crypto callback function used in wpa enterprise hash operation when connect. + * Initialize a esp_crypto_hash_t structure. + * + * @param alg Hash algorithm. + * @param key Key for keyed hash (e.g., HMAC) or %NULL if not needed. + * @param key_len Length of the key in bytes + * + */ +typedef esp_crypto_hash_t * (*esp_crypto_hash_init_t)(esp_crypto_hash_alg_t alg, const unsigned char *key, int key_len); + +/** + * @brief The crypto callback function used in wpa enterprise hash operation when connect. + * Add data to hash calculation. + * + * @param ctz Context pointer from esp_crypto_hash_init_t function. + * @param data Data buffer to add. + * @param len Length of the buffer. + * + */ +typedef void * (*esp_crypto_hash_update_t)(esp_crypto_hash_t *ctx, const unsigned char *data, int len); + +/** + * @brief The crypto callback function used in wpa enterprise hash operation when connect. + * Complete hash calculation. + * + * @param ctz Context pointer from esp_crypto_hash_init_t function. + * @param hash Buffer for hash value or %NULL if caller is just freeing the hash + * context. + * @param len Pointer to length of the buffer or %NULL if caller is just freeing the + * hash context; on return, this is set to the actual length of the hash value + * Returns: 0 on success, -1 if buffer is too small (len set to needed length), + * or -2 on other failures (including failed crypto_hash_update() operations) + * + */ +typedef int * (*esp_crypto_hash_finish_t)(esp_crypto_hash_t *ctx, unsigned char *hash, int *len); + +/** + * @brief The AES callback function when do WPS connect. + * + * @param key Encryption key. + * @param iv Encryption IV for CBC mode (16 bytes). + * @param data Data to encrypt in-place. + * @param data_len Length of data in bytes (must be divisible by 16) + */ +typedef int * (*esp_aes_128_encrypt_t)(const unsigned char *key, const unsigned char *iv, unsigned char *data, int data_len); + +/** + * @brief The AES callback function when do WPS connect. + * + * @param key Decryption key. + * @param iv Decryption IV for CBC mode (16 bytes). + * @param data Data to decrypt in-place. + * @param data_len Length of data in bytes (must be divisible by 16) + * + */ +typedef int * (*esp_aes_128_decrypt_t)(const unsigned char *key, const unsigned char *iv, unsigned char *data, int data_len); + +/** + * @brief The AES callback function when do STA connect. + * + * @param kek 16-octet Key encryption key (KEK). + * @param n Length of the plaintext key in 64-bit units; + * @param plain Plaintext key to be wrapped, n * 64 bits + * @param cipher Wrapped key, (n + 1) * 64 bits + * + */ +typedef int * (*esp_aes_wrap_t)(const unsigned char *kek, int n, const unsigned char *plain, unsigned char *cipher); + +/** + * @brief The AES callback function when do STA connect. + * + * @param kek 16-octet Key decryption key (KEK). + * @param n Length of the plaintext key in 64-bit units; + * @param cipher Wrapped key to be unwrapped, (n + 1) * 64 bits + * @param plain Plaintext key, n * 64 bits + * + */ +typedef int * (*esp_aes_unwrap_t)(const unsigned char *kek, int n, const unsigned char *cipher, unsigned char *plain); + +/** + * @brief The crypto callback function used in wpa enterprise cipher operation when connect. + * Initialize a esp_crypto_cipher_t structure. + * + * @param alg cipher algorithm. + * @param iv Initialization vector for block ciphers or %NULL for stream ciphers. + * @param key Cipher key + * @param key_len Length of key in bytes + * + */ +typedef esp_crypto_cipher_t * (*esp_crypto_cipher_init_t)(esp_crypto_cipher_alg_t alg, const unsigned char *iv, const unsigned char *key, int key_len); + +/** + * @brief The crypto callback function used in wpa enterprise cipher operation when connect. + * Cipher encrypt. + * + * @param ctx Context pointer from esp_crypto_cipher_init_t callback function. + * @param plain Plaintext to cipher. + * @param crypt Resulting ciphertext. + * @param len Length of the plaintext. + * + */ +typedef int * (*esp_crypto_cipher_encrypt_t)(esp_crypto_cipher_t *ctx, + const unsigned char *plain, unsigned char *crypt, int len); +/** + * @brief The crypto callback function used in wpa enterprise cipher operation when connect. + * Cipher decrypt. + * + * @param ctx Context pointer from esp_crypto_cipher_init_t callback function. + * @param crypt Ciphertext to decrypt. + * @param plain Resulting plaintext. + * @param len Length of the cipher text. + * + */ +typedef int * (*esp_crypto_cipher_decrypt_t)(esp_crypto_cipher_t *ctx, + const unsigned char *crypt, unsigned char *plain, int len); +/** + * @brief The crypto callback function used in wpa enterprise cipher operation when connect. + * Free cipher context. + * + * @param ctx Context pointer from esp_crypto_cipher_init_t callback function. + * + */ +typedef void * (*esp_crypto_cipher_deinit_t)(esp_crypto_cipher_t *ctx); + +/** + * @brief The SHA256 callback function when do WPS connect. + * + * @param key Key for HMAC operations. + * @param key_len Length of the key in bytes. + * @param data Pointers to the data area. + * @param data_len Length of the data area. + * @param mac Buffer for the hash (20 bytes). + * + */ +typedef void * (*esp_hmac_sha256_t)(const unsigned char *key, int key_len, const unsigned char *data, + int data_len, unsigned char *mac); + +/** + * @brief The SHA256 callback function when do WPS connect. + * + * @param key Key for HMAC operations. + * @param key_len Length of the key in bytes. + * @param num_elem Number of elements in the data vector. + * @param addr Pointers to the data areas. + * @param len Lengths of the data blocks. + * @param mac Buffer for the hash (32 bytes). + * + */ +typedef void * (*esp_hmac_sha256_vector_t)(const unsigned char *key, int key_len, int num_elem, + const unsigned char *addr[], const int *len, unsigned char *mac); + +/** + * @brief The AES callback function when do STA connect. + * + * @param key Key for PRF. + * @param key_len Length of the key in bytes. + * @param label A unique label for each purpose of the PRF. + * @param data Extra data to bind into the key. + * @param data_len Length of the data. + * @param buf Buffer for the generated pseudo-random key. + * @param buf_len Number of bytes of key to generate. + * + */ +typedef void * (*esp_sha256_prf_t)(const unsigned char *key, int key_len, const char *label, + const unsigned char *data, int data_len, unsigned char *buf, int buf_len); + +/** + * @brief The SHA256 callback function when do WPS connect. + * + * @param num_elem Number of elements in the data vector. + * @param addr Pointers to the data areas. + * @param len Lengths of the data blocks. + * @param mac Buffer for the hash. + * + */ +typedef int * (*esp_sha256_vector_t)(int num_elem, const unsigned char *addr[], const int *len, + unsigned char *mac); + +/** + * @brief The bignum calculate callback function used when do connect. + * In WPS process, it used to calculate public key and private key. + * + * @param base Base integer (big endian byte array). + * @param base_len Length of base integer in bytes. + * @param power Power integer (big endian byte array). + * @param power_len Length of power integer in bytes. + * @param modulus Modulus integer (big endian byte array). + * @param modulus_len Length of modulus integer in bytes. + * @param result Buffer for the result. + * @param result_len Result length (max buffer size on input, real len on output). + * + */ +typedef int * (*esp_crypto_mod_exp_t)(const unsigned char *base, int base_len, + const unsigned char *power, int power_len, + const unsigned char *modulus, int modulus_len, + unsigned char *result, unsigned int *result_len); +/** + * @brief The crypto callback function structure used when do station security connect. + * The structure can be set as software crypto or the crypto optimized by ESP32 + * hardware. + */ +typedef struct { + esp_aes_wrap_t aes_wrap; /**< station connect function used when send EAPOL frame */ + esp_aes_unwrap_t aes_unwrap; /**< station connect function used when decrypt key data */ + esp_hmac_sha256_vector_t hmac_sha256_vector; /**< station connect function used when check MIC */ + esp_sha256_prf_t sha256_prf; /**< station connect function used when check MIC */ +}wpa_crypto_funcs_t; + +/** + * @brief The crypto callback function structure used when do WPS process. The + * structure can be set as software crypto or the crypto optimized by ESP32 + * hardware. + */ +typedef struct{ + esp_aes_128_encrypt_t aes_128_encrypt; /**< function used to process message when do WPS */ + esp_aes_128_decrypt_t aes_128_decrypt; /**< function used to process message when do WPS */ + esp_crypto_mod_exp_t crypto_mod_exp; /**< function used to calculate public key and private key */ + esp_hmac_sha256_t hmac_sha256; /**< function used to get attribute */ + esp_hmac_sha256_vector_t hmac_sha256_vector; /**< function used to process message when do WPS */ + esp_sha256_vector_t sha256_vector; /**< function used to process message when do WPS */ +}wps_crypto_funcs_t; + +/** + * @brief The crypto callback function structure used when do WPA enterprise connect. + * The structure can be set as software crypto or the crypto optimized by ESP32 + * hardware. + */ +typedef struct { + esp_crypto_hash_init_t crypto_hash_init; /**< function used to initialize a crypto_hash structure when use TLSV1 */ + esp_crypto_hash_update_t crypto_hash_update; /**< function used to calculate hash data when use TLSV1 */ + esp_crypto_hash_finish_t crypto_hash_finish; /**< function used to finish the hash calculate when use TLSV1 */ + esp_crypto_cipher_init_t crypto_cipher_init; /**< function used to initialize a crypt_cipher structure when use TLSV1 */ + esp_crypto_cipher_encrypt_t crypto_cipher_encrypt; /**< function used to encrypt cipher when use TLSV1 */ + esp_crypto_cipher_decrypt_t crypto_cipher_decrypt; /**< function used to decrypt cipher when use TLSV1 */ + esp_crypto_cipher_deinit_t crypto_cipher_deinit; /**< function used to free context when use TLSV1 */ + esp_sha256_vector_t sha256_vector; /**< function used to do X.509v3 certificate parsing and processing */ + esp_crypto_mod_exp_t crypto_mod_exp; /**< function used to do key exchange when use TLSV1 */ +}wpa2_crypto_funcs_t; + +#ifdef __cplusplus +} +#endif +#endif diff --git a/components/esp32/include/esp_wpa2.h b/components/esp32/include/esp_wpa2.h index e33e0e6dc..6628bd1c9 100644 --- a/components/esp32/include/esp_wpa2.h +++ b/components/esp32/include/esp_wpa2.h @@ -1,4 +1,4 @@ -// Copyright 2015-2016 Espressif Systems (Shanghai) PTE LTD +// Hardware crypto support Copyright 2017 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. @@ -16,11 +16,22 @@ #define ESP_WPA2_H #include "esp_err.h" +#include "esp_wifi_crypto_types.h" #ifdef __cplusplus extern "C" { #endif +extern const wpa2_crypto_funcs_t g_wifi_default_wpa2_crypto_funcs; + +typedef struct { + const wpa2_crypto_funcs_t *crypto_funcs; +}esp_wpa2_config_t; + +#define WPA2_CONFIG_INIT_DEFAULT() { \ + .crypto_funcs = &g_wifi_default_wpa2_crypto_funcs \ +} + /** * @brief Enable wpa2 enterprise authentication. * @@ -31,7 +42,7 @@ extern "C" { * - ESP_ERR_WIFI_OK: succeed. * - ESP_ERR_WIFI_NO_MEM: fail(internal memory malloc fail) */ -esp_err_t esp_wifi_sta_wpa2_ent_enable(void); +esp_err_t esp_wifi_sta_wpa2_ent_enable(const esp_wpa2_config_t *config); /** * @brief Disable wpa2 enterprise authentication. diff --git a/components/esp32/include/esp_wps.h b/components/esp32/include/esp_wps.h index f95eaa5e2..bfbb21537 100644 --- a/components/esp32/include/esp_wps.h +++ b/components/esp32/include/esp_wps.h @@ -15,8 +15,10 @@ #ifndef __ESP_WPS_H__ #define __ESP_WPS_H__ +#include #include #include "esp_err.h" +#include "esp_wifi_crypto_types.h" #ifdef __cplusplus extern "C" { @@ -52,6 +54,18 @@ typedef enum wps_type { WPS_TYPE_MAX, } wps_type_t; +extern const wps_crypto_funcs_t g_wifi_default_wps_crypto_funcs; + +typedef struct { + wps_type_t wps_type; + const wps_crypto_funcs_t *crypto_funcs; +}esp_wps_config_t; + +#define WPS_CONFIG_INIT_DEFAULT(type) { \ + .wps_type = type, \ + .crypto_funcs = &g_wifi_default_wps_crypto_funcs, \ +} + /** * @brief Enable Wi-Fi WPS function. * @@ -65,7 +79,7 @@ typedef enum wps_type { * - ESP_ERR_WIFI_WPS_MODE : wifi is not in station mode or sniffer mode is on * - ESP_ERR_WIFI_FAIL : wps initialization fails */ -esp_err_t esp_wifi_wps_enable(wps_type_t wps_type); +esp_err_t esp_wifi_wps_enable(const esp_wps_config_t *config); /** * @brief Disable Wi-Fi WPS function and release resource it taken. diff --git a/components/esp32/lib b/components/esp32/lib index 57b3072bd..e8d8e908f 160000 --- a/components/esp32/lib +++ b/components/esp32/lib @@ -1 +1 @@ -Subproject commit 57b3072bd3fd2f7759225d8407443e9e983520ae +Subproject commit e8d8e908fb37c4d9e8a3f23e63f6b34f5178e24a diff --git a/components/wpa_supplicant/component.mk b/components/wpa_supplicant/component.mk index daac5ca70..f34cb95f3 100644 --- a/components/wpa_supplicant/component.mk +++ b/components/wpa_supplicant/component.mk @@ -1,4 +1,4 @@ -COMPONENT_ADD_INCLUDEDIRS := include port/include -COMPONENT_SRCDIRS := src/crypto port +COMPONENT_ADD_INCLUDEDIRS := include port/include ../esp32/include +COMPONENT_SRCDIRS := src/crypto port src/fast_crypto CFLAGS += -DEMBEDDED_SUPP -D__ets__ -Wno-strict-aliasing diff --git a/components/wpa_supplicant/include/crypto/aes_wrap.h b/components/wpa_supplicant/include/crypto/aes_wrap.h index 4b1c7b083..933031e4b 100644 --- a/components/wpa_supplicant/include/crypto/aes_wrap.h +++ b/components/wpa_supplicant/include/crypto/aes_wrap.h @@ -44,5 +44,10 @@ int __must_check aes_128_cbc_encrypt(const u8 *key, const u8 *iv, u8 *data, size_t data_len); int __must_check aes_128_cbc_decrypt(const u8 *key, const u8 *iv, u8 *data, size_t data_len); - +int __must_check fast_aes_wrap(const uint8_t *kek, int n, const uint8_t *plain, uint8_t *cipher); +int __must_check fast_aes_unwrap(const uint8_t *kek, int n, const uint8_t *cipher, uint8_t *plain); +int __must_check fast_aes_128_cbc_encrypt(const uint8_t *key, const uint8_t *iv, uint8_t *data, + size_t data_len); +int __must_check fast_aes_128_cbc_decrypt(const uint8_t *key, const uint8_t *iv, uint8_t *data, + size_t data_len); #endif /* AES_WRAP_H */ diff --git a/components/wpa_supplicant/include/crypto/crypto.h b/components/wpa_supplicant/include/crypto/crypto.h index f0b9f2243..b8877993d 100644 --- a/components/wpa_supplicant/include/crypto/crypto.h +++ b/components/wpa_supplicant/include/crypto/crypto.h @@ -100,6 +100,17 @@ int __must_check fips186_2_prf(const u8 *seed, size_t seed_len, u8 *x, int sha256_vector(size_t num_elem, const u8 *addr[], const size_t *len, u8 *mac); +/** + * fast_sha256_vector - fast SHA256 hash for data vector + * @num_elem: Number of elements in the data vector + * @addr: Pointers to the data areas + * @len: Lengths of the data blocks + * @mac: Buffer for the hash + * Returns: 0 on success, -1 on failure + */ +int fast_sha256_vector(size_t num_elem, const uint8_t *addr[], const size_t *len, + uint8_t *mac); + /** * des_encrypt - Encrypt one block with DES * @clear: 8 octets (in) @@ -159,7 +170,6 @@ enum crypto_hash_alg { CRYPTO_HASH_ALG_SHA256, CRYPTO_HASH_ALG_HMAC_SHA256 }; - struct crypto_hash; /** @@ -177,6 +187,21 @@ struct crypto_hash; struct crypto_hash * crypto_hash_init(enum crypto_hash_alg alg, const u8 *key, size_t key_len); +/** + * fast_crypto_hash_init - Initialize hash/HMAC function + * @alg: Hash algorithm + * @key: Key for keyed hash (e.g., HMAC) or %NULL if not needed + * @key_len: Length of the key in bytes + * Returns: Pointer to hash context to use with other hash functions or %NULL + * on failure + * + * This function is only used with internal TLSv1 implementation + * (CONFIG_TLS=internal). If that is not used, the crypto wrapper does not need + * to implement this. + */ +struct crypto_hash * fast_crypto_hash_init(enum crypto_hash_alg alg, const uint8_t *key, + size_t key_len); + /** * crypto_hash_update - Add data to hash calculation * @ctx: Context pointer from crypto_hash_init() @@ -189,6 +214,18 @@ struct crypto_hash * crypto_hash_init(enum crypto_hash_alg alg, const u8 *key, */ void crypto_hash_update(struct crypto_hash *ctx, const u8 *data, size_t len); +/** + * fast_crypto_hash_update - Add data to hash calculation + * @ctx: Context pointer from crypto_hash_init() + * @data: Data buffer to add + * @len: Length of the buffer + * + * This function is only used with internal TLSv1 implementation + * (CONFIG_TLS=internal). If that is not used, the crypto wrapper does not need + * to implement this. + */ +void fast_crypto_hash_update(struct crypto_hash *ctx, const uint8_t *data, size_t len); + /** * crypto_hash_finish - Complete hash calculation * @ctx: Context pointer from crypto_hash_init() @@ -208,6 +245,25 @@ void crypto_hash_update(struct crypto_hash *ctx, const u8 *data, size_t len); */ int crypto_hash_finish(struct crypto_hash *ctx, u8 *hash, size_t *len); +/** + * fast_crypto_hash_finish - Complete hash calculation + * @ctx: Context pointer from crypto_hash_init() + * @hash: Buffer for hash value or %NULL if caller is just freeing the hash + * context + * @len: Pointer to length of the buffer or %NULL if caller is just freeing the + * hash context; on return, this is set to the actual length of the hash value + * Returns: 0 on success, -1 if buffer is too small (len set to needed length), + * or -2 on other failures (including failed crypto_hash_update() operations) + * + * This function calculates the hash value and frees the context buffer that + * was used for hash calculation. + * + * This function is only used with internal TLSv1 implementation + * (CONFIG_TLS=internal). If that is not used, the crypto wrapper does not need + * to implement this. + */ +int fast_crypto_hash_finish(struct crypto_hash *ctx, uint8_t *hash, size_t *len); + enum crypto_cipher_alg { CRYPTO_CIPHER_NULL = 0, CRYPTO_CIPHER_ALG_AES, CRYPTO_CIPHER_ALG_3DES, @@ -233,6 +289,22 @@ struct crypto_cipher * crypto_cipher_init(enum crypto_cipher_alg alg, const u8 *iv, const u8 *key, size_t key_len); +/** + * fast_crypto_cipher_init - Initialize block/stream cipher function + * @alg: Cipher algorithm + * @iv: Initialization vector for block ciphers or %NULL for stream ciphers + * @key: Cipher key + * @key_len: Length of key in bytes + * Returns: Pointer to cipher context to use with other cipher functions or + * %NULL on failure + * + * This function is only used with internal TLSv1 implementation + * (CONFIG_TLS=internal). If that is not used, the crypto wrapper does not need + * to implement this. + */ +struct crypto_cipher * fast_crypto_cipher_init(enum crypto_cipher_alg alg, + const uint8_t *iv, const uint8_t *key, + size_t key_len); /** * crypto_cipher_encrypt - Cipher encrypt * @ctx: Context pointer from crypto_cipher_init() @@ -248,6 +320,21 @@ struct crypto_cipher * crypto_cipher_init(enum crypto_cipher_alg alg, int __must_check crypto_cipher_encrypt(struct crypto_cipher *ctx, const u8 *plain, u8 *crypt, size_t len); +/** + * fast_crypto_cipher_encrypt - Cipher encrypt + * @ctx: Context pointer from crypto_cipher_init() + * @plain: Plaintext to cipher + * @crypt: Resulting ciphertext + * @len: Length of the plaintext + * Returns: 0 on success, -1 on failure + * + * This function is only used with internal TLSv1 implementation + * (CONFIG_TLS=internal). If that is not used, the crypto wrapper does not need + * to implement this. + */ +int __must_check fast_crypto_cipher_encrypt(struct crypto_cipher *ctx, + const uint8_t *plain, uint8_t *crypt, size_t len); + /** * crypto_cipher_decrypt - Cipher decrypt * @ctx: Context pointer from crypto_cipher_init() @@ -263,6 +350,21 @@ int __must_check crypto_cipher_encrypt(struct crypto_cipher *ctx, int __must_check crypto_cipher_decrypt(struct crypto_cipher *ctx, const u8 *crypt, u8 *plain, size_t len); +/** + * fast_crypto_cipher_decrypt - Cipher decrypt + * @ctx: Context pointer from crypto_cipher_init() + * @crypt: Ciphertext to decrypt + * @plain: Resulting plaintext + * @len: Length of the cipher text + * Returns: 0 on success, -1 on failure + * + * This function is only used with internal TLSv1 implementation + * (CONFIG_TLS=internal). If that is not used, the crypto wrapper does not need + * to implement this. + */ +int __must_check fast_crypto_cipher_decrypt(struct crypto_cipher *ctx, + const uint8_t *crypt, uint8_t *plain, size_t len); + /** * crypto_cipher_decrypt - Free cipher context * @ctx: Context pointer from crypto_cipher_init() @@ -273,6 +375,15 @@ int __must_check crypto_cipher_decrypt(struct crypto_cipher *ctx, */ void crypto_cipher_deinit(struct crypto_cipher *ctx); +/** + * fast_crypto_cipher_decrypt - Free cipher context + * @ctx: Context pointer from crypto_cipher_init() + * + * This function is only used with internal TLSv1 implementation + * (CONFIG_TLS=internal). If that is not used, the crypto wrapper does not need + * to implement this. + */ +void fast_crypto_cipher_deinit(struct crypto_cipher *ctx); struct crypto_public_key; struct crypto_private_key; @@ -452,6 +563,31 @@ int __must_check crypto_mod_exp(const u8 *base, size_t base_len, const u8 *modulus, size_t modulus_len, u8 *result, size_t *result_len); +/** + * fast_crypto_mod_exp - Modular exponentiation of large integers + * @base: Base integer (big endian byte array) + * @base_len: Length of base integer in bytes + * @power: Power integer (big endian byte array) + * @power_len: Length of power integer in bytes + * @modulus: Modulus integer (big endian byte array) + * @modulus_len: Length of modulus integer in bytes + * @result: Buffer for the result + * @result_len: Result length (max buffer size on input, real len on output) + * Returns: 0 on success, -1 on failure + * + * This function calculates result = base ^ power mod modulus. modules_len is + * used as the maximum size of modulus buffer. It is set to the used size on + * success. + * + * This function is only used with internal TLSv1 implementation + * (CONFIG_TLS=internal). If that is not used, the crypto wrapper does not need + * to implement this. + */ +int __must_check fast_crypto_mod_exp(const uint8_t *base, size_t base_len, + const uint8_t *power, size_t power_len, + const uint8_t *modulus, size_t modulus_len, + uint8_t *result, size_t *result_len); + /** * rc4_skip - XOR RC4 stream to given data with skip-stream-start * @key: RC4 key diff --git a/components/wpa_supplicant/include/crypto/sha256.h b/components/wpa_supplicant/include/crypto/sha256.h index dc597f09b..8025a29de 100644 --- a/components/wpa_supplicant/include/crypto/sha256.h +++ b/components/wpa_supplicant/include/crypto/sha256.h @@ -24,4 +24,10 @@ void hmac_sha256(const u8 *key, size_t key_len, const u8 *data, void sha256_prf(const u8 *key, size_t key_len, const char *label, const u8 *data, size_t data_len, u8 *buf, size_t buf_len); +void fast_hmac_sha256_vector(const uint8_t *key, size_t key_len, size_t num_elem, + const uint8_t *addr[], const size_t *len, uint8_t *mac); +void fast_hmac_sha256(const uint8_t *key, size_t key_len, const uint8_t *data, + size_t data_len, uint8_t *mac); +void fast_sha256_prf(const uint8_t *key, size_t key_len, const char *label, + const uint8_t *data, size_t data_len, uint8_t *buf, size_t buf_len); #endif /* SHA256_H */ diff --git a/components/wpa_supplicant/src/crypto/dh_groups.c b/components/wpa_supplicant/src/crypto/dh_groups.c index 6ec9a36a9..c08f8f29d 100644 --- a/components/wpa_supplicant/src/crypto/dh_groups.c +++ b/components/wpa_supplicant/src/crypto/dh_groups.c @@ -20,11 +20,9 @@ #include "crypto/dh_groups.h" #include "wpa/wpabuf.h" #include "wpa/wpa_debug.h" +#include "esp_wifi_crypto_types.h" -extern int crypto_mod_exp(const u8 *base, size_t base_len, - const u8 *power, size_t power_len, - const u8 *modulus, size_t modulus_len, - u8 *result, size_t *result_len); +extern wps_crypto_funcs_t wps_crypto_funcs; #ifdef ALL_DH_GROUPS @@ -589,10 +587,17 @@ dh_init(const struct dh_group *dh, struct wpabuf **priv) pv = wpabuf_alloc(pv_len); if (pv == NULL) return NULL; - if (crypto_mod_exp(dh->generator, dh->generator_len, - wpabuf_head(*priv), wpabuf_len(*priv), - dh->prime, dh->prime_len, wpabuf_mhead(pv), - &pv_len) < 0) { + + if (wps_crypto_funcs.crypto_mod_exp) { + if (wps_crypto_funcs.crypto_mod_exp(dh->generator, dh->generator_len, + wpabuf_head(*priv), wpabuf_len(*priv), + dh->prime, dh->prime_len, wpabuf_mhead(pv), + &pv_len)) { + wpabuf_free(pv); + wpa_printf(MSG_INFO, "DH: crypto_mod_exp failed"); + return NULL; + } + } else { wpabuf_free(pv); wpa_printf(MSG_INFO, "DH: crypto_mod_exp failed"); return NULL; @@ -626,14 +631,22 @@ dh_derive_shared(const struct wpabuf *peer_public, shared = wpabuf_alloc(shared_len); if (shared == NULL) return NULL; - if (crypto_mod_exp(wpabuf_head(peer_public), wpabuf_len(peer_public), - wpabuf_head(own_private), wpabuf_len(own_private), - dh->prime, dh->prime_len, - wpabuf_mhead(shared), &shared_len) < 0) { + + if (wps_crypto_funcs.crypto_mod_exp) { + if (wps_crypto_funcs.crypto_mod_exp(wpabuf_head(peer_public), wpabuf_len(peer_public), + wpabuf_head(own_private), wpabuf_len(own_private), + dh->prime, dh->prime_len, + wpabuf_mhead(shared), &shared_len)) { + wpabuf_free(shared); + wpa_printf(MSG_INFO, "DH: crypto_mod_exp failed"); + return NULL; + } + } else { wpabuf_free(shared); wpa_printf(MSG_INFO, "DH: crypto_mod_exp failed"); return NULL; } + wpabuf_put(shared, shared_len); wpa_hexdump_buf_key(MSG_DEBUG, "DH: shared key", shared); diff --git a/components/wpa_supplicant/src/fast_crypto/fast_aes-cbc.c b/components/wpa_supplicant/src/fast_crypto/fast_aes-cbc.c new file mode 100644 index 000000000..5c362fa22 --- /dev/null +++ b/components/wpa_supplicant/src/fast_crypto/fast_aes-cbc.c @@ -0,0 +1,78 @@ +// Hardware crypto support Copyright 2017 Espressif Systems (Shanghai) PTE LTD +// +// Licensed under the Apache License, Version 2.0 (the "License"); + + +#include "crypto/includes.h" +#include "crypto/common.h" +#include "crypto/aes.h" +#include "crypto/aes_wrap.h" +#include "mbedtls/aes.h" + +/** + * fast_aes_128_cbc_encrypt - AES-128 CBC encryption + * @key: Encryption key + * @iv: Encryption IV for CBC mode (16 bytes) + * @data: Data to encrypt in-place + * @data_len: Length of data in bytes (must be divisible by 16) + * Returns: 0 on success, -1 on failure + */ +int +fast_aes_128_cbc_encrypt(const uint8_t *key, const uint8_t *iv, uint8_t *data, size_t data_len) +{ + int ret = 0; + mbedtls_aes_context ctx; + uint8_t cbc[AES_BLOCK_SIZE]; + + mbedtls_aes_init(&ctx); + + ret = mbedtls_aes_setkey_enc(&ctx, key, 128); + + if(ret < 0) { + mbedtls_aes_free(&ctx); + return ret; + } + + os_memcpy(cbc, iv, AES_BLOCK_SIZE); + + ret = mbedtls_aes_crypt_cbc(&ctx, MBEDTLS_AES_ENCRYPT, data_len, cbc, data, data); + + mbedtls_aes_free(&ctx); + + return ret; +} + + +/** + * fast_aes_128_cbc_decrypt - AES-128 CBC decryption + * @key: Decryption key + * @iv: Decryption IV for CBC mode (16 bytes) + * @data: Data to decrypt in-place + * @data_len: Length of data in bytes (must be divisible by 16) + * Returns: 0 on success, -1 on failure + */ +int +fast_aes_128_cbc_decrypt(const uint8_t *key, const uint8_t *iv, uint8_t *data, size_t data_len) +{ + int ret = 0; + mbedtls_aes_context ctx; + uint8_t cbc[AES_BLOCK_SIZE]; + + mbedtls_aes_init(&ctx); + + ret = mbedtls_aes_setkey_dec(&ctx, key, 128); + + if(ret < 0) { + mbedtls_aes_free(&ctx); + return ret; + } + + os_memcpy(cbc, iv, AES_BLOCK_SIZE); + + ret = mbedtls_aes_crypt_cbc(&ctx, MBEDTLS_AES_DECRYPT, data_len, cbc, data, data); + + mbedtls_aes_free(&ctx); + + return ret; + +} diff --git a/components/wpa_supplicant/src/fast_crypto/fast_aes-unwrap.c b/components/wpa_supplicant/src/fast_crypto/fast_aes-unwrap.c new file mode 100644 index 000000000..d6bfdfab1 --- /dev/null +++ b/components/wpa_supplicant/src/fast_crypto/fast_aes-unwrap.c @@ -0,0 +1,81 @@ +// 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 +// +// Hardware crypto support Copyright 2017 Espressif Systems (Shanghai) PTE LTD +// +// 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 "crypto/includes.h" +#include "crypto/common.h" +#include "mbedtls/aes.h" + +/** + * fast_aes_unwrap - Unwrap key with AES Key Wrap Algorithm (128-bit KEK) (RFC3394) + * @kek: Key encryption key (KEK) + * @n: Length of the plaintext key in 64-bit units; e.g., 2 = 128-bit = 16 + * bytes + * @cipher: Wrapped key to be unwrapped, (n + 1) * 64 bits + * @plain: Plaintext key, n * 64 bits + * Returns: 0 on success, -1 on failure (e.g., integrity verification failed) + */ +int +fast_aes_unwrap(const uint8_t *kek, int n, const uint8_t *cipher, uint8_t *plain) +{ + uint8_t a[8], *r, b[16]; + int32_t i, j; + int32_t ret = 0; + mbedtls_aes_context ctx; + + /* 1) Initialize variables. */ + os_memcpy(a, cipher, 8); + r = plain; + os_memcpy(r, cipher + 8, 8 * n); + + mbedtls_aes_init(&ctx); + ret = mbedtls_aes_setkey_dec(&ctx, kek, 128); + if (ret < 0) { + mbedtls_aes_free(&ctx); + return ret; + } + + /* 2) Compute intermediate values. + * For j = 5 to 0 + * For i = n to 1 + * B = AES-1(K, (A ^ t) | R[i]) where t = n*j+i + * A = MSB(64, B) + * R[i] = LSB(64, B) + */ + for (j = 5; j >= 0; j--) { + r = plain + (n - 1) * 8; + for (i = n; i >= 1; i--) { + os_memcpy(b, a, 8); + b[7] ^= n * j + i; + os_memcpy(b + 8, r, 8); + mbedtls_aes_decrypt(&ctx, b, b); + os_memcpy(a, b, 8); + os_memcpy(r, b + 8, 8); + r -= 8; + } + } + mbedtls_aes_free(&ctx); + + /* 3) Output results. + * + * These are already in @plain due to the location of temporary + * variables. Just verify that the IV matches with the expected value. + */ + for (i = 0; i < 8; i++) { + if (a[i] != 0xa6) { + return -1; + } + } + + return 0; +} diff --git a/components/wpa_supplicant/src/fast_crypto/fast_aes-wrap.c b/components/wpa_supplicant/src/fast_crypto/fast_aes-wrap.c new file mode 100644 index 000000000..01a98a3ad --- /dev/null +++ b/components/wpa_supplicant/src/fast_crypto/fast_aes-wrap.c @@ -0,0 +1,80 @@ +// 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 +// +// Hardware crypto support Copyright 2017 Espressif Systems (Shanghai) PTE LTD +// +// 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 "crypto/includes.h" + +#include "crypto/common.h" +#include "crypto/aes.h" +#include "crypto/aes_wrap.h" +#include "mbedtls/aes.h" + +/** + * fast_aes_wrap - Wrap keys with AES Key Wrap Algorithm (128-bit KEK) (RFC3394) + * @kek: 16-octet Key encryption key (KEK) + * @n: Length of the plaintext key in 64-bit units; e.g., 2 = 128-bit = 16 + * bytes + * @plain: Plaintext key to be wrapped, n * 64 bits + * @cipher: Wrapped key, (n + 1) * 64 bits + * Returns: 0 on success, -1 on failure + */ +int fast_aes_wrap(const uint8_t *kek, int n, const uint8_t *plain, uint8_t *cipher) +{ + uint8_t *a, *r, b[16]; + int32_t i, j; + int32_t ret = 0; + mbedtls_aes_context ctx; + + a = cipher; + r = cipher + 8; + + /* 1) Initialize variables. */ + os_memset(a, 0xa6, 8); + os_memcpy(r, plain, 8 * n); + + mbedtls_aes_init(&ctx); + ret = mbedtls_aes_setkey_enc(&ctx, kek, 128); + if (ret < 0) { + mbedtls_aes_free(&ctx); + return ret; + } + + /* 2) Calculate intermediate values. + * For j = 0 to 5 + * For i=1 to n + * B = AES(K, A | R[i]) + * A = MSB(64, B) ^ t where t = (n*j)+i + * R[i] = LSB(64, B) + */ + for (j = 0; j <= 5; j++) { + r = cipher + 8; + for (i = 1; i <= n; i++) { + os_memcpy(b, a, 8); + os_memcpy(b + 8, r, 8); + mbedtls_aes_encrypt(&ctx, b, b); + os_memcpy(a, b, 8); + a[7] ^= n * j + i; + os_memcpy(r, b + 8, 8); + r += 8; + } + } + mbedtls_aes_free(&ctx); + + /* 3) Output the results. + * + * These are already in @cipher due to the location of temporary + * variables. + */ + + return 0; +} diff --git a/components/wpa_supplicant/src/fast_crypto/fast_crypto_internal-cipher.c b/components/wpa_supplicant/src/fast_crypto/fast_crypto_internal-cipher.c new file mode 100644 index 000000000..fb00760bd --- /dev/null +++ b/components/wpa_supplicant/src/fast_crypto/fast_crypto_internal-cipher.c @@ -0,0 +1,283 @@ +// 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 +// +// Hardware crypto support Copyright 2017 Espressif Systems (Shanghai) PTE LTD +// +// 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 "wpa/includes.h" + +//#include "wpa/common.h" +#include "crypto/common.h" +#include "crypto/crypto.h" +#include "crypto/aes.h" +#if defined(CONFIG_DES) || defined(CONFIG_DES3) +#include "crypto/des_i.h" +#endif +#include "mbedtls/aes.h" + +struct fast_crypto_cipher { + enum crypto_cipher_alg alg; + union { + struct { + size_t used_bytes; + uint8_t key[16]; + size_t keylen; + } rc4; + struct { + uint8_t cbc[32]; + mbedtls_aes_context ctx_enc; + mbedtls_aes_context ctx_dec; + } aes; +#ifdef CONFIG_DES3 + struct { + struct des3_key_s key; + uint8_t cbc[8]; + } des3; +#endif +#ifdef CONFIG_DES + struct { + uint32_t ek[32]; + uint32_t dk[32]; + uint32_t cbc[8]; + } des; +#endif + } u; +}; + + +struct crypto_cipher * fast_crypto_cipher_init(enum crypto_cipher_alg alg, + const uint8_t *iv, const uint8_t *key, + size_t key_len) +{ + struct fast_crypto_cipher *ctx; + + ctx = (struct fast_crypto_cipher *)os_zalloc(sizeof(*ctx)); + if (ctx == NULL) { + return NULL; + } + + ctx->alg = alg; + + switch (alg) { + case CRYPTO_CIPHER_ALG_RC4: + if (key_len > sizeof(ctx->u.rc4.key)) { + os_free(ctx); + return NULL; + } + ctx->u.rc4.keylen = key_len; + os_memcpy(ctx->u.rc4.key, key, key_len); + break; + case CRYPTO_CIPHER_ALG_AES: + mbedtls_aes_init(&(ctx->u.aes.ctx_enc)); + mbedtls_aes_setkey_enc(&(ctx->u.aes.ctx_enc), key, 256); + mbedtls_aes_init(&(ctx->u.aes.ctx_dec)); + mbedtls_aes_setkey_dec(&(ctx->u.aes.ctx_dec), key, 256); + os_memcpy(ctx->u.aes.cbc, iv, AES_BLOCK_SIZE); + break; +#ifdef CONFIG_DES3 + case CRYPTO_CIPHER_ALG_3DES: + if (key_len != 24) { + os_free(ctx); + return NULL; + } + des3_key_setup(key, &ctx->u.des3.key); + os_memcpy(ctx->u.des3.cbc, iv, 8); + break; +#endif +#ifdef CONFIG_DES + case CRYPTO_CIPHER_ALG_DES: + if (key_len != 8) { + os_free(ctx); + return NULL; + } + des_key_setup(key, ctx->u.des.ek, ctx->u.des.dk); + os_memcpy(ctx->u.des.cbc, iv, 8); + break; +#endif + default: + os_free(ctx); + return NULL; + } + + return (struct crypto_cipher *)ctx; +} + + +int fast_crypto_cipher_encrypt(struct crypto_cipher *ctx, const uint8_t *plain, + uint8_t *crypt, size_t len) +{ + size_t i, j, blocks; + struct fast_crypto_cipher *fast_ctx; + + fast_ctx = (struct fast_crypto_cipher *)ctx; + + switch (fast_ctx->alg) { + case CRYPTO_CIPHER_ALG_RC4: + if (plain != crypt) { + os_memcpy(crypt, plain, len); + } + rc4_skip(fast_ctx->u.rc4.key, fast_ctx->u.rc4.keylen, + fast_ctx->u.rc4.used_bytes, crypt, len); + fast_ctx->u.rc4.used_bytes += len; + break; + case CRYPTO_CIPHER_ALG_AES: + if (len % AES_BLOCK_SIZE) { + return -1; + } + blocks = len / AES_BLOCK_SIZE; + for (i = 0; i < blocks; i++) { + for (j = 0; j < AES_BLOCK_SIZE; j++) + fast_ctx->u.aes.cbc[j] ^= plain[j]; + mbedtls_aes_encrypt(&(fast_ctx->u.aes.ctx_enc), fast_ctx->u.aes.cbc, fast_ctx->u.aes.cbc); + os_memcpy(crypt, fast_ctx->u.aes.cbc, AES_BLOCK_SIZE); + plain += AES_BLOCK_SIZE; + crypt += AES_BLOCK_SIZE; + } + break; +#ifdef CONFIG_DES3 + case CRYPTO_CIPHER_ALG_3DES: + if (len % 8) { + return -1; + } + blocks = len / 8; + for (i = 0; i < blocks; i++) { + for (j = 0; j < 8; j++) + fast_ctx->u.des3.cbc[j] ^= plain[j]; + des3_encrypt(fast_ctx->u.des3.cbc, &fast_ctx->u.des3.key, + fast_ctx->u.des3.cbc); + os_memcpy(crypt, fast_ctx->u.des3.cbc, 8); + plain += 8; + crypt += 8; + } + break; +#endif +#ifdef CONFIG_DES + case CRYPTO_CIPHER_ALG_DES: + if (len % 8) { + return -1; + } + blocks = len / 8; + for (i = 0; i < blocks; i++) { + for (j = 0; j < 8; j++) + fast_ctx->u.des3.cbc[j] ^= plain[j]; + des_block_encrypt(fast_ctx->u.des.cbc, fast_ctx->u.des.ek, + fast_ctx->u.des.cbc); + os_memcpy(crypt, fast_ctx->u.des.cbc, 8); + plain += 8; + crypt += 8; + } + break; +#endif + default: + return -1; + } + + return 0; +} + + +int fast_crypto_cipher_decrypt(struct crypto_cipher *ctx, const uint8_t *crypt, + uint8_t *plain, size_t len) +{ + size_t i, j, blocks; + uint8_t tmp[32]; + struct fast_crypto_cipher *fast_ctx; + + fast_ctx = (struct fast_crypto_cipher *)ctx; + + switch (fast_ctx->alg) { + case CRYPTO_CIPHER_ALG_RC4: + if (plain != crypt) { + os_memcpy(plain, crypt, len); + } + rc4_skip(fast_ctx->u.rc4.key, fast_ctx->u.rc4.keylen, + fast_ctx->u.rc4.used_bytes, plain, len); + fast_ctx->u.rc4.used_bytes += len; + break; + case CRYPTO_CIPHER_ALG_AES: + if (len % AES_BLOCK_SIZE) { + return -1; + } + blocks = len / AES_BLOCK_SIZE; + for (i = 0; i < blocks; i++) { + os_memcpy(tmp, crypt, AES_BLOCK_SIZE); + mbedtls_aes_decrypt(&(fast_ctx->u.aes.ctx_dec), crypt, plain); + for (j = 0; j < AES_BLOCK_SIZE; j++) + plain[j] ^= fast_ctx->u.aes.cbc[j]; + os_memcpy(fast_ctx->u.aes.cbc, tmp, AES_BLOCK_SIZE); + plain += AES_BLOCK_SIZE; + crypt += AES_BLOCK_SIZE; + } + break; +#ifdef CONFIG_DES3 + case CRYPTO_CIPHER_ALG_3DES: + if (len % 8) { + return -1; + } + blocks = len / 8; + for (i = 0; i < blocks; i++) { + os_memcpy(tmp, crypt, 8); + des3_decrypt(crypt, &fast_ctx->u.des3.key, plain); + for (j = 0; j < 8; j++) { + plain[j] ^= fast_ctx->u.des3.cbc[j]; + } + os_memcpy(fast_ctx->u.des3.cbc, tmp, 8); + plain += 8; + crypt += 8; + } + break; +#endif +#ifdef CONFIG_DES + case CRYPTO_CIPHER_ALG_DES: + if (len % 8) { + return -1; + } + blocks = len / 8; + for (i = 0; i < blocks; i++) { + os_memcpy(tmp, crypt, 8); + des_block_decrypt(crypt, fast_ctx->u.des.dk, plain); + for (j = 0; j < 8; j++) { + plain[j] ^= fast_ctx->u.des.cbc[j]; + } + os_memcpy(fast_ctx->u.des.cbc, tmp, 8); + plain += 8; + crypt += 8; + } + break; +#endif + default: + return -1; +} + +return 0; +} + + +void fast_crypto_cipher_deinit(struct crypto_cipher *ctx) +{ + struct fast_crypto_cipher *fast_ctx; + + fast_ctx = (struct fast_crypto_cipher *)ctx; + + switch (fast_ctx->alg) { + case CRYPTO_CIPHER_ALG_AES: + mbedtls_aes_free(&(fast_ctx->u.aes.ctx_enc)); + mbedtls_aes_free(&(fast_ctx->u.aes.ctx_dec)); + break; +#ifdef CONFIG_DES3 + case CRYPTO_CIPHER_ALG_3DES: + break; +#endif + default: + break; + } + os_free(ctx); +} diff --git a/components/wpa_supplicant/src/fast_crypto/fast_crypto_internal-modexp.c b/components/wpa_supplicant/src/fast_crypto/fast_crypto_internal-modexp.c new file mode 100644 index 000000000..66d4aa2de --- /dev/null +++ b/components/wpa_supplicant/src/fast_crypto/fast_crypto_internal-modexp.c @@ -0,0 +1,59 @@ +// Hardware crypto support Copyright 2017 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 "crypto/includes.h" + +#include "crypto/common.h" +#include "crypto/crypto.h" +#include "mbedtls/bignum.h" + +int +fast_crypto_mod_exp(const uint8_t *base, size_t base_len, + const uint8_t *power, size_t power_len, + const uint8_t *modulus, size_t modulus_len, + uint8_t *result, size_t *result_len) +{ + mbedtls_mpi bn_base, bn_exp, bn_modulus, bn_result, bn_rinv; + int32_t ret = 0; + mbedtls_mpi_init(&bn_base); + mbedtls_mpi_init(&bn_exp); + mbedtls_mpi_init(&bn_modulus); + mbedtls_mpi_init(&bn_result); + mbedtls_mpi_init(&bn_rinv); + + mbedtls_mpi_read_binary(&bn_base, base, base_len); + mbedtls_mpi_read_binary(&bn_exp, power, power_len); + mbedtls_mpi_read_binary(&bn_modulus, modulus, modulus_len); + + ret = mbedtls_mpi_exp_mod(&bn_result, &bn_base, &bn_exp, &bn_modulus, &bn_rinv); + if (ret < 0) { + mbedtls_mpi_free(&bn_base); + mbedtls_mpi_free(&bn_exp); + mbedtls_mpi_free(&bn_modulus); + mbedtls_mpi_free(&bn_result); + mbedtls_mpi_free(&bn_rinv); + return ret; + } + + ret = mbedtls_mpi_write_binary(&bn_result, result, *result_len); + + + mbedtls_mpi_free(&bn_base); + mbedtls_mpi_free(&bn_exp); + mbedtls_mpi_free(&bn_modulus); + mbedtls_mpi_free(&bn_result); + mbedtls_mpi_free(&bn_rinv); + + return ret; +} diff --git a/components/wpa_supplicant/src/fast_crypto/fast_crypto_internal.c b/components/wpa_supplicant/src/fast_crypto/fast_crypto_internal.c new file mode 100644 index 000000000..a0f7da83a --- /dev/null +++ b/components/wpa_supplicant/src/fast_crypto/fast_crypto_internal.c @@ -0,0 +1,282 @@ +/* + * Crypto wrapper for internal crypto implementation + * Copyright (c) 2006-2011, Jouni Malinen + * + * Hardware crypto support Copyright 2017 Espressif Systems (Shanghai) PTE LTD + * + * This software may be distributed under the terms of the BSD license. + * See README for more details. + */ + +#include "crypto/includes.h" +#include "crypto/common.h" +#include "crypto/crypto.h" +#include "crypto/sha1_i.h" +#include "crypto/md5_i.h" +#include "mbedtls/sha256.h" + + +#ifdef MEMLEAK_DEBUG +static const char mem_debug_file[] ICACHE_RODATA_ATTR = __FILE__; +#endif + +struct fast_crypto_hash { + enum crypto_hash_alg alg; + union { + struct MD5Context md5; + struct SHA1Context sha1; +#ifdef CONFIG_SHA256 + mbedtls_sha256_context sha256; +#endif /* CONFIG_SHA256 */ + } u; + u8 key[64]; + size_t key_len; +}; + +struct crypto_hash * fast_crypto_hash_init(enum crypto_hash_alg alg, const u8 *key, + size_t key_len) +{ + struct fast_crypto_hash *ctx; + u8 k_pad[64]; + u8 tk[32]; + size_t i; + + ctx = (struct fast_crypto_hash *)os_zalloc(sizeof(*ctx)); + if (ctx == NULL) + return NULL; + + ctx->alg = alg; + + switch (alg) { + case CRYPTO_HASH_ALG_MD5: + MD5Init(&ctx->u.md5); + break; + case CRYPTO_HASH_ALG_SHA1: + SHA1Init(&ctx->u.sha1); + break; +#ifdef CONFIG_SHA256 + case CRYPTO_HASH_ALG_SHA256: + mbedtls_sha256_init(&ctx->u.sha256); + mbedtls_sha256_starts(&ctx->u.sha256, 0); + break; +#endif /* CONFIG_SHA256 */ + case CRYPTO_HASH_ALG_HMAC_MD5: + if (key_len > sizeof(k_pad)) { + MD5Init(&ctx->u.md5); + MD5Update(&ctx->u.md5, key, key_len); + MD5Final(tk, &ctx->u.md5); + key = tk; + key_len = 16; + } + os_memcpy(ctx->key, key, key_len); + ctx->key_len = key_len; + + os_memcpy(k_pad, key, key_len); + if (key_len < sizeof(k_pad)) + os_memset(k_pad + key_len, 0, sizeof(k_pad) - key_len); + for (i = 0; i < sizeof(k_pad); i++) + k_pad[i] ^= 0x36; + MD5Init(&ctx->u.md5); + MD5Update(&ctx->u.md5, k_pad, sizeof(k_pad)); + break; + case CRYPTO_HASH_ALG_HMAC_SHA1: + if (key_len > sizeof(k_pad)) { + SHA1Init(&ctx->u.sha1); + SHA1Update(&ctx->u.sha1, key, key_len); + SHA1Final(tk, &ctx->u.sha1); + key = tk; + key_len = 20; + } + os_memcpy(ctx->key, key, key_len); + ctx->key_len = key_len; + + os_memcpy(k_pad, key, key_len); + if (key_len < sizeof(k_pad)) + os_memset(k_pad + key_len, 0, sizeof(k_pad) - key_len); + for (i = 0; i < sizeof(k_pad); i++) + k_pad[i] ^= 0x36; + SHA1Init(&ctx->u.sha1); + SHA1Update(&ctx->u.sha1, k_pad, sizeof(k_pad)); + break; +#ifdef CONFIG_SHA256 + case CRYPTO_HASH_ALG_HMAC_SHA256: + if (key_len > sizeof(k_pad)) { + mbedtls_sha256_init(&ctx->u.sha256); + mbedtls_sha256_starts(&ctx->u.sha256, 0); + mbedtls_sha256_update(&ctx->u.sha256, key, key_len); + mbedtls_sha256_finish(&ctx->u.sha256, tk); + mbedtls_sha256_free(&ctx->u.sha256); + key = tk; + key_len = 32; + } + os_memcpy(ctx->key, key, key_len); + ctx->key_len = key_len; + + os_memcpy(k_pad, key, key_len); + if (key_len < sizeof(k_pad)) + os_memset(k_pad + key_len, 0, sizeof(k_pad) - key_len); + for (i = 0; i < sizeof(k_pad); i++) + k_pad[i] ^= 0x36; + mbedtls_sha256_init(&ctx->u.sha256); + mbedtls_sha256_starts(&ctx->u.sha256, 0); + mbedtls_sha256_update(&ctx->u.sha256, k_pad, sizeof(k_pad)); + break; +#endif /* CONFIG_SHA256 */ + default: + os_free(ctx); + return NULL; + } + + return (struct crypto_hash *)ctx; +} + + +void fast_crypto_hash_update(struct crypto_hash *ctx, const u8 *data, size_t len) +{ + + struct fast_crypto_hash *fast_ctx; + fast_ctx = (struct fast_crypto_hash *)ctx; + + if (fast_ctx == NULL) + return; + + switch (fast_ctx->alg) { + case CRYPTO_HASH_ALG_MD5: + case CRYPTO_HASH_ALG_HMAC_MD5: + MD5Update(&fast_ctx->u.md5, data, len); + break; + case CRYPTO_HASH_ALG_SHA1: + case CRYPTO_HASH_ALG_HMAC_SHA1: + SHA1Update(&fast_ctx->u.sha1, data, len); + break; +#ifdef CONFIG_SHA256 + case CRYPTO_HASH_ALG_SHA256: + case CRYPTO_HASH_ALG_HMAC_SHA256: + mbedtls_sha256_update(&fast_ctx->u.sha256, data, len); + break; +#endif /* CONFIG_SHA256 */ + default: + break; + } +} + + +int fast_crypto_hash_finish(struct crypto_hash *ctx, u8 *mac, size_t *len) +{ + u8 k_pad[64]; + size_t i; + struct fast_crypto_hash *fast_ctx; + + if (ctx == NULL) + return -2; + + fast_ctx = (struct fast_crypto_hash *)ctx; + + if (mac == NULL || len == NULL) { + os_free(fast_ctx); + return 0; + } + + switch (fast_ctx->alg) { + case CRYPTO_HASH_ALG_MD5: + if (*len < 16) { + *len = 16; + os_free(fast_ctx); + return -1; + } + *len = 16; + MD5Final(mac, &fast_ctx->u.md5); + break; + case CRYPTO_HASH_ALG_SHA1: + if (*len < 20) { + *len = 20; + os_free(fast_ctx); + return -1; + } + *len = 20; + SHA1Final(mac, &fast_ctx->u.sha1); + break; +#ifdef CONFIG_SHA256 + case CRYPTO_HASH_ALG_SHA256: + if (*len < 32) { + *len = 32; + os_free(fast_ctx); + return -1; + } + *len = 32; + mbedtls_sha256_finish(&fast_ctx->u.sha256, mac); + mbedtls_sha256_free(&fast_ctx->u.sha256); + break; +#endif /* CONFIG_SHA256 */ + case CRYPTO_HASH_ALG_HMAC_MD5: + if (*len < 16) { + *len = 16; + os_free(fast_ctx); + return -1; + } + *len = 16; + + MD5Final(mac, &fast_ctx->u.md5); + + os_memcpy(k_pad, fast_ctx->key, fast_ctx->key_len); + os_memset(k_pad + fast_ctx->key_len, 0, + sizeof(k_pad) - fast_ctx->key_len); + for (i = 0; i < sizeof(k_pad); i++) + k_pad[i] ^= 0x5c; + MD5Init(&fast_ctx->u.md5); + MD5Update(&fast_ctx->u.md5, k_pad, sizeof(k_pad)); + MD5Update(&fast_ctx->u.md5, mac, 16); + MD5Final(mac, &fast_ctx->u.md5); + break; + case CRYPTO_HASH_ALG_HMAC_SHA1: + if (*len < 20) { + *len = 20; + os_free(ctx); + return -1; + } + *len = 20; + + SHA1Final(mac, &fast_ctx->u.sha1); + os_memcpy(k_pad, fast_ctx->key, fast_ctx->key_len); + os_memset(k_pad + fast_ctx->key_len, 0, + sizeof(k_pad) - fast_ctx->key_len); + for (i = 0; i < sizeof(k_pad); i++) + k_pad[i] ^= 0x5c; + SHA1Init(&fast_ctx->u.sha1); + SHA1Update(&fast_ctx->u.sha1, k_pad, sizeof(k_pad)); + SHA1Update(&fast_ctx->u.sha1, mac, 20); + SHA1Final(mac, &fast_ctx->u.sha1); + break; +#ifdef CONFIG_SHA256 + case CRYPTO_HASH_ALG_HMAC_SHA256: + if (*len < 32) { + *len = 32; + os_free(fast_ctx); + return -1; + } + *len = 32; + mbedtls_sha256_finish(&fast_ctx->u.sha256, mac); + mbedtls_sha256_free(&fast_ctx->u.sha256); + + os_memcpy(k_pad, fast_ctx->key, fast_ctx->key_len); + os_memset(k_pad + fast_ctx->key_len, 0, + sizeof(k_pad) - fast_ctx->key_len); + for (i = 0; i < sizeof(k_pad); i++) + k_pad[i] ^= 0x5c; + mbedtls_sha256_init(&fast_ctx->u.sha256); + mbedtls_sha256_starts(&fast_ctx->u.sha256, 0); + mbedtls_sha256_update(&fast_ctx->u.sha256, k_pad, sizeof(k_pad)); + mbedtls_sha256_update(&fast_ctx->u.sha256, mac, 32); + mbedtls_sha256_finish(&fast_ctx->u.sha256, mac); + mbedtls_sha256_free(&fast_ctx->u.sha256); + break; +#endif /* CONFIG_SHA256 */ + default: + os_free(fast_ctx); + return -1; + } + + os_free(fast_ctx); + + return 0; +} diff --git a/components/wpa_supplicant/src/fast_crypto/fast_sha256-internal.c b/components/wpa_supplicant/src/fast_crypto/fast_sha256-internal.c new file mode 100644 index 000000000..587b9096f --- /dev/null +++ b/components/wpa_supplicant/src/fast_crypto/fast_sha256-internal.c @@ -0,0 +1,48 @@ +// Hardware crypto support Copyright 2017 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 "crypto/includes.h" +#include "crypto/common.h" +#include "mbedtls/sha256.h" + +/** + * fast_sha256_vector - SHA256 hash for data vector + * @num_elem: Number of elements in the data vector + * @addr: Pointers to the data areas + * @len: Lengths of the data blocks + * @mac: Buffer for the hash + * Returns: 0 on success, -1 of failure + */ +int +fast_sha256_vector(size_t num_elem, const uint8_t *addr[], const size_t *len, + uint8_t *mac) +{ + mbedtls_sha256_context ctx; + + mbedtls_sha256_init(&ctx); + + mbedtls_sha256_starts(&ctx, 0); + + for(size_t index = 0; index < num_elem; index++) { + mbedtls_sha256_update(&ctx, addr[index], len[index]); + } + + mbedtls_sha256_finish(&ctx, mac); + + mbedtls_sha256_free(&ctx); + + return 0; +} + + diff --git a/components/wpa_supplicant/src/fast_crypto/fast_sha256.c b/components/wpa_supplicant/src/fast_crypto/fast_sha256.c new file mode 100644 index 000000000..b0fb03e4f --- /dev/null +++ b/components/wpa_supplicant/src/fast_crypto/fast_sha256.c @@ -0,0 +1,165 @@ +/* + * SHA-256 hash implementation and interface functions + * Copyright (c) 2003-2007, Jouni Malinen + * + * Hardware crypto support Copyright 2017 Espressif Systems (Shanghai) PTE LTD + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * + * Alternatively, this software may be distributed under the terms of BSD + * license. + * + * See README and COPYING for more details. + */ + +#include "crypto/includes.h" + +#include "crypto/common.h" +#include "crypto/sha256.h" +#include "crypto/crypto.h" + + +/** + * fast_hmac_sha256_vector - HMAC-SHA256 over data vector (RFC 2104) + * @key: Key for HMAC operations + * @key_len: Length of the key in bytes + * @num_elem: Number of elements in the data vector + * @addr: Pointers to the data areas + * @len: Lengths of the data blocks + * @mac: Buffer for the hash (32 bytes) + */ +void +fast_hmac_sha256_vector(const uint8_t *key, size_t key_len, size_t num_elem, + const uint8_t *addr[], const size_t *len, uint8_t *mac) +{ + uint8_t k_pad[64]; /* padding - key XORd with ipad/opad */ + uint8_t tk[32]; + const uint8_t *_addr[6]; + size_t _len[6], i; + + if (num_elem > 5) { + /* + * Fixed limit on the number of fragments to avoid having to + * allocate memory (which could fail). + */ + return; + } + + /* if key is longer than 64 bytes reset it to key = SHA256(key) */ + if (key_len > 64) { + fast_sha256_vector(1, &key, &key_len, tk); + key = tk; + key_len = 32; + } + + /* the HMAC_SHA256 transform looks like: + * + * SHA256(K XOR opad, SHA256(K XOR ipad, text)) + * + * where K is an n byte key + * ipad is the byte 0x36 repeated 64 times + * opad is the byte 0x5c repeated 64 times + * and text is the data being protected + */ + + /* start out by storing key in ipad */ + os_memset(k_pad, 0, sizeof(k_pad)); + os_memcpy(k_pad, key, key_len); + /* XOR key with ipad values */ + for (i = 0; i < 64; i++) { + k_pad[i] ^= 0x36; + } + + /* perform inner SHA256 */ + _addr[0] = k_pad; + _len[0] = 64; + for (i = 0; i < num_elem; i++) { + _addr[i + 1] = addr[i]; + _len[i + 1] = len[i]; + } + fast_sha256_vector(1 + num_elem, _addr, _len, mac); + + os_memset(k_pad, 0, sizeof(k_pad)); + os_memcpy(k_pad, key, key_len); + /* XOR key with opad values */ + for (i = 0; i < 64; i++) { + k_pad[i] ^= 0x5c; + } + + /* perform outer SHA256 */ + _addr[0] = k_pad; + _len[0] = 64; + _addr[1] = mac; + _len[1] = SHA256_MAC_LEN; + fast_sha256_vector(2, _addr, _len, mac); +} + + +/** + * fast_hmac_sha256 - HMAC-SHA256 over data buffer (RFC 2104) + * @key: Key for HMAC operations + * @key_len: Length of the key in bytes + * @data: Pointers to the data area + * @data_len: Length of the data area + * @mac: Buffer for the hash (20 bytes) + */ +void +fast_hmac_sha256(const uint8_t *key, size_t key_len, const uint8_t *data, + size_t data_len, uint8_t *mac) +{ + fast_hmac_sha256_vector(key, key_len, 1, &data, &data_len, mac); +} + + +/** + * fast_sha256_prf - SHA256-based Pseudo-Random Function (IEEE 802.11r, 8.5.1.5.2) + * @key: Key for PRF + * @key_len: Length of the key in bytes + * @label: A unique label for each purpose of the PRF + * @data: Extra data to bind into the key + * @data_len: Length of the data + * @buf: Buffer for the generated pseudo-random key + * @buf_len: Number of bytes of key to generate + * + * This function is used to derive new, cryptographically separate keys from a + * given key. + */ +void +fast_sha256_prf(const uint8_t *key, size_t key_len, const char *label, + const uint8_t *data, size_t data_len, uint8_t *buf, size_t buf_len) +{ + uint16_t counter = 1; + size_t pos, plen; + uint8_t hash[SHA256_MAC_LEN]; + const uint8_t *addr[4]; + size_t len[4]; + uint8_t counter_le[2], length_le[2]; + + addr[0] = counter_le; + len[0] = 2; + addr[1] = (uint8_t *) label; + len[1] = os_strlen(label); + addr[2] = data; + len[2] = data_len; + addr[3] = length_le; + len[3] = sizeof(length_le); + + WPA_PUT_LE16(length_le, buf_len * 8); + pos = 0; + while (pos < buf_len) { + plen = buf_len - pos; + WPA_PUT_LE16(counter_le, counter); + if (plen >= SHA256_MAC_LEN) { + fast_hmac_sha256_vector(key, key_len, 4, addr, len, + &buf[pos]); + pos += SHA256_MAC_LEN; + } else { + fast_hmac_sha256_vector(key, key_len, 4, addr, len, hash); + os_memcpy(&buf[pos], hash, plen); + break; + } + counter++; + } +} diff --git a/docs/Doxyfile b/docs/Doxyfile index e6af25c90..15feda1a7 100644 --- a/docs/Doxyfile +++ b/docs/Doxyfile @@ -25,6 +25,7 @@ INPUT = \ ## Wi-Fi - API Reference ## ../components/esp32/include/esp_wifi.h \ + ../components/esp32/include/esp_wifi_crypto_types.h\ ../components/esp32/include/esp_smartconfig.h \ ## Bluetooth - API Reference ## Controller && VHCI diff --git a/docs/api-guides/wifi.rst b/docs/api-guides/wifi.rst index 800f8ae05..26b032e44 100644 --- a/docs/api-guides/wifi.rst +++ b/docs/api-guides/wifi.rst @@ -19,6 +19,7 @@ ESP32 Wi-Fi Feature List - Supports an Espressif-specific protocol which, in turn, supports up to **1 km** of data traffic - Up to 20 MBit/sec TCP throughput and 30 MBit/sec UDP throughput over the air - Supports Sniffer +- Support set fast_crypto algorithm and normal algorithm switch which used in wifi connect How To Write a Wi-Fi Application ---------------------------------- @@ -1215,6 +1216,15 @@ Currently, ESP32 Wi-Fi supports the Modem-sleep mode which refers to WMM (Wi-Fi Call esp_wifi_set_ps(WIFI_PS_MODEM) to enable Modem-sleep mode after calling esp_wifi_init(). About 10 seconds after the station connects to the AP, Modem-sleep will start. When the station disconnects from the AP, Modem-sleep will stop. +ESP32 Wi-Fi Connect Crypto +----------------------------------- +Now ESP32 have two group crypto functions can be used when do wifi connect, one is the original functions, the other is optimized by ESP hardware: +1. Original functions which is the source code used in the folder components/wpa_supplicant/src/crypto function; +2. The optimized functions is in the folder components/wpa_supplicant/src/fast_crypto, these function used the hardware crypto to make it faster than origin one, the type of function's name add fast_ to distinguish with the original one. For example, the API aes_wrap() is used to encrypt frame information when do 4 way handshake, the fast_aes_wrap() has the same result but can be faster. + +Two groups of crypto function can be used when register in the wpa_crypto_funcs_t, wpa2_crypto_funcs_t and wps_crypto_funcs_t structure, also we have given the recommend functions to register in the +fast_crypto_ops.c, you can register the function as the way you need, however what should make action is that the crypto_hash_xxx function and crypto_cipher_xxx function need to register with the same function to operation. For example, if you register crypto_hash_init() function to initialize the esp_crypto_hash structure, you need use the crypto_hash_update() and crypto_hash_finish() function to finish the operation, rather than fast_crypto_hash_update() or fast_crypto_hash_finish(). + ESP32 Wi-Fi Throughput ----------------------------------- diff --git a/examples/wifi/power_save/main/power_save.c b/examples/wifi/power_save/main/power_save.c index d03881ff8..98bc601ed 100644 --- a/examples/wifi/power_save/main/power_save.c +++ b/examples/wifi/power_save/main/power_save.c @@ -62,6 +62,7 @@ static void wifi_power_save(void) { tcpip_adapter_init(); ESP_ERROR_CHECK(esp_event_loop_init(event_handler, NULL)); + wifi_init_config_t cfg = WIFI_INIT_CONFIG_DEFAULT(); ESP_ERROR_CHECK(esp_wifi_init(&cfg)); wifi_config_t wifi_config = { diff --git a/examples/wifi/smart_config/main/smartconfig_main.c b/examples/wifi/smart_config/main/smartconfig_main.c index 63af25e65..3cbf8737d 100644 --- a/examples/wifi/smart_config/main/smartconfig_main.c +++ b/examples/wifi/smart_config/main/smartconfig_main.c @@ -57,7 +57,9 @@ static void initialise_wifi(void) tcpip_adapter_init(); wifi_event_group = xEventGroupCreate(); ESP_ERROR_CHECK( esp_event_loop_init(event_handler, NULL) ); + wifi_init_config_t cfg = WIFI_INIT_CONFIG_DEFAULT(); + ESP_ERROR_CHECK( esp_wifi_init(&cfg) ); ESP_ERROR_CHECK( esp_wifi_set_mode(WIFI_MODE_STA) ); ESP_ERROR_CHECK( esp_wifi_start() ); diff --git a/examples/wifi/wpa2_enterprise/main/wpa2_enterprise_main.c b/examples/wifi/wpa2_enterprise/main/wpa2_enterprise_main.c index d2b6344ec..5b3f804e1 100644 --- a/examples/wifi/wpa2_enterprise/main/wpa2_enterprise_main.c +++ b/examples/wifi/wpa2_enterprise/main/wpa2_enterprise_main.c @@ -100,6 +100,7 @@ static void initialise_wifi(void) unsigned int ca_pem_bytes = ca_pem_end - ca_pem_start; unsigned int client_crt_bytes = client_crt_end - client_crt_start; unsigned int client_key_bytes = client_key_end - client_key_start; + esp_wpa2_config_t config = WPA2_CONFIG_INIT_DEFAULT(); tcpip_adapter_init(); wifi_event_group = xEventGroupCreate(); @@ -123,7 +124,8 @@ static void initialise_wifi(void) ESP_ERROR_CHECK( esp_wifi_sta_wpa2_ent_set_username((uint8_t *)EXAMPLE_EAP_USERNAME, strlen(EXAMPLE_EAP_USERNAME)) ); ESP_ERROR_CHECK( esp_wifi_sta_wpa2_ent_set_password((uint8_t *)EXAMPLE_EAP_PASSWORD, strlen(EXAMPLE_EAP_PASSWORD)) ); } - ESP_ERROR_CHECK( esp_wifi_sta_wpa2_ent_enable() ); + + ESP_ERROR_CHECK( esp_wifi_sta_wpa2_ent_enable(&config) ); ESP_ERROR_CHECK( esp_wifi_start() ); } diff --git a/examples/wifi/wps/main/wps.c b/examples/wifi/wps/main/wps.c index dd4a66c19..6fb8ad246 100644 --- a/examples/wifi/wps/main/wps.c +++ b/examples/wifi/wps/main/wps.c @@ -40,7 +40,7 @@ static const char *TAG = "example_wps"; - +static esp_wps_config_t config = WPS_CONFIG_INIT_DEFAULT(WPS_TEST_MODE); static esp_err_t event_handler(void *ctx, system_event_t *event) { @@ -68,13 +68,13 @@ static esp_err_t event_handler(void *ctx, system_event_t *event) case SYSTEM_EVENT_STA_WPS_ER_FAILED: ESP_LOGI(TAG, "SYSTEM_EVENT_STA_WPS_ER_FAILED"); ESP_ERROR_CHECK(esp_wifi_wps_disable()); - ESP_ERROR_CHECK(esp_wifi_wps_enable(WPS_TEST_MODE)); + ESP_ERROR_CHECK(esp_wifi_wps_enable(&config)); ESP_ERROR_CHECK(esp_wifi_wps_start(0)); break; case SYSTEM_EVENT_STA_WPS_ER_TIMEOUT: ESP_LOGI(TAG, "SYSTEM_EVENT_STA_WPS_ER_TIMEOUT"); ESP_ERROR_CHECK(esp_wifi_wps_disable()); - ESP_ERROR_CHECK(esp_wifi_wps_enable(WPS_TEST_MODE)); + ESP_ERROR_CHECK(esp_wifi_wps_enable(&config)); ESP_ERROR_CHECK(esp_wifi_wps_start(0)); break; case SYSTEM_EVENT_STA_WPS_ER_PIN: @@ -95,13 +95,16 @@ static void start_wps(void) ESP_ERROR_CHECK(esp_event_loop_init(event_handler, NULL)); wifi_init_config_t cfg = WIFI_INIT_CONFIG_DEFAULT(); + ESP_ERROR_CHECK(esp_wifi_init(&cfg)); ESP_ERROR_CHECK(esp_wifi_set_mode(WIFI_MODE_STA)); ESP_ERROR_CHECK(esp_wifi_start()); ESP_LOGI(TAG, "start wps..."); - ESP_ERROR_CHECK(esp_wifi_wps_enable(WPS_TEST_MODE)); + + + ESP_ERROR_CHECK(esp_wifi_wps_enable(&config)); ESP_ERROR_CHECK(esp_wifi_wps_start(0)); }