Add the fast crypto function in supplicant

optimize the speed when do wifi connect
This commit is contained in:
Deng Xin 2017-08-01 22:29:16 +08:00
parent 1c4f7f2081
commit 57bc38d867
25 changed files with 1673 additions and 26 deletions

View file

@ -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
};

View file

@ -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,\

View file

@ -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

View file

@ -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.

View file

@ -15,8 +15,10 @@
#ifndef __ESP_WPS_H__
#define __ESP_WPS_H__
#include <stdint.h>
#include <stdbool.h>
#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.

@ -1 +1 @@
Subproject commit 57b3072bd3fd2f7759225d8407443e9e983520ae
Subproject commit e8d8e908fb37c4d9e8a3f23e63f6b34f5178e24a

View file

@ -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

View file

@ -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 */

View file

@ -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

View file

@ -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 */

View file

@ -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);

View file

@ -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;
}

View file

@ -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;
}

View file

@ -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;
}

View file

@ -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);
}

View file

@ -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;
}

View file

@ -0,0 +1,282 @@
/*
* Crypto wrapper for internal crypto implementation
* Copyright (c) 2006-2011, Jouni Malinen <j@w1.fi>
*
* 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;
}

View file

@ -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;
}

View file

@ -0,0 +1,165 @@
/*
* SHA-256 hash implementation and interface functions
* Copyright (c) 2003-2007, Jouni Malinen <j@w1.fi>
*
* 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++;
}
}

View file

@ -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

View file

@ -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
-----------------------------------

View file

@ -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 = {

View file

@ -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() );

View file

@ -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() );
}

View file

@ -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));
}